summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSean Whitton <spwhitton@spwhitton.name>2024-01-10 21:06:01 +0000
committerSean Whitton <spwhitton@spwhitton.name>2024-01-10 21:06:01 +0000
commita5ec494a7f36a2d200cd5438194f30fdf3edff36 (patch)
treed2d33029b3b73f249f380745c52108d86fc48f08
parentf4b0b5e20a9e3a6ccce52e41314763cebc8a9769 (diff)
parent0c5cfd0a236346265e06a46cfff43239868051c9 (diff)
downloademacs-a5ec494a7f36a2d200cd5438194f30fdf3edff36.tar.gz
Merge upstream Git snapshot into athena/unstable
-rw-r--r--.clang-format5
-rw-r--r--.clangd5
-rw-r--r--.gitattributes2
-rw-r--r--.gitignore3
-rw-r--r--.gitlab-ci.yml2
-rw-r--r--.mailmap6
-rw-r--r--CONTRIBUTE13
-rw-r--r--ChangeLog.14
-rw-r--r--ChangeLog.227
-rw-r--r--ChangeLog.3104
-rw-r--r--ChangeLog.42655
-rw-r--r--ChangeLog.android37
-rw-r--r--GNUmakefile2
-rw-r--r--INSTALL6
-rw-r--r--INSTALL.REPO2
-rw-r--r--Makefile.in10
-rw-r--r--README2
-rw-r--r--admin/ChangeLog.12
-rw-r--r--admin/MAINTAINERS74
-rw-r--r--admin/README2
-rw-r--r--admin/admin.el2
-rw-r--r--admin/alloc-colors.c2
-rw-r--r--admin/authors.el15
-rwxr-xr-xadmin/automerge2
-rwxr-xr-xadmin/build-configs2
-rw-r--r--admin/charsets/Makefile.in2
-rwxr-xr-xadmin/charsets/mapconv2
-rw-r--r--admin/charsets/mapfiles/README2
-rwxr-xr-xadmin/check-man-pages2
-rw-r--r--admin/cus-test.el2
-rwxr-xr-xadmin/diff-tar-files2
-rw-r--r--admin/emacs-shell-lib2
-rwxr-xr-xadmin/emake2
-rw-r--r--admin/find-gc.el2
-rwxr-xr-xadmin/git-bisect-start18
-rw-r--r--admin/gitmerge.el2
-rw-r--r--admin/grammars/Makefile.in2
-rw-r--r--admin/grammars/c.by2
-rw-r--r--admin/grammars/grammar.wy2
-rw-r--r--admin/grammars/java-tags.wy2
-rw-r--r--admin/grammars/js.wy2
-rw-r--r--admin/grammars/make.by2
-rw-r--r--admin/grammars/python.wy2
-rw-r--r--admin/grammars/scheme.by2
-rw-r--r--admin/grammars/srecode-template.wy2
-rw-r--r--admin/last-chance.el2
-rwxr-xr-xadmin/make-emacs2
-rwxr-xr-xadmin/make-manuals2
-rw-r--r--admin/make-tarball.txt25
-rwxr-xr-xadmin/merge-gnulib2
-rwxr-xr-xadmin/merge-pkg-config2
-rw-r--r--admin/notes/bug-triage71
-rw-r--r--admin/notes/copyright2
-rw-r--r--admin/notes/emba4
-rw-r--r--admin/notes/hydra2
-rw-r--r--admin/notes/java1097
-rw-r--r--admin/notes/multi-tty4
-rwxr-xr-xadmin/notes/tree-sitter/build-module/batch.sh2
-rwxr-xr-xadmin/notes/tree-sitter/build-module/build.sh3
-rw-r--r--admin/notes/tree-sitter/performance25
-rw-r--r--admin/notes/unicode20
-rw-r--r--admin/notes/www2
-rw-r--r--admin/notes/years2
-rw-r--r--admin/nt/README-UNDUMP.W322
-rw-r--r--admin/nt/dist-build/README-windows-binaries2
-rwxr-xr-xadmin/nt/dist-build/build-dep-zips.py2
-rwxr-xr-xadmin/nt/dist-build/build-zips.sh2
-rwxr-xr-xadmin/quick-install-emacs2
-rw-r--r--admin/unidata/BidiBrackets.txt10
-rw-r--r--admin/unidata/BidiMirroring.txt8
-rw-r--r--admin/unidata/Blocks.txt7
-rw-r--r--admin/unidata/IdnaMappingTable.txt23
-rw-r--r--admin/unidata/Makefile.in2
-rw-r--r--admin/unidata/NormalizationTest.txt6
-rw-r--r--admin/unidata/PropertyValueAliases.txt38
-rw-r--r--admin/unidata/ScriptExtensions.txt47
-rw-r--r--admin/unidata/Scripts.txt14
-rw-r--r--admin/unidata/SpecialCasing.txt6
-rw-r--r--admin/unidata/UnicodeData.txt7
-rwxr-xr-xadmin/unidata/blocks.awk5
-rw-r--r--admin/unidata/confusables.txt10
-rw-r--r--admin/unidata/copyright.html20
-rw-r--r--admin/unidata/emoji-data.txt6
-rw-r--r--admin/unidata/emoji-sequences.txt17
-rw-r--r--admin/unidata/emoji-test.txt337
-rw-r--r--admin/unidata/emoji-variation-sequences.txt1458
-rw-r--r--admin/unidata/emoji-zwj-sequences.txt144
-rw-r--r--admin/unidata/emoji-zwj.awk10
-rw-r--r--admin/unidata/unidata-gen.el2
-rw-r--r--admin/unidata/uvs.el2
-rwxr-xr-xadmin/update-copyright2
-rwxr-xr-xadmin/update_autogen2
-rwxr-xr-xadmin/upload-manuals2
-rwxr-xr-xautogen.sh2
-rwxr-xr-xbuild-aux/config.guess2
-rwxr-xr-xbuild-aux/config.sub2
-rwxr-xr-xbuild-aux/git-hooks/commit-msg2
-rw-r--r--build-aux/git-hooks/commit-msg-files.awk2
-rwxr-xr-xbuild-aux/git-hooks/post-commit2
-rwxr-xr-xbuild-aux/git-hooks/pre-commit2
-rwxr-xr-xbuild-aux/git-hooks/pre-push2
-rwxr-xr-xbuild-aux/git-hooks/prepare-commit-msg2
-rwxr-xr-xbuild-aux/gitlog-to-changelog4
-rwxr-xr-xbuild-aux/gitlog-to-emacslog2
-rwxr-xr-xbuild-aux/make-info-dir2
-rwxr-xr-xbuild-aux/makecounter.sh2
-rwxr-xr-xbuild-aux/move-if-change2
-rwxr-xr-xbuild-aux/msys-to-w322
-rw-r--r--build-aux/ndk-build-helper-1.mk2
-rw-r--r--build-aux/ndk-build-helper-2.mk2
-rw-r--r--build-aux/ndk-build-helper-3.mk2
-rw-r--r--build-aux/ndk-build-helper-4.mk2
-rw-r--r--build-aux/ndk-build-helper.mk2
-rwxr-xr-xbuild-aux/update-copyright4
-rwxr-xr-xbuild-aux/update-subdirs2
-rw-r--r--config.bat2
-rw-r--r--configure.ac120
-rw-r--r--cross/Makefile.in2
-rw-r--r--cross/langinfo.h2
-rw-r--r--cross/ndk-build/Makefile.in2
-rw-r--r--cross/ndk-build/README6
-rw-r--r--cross/ndk-build/ndk-build-executable.mk2
-rw-r--r--cross/ndk-build/ndk-build-shared-library.mk2
-rw-r--r--cross/ndk-build/ndk-build-static-library.mk2
-rw-r--r--cross/ndk-build/ndk-build.mk.in2
-rw-r--r--cross/ndk-build/ndk-clear-vars.mk2
-rw-r--r--cross/ndk-build/ndk-prebuilt-shared-library.mk2
-rw-r--r--cross/ndk-build/ndk-prebuilt-static-library.mk2
-rw-r--r--cross/ndk-build/ndk-resolve.mk2
-rw-r--r--cross/verbose.mk.android2
-rw-r--r--doc/emacs/ChangeLog.18
-rw-r--r--doc/emacs/Makefile.in2
-rw-r--r--doc/emacs/abbrevs.texi17
-rw-r--r--doc/emacs/ack.texi18
-rw-r--r--doc/emacs/android.texi322
-rw-r--r--doc/emacs/anti.texi2
-rw-r--r--doc/emacs/arevert-xtra.texi2
-rw-r--r--doc/emacs/back.texi2
-rw-r--r--doc/emacs/basic.texi27
-rw-r--r--doc/emacs/buffers.texi29
-rw-r--r--doc/emacs/building.texi29
-rw-r--r--doc/emacs/cal-xtra.texi2
-rw-r--r--doc/emacs/calendar.texi2
-rw-r--r--doc/emacs/cmdargs.texi10
-rw-r--r--doc/emacs/commands.texi4
-rw-r--r--doc/emacs/custom.texi28
-rw-r--r--doc/emacs/dired-xtra.texi2
-rw-r--r--doc/emacs/dired.texi6
-rw-r--r--doc/emacs/display.texi11
-rw-r--r--doc/emacs/emacs-xtra.texi2
-rw-r--r--doc/emacs/emacs.texi18
-rw-r--r--doc/emacs/emerge-xtra.texi2
-rw-r--r--doc/emacs/entering.texi2
-rw-r--r--doc/emacs/files.texi10
-rw-r--r--doc/emacs/fixit.texi17
-rw-r--r--doc/emacs/fortran-xtra.texi2
-rw-r--r--doc/emacs/frames.texi39
-rw-r--r--doc/emacs/glossary.texi2
-rw-r--r--doc/emacs/gnu.texi2
-rw-r--r--doc/emacs/haiku.texi114
-rw-r--r--doc/emacs/help.texi2
-rw-r--r--doc/emacs/indent.texi236
-rw-r--r--doc/emacs/input.texi225
-rw-r--r--doc/emacs/killing.texi4
-rw-r--r--doc/emacs/kmacro.texi21
-rw-r--r--doc/emacs/m-x.texi2
-rw-r--r--doc/emacs/macos.texi7
-rw-r--r--doc/emacs/maintaining.texi327
-rw-r--r--doc/emacs/mark.texi2
-rw-r--r--doc/emacs/mini.texi2
-rw-r--r--doc/emacs/misc.texi33
-rw-r--r--doc/emacs/modes.texi2
-rw-r--r--doc/emacs/msdos-xtra.texi2
-rw-r--r--doc/emacs/msdos.texi6
-rw-r--r--doc/emacs/mule.texi2
-rw-r--r--doc/emacs/package.texi10
-rw-r--r--doc/emacs/picture-xtra.texi2
-rw-r--r--doc/emacs/programs.texi20
-rw-r--r--doc/emacs/regs.texi60
-rw-r--r--doc/emacs/rmail.texi2
-rw-r--r--doc/emacs/screen.texi10
-rw-r--r--doc/emacs/search.texi11
-rw-r--r--doc/emacs/sending.texi24
-rw-r--r--doc/emacs/text.texi23
-rw-r--r--doc/emacs/trouble.texi4
-rw-r--r--doc/emacs/vc-xtra.texi2
-rw-r--r--doc/emacs/vc1-xtra.texi2
-rw-r--r--doc/emacs/windows.texi26
-rw-r--r--doc/emacs/xresources.texi2
-rw-r--r--doc/lang/fr/misc/ses-fr.texi1631
-rw-r--r--doc/lispintro/ChangeLog.12
-rw-r--r--doc/lispintro/Makefile.in2
-rw-r--r--doc/lispintro/README2
-rw-r--r--doc/lispintro/cons-1.eps2
-rw-r--r--doc/lispintro/cons-2.eps2
-rw-r--r--doc/lispintro/cons-2a.eps2
-rw-r--r--doc/lispintro/cons-3.eps2
-rw-r--r--doc/lispintro/cons-4.eps2
-rw-r--r--doc/lispintro/cons-5.eps2
-rw-r--r--doc/lispintro/drawers.eps2
-rw-r--r--doc/lispintro/emacs-lisp-intro.texi236
-rw-r--r--doc/lispintro/lambda-1.eps2
-rw-r--r--doc/lispintro/lambda-2.eps2
-rw-r--r--doc/lispintro/lambda-3.eps2
-rw-r--r--doc/lispref/ChangeLog.14
-rw-r--r--doc/lispref/Makefile.in2
-rw-r--r--doc/lispref/README2
-rw-r--r--doc/lispref/abbrevs.texi2
-rw-r--r--doc/lispref/anti.texi2
-rw-r--r--doc/lispref/back.texi2
-rw-r--r--doc/lispref/backups.texi2
-rw-r--r--doc/lispref/buffers.texi24
-rw-r--r--doc/lispref/commands.texi100
-rw-r--r--doc/lispref/compile.texi33
-rw-r--r--doc/lispref/control.texi97
-rw-r--r--doc/lispref/customize.texi2
-rw-r--r--doc/lispref/debugging.texi32
-rw-r--r--doc/lispref/display.texi38
-rw-r--r--doc/lispref/edebug.texi4
-rw-r--r--doc/lispref/elisp.texi8
-rw-r--r--doc/lispref/errors.texi5
-rw-r--r--doc/lispref/eval.texi16
-rw-r--r--doc/lispref/files.texi11
-rw-r--r--doc/lispref/frames.texi905
-rw-r--r--doc/lispref/functions.texi55
-rw-r--r--doc/lispref/hash.texi2
-rw-r--r--doc/lispref/help.texi2
-rw-r--r--doc/lispref/hooks.texi2
-rw-r--r--doc/lispref/internals.texi5
-rw-r--r--doc/lispref/intro.texi2
-rw-r--r--doc/lispref/keymaps.texi6
-rw-r--r--doc/lispref/lay-flat.texi2
-rw-r--r--doc/lispref/lists.texi2
-rw-r--r--doc/lispref/loading.texi15
-rw-r--r--doc/lispref/macros.texi2
-rw-r--r--doc/lispref/maps.texi2
-rw-r--r--doc/lispref/markers.texi2
-rw-r--r--doc/lispref/minibuf.texi32
-rw-r--r--doc/lispref/modes.texi64
-rw-r--r--doc/lispref/nonascii.texi6
-rw-r--r--doc/lispref/numbers.texi2
-rw-r--r--doc/lispref/objects.texi46
-rw-r--r--doc/lispref/os.texi74
-rw-r--r--doc/lispref/package.texi2
-rw-r--r--doc/lispref/parsing.texi84
-rw-r--r--doc/lispref/positions.texi17
-rw-r--r--doc/lispref/processes.texi60
-rw-r--r--doc/lispref/records.texi2
-rw-r--r--doc/lispref/searching.texi15
-rw-r--r--doc/lispref/sequences.texi5
-rw-r--r--doc/lispref/streams.texi2
-rw-r--r--doc/lispref/strings.texi15
-rw-r--r--doc/lispref/symbols.texi42
-rw-r--r--doc/lispref/syntax.texi2
-rw-r--r--doc/lispref/text.texi131
-rw-r--r--doc/lispref/threads.texi2
-rw-r--r--doc/lispref/tips.texi45
-rw-r--r--doc/lispref/two-volume-cross-refs.txt2
-rw-r--r--doc/lispref/two-volume.make2
-rw-r--r--doc/lispref/variables.texi441
-rw-r--r--doc/lispref/windows.texi43
-rw-r--r--doc/man/ChangeLog.16
-rw-r--r--doc/man/ebrowse.12
-rw-r--r--doc/man/emacs.1.in2
-rw-r--r--doc/man/emacsclient.186
-rw-r--r--doc/man/etags.12
-rw-r--r--doc/misc/ChangeLog.18
-rw-r--r--doc/misc/Makefile.in2
-rw-r--r--doc/misc/auth.texi2
-rw-r--r--doc/misc/autotype.texi10
-rw-r--r--doc/misc/bovine.texi2
-rw-r--r--doc/misc/calc.texi12
-rw-r--r--doc/misc/cc-mode.texi9
-rw-r--r--doc/misc/cl.texi157
-rw-r--r--doc/misc/dbus.texi5
-rw-r--r--doc/misc/dired-x.texi2
-rw-r--r--doc/misc/ebrowse.texi2
-rw-r--r--doc/misc/ede.texi212
-rw-r--r--doc/misc/ediff.texi8
-rw-r--r--doc/misc/edt.texi2
-rw-r--r--doc/misc/efaq-w32.texi14
-rw-r--r--doc/misc/efaq.texi115
-rw-r--r--doc/misc/eglot.texi282
-rw-r--r--doc/misc/eieio.texi2
-rw-r--r--doc/misc/emacs-gnutls.texi2
-rw-r--r--doc/misc/emacs-mime.texi2
-rw-r--r--doc/misc/epa.texi9
-rw-r--r--doc/misc/erc.texi161
-rw-r--r--doc/misc/ert.texi122
-rw-r--r--doc/misc/eshell.texi82
-rw-r--r--doc/misc/eudc.texi2
-rw-r--r--doc/misc/eww.texi2
-rw-r--r--doc/misc/flymake.texi17
-rw-r--r--doc/misc/forms.texi2
-rw-r--r--doc/misc/gnus-faq.texi2
-rw-r--r--doc/misc/gnus.texi69
-rw-r--r--doc/misc/htmlfontify.texi2
-rw-r--r--doc/misc/idlwave.texi4
-rw-r--r--doc/misc/ido.texi2
-rw-r--r--doc/misc/info.texi2
-rw-r--r--doc/misc/mairix-el.texi2
-rw-r--r--doc/misc/message.texi2
-rw-r--r--doc/misc/mh-e.texi5
-rw-r--r--doc/misc/modus-themes.org161
-rw-r--r--doc/misc/newsticker.texi2
-rw-r--r--doc/misc/nxml-mode.texi2
-rw-r--r--doc/misc/octave-mode.texi8
-rw-r--r--doc/misc/org-setup.org2
-rw-r--r--doc/misc/org.org18
-rw-r--r--doc/misc/pcl-cvs.texi2
-rw-r--r--doc/misc/pgg.texi2
-rw-r--r--doc/misc/rcirc.texi6
-rw-r--r--doc/misc/reftex.texi2
-rw-r--r--doc/misc/remember.texi2
-rw-r--r--doc/misc/sasl.texi2
-rw-r--r--doc/misc/sc.texi2
-rw-r--r--doc/misc/sem-user.texi2
-rw-r--r--doc/misc/semantic.texi2
-rw-r--r--doc/misc/ses.texi301
-rw-r--r--doc/misc/sieve.texi2
-rw-r--r--doc/misc/smtpmail.texi8
-rw-r--r--doc/misc/speedbar.texi2
-rw-r--r--doc/misc/srecode.texi2
-rw-r--r--doc/misc/texinfo.tex4
-rw-r--r--doc/misc/todo-mode.texi2
-rw-r--r--doc/misc/tramp.texi165
-rw-r--r--doc/misc/trampver.texi2
-rw-r--r--doc/misc/transient.texi1000
-rw-r--r--doc/misc/url.texi46
-rw-r--r--doc/misc/use-package.texi6
-rw-r--r--doc/misc/vhdl-mode.texi2
-rw-r--r--doc/misc/vip.texi2
-rw-r--r--doc/misc/viper.texi7
-rw-r--r--doc/misc/vtable.texi2
-rw-r--r--doc/misc/widget.texi2469
-rw-r--r--doc/misc/wisent.texi5
-rw-r--r--doc/misc/woman.texi2
-rw-r--r--etc/AUTHORS128
-rw-r--r--etc/CALC-NEWS4
-rw-r--r--etc/ChangeLog.18
-rw-r--r--etc/DEBUG109
-rw-r--r--etc/DISTRIB2
-rw-r--r--etc/EGLOT-NEWS63
-rw-r--r--etc/ERC-NEWS415
-rw-r--r--etc/ETAGS.EBNF2
-rw-r--r--etc/ETAGS.README2
-rw-r--r--etc/HELLO2
-rw-r--r--etc/MACHINES2
-rw-r--r--etc/MH-E-NEWS2
-rw-r--r--etc/NEWS785
-rw-r--r--etc/NEWS.1-172
-rw-r--r--etc/NEWS.182
-rw-r--r--etc/NEWS.192
-rw-r--r--etc/NEWS.206
-rw-r--r--etc/NEWS.2122
-rw-r--r--etc/NEWS.224
-rw-r--r--etc/NEWS.2310
-rw-r--r--etc/NEWS.2414
-rw-r--r--etc/NEWS.252
-rw-r--r--etc/NEWS.264
-rw-r--r--etc/NEWS.272
-rw-r--r--etc/NEWS.282
-rw-r--r--etc/NEWS.2920
-rw-r--r--etc/NEXTSTEP2
-rw-r--r--etc/NXML-NEWS2
-rw-r--r--etc/ORG-NEWS4
-rw-r--r--etc/PROBLEMS101
-rw-r--r--etc/README2
-rw-r--r--etc/TERMS2
-rw-r--r--etc/TODO120
-rw-r--r--etc/charsets/README2
-rw-r--r--etc/compilation.txt2
-rw-r--r--etc/edt-user.el2
-rw-r--r--etc/emacs-buffer.gdb2
-rw-r--r--etc/emacs.metainfo.xml2
-rw-r--r--etc/emacs_lldb.py117
-rw-r--r--etc/emacsclient-mail.desktop7
-rw-r--r--etc/emacsclient.desktop2
-rw-r--r--etc/enriched.txt2
-rw-r--r--etc/forms/forms-d2.el2
-rw-r--r--etc/gnus-tut.txt2
-rw-r--r--etc/grep.txt2
-rw-r--r--etc/images/README19
-rw-r--r--etc/images/commit.pbmbin0 -> 81 bytes
-rw-r--r--etc/images/commit.xpm101
-rw-r--r--etc/images/custom/README2
-rw-r--r--etc/images/ezimage/README2
-rw-r--r--etc/images/gen-changelog.pbmbin0 -> 81 bytes
-rw-r--r--etc/images/gen-changelog.xpm152
-rw-r--r--etc/images/gnus/README6
-rw-r--r--etc/images/gnus/gnus-pointer.svg94
-rw-r--r--etc/images/gnus/gnus.svg2
-rw-r--r--etc/images/gud/README2
-rw-r--r--etc/images/icons/README8
-rw-r--r--etc/images/icons/hicolor/scalable/apps/emacs.svg2
-rw-r--r--etc/images/icons/hicolor/scalable/apps/emacs23.svg2
-rw-r--r--etc/images/icons/hicolor/scalable/mimetypes/emacs-document23.svg2
-rw-r--r--etc/images/ins-changelog.pbm3
-rw-r--r--etc/images/ins-changelog.xpm67
-rw-r--r--etc/images/load-changelog.pbmbin0 -> 81 bytes
-rw-r--r--etc/images/load-changelog.xpm82
-rw-r--r--etc/images/mpc/README2
-rw-r--r--etc/images/newsticker/README2
-rw-r--r--etc/images/smilies/README2
-rw-r--r--etc/images/smilies/grayscale/README2
-rw-r--r--etc/images/smilies/medium/README2
-rw-r--r--etc/images/splash.svg2
-rw-r--r--etc/images/symbols/README2
-rw-r--r--etc/images/symbols/dot_large_16.pbmbin0 -> 41 bytes
-rw-r--r--etc/images/symbols/dot_large_16.svg3
-rw-r--r--etc/images/symbols/dot_medium_16.pbmbin0 -> 41 bytes
-rw-r--r--etc/images/symbols/dot_medium_16.svg3
-rw-r--r--etc/images/symbols/dot_small_16.pbmbin0 -> 41 bytes
-rw-r--r--etc/images/symbols/dot_small_16.svg3
-rw-r--r--etc/images/symbols/minus_16.pbmbin41 -> 41 bytes
-rw-r--r--etc/images/symbols/minus_16.svg2
-rw-r--r--etc/images/symbols/plus_16.pbmbin41 -> 41 bytes
-rw-r--r--etc/images/symbols/plus_16.svg2
-rw-r--r--etc/images/tabs/README2
-rw-r--r--etc/images/tree-widget/default/README2
-rw-r--r--etc/images/tree-widget/folder/README2
-rw-r--r--etc/images/view-diff.pbmbin0 -> 81 bytes
-rw-r--r--etc/images/view-diff.xpm93
-rw-r--r--etc/org.gnu.emacs.defaults.gschema.xml2
-rw-r--r--etc/org/README2
-rw-r--r--etc/ps-prin0.ps2
-rw-r--r--etc/ps-prin1.ps2
-rw-r--r--etc/publicsuffix.txt4740
-rw-r--r--etc/refcards/Makefile2
-rw-r--r--etc/refcards/README4
-rw-r--r--etc/refcards/calccard.tex2
-rw-r--r--etc/refcards/cs-dired-ref.tex2
-rw-r--r--etc/refcards/cs-refcard.tex2
-rw-r--r--etc/refcards/cs-survival.tex2
-rw-r--r--etc/refcards/de-refcard.tex2
-rw-r--r--etc/refcards/dired-ref.tex2
-rw-r--r--etc/refcards/emacsver.tex.in2
-rw-r--r--etc/refcards/fr-dired-ref.tex2
-rw-r--r--etc/refcards/fr-refcard.tex2
-rw-r--r--etc/refcards/fr-survival.tex2
-rw-r--r--etc/refcards/gnus-logo.eps2
-rw-r--r--etc/refcards/gnus-refcard.tex2
-rw-r--r--etc/refcards/orgcard.tex4
-rw-r--r--etc/refcards/pdflayout.sty2
-rw-r--r--etc/refcards/pl-refcard.tex2
-rw-r--r--etc/refcards/pt-br-refcard.tex2
-rw-r--r--etc/refcards/refcard.tex2
-rw-r--r--etc/refcards/ru-refcard.tex6
-rw-r--r--etc/refcards/sk-dired-ref.tex2
-rw-r--r--etc/refcards/sk-refcard.tex2
-rw-r--r--etc/refcards/sk-survival.tex2
-rw-r--r--etc/refcards/survival.tex2
-rw-r--r--etc/refcards/vipcard.tex2
-rw-r--r--etc/refcards/viperCard.tex2
-rw-r--r--etc/schema/locate.rnc2
-rw-r--r--etc/schema/relaxng.rnc2
-rw-r--r--etc/schema/schemas.xml2
-rw-r--r--etc/ses-example.ses2
-rw-r--r--etc/srecode/c.srt2
-rw-r--r--etc/srecode/cpp.srt2
-rw-r--r--etc/srecode/default.srt2
-rw-r--r--etc/srecode/doc-cpp.srt2
-rw-r--r--etc/srecode/doc-default.srt2
-rw-r--r--etc/srecode/doc-java.srt2
-rw-r--r--etc/srecode/ede-autoconf.srt2
-rw-r--r--etc/srecode/ede-make.srt2
-rw-r--r--etc/srecode/el.srt2
-rw-r--r--etc/srecode/getset-cpp.srt2
-rw-r--r--etc/srecode/java.srt2
-rw-r--r--etc/srecode/make.srt2
-rw-r--r--etc/srecode/proj-test.srt2
-rw-r--r--etc/srecode/template.srt2
-rw-r--r--etc/srecode/test.srt2
-rw-r--r--etc/srecode/texi.srt2
-rw-r--r--etc/srecode/wisent.srt2
-rw-r--r--etc/themes/adwaita-theme.el2
-rw-r--r--etc/themes/deeper-blue-theme.el2
-rw-r--r--etc/themes/dichromacy-theme.el2
-rw-r--r--etc/themes/leuven-dark-theme.el2
-rw-r--r--etc/themes/leuven-theme.el2
-rw-r--r--etc/themes/light-blue-theme.el2
-rw-r--r--etc/themes/manoj-dark-theme.el15
-rw-r--r--etc/themes/misterioso-theme.el2
-rw-r--r--etc/themes/modus-operandi-deuteranopia-theme.el60
-rw-r--r--etc/themes/modus-operandi-theme.el58
-rw-r--r--etc/themes/modus-operandi-tinted-theme.el62
-rw-r--r--etc/themes/modus-operandi-tritanopia-theme.el62
-rw-r--r--etc/themes/modus-themes.el239
-rw-r--r--etc/themes/modus-vivendi-deuteranopia-theme.el58
-rw-r--r--etc/themes/modus-vivendi-theme.el56
-rw-r--r--etc/themes/modus-vivendi-tinted-theme.el56
-rw-r--r--etc/themes/modus-vivendi-tritanopia-theme.el59
-rw-r--r--etc/themes/tango-dark-theme.el2
-rw-r--r--etc/themes/tango-theme.el2
-rw-r--r--etc/themes/tsdh-dark-theme.el2
-rw-r--r--etc/themes/tsdh-light-theme.el2
-rw-r--r--etc/themes/wheatgrass-theme.el2
-rw-r--r--etc/themes/whiteboard-theme.el2
-rw-r--r--etc/themes/wombat-theme.el2
-rw-r--r--etc/tutorials/TUTORIAL2
-rw-r--r--etc/tutorials/TUTORIAL.bg2
-rw-r--r--etc/tutorials/TUTORIAL.cn4
-rw-r--r--etc/tutorials/TUTORIAL.cs2
-rw-r--r--etc/tutorials/TUTORIAL.de2
-rw-r--r--etc/tutorials/TUTORIAL.el_GR2
-rw-r--r--etc/tutorials/TUTORIAL.eo2
-rw-r--r--etc/tutorials/TUTORIAL.es2
-rw-r--r--etc/tutorials/TUTORIAL.fa3
-rw-r--r--etc/tutorials/TUTORIAL.fr2
-rw-r--r--etc/tutorials/TUTORIAL.he2
-rw-r--r--etc/tutorials/TUTORIAL.it2
-rw-r--r--etc/tutorials/TUTORIAL.ja2
-rw-r--r--etc/tutorials/TUTORIAL.ko2
-rw-r--r--etc/tutorials/TUTORIAL.nl4
-rw-r--r--etc/tutorials/TUTORIAL.pl2
-rw-r--r--etc/tutorials/TUTORIAL.pt_BR2
-rw-r--r--etc/tutorials/TUTORIAL.ro4
-rw-r--r--etc/tutorials/TUTORIAL.ru2
-rw-r--r--etc/tutorials/TUTORIAL.sk2
-rw-r--r--etc/tutorials/TUTORIAL.sl2
-rw-r--r--etc/tutorials/TUTORIAL.sv2
-rw-r--r--etc/tutorials/TUTORIAL.th2
-rw-r--r--etc/tutorials/TUTORIAL.uk2
-rw-r--r--etc/tutorials/TUTORIAL.zh2
-rw-r--r--etc/w32-feature.el2
-rw-r--r--exec/Makefile.in2
-rw-r--r--exec/config-mips.m4.in2
-rwxr-xr-xexec/config.guess28
-rwxr-xr-xexec/config.sub49
-rw-r--r--exec/configure.ac4
-rw-r--r--exec/deps.mk2
-rw-r--r--exec/exec.c4
-rw-r--r--exec/exec.h2
-rw-r--r--exec/exec1.c4
-rw-r--r--exec/loader-aarch64.s2
-rw-r--r--exec/loader-armeabi.s4
-rw-r--r--exec/loader-mips64el.s4
-rw-r--r--exec/loader-mipsel.s4
-rw-r--r--exec/loader-x86.s2
-rw-r--r--exec/loader-x86_64.s2
-rw-r--r--exec/mipsel-user.h2
-rw-r--r--exec/mipsfpu.c2
-rw-r--r--exec/mipsfpu.h2
-rw-r--r--exec/test.c2
-rw-r--r--exec/trace.c26
-rw-r--r--java/AndroidManifest.xml.in106
-rw-r--r--java/INSTALL22
-rw-r--r--java/Makefile.in9
-rw-r--r--java/README1027
-rwxr-xr-xjava/debug.sh2
-rw-r--r--java/org/gnu/emacs/EmacsActivity.java17
-rw-r--r--java/org/gnu/emacs/EmacsApplication.java75
-rw-r--r--java/org/gnu/emacs/EmacsClipboard.java2
-rw-r--r--java/org/gnu/emacs/EmacsContextMenu.java41
-rw-r--r--java/org/gnu/emacs/EmacsCursor.java2
-rw-r--r--java/org/gnu/emacs/EmacsDesktopNotification.java39
-rw-r--r--java/org/gnu/emacs/EmacsDialog.java47
-rw-r--r--java/org/gnu/emacs/EmacsDialogButtonLayout.java2
-rw-r--r--java/org/gnu/emacs/EmacsDirectoryEntry.java2
-rw-r--r--java/org/gnu/emacs/EmacsDocumentsProvider.java2
-rw-r--r--java/org/gnu/emacs/EmacsDrawLine.java6
-rw-r--r--java/org/gnu/emacs/EmacsDrawPoint.java2
-rw-r--r--java/org/gnu/emacs/EmacsDrawRectangle.java5
-rw-r--r--java/org/gnu/emacs/EmacsDrawable.java3
-rw-r--r--java/org/gnu/emacs/EmacsFillPolygon.java2
-rw-r--r--java/org/gnu/emacs/EmacsFillRectangle.java2
-rw-r--r--java/org/gnu/emacs/EmacsFontDriver.java13
-rw-r--r--java/org/gnu/emacs/EmacsGC.java2
-rw-r--r--java/org/gnu/emacs/EmacsHandleObject.java2
-rw-r--r--java/org/gnu/emacs/EmacsHolder.java2
-rw-r--r--java/org/gnu/emacs/EmacsInputConnection.java19
-rw-r--r--java/org/gnu/emacs/EmacsLauncherPreferencesActivity.java2
-rw-r--r--java/org/gnu/emacs/EmacsMultitaskActivity.java2
-rw-r--r--java/org/gnu/emacs/EmacsNative.java31
-rw-r--r--java/org/gnu/emacs/EmacsNoninteractive.java2
-rw-r--r--java/org/gnu/emacs/EmacsOpenActivity.java266
-rw-r--r--java/org/gnu/emacs/EmacsPixmap.java42
-rw-r--r--java/org/gnu/emacs/EmacsPreferencesActivity.java2
-rw-r--r--java/org/gnu/emacs/EmacsSafThread.java17
-rw-r--r--java/org/gnu/emacs/EmacsSdk11Clipboard.java28
-rw-r--r--java/org/gnu/emacs/EmacsSdk23FontDriver.java12
-rw-r--r--java/org/gnu/emacs/EmacsSdk7FontDriver.java214
-rw-r--r--java/org/gnu/emacs/EmacsSdk8Clipboard.java2
-rw-r--r--java/org/gnu/emacs/EmacsService.java537
-rw-r--r--java/org/gnu/emacs/EmacsSurfaceView.java2
-rw-r--r--java/org/gnu/emacs/EmacsThread.java2
-rw-r--r--java/org/gnu/emacs/EmacsView.java198
-rw-r--r--java/org/gnu/emacs/EmacsWindow.java400
-rw-r--r--java/org/gnu/emacs/EmacsWindowAttachmentManager.java26
-rw-r--r--java/res/drawable/emacs_background.xml2
-rw-r--r--java/res/drawable/emacs_foreground.xml2
-rw-r--r--java/res/layout/sdk8_notifications_view.xml2
-rw-r--r--java/res/mipmap-v26/emacs_icon.xml2
-rw-r--r--java/res/values-v11/style.xml2
-rw-r--r--java/res/values-v14/style.xml2
-rw-r--r--java/res/values-v19/bool.xml2
-rw-r--r--java/res/values-v24/bool.xml2
-rw-r--r--java/res/values-v29/style.xml2
-rw-r--r--java/res/values/bool.xml2
-rw-r--r--java/res/values/strings.xml2
-rw-r--r--java/res/values/style.xml2
-rw-r--r--java/res/xml/preferences.xml2
-rw-r--r--leim/ChangeLog.12
-rw-r--r--leim/Makefile.in11
-rw-r--r--leim/README2
-rw-r--r--leim/leim-ext.el2
-rw-r--r--lib-src/ChangeLog.110
-rw-r--r--lib-src/Makefile.in2
-rw-r--r--lib-src/asset-directory-tool.c2
-rw-r--r--lib-src/be_resources.cc2
-rw-r--r--lib-src/ebrowse.c2
-rw-r--r--lib-src/emacsclient.c19
-rw-r--r--lib-src/etags.c2
-rw-r--r--lib-src/hexl.c2
-rw-r--r--lib-src/make-docfile.c2
-rw-r--r--lib-src/make-fingerprint.c2
-rw-r--r--lib-src/movemail.c2
-rw-r--r--lib-src/ntlib.c2
-rw-r--r--lib-src/ntlib.h2
-rw-r--r--lib-src/pop.c2
-rw-r--r--lib-src/pop.h2
-rwxr-xr-xlib-src/rcs2log4
-rw-r--r--lib-src/seccomp-filter.c2
-rw-r--r--lib-src/update-game-score.c2
-rw-r--r--lib/Makefile.in2
-rw-r--r--lib/_Noreturn.h2
-rw-r--r--lib/acl-errno-valid.c2
-rw-r--r--lib/acl-internal.c2
-rw-r--r--lib/acl-internal.h2
-rw-r--r--lib/acl.h2
-rw-r--r--lib/acl_entries.c2
-rw-r--r--lib/af_alg.h2
-rw-r--r--lib/alloca.in.h4
-rw-r--r--lib/allocator.c2
-rw-r--r--lib/allocator.h2
-rw-r--r--lib/arg-nonnull.h2
-rw-r--r--lib/assert.in.h2
-rw-r--r--lib/at-func.c2
-rw-r--r--lib/attribute.h2
-rw-r--r--lib/binary-io.c2
-rw-r--r--lib/binary-io.h3
-rw-r--r--lib/boot-time-aux.h2
-rw-r--r--lib/boot-time.c2
-rw-r--r--lib/boot-time.h2
-rw-r--r--lib/byteswap.in.h2
-rw-r--r--lib/c++defs.h2
-rw-r--r--lib/c-ctype.c2
-rw-r--r--lib/c-ctype.h3
-rw-r--r--lib/c-strcase.h2
-rw-r--r--lib/c-strcasecmp.c3
-rw-r--r--lib/c-strncasecmp.c3
-rw-r--r--lib/canonicalize-lgpl.c2
-rw-r--r--lib/careadlinkat.c4
-rw-r--r--lib/careadlinkat.h2
-rw-r--r--lib/cdefs.h2
-rw-r--r--lib/cloexec.c3
-rw-r--r--lib/cloexec.h2
-rw-r--r--lib/close-stream.c3
-rw-r--r--lib/close-stream.h2
-rw-r--r--lib/copy-file-range.c2
-rw-r--r--lib/count-leading-zeros.c2
-rw-r--r--lib/count-leading-zeros.h2
-rw-r--r--lib/count-one-bits.c2
-rw-r--r--lib/count-one-bits.h2
-rw-r--r--lib/count-trailing-zeros.c2
-rw-r--r--lib/count-trailing-zeros.h2
-rw-r--r--lib/diffseq.h4
-rw-r--r--lib/dirent-private.h2
-rw-r--r--lib/dirent.in.h2
-rw-r--r--lib/dirfd.c2
-rw-r--r--lib/dtoastr.c2
-rw-r--r--lib/dtotimespec.c2
-rw-r--r--lib/dup2.c3
-rw-r--r--lib/dynarray.h2
-rw-r--r--lib/eloop-threshold.h2
-rw-r--r--lib/errno.in.h2
-rw-r--r--lib/euidaccess.c2
-rw-r--r--lib/execinfo.c2
-rw-r--r--lib/execinfo.in.h2
-rw-r--r--lib/explicit_bzero.c2
-rw-r--r--lib/faccessat.c2
-rw-r--r--lib/fchmodat.c2
-rw-r--r--lib/fcntl.c2
-rw-r--r--lib/fcntl.in.h2
-rw-r--r--lib/fdopendir.c2
-rw-r--r--lib/file-has-acl.c2
-rw-r--r--lib/filemode.c2
-rw-r--r--lib/filemode.h4
-rw-r--r--lib/filename.h2
-rw-r--r--lib/filevercmp.c2
-rw-r--r--lib/filevercmp.h2
-rw-r--r--lib/fingerprint.c2
-rw-r--r--lib/fingerprint.h2
-rw-r--r--lib/flexmember.h2
-rw-r--r--lib/fpending.c4
-rw-r--r--lib/fpending.h4
-rw-r--r--lib/free.c2
-rw-r--r--lib/fstatat.c2
-rw-r--r--lib/fsusage.c4
-rw-r--r--lib/fsusage.h2
-rw-r--r--lib/fsync.c2
-rw-r--r--lib/ftoastr.c2
-rw-r--r--lib/ftoastr.h2
-rw-r--r--lib/futimens.c2
-rw-r--r--lib/get-permissions.c2
-rw-r--r--lib/getdelim.c2
-rw-r--r--lib/getdtablesize.c2
-rw-r--r--lib/getgroups.c3
-rw-r--r--lib/getline.c2
-rw-r--r--lib/getloadavg.c4
-rw-r--r--lib/getopt-cdefs.in.h2
-rw-r--r--lib/getopt-core.h2
-rw-r--r--lib/getopt-ext.h2
-rw-r--r--lib/getopt-pfx-core.h2
-rw-r--r--lib/getopt-pfx-ext.h2
-rw-r--r--lib/getopt.c2
-rw-r--r--lib/getopt.in.h2
-rw-r--r--lib/getopt1.c2
-rw-r--r--lib/getopt_int.h2
-rw-r--r--lib/getrandom.c2
-rw-r--r--lib/gettext.h4
-rw-r--r--lib/gettime.c3
-rw-r--r--lib/gettimeofday.c3
-rw-r--r--lib/gnulib.mk.in2
-rw-r--r--lib/group-member.c4
-rw-r--r--lib/idx.h2
-rw-r--r--lib/ieee754.in.h2
-rw-r--r--lib/ignore-value.h2
-rw-r--r--lib/intprops-internal.h2
-rw-r--r--lib/intprops.h2
-rw-r--r--lib/inttypes.in.h2
-rw-r--r--lib/lchmod.c2
-rw-r--r--lib/libc-config.h2
-rw-r--r--lib/limits.in.h2
-rw-r--r--lib/lstat.c2
-rw-r--r--lib/malloc.c3
-rw-r--r--lib/malloc/dynarray-skeleton.c2
-rw-r--r--lib/malloc/dynarray.h2
-rw-r--r--lib/malloc/dynarray_at_failure.c2
-rw-r--r--lib/malloc/dynarray_emplace_enlarge.c2
-rw-r--r--lib/malloc/dynarray_finalize.c2
-rw-r--r--lib/malloc/dynarray_resize.c2
-rw-r--r--lib/malloc/dynarray_resize_clear.c2
-rw-r--r--lib/malloc/scratch_buffer.h2
-rw-r--r--lib/malloc/scratch_buffer_dupfree.c2
-rw-r--r--lib/malloc/scratch_buffer_grow.c2
-rw-r--r--lib/malloc/scratch_buffer_grow_preserve.c2
-rw-r--r--lib/malloc/scratch_buffer_set_array_size.c2
-rw-r--r--lib/md5-stream.c4
-rw-r--r--lib/md5.c4
-rw-r--r--lib/md5.h4
-rw-r--r--lib/memmem.c4
-rw-r--r--lib/mempcpy.c2
-rw-r--r--lib/memrchr.c4
-rw-r--r--lib/memset_explicit.c2
-rw-r--r--lib/mini-gmp-gnulib.c2
-rw-r--r--lib/minmax.h2
-rw-r--r--lib/mkostemp.c2
-rw-r--r--lib/mktime-internal.h2
-rw-r--r--lib/mktime.c2
-rw-r--r--lib/nanosleep.c3
-rw-r--r--lib/nproc.c2
-rw-r--r--lib/nproc.h2
-rw-r--r--lib/nstrftime.c2
-rw-r--r--lib/open.c2
-rw-r--r--lib/openat-priv.h2
-rw-r--r--lib/openat-proc.c2
-rw-r--r--lib/openat.h2
-rw-r--r--lib/pathmax.h2
-rw-r--r--lib/pipe2.c2
-rw-r--r--lib/pselect.c2
-rw-r--r--lib/pthread_sigmask.c2
-rw-r--r--lib/qcopy-acl.c2
-rw-r--r--lib/rawmemchr.c2
-rw-r--r--lib/rawmemchr.valgrind2
-rw-r--r--lib/readlink.c2
-rw-r--r--lib/readlinkat.c2
-rw-r--r--lib/readutmp.h2
-rw-r--r--lib/realloc.c2
-rw-r--r--lib/regcomp.c2
-rw-r--r--lib/regex.c2
-rw-r--r--lib/regex.h2
-rw-r--r--lib/regex_internal.c2
-rw-r--r--lib/regex_internal.h2
-rw-r--r--lib/regexec.c2
-rw-r--r--lib/root-uid.h2
-rw-r--r--lib/save-cwd.c2
-rw-r--r--lib/save-cwd.h4
-rw-r--r--lib/scratch_buffer.h2
-rw-r--r--lib/set-permissions.c2
-rw-r--r--lib/sha1.c3
-rw-r--r--lib/sha1.h2
-rw-r--r--lib/sha256.c2
-rw-r--r--lib/sha256.h2
-rw-r--r--lib/sha512.c2
-rw-r--r--lib/sha512.h2
-rw-r--r--lib/sig2str.c3
-rw-r--r--lib/sig2str.h2
-rw-r--r--lib/sigdescr_np.c2
-rw-r--r--lib/signal.in.h2
-rw-r--r--lib/stat-time.c2
-rw-r--r--lib/stat-time.h2
-rw-r--r--lib/stdalign.in.h2
-rw-r--r--lib/stdckdint.in.h2
-rw-r--r--lib/stddef.in.h2
-rw-r--r--lib/stdint.in.h2
-rw-r--r--lib/stdio-impl.h2
-rw-r--r--lib/stdio.in.h2
-rw-r--r--lib/stdlib.in.h3
-rw-r--r--lib/stpcpy.c2
-rw-r--r--lib/str-two-way.h2
-rw-r--r--lib/strftime.h2
-rw-r--r--lib/string.in.h2
-rw-r--r--lib/strnlen.c2
-rw-r--r--lib/strtoimax.c4
-rw-r--r--lib/strtol.c4
-rw-r--r--lib/strtoll.c4
-rw-r--r--lib/symlink.c2
-rw-r--r--lib/sys_random.in.h2
-rw-r--r--lib/sys_select.in.h2
-rw-r--r--lib/sys_stat.in.h2
-rw-r--r--lib/sys_time.in.h2
-rw-r--r--lib/sys_types.in.h2
-rw-r--r--lib/tempname.c2
-rw-r--r--lib/tempname.h2
-rw-r--r--lib/time-internal.h2
-rw-r--r--lib/time.in.h2
-rw-r--r--lib/time_r.c3
-rw-r--r--lib/time_rz.c2
-rw-r--r--lib/timegm.c2
-rw-r--r--lib/timespec-add.c2
-rw-r--r--lib/timespec-sub.c2
-rw-r--r--lib/timespec.c2
-rw-r--r--lib/timespec.h2
-rw-r--r--lib/u64.c2
-rw-r--r--lib/u64.h2
-rw-r--r--lib/unistd.c2
-rw-r--r--lib/unistd.in.h2
-rw-r--r--lib/unlocked-io.h2
-rw-r--r--lib/utimens.c2
-rw-r--r--lib/utimens.h2
-rw-r--r--lib/utimensat.c2
-rw-r--r--lib/verify.h2
-rw-r--r--lib/vla.h2
-rw-r--r--lib/warn-on-use.h2
-rw-r--r--lib/xalloc-oversized.h3
-rw-r--r--lisp/ChangeLog.12
-rw-r--r--lisp/ChangeLog.102
-rw-r--r--lisp/ChangeLog.112
-rw-r--r--lisp/ChangeLog.1210
-rw-r--r--lisp/ChangeLog.138
-rw-r--r--lisp/ChangeLog.1428
-rw-r--r--lisp/ChangeLog.1514
-rw-r--r--lisp/ChangeLog.1612
-rw-r--r--lisp/ChangeLog.176
-rw-r--r--lisp/ChangeLog.22
-rw-r--r--lisp/ChangeLog.32
-rw-r--r--lisp/ChangeLog.48
-rw-r--r--lisp/ChangeLog.54
-rw-r--r--lisp/ChangeLog.64
-rw-r--r--lisp/ChangeLog.74
-rw-r--r--lisp/ChangeLog.82
-rw-r--r--lisp/ChangeLog.92
-rw-r--r--lisp/Makefile.in4
-rw-r--r--lisp/abbrev.el41
-rw-r--r--lisp/align.el104
-rw-r--r--lisp/allout-widgets.el2
-rw-r--r--lisp/allout.el4
-rw-r--r--lisp/ansi-color.el2
-rw-r--r--lisp/ansi-osc.el2
-rw-r--r--lisp/apropos.el2
-rw-r--r--lisp/arc-mode.el40
-rw-r--r--lisp/array.el2
-rw-r--r--lisp/auth-source-pass.el8
-rw-r--r--lisp/auth-source.el11
-rw-r--r--lisp/autoinsert.el2
-rw-r--r--lisp/autorevert.el2
-rw-r--r--lisp/avoid.el2
-rw-r--r--lisp/battery.el2
-rw-r--r--lisp/bind-key.el (renamed from lisp/use-package/bind-key.el)5
-rw-r--r--lisp/bindings.el55
-rw-r--r--lisp/bookmark.el4
-rw-r--r--lisp/bs.el2
-rw-r--r--lisp/buff-menu.el2
-rw-r--r--lisp/button.el8
-rw-r--r--lisp/calc/calc-aent.el47
-rw-r--r--lisp/calc/calc-alg.el2
-rw-r--r--lisp/calc/calc-arith.el2
-rw-r--r--lisp/calc/calc-bin.el2
-rw-r--r--lisp/calc/calc-comb.el2
-rw-r--r--lisp/calc/calc-cplx.el2
-rw-r--r--lisp/calc/calc-embed.el2
-rw-r--r--lisp/calc/calc-ext.el2
-rw-r--r--lisp/calc/calc-fin.el2
-rw-r--r--lisp/calc/calc-forms.el2
-rw-r--r--lisp/calc/calc-frac.el2
-rw-r--r--lisp/calc/calc-funcs.el2
-rw-r--r--lisp/calc/calc-graph.el2
-rw-r--r--lisp/calc/calc-help.el2
-rw-r--r--lisp/calc/calc-incom.el2
-rw-r--r--lisp/calc/calc-keypd.el2
-rw-r--r--lisp/calc/calc-lang.el2
-rw-r--r--lisp/calc/calc-macs.el2
-rw-r--r--lisp/calc/calc-map.el2
-rw-r--r--lisp/calc/calc-math.el2
-rw-r--r--lisp/calc/calc-menu.el2
-rw-r--r--lisp/calc/calc-misc.el2
-rw-r--r--lisp/calc/calc-mode.el2
-rw-r--r--lisp/calc/calc-mtx.el2
-rw-r--r--lisp/calc/calc-nlfit.el2
-rw-r--r--lisp/calc/calc-poly.el2
-rw-r--r--lisp/calc/calc-prog.el2
-rw-r--r--lisp/calc/calc-rewr.el2
-rw-r--r--lisp/calc/calc-rules.el2
-rw-r--r--lisp/calc/calc-sel.el2
-rw-r--r--lisp/calc/calc-stat.el2
-rw-r--r--lisp/calc/calc-store.el2
-rw-r--r--lisp/calc/calc-stuff.el2
-rw-r--r--lisp/calc/calc-trail.el2
-rw-r--r--lisp/calc/calc-undo.el2
-rw-r--r--lisp/calc/calc-units.el140
-rw-r--r--lisp/calc/calc-vec.el2
-rw-r--r--lisp/calc/calc-yank.el2
-rw-r--r--lisp/calc/calc.el8
-rw-r--r--lisp/calc/calcalg2.el2
-rw-r--r--lisp/calc/calcalg3.el2
-rw-r--r--lisp/calc/calccomp.el2
-rw-r--r--lisp/calc/calcsel2.el2
-rw-r--r--lisp/calculator.el2
-rw-r--r--lisp/calendar/appt.el13
-rw-r--r--lisp/calendar/cal-bahai.el2
-rw-r--r--lisp/calendar/cal-china.el2
-rw-r--r--lisp/calendar/cal-coptic.el2
-rw-r--r--lisp/calendar/cal-dst.el2
-rw-r--r--lisp/calendar/cal-french.el2
-rw-r--r--lisp/calendar/cal-hebrew.el2
-rw-r--r--lisp/calendar/cal-html.el2
-rw-r--r--lisp/calendar/cal-islam.el2
-rw-r--r--lisp/calendar/cal-iso.el2
-rw-r--r--lisp/calendar/cal-julian.el2
-rw-r--r--lisp/calendar/cal-mayan.el2
-rw-r--r--lisp/calendar/cal-menu.el2
-rw-r--r--lisp/calendar/cal-move.el2
-rw-r--r--lisp/calendar/cal-persia.el2
-rw-r--r--lisp/calendar/cal-tex.el2
-rw-r--r--lisp/calendar/cal-x.el2
-rw-r--r--lisp/calendar/calendar.el2
-rw-r--r--lisp/calendar/diary-lib.el6
-rw-r--r--lisp/calendar/holidays.el2
-rw-r--r--lisp/calendar/icalendar.el7
-rw-r--r--lisp/calendar/iso8601.el2
-rw-r--r--lisp/calendar/lunar.el2
-rw-r--r--lisp/calendar/parse-time.el2
-rw-r--r--lisp/calendar/solar.el2
-rw-r--r--lisp/calendar/time-date.el10
-rw-r--r--lisp/calendar/timeclock.el12
-rw-r--r--lisp/calendar/todo-mode.el301
-rw-r--r--lisp/case-table.el2
-rw-r--r--lisp/cdl.el2
-rw-r--r--lisp/cedet/ChangeLog.14
-rw-r--r--lisp/cedet/cedet-cscope.el2
-rw-r--r--lisp/cedet/cedet-files.el2
-rw-r--r--lisp/cedet/cedet-global.el11
-rw-r--r--lisp/cedet/cedet-idutils.el2
-rw-r--r--lisp/cedet/cedet.el2
-rw-r--r--lisp/cedet/data-debug.el2
-rw-r--r--lisp/cedet/ede.el2
-rw-r--r--lisp/cedet/ede/auto.el2
-rw-r--r--lisp/cedet/ede/autoconf-edit.el2
-rw-r--r--lisp/cedet/ede/base.el5
-rw-r--r--lisp/cedet/ede/config.el2
-rw-r--r--lisp/cedet/ede/cpp-root.el2
-rw-r--r--lisp/cedet/ede/custom.el2
-rw-r--r--lisp/cedet/ede/detect.el2
-rw-r--r--lisp/cedet/ede/dired.el2
-rw-r--r--lisp/cedet/ede/emacs.el2
-rw-r--r--lisp/cedet/ede/files.el2
-rw-r--r--lisp/cedet/ede/generic.el2
-rw-r--r--lisp/cedet/ede/linux.el2
-rw-r--r--lisp/cedet/ede/locate.el2
-rw-r--r--lisp/cedet/ede/make.el2
-rw-r--r--lisp/cedet/ede/makefile-edit.el2
-rw-r--r--lisp/cedet/ede/pconf.el2
-rw-r--r--lisp/cedet/ede/pmake.el2
-rw-r--r--lisp/cedet/ede/proj-archive.el2
-rw-r--r--lisp/cedet/ede/proj-aux.el2
-rw-r--r--lisp/cedet/ede/proj-comp.el2
-rw-r--r--lisp/cedet/ede/proj-elisp.el2
-rw-r--r--lisp/cedet/ede/proj-info.el2
-rw-r--r--lisp/cedet/ede/proj-misc.el2
-rw-r--r--lisp/cedet/ede/proj-obj.el2
-rw-r--r--lisp/cedet/ede/proj-prog.el2
-rw-r--r--lisp/cedet/ede/proj-scheme.el2
-rw-r--r--lisp/cedet/ede/proj-shared.el2
-rw-r--r--lisp/cedet/ede/proj.el2
-rw-r--r--lisp/cedet/ede/project-am.el2
-rw-r--r--lisp/cedet/ede/shell.el2
-rw-r--r--lisp/cedet/ede/simple.el2
-rw-r--r--lisp/cedet/ede/source.el2
-rw-r--r--lisp/cedet/ede/speedbar.el2
-rw-r--r--lisp/cedet/ede/srecode.el2
-rw-r--r--lisp/cedet/ede/system.el2
-rw-r--r--lisp/cedet/ede/util.el2
-rw-r--r--lisp/cedet/mode-local.el69
-rw-r--r--lisp/cedet/pulse.el6
-rw-r--r--lisp/cedet/semantic.el2
-rw-r--r--lisp/cedet/semantic/analyze.el2
-rw-r--r--lisp/cedet/semantic/analyze/complete.el2
-rw-r--r--lisp/cedet/semantic/analyze/debug.el2
-rw-r--r--lisp/cedet/semantic/analyze/fcn.el2
-rw-r--r--lisp/cedet/semantic/analyze/refs.el2
-rw-r--r--lisp/cedet/semantic/bovine.el2
-rw-r--r--lisp/cedet/semantic/bovine/c.el2
-rw-r--r--lisp/cedet/semantic/bovine/debug.el2
-rw-r--r--lisp/cedet/semantic/bovine/el.el2
-rw-r--r--lisp/cedet/semantic/bovine/gcc.el2
-rw-r--r--lisp/cedet/semantic/bovine/grammar.el2
-rw-r--r--lisp/cedet/semantic/bovine/make.el2
-rw-r--r--lisp/cedet/semantic/bovine/scm.el2
-rw-r--r--lisp/cedet/semantic/chart.el2
-rw-r--r--lisp/cedet/semantic/complete.el4
-rw-r--r--lisp/cedet/semantic/ctxt.el2
-rw-r--r--lisp/cedet/semantic/db-debug.el2
-rw-r--r--lisp/cedet/semantic/db-ebrowse.el2
-rw-r--r--lisp/cedet/semantic/db-el.el2
-rw-r--r--lisp/cedet/semantic/db-file.el2
-rw-r--r--lisp/cedet/semantic/db-find.el2
-rw-r--r--lisp/cedet/semantic/db-global.el2
-rw-r--r--lisp/cedet/semantic/db-javascript.el2
-rw-r--r--lisp/cedet/semantic/db-mode.el2
-rw-r--r--lisp/cedet/semantic/db-ref.el2
-rw-r--r--lisp/cedet/semantic/db-typecache.el2
-rw-r--r--lisp/cedet/semantic/db.el8
-rw-r--r--lisp/cedet/semantic/debug.el2
-rw-r--r--lisp/cedet/semantic/decorate.el2
-rw-r--r--lisp/cedet/semantic/decorate/include.el2
-rw-r--r--lisp/cedet/semantic/decorate/mode.el2
-rw-r--r--lisp/cedet/semantic/dep.el2
-rw-r--r--lisp/cedet/semantic/doc.el2
-rw-r--r--lisp/cedet/semantic/ede-grammar.el2
-rw-r--r--lisp/cedet/semantic/edit.el2
-rw-r--r--lisp/cedet/semantic/find.el2
-rw-r--r--lisp/cedet/semantic/format.el2
-rw-r--r--lisp/cedet/semantic/fw.el7
-rw-r--r--lisp/cedet/semantic/grammar.el13
-rw-r--r--lisp/cedet/semantic/grm-wy-boot.el2
-rw-r--r--lisp/cedet/semantic/html.el2
-rw-r--r--lisp/cedet/semantic/ia-sb.el2
-rw-r--r--lisp/cedet/semantic/ia.el2
-rw-r--r--lisp/cedet/semantic/idle.el2
-rw-r--r--lisp/cedet/semantic/imenu.el8
-rw-r--r--lisp/cedet/semantic/java.el2
-rw-r--r--lisp/cedet/semantic/lex-spp.el8
-rw-r--r--lisp/cedet/semantic/lex.el2
-rw-r--r--lisp/cedet/semantic/mru-bookmark.el2
-rw-r--r--lisp/cedet/semantic/sb.el2
-rw-r--r--lisp/cedet/semantic/scope.el2
-rw-r--r--lisp/cedet/semantic/senator.el2
-rw-r--r--lisp/cedet/semantic/sort.el2
-rw-r--r--lisp/cedet/semantic/symref.el2
-rw-r--r--lisp/cedet/semantic/symref/cscope.el2
-rw-r--r--lisp/cedet/semantic/symref/filter.el2
-rw-r--r--lisp/cedet/semantic/symref/global.el2
-rw-r--r--lisp/cedet/semantic/symref/grep.el2
-rw-r--r--lisp/cedet/semantic/symref/idutils.el2
-rw-r--r--lisp/cedet/semantic/symref/list.el2
-rw-r--r--lisp/cedet/semantic/tag-file.el2
-rw-r--r--lisp/cedet/semantic/tag-ls.el2
-rw-r--r--lisp/cedet/semantic/tag-write.el2
-rw-r--r--lisp/cedet/semantic/tag.el2
-rw-r--r--lisp/cedet/semantic/texi.el2
-rw-r--r--lisp/cedet/semantic/util-modes.el2
-rw-r--r--lisp/cedet/semantic/util.el2
-rw-r--r--lisp/cedet/semantic/wisent.el2
-rw-r--r--lisp/cedet/semantic/wisent/comp.el2
-rw-r--r--lisp/cedet/semantic/wisent/grammar.el2
-rw-r--r--lisp/cedet/semantic/wisent/java-tags.el2
-rw-r--r--lisp/cedet/semantic/wisent/javascript.el2
-rw-r--r--lisp/cedet/semantic/wisent/python.el27
-rw-r--r--lisp/cedet/semantic/wisent/wisent.el2
-rw-r--r--lisp/cedet/srecode.el2
-rw-r--r--lisp/cedet/srecode/args.el2
-rw-r--r--lisp/cedet/srecode/compile.el2
-rw-r--r--lisp/cedet/srecode/cpp.el2
-rw-r--r--lisp/cedet/srecode/ctxt.el2
-rw-r--r--lisp/cedet/srecode/dictionary.el2
-rw-r--r--lisp/cedet/srecode/document.el2
-rw-r--r--lisp/cedet/srecode/el.el2
-rw-r--r--lisp/cedet/srecode/expandproto.el2
-rw-r--r--lisp/cedet/srecode/extract.el4
-rw-r--r--lisp/cedet/srecode/fields.el2
-rw-r--r--lisp/cedet/srecode/filters.el2
-rw-r--r--lisp/cedet/srecode/find.el66
-rw-r--r--lisp/cedet/srecode/getset.el2
-rw-r--r--lisp/cedet/srecode/insert.el2
-rw-r--r--lisp/cedet/srecode/java.el2
-rw-r--r--lisp/cedet/srecode/map.el7
-rw-r--r--lisp/cedet/srecode/mode.el2
-rw-r--r--lisp/cedet/srecode/semantic.el2
-rw-r--r--lisp/cedet/srecode/srt-mode.el4
-rw-r--r--lisp/cedet/srecode/srt.el2
-rw-r--r--lisp/cedet/srecode/table.el53
-rw-r--r--lisp/cedet/srecode/template.el2
-rw-r--r--lisp/cedet/srecode/texi.el2
-rw-r--r--lisp/char-fold.el2
-rw-r--r--lisp/chistory.el2
-rw-r--r--lisp/cmuscheme.el2
-rw-r--r--lisp/color.el2
-rw-r--r--lisp/comint.el9
-rw-r--r--lisp/completion-preview.el417
-rw-r--r--lisp/completion.el22
-rw-r--r--lisp/composite.el2
-rw-r--r--lisp/cus-dep.el2
-rw-r--r--lisp/cus-edit.el375
-rw-r--r--lisp/cus-face.el2
-rw-r--r--lisp/cus-start.el2
-rw-r--r--lisp/cus-theme.el36
-rw-r--r--lisp/custom.el4
-rw-r--r--lisp/dabbrev.el2
-rw-r--r--lisp/delim-col.el2
-rw-r--r--lisp/delsel.el2
-rw-r--r--lisp/descr-text.el2
-rw-r--r--lisp/desktop.el4
-rw-r--r--lisp/dframe.el2
-rw-r--r--lisp/dired-aux.el288
-rw-r--r--lisp/dired-x.el49
-rw-r--r--lisp/dired.el669
-rw-r--r--lisp/dirtrack.el2
-rw-r--r--lisp/disp-table.el2
-rw-r--r--lisp/display-fill-column-indicator.el2
-rw-r--r--lisp/display-line-numbers.el2
-rw-r--r--lisp/dnd.el118
-rw-r--r--lisp/doc-view.el55
-rw-r--r--lisp/dom.el2
-rw-r--r--lisp/dos-fns.el2
-rw-r--r--lisp/dos-vars.el2
-rw-r--r--lisp/dos-w32.el2
-rw-r--r--lisp/double.el2
-rw-r--r--lisp/dynamic-setting.el2
-rw-r--r--lisp/ebuff-menu.el2
-rw-r--r--lisp/echistory.el2
-rw-r--r--lisp/ecomplete.el2
-rw-r--r--lisp/edmacro.el130
-rw-r--r--lisp/ehelp.el2
-rw-r--r--lisp/elec-pair.el4
-rw-r--r--lisp/electric.el2
-rw-r--r--lisp/elide-head.el2
-rw-r--r--lisp/emacs-lisp/advice.el9
-rw-r--r--lisp/emacs-lisp/avl-tree.el2
-rw-r--r--lisp/emacs-lisp/backquote.el2
-rw-r--r--lisp/emacs-lisp/backtrace.el2
-rw-r--r--lisp/emacs-lisp/benchmark.el2
-rw-r--r--lisp/emacs-lisp/bindat.el2
-rw-r--r--lisp/emacs-lisp/byte-opt.el98
-rw-r--r--lisp/emacs-lisp/byte-run.el9
-rw-r--r--lisp/emacs-lisp/bytecomp.el1044
-rw-r--r--lisp/emacs-lisp/cconv.el577
-rw-r--r--lisp/emacs-lisp/chart.el2
-rw-r--r--lisp/emacs-lisp/check-declare.el2
-rw-r--r--lisp/emacs-lisp/checkdoc.el20
-rw-r--r--lisp/emacs-lisp/cl-extra.el28
-rw-r--r--lisp/emacs-lisp/cl-generic.el12
-rw-r--r--lisp/emacs-lisp/cl-indent.el2
-rw-r--r--lisp/emacs-lisp/cl-lib.el24
-rw-r--r--lisp/emacs-lisp/cl-macs.el127
-rw-r--r--lisp/emacs-lisp/cl-preloaded.el31
-rw-r--r--lisp/emacs-lisp/cl-print.el136
-rw-r--r--lisp/emacs-lisp/cl-seq.el2
-rw-r--r--lisp/emacs-lisp/comp-common.el553
-rw-r--r--lisp/emacs-lisp/comp-cstr.el171
-rw-r--r--lisp/emacs-lisp/comp-run.el460
-rw-r--r--lisp/emacs-lisp/comp.el1235
-rw-r--r--lisp/emacs-lisp/copyright.el2
-rw-r--r--lisp/emacs-lisp/crm.el2
-rw-r--r--lisp/emacs-lisp/cursor-sensor.el2
-rw-r--r--lisp/emacs-lisp/debug-early.el2
-rw-r--r--lisp/emacs-lisp/debug.el71
-rw-r--r--lisp/emacs-lisp/derived.el6
-rw-r--r--lisp/emacs-lisp/disass.el36
-rw-r--r--lisp/emacs-lisp/easy-mmode.el4
-rw-r--r--lisp/emacs-lisp/easymenu.el2
-rw-r--r--lisp/emacs-lisp/edebug.el54
-rw-r--r--lisp/emacs-lisp/eieio-base.el2
-rw-r--r--lisp/emacs-lisp/eieio-core.el68
-rw-r--r--lisp/emacs-lisp/eieio-custom.el2
-rw-r--r--lisp/emacs-lisp/eieio-datadebug.el2
-rw-r--r--lisp/emacs-lisp/eieio-opt.el2
-rw-r--r--lisp/emacs-lisp/eieio-speedbar.el2
-rw-r--r--lisp/emacs-lisp/eieio.el17
-rw-r--r--lisp/emacs-lisp/eldoc.el44
-rw-r--r--lisp/emacs-lisp/elint.el29
-rw-r--r--lisp/emacs-lisp/elp.el2
-rw-r--r--lisp/emacs-lisp/ert-font-lock.el364
-rw-r--r--lisp/emacs-lisp/ert-x.el2
-rw-r--r--lisp/emacs-lisp/ert.el45
-rw-r--r--lisp/emacs-lisp/ewoc.el2
-rw-r--r--lisp/emacs-lisp/faceup.el2
-rw-r--r--lisp/emacs-lisp/find-func.el27
-rw-r--r--lisp/emacs-lisp/float-sup.el2
-rw-r--r--lisp/emacs-lisp/generate-lisp-file.el2
-rw-r--r--lisp/emacs-lisp/generator.el2
-rw-r--r--lisp/emacs-lisp/generic.el2
-rw-r--r--lisp/emacs-lisp/gv.el17
-rw-r--r--lisp/emacs-lisp/helper.el2
-rw-r--r--lisp/emacs-lisp/hierarchy.el2
-rw-r--r--lisp/emacs-lisp/icons.el8
-rw-r--r--lisp/emacs-lisp/inline.el2
-rw-r--r--lisp/emacs-lisp/let-alist.el17
-rw-r--r--lisp/emacs-lisp/lisp-mnt.el35
-rw-r--r--lisp/emacs-lisp/lisp-mode.el7
-rw-r--r--lisp/emacs-lisp/lisp.el7
-rw-r--r--lisp/emacs-lisp/loaddefs-gen.el3
-rw-r--r--lisp/emacs-lisp/macroexp.el87
-rw-r--r--lisp/emacs-lisp/map-ynp.el12
-rw-r--r--lisp/emacs-lisp/map.el5
-rw-r--r--lisp/emacs-lisp/memory-report.el2
-rw-r--r--lisp/emacs-lisp/multisession.el4
-rw-r--r--lisp/emacs-lisp/nadvice.el42
-rw-r--r--lisp/emacs-lisp/oclosure.el4
-rw-r--r--lisp/emacs-lisp/package-vc.el312
-rw-r--r--lisp/emacs-lisp/package-x.el2
-rw-r--r--lisp/emacs-lisp/package.el100
-rw-r--r--lisp/emacs-lisp/pcase.el12
-rw-r--r--lisp/emacs-lisp/pp.el5
-rw-r--r--lisp/emacs-lisp/radix-tree.el2
-rw-r--r--lisp/emacs-lisp/range.el2
-rw-r--r--lisp/emacs-lisp/re-builder.el2
-rw-r--r--lisp/emacs-lisp/regexp-opt.el2
-rw-r--r--lisp/emacs-lisp/regi.el2
-rw-r--r--lisp/emacs-lisp/ring.el2
-rw-r--r--lisp/emacs-lisp/rmc.el5
-rw-r--r--lisp/emacs-lisp/rx.el2
-rw-r--r--lisp/emacs-lisp/seq.el17
-rw-r--r--lisp/emacs-lisp/shadow.el2
-rw-r--r--lisp/emacs-lisp/shortdoc.el4
-rw-r--r--lisp/emacs-lisp/shorthands.el26
-rw-r--r--lisp/emacs-lisp/smie.el6
-rw-r--r--lisp/emacs-lisp/subr-x.el9
-rw-r--r--lisp/emacs-lisp/syntax.el290
-rw-r--r--lisp/emacs-lisp/tabulated-list.el2
-rw-r--r--lisp/emacs-lisp/tcover-ses.el2
-rw-r--r--lisp/emacs-lisp/testcover.el2
-rw-r--r--lisp/emacs-lisp/text-property-search.el2
-rw-r--r--lisp/emacs-lisp/thunk.el2
-rw-r--r--lisp/emacs-lisp/timer-list.el2
-rw-r--r--lisp/emacs-lisp/timer.el2
-rw-r--r--lisp/emacs-lisp/tq.el2
-rw-r--r--lisp/emacs-lisp/trace.el12
-rw-r--r--lisp/emacs-lisp/unsafep.el2
-rw-r--r--lisp/emacs-lisp/vtable.el7
-rw-r--r--lisp/emacs-lisp/warnings.el3
-rw-r--r--lisp/emacs-lock.el2
-rw-r--r--lisp/emulation/cua-base.el4
-rw-r--r--lisp/emulation/cua-gmrk.el2
-rw-r--r--lisp/emulation/cua-rect.el2
-rw-r--r--lisp/emulation/edt-lk201.el2
-rw-r--r--lisp/emulation/edt-mapper.el2
-rw-r--r--lisp/emulation/edt-pc.el2
-rw-r--r--lisp/emulation/edt-vt100.el2
-rw-r--r--lisp/emulation/edt.el2
-rw-r--r--lisp/emulation/keypad.el2
-rw-r--r--lisp/emulation/viper-cmd.el2
-rw-r--r--lisp/emulation/viper-ex.el2
-rw-r--r--lisp/emulation/viper-init.el2
-rw-r--r--lisp/emulation/viper-keym.el2
-rw-r--r--lisp/emulation/viper-macs.el2
-rw-r--r--lisp/emulation/viper-mous.el2
-rw-r--r--lisp/emulation/viper-util.el2
-rw-r--r--lisp/emulation/viper.el12
-rw-r--r--lisp/env.el2
-rw-r--r--lisp/epa-dired.el2
-rw-r--r--lisp/epa-file.el2
-rw-r--r--lisp/epa-hook.el2
-rw-r--r--lisp/epa-ks.el3
-rw-r--r--lisp/epa-mail.el2
-rw-r--r--lisp/epa.el4
-rw-r--r--lisp/epg-config.el2
-rw-r--r--lisp/epg.el68
-rw-r--r--lisp/erc/ChangeLog.12
-rw-r--r--lisp/erc/ChangeLog.22
-rw-r--r--lisp/erc/erc-autoaway.el2
-rw-r--r--lisp/erc/erc-backend.el319
-rw-r--r--lisp/erc/erc-button.el197
-rw-r--r--lisp/erc/erc-capab.el2
-rw-r--r--lisp/erc/erc-common.el177
-rw-r--r--lisp/erc/erc-compat.el37
-rw-r--r--lisp/erc/erc-dcc.el17
-rw-r--r--lisp/erc/erc-desktop-notifications.el2
-rw-r--r--lisp/erc/erc-ezbounce.el2
-rw-r--r--lisp/erc/erc-fill.el521
-rw-r--r--lisp/erc/erc-goodies.el362
-rw-r--r--lisp/erc/erc-ibuffer.el18
-rw-r--r--lisp/erc/erc-identd.el2
-rw-r--r--lisp/erc/erc-imenu.el2
-rw-r--r--lisp/erc/erc-join.el2
-rw-r--r--lisp/erc/erc-lang.el2
-rw-r--r--lisp/erc/erc-list.el2
-rw-r--r--lisp/erc/erc-log.el20
-rw-r--r--lisp/erc/erc-match.el51
-rw-r--r--lisp/erc/erc-menu.el2
-rw-r--r--lisp/erc/erc-netsplit.el15
-rw-r--r--lisp/erc/erc-networks.el75
-rw-r--r--lisp/erc/erc-nicks.el183
-rw-r--r--lisp/erc/erc-notify.el87
-rw-r--r--lisp/erc/erc-page.el5
-rw-r--r--lisp/erc/erc-pcomplete.el2
-rw-r--r--lisp/erc/erc-replace.el2
-rw-r--r--lisp/erc/erc-ring.el2
-rw-r--r--lisp/erc/erc-sasl.el16
-rw-r--r--lisp/erc/erc-services.el4
-rw-r--r--lisp/erc/erc-sound.el5
-rw-r--r--lisp/erc/erc-speedbar.el220
-rw-r--r--lisp/erc/erc-spelling.el2
-rw-r--r--lisp/erc/erc-stamp.el490
-rw-r--r--lisp/erc/erc-status-sidebar.el23
-rw-r--r--lisp/erc/erc-track.el286
-rw-r--r--lisp/erc/erc-truncate.el49
-rw-r--r--lisp/erc/erc-xdcc.el2
-rw-r--r--lisp/erc/erc.el2573
-rw-r--r--lisp/eshell/em-alias.el2
-rw-r--r--lisp/eshell/em-banner.el2
-rw-r--r--lisp/eshell/em-basic.el34
-rw-r--r--lisp/eshell/em-cmpl.el30
-rw-r--r--lisp/eshell/em-dirs.el17
-rw-r--r--lisp/eshell/em-elecslash.el2
-rw-r--r--lisp/eshell/em-extpipe.el163
-rw-r--r--lisp/eshell/em-glob.el6
-rw-r--r--lisp/eshell/em-hist.el94
-rw-r--r--lisp/eshell/em-ls.el8
-rw-r--r--lisp/eshell/em-pred.el26
-rw-r--r--lisp/eshell/em-prompt.el62
-rw-r--r--lisp/eshell/em-rebind.el2
-rw-r--r--lisp/eshell/em-script.el34
-rw-r--r--lisp/eshell/em-smart.el85
-rw-r--r--lisp/eshell/em-term.el2
-rw-r--r--lisp/eshell/em-tramp.el2
-rw-r--r--lisp/eshell/em-unix.el4
-rw-r--r--lisp/eshell/em-xtra.el2
-rw-r--r--lisp/eshell/esh-arg.el272
-rw-r--r--lisp/eshell/esh-cmd.el587
-rw-r--r--lisp/eshell/esh-ext.el2
-rw-r--r--lisp/eshell/esh-io.el19
-rw-r--r--lisp/eshell/esh-mode.el9
-rw-r--r--lisp/eshell/esh-module.el2
-rw-r--r--lisp/eshell/esh-opt.el2
-rw-r--r--lisp/eshell/esh-proc.el288
-rw-r--r--lisp/eshell/esh-util.el129
-rw-r--r--lisp/eshell/esh-var.el72
-rw-r--r--lisp/eshell/eshell.el11
-rw-r--r--lisp/expand.el2
-rw-r--r--lisp/external-completion.el5
-rw-r--r--lisp/ezimage.el2
-rw-r--r--lisp/face-remap.el2
-rw-r--r--lisp/facemenu.el2
-rw-r--r--lisp/faces.el34
-rw-r--r--lisp/ffap.el27
-rw-r--r--lisp/filecache.el2
-rw-r--r--lisp/fileloop.el2
-rw-r--r--lisp/filenotify.el16
-rw-r--r--lisp/files-x.el158
-rw-r--r--lisp/files.el681
-rw-r--r--lisp/filesets.el45
-rw-r--r--lisp/find-cmd.el2
-rw-r--r--lisp/find-dired.el2
-rw-r--r--lisp/find-file.el2
-rw-r--r--lisp/find-lisp.el2
-rw-r--r--lisp/finder.el10
-rw-r--r--lisp/flow-ctrl.el2
-rw-r--r--lisp/foldout.el2
-rw-r--r--lisp/follow.el2
-rw-r--r--lisp/font-core.el2
-rw-r--r--lisp/font-lock.el6
-rw-r--r--lisp/format-spec.el2
-rw-r--r--lisp/format.el4
-rw-r--r--lisp/forms.el2
-rw-r--r--lisp/frame.el4
-rw-r--r--lisp/frameset.el2
-rw-r--r--lisp/fringe.el2
-rw-r--r--lisp/generic-x.el2
-rw-r--r--lisp/gnus/ChangeLog.16
-rw-r--r--lisp/gnus/ChangeLog.26
-rw-r--r--lisp/gnus/ChangeLog.38
-rw-r--r--lisp/gnus/canlock.el2
-rw-r--r--lisp/gnus/deuglify.el2
-rw-r--r--lisp/gnus/gmm-utils.el2
-rw-r--r--lisp/gnus/gnus-agent.el2
-rw-r--r--lisp/gnus/gnus-art.el29
-rw-r--r--lisp/gnus/gnus-async.el2
-rw-r--r--lisp/gnus/gnus-bcklg.el2
-rw-r--r--lisp/gnus/gnus-bookmark.el10
-rw-r--r--lisp/gnus/gnus-cache.el2
-rw-r--r--lisp/gnus/gnus-cite.el8
-rw-r--r--lisp/gnus/gnus-cloud.el3
-rw-r--r--lisp/gnus/gnus-cus.el2
-rw-r--r--lisp/gnus/gnus-dbus.el2
-rw-r--r--lisp/gnus/gnus-delay.el2
-rw-r--r--lisp/gnus/gnus-demon.el2
-rw-r--r--lisp/gnus/gnus-diary.el2
-rw-r--r--lisp/gnus/gnus-dired.el2
-rw-r--r--lisp/gnus/gnus-draft.el2
-rw-r--r--lisp/gnus/gnus-dup.el2
-rw-r--r--lisp/gnus/gnus-eform.el2
-rw-r--r--lisp/gnus/gnus-fun.el2
-rw-r--r--lisp/gnus/gnus-gravatar.el2
-rw-r--r--lisp/gnus/gnus-group.el36
-rw-r--r--lisp/gnus/gnus-html.el2
-rw-r--r--lisp/gnus/gnus-icalendar.el2
-rw-r--r--lisp/gnus/gnus-int.el2
-rw-r--r--lisp/gnus/gnus-kill.el2
-rw-r--r--lisp/gnus/gnus-logic.el12
-rw-r--r--lisp/gnus/gnus-mh.el2
-rw-r--r--lisp/gnus/gnus-ml.el2
-rw-r--r--lisp/gnus/gnus-mlspl.el2
-rw-r--r--lisp/gnus/gnus-msg.el40
-rw-r--r--lisp/gnus/gnus-notifications.el2
-rw-r--r--lisp/gnus/gnus-picon.el2
-rw-r--r--lisp/gnus/gnus-range.el2
-rw-r--r--lisp/gnus/gnus-registry.el2
-rw-r--r--lisp/gnus/gnus-rfc1843.el2
-rw-r--r--lisp/gnus/gnus-rmail.el2
-rw-r--r--lisp/gnus/gnus-salt.el2
-rw-r--r--lisp/gnus/gnus-score.el13
-rw-r--r--lisp/gnus/gnus-search.el11
-rw-r--r--lisp/gnus/gnus-sieve.el2
-rw-r--r--lisp/gnus/gnus-spec.el2
-rw-r--r--lisp/gnus/gnus-srvr.el2
-rw-r--r--lisp/gnus/gnus-start.el2
-rw-r--r--lisp/gnus/gnus-sum.el47
-rw-r--r--lisp/gnus/gnus-topic.el2
-rw-r--r--lisp/gnus/gnus-undo.el2
-rw-r--r--lisp/gnus/gnus-util.el10
-rw-r--r--lisp/gnus/gnus-uu.el5
-rw-r--r--lisp/gnus/gnus-vm.el2
-rw-r--r--lisp/gnus/gnus-win.el2
-rw-r--r--lisp/gnus/gnus.el17
-rw-r--r--lisp/gnus/gssapi.el2
-rw-r--r--lisp/gnus/legacy-gnus-agent.el2
-rw-r--r--lisp/gnus/mail-source.el2
-rw-r--r--lisp/gnus/message.el106
-rw-r--r--lisp/gnus/mm-archive.el2
-rw-r--r--lisp/gnus/mm-bodies.el2
-rw-r--r--lisp/gnus/mm-decode.el8
-rw-r--r--lisp/gnus/mm-encode.el2
-rw-r--r--lisp/gnus/mm-extern.el2
-rw-r--r--lisp/gnus/mm-partial.el2
-rw-r--r--lisp/gnus/mm-url.el2
-rw-r--r--lisp/gnus/mm-util.el2
-rw-r--r--lisp/gnus/mm-uu.el2
-rw-r--r--lisp/gnus/mm-view.el4
-rw-r--r--lisp/gnus/mml-sec.el2
-rw-r--r--lisp/gnus/mml-smime.el2
-rw-r--r--lisp/gnus/mml.el61
-rw-r--r--lisp/gnus/mml1991.el2
-rw-r--r--lisp/gnus/mml2015.el6
-rw-r--r--lisp/gnus/nnagent.el2
-rw-r--r--lisp/gnus/nnbabyl.el2
-rw-r--r--lisp/gnus/nndiary.el4
-rw-r--r--lisp/gnus/nndir.el2
-rw-r--r--lisp/gnus/nndoc.el2
-rw-r--r--lisp/gnus/nndraft.el2
-rw-r--r--lisp/gnus/nneething.el2
-rw-r--r--lisp/gnus/nnfolder.el2
-rw-r--r--lisp/gnus/nngateway.el2
-rw-r--r--lisp/gnus/nnheader.el4
-rw-r--r--lisp/gnus/nnimap.el2
-rw-r--r--lisp/gnus/nnmail.el6
-rw-r--r--lisp/gnus/nnmairix.el5
-rw-r--r--lisp/gnus/nnmbox.el2
-rw-r--r--lisp/gnus/nnmh.el2
-rw-r--r--lisp/gnus/nnml.el4
-rw-r--r--lisp/gnus/nnoo.el2
-rw-r--r--lisp/gnus/nnregistry.el2
-rw-r--r--lisp/gnus/nnrss.el4
-rw-r--r--lisp/gnus/nnselect.el2
-rw-r--r--lisp/gnus/nnspool.el2
-rw-r--r--lisp/gnus/nntp.el2
-rw-r--r--lisp/gnus/nnvirtual.el2
-rw-r--r--lisp/gnus/nnweb.el41
-rw-r--r--lisp/gnus/score-mode.el2
-rw-r--r--lisp/gnus/smiley.el2
-rw-r--r--lisp/gnus/smime.el2
-rw-r--r--lisp/gnus/spam-report.el8
-rw-r--r--lisp/gnus/spam-stat.el2
-rw-r--r--lisp/gnus/spam-wash.el2
-rw-r--r--lisp/gnus/spam.el5
-rw-r--r--lisp/help-at-pt.el2
-rw-r--r--lisp/help-fns.el13
-rw-r--r--lisp/help-macro.el2
-rw-r--r--lisp/help-mode.el2
-rw-r--r--lisp/help.el90
-rw-r--r--lisp/hex-util.el2
-rw-r--r--lisp/hexl.el2
-rw-r--r--lisp/hfy-cmap.el2
-rw-r--r--lisp/hi-lock.el2
-rw-r--r--lisp/hilit-chg.el2
-rw-r--r--lisp/hippie-exp.el2
-rw-r--r--lisp/hl-line.el2
-rw-r--r--lisp/htmlfontify.el2
-rw-r--r--lisp/ibuf-ext.el33
-rw-r--r--lisp/ibuf-macs.el11
-rw-r--r--lisp/ibuffer.el19
-rw-r--r--lisp/icomplete.el10
-rw-r--r--lisp/ido.el11
-rw-r--r--lisp/ielm.el5
-rw-r--r--lisp/iimage.el2
-rw-r--r--lisp/image-file.el2
-rw-r--r--lisp/image-mode.el26
-rw-r--r--lisp/image.el4
-rw-r--r--lisp/image/compface.el2
-rw-r--r--lisp/image/exif.el2
-rw-r--r--lisp/image/gravatar.el2
-rw-r--r--lisp/image/image-converter.el2
-rw-r--r--lisp/image/image-crop.el2
-rw-r--r--lisp/image/image-dired-dired.el3
-rw-r--r--lisp/image/image-dired-external.el3
-rw-r--r--lisp/image/image-dired-tags.el3
-rw-r--r--lisp/image/image-dired-util.el3
-rw-r--r--lisp/image/image-dired.el38
-rw-r--r--lisp/image/wallpaper.el2
-rw-r--r--lisp/imenu.el2
-rw-r--r--lisp/indent-aux.el2
-rw-r--r--lisp/indent.el28
-rw-r--r--lisp/info-look.el37
-rw-r--r--lisp/info-xref.el2
-rw-r--r--lisp/info.el31
-rw-r--r--lisp/informat.el2
-rw-r--r--lisp/international/ccl.el2
-rw-r--r--lisp/international/characters.el16
-rw-r--r--lisp/international/emoji.el53
-rw-r--r--lisp/international/fontset.el2
-rw-r--r--lisp/international/isearch-x.el2
-rw-r--r--lisp/international/iso-ascii.el2
-rw-r--r--lisp/international/iso-cvt.el2
-rw-r--r--lisp/international/iso-transl.el4
-rw-r--r--lisp/international/ja-dic-cnv.el4
-rw-r--r--lisp/international/kinsoku.el2
-rw-r--r--lisp/international/kkc.el2
-rw-r--r--lisp/international/latexenc.el2
-rw-r--r--lisp/international/latin1-disp.el2
-rw-r--r--lisp/international/mule-cmds.el31
-rw-r--r--lisp/international/mule-conf.el2
-rw-r--r--lisp/international/mule-diag.el2
-rw-r--r--lisp/international/mule-util.el2
-rw-r--r--lisp/international/mule.el2
-rw-r--r--lisp/international/ogonek.el2
-rw-r--r--lisp/international/quail.el2
-rw-r--r--lisp/international/rfc1843.el2
-rw-r--r--lisp/international/textsec-check.el2
-rw-r--r--lisp/international/textsec.el2
-rw-r--r--lisp/international/titdic-cnv.el2
-rw-r--r--lisp/international/ucs-normalize.el16
-rw-r--r--lisp/international/utf-7.el2
-rw-r--r--lisp/international/utf7.el2
-rw-r--r--lisp/isearch.el20
-rw-r--r--lisp/isearchb.el2
-rw-r--r--lisp/jit-lock.el6
-rw-r--r--lisp/jka-cmpr-hook.el2
-rw-r--r--lisp/jka-compr.el2
-rw-r--r--lisp/json.el2
-rw-r--r--lisp/jsonrpc.el845
-rw-r--r--lisp/kermit.el2
-rw-r--r--lisp/keymap.el14
-rw-r--r--lisp/kmacro.el2
-rw-r--r--lisp/language/china-util.el2
-rw-r--r--lisp/language/chinese.el2
-rw-r--r--lisp/language/cyril-util.el2
-rw-r--r--lisp/language/cyrillic.el2
-rw-r--r--lisp/language/czech.el2
-rw-r--r--lisp/language/english.el2
-rw-r--r--lisp/language/ethio-util.el2
-rw-r--r--lisp/language/ethiopic.el2
-rw-r--r--lisp/language/european.el2
-rw-r--r--lisp/language/georgian.el2
-rw-r--r--lisp/language/greek.el2
-rw-r--r--lisp/language/hanja-util.el22
-rw-r--r--lisp/language/hebrew.el2
-rw-r--r--lisp/language/ind-util.el2
-rw-r--r--lisp/language/indian.el2
-rw-r--r--lisp/language/indonesian.el2
-rw-r--r--lisp/language/japan-util.el2
-rw-r--r--lisp/language/japanese.el2
-rw-r--r--lisp/language/korea-util.el2
-rw-r--r--lisp/language/korean.el2
-rw-r--r--lisp/language/lao-util.el2
-rw-r--r--lisp/language/lao.el2
-rw-r--r--lisp/language/misc-lang.el2
-rw-r--r--lisp/language/philippine.el2
-rw-r--r--lisp/language/romanian.el2
-rw-r--r--lisp/language/sinhala.el6
-rw-r--r--lisp/language/slovak.el2
-rw-r--r--lisp/language/tai-viet.el2
-rw-r--r--lisp/language/thai-util.el2
-rw-r--r--lisp/language/thai.el2
-rw-r--r--lisp/language/tibet-util.el2
-rw-r--r--lisp/language/tibetan.el2
-rw-r--r--lisp/language/utf-8-lang.el2
-rw-r--r--lisp/language/viet-util.el2
-rw-r--r--lisp/language/vietnamese.el2
-rw-r--r--lisp/ldefs-boot.el903
-rw-r--r--lisp/leim/quail/arabic.el2
-rw-r--r--lisp/leim/quail/cham.el2
-rw-r--r--lisp/leim/quail/compose.el2
-rw-r--r--lisp/leim/quail/croatian.el2
-rw-r--r--lisp/leim/quail/cyril-jis.el2
-rw-r--r--lisp/leim/quail/cyrillic.el6
-rw-r--r--lisp/leim/quail/czech.el2
-rw-r--r--lisp/leim/quail/emoji.el2
-rw-r--r--lisp/leim/quail/georgian.el2
-rw-r--r--lisp/leim/quail/greek.el2
-rw-r--r--lisp/leim/quail/hangul.el45
-rw-r--r--lisp/leim/quail/hanja.el2
-rw-r--r--lisp/leim/quail/hanja3.el2
-rw-r--r--lisp/leim/quail/indian.el6
-rw-r--r--lisp/leim/quail/indonesian.el2
-rw-r--r--lisp/leim/quail/ipa-praat.el2
-rw-r--r--lisp/leim/quail/ipa.el2
-rw-r--r--lisp/leim/quail/japanese.el2
-rw-r--r--lisp/leim/quail/latin-alt.el2
-rw-r--r--lisp/leim/quail/latin-ltx.el2
-rw-r--r--lisp/leim/quail/latin-post.el2
-rw-r--r--lisp/leim/quail/latin-pre.el8
-rw-r--r--lisp/leim/quail/lrt.el2
-rw-r--r--lisp/leim/quail/misc-lang.el2
-rw-r--r--lisp/leim/quail/pakistan.el726
-rw-r--r--lisp/leim/quail/persian.el2
-rw-r--r--lisp/leim/quail/philippine.el2
-rw-r--r--lisp/leim/quail/programmer-dvorak.el2
-rw-r--r--lisp/leim/quail/py-punct.el2
-rw-r--r--lisp/leim/quail/rfc1345.el2
-rw-r--r--lisp/leim/quail/sami.el2
-rw-r--r--lisp/leim/quail/sgml-input.el2
-rw-r--r--lisp/leim/quail/sisheng.el2
-rw-r--r--lisp/leim/quail/slovak.el2
-rw-r--r--lisp/leim/quail/symbol-ksc.el2
-rw-r--r--lisp/leim/quail/tamil-dvorak.el2
-rw-r--r--lisp/leim/quail/tibetan.el2
-rw-r--r--lisp/leim/quail/uni-input.el2
-rw-r--r--lisp/leim/quail/vntelex.el2
-rw-r--r--lisp/leim/quail/vnvni.el2
-rw-r--r--lisp/leim/quail/welsh.el2
-rw-r--r--lisp/loadhist.el15
-rw-r--r--lisp/loadup.el72
-rw-r--r--lisp/locate.el54
-rw-r--r--lisp/lpr.el2
-rw-r--r--lisp/ls-lisp.el198
-rw-r--r--lisp/macros.el2
-rw-r--r--lisp/mail/binhex.el2
-rw-r--r--lisp/mail/blessmail.el2
-rw-r--r--lisp/mail/emacsbug.el8
-rw-r--r--lisp/mail/flow-fill.el2
-rw-r--r--lisp/mail/footnote.el2
-rw-r--r--lisp/mail/hashcash.el2
-rw-r--r--lisp/mail/ietf-drums-date.el3
-rw-r--r--lisp/mail/ietf-drums.el2
-rw-r--r--lisp/mail/mail-extr.el2
-rw-r--r--lisp/mail/mail-hist.el2
-rw-r--r--lisp/mail/mail-parse.el2
-rw-r--r--lisp/mail/mail-prsvr.el2
-rw-r--r--lisp/mail/mail-utils.el2
-rw-r--r--lisp/mail/mailabbrev.el2
-rw-r--r--lisp/mail/mailalias.el2
-rw-r--r--lisp/mail/mailclient.el2
-rw-r--r--lisp/mail/mailheader.el2
-rw-r--r--lisp/mail/mspools.el2
-rw-r--r--lisp/mail/qp.el2
-rw-r--r--lisp/mail/reporter.el2
-rw-r--r--lisp/mail/rfc2045.el2
-rw-r--r--lisp/mail/rfc2047.el2
-rw-r--r--lisp/mail/rfc2231.el2
-rw-r--r--lisp/mail/rfc6068.el2
-rw-r--r--lisp/mail/rfc822.el2
-rw-r--r--lisp/mail/rmail-spam-filter.el2
-rw-r--r--lisp/mail/rmail.el41
-rw-r--r--lisp/mail/rmailedit.el2
-rw-r--r--lisp/mail/rmailkwd.el2
-rw-r--r--lisp/mail/rmailmm.el2
-rw-r--r--lisp/mail/rmailmsc.el2
-rw-r--r--lisp/mail/rmailout.el4
-rw-r--r--lisp/mail/rmailsort.el2
-rw-r--r--lisp/mail/rmailsum.el4
-rw-r--r--lisp/mail/sendmail.el13
-rw-r--r--lisp/mail/smtpmail.el6
-rw-r--r--lisp/mail/supercite.el2
-rw-r--r--lisp/mail/undigest.el2
-rw-r--r--lisp/mail/unrmail.el2
-rw-r--r--lisp/mail/uudecode.el2
-rw-r--r--lisp/mail/yenc.el2
-rw-r--r--lisp/man.el161
-rw-r--r--lisp/master.el2
-rw-r--r--lisp/mb-depth.el2
-rw-r--r--lisp/md4.el2
-rw-r--r--lisp/menu-bar.el24
-rw-r--r--lisp/mh-e/ChangeLog.14
-rw-r--r--lisp/mh-e/ChangeLog.24
-rw-r--r--lisp/mh-e/mh-acros.el75
-rw-r--r--lisp/mh-e/mh-alias.el2
-rw-r--r--lisp/mh-e/mh-buffers.el2
-rw-r--r--lisp/mh-e/mh-comp.el4
-rw-r--r--lisp/mh-e/mh-e.el2
-rw-r--r--lisp/mh-e/mh-folder.el2
-rw-r--r--lisp/mh-e/mh-funcs.el2
-rw-r--r--lisp/mh-e/mh-gnus.el2
-rw-r--r--lisp/mh-e/mh-identity.el2
-rw-r--r--lisp/mh-e/mh-inc.el2
-rw-r--r--lisp/mh-e/mh-junk.el2
-rw-r--r--lisp/mh-e/mh-letter.el2
-rw-r--r--lisp/mh-e/mh-limit.el2
-rw-r--r--lisp/mh-e/mh-mime.el3
-rw-r--r--lisp/mh-e/mh-print.el2
-rw-r--r--lisp/mh-e/mh-scan.el2
-rw-r--r--lisp/mh-e/mh-search.el2
-rw-r--r--lisp/mh-e/mh-seq.el2
-rw-r--r--lisp/mh-e/mh-show.el2
-rw-r--r--lisp/mh-e/mh-speed.el2
-rw-r--r--lisp/mh-e/mh-thread.el2
-rw-r--r--lisp/mh-e/mh-tool-bar.el2
-rw-r--r--lisp/mh-e/mh-utils.el2
-rw-r--r--lisp/mh-e/mh-xface.el2
-rw-r--r--lisp/midnight.el2
-rw-r--r--lisp/minibuf-eldef.el2
-rw-r--r--lisp/minibuffer.el824
-rw-r--r--lisp/misc.el2
-rw-r--r--lisp/misearch.el153
-rw-r--r--lisp/mouse-copy.el2
-rw-r--r--lisp/mouse-drag.el2
-rw-r--r--lisp/mouse.el13
-rw-r--r--lisp/mpc.el2
-rw-r--r--lisp/msb.el2
-rw-r--r--lisp/mwheel.el2
-rw-r--r--lisp/net/ange-ftp.el43
-rw-r--r--lisp/net/browse-url.el22
-rw-r--r--lisp/net/dbus.el25
-rw-r--r--lisp/net/dictionary-connection.el2
-rw-r--r--lisp/net/dictionary.el56
-rw-r--r--lisp/net/dig.el2
-rw-r--r--lisp/net/dns.el2
-rw-r--r--lisp/net/eudc-bob.el2
-rw-r--r--lisp/net/eudc-capf.el13
-rw-r--r--lisp/net/eudc-export.el2
-rw-r--r--lisp/net/eudc-hotlist.el2
-rw-r--r--lisp/net/eudc-vars.el2
-rw-r--r--lisp/net/eudc.el2
-rw-r--r--lisp/net/eudcb-bbdb.el2
-rw-r--r--lisp/net/eudcb-ecomplete.el15
-rw-r--r--lisp/net/eudcb-ldap.el2
-rw-r--r--lisp/net/eudcb-mab.el2
-rw-r--r--lisp/net/eudcb-macos-contacts.el5
-rw-r--r--lisp/net/eudcb-mailabbrev.el15
-rw-r--r--lisp/net/eww.el103
-rw-r--r--lisp/net/gnutls.el4
-rw-r--r--lisp/net/goto-addr.el2
-rw-r--r--lisp/net/hmac-def.el2
-rw-r--r--lisp/net/hmac-md5.el2
-rw-r--r--lisp/net/imap.el4
-rw-r--r--lisp/net/ldap.el2
-rw-r--r--lisp/net/mailcap.el4
-rw-r--r--lisp/net/mairix.el7
-rw-r--r--lisp/net/net-utils.el2
-rw-r--r--lisp/net/network-stream.el2
-rw-r--r--lisp/net/newst-backend.el15
-rw-r--r--lisp/net/newst-plainview.el42
-rw-r--r--lisp/net/newst-reader.el7
-rw-r--r--lisp/net/newst-ticker.el2
-rw-r--r--lisp/net/newst-treeview.el4
-rw-r--r--lisp/net/newsticker.el2
-rw-r--r--lisp/net/nsm.el34
-rw-r--r--lisp/net/ntlm.el5
-rw-r--r--lisp/net/pop3.el2
-rw-r--r--lisp/net/puny.el2
-rw-r--r--lisp/net/rcirc.el25
-rw-r--r--lisp/net/rfc2104.el2
-rw-r--r--lisp/net/sasl-cram.el2
-rw-r--r--lisp/net/sasl-digest.el2
-rw-r--r--lisp/net/sasl-ntlm.el2
-rw-r--r--lisp/net/sasl-scram-rfc.el2
-rw-r--r--lisp/net/sasl-scram-sha256.el2
-rw-r--r--lisp/net/sasl.el2
-rw-r--r--lisp/net/secrets.el2
-rw-r--r--lisp/net/shr-color.el2
-rw-r--r--lisp/net/shr.el174
-rw-r--r--lisp/net/sieve-manage.el8
-rw-r--r--lisp/net/sieve-mode.el30
-rw-r--r--lisp/net/sieve.el2
-rw-r--r--lisp/net/snmp-mode.el2
-rw-r--r--lisp/net/soap-client.el7
-rw-r--r--lisp/net/soap-inspect.el2
-rw-r--r--lisp/net/socks.el32
-rw-r--r--lisp/net/telnet.el2
-rw-r--r--lisp/net/tramp-adb.el21
-rw-r--r--lisp/net/tramp-archive.el2
-rw-r--r--lisp/net/tramp-cache.el27
-rw-r--r--lisp/net/tramp-cmds.el85
-rw-r--r--lisp/net/tramp-compat.el15
-rw-r--r--lisp/net/tramp-container.el242
-rw-r--r--lisp/net/tramp-crypt.el29
-rw-r--r--lisp/net/tramp-ftp.el2
-rw-r--r--lisp/net/tramp-fuse.el20
-rw-r--r--lisp/net/tramp-gvfs.el19
-rw-r--r--lisp/net/tramp-integration.el6
-rw-r--r--lisp/net/tramp-message.el61
-rw-r--r--lisp/net/tramp-rclone.el2
-rw-r--r--lisp/net/tramp-sh.el319
-rw-r--r--lisp/net/tramp-smb.el24
-rw-r--r--lisp/net/tramp-sshfs.el6
-rw-r--r--lisp/net/tramp-sudoedit.el27
-rw-r--r--lisp/net/tramp-uu.el2
-rw-r--r--lisp/net/tramp.el483
-rw-r--r--lisp/net/trampver.el4
-rw-r--r--lisp/net/webjump.el55
-rw-r--r--lisp/net/zeroconf.el2
-rw-r--r--lisp/newcomment.el2
-rw-r--r--lisp/notifications.el2
-rw-r--r--lisp/novice.el9
-rw-r--r--lisp/nxml/nxml-enc.el4
-rw-r--r--lisp/nxml/nxml-maint.el4
-rw-r--r--lisp/nxml/nxml-mode.el5
-rw-r--r--lisp/nxml/nxml-ns.el4
-rw-r--r--lisp/nxml/nxml-outln.el4
-rw-r--r--lisp/nxml/nxml-parse.el4
-rw-r--r--lisp/nxml/nxml-rap.el4
-rw-r--r--lisp/nxml/nxml-util.el4
-rw-r--r--lisp/nxml/rng-cmpct.el4
-rw-r--r--lisp/nxml/rng-dt.el4
-rw-r--r--lisp/nxml/rng-loc.el4
-rw-r--r--lisp/nxml/rng-maint.el4
-rw-r--r--lisp/nxml/rng-match.el4
-rw-r--r--lisp/nxml/rng-nxml.el4
-rw-r--r--lisp/nxml/rng-parse.el4
-rw-r--r--lisp/nxml/rng-pttrn.el4
-rw-r--r--lisp/nxml/rng-uri.el4
-rw-r--r--lisp/nxml/rng-util.el4
-rw-r--r--lisp/nxml/rng-valid.el4
-rw-r--r--lisp/nxml/rng-xsd.el4
-rw-r--r--lisp/nxml/xmltok.el4
-rw-r--r--lisp/nxml/xsd-regexp.el4
-rw-r--r--lisp/obarray.el2
-rw-r--r--lisp/obsolete/autoarg.el2
-rw-r--r--lisp/obsolete/autoload.el2
-rw-r--r--lisp/obsolete/bruce.el2
-rw-r--r--lisp/obsolete/cc-compat.el2
-rw-r--r--lisp/obsolete/cl-compat.el2
-rw-r--r--lisp/obsolete/cl.el2
-rw-r--r--lisp/obsolete/crisp.el2
-rw-r--r--lisp/obsolete/eieio-compat.el2
-rw-r--r--lisp/obsolete/eudcb-ph.el2
-rw-r--r--lisp/obsolete/gs.el2
-rw-r--r--lisp/obsolete/gulp.el2
-rw-r--r--lisp/obsolete/html2text.el2
-rw-r--r--lisp/obsolete/info-edit.el2
-rw-r--r--lisp/obsolete/inversion.el2
-rw-r--r--lisp/obsolete/iswitchb.el2
-rw-r--r--lisp/obsolete/landmark.el10
-rw-r--r--lisp/obsolete/linum.el2
-rw-r--r--lisp/obsolete/longlines.el4
-rw-r--r--lisp/obsolete/makesum.el2
-rw-r--r--lisp/obsolete/mantemp.el2
-rw-r--r--lisp/obsolete/messcompat.el2
-rw-r--r--lisp/obsolete/metamail.el2
-rw-r--r--lisp/obsolete/mh-compat.el2
-rw-r--r--lisp/obsolete/netrc.el2
-rw-r--r--lisp/obsolete/nnir.el2
-rw-r--r--lisp/obsolete/otodo-mode.el2
-rw-r--r--lisp/obsolete/pgg-def.el2
-rw-r--r--lisp/obsolete/pgg-gpg.el2
-rw-r--r--lisp/obsolete/pgg-parse.el2
-rw-r--r--lisp/obsolete/pgg-pgp.el2
-rw-r--r--lisp/obsolete/pgg-pgp5.el2
-rw-r--r--lisp/obsolete/pgg.el2
-rw-r--r--lisp/obsolete/ps-def.el4
-rw-r--r--lisp/obsolete/quickurl.el2
-rw-r--r--lisp/obsolete/rcompile.el2
-rw-r--r--lisp/obsolete/rfc2368.el2
-rw-r--r--lisp/obsolete/rlogin.el2
-rw-r--r--lisp/obsolete/sb-image.el2
-rw-r--r--lisp/obsolete/starttls.el2
-rw-r--r--lisp/obsolete/sup-mouse.el2
-rw-r--r--lisp/obsolete/terminal.el4
-rw-r--r--lisp/obsolete/thumbs.el2
-rw-r--r--lisp/obsolete/tls.el2
-rw-r--r--lisp/obsolete/tpu-edt.el2
-rw-r--r--lisp/obsolete/tpu-extras.el2
-rw-r--r--lisp/obsolete/tpu-mapper.el2
-rw-r--r--lisp/obsolete/uce.el2
-rw-r--r--lisp/obsolete/url-about.el2
-rw-r--r--lisp/obsolete/url-dired.el2
-rw-r--r--lisp/obsolete/url-ns.el7
-rw-r--r--lisp/obsolete/vc-arch.el2
-rw-r--r--lisp/obsolete/vc-mtn.el2
-rw-r--r--lisp/obsolete/vip.el2
-rw-r--r--lisp/obsolete/vt-control.el2
-rw-r--r--lisp/obsolete/vt100-led.el2
-rw-r--r--lisp/obsolete/ws-mode.el2
-rw-r--r--lisp/obsolete/yow.el2
-rw-r--r--lisp/org/ChangeLog.120
-rw-r--r--lisp/org/ob-C.el2
-rw-r--r--lisp/org/ob-R.el2
-rw-r--r--lisp/org/ob-awk.el2
-rw-r--r--lisp/org/ob-calc.el2
-rw-r--r--lisp/org/ob-clojure.el2
-rw-r--r--lisp/org/ob-comint.el2
-rw-r--r--lisp/org/ob-core.el12
-rw-r--r--lisp/org/ob-css.el2
-rw-r--r--lisp/org/ob-ditaa.el2
-rw-r--r--lisp/org/ob-dot.el2
-rw-r--r--lisp/org/ob-emacs-lisp.el2
-rw-r--r--lisp/org/ob-eshell.el11
-rw-r--r--lisp/org/ob-eval.el2
-rw-r--r--lisp/org/ob-exp.el2
-rw-r--r--lisp/org/ob-forth.el2
-rw-r--r--lisp/org/ob-fortran.el2
-rw-r--r--lisp/org/ob-gnuplot.el2
-rw-r--r--lisp/org/ob-groovy.el2
-rw-r--r--lisp/org/ob-haskell.el2
-rw-r--r--lisp/org/ob-java.el2
-rw-r--r--lisp/org/ob-js.el2
-rw-r--r--lisp/org/ob-julia.el2
-rw-r--r--lisp/org/ob-latex.el2
-rw-r--r--lisp/org/ob-lilypond.el2
-rw-r--r--lisp/org/ob-lisp.el2
-rw-r--r--lisp/org/ob-lob.el2
-rw-r--r--lisp/org/ob-lua.el4
-rw-r--r--lisp/org/ob-makefile.el2
-rw-r--r--lisp/org/ob-matlab.el2
-rw-r--r--lisp/org/ob-maxima.el2
-rw-r--r--lisp/org/ob-ocaml.el2
-rw-r--r--lisp/org/ob-octave.el2
-rw-r--r--lisp/org/ob-org.el2
-rw-r--r--lisp/org/ob-perl.el2
-rw-r--r--lisp/org/ob-plantuml.el4
-rw-r--r--lisp/org/ob-processing.el2
-rw-r--r--lisp/org/ob-python.el6
-rw-r--r--lisp/org/ob-ref.el2
-rw-r--r--lisp/org/ob-ruby.el2
-rw-r--r--lisp/org/ob-sass.el2
-rw-r--r--lisp/org/ob-scheme.el2
-rw-r--r--lisp/org/ob-screen.el2
-rw-r--r--lisp/org/ob-sed.el2
-rw-r--r--lisp/org/ob-shell.el14
-rw-r--r--lisp/org/ob-sql.el2
-rw-r--r--lisp/org/ob-sqlite.el2
-rw-r--r--lisp/org/ob-table.el2
-rw-r--r--lisp/org/ob-tangle.el2
-rw-r--r--lisp/org/ob.el2
-rw-r--r--lisp/org/oc-basic.el4
-rw-r--r--lisp/org/oc-biblatex.el4
-rw-r--r--lisp/org/oc-bibtex.el2
-rw-r--r--lisp/org/oc-csl.el2
-rw-r--r--lisp/org/oc-natbib.el2
-rw-r--r--lisp/org/oc.el4
-rw-r--r--lisp/org/ol-bbdb.el4
-rw-r--r--lisp/org/ol-bibtex.el4
-rw-r--r--lisp/org/ol-docview.el4
-rw-r--r--lisp/org/ol-doi.el2
-rw-r--r--lisp/org/ol-eshell.el2
-rw-r--r--lisp/org/ol-eww.el2
-rw-r--r--lisp/org/ol-gnus.el4
-rw-r--r--lisp/org/ol-info.el18
-rw-r--r--lisp/org/ol-irc.el2
-rw-r--r--lisp/org/ol-man.el4
-rw-r--r--lisp/org/ol-mhe.el4
-rw-r--r--lisp/org/ol-rmail.el4
-rw-r--r--lisp/org/ol-w3m.el4
-rw-r--r--lisp/org/ol.el8
-rw-r--r--lisp/org/org-agenda.el17
-rw-r--r--lisp/org/org-archive.el4
-rw-r--r--lisp/org/org-attach-git.el2
-rw-r--r--lisp/org/org-attach.el2
-rw-r--r--lisp/org/org-capture.el6
-rw-r--r--lisp/org/org-clock.el4
-rw-r--r--lisp/org/org-colview.el7
-rw-r--r--lisp/org/org-compat.el6
-rw-r--r--lisp/org/org-crypt.el2
-rw-r--r--lisp/org/org-ctags.el4
-rw-r--r--lisp/org/org-cycle.el2
-rw-r--r--lisp/org/org-datetree.el4
-rw-r--r--lisp/org/org-duration.el4
-rw-r--r--lisp/org/org-element.el36
-rw-r--r--lisp/org/org-entities.el25
-rw-r--r--lisp/org/org-faces.el4
-rw-r--r--lisp/org/org-feed.el4
-rw-r--r--lisp/org/org-fold-core.el2
-rw-r--r--lisp/org/org-fold.el2
-rw-r--r--lisp/org/org-footnote.el4
-rw-r--r--lisp/org/org-goto.el4
-rw-r--r--lisp/org/org-habit.el4
-rw-r--r--lisp/org/org-id.el4
-rw-r--r--lisp/org/org-indent.el4
-rw-r--r--lisp/org/org-inlinetask.el4
-rw-r--r--lisp/org/org-keys.el2
-rw-r--r--lisp/org/org-lint.el4
-rw-r--r--lisp/org/org-list.el4
-rw-r--r--lisp/org/org-macro.el4
-rw-r--r--lisp/org/org-macs.el32
-rw-r--r--lisp/org/org-mobile.el4
-rw-r--r--lisp/org/org-mouse.el6
-rw-r--r--lisp/org/org-num.el4
-rw-r--r--lisp/org/org-pcomplete.el4
-rw-r--r--lisp/org/org-persist.el21
-rw-r--r--lisp/org/org-plot.el2
-rw-r--r--lisp/org/org-protocol.el25
-rw-r--r--lisp/org/org-refile.el4
-rw-r--r--lisp/org/org-src.el11
-rw-r--r--lisp/org/org-table.el10
-rw-r--r--lisp/org/org-tempo.el4
-rw-r--r--lisp/org/org-timer.el4
-rw-r--r--lisp/org/org-version.el4
-rw-r--r--lisp/org/org.el72
-rw-r--r--lisp/org/ox-ascii.el4
-rw-r--r--lisp/org/ox-beamer.el15
-rw-r--r--lisp/org/ox-html.el5
-rw-r--r--lisp/org/ox-icalendar.el4
-rw-r--r--lisp/org/ox-koma-letter.el4
-rw-r--r--lisp/org/ox-latex.el4
-rw-r--r--lisp/org/ox-man.el4
-rw-r--r--lisp/org/ox-md.el6
-rw-r--r--lisp/org/ox-odt.el4
-rw-r--r--lisp/org/ox-org.el4
-rw-r--r--lisp/org/ox-publish.el4
-rw-r--r--lisp/org/ox-texinfo.el4
-rw-r--r--lisp/org/ox.el32
-rw-r--r--lisp/outline.el5
-rw-r--r--lisp/paren.el2
-rw-r--r--lisp/password-cache.el2
-rw-r--r--lisp/pcmpl-cvs.el2
-rw-r--r--lisp/pcmpl-git.el2
-rw-r--r--lisp/pcmpl-gnu.el2
-rw-r--r--lisp/pcmpl-linux.el2
-rw-r--r--lisp/pcmpl-rpm.el2
-rw-r--r--lisp/pcmpl-unix.el10
-rw-r--r--lisp/pcmpl-x.el2
-rw-r--r--lisp/pcomplete.el66
-rw-r--r--lisp/pgtk-dnd.el32
-rw-r--r--lisp/pixel-scroll.el20
-rw-r--r--lisp/play/5x5.el2
-rw-r--r--lisp/play/animate.el2
-rw-r--r--lisp/play/blackbox.el2
-rw-r--r--lisp/play/bubbles.el2
-rw-r--r--lisp/play/cookie1.el2
-rw-r--r--lisp/play/decipher.el2
-rw-r--r--lisp/play/dissociate.el2
-rw-r--r--lisp/play/doctor.el2
-rw-r--r--lisp/play/dunnet.el2
-rw-r--r--lisp/play/fortune.el2
-rw-r--r--lisp/play/gamegrid.el2
-rw-r--r--lisp/play/gametree.el2
-rw-r--r--lisp/play/gomoku.el2
-rw-r--r--lisp/play/handwrite.el4
-rw-r--r--lisp/play/life.el2
-rw-r--r--lisp/play/morse.el2
-rw-r--r--lisp/play/mpuz.el2
-rw-r--r--lisp/play/pong.el2
-rw-r--r--lisp/play/snake.el2
-rw-r--r--lisp/play/solitaire.el2
-rw-r--r--lisp/play/spook.el2
-rw-r--r--lisp/play/tetris.el2
-rw-r--r--lisp/play/zone.el4
-rw-r--r--lisp/plstore.el65
-rw-r--r--lisp/printing.el9
-rw-r--r--lisp/proced.el2
-rw-r--r--lisp/profiler.el2
-rw-r--r--lisp/progmodes/antlr-mode.el2
-rw-r--r--lisp/progmodes/asm-mode.el8
-rw-r--r--lisp/progmodes/autoconf.el2
-rw-r--r--lisp/progmodes/bat-mode.el2
-rw-r--r--lisp/progmodes/bug-reference.el45
-rw-r--r--lisp/progmodes/c-ts-common.el7
-rw-r--r--lisp/progmodes/c-ts-mode.el179
-rw-r--r--lisp/progmodes/cc-align.el2
-rw-r--r--lisp/progmodes/cc-awk.el18
-rw-r--r--lisp/progmodes/cc-bytecomp.el2
-rw-r--r--lisp/progmodes/cc-cmds.el5
-rw-r--r--lisp/progmodes/cc-defs.el167
-rw-r--r--lisp/progmodes/cc-engine.el282
-rw-r--r--lisp/progmodes/cc-fonts.el2
-rw-r--r--lisp/progmodes/cc-guess.el2
-rw-r--r--lisp/progmodes/cc-langs.el2
-rw-r--r--lisp/progmodes/cc-menus.el2
-rw-r--r--lisp/progmodes/cc-mode.el21
-rw-r--r--lisp/progmodes/cc-styles.el2
-rw-r--r--lisp/progmodes/cc-vars.el2
-rw-r--r--lisp/progmodes/cfengine.el2
-rw-r--r--lisp/progmodes/cl-font-lock.el4
-rw-r--r--lisp/progmodes/cmacexp.el2
-rw-r--r--lisp/progmodes/cmake-ts-mode.el16
-rw-r--r--lisp/progmodes/compile.el11
-rw-r--r--lisp/progmodes/cperl-mode.el479
-rw-r--r--lisp/progmodes/cpp.el2
-rw-r--r--lisp/progmodes/csharp-mode.el14
-rw-r--r--lisp/progmodes/cwarn.el2
-rw-r--r--lisp/progmodes/dcl-mode.el2
-rw-r--r--lisp/progmodes/dockerfile-ts-mode.el7
-rw-r--r--lisp/progmodes/ebnf-abn.el4
-rw-r--r--lisp/progmodes/ebnf-bnf.el4
-rw-r--r--lisp/progmodes/ebnf-dtd.el4
-rw-r--r--lisp/progmodes/ebnf-ebx.el4
-rw-r--r--lisp/progmodes/ebnf-iso.el4
-rw-r--r--lisp/progmodes/ebnf-otz.el4
-rw-r--r--lisp/progmodes/ebnf-yac.el4
-rw-r--r--lisp/progmodes/ebnf2ps.el6
-rw-r--r--lisp/progmodes/ebrowse.el2
-rw-r--r--lisp/progmodes/eglot.el957
-rw-r--r--lisp/progmodes/elisp-mode.el65
-rw-r--r--lisp/progmodes/elixir-ts-mode.el372
-rw-r--r--lisp/progmodes/erts-mode.el5
-rw-r--r--lisp/progmodes/etags.el22
-rw-r--r--lisp/progmodes/executable.el2
-rw-r--r--lisp/progmodes/f90.el3
-rw-r--r--lisp/progmodes/flymake-cc.el2
-rw-r--r--lisp/progmodes/flymake-proc.el7
-rw-r--r--lisp/progmodes/flymake.el255
-rw-r--r--lisp/progmodes/fortran.el4
-rw-r--r--lisp/progmodes/gdb-mi.el162
-rw-r--r--lisp/progmodes/glasses.el2
-rw-r--r--lisp/progmodes/go-ts-mode.el2
-rw-r--r--lisp/progmodes/grep.el2
-rw-r--r--lisp/progmodes/gud.el453
-rw-r--r--lisp/progmodes/heex-ts-mode.el7
-rw-r--r--lisp/progmodes/hideif.el4
-rw-r--r--lisp/progmodes/hideshow.el3
-rw-r--r--lisp/progmodes/icon.el2
-rw-r--r--lisp/progmodes/idlw-complete-structtag.el2
-rw-r--r--lisp/progmodes/idlw-help.el3
-rw-r--r--lisp/progmodes/idlw-shell.el6
-rw-r--r--lisp/progmodes/idlw-toolbar.el2
-rw-r--r--lisp/progmodes/idlwave.el14
-rw-r--r--lisp/progmodes/inf-lisp.el2
-rw-r--r--lisp/progmodes/java-ts-mode.el68
-rw-r--r--lisp/progmodes/js.el113
-rw-r--r--lisp/progmodes/json-ts-mode.el6
-rw-r--r--lisp/progmodes/ld-script.el2
-rw-r--r--lisp/progmodes/lua-ts-mode.el765
-rw-r--r--lisp/progmodes/m4-mode.el2
-rw-r--r--lisp/progmodes/make-mode.el126
-rw-r--r--lisp/progmodes/meta-mode.el2
-rw-r--r--lisp/progmodes/mixal-mode.el2
-rw-r--r--lisp/progmodes/octave.el6
-rw-r--r--lisp/progmodes/opascal.el2
-rw-r--r--lisp/progmodes/pascal.el2
-rw-r--r--lisp/progmodes/perl-mode.el42
-rw-r--r--lisp/progmodes/prog-mode.el13
-rw-r--r--lisp/progmodes/project.el480
-rw-r--r--lisp/progmodes/prolog.el2
-rw-r--r--lisp/progmodes/ps-mode.el8
-rw-r--r--lisp/progmodes/python.el271
-rw-r--r--lisp/progmodes/ruby-mode.el30
-rw-r--r--lisp/progmodes/ruby-ts-mode.el117
-rw-r--r--lisp/progmodes/rust-ts-mode.el44
-rw-r--r--lisp/progmodes/scheme.el2
-rw-r--r--lisp/progmodes/sh-script.el28
-rw-r--r--lisp/progmodes/simula.el2
-rw-r--r--lisp/progmodes/sql.el17
-rw-r--r--lisp/progmodes/subword.el2
-rw-r--r--lisp/progmodes/tcl.el6
-rw-r--r--lisp/progmodes/typescript-ts-mode.el107
-rw-r--r--lisp/progmodes/vera-mode.el4
-rw-r--r--lisp/progmodes/verilog-mode.el7
-rw-r--r--lisp/progmodes/vhdl-mode.el21
-rw-r--r--lisp/progmodes/which-func.el41
-rw-r--r--lisp/progmodes/xref.el66
-rw-r--r--lisp/progmodes/xscheme.el2
-rw-r--r--lisp/ps-bdf.el4
-rw-r--r--lisp/ps-mule.el4
-rw-r--r--lisp/ps-print.el20
-rw-r--r--lisp/ps-samp.el4
-rw-r--r--lisp/recentf.el20
-rw-r--r--lisp/rect.el13
-rw-r--r--lisp/register.el443
-rw-r--r--lisp/registry.el2
-rw-r--r--lisp/repeat.el2
-rw-r--r--lisp/replace.el13
-rw-r--r--lisp/reposition.el2
-rw-r--r--lisp/reveal.el2
-rw-r--r--lisp/rfn-eshadow.el2
-rw-r--r--lisp/rot13.el2
-rw-r--r--lisp/rtree.el2
-rw-r--r--lisp/ruler-mode.el2
-rw-r--r--lisp/savehist.el2
-rw-r--r--lisp/saveplace.el17
-rw-r--r--lisp/scroll-all.el2
-rw-r--r--lisp/scroll-bar.el2
-rw-r--r--lisp/scroll-lock.el2
-rw-r--r--lisp/select.el41
-rw-r--r--lisp/server.el38
-rw-r--r--lisp/ses.el92
-rw-r--r--lisp/shadowfile.el2
-rw-r--r--lisp/shell.el24
-rw-r--r--lisp/simple.el247
-rw-r--r--lisp/skeleton.el2
-rw-r--r--lisp/so-long.el32
-rw-r--r--lisp/sort.el15
-rw-r--r--lisp/soundex.el2
-rw-r--r--lisp/speedbar.el9
-rw-r--r--lisp/sqlite-mode.el21
-rw-r--r--lisp/sqlite.el27
-rw-r--r--lisp/startup.el38
-rw-r--r--lisp/strokes.el34
-rw-r--r--lisp/subr.el331
-rw-r--r--lisp/svg.el5
-rw-r--r--lisp/t-mouse.el2
-rw-r--r--lisp/tab-bar.el118
-rw-r--r--lisp/tab-line.el180
-rw-r--r--lisp/tabify.el2
-rw-r--r--lisp/talk.el2
-rw-r--r--lisp/tar-mode.el2
-rw-r--r--lisp/tempo.el187
-rw-r--r--lisp/term.el24
-rw-r--r--lisp/term/AT386.el2
-rw-r--r--lisp/term/README2
-rw-r--r--lisp/term/android-win.el283
-rw-r--r--lisp/term/bobcat.el4
-rw-r--r--lisp/term/common-win.el2
-rw-r--r--lisp/term/fbterm.el2
-rw-r--r--lisp/term/haiku-win.el13
-rw-r--r--lisp/term/internal.el2
-rw-r--r--lisp/term/iris-ansi.el2
-rw-r--r--lisp/term/konsole.el2
-rw-r--r--lisp/term/linux.el6
-rw-r--r--lisp/term/news.el2
-rw-r--r--lisp/term/ns-win.el13
-rw-r--r--lisp/term/pc-win.el2
-rw-r--r--lisp/term/pgtk-win.el42
-rw-r--r--lisp/term/rxvt.el2
-rw-r--r--lisp/term/screen.el2
-rw-r--r--lisp/term/st.el2
-rw-r--r--lisp/term/sun.el2
-rw-r--r--lisp/term/tmux.el2
-rw-r--r--lisp/term/tty-colors.el2
-rw-r--r--lisp/term/tvi970.el2
-rw-r--r--lisp/term/vt100.el2
-rw-r--r--lisp/term/w32-win.el16
-rw-r--r--lisp/term/w32console.el2
-rw-r--r--lisp/term/wyse50.el2
-rw-r--r--lisp/term/x-win.el2
-rw-r--r--lisp/term/xterm.el4
-rw-r--r--lisp/textmodes/artist.el2
-rw-r--r--lisp/textmodes/bib-mode.el2
-rw-r--r--lisp/textmodes/bibtex-style.el2
-rw-r--r--lisp/textmodes/bibtex.el18
-rw-r--r--lisp/textmodes/conf-mode.el2
-rw-r--r--lisp/textmodes/css-mode.el2
-rw-r--r--lisp/textmodes/dns-mode.el4
-rw-r--r--lisp/textmodes/emacs-authors-mode.el2
-rw-r--r--lisp/textmodes/emacs-news-mode.el2
-rw-r--r--lisp/textmodes/enriched.el6
-rw-r--r--lisp/textmodes/fill.el6
-rw-r--r--lisp/textmodes/flyspell.el49
-rw-r--r--lisp/textmodes/glyphless-mode.el3
-rw-r--r--lisp/textmodes/html-ts-mode.el21
-rw-r--r--lisp/textmodes/ispell.el45
-rw-r--r--lisp/textmodes/less-css-mode.el2
-rw-r--r--lisp/textmodes/makeinfo.el2
-rw-r--r--lisp/textmodes/mhtml-mode.el4
-rw-r--r--lisp/textmodes/nroff-mode.el4
-rw-r--r--lisp/textmodes/page-ext.el4
-rw-r--r--lisp/textmodes/page.el4
-rw-r--r--lisp/textmodes/paragraphs.el4
-rw-r--r--lisp/textmodes/picture.el4
-rw-r--r--lisp/textmodes/pixel-fill.el2
-rw-r--r--lisp/textmodes/po.el2
-rw-r--r--lisp/textmodes/refbib.el2
-rw-r--r--lisp/textmodes/refer.el2
-rw-r--r--lisp/textmodes/refill.el4
-rw-r--r--lisp/textmodes/reftex-auc.el2
-rw-r--r--lisp/textmodes/reftex-cite.el6
-rw-r--r--lisp/textmodes/reftex-dcr.el2
-rw-r--r--lisp/textmodes/reftex-global.el2
-rw-r--r--lisp/textmodes/reftex-index.el6
-rw-r--r--lisp/textmodes/reftex-parse.el2
-rw-r--r--lisp/textmodes/reftex-ref.el3
-rw-r--r--lisp/textmodes/reftex-sel.el4
-rw-r--r--lisp/textmodes/reftex-toc.el4
-rw-r--r--lisp/textmodes/reftex-vars.el5
-rw-r--r--lisp/textmodes/reftex.el33
-rw-r--r--lisp/textmodes/remember.el9
-rw-r--r--lisp/textmodes/rst.el5
-rw-r--r--lisp/textmodes/sgml-mode.el8
-rw-r--r--lisp/textmodes/string-edit.el2
-rw-r--r--lisp/textmodes/table.el4
-rw-r--r--lisp/textmodes/tex-mode.el24
-rw-r--r--lisp/textmodes/texinfmt.el2
-rw-r--r--lisp/textmodes/texinfo.el2
-rw-r--r--lisp/textmodes/texnfo-upd.el2
-rw-r--r--lisp/textmodes/text-mode.el23
-rw-r--r--lisp/textmodes/tildify.el4
-rw-r--r--lisp/textmodes/toml-ts-mode.el2
-rw-r--r--lisp/textmodes/two-column.el4
-rw-r--r--lisp/textmodes/underline.el4
-rw-r--r--lisp/textmodes/word-wrap-mode.el2
-rw-r--r--lisp/textmodes/yaml-ts-mode.el2
-rw-r--r--lisp/thingatpt.el22
-rw-r--r--lisp/thread.el2
-rw-r--r--lisp/time-stamp.el2
-rw-r--r--lisp/time.el2
-rw-r--r--lisp/timezone.el2
-rw-r--r--lisp/tmm.el5
-rw-r--r--lisp/tool-bar.el2
-rw-r--r--lisp/tooltip.el2
-rw-r--r--lisp/touch-screen.el971
-rw-r--r--lisp/transient.el1722
-rw-r--r--lisp/tree-widget.el2
-rw-r--r--lisp/treesit.el907
-rw-r--r--lisp/tutorial.el2
-rw-r--r--lisp/type-break.el8
-rw-r--r--lisp/uniquify.el6
-rw-r--r--lisp/url/ChangeLog.12
-rw-r--r--lisp/url/url-auth.el2
-rw-r--r--lisp/url/url-cache.el2
-rw-r--r--lisp/url/url-cid.el2
-rw-r--r--lisp/url/url-cookie.el2
-rw-r--r--lisp/url/url-dav.el2
-rw-r--r--lisp/url/url-domsuf.el2
-rw-r--r--lisp/url/url-expand.el2
-rw-r--r--lisp/url/url-file.el2
-rw-r--r--lisp/url/url-ftp.el2
-rw-r--r--lisp/url/url-future.el2
-rw-r--r--lisp/url/url-gw.el17
-rw-r--r--lisp/url/url-handlers.el2
-rw-r--r--lisp/url/url-history.el2
-rw-r--r--lisp/url/url-http.el6
-rw-r--r--lisp/url/url-imap.el2
-rw-r--r--lisp/url/url-irc.el16
-rw-r--r--lisp/url/url-ldap.el2
-rw-r--r--lisp/url/url-mailto.el2
-rw-r--r--lisp/url/url-methods.el2
-rw-r--r--lisp/url/url-misc.el2
-rw-r--r--lisp/url/url-news.el2
-rw-r--r--lisp/url/url-nfs.el2
-rw-r--r--lisp/url/url-parse.el2
-rw-r--r--lisp/url/url-privacy.el12
-rw-r--r--lisp/url/url-proxy.el2
-rw-r--r--lisp/url/url-queue.el2
-rw-r--r--lisp/url/url-tramp.el2
-rw-r--r--lisp/url/url-util.el2
-rw-r--r--lisp/url/url-vars.el15
-rw-r--r--lisp/url/url.el2
-rw-r--r--lisp/use-package/use-package-bind-key.el2
-rw-r--r--lisp/use-package/use-package-core.el6
-rw-r--r--lisp/use-package/use-package-delight.el2
-rw-r--r--lisp/use-package/use-package-diminish.el2
-rw-r--r--lisp/use-package/use-package-ensure-system-package.el2
-rw-r--r--lisp/use-package/use-package-ensure.el2
-rw-r--r--lisp/use-package/use-package-jump.el2
-rw-r--r--lisp/use-package/use-package-lint.el2
-rw-r--r--lisp/use-package/use-package.el5
-rw-r--r--lisp/userlock.el5
-rw-r--r--lisp/vc/add-log.el2
-rw-r--r--lisp/vc/compare-w.el2
-rw-r--r--lisp/vc/cvs-status.el6
-rw-r--r--lisp/vc/diff-mode.el37
-rw-r--r--lisp/vc/diff.el4
-rw-r--r--lisp/vc/ediff-diff.el2
-rw-r--r--lisp/vc/ediff-help.el2
-rw-r--r--lisp/vc/ediff-hook.el2
-rw-r--r--lisp/vc/ediff-init.el2
-rw-r--r--lisp/vc/ediff-merg.el2
-rw-r--r--lisp/vc/ediff-mult.el2
-rw-r--r--lisp/vc/ediff-ptch.el2
-rw-r--r--lisp/vc/ediff-util.el91
-rw-r--r--lisp/vc/ediff-vers.el2
-rw-r--r--lisp/vc/ediff-wind.el2
-rw-r--r--lisp/vc/ediff.el8
-rw-r--r--lisp/vc/emerge.el30
-rw-r--r--lisp/vc/log-edit.el71
-rw-r--r--lisp/vc/log-view.el20
-rw-r--r--lisp/vc/pcvs-defs.el2
-rw-r--r--lisp/vc/pcvs-info.el2
-rw-r--r--lisp/vc/pcvs-parse.el2
-rw-r--r--lisp/vc/pcvs-util.el2
-rw-r--r--lisp/vc/pcvs.el2
-rw-r--r--lisp/vc/smerge-mode.el12
-rw-r--r--lisp/vc/vc-annotate.el45
-rw-r--r--lisp/vc/vc-bzr.el2
-rw-r--r--lisp/vc/vc-cvs.el2
-rw-r--r--lisp/vc/vc-dav.el2
-rw-r--r--lisp/vc/vc-dir.el5
-rw-r--r--lisp/vc/vc-dispatcher.el2
-rw-r--r--lisp/vc/vc-filewise.el2
-rw-r--r--lisp/vc/vc-git.el102
-rw-r--r--lisp/vc/vc-hg.el93
-rw-r--r--lisp/vc/vc-hooks.el123
-rw-r--r--lisp/vc/vc-rcs.el9
-rw-r--r--lisp/vc/vc-sccs.el2
-rw-r--r--lisp/vc/vc-src.el2
-rw-r--r--lisp/vc/vc-svn.el2
-rw-r--r--lisp/vc/vc.el226
-rw-r--r--lisp/vcursor.el2
-rw-r--r--lisp/version.el2
-rw-r--r--lisp/view.el2
-rw-r--r--lisp/w32-fns.el2
-rw-r--r--lisp/w32-vars.el2
-rw-r--r--lisp/wdired.el11
-rw-r--r--lisp/whitespace.el8
-rw-r--r--lisp/wid-browse.el2
-rw-r--r--lisp/wid-edit.el33
-rw-r--r--lisp/widget.el2
-rw-r--r--lisp/windmove.el12
-rw-r--r--lisp/window.el133
-rw-r--r--lisp/winner.el2
-rw-r--r--lisp/woman.el18
-rw-r--r--lisp/x-dnd.el33
-rw-r--r--lisp/xdg.el2
-rw-r--r--lisp/xml.el2
-rw-r--r--lisp/xt-mouse.el12
-rw-r--r--lisp/xwidget.el2
-rw-r--r--lisp/yank-media.el2
-rw-r--r--lwlib/ChangeLog.12
-rw-r--r--lwlib/Makefile.in2
-rw-r--r--lwlib/deps.mk2
-rw-r--r--lwlib/lwlib-Xaw.c2
-rw-r--r--lwlib/lwlib-Xlw.c2
-rw-r--r--lwlib/lwlib-Xm.c2
-rw-r--r--lwlib/lwlib-int.h2
-rw-r--r--lwlib/lwlib-utils.c2
-rw-r--r--lwlib/lwlib-widget.h2
-rw-r--r--lwlib/lwlib.c2
-rw-r--r--lwlib/lwlib.h2
-rw-r--r--lwlib/xlwmenu.c2
-rw-r--r--lwlib/xlwmenu.h2
-rw-r--r--lwlib/xlwmenuP.h2
-rw-r--r--m4/00gnulib.m42
-rw-r--r--m4/__inline.m42
-rw-r--r--m4/absolute-header.m42
-rw-r--r--m4/acl.m42
-rw-r--r--m4/alloca.m44
-rw-r--r--m4/assert_h.m42
-rw-r--r--m4/builtin-expect.m42
-rw-r--r--m4/byteswap.m42
-rw-r--r--m4/c-bool.m42
-rw-r--r--m4/canonicalize.m42
-rw-r--r--m4/clock_time.m42
-rw-r--r--m4/codeset.m44
-rw-r--r--m4/copy-file-range.m42
-rw-r--r--m4/d-type.m43
-rw-r--r--m4/dirent_h.m42
-rw-r--r--m4/dirfd.m42
-rw-r--r--m4/double-slash-root.m42
-rw-r--r--m4/dup2.m43
-rw-r--r--m4/eealloc.m42
-rw-r--r--m4/environ.m42
-rw-r--r--m4/errno_h.m42
-rw-r--r--m4/euidaccess.m42
-rw-r--r--m4/execinfo.m42
-rw-r--r--m4/explicit_bzero.m42
-rw-r--r--m4/extensions.m42
-rw-r--r--m4/extern-inline.m42
-rw-r--r--m4/faccessat.m42
-rw-r--r--m4/fchmodat.m42
-rw-r--r--m4/fcntl.m42
-rw-r--r--m4/fcntl_h.m42
-rw-r--r--m4/fdopendir.m42
-rw-r--r--m4/filemode.m43
-rw-r--r--m4/flexmember.m42
-rw-r--r--m4/fpending.m42
-rw-r--r--m4/fpieee.m42
-rw-r--r--m4/free.m42
-rw-r--r--m4/fstatat.m42
-rw-r--r--m4/fsusage.m43
-rw-r--r--m4/fsync.m42
-rw-r--r--m4/futimens.m42
-rw-r--r--m4/getdelim.m42
-rw-r--r--m4/getdtablesize.m42
-rw-r--r--m4/getgroups.m43
-rw-r--r--m4/getline.m44
-rw-r--r--m4/getloadavg.m44
-rw-r--r--m4/getopt.m42
-rw-r--r--m4/getrandom.m42
-rw-r--r--m4/gettime.m43
-rw-r--r--m4/gettimeofday.m43
-rw-r--r--m4/gnulib-common.m42
-rw-r--r--m4/gnulib-comp.m42
-rw-r--r--m4/group-member.m43
-rw-r--r--m4/ieee754-h.m42
-rw-r--r--m4/include_next.m42
-rw-r--r--m4/inttypes.m42
-rw-r--r--m4/largefile.m42
-rw-r--r--m4/lchmod.m42
-rw-r--r--m4/libgmp.m42
-rw-r--r--m4/limits-h.m42
-rw-r--r--m4/lstat.m42
-rw-r--r--m4/malloc.m42
-rw-r--r--m4/manywarnings.m42
-rw-r--r--m4/mbstate_t.m42
-rw-r--r--m4/md5.m42
-rw-r--r--m4/memmem.m42
-rw-r--r--m4/mempcpy.m44
-rw-r--r--m4/memrchr.m44
-rw-r--r--m4/memset_explicit.m42
-rw-r--r--m4/minmax.m42
-rw-r--r--m4/mkostemp.m42
-rw-r--r--m4/mktime.m44
-rw-r--r--m4/mode_t.m42
-rw-r--r--m4/multiarch.m42
-rw-r--r--m4/musl.m42
-rw-r--r--m4/nanosleep.m42
-rw-r--r--m4/ndk-build.m42
-rw-r--r--m4/nocrash.m42
-rw-r--r--m4/nproc.m42
-rw-r--r--m4/nstrftime.m43
-rw-r--r--m4/off_t.m42
-rw-r--r--m4/open-cloexec.m42
-rw-r--r--m4/open-slash.m42
-rw-r--r--m4/open.m42
-rw-r--r--m4/pathmax.m44
-rw-r--r--m4/pid_t.m42
-rw-r--r--m4/pipe2.m42
-rw-r--r--m4/printf-posix-rpl.m42
-rw-r--r--m4/pselect.m42
-rw-r--r--m4/pthread_sigmask.m42
-rw-r--r--m4/rawmemchr.m42
-rw-r--r--m4/readlink.m42
-rw-r--r--m4/readlinkat.m42
-rw-r--r--m4/readutmp.m42
-rw-r--r--m4/realloc.m42
-rw-r--r--m4/regex.m42
-rw-r--r--m4/sha1.m42
-rw-r--r--m4/sha256.m42
-rw-r--r--m4/sha512.m42
-rw-r--r--m4/sig2str.m43
-rw-r--r--m4/sigdescr_np.m42
-rw-r--r--m4/signal_h.m42
-rw-r--r--m4/socklen.m42
-rw-r--r--m4/ssize_t.m43
-rw-r--r--m4/st_dm_mode.m42
-rw-r--r--m4/stat-time.m44
-rw-r--r--m4/std-gnu11.m42
-rw-r--r--m4/stdalign.m42
-rw-r--r--m4/stddef_h.m42
-rw-r--r--m4/stdint.m42
-rw-r--r--m4/stdio_h.m42
-rw-r--r--m4/stdlib_h.m42
-rw-r--r--m4/stpcpy.m42
-rw-r--r--m4/string_h.m42
-rw-r--r--m4/strnlen.m44
-rw-r--r--m4/strtoimax.m43
-rw-r--r--m4/strtoll.m43
-rw-r--r--m4/symlink.m42
-rw-r--r--m4/sys_random_h.m42
-rw-r--r--m4/sys_select_h.m42
-rw-r--r--m4/sys_socket_h.m42
-rw-r--r--m4/sys_stat_h.m42
-rw-r--r--m4/sys_time_h.m42
-rw-r--r--m4/sys_types_h.m42
-rw-r--r--m4/tempname.m42
-rw-r--r--m4/time_h.m43
-rw-r--r--m4/time_r.m42
-rw-r--r--m4/time_rz.m42
-rw-r--r--m4/timegm.m42
-rw-r--r--m4/timer_time.m42
-rw-r--r--m4/timespec.m43
-rw-r--r--m4/tm_gmtoff.m42
-rw-r--r--m4/unistd_h.m42
-rw-r--r--m4/unlocked-io.m42
-rw-r--r--m4/utimens.m42
-rw-r--r--m4/utimensat.m42
-rw-r--r--m4/utimes.m42
-rw-r--r--m4/vararrays.m42
-rw-r--r--m4/warnings.m42
-rw-r--r--m4/wchar_t.m42
-rw-r--r--m4/xattr.m42
-rw-r--r--m4/year2038.m42
-rw-r--r--m4/zzgnulib.m42
-rwxr-xr-xmake-dist7
-rwxr-xr-xmodules/modhelp.py2
-rw-r--r--msdos/ChangeLog.12
-rw-r--r--msdos/INSTALL2
-rw-r--r--msdos/README4
-rw-r--r--msdos/autogen/Makefile.in2
-rw-r--r--msdos/autogen/config.in2
-rw-r--r--msdos/depfiles.bat2
-rw-r--r--msdos/inttypes.h2
-rw-r--r--msdos/langinfo.h2
-rw-r--r--msdos/mainmake.v22
-rw-r--r--msdos/sed1v2.inp2
-rw-r--r--msdos/sed1x.inp2
-rw-r--r--msdos/sed2v2.inp4
-rw-r--r--msdos/sed2x.inp2
-rw-r--r--msdos/sed3v2.inp2
-rw-r--r--msdos/sed4.inp2
-rw-r--r--msdos/sed5x.inp2
-rw-r--r--msdos/sed6.inp2
-rw-r--r--msdos/sedadmin.inp2
-rw-r--r--msdos/sedalloc.inp2
-rw-r--r--msdos/sedleim.inp2
-rw-r--r--msdos/sedlibcf.inp2
-rw-r--r--msdos/sedlibmk.inp2
-rw-r--r--msdos/sedlisp.inp2
-rw-r--r--nextstep/ChangeLog.14
-rw-r--r--nextstep/INSTALL2
-rw-r--r--nextstep/Makefile.in14
-rw-r--r--nextstep/README2
-rw-r--r--nextstep/templates/Info.plist.in2
-rw-r--r--nt/ChangeLog.12
-rw-r--r--nt/INSTALL2
-rw-r--r--nt/INSTALL.W642
-rw-r--r--nt/Makefile.in2
-rw-r--r--nt/README2
-rw-r--r--nt/README.W322
-rw-r--r--nt/addpm.c2
-rw-r--r--nt/cmdproxy.c2
-rwxr-xr-xnt/configure.bat26
-rw-r--r--nt/ddeclient.c2
-rw-r--r--nt/epaths.nt2
-rw-r--r--nt/gnulib-cfg.mk2
-rw-r--r--nt/icons/README6
-rw-r--r--nt/inc/grp.h2
-rw-r--r--nt/inc/inttypes.h2
-rw-r--r--nt/inc/langinfo.h2
-rw-r--r--nt/inc/ms-w32.h4
-rw-r--r--nt/inc/nl_types.h2
-rw-r--r--nt/inc/stdint.h2
-rw-r--r--nt/inc/sys/resource.h2
-rw-r--r--nt/inc/sys/socket.h2
-rw-r--r--nt/inc/sys/stat.h2
-rw-r--r--nt/inc/sys/wait.h2
-rw-r--r--nt/preprep.c830
-rw-r--r--nt/runemacs.c2
-rw-r--r--oldXMenu/Activate.c2
-rw-r--r--oldXMenu/ChangeLog.16
-rw-r--r--oldXMenu/Create.c2
-rw-r--r--oldXMenu/FindSel.c2
-rw-r--r--oldXMenu/Internal.c2
-rw-r--r--oldXMenu/Makefile.in2
-rw-r--r--oldXMenu/deps.mk2
-rw-r--r--oldXMenu/insque.c2
-rw-r--r--src/.gdbinit2
-rw-r--r--src/.lldbinit5
-rw-r--r--src/ChangeLog.12
-rw-r--r--src/ChangeLog.102
-rw-r--r--src/ChangeLog.1122
-rw-r--r--src/ChangeLog.122
-rw-r--r--src/ChangeLog.138
-rw-r--r--src/ChangeLog.22
-rw-r--r--src/ChangeLog.32
-rw-r--r--src/ChangeLog.44
-rw-r--r--src/ChangeLog.52
-rw-r--r--src/ChangeLog.62
-rw-r--r--src/ChangeLog.72
-rw-r--r--src/ChangeLog.84
-rw-r--r--src/ChangeLog.94
-rw-r--r--src/Makefile.in4
-rw-r--r--src/README2
-rw-r--r--src/alloc.c400
-rw-r--r--src/android-asset.h14
-rw-r--r--src/android-emacs.c2
-rw-r--r--src/android.c831
-rw-r--r--src/android.h16
-rw-r--r--src/androidfns.c333
-rw-r--r--src/androidfont.c8
-rw-r--r--src/androidgui.h54
-rw-r--r--src/androidmenu.c129
-rw-r--r--src/androidselect.c38
-rw-r--r--src/androidterm.c184
-rw-r--r--src/androidterm.h4
-rw-r--r--src/androidvfs.c198
-rw-r--r--src/atimer.c2
-rw-r--r--src/atimer.h2
-rw-r--r--src/bidi.c2
-rw-r--r--src/bignum.c2
-rw-r--r--src/bignum.h2
-rw-r--r--src/blockinput.h2
-rw-r--r--src/buffer.c54
-rw-r--r--src/buffer.h9
-rw-r--r--src/bytecode.c2
-rw-r--r--src/callint.c2
-rw-r--r--src/callproc.c33
-rw-r--r--src/casefiddle.c27
-rw-r--r--src/casetab.c2
-rw-r--r--src/category.c2
-rw-r--r--src/ccl.c2
-rw-r--r--src/character.c2
-rw-r--r--src/charset.c2
-rw-r--r--src/charset.h2
-rw-r--r--src/chartab.c3
-rw-r--r--src/cm.c2
-rw-r--r--src/cm.h2
-rw-r--r--src/cmds.c2
-rw-r--r--src/coding.c6
-rw-r--r--src/coding.h2
-rw-r--r--src/commands.h2
-rw-r--r--src/comp.c2
-rw-r--r--src/comp.h2
-rw-r--r--src/composite.c4
-rw-r--r--src/composite.h2
-rw-r--r--src/conf_post.h4
-rw-r--r--src/cygw32.c2
-rw-r--r--src/cygw32.h2
-rw-r--r--src/data.c8
-rw-r--r--src/dbusbind.c2
-rw-r--r--src/decompress.c2
-rw-r--r--src/deps.mk2
-rw-r--r--src/dired.c2
-rw-r--r--src/dispextern.h3
-rw-r--r--src/dispnew.c8
-rw-r--r--src/disptab.h2
-rw-r--r--src/dmpstruct.awk2
-rw-r--r--src/doc.c2
-rw-r--r--src/doprnt.c2
-rw-r--r--src/dosfns.c2
-rw-r--r--src/dosfns.h2
-rw-r--r--src/dynlib.c2
-rw-r--r--src/dynlib.h2
-rw-r--r--src/editfns.c11
-rw-r--r--src/emacs-icon.h2
-rw-r--r--src/emacs-module.c2
-rw-r--r--src/emacs-module.h.in2
-rw-r--r--src/emacs.c28
-rw-r--r--src/emacsgtkfixed.c2
-rw-r--r--src/emacsgtkfixed.h2
-rw-r--r--src/epaths.in2
-rw-r--r--src/eval.c107
-rw-r--r--src/fileio.c12
-rw-r--r--src/filelock.c4
-rw-r--r--src/firstfile.c2
-rw-r--r--src/floatfns.c2
-rw-r--r--src/fns.c82
-rw-r--r--src/font.c259
-rw-r--r--src/font.h20
-rw-r--r--src/fontset.c33
-rw-r--r--src/fontset.h2
-rw-r--r--src/frame.c21
-rw-r--r--src/frame.h7
-rw-r--r--src/fringe.c2
-rw-r--r--src/ftcrfont.c2
-rw-r--r--src/ftfont.c8
-rw-r--r--src/getpagesize.h2
-rw-r--r--src/gfilenotify.c10
-rw-r--r--src/gmalloc.c2
-rw-r--r--src/gnutls.c2
-rw-r--r--src/gnutls.h2
-rw-r--r--src/gtkutil.c8
-rw-r--r--src/gtkutil.h2
-rw-r--r--src/haiku.c2
-rw-r--r--src/haiku_draw_support.cc2
-rw-r--r--src/haiku_font_support.cc2
-rw-r--r--src/haiku_io.c2
-rw-r--r--src/haiku_select.cc2
-rw-r--r--src/haiku_support.cc48
-rw-r--r--src/haiku_support.h2
-rw-r--r--src/haikufns.c7
-rw-r--r--src/haikufont.c5
-rw-r--r--src/haikugui.h2
-rw-r--r--src/haikuimage.c2
-rw-r--r--src/haikumenu.c2
-rw-r--r--src/haikuselect.c4
-rw-r--r--src/haikuselect.h2
-rw-r--r--src/haikuterm.c14
-rw-r--r--src/haikuterm.h2
-rw-r--r--src/hbfont.c2
-rw-r--r--src/image.c294
-rw-r--r--src/indent.c6
-rw-r--r--src/indent.h2
-rw-r--r--src/inotify.c9
-rw-r--r--src/insdel.c2
-rw-r--r--src/intervals.c2
-rw-r--r--src/intervals.h2
-rw-r--r--src/itree.c6
-rw-r--r--src/itree.h2
-rw-r--r--src/json.c2
-rw-r--r--src/keyboard.c115
-rw-r--r--src/keyboard.h2
-rw-r--r--src/keymap.c28
-rw-r--r--src/keymap.h2
-rw-r--r--src/kqueue.c12
-rw-r--r--src/lastfile.c2
-rw-r--r--src/lcms.c2
-rw-r--r--src/lisp.h164
-rw-r--r--src/lread.c2
-rw-r--r--src/macfont.h2
-rw-r--r--src/macfont.m2
-rw-r--r--src/macros.c2
-rw-r--r--src/macros.h2
-rw-r--r--src/marker.c2
-rw-r--r--src/menu.c2
-rw-r--r--src/menu.h2
-rw-r--r--src/minibuf.c3
-rw-r--r--src/module-env-30.h6
-rw-r--r--src/msdos.c4
-rw-r--r--src/msdos.h2
-rw-r--r--src/nsfns.m50
-rw-r--r--src/nsfont.m2
-rw-r--r--src/nsgui.h2
-rw-r--r--src/nsimage.m2
-rw-r--r--src/nsmenu.m14
-rw-r--r--src/nsselect.m2
-rw-r--r--src/nsterm.h16
-rw-r--r--src/nsterm.m157
-rw-r--r--src/nsxwidget.h2
-rw-r--r--src/nsxwidget.m2
-rw-r--r--src/pdumper.c99
-rw-r--r--src/pdumper.h2
-rw-r--r--src/pgtkfns.c7
-rw-r--r--src/pgtkgui.h2
-rw-r--r--src/pgtkim.c2
-rw-r--r--src/pgtkmenu.c2
-rw-r--r--src/pgtkselect.c2
-rw-r--r--src/pgtkterm.c8
-rw-r--r--src/pgtkterm.h2
-rw-r--r--src/print.c275
-rw-r--r--src/process.c46
-rw-r--r--src/process.h2
-rw-r--r--src/profiler.c73
-rw-r--r--src/puresize.h2
-rw-r--r--src/ralloc.c2
-rw-r--r--src/regex-emacs.c1302
-rw-r--r--src/regex-emacs.h6
-rw-r--r--src/region-cache.c2
-rw-r--r--src/region-cache.h2
-rw-r--r--src/scroll.c2
-rw-r--r--src/search.c80
-rw-r--r--src/sfnt.c2743
-rw-r--r--src/sfnt.h159
-rw-r--r--src/sfntfont-android.c39
-rw-r--r--src/sfntfont.c500
-rw-r--r--src/sfntfont.h2
-rw-r--r--src/sheap.c2
-rw-r--r--src/sheap.h2
-rw-r--r--src/sort.c2
-rw-r--r--src/sound.c2
-rw-r--r--src/sqlite.c4
-rw-r--r--src/syntax.c4
-rw-r--r--src/syntax.h2
-rw-r--r--src/sysdep.c13
-rw-r--r--src/sysselect.h2
-rw-r--r--src/syssignal.h2
-rw-r--r--src/sysstdio.h2
-rw-r--r--src/systhread.c2
-rw-r--r--src/systhread.h2
-rw-r--r--src/systime.h2
-rw-r--r--src/systty.h2
-rw-r--r--src/syswait.h2
-rw-r--r--src/term.c29
-rw-r--r--src/termcap.c2
-rw-r--r--src/termchar.h2
-rw-r--r--src/termhooks.h2
-rw-r--r--src/terminal.c4
-rw-r--r--src/terminfo.c2
-rw-r--r--src/termopts.h2
-rw-r--r--src/textconv.c176
-rw-r--r--src/textconv.h5
-rw-r--r--src/textprop.c2
-rw-r--r--src/thread.c2
-rw-r--r--src/thread.h2
-rw-r--r--src/timefns.c2
-rw-r--r--src/tparam.c4
-rw-r--r--src/tparam.h2
-rw-r--r--src/treesit.c269
-rw-r--r--src/treesit.h21
-rw-r--r--src/undo.c2
-rw-r--r--src/unexaix.c2
-rw-r--r--src/unexcoff.c2
-rw-r--r--src/unexcw.c2
-rw-r--r--src/unexelf.c2
-rw-r--r--src/unexmacosx.c2
-rw-r--r--src/unexw32.c2
-rw-r--r--src/verbose.mk.in2
-rw-r--r--src/vm-limit.c2
-rw-r--r--src/w16select.c2
-rw-r--r--src/w32.c4
-rw-r--r--src/w32.h2
-rw-r--r--src/w32common.h2
-rw-r--r--src/w32console.c2
-rw-r--r--src/w32cygwinx.c2
-rw-r--r--src/w32fns.c7
-rw-r--r--src/w32font.c4
-rw-r--r--src/w32font.h2
-rw-r--r--src/w32gui.h2
-rw-r--r--src/w32heap.c4
-rw-r--r--src/w32heap.h2
-rw-r--r--src/w32image.c2
-rw-r--r--src/w32inevt.c4
-rw-r--r--src/w32inevt.h2
-rw-r--r--src/w32menu.c2
-rw-r--r--src/w32notify.c2
-rw-r--r--src/w32proc.c2
-rw-r--r--src/w32reg.c2
-rw-r--r--src/w32select.c2
-rw-r--r--src/w32select.h2
-rw-r--r--src/w32term.c10
-rw-r--r--src/w32term.h2
-rw-r--r--src/w32uniscribe.c2
-rw-r--r--src/w32xfns.c2
-rw-r--r--src/widget.c2
-rw-r--r--src/widget.h2
-rw-r--r--src/widgetprv.h2
-rw-r--r--src/window.c26
-rw-r--r--src/window.h6
-rw-r--r--src/xdisp.c349
-rw-r--r--src/xfaces.c26
-rw-r--r--src/xfns.c17
-rw-r--r--src/xfont.c4
-rw-r--r--src/xftfont.c2
-rw-r--r--src/xgselect.c2
-rw-r--r--src/xgselect.h2
-rw-r--r--src/xmenu.c2
-rw-r--r--src/xml.c2
-rw-r--r--src/xrdb.c2
-rw-r--r--src/xselect.c4
-rw-r--r--src/xsettings.c2
-rw-r--r--src/xsettings.h2
-rw-r--r--src/xsmfns.c2
-rw-r--r--src/xterm.c512
-rw-r--r--src/xterm.h2
-rw-r--r--src/xwidget.c2
-rw-r--r--src/xwidget.h2
-rw-r--r--test/ChangeLog.12
-rw-r--r--test/Makefile.in2
-rw-r--r--test/README2
-rw-r--r--test/infra/Dockerfile.emba3
-rw-r--r--test/infra/Makefile.in2
-rw-r--r--test/infra/gitlab-ci.yml6
-rw-r--r--test/infra/test-jobs.yml1
-rw-r--r--test/lib-src/emacsclient-tests.el2
-rw-r--r--test/lisp/abbrev-tests.el2
-rw-r--r--test/lisp/align-resources/lua-ts-mode.erts67
-rw-r--r--test/lisp/align-tests.el11
-rw-r--r--test/lisp/allout-tests.el2
-rw-r--r--test/lisp/allout-widgets-tests.el2
-rw-r--r--test/lisp/ansi-color-tests.el2
-rw-r--r--test/lisp/ansi-osc-tests.el2
-rw-r--r--test/lisp/apropos-tests.el2
-rw-r--r--test/lisp/arc-mode-tests.el2
-rw-r--r--test/lisp/auth-source-pass-tests.el2
-rw-r--r--test/lisp/auth-source-tests.el2
-rw-r--r--test/lisp/autoinsert-tests.el2
-rw-r--r--test/lisp/autorevert-tests.el4
-rw-r--r--test/lisp/battery-tests.el2
-rw-r--r--test/lisp/bookmark-tests.el2
-rw-r--r--test/lisp/buff-menu-tests.el2
-rw-r--r--test/lisp/button-tests.el2
-rw-r--r--test/lisp/calc/calc-tests.el40
-rw-r--r--test/lisp/calculator-tests.el2
-rw-r--r--test/lisp/calendar/cal-french-tests.el2
-rw-r--r--test/lisp/calendar/cal-julian-tests.el2
-rw-r--r--test/lisp/calendar/icalendar-tests.el2
-rw-r--r--test/lisp/calendar/iso8601-tests.el2
-rw-r--r--test/lisp/calendar/lunar-tests.el2
-rw-r--r--test/lisp/calendar/parse-time-tests.el2
-rw-r--r--test/lisp/calendar/solar-tests.el2
-rw-r--r--test/lisp/calendar/time-date-tests.el2
-rw-r--r--test/lisp/calendar/todo-mode-tests.el2
-rw-r--r--test/lisp/cedet/cedet-files-tests.el2
-rw-r--r--test/lisp/cedet/semantic-utest-c.el2
-rw-r--r--test/lisp/cedet/semantic-utest-ia-resources/test.srt2
-rw-r--r--test/lisp/cedet/semantic-utest-ia-resources/testdoublens.cpp2
-rw-r--r--test/lisp/cedet/semantic-utest-ia-resources/testdoublens.hpp2
-rw-r--r--test/lisp/cedet/semantic-utest-ia-resources/testjavacomp.java2
-rw-r--r--test/lisp/cedet/semantic-utest-ia-resources/testlocalvars.cpp2
-rw-r--r--test/lisp/cedet/semantic-utest-ia-resources/testnsp.cpp2
-rw-r--r--test/lisp/cedet/semantic-utest-ia-resources/testsppcomplete.c2
-rw-r--r--test/lisp/cedet/semantic-utest-ia-resources/teststruct.cpp2
-rw-r--r--test/lisp/cedet/semantic-utest-ia-resources/testsubclass.cpp2
-rw-r--r--test/lisp/cedet/semantic-utest-ia-resources/testsubclass.hh2
-rw-r--r--test/lisp/cedet/semantic-utest-ia-resources/testtemplates.cpp2
-rw-r--r--test/lisp/cedet/semantic-utest-ia-resources/testtypedefs.cpp2
-rw-r--r--test/lisp/cedet/semantic-utest-ia-resources/testusing.cpp2
-rw-r--r--test/lisp/cedet/semantic-utest-ia-resources/testusing.hh2
-rw-r--r--test/lisp/cedet/semantic-utest-ia-resources/testvarnames.c2
-rw-r--r--test/lisp/cedet/semantic-utest-ia-resources/testvarnames.java2
-rw-r--r--test/lisp/cedet/semantic-utest-ia-resources/testwisent.wy2
-rw-r--r--test/lisp/cedet/semantic-utest-ia.el2
-rw-r--r--test/lisp/cedet/semantic-utest.el2
-rw-r--r--test/lisp/cedet/semantic/bovine/gcc-tests.el111
-rw-r--r--test/lisp/cedet/semantic/format-resources/test-fmt.cpp2
-rw-r--r--test/lisp/cedet/semantic/format-resources/test-fmt.el2
-rw-r--r--test/lisp/cedet/semantic/format-tests.el2
-rw-r--r--test/lisp/cedet/semantic/fw-tests.el2
-rw-r--r--test/lisp/cedet/srecode-utest-getset.el2
-rw-r--r--test/lisp/cedet/srecode-utest-template.el2
-rw-r--r--test/lisp/cedet/srecode/document-tests.el2
-rw-r--r--test/lisp/cedet/srecode/fields-tests.el2
-rw-r--r--test/lisp/char-fold-tests.el2
-rw-r--r--test/lisp/color-tests.el2
-rw-r--r--test/lisp/comint-tests.el2
-rw-r--r--test/lisp/completion-preview-tests.el184
-rw-r--r--test/lisp/completion-tests.el2
-rw-r--r--test/lisp/cus-edit-tests.el2
-rw-r--r--test/lisp/custom-tests.el2
-rw-r--r--test/lisp/dabbrev-tests.el2
-rw-r--r--test/lisp/delim-col-tests.el2
-rw-r--r--test/lisp/descr-text-tests.el2
-rw-r--r--test/lisp/desktop-tests.el2
-rw-r--r--test/lisp/dired-aux-tests.el2
-rw-r--r--test/lisp/dired-tests.el6
-rw-r--r--test/lisp/dired-x-tests.el2
-rw-r--r--test/lisp/dnd-tests.el160
-rw-r--r--test/lisp/dom-tests.el2
-rw-r--r--test/lisp/edmacro-tests.el2
-rw-r--r--test/lisp/electric-tests.el2
-rw-r--r--test/lisp/elide-head-tests.el2
-rw-r--r--test/lisp/emacs-lisp/backquote-tests.el2
-rw-r--r--test/lisp/emacs-lisp/backtrace-tests.el2
-rw-r--r--test/lisp/emacs-lisp/benchmark-tests.el6
-rw-r--r--test/lisp/emacs-lisp/bindat-tests.el2
-rw-r--r--test/lisp/emacs-lisp/byte-run-tests.el32
-rw-r--r--test/lisp/emacs-lisp/bytecomp-resources/no-byte-compile.el2
-rw-r--r--test/lisp/emacs-lisp/bytecomp-tests.el178
-rw-r--r--test/lisp/emacs-lisp/cconv-tests.el2
-rw-r--r--test/lisp/emacs-lisp/check-declare-tests.el2
-rw-r--r--test/lisp/emacs-lisp/checkdoc-tests.el11
-rw-r--r--test/lisp/emacs-lisp/cl-extra-tests.el2
-rw-r--r--test/lisp/emacs-lisp/cl-generic-tests.el2
-rw-r--r--test/lisp/emacs-lisp/cl-lib-tests.el38
-rw-r--r--test/lisp/emacs-lisp/cl-macs-tests.el2
-rw-r--r--test/lisp/emacs-lisp/cl-preloaded-tests.el2
-rw-r--r--test/lisp/emacs-lisp/cl-print-tests.el20
-rw-r--r--test/lisp/emacs-lisp/cl-seq-tests.el2
-rw-r--r--test/lisp/emacs-lisp/comp-cstr-tests.el23
-rw-r--r--test/lisp/emacs-lisp/comp-tests.el2
-rw-r--r--test/lisp/emacs-lisp/copyright-tests.el2
-rw-r--r--test/lisp/emacs-lisp/derived-tests.el2
-rw-r--r--test/lisp/emacs-lisp/easy-mmode-tests.el2
-rw-r--r--test/lisp/emacs-lisp/edebug-resources/edebug-test-code.el2
-rw-r--r--test/lisp/emacs-lisp/edebug-tests.el2
-rw-r--r--test/lisp/emacs-lisp/eieio-tests/eieio-test-methodinvoke.el2
-rw-r--r--test/lisp/emacs-lisp/eieio-tests/eieio-test-persist.el2
-rw-r--r--test/lisp/emacs-lisp/eieio-tests/eieio-tests.el23
-rw-r--r--test/lisp/emacs-lisp/ert-font-lock-resources/broken.js3
-rw-r--r--test/lisp/emacs-lisp/ert-font-lock-resources/correct.js3
-rw-r--r--test/lisp/emacs-lisp/ert-font-lock-tests.el464
-rw-r--r--test/lisp/emacs-lisp/ert-tests.el16
-rw-r--r--test/lisp/emacs-lisp/ert-x-tests.el2
-rw-r--r--test/lisp/emacs-lisp/faceup-resources/faceup-test-mode.el2
-rw-r--r--test/lisp/emacs-lisp/faceup-resources/faceup-test-this-file-directory.el2
-rw-r--r--test/lisp/emacs-lisp/faceup-tests/faceup-test-basics.el2
-rw-r--r--test/lisp/emacs-lisp/faceup-tests/faceup-test-files.el2
-rw-r--r--test/lisp/emacs-lisp/find-func-tests.el4
-rw-r--r--test/lisp/emacs-lisp/float-sup-tests.el2
-rw-r--r--test/lisp/emacs-lisp/generator-tests.el2
-rw-r--r--test/lisp/emacs-lisp/gv-tests.el2
-rw-r--r--test/lisp/emacs-lisp/icons-tests.el2
-rw-r--r--test/lisp/emacs-lisp/let-alist-tests.el2
-rw-r--r--test/lisp/emacs-lisp/lisp-mnt-tests.el22
-rw-r--r--test/lisp/emacs-lisp/lisp-mode-tests.el2
-rw-r--r--test/lisp/emacs-lisp/lisp-tests.el2
-rw-r--r--test/lisp/emacs-lisp/macroexp-resources/m1.el2
-rw-r--r--test/lisp/emacs-lisp/macroexp-resources/m2.el2
-rw-r--r--test/lisp/emacs-lisp/macroexp-resources/vk.el2
-rw-r--r--test/lisp/emacs-lisp/macroexp-tests.el2
-rw-r--r--test/lisp/emacs-lisp/map-tests.el2
-rw-r--r--test/lisp/emacs-lisp/memory-report-tests.el2
-rw-r--r--test/lisp/emacs-lisp/multisession-tests.el2
-rw-r--r--test/lisp/emacs-lisp/nadvice-tests.el2
-rw-r--r--test/lisp/emacs-lisp/oclosure-tests.el2
-rwxr-xr-xtest/lisp/emacs-lisp/package-resources/signed/update-signatures.sh2
-rw-r--r--test/lisp/emacs-lisp/package-tests.el18
-rw-r--r--test/lisp/emacs-lisp/pcase-tests.el2
-rw-r--r--test/lisp/emacs-lisp/pp-tests.el2
-rw-r--r--test/lisp/emacs-lisp/range-tests.el2
-rw-r--r--test/lisp/emacs-lisp/regexp-opt-tests.el2
-rw-r--r--test/lisp/emacs-lisp/ring-tests.el2
-rw-r--r--test/lisp/emacs-lisp/rmc-tests.el2
-rw-r--r--test/lisp/emacs-lisp/rx-tests.el2
-rw-r--r--test/lisp/emacs-lisp/seq-tests.el2
-rw-r--r--test/lisp/emacs-lisp/shadow-tests.el2
-rw-r--r--test/lisp/emacs-lisp/shortdoc-tests.el2
-rw-r--r--test/lisp/emacs-lisp/subr-x-tests.el2
-rw-r--r--test/lisp/emacs-lisp/syntax-tests.el2
-rw-r--r--test/lisp/emacs-lisp/tabulated-list-tests.el2
-rw-r--r--test/lisp/emacs-lisp/testcover-resources/testcases.el2
-rw-r--r--test/lisp/emacs-lisp/testcover-tests.el2
-rw-r--r--test/lisp/emacs-lisp/text-property-search-tests.el2
-rw-r--r--test/lisp/emacs-lisp/thunk-tests.el2
-rw-r--r--test/lisp/emacs-lisp/timer-tests.el2
-rw-r--r--test/lisp/emacs-lisp/unsafep-tests.el2
-rw-r--r--test/lisp/emacs-lisp/vtable-tests.el2
-rw-r--r--test/lisp/emacs-lisp/warnings-tests.el2
-rw-r--r--test/lisp/emulation/viper-tests.el2
-rw-r--r--test/lisp/env-tests.el2
-rw-r--r--test/lisp/epg-config-tests.el2
-rw-r--r--test/lisp/epg-tests.el13
-rw-r--r--test/lisp/erc/erc-button-tests.el55
-rw-r--r--test/lisp/erc/erc-dcc-tests.el2
-rw-r--r--test/lisp/erc/erc-fill-tests.el242
-rw-r--r--test/lisp/erc/erc-goodies-tests.el27
-rw-r--r--test/lisp/erc/erc-join-tests.el2
-rw-r--r--test/lisp/erc/erc-match-tests.el2
-rw-r--r--test/lisp/erc/erc-networks-tests.el29
-rw-r--r--test/lisp/erc/erc-nicks-tests.el83
-rw-r--r--test/lisp/erc/erc-sasl-tests.el2
-rw-r--r--test/lisp/erc/erc-scenarios-auth-source.el4
-rw-r--r--test/lisp/erc/erc-scenarios-base-association-nick.el2
-rw-r--r--test/lisp/erc/erc-scenarios-base-association-query.el2
-rw-r--r--test/lisp/erc/erc-scenarios-base-association-samenet.el2
-rw-r--r--test/lisp/erc/erc-scenarios-base-association.el4
-rw-r--r--test/lisp/erc/erc-scenarios-base-attach.el6
-rw-r--r--test/lisp/erc/erc-scenarios-base-auto-recon.el2
-rw-r--r--test/lisp/erc/erc-scenarios-base-buffer-display.el106
-rw-r--r--test/lisp/erc/erc-scenarios-base-chan-modes.el84
-rw-r--r--test/lisp/erc/erc-scenarios-base-compat-rename-bouncer.el2
-rw-r--r--test/lisp/erc/erc-scenarios-base-local-module-modes.el2
-rw-r--r--test/lisp/erc/erc-scenarios-base-local-modules.el2
-rw-r--r--test/lisp/erc/erc-scenarios-base-misc-regressions.el50
-rw-r--r--test/lisp/erc/erc-scenarios-base-netid-bouncer-id.el2
-rw-r--r--test/lisp/erc/erc-scenarios-base-netid-bouncer-recon-base.el2
-rw-r--r--test/lisp/erc/erc-scenarios-base-netid-bouncer-recon-both.el2
-rw-r--r--test/lisp/erc/erc-scenarios-base-netid-bouncer-recon-id.el2
-rw-r--r--test/lisp/erc/erc-scenarios-base-netid-bouncer.el2
-rw-r--r--test/lisp/erc/erc-scenarios-base-netid-samenet.el2
-rw-r--r--test/lisp/erc/erc-scenarios-base-reconnect.el4
-rw-r--r--test/lisp/erc/erc-scenarios-base-renick.el6
-rw-r--r--test/lisp/erc/erc-scenarios-base-reuse-buffers.el4
-rw-r--r--test/lisp/erc/erc-scenarios-base-send-message.el126
-rw-r--r--test/lisp/erc/erc-scenarios-base-split-line.el2
-rw-r--r--test/lisp/erc/erc-scenarios-base-statusmsg.el103
-rw-r--r--test/lisp/erc/erc-scenarios-base-unstable.el2
-rw-r--r--test/lisp/erc/erc-scenarios-base-upstream-recon-soju.el2
-rw-r--r--test/lisp/erc/erc-scenarios-base-upstream-recon-znc.el2
-rw-r--r--test/lisp/erc/erc-scenarios-display-message.el63
-rw-r--r--test/lisp/erc/erc-scenarios-internal.el37
-rw-r--r--test/lisp/erc/erc-scenarios-join-auth-source.el2
-rw-r--r--test/lisp/erc/erc-scenarios-join-display-context.el2
-rw-r--r--test/lisp/erc/erc-scenarios-join-netid-newcmd-id.el2
-rw-r--r--test/lisp/erc/erc-scenarios-join-netid-newcmd.el2
-rw-r--r--test/lisp/erc/erc-scenarios-join-netid-recon-id.el2
-rw-r--r--test/lisp/erc/erc-scenarios-join-netid-recon.el2
-rw-r--r--test/lisp/erc/erc-scenarios-keep-place-indicator.el141
-rw-r--r--test/lisp/erc/erc-scenarios-log.el61
-rw-r--r--test/lisp/erc/erc-scenarios-match.el274
-rw-r--r--test/lisp/erc/erc-scenarios-misc-commands.el126
-rw-r--r--test/lisp/erc/erc-scenarios-misc.el4
-rw-r--r--test/lisp/erc/erc-scenarios-prompt-format.el117
-rw-r--r--test/lisp/erc/erc-scenarios-sasl.el37
-rw-r--r--test/lisp/erc/erc-scenarios-scrolltobottom-relaxed.el140
-rw-r--r--test/lisp/erc/erc-scenarios-scrolltobottom.el68
-rw-r--r--test/lisp/erc/erc-scenarios-services-misc.el2
-rw-r--r--test/lisp/erc/erc-scenarios-stamp.el181
-rw-r--r--test/lisp/erc/erc-scenarios-status-sidebar.el21
-rw-r--r--test/lisp/erc/erc-services-tests.el2
-rw-r--r--test/lisp/erc/erc-stamp-tests.el87
-rw-r--r--test/lisp/erc/erc-tests.el1819
-rw-r--r--test/lisp/erc/erc-track-tests.el168
-rw-r--r--test/lisp/erc/resources/base/assoc/bouncer-history/barnet.eld4
-rw-r--r--test/lisp/erc/resources/base/assoc/bouncer-history/foonet.eld4
-rw-r--r--test/lisp/erc/resources/base/assoc/bumped/again.eld10
-rw-r--r--test/lisp/erc/resources/base/assoc/bumped/foisted.eld10
-rw-r--r--test/lisp/erc/resources/base/assoc/bumped/refoisted.eld8
-rw-r--r--test/lisp/erc/resources/base/assoc/multi-net/barnet.eld12
-rw-r--r--test/lisp/erc/resources/base/assoc/multi-net/foonet.eld12
-rw-r--r--test/lisp/erc/resources/base/assoc/reconplay/foonet.eld2
-rw-r--r--test/lisp/erc/resources/base/display-message/multibuf.eld45
-rw-r--r--test/lisp/erc/resources/base/display-message/statusmsg.eld47
-rw-r--r--test/lisp/erc/resources/base/flood/soju.eld2
-rw-r--r--test/lisp/erc/resources/base/local-modules/first.eld6
-rw-r--r--test/lisp/erc/resources/base/local-modules/second.eld2
-rw-r--r--test/lisp/erc/resources/base/local-modules/third.eld2
-rw-r--r--test/lisp/erc/resources/base/modes/chan-changed.eld55
-rw-r--r--test/lisp/erc/resources/base/netid/bouncer/barnet-drop.eld4
-rw-r--r--test/lisp/erc/resources/base/netid/bouncer/barnet.eld2
-rw-r--r--test/lisp/erc/resources/base/netid/bouncer/foonet-drop.eld6
-rw-r--r--test/lisp/erc/resources/base/netid/bouncer/foonet.eld2
-rw-r--r--test/lisp/erc/resources/base/reconnect/aborted-dupe.eld2
-rw-r--r--test/lisp/erc/resources/base/reconnect/aborted.eld2
-rw-r--r--test/lisp/erc/resources/base/reconnect/options-again.eld4
-rw-r--r--test/lisp/erc/resources/base/renick/queries/solo.eld2
-rw-r--r--test/lisp/erc/resources/base/renick/self/qual-chester.eld2
-rw-r--r--test/lisp/erc/resources/base/renick/self/qual-tester.eld2
-rw-r--r--test/lisp/erc/resources/base/reuse-buffers/channel/barnet.eld2
-rw-r--r--test/lisp/erc/resources/base/reuse-buffers/channel/foonet.eld2
-rw-r--r--test/lisp/erc/resources/base/reuse-buffers/server/barnet.eld6
-rw-r--r--test/lisp/erc/resources/base/reuse-buffers/server/foonet.eld6
-rw-r--r--test/lisp/erc/resources/base/send-message/noncommands.eld52
-rw-r--r--test/lisp/erc/resources/commands/motd.eld (renamed from test/lisp/erc/resources/base/commands/motd.eld)0
-rw-r--r--test/lisp/erc/resources/commands/squery.eld31
-rw-r--r--test/lisp/erc/resources/commands/vhost.eld40
-rw-r--r--test/lisp/erc/resources/dcc/chat/accept.eld2
-rw-r--r--test/lisp/erc/resources/erc-d/erc-d-i.el2
-rw-r--r--test/lisp/erc/resources/erc-d/erc-d-t.el10
-rw-r--r--test/lisp/erc/resources/erc-d/erc-d-tests.el2
-rw-r--r--test/lisp/erc/resources/erc-d/erc-d-u.el3
-rw-r--r--test/lisp/erc/resources/erc-d/erc-d.el54
-rw-r--r--test/lisp/erc/resources/erc-d/resources/dynamic-barnet.eld4
-rw-r--r--test/lisp/erc/resources/erc-d/resources/dynamic-foonet.eld4
-rw-r--r--test/lisp/erc/resources/erc-d/resources/linger.eld4
-rw-r--r--test/lisp/erc/resources/erc-d/resources/proxy-subprocess.el2
-rw-r--r--test/lisp/erc/resources/erc-scenarios-common.el282
-rw-r--r--test/lisp/erc/resources/erc-tests-common.el301
-rw-r--r--test/lisp/erc/resources/fill/snapshots/merge-01-start.eld2
-rw-r--r--test/lisp/erc/resources/fill/snapshots/merge-02-right.eld2
-rw-r--r--test/lisp/erc/resources/fill/snapshots/merge-wrap-01.eld2
-rw-r--r--test/lisp/erc/resources/fill/snapshots/merge-wrap-indicator-post-01.eld1
-rw-r--r--test/lisp/erc/resources/fill/snapshots/merge-wrap-indicator-pre-01.eld1
-rw-r--r--test/lisp/erc/resources/fill/snapshots/monospace-01-start.eld2
-rw-r--r--test/lisp/erc/resources/fill/snapshots/monospace-02-right.eld2
-rw-r--r--test/lisp/erc/resources/fill/snapshots/monospace-03-left.eld2
-rw-r--r--test/lisp/erc/resources/fill/snapshots/monospace-04-reset.eld2
-rw-r--r--test/lisp/erc/resources/fill/snapshots/spacing-01-mono.eld2
-rw-r--r--test/lisp/erc/resources/fill/snapshots/stamps-left-01.eld2
-rw-r--r--test/lisp/erc/resources/join/legacy/foonet.eld2
-rw-r--r--test/lisp/erc/resources/join/network-id/barnet.eld2
-rw-r--r--test/lisp/erc/resources/join/network-id/foonet-again.eld2
-rw-r--r--test/lisp/erc/resources/join/network-id/foonet.eld4
-rw-r--r--test/lisp/erc/resources/keep-place/follow.eld78
-rw-r--r--test/lisp/erc/resources/match/fools/fill-wrap.eld41
-rw-r--r--test/lisp/erc/resources/sasl/plain-failed.eld10
-rw-r--r--test/lisp/erc/resources/sasl/scram-sha-1.eld2
-rw-r--r--test/lisp/erc/resources/sasl/scram-sha-256.eld2
-rw-r--r--test/lisp/erc/resources/scrolltobottom/help.eld46
-rw-r--r--test/lisp/eshell/em-alias-tests.el2
-rw-r--r--test/lisp/eshell/em-basic-tests.el2
-rw-r--r--test/lisp/eshell/em-cmpl-tests.el34
-rw-r--r--test/lisp/eshell/em-dirs-tests.el2
-rw-r--r--test/lisp/eshell/em-extpipe-tests.el10
-rw-r--r--test/lisp/eshell/em-glob-tests.el2
-rw-r--r--test/lisp/eshell/em-hist-tests.el136
-rw-r--r--test/lisp/eshell/em-ls-tests.el2
-rw-r--r--test/lisp/eshell/em-pred-tests.el2
-rw-r--r--test/lisp/eshell/em-prompt-tests.el111
-rw-r--r--test/lisp/eshell/em-script-tests.el15
-rw-r--r--test/lisp/eshell/em-tramp-tests.el2
-rw-r--r--test/lisp/eshell/em-unix-tests.el2
-rw-r--r--test/lisp/eshell/esh-arg-tests.el65
-rw-r--r--test/lisp/eshell/esh-cmd-tests.el121
-rw-r--r--test/lisp/eshell/esh-ext-tests.el2
-rw-r--r--test/lisp/eshell/esh-io-tests.el15
-rw-r--r--test/lisp/eshell/esh-opt-tests.el2
-rw-r--r--test/lisp/eshell/esh-proc-tests.el75
-rw-r--r--test/lisp/eshell/esh-util-tests.el32
-rw-r--r--test/lisp/eshell/esh-var-tests.el56
-rw-r--r--test/lisp/eshell/eshell-tests-helpers.el39
-rw-r--r--test/lisp/eshell/eshell-tests-unload.el2
-rw-r--r--test/lisp/eshell/eshell-tests.el129
-rw-r--r--test/lisp/faces-resources/faces-test-dark-theme.el2
-rw-r--r--test/lisp/faces-resources/faces-test-light-theme.el2
-rw-r--r--test/lisp/faces-tests.el2
-rw-r--r--test/lisp/ffap-tests.el2
-rw-r--r--test/lisp/filenotify-tests.el72
-rw-r--r--test/lisp/files-tests.el200
-rw-r--r--test/lisp/files-x-tests.el78
-rw-r--r--test/lisp/find-cmd-tests.el2
-rw-r--r--test/lisp/font-lock-tests.el2
-rw-r--r--test/lisp/format-spec-tests.el2
-rw-r--r--test/lisp/gnus/gnus-group-tests.el4
-rw-r--r--test/lisp/gnus/gnus-icalendar-tests.el2
-rw-r--r--test/lisp/gnus/gnus-search-tests.el2
-rw-r--r--test/lisp/gnus/gnus-test-headers.el2
-rw-r--r--test/lisp/gnus/gnus-tests.el2
-rw-r--r--test/lisp/gnus/gnus-util-tests.el2
-rw-r--r--test/lisp/gnus/message-tests.el2
-rw-r--r--test/lisp/gnus/mm-decode-tests.el2
-rw-r--r--test/lisp/gnus/mml-sec-tests.el2
-rw-r--r--test/lisp/gnus/nnrss-tests.el2
-rw-r--r--test/lisp/help-fns-tests.el2
-rw-r--r--test/lisp/help-mode-tests.el2
-rw-r--r--test/lisp/help-tests.el14
-rw-r--r--test/lisp/hfy-cmap-tests.el2
-rw-r--r--test/lisp/hi-lock-tests.el2
-rw-r--r--test/lisp/hl-line-tests.el2
-rw-r--r--test/lisp/htmlfontify-tests.el2
-rw-r--r--test/lisp/ibuffer-tests.el4
-rw-r--r--test/lisp/ido-tests.el2
-rw-r--r--test/lisp/image-file-tests.el2
-rw-r--r--test/lisp/image-tests.el2
-rw-r--r--test/lisp/image/exif-tests.el2
-rw-r--r--test/lisp/image/gravatar-tests.el2
-rw-r--r--test/lisp/image/image-dired-tests.el2
-rw-r--r--test/lisp/image/image-dired-util-tests.el2
-rw-r--r--test/lisp/image/wallpaper-tests.el2
-rw-r--r--test/lisp/imenu-tests.el2
-rw-r--r--test/lisp/info-tests.el2
-rw-r--r--test/lisp/info-xref-tests.el2
-rw-r--r--test/lisp/international/ccl-tests.el2
-rw-r--r--test/lisp/international/mule-tests.el26
-rw-r--r--test/lisp/international/mule-util-tests.el2
-rw-r--r--test/lisp/international/textsec-tests.el2
-rw-r--r--test/lisp/international/ucs-normalize-tests.el140
-rw-r--r--test/lisp/isearch-tests.el153
-rw-r--r--test/lisp/jit-lock-tests.el2
-rw-r--r--test/lisp/json-tests.el2
-rw-r--r--test/lisp/jsonrpc-tests.el11
-rw-r--r--test/lisp/kmacro-tests.el2
-rw-r--r--test/lisp/loadhist-resources/loadhist--bar.el2
-rw-r--r--test/lisp/loadhist-resources/loadhist--foo.el2
-rw-r--r--test/lisp/loadhist-tests.el2
-rw-r--r--test/lisp/lpr-tests.el2
-rw-r--r--test/lisp/ls-lisp-tests.el9
-rw-r--r--test/lisp/mail/flow-fill-tests.el2
-rw-r--r--test/lisp/mail/footnote-tests.el2
-rw-r--r--test/lisp/mail/ietf-drums-date-tests.el2
-rw-r--r--test/lisp/mail/ietf-drums-tests.el2
-rw-r--r--test/lisp/mail/mail-extr-tests.el2
-rw-r--r--test/lisp/mail/mail-parse-tests.el2
-rw-r--r--test/lisp/mail/mail-utils-tests.el2
-rw-r--r--test/lisp/mail/qp-tests.el2
-rw-r--r--test/lisp/mail/rfc2045-tests.el2
-rw-r--r--test/lisp/mail/rfc2047-tests.el2
-rw-r--r--test/lisp/mail/rfc6068-tests.el2
-rw-r--r--test/lisp/mail/rfc822-tests.el2
-rw-r--r--test/lisp/mail/rmail-tests.el2
-rw-r--r--test/lisp/mail/rmailmm-tests.el2
-rw-r--r--test/lisp/mail/undigest-tests.el2
-rw-r--r--test/lisp/mail/uudecode-tests.el2
-rw-r--r--test/lisp/man-tests.el2
-rw-r--r--test/lisp/md4-tests.el2
-rw-r--r--test/lisp/mh-e/mh-limit-tests.el2
-rw-r--r--test/lisp/mh-e/mh-thread-tests.el2
-rw-r--r--test/lisp/mh-e/mh-utils-tests.el2
-rw-r--r--test/lisp/mh-e/mh-xface-tests.el2
-rwxr-xr-xtest/lisp/mh-e/test-all-mh-variants.sh6
-rw-r--r--test/lisp/minibuffer-tests.el121
-rw-r--r--test/lisp/misc-tests.el2
-rw-r--r--test/lisp/mouse-tests.el2
-rw-r--r--test/lisp/mwheel-tests.el2
-rw-r--r--test/lisp/net/browse-url-tests.el2
-rw-r--r--test/lisp/net/dbus-tests.el5
-rw-r--r--test/lisp/net/dig-tests.el2
-rw-r--r--test/lisp/net/eudc-tests.el2
-rw-r--r--test/lisp/net/gnutls-tests.el2
-rw-r--r--test/lisp/net/hmac-md5-tests.el2
-rw-r--r--test/lisp/net/mailcap-tests.el26
-rw-r--r--test/lisp/net/network-stream-tests.el22
-rw-r--r--test/lisp/net/newsticker-tests.el2
-rw-r--r--test/lisp/net/nsm-tests.el2
-rw-r--r--test/lisp/net/ntlm-tests.el2
-rw-r--r--test/lisp/net/puny-tests.el2
-rw-r--r--test/lisp/net/rcirc-tests.el2
-rw-r--r--test/lisp/net/rfc2104-tests.el2
-rw-r--r--test/lisp/net/sasl-cram-tests.el2
-rw-r--r--test/lisp/net/sasl-scram-rfc-tests.el2
-rw-r--r--test/lisp/net/sasl-tests.el2
-rw-r--r--test/lisp/net/secrets-tests.el2
-rw-r--r--test/lisp/net/shr-tests.el2
-rw-r--r--test/lisp/net/socks-tests.el86
-rw-r--r--test/lisp/net/tramp-archive-tests.el2
-rw-r--r--test/lisp/net/tramp-tests.el231
-rw-r--r--test/lisp/net/webjump-tests.el4
-rw-r--r--test/lisp/newcomment-tests.el2
-rw-r--r--test/lisp/nxml/nxml-mode-tests.el2
-rw-r--r--test/lisp/nxml/xsd-regexp-tests.el2
-rw-r--r--test/lisp/obarray-tests.el2
-rw-r--r--test/lisp/obsolete/cl-tests.el2
-rw-r--r--test/lisp/obsolete/inversion-tests.el2
-rw-r--r--test/lisp/obsolete/makesum-tests.el2
-rw-r--r--test/lisp/obsolete/rfc2368-tests.el2
-rw-r--r--test/lisp/obsolete/thumbs-tests.el2
-rw-r--r--test/lisp/org/org-tests.el2
-rw-r--r--test/lisp/paren-tests.el2
-rw-r--r--test/lisp/password-cache-tests.el2
-rw-r--r--test/lisp/pcmpl-linux-tests.el2
-rw-r--r--test/lisp/pcomplete-tests.el2
-rw-r--r--test/lisp/play/animate-tests.el2
-rw-r--r--test/lisp/play/cookie1-tests.el2
-rw-r--r--test/lisp/play/dissociate-tests.el2
-rw-r--r--test/lisp/play/fortune-tests.el2
-rw-r--r--test/lisp/play/life-tests.el2
-rw-r--r--test/lisp/play/morse-tests.el2
-rw-r--r--test/lisp/play/studly-tests.el2
-rw-r--r--test/lisp/proced-tests.el5
-rw-r--r--test/lisp/progmodes/asm-mode-tests.el2
-rw-r--r--test/lisp/progmodes/autoconf-tests.el2
-rw-r--r--test/lisp/progmodes/bat-mode-tests.el2
-rw-r--r--test/lisp/progmodes/bug-reference-tests.el17
-rw-r--r--test/lisp/progmodes/c-ts-mode-resources/indent-bsd.erts34
-rw-r--r--test/lisp/progmodes/c-ts-mode-resources/indent.erts68
-rw-r--r--test/lisp/progmodes/c-ts-mode-tests.el2
-rw-r--r--test/lisp/progmodes/cc-mode-tests.el2
-rw-r--r--test/lisp/progmodes/compile-tests.el28
-rw-r--r--test/lisp/progmodes/cperl-mode-resources/cperl-bug-35925.pl36
-rw-r--r--test/lisp/progmodes/cperl-mode-resources/cperl-bug-65834.pl5
-rw-r--r--test/lisp/progmodes/cperl-mode-resources/cperl-bug-66145.pl62
-rw-r--r--test/lisp/progmodes/cperl-mode-resources/cperl-bug-66161.pl13
-rw-r--r--test/lisp/progmodes/cperl-mode-tests.el73
-rw-r--r--test/lisp/progmodes/eglot-tests.el93
-rw-r--r--test/lisp/progmodes/elisp-mode-tests.el10
-rw-r--r--test/lisp/progmodes/elixir-ts-mode-resources/indent.erts16
-rw-r--r--test/lisp/progmodes/elixir-ts-mode-tests.el2
-rw-r--r--test/lisp/progmodes/etags-tests.el2
-rw-r--r--test/lisp/progmodes/executable-tests.el2
-rw-r--r--test/lisp/progmodes/f90-tests.el2
-rw-r--r--test/lisp/progmodes/flymake-tests.el5
-rw-r--r--test/lisp/progmodes/gdb-mi-tests.el2
-rw-r--r--test/lisp/progmodes/glasses-tests.el2
-rw-r--r--test/lisp/progmodes/go-ts-mode-tests.el2
-rw-r--r--test/lisp/progmodes/grep-tests.el2
-rw-r--r--test/lisp/progmodes/heex-ts-mode-tests.el2
-rw-r--r--test/lisp/progmodes/hideshow-tests.el2
-rw-r--r--test/lisp/progmodes/java-ts-mode-tests.el2
-rw-r--r--test/lisp/progmodes/js-resources/js-ts-indents.erts44
-rw-r--r--test/lisp/progmodes/js-tests.el8
-rw-r--r--test/lisp/progmodes/lua-ts-mode-resources/font-lock.lua339
-rw-r--r--test/lisp/progmodes/lua-ts-mode-resources/indent.erts679
-rw-r--r--test/lisp/progmodes/lua-ts-mode-resources/movement.erts603
-rw-r--r--test/lisp/progmodes/lua-ts-mode-tests.el42
-rw-r--r--test/lisp/progmodes/octave-tests.el2
-rw-r--r--test/lisp/progmodes/opascal-tests.el2
-rw-r--r--test/lisp/progmodes/pascal-tests.el2
-rw-r--r--test/lisp/progmodes/perl-mode-tests.el21
-rw-r--r--test/lisp/progmodes/project-tests.el3
-rw-r--r--test/lisp/progmodes/ps-mode-tests.el2
-rw-r--r--test/lisp/progmodes/python-tests.el306
-rw-r--r--test/lisp/progmodes/ruby-mode-resources/ruby-ts.rb4
-rw-r--r--test/lisp/progmodes/ruby-mode-resources/ruby.rb6
-rw-r--r--test/lisp/progmodes/ruby-mode-tests.el14
-rw-r--r--test/lisp/progmodes/ruby-ts-mode-tests.el2
-rw-r--r--test/lisp/progmodes/scheme-tests.el2
-rw-r--r--test/lisp/progmodes/sh-script-resources/sh-indents.erts7
-rw-r--r--test/lisp/progmodes/sh-script-tests.el13
-rw-r--r--test/lisp/progmodes/sql-tests.el2
-rw-r--r--test/lisp/progmodes/subword-tests.el2
-rw-r--r--test/lisp/progmodes/tcl-tests.el2
-rw-r--r--test/lisp/progmodes/typescript-ts-mode-resources/indent.erts39
-rw-r--r--test/lisp/progmodes/typescript-ts-mode-tests.el2
-rw-r--r--test/lisp/progmodes/which-func-tests.el58
-rw-r--r--test/lisp/progmodes/xref-tests.el2
-rw-r--r--test/lisp/ps-print-tests.el2
-rw-r--r--test/lisp/register-tests.el2
-rw-r--r--test/lisp/repeat-tests.el2
-rw-r--r--test/lisp/replace-tests.el2
-rw-r--r--test/lisp/rot13-tests.el2
-rw-r--r--test/lisp/saveplace-tests.el2
-rw-r--r--test/lisp/scroll-lock-tests.el2
-rw-r--r--test/lisp/server-tests.el2
-rw-r--r--test/lisp/ses-tests.el26
-rw-r--r--test/lisp/shadowfile-tests.el22
-rw-r--r--test/lisp/shell-tests.el2
-rw-r--r--test/lisp/simple-tests.el8
-rw-r--r--test/lisp/so-long-tests/autoload-longlines-mode-tests.el2
-rw-r--r--test/lisp/so-long-tests/autoload-major-mode-tests.el2
-rw-r--r--test/lisp/so-long-tests/autoload-minor-mode-tests.el2
-rw-r--r--test/lisp/so-long-tests/so-long-tests-helpers.el2
-rw-r--r--test/lisp/so-long-tests/so-long-tests.el2
-rw-r--r--test/lisp/so-long-tests/spelling-tests.el2
-rw-r--r--test/lisp/sort-tests.el2
-rw-r--r--test/lisp/soundex-tests.el2
-rw-r--r--test/lisp/startup-tests.el2
-rw-r--r--test/lisp/subr-tests.el56
-rw-r--r--test/lisp/tab-bar-tests.el2
-rw-r--r--test/lisp/tabify-tests.el2
-rw-r--r--test/lisp/tar-mode-tests.el2
-rw-r--r--test/lisp/tempo-tests.el2
-rw-r--r--test/lisp/term-tests.el22
-rw-r--r--test/lisp/term/tty-colors-tests.el2
-rw-r--r--test/lisp/textmodes/bibtex-tests.el2
-rw-r--r--test/lisp/textmodes/conf-mode-tests.el2
-rw-r--r--test/lisp/textmodes/css-mode-tests.el2
-rw-r--r--test/lisp/textmodes/dns-mode-tests.el2
-rw-r--r--test/lisp/textmodes/emacs-news-mode-tests.el2
-rw-r--r--test/lisp/textmodes/fill-tests.el4
-rw-r--r--test/lisp/textmodes/mhtml-mode-tests.el2
-rw-r--r--test/lisp/textmodes/page-tests.el2
-rw-r--r--test/lisp/textmodes/paragraphs-tests.el2
-rw-r--r--test/lisp/textmodes/po-tests.el2
-rw-r--r--test/lisp/textmodes/reftex-tests.el2
-rw-r--r--test/lisp/textmodes/sgml-mode-tests.el2
-rw-r--r--test/lisp/textmodes/texinfo-tests.el2
-rw-r--r--test/lisp/textmodes/tildify-tests.el4
-rw-r--r--test/lisp/textmodes/underline-tests.el2
-rw-r--r--test/lisp/thingatpt-tests.el8
-rw-r--r--test/lisp/thread-tests.el4
-rw-r--r--test/lisp/time-stamp-tests.el34
-rw-r--r--test/lisp/time-tests.el2
-rw-r--r--test/lisp/timezone-tests.el2
-rw-r--r--test/lisp/uniquify-tests.el2
-rw-r--r--test/lisp/url/url-auth-tests.el2
-rw-r--r--test/lisp/url/url-domsuf-tests.el2
-rw-r--r--test/lisp/url/url-expand-tests.el3
-rw-r--r--test/lisp/url/url-file-tests.el2
-rw-r--r--test/lisp/url/url-future-tests.el2
-rw-r--r--test/lisp/url/url-handlers-tests.el2
-rw-r--r--test/lisp/url/url-misc-tests.el2
-rw-r--r--test/lisp/url/url-parse-tests.el3
-rw-r--r--test/lisp/url/url-tramp-tests.el2
-rw-r--r--test/lisp/url/url-util-tests.el2
-rw-r--r--test/lisp/use-package/use-package-tests.el2
-rw-r--r--test/lisp/vc/add-log-tests.el2
-rw-r--r--test/lisp/vc/diff-mode-tests.el2
-rw-r--r--test/lisp/vc/ediff-diff-tests.el2
-rw-r--r--test/lisp/vc/ediff-ptch-tests.el2
-rw-r--r--test/lisp/vc/log-edit-tests.el2
-rw-r--r--test/lisp/vc/smerge-mode-tests.el2
-rw-r--r--test/lisp/vc/vc-bzr-tests.el2
-rw-r--r--test/lisp/vc/vc-cvs-tests.el2
-rw-r--r--test/lisp/vc/vc-git-tests.el2
-rw-r--r--test/lisp/vc/vc-hg-tests.el6
-rw-r--r--test/lisp/vc/vc-tests.el11
-rw-r--r--test/lisp/version-tests.el2
-rw-r--r--test/lisp/wdired-tests.el2
-rw-r--r--test/lisp/whitespace-tests.el2
-rw-r--r--test/lisp/wid-edit-tests.el13
-rw-r--r--test/lisp/x-dnd-tests.el2
-rw-r--r--test/lisp/xdg-tests.el2
-rw-r--r--test/lisp/xml-tests.el2
-rw-r--r--test/lisp/xt-mouse-tests.el2
-rw-r--r--test/lisp/yank-media-tests.el2
-rw-r--r--test/manual/BidiCharacterTest.txt6
-rw-r--r--test/manual/biditest.el2
-rw-r--r--test/manual/cedet/cedet-utests.el2
-rw-r--r--test/manual/cedet/ede-tests.el2
-rw-r--r--test/manual/cedet/semantic-tests.el2
-rw-r--r--test/manual/cedet/tests/test.c2
-rw-r--r--test/manual/cedet/tests/test.el2
-rw-r--r--test/manual/cedet/tests/test.make2
-rw-r--r--test/manual/cedet/tests/testpolymorph.cpp2
-rw-r--r--test/manual/cedet/tests/testspp.c2
-rw-r--r--test/manual/cedet/tests/testsppreplace.c2
-rw-r--r--test/manual/cedet/tests/testsppreplaced.c2
-rw-r--r--test/manual/etags/c-src/abbrev.c2
-rw-r--r--test/manual/etags/c-src/emacs/src/gmalloc.c2
-rw-r--r--test/manual/etags/c-src/emacs/src/keyboard.c2
-rw-r--r--test/manual/etags/c-src/emacs/src/lisp.h2
-rw-r--r--test/manual/etags/c-src/emacs/src/regex.h2
-rw-r--r--test/manual/etags/c-src/etags.c2
-rw-r--r--test/manual/etags/c-src/exit.c2
-rw-r--r--test/manual/etags/c-src/exit.strange_suffix2
-rw-r--r--test/manual/etags/c-src/getopt.h2
-rw-r--r--test/manual/etags/c-src/sysdep.h2
-rw-r--r--test/manual/etags/el-src/emacs/lisp/progmodes/etags.el2
-rw-r--r--test/manual/etags/tex-src/texinfo.tex2
-rw-r--r--test/manual/etags/y-src/cccp.c2
-rw-r--r--test/manual/etags/y-src/parse.c2
-rw-r--r--test/manual/etags/y-src/parse.y2
-rw-r--r--test/manual/image-circular-tests.el2
-rw-r--r--test/manual/image-size-tests.el2
-rw-r--r--test/manual/image-tests.el16
-rw-r--r--test/manual/image-transforms-tests.el2
-rw-r--r--test/manual/indent/pascal.pas2
-rw-r--r--test/manual/noverlay/Makefile.in2
-rwxr-xr-xtest/manual/noverlay/check-sanitize.sh2
-rw-r--r--test/manual/noverlay/emacs-compat.h2
-rw-r--r--test/manual/noverlay/itree-tests.c2
-rw-r--r--test/manual/noverlay/overlay-perf.el2
-rw-r--r--test/manual/process-callout-tests.el2
-rw-r--r--test/manual/redisplay-testsuite.el2
-rw-r--r--test/manual/scroll-tests.el12
-rw-r--r--test/misc/test-custom-deps.el2
-rw-r--r--test/misc/test-custom-libs.el4
-rw-r--r--test/misc/test-custom-noloads.el2
-rw-r--r--test/misc/test-custom-opts.el2
-rw-r--r--test/src/alloc-tests.el2
-rw-r--r--test/src/buffer-tests.el3
-rw-r--r--test/src/callint-tests.el2
-rw-r--r--test/src/callproc-tests.el2
-rw-r--r--test/src/casefiddle-tests.el14
-rw-r--r--test/src/character-tests.el2
-rw-r--r--test/src/charset-tests.el2
-rw-r--r--test/src/chartab-tests.el2
-rw-r--r--test/src/cmds-tests.el2
-rw-r--r--test/src/coding-tests.el2
-rw-r--r--test/src/comp-resources/comp-test-funcs-dyn.el2
-rw-r--r--test/src/comp-resources/comp-test-funcs-dyn2.el2
-rw-r--r--test/src/comp-resources/comp-test-funcs.el22
-rw-r--r--test/src/comp-resources/comp-test-pure.el2
-rw-r--r--test/src/comp-tests.el40
-rw-r--r--test/src/data-tests.el2
-rw-r--r--test/src/decompress-tests.el2
-rw-r--r--test/src/doc-tests.el2
-rw-r--r--test/src/editfns-tests.el2
-rw-r--r--test/src/emacs-module-resources/mod-test.c2
-rw-r--r--test/src/emacs-module-tests.el4
-rw-r--r--test/src/emacs-tests.el2
-rw-r--r--test/src/eval-tests.el23
-rw-r--r--test/src/fileio-tests.el4
-rw-r--r--test/src/filelock-tests.el14
-rw-r--r--test/src/floatfns-tests.el2
-rw-r--r--test/src/fns-tests.el22
-rw-r--r--test/src/font-tests.el2
-rw-r--r--test/src/image-tests.el8
-rw-r--r--test/src/indent-tests.el2
-rw-r--r--test/src/inotify-tests.el2
-rw-r--r--test/src/json-tests.el2
-rw-r--r--test/src/keyboard-tests.el2
-rw-r--r--test/src/keymap-tests.el2
-rw-r--r--test/src/lcms-tests.el2
-rw-r--r--test/src/lread-tests.el2
-rw-r--r--test/src/marker-tests.el2
-rw-r--r--test/src/minibuf-tests.el2
-rw-r--r--test/src/print-tests.el2
-rw-r--r--test/src/process-tests.el8
-rw-r--r--test/src/regex-emacs-tests.el45
-rw-r--r--test/src/regex-resources/PTESTS1
-rw-r--r--test/src/search-tests.el40
-rw-r--r--test/src/sqlite-tests.el2
-rw-r--r--test/src/syntax-tests.el2
-rw-r--r--test/src/textprop-tests.el2
-rw-r--r--test/src/thread-tests.el2
-rw-r--r--test/src/timefns-tests.el2
-rw-r--r--test/src/treesit-tests.el59
-rw-r--r--test/src/undo-tests.el2
-rw-r--r--test/src/xdisp-tests.el2
-rw-r--r--test/src/xfaces-tests.el2
-rw-r--r--test/src/xml-tests.el2
3580 files changed, 69515 insertions, 29651 deletions
diff --git a/.clang-format b/.clang-format
index 5c987536b0c..7929a7435f2 100644
--- a/.clang-format
+++ b/.clang-format
@@ -1,4 +1,3 @@
-Language: Cpp
BasedOnStyle: GNU
AlignEscapedNewlinesLeft: true
AlignOperands: Align
@@ -35,6 +34,10 @@ PenaltyBreakBeforeFirstCallParameter: 2000
SpaceAfterCStyleCast: true
SpaceBeforeParens: Always
UseTab: Always
+---
+Language: Cpp
+---
+Language: ObjC
# Local Variables:
# mode: yaml
diff --git a/.clangd b/.clangd
new file mode 100644
index 00000000000..469d33dfd03
--- /dev/null
+++ b/.clangd
@@ -0,0 +1,5 @@
+---
+If:
+ PathMatch: "src/*.c"
+CompileFlags:
+ Add: [-Wno-unused-macros, -include=config.h]
diff --git a/.gitattributes b/.gitattributes
index 39a82cc0efc..38cc45f3ee3 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -1,6 +1,6 @@
# Attributes of Emacs files in the Git repository.
-# Copyright 2015-2023 Free Software Foundation, Inc.
+# Copyright 2015-2024 Free Software Foundation, Inc.
# This file is part of GNU Emacs.
diff --git a/.gitignore b/.gitignore
index 7cd2241f149..b9dfdc4579e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,6 @@
# Files that Git should ignore in the Emacs source directory.
-# Copyright 2009-2023 Free Software Foundation, Inc.
+# Copyright 2009-2024 Free Software Foundation, Inc.
# This file is part of GNU Emacs.
@@ -132,6 +132,7 @@ lisp/cedet/semantic/grammar-wy.el
lisp/eshell/esh-groups.el
lisp/finder-inf.el
lisp/leim/ja-dic/
+leim/small-ja-dic-option
lisp/leim/leim-list.el
lisp/leim/quail/4Corner.el
lisp/leim/quail/ARRAY30.el
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 8462fdddc3a..a9cf69ac195 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -1,4 +1,4 @@
-# Copyright (C) 2021-2023 Free Software Foundation, Inc.
+# Copyright (C) 2021-2024 Free Software Foundation, Inc.
#
# This file is part of GNU Emacs.
#
diff --git a/.mailmap b/.mailmap
index f14f086b2e5..5d80e4aa082 100644
--- a/.mailmap
+++ b/.mailmap
@@ -27,6 +27,7 @@ Andrew G Cohen <cohen@andy.bu.edu> <cohen@bu.edu>
Arash Esbati <arash@gnu.org> <arash.esbati@gmail.com>
Arash Esbati <arash@gnu.org> <esbati@gmx.de>
Artur Malabarba <bruce.connor.am@gmail.com> <am12548@it055607.users.bris.ac.uk>
+Artur Malabarba <bruce.connor.am@gmail.com> Artur Malabarba <address@hidden>
Bastien Guerry <bzg@gnu.org>
Bastien Guerry <bzg@gnu.org> <bastien1@free.fr>
Bastien Guerry <bzg@gnu.org> <bzg@altern.org>
@@ -60,7 +61,7 @@ Era Eriksson <era+emacs@iki.fi> <era+emacsbugs@iki.fi>
Eric Ludlam <zappo@gnu.org>
Eric Ludlam <zappo@gnu.org> <eric@siege-engine.com>
Eric Ludlam <zappo@gnu.org> <ericludlam@gmail.com>
-Eric S. Raymond <esr@thyrsus.com>
+Eric S. Raymond <esr@thyrsus.com> <esr@snark.thyrsus.com>
Etienne Prud’homme <e.e.f.prudhomme@gmail.com>
Fabián Ezequiel Gallina <fgallina@gnu.org> <fgallina@cuca>
Fabián Ezequiel Gallina <fgallina@gnu.org> <galli.87@gmail.com>
@@ -89,6 +90,7 @@ Joakim Verona <joakim@verona.se> <root@exodia.verona.se>
John Wiegley <johnw@newartisans.com> <jwiegley@gmail.com>
Jose A. Ortega Ruiz <jao@gnu.org>
João Távora <joaotavora@gmail.com>
+João Távora <joaotavora@gmail.com> <capitaomorte@archlinux2022.linuxvmimages.local>
Julien Danjou <julien@danjou.info> <jd@dex.adm.naquadah.org>
Julien Danjou <julien@danjou.info> Julien Danjou <jd@abydos>
Juri Linkov <juri@linkov.net> <juri@jurta.org>
@@ -121,6 +123,7 @@ Masatake YAMATO <yamato@redhat.com> <jet@gyve.org>
Matt Armstrong <matt@rfc20.org> <marmstrong@google.com>
Matt Armstrong <matt@rfc20.org> <matt@mdeb>
Mattias Engdegård <mattiase@acm.org>
+Mattias Engdegård <mattiase@acm.org> <mattias.engdegard@gmail.com>
Maxim Nikulin <manikulin@gmail.com>
Michael Albinus <michael.albinus@gmx.de> <albinus@detlef>
Michalis V <mvar.40k@gmail.com>
@@ -189,6 +192,7 @@ Wolfgang Scherer <wolfgang.scherer@gmx.de> <Wolfgang.Scherer@gmx.de>
Xi Lu <lx@shellcodes.org>
Xue Fuqiao <xfq.free@gmail.com> <xfq@gnu.org>
Yilkal Argaw <yilkalargawworkneh@gmail.com>
+Yuan Fu <casouri@gmail.com> <yuan@debian-BULLSEYE-live-builder-AMD64>
Yuuki Harano <masm+github@masm11.me> <masm@masm11.ddo.jp>
Óscar Fuentes <ofv@wanadoo.es>
İ. Göktuğ Kayaalp <self@gkayaalp.com>
diff --git a/CONTRIBUTE b/CONTRIBUTE
index 464b800adfb..70b9760bb99 100644
--- a/CONTRIBUTE
+++ b/CONTRIBUTE
@@ -1,4 +1,4 @@
-Copyright (C) 2006-2023 Free Software Foundation, Inc.
+Copyright (C) 2006-2024 Free Software Foundation, Inc.
See the end of the file for license conditions.
* How developers contribute to GNU Emacs
@@ -120,9 +120,9 @@ Emacs version in which they will appear. Likewise with defcustom's
whose value is changed -- update their ':version' tag.
Think about whether your change requires updating the manuals. If you
-know it does not, mark the NEWS entry with "---". If you know
-that *all* the necessary documentation updates have been made as part
-of your changes or those by others, mark the entry with "+++".
+know it does not, mark the NEWS entry with "---" before the entry. If
+you know that *all* the necessary documentation updates have been made
+as part of your changes or those by others, mark the entry with "+++".
Otherwise, do not mark it.
If your change requires updating the manuals to document new
@@ -300,6 +300,11 @@ them right the first time, so here are guidelines for formatting them:
blank ChangeLog entries from the diff being committed, then use
'M-q' to combine and fill them. See 'info "(emacs) Log Buffer"'.
+- If you use the third-party package Magit, you can use
+ 'magit-generate-changelog' from the commit message buffer.
+ See also 'magit-add-change-log-entry' and
+ 'magit-add-change-log-entry-other-window'.
+
- Alternatively, you can use Emacs functions for ChangeLog files; see
https://www.gnu.org/software/emacs/manual/html_node/emacs/Change-Log-Commands.html
or run 'info "(emacs)Change Log Commands"'.
diff --git a/ChangeLog.1 b/ChangeLog.1
index 654cb43d4dc..b592cc0bcab 100644
--- a/ChangeLog.1
+++ b/ChangeLog.1
@@ -1494,7 +1494,7 @@
2014-01-05 Paul Eggert <eggert@cs.ucla.edu>
Port to GNU/Linux with recent grsecurity/PaX patches (Bug#16343).
- Problem and proposed patch reported by Ulrich Mueller;
+ Problem and proposed patch reported by Ulrich Müller;
this patch uses a somewhat-different approach.
* configure.ac (SETFATTR): New variable.
@@ -14700,7 +14700,7 @@
;; coding: utf-8
;; End:
- Copyright (C) 1993-1999, 2001-2023 Free Software Foundation, Inc.
+ Copyright (C) 1993-1999, 2001-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/ChangeLog.2 b/ChangeLog.2
index 11e6049b0bd..7c1267e66b9 100644
--- a/ChangeLog.2
+++ b/ChangeLog.2
@@ -8956,10 +8956,10 @@
2016-02-04 Carlos Pita <carlosjosepita@gmail.com> (tiny change)
- Make complection in erc use consistent casing
+ Make completion in erc use consistent casing
* lisp/erc/erc-pcomplete.el (pcomplete-erc-all-nicks): Make
- case in the complection consistent (bug#18509).
+ case in the completion consistent (bug#18509).
2016-02-04 Francis Litterio <flitterio@gmail.com>
@@ -10661,8 +10661,8 @@
* lisp/gnus/nnir.el (nnir-request-update-mark):
Default to the original mark.
- cf. <http://thread.gmane.org/gmane.emacs.gnus.general/86583>
- and <http://thread.gmane.org/gmane.emacs.gnus.general/86640>
+ cf. <http://thread.gmane.org/gmane.emacs.gnus.general/86583> [dead link]
+ and <http://thread.gmane.org/gmane.emacs.gnus.general/86640> [dead link]
2016-01-19 Glenn Morris <rgm@gnu.org>
@@ -12012,7 +12012,7 @@
(Maybe this is the last merge from Gnus git to Emacs git)
Cf. discussion on ding mailing list, messages in
- <http://thread.gmane.org/gmane.emacs.gnus.general/86228>.
+ <http://thread.gmane.org/gmane.emacs.gnus.general/86228>. [dead link]
Common code from the three files mml-smime.el, mml1991.el, and
mml2015.el is moved to mml-sec.el. Auxiliary functions are added
to gnus-util.el.
@@ -15206,8 +15206,9 @@
Remove nnml-retrieve-groups that is unnecessary and somewhat problematic
* lisp/gnus/nnml.el (nnml-retrieve-groups): Remove. See:
- <http://thread.gmane.org/gmane.emacs.gnus.general/86308> and
- <http://thread.gmane.org/gmane.emacs.gnus.general/86321>
+ <http://thread.gmane.org/gmane.emacs.gnus.general/86308> [dead link]
+ and
+ <http://thread.gmane.org/gmane.emacs.gnus.general/86321> [dead link]
2015-11-25 Paul Eggert <eggert@cs.ucla.edu>
@@ -17093,11 +17094,11 @@
* lisp/json.el (json-encoding-object-sort-predicate): New variable
for specifying a sorting predicate for JSON objects during encoding.
(json--plist-to-alist): New utility function.
- (json-encode-hash-table): Re-use `json-encode-alist' when object keys
+ (json-encode-hash-table): Reuse `json-encode-alist' when object keys
are to be sorted.
(json-encode-alist): Sort output by
`json-encoding-object-sort-predicate, when set.
- (json-encode-plist): Re-use `json-encode-alist' when object keys are
+ (json-encode-plist): Reuse `json-encode-alist' when object keys are
to be sorted.
(json-pretty-print-buffer-ordered): New command to pretty print the
buffer with object keys sorted alphabetically.
@@ -19541,7 +19542,7 @@
calling low-level functions.
* test/automated/file-notify-tests.el (file-notify--test-timeout):
- Decrase to 6 seconds for remote directories.
+ Decrease to 6 seconds for remote directories.
(file-notify-test02-events): Expect different number of
`attribute-changed' events for the local and remote cases. Apply
short delays between the operations, in order to receive all
@@ -30968,7 +30969,7 @@
2015-05-28 Katsumi Yamaoka <yamaoka@jpl.org>
* lisp/gnus/gnus-art.el (gnus-button-alist): Re-revert last change.
- cf. <http://news.gmane.org/group/gmane.emacs.devel/thread=186896>
+ cf. <http://news.gmane.org/group/gmane.emacs.devel/thread=186896> [dead link]
2015-05-28 Samer Masterson <samer@samertm.com>
@@ -32623,7 +32624,7 @@
(verilog-set-auto-endcomments): Fix end comments for functions of
type void, etc. Reported by Alex Reed.
(verilog-do-indent): Fix electric tab deleting form-feeds. Note
- caused by indent-line-to deleting tabls pre 24.5.
+ caused by indent-line-to deleting tables pre 24.5.
(verilog-nameable-item-re): Fix nameable items that can have an
end-identifier to include endchecker, endgroup, endprogram,
endproperty, and endsequence. Reported by Alex Reed.
@@ -35787,7 +35788,7 @@ See ChangeLog.1 for earlier changes.
;; coding: utf-8
;; End:
- Copyright (C) 2015-2023 Free Software Foundation, Inc.
+ Copyright (C) 2015-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/ChangeLog.3 b/ChangeLog.3
index 85cccf0d6ed..dc712df43ad 100644
--- a/ChangeLog.3
+++ b/ChangeLog.3
@@ -146,7 +146,7 @@
2022-10-04 Andreas Schwab <schwab@linux-m68k.org>
- * src/emacs.c (load_pdump): Propery handle case when executable
+ * src/emacs.c (load_pdump): Properly handle case when executable
wasn't found.
2022-10-04 Eli Zaretskii <eliz@gnu.org>
@@ -3672,7 +3672,7 @@
* lib-src/emacsclient.c (set_local_socket): Revert to the Emacs 27
behavior of not trying TMPDIR if XDG_RUNTIME_DIR is set.
This is one of the suggestions made by Jim Porter and
- independently by Ulrich Mueller in Bug#51327.
+ independently by Ulrich Müller in Bug#51327.
2021-12-09 Cameron Desautels <camdez@gmail.com>
@@ -6570,7 +6570,7 @@
2021-10-04 Lars Ingebrigtsen <larsi@gnus.org>
- Mention ffap-file-name-with-spaces in the ffap doc strin
+ Mention ffap-file-name-with-spaces in the ffap doc string
* lisp/ffap.el (find-file-at-point): Mention
ffap-file-name-with-spaces in the doc string.
@@ -7174,7 +7174,7 @@
(ess-eval-visibly-p): Declare.
(org-babel-julia-assign-elisp): Remove unused vars `header` and
- `row-names` and corespondingly remove now unused args `colnames-p` and
+ `row-names` and correspondingly remove now unused args `colnames-p` and
`rownames-p`.
(org-babel-variable-assignments:julia): Adjust call to
`org-babel-julia-assign-elisp` accordingly.
@@ -10203,7 +10203,7 @@
2021-09-17 Lars Ingebrigtsen <larsi@gnus.org>
- Mention that the garbage collection is convervative
+ Mention that the garbage collection is conservative
* doc/lispref/internals.texi (Garbage Collection): Mention that
we're using a conservative gc (bug#42013).
@@ -21832,7 +21832,7 @@
* src/doprnt.c (exprintf, evxprintf):
* src/lisp.h (exprintf, evxprintf): Don't use a pointer-to-const type
for the `nonheapbuf` argument: although it is never dereferenced, GCC
- will warn when passing a pointer to uninitialised memory otherwise.
+ will warn when passing a pointer to uninitialized memory otherwise.
* src/fns.c (sort_vector_copy, realize_face, realize_gui_face)
(realize_tty_face): Use the same signatures in the prototypes as in
the actual function definitions.
@@ -23755,7 +23755,7 @@
2021-05-29 Lars Ingebrigtsen <larsi@gnus.org>
- Improve the file-accessible-directory-p doc strin
+ Improve the file-accessible-directory-p doc string
* src/fileio.c (Ffile_accessible_directory_p): Don't use the
phrase "directory name spec", which isn't defined (bug#18201).
@@ -44752,7 +44752,7 @@
(nxml-prefer-utf-16-little-to-big-endian-flag)
(nxml-default-buffer-file-coding-system)
(nxml-auto-insert-xml-declaration-flag): Add :safe to allow easier
- cusomization (bug#45969).
+ customization (bug#45969).
2021-01-19 Lars Ingebrigtsen <larsi@gnus.org>
@@ -44923,7 +44923,7 @@
* etc/NEWS: Announce the new 'cham' input method.
* etc/HELLO: Fix the order of letters in the Cham greeting.
- Remove redundant newlines (reported by Ulrich Mueller
+ Remove redundant newlines (reported by Ulrich Müller
<ulm@gentoo.org>).
* lisp/language/cham.el ("Cham"): Add input-method entry.
@@ -47582,10 +47582,10 @@
2020-12-30 Andrea Corallo <akrl@sdf.org>
- Order function types in aphabetical order
+ Order function types in alphabetical order
* lisp/emacs-lisp/comp.el (comp-known-type-specifiers): Reorder in
- aphabetical order and comment.
+ alphabetical order and comment.
2020-12-30 Andrea Corallo <akrl@sdf.org>
@@ -55395,7 +55395,7 @@
2020-11-18 Andrea Corallo <akrl@sdf.org>
- Fix eln file hasing for symlink paths (bug#44701)
+ Fix eln file hashing for symlink paths (bug#44701)
* src/comp.c (Fcomp_el_to_eln_filename): Call `file-truename'
in place of `expand-file-name' when available.
@@ -55928,7 +55928,7 @@
Fix debug symbol emission
* src/comp.c (Fcomp__compile_ctxt_to_file): Now that we do not
- rely anymore on globlal variables move logic in from
+ rely anymore on global variables move logic in from
'Fcomp__init_ctxt' so comp.debug is already set correctly.
2020-11-14 Andrea Corallo <akrl@sdf.org>
@@ -59251,7 +59251,7 @@
2020-10-26 Andrea Corallo <akrl@sdf.org>
- Make native compiler tollerant to redefined primitives (bug#44221).
+ Make native compiler tolerant to redefined primitives (bug#44221).
* lisp/emacs-lisp/comp.el (comp-emit-set-call-subr): Rework based
on the fact that the subr can now be redefined.
@@ -59833,7 +59833,7 @@
Fix error in tramp-sh-handle-make-process
* lisp/net/tramp-sh.el (tramp-sh-handle-make-process): Don't use heredoc
- script whent the argument contains a string.
+ script when the argument contains a string.
2020-10-23 Stefan Kangas <stefan@marxist.se>
@@ -64846,7 +64846,7 @@
2020-09-24 Andrea Corallo <akrl@sdf.org>
- Add a test for primitive advicing effectiveness
+ Add a test for primitive advising effectiveness
* test/src/comp-test-funcs.el (comp-test-primitive-advice-f): New
function.
@@ -64903,7 +64903,7 @@
install a subr trampoline into the function relocation table.
Once this is done any call from native compiled Lisp to the
related primitive will go through the `funcall' trampoline
- making advicing effective.
+ making advising effective.
2020-09-23 Andrea Corallo <akrl@sdf.org>
@@ -70385,7 +70385,7 @@
(MD5_BLOCKSIZE): New macro.
(accumulate_and_process_md5, final_process_md5, md5_gz_stream)
(comp_hash_source_file): New functions.
- (Fcomp_el_to_eln_filename): Rework for hasing using also source
+ (Fcomp_el_to_eln_filename): Rework for hashing using also source
file content.
* src/lread.c (maybe_swap_for_eln): Rename el_name -> src_name as
@@ -73450,7 +73450,7 @@
2020-08-11 Paul Eggert <eggert@cs.ucla.edu>
- pdumper speed tweeks for hash tables
+ pdumper speed tweaks for hash tables
* src/pdumper.c (dump_queue_empty_p): Avoid unnecessary call
to Fhash_table_count on a known hash table.
@@ -77752,7 +77752,7 @@
2020-06-22 Andrea Corallo <akrl@sdf.org>
- Handle correctly pure delaration specifier.
+ Handle correctly pure declaration specifier.
* lisp/emacs-lisp/comp.el (comp-func): New slot 'pure'.
(comp-spill-decl-spec): New function.
@@ -81415,7 +81415,7 @@
2020-05-14 Andrea Corallo <akrl@sdf.org>
- Dump log and intemediate GCC IRs only at comp-debug 3
+ Dump log and intermediate GCC IRs only at comp-debug 3
* src/comp.c (Fcomp__init_ctxt): Increase threshold for dumping
really everything to 'comp-debug' 3.
@@ -84459,7 +84459,7 @@
either be encoding a string without NL, or decoding without CR.
* src/coding.c (string_ascii_p): Revert to a pure predicate.
- (code_convert_string): Fix logic. Don't use uninitialised
+ (code_convert_string): Fix logic. Don't use uninitialized
ascii_p (removed). Use memchr to detect CR or LF in string when needed.
* test/src/coding-tests.el (coding-nocopy-ascii):
Update tests to include encodings with explicit EOL conversions.
@@ -86579,7 +86579,7 @@
Merge remote-tracking branch 'savannah/master' into HEAD
- * Fix regexp instroduced by f055f52321
+ * Fix regexp introduced by f055f52321
2020-03-09 Paul Eggert <eggert@cs.ucla.edu>
@@ -86613,7 +86613,7 @@
* lisp/term/rxvt.el: Enable backeted paste and window title
- rxvt-unicode uses the same escape sequences as xterm so just re-use
+ rxvt-unicode uses the same escape sequences as xterm so just reuse
the xterm functions to enable them. The `xterm-rxvt-function-map`
keymap already has
@@ -94009,7 +94009,7 @@
Fix an error in tramp-sh-handle-make-process. Don't merge with master
* lisp/net/tramp-sh.el (tramp-sh-handle-make-process): Don't use heredoc
- script whent the argument contains a string.
+ script when the argument contains a string.
2021-02-03 Stefan Kangas <stefan@marxist.se>
@@ -97511,7 +97511,7 @@
* lisp/subr.el (cancel-change-group): Fix bug#39680
- Don't re-use an existing `pending-undo-list` even if (eq last-command 'undo)
+ Don't reuse an existing `pending-undo-list` even if (eq last-command 'undo)
since there might have been changes to the buffer since that `undo` command
and the `pending-undo-list` can hence be invalid for the current
buffer contents.
@@ -110510,7 +110510,7 @@
2019-10-01 Lars Ingebrigtsen <larsi@gnus.org>
- Make the help page mention the customizeable global mode variable
+ Make the help page mention the customizable global mode variable
* lisp/help-fns.el (help-fns--customize-variable): Factor out into
own function for reuse.
@@ -117135,7 +117135,7 @@
Use timer-convert with t rather than doing it by hand.
* src/timefns.c (time_hz_ticks, time_form_stamp, lisp_time_form_stamp):
Remove; no longer needed.
- (decode_lisp_time): Rturn the form instead of having a *PFORM arg.
+ (decode_lisp_time): Return the form instead of having a *PFORM arg.
All uses changed.
(time_arith): Just return TICKS if HZ is 1.
(Fencode_time): Remove argument FORM. All callers changed.
@@ -131090,7 +131090,7 @@
Make shr-rescale-image respect get-buffer-window again
* lisp/net/shr.el (shr-rescale-image): Partially revert previous
- change -- ressurrect the check for `get-buffer-window'.
+ change -- resurrect the check for `get-buffer-window'.
2019-05-16 Ivan Shmakov <ivan@siamics.net>
@@ -135103,7 +135103,7 @@
(help-fns--var-ignored-local, help-fns--var-file-local)
(help-fns--var-watchpoints, help-fns--var-obsolete)
(help-fns--var-alias, help-fns--var-bufferlocal): New functions,
- extacted from describe-variable.
+ extracted from describe-variable.
(describe-variable): Run help-fns-describe-variable-functions instead.
2019-04-12 Glenn Morris <rgm@gnu.org>
@@ -155306,7 +155306,7 @@
Set group when installing, too
- From a patch by Ulrich Mueller in:
+ From a patch by Ulrich Müller in:
https://lists.gnu.org/r/emacs-devel/2018-06/msg00687.html
* Makefile.in (set_installuser): Also set the group, in order
to match install(1) behavior. Also, don’t clutter stderr
@@ -161872,7 +161872,7 @@
Port to 32-bit sparc64
- Problem reported by Ulrich Mueller; fix suggested by Eli Zaretskii
+ Problem reported by Ulrich Müller; fix suggested by Eli Zaretskii
and Andreas Schwab (Bug#30855).
* src/alloc.c (mark_memory): Call mark_maybe_object only on
pointers that are properly aligned for Lisp_Object.
@@ -163190,7 +163190,7 @@
Quieten eshell compilation
* lisp/eshell/em-tramp.el: Require esh-cmd.
- * lisp/eshell/esh-ext.el: Requie esh-io at runtime too.
+ * lisp/eshell/esh-ext.el: Require esh-io at runtime too.
2018-02-28 Glenn Morris <rgm@gnu.org>
@@ -164098,7 +164098,7 @@
(server-socket-dir): Compute socket dir from
`get-external-sockname'.
(server-start): Don't check for existing server when an
- uninitialised external socket has been passed to Emacs.
+ uninitialized external socket has been passed to Emacs.
* src/emacs.c: (main): Obtain socket name via getsockname and pass
to `init_process_emacs'.
* src/lisp.h: (init_process_emacs): Add second parameter.
@@ -165010,7 +165010,7 @@
Merge from origin/emacs-26
- 6415b2d Allow read-passwd to hide characters inserted by C-y. (Secur...
+ 6415b2d Allow read-passwd to hide characters inserted by C-y. (Secure...
8cb4ffb * etc/PROBLEMS: Document issues with double-buffering. (Bug#...
fd10070 * lisp/window.el (window-largest-empty-rectangle): Fix grammar.
e1a4403 Minor changes in the Emacs manual
@@ -165500,7 +165500,7 @@
1fc98ed073 ; Spelling fix
bb396a369c Update Org to v9.1.6
fa582153f7 Use text-pixels values only when saving framesets (Bug#30141)
- 6b01b9475d Minor improvement in section "Pages" of the usere manual
+ 6b01b9475d Minor improvement in section "Pages" of the user manual
e8c8bd3de2 Minor improvements in user manual
26b8b92e63 Improve the "Mark" chapter of the user manual
759569fe40 Improve the "Buffers" chapter of the user manual
@@ -167643,7 +167643,7 @@
2017-12-12 Glenn Morris <rgm@gnu.org>
- Fix gitmerge handling of automatic conflict reslution
+ Fix gitmerge handling of automatic conflict resolution
* admin/gitmerge.el (gitmerge-resolve): Reenable NEWS handling.
(gitmerge-resolve-unmerged): Commit after successful resolution.
@@ -172441,11 +172441,11 @@
* src/window.c (Fset_window_margins, Fset_window_fringes)
(Fset_window_scroll_bars): In doc-strings tell that a window
- must be large enough to accommodate fringes, sroll bars and
+ must be large enough to accommodate fringes, scroll bars and
margins of the desired size.
* doc/lispref/display.texi (Fringe Size/Pos, Scroll Bars)
(Display Margins): Tell that windows must be large enough to
- accommodate fringes, sroll bars and margins of the desired
+ accommodate fringes, scroll bars and margins of the desired
size.
2019-03-10 Eli Zaretskii <eliz@gnu.org>
@@ -175963,7 +175963,7 @@
Save the server alias on reconnect (Bug#29657)
rcirc does not retain the server alias on reconnect. As a result, rcirc
- fails to re-use server and channel buffers when an alias is used. Further
+ fails to reuse server and channel buffers when an alias is used. Further
problems may ensue when aliases are used to differentiate multiple
connections to the same host, for example when using a single IRC bouncer
or proxy to connect to multiple IRC networks.
@@ -178544,7 +178544,7 @@
Port to 32-bit sparc64
Backport from master.
- Problem reported by Ulrich Mueller; fix suggested by Eli Zaretskii
+ Problem reported by Ulrich Müller; fix suggested by Eli Zaretskii
and Andreas Schwab (Bug#30855).
* src/alloc.c (mark_memory): Call mark_maybe_object only on
pointers that are properly aligned for Lisp_Object.
@@ -180914,7 +180914,7 @@
2018-01-21 Eli Zaretskii <eliz@gnu.org>
- Minor improvement in section "Pages" of the usere manual
+ Minor improvement in section "Pages" of the user manual
* doc/emacs/text.texi (Pages): Improve wording. Suggested by Will
Korteland <emacs-devel@korte.land> in emacs-manual-bugs@gnu.org.
@@ -184512,7 +184512,7 @@
* src/lisp.h (GCALIGNMENT): Change it back to a macro
that expands to a literal integer constant, for older GCC.
I had mistakenly thought that only MSVC had the problem.
- Problem repored by Eli Zaretskii (Bug#29040#69).
+ Problem reported by Eli Zaretskii (Bug#29040#69).
2017-11-03 Paul Eggert <eggert@cs.ucla.edu>
@@ -186856,7 +186856,7 @@
* doc/misc/flymake.texi (Overview of Flymake): Rewrite a bit.
(Installing Flymake): Mostly scratch. Flymake comes with Emacs.
(Running the syntax check): Simplify.
- (Viewing error messages): Dekete,
+ (Viewing error messages): Delete.
(Syntax check statuses): Rewrite.
(Troubleshooting): Simplify.
(Customizable variables): Rewrite.
@@ -188461,7 +188461,7 @@
Loosen strict parsing requirement for desktop files
There are other desktop-looking files, for instance those having to do
- with MIME typess, that would benefit from being able to be read by this
+ with MIME types, that would benefit from being able to be read by this
function. It helps to have some flexibility.
* lisp/xdg.el (xdg-desktop-read-file): Remove an error condition.
* test/lisp/xdg-tests.el: Remove a test.
@@ -219622,7 +219622,7 @@
for 0x80 ⪬ c < 0x100. In other words, the loop never executes for
c ≥ 0x80 and RE_CHAR_TO_MULTIBYTE call is unnecessary for c < 0x80.
- * src/regex.c (regex_compile): Simplyfy a for loop by eliminating
+ * src/regex.c (regex_compile): Simplify a for loop by eliminating
dead iterations and unnecessary macro calls.
2016-09-08 Michal Nazarewicz <mina86@mina86.com>
@@ -229115,7 +229115,7 @@
6da3a6d Port to strict C99 offsetof
de7601f Port to GTK with strict C11 compiler
658aa2d Port to GTK with strict C99 compiler
- 1df7173 Avoid screen artifacts with new OS X visible bell after scrol...
+ 1df7173 Avoid screen artifacts with new OS X visible bell after scroll...
7a2edd3 Merge branch 'emacs-25' of git.sv.gnu.org:/srv/git/emacs into...
dca240a Suppress some Tramp tests for OSX, do not merge with master
9094304 * lisp/progmodes/xref.el (xref-buffer-name, xref--window): Mo...
@@ -233746,7 +233746,7 @@
ee73997 Make erc work better when encountering unknown prefix chars
b99141d Make erc completion case-insensitive again
- 66c4620 Make complection in erc use consistent casing
+ 66c4620 Make completion in erc use consistent casing
8c562b2 Make /QUIT in erc more robust
d93d2c5 Make tracking faces in Emacs work more reliably
af6ab7e Make shr not bug out on images on non-graphical displays
@@ -234791,7 +234791,7 @@
(Maybe this is the last merge from Gnus git to Emacs git)
Cf. discussion on ding mailing list, messages in
- <http://thread.gmane.org/gmane.emacs.gnus.general/86228>.
+ <http://thread.gmane.org/gmane.emacs.gnus.general/86228>. [dead link]
Common code from the three files mml-smime.el, mml1991.el, and
mml2015.el is moved to mml-sec.el. Auxiliary functions are added
to gnus-util.el.
@@ -234944,7 +234944,7 @@
(rng-complete-attribute-value): Don't perform completion, but return
completion data instead.
(rng-complete-qname-function, rng-generate-qname-list): Add a few
- arguments, previously passed via dynamic coping.
+ arguments, previously passed via dynamic copying.
(rng-strings-to-completion-table): Rename from
rng-strings-to-completion-alist. Don't return an alist. Don't both
sorting and uniquifying.
@@ -235280,7 +235280,7 @@
d400753 * src/buffer.c: Stick with ASCII in doc string.
221240c Reword transient-mark-mode doc string
977d3ea Update doc string of 'selective-display'
- 229c3fa Make C++ buffers writeable when writing their initial text
+ 229c3fa Make C++ buffers writable when writing their initial text
properties.
f5c762c Additional changes for "make check-expensive"
1729cf3 ; * admin/MAINTAINERS: Remove myself.
@@ -237355,7 +237355,7 @@ See ChangeLog.2 for earlier changes.
;; coding: utf-8
;; End:
- Copyright (C) 2015-2023 Free Software Foundation, Inc.
+ Copyright (C) 2015-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/ChangeLog.4 b/ChangeLog.4
index 372b03b32b2..3d794e86b99 100644
--- a/ChangeLog.4
+++ b/ChangeLog.4
@@ -1,3 +1,1984 @@
+2023-10-16 Po Lu <luangruo@yahoo.com>
+
+ Correctly register focus events concomitant with alpha changes
+
+ * src/xterm.c (x_frame_highlight, x_frame_unhighlight): Skip
+ changing the frame alpha when the frame is not eligible for
+ focus state-specific alpha values; otherwise, the alpha might be
+ reset by the time a alpha change wrought by a focus change
+ arrives, impeding handle_one_xevent from subsequently restoring
+ the initial value. (bug#66398)
+
+2023-10-16 Michael Albinus <michael.albinus@gmx.de>
+
+ * doc/man/emacsclient.1: Add missing options.
+
+2023-10-15 Michael Albinus <michael.albinus@gmx.de>
+
+ Fix test in files-tests
+
+ * test/lisp/files-tests.el
+ (files-tests-file-name-non-special-expand-file-name-tilde): Fix test.
+
+2023-10-14 Stefan Kangas <stefankangas@gmail.com>
+
+ Add missing :version to two defcustoms
+
+ * lisp/emacs-lisp/eldoc.el (eldoc-print-after-edit)
+ (eldoc-echo-area-prefer-doc-buffer): Add missing custom :version.
+
+2023-10-14 Mauro Aranda <maurooaranda@gmail.com>
+
+ Fix a defcustom :type in eldoc.el
+
+ * lisp/emacs-lisp/eldoc.el (eldoc-echo-area-prefer-doc-buffer): Make
+ :type a choice, to allow for the value 'maybe'. (Bug##66539)
+
+2023-10-14 Eshel Yaron <me@eshelyaron.com>
+
+ Document 'M-x align' in the Emacs manual
+
+ * doc/emacs/indent.texi (Alignment): New section.
+ * doc/emacs/emacs.texi: Update menu. (Bug#66303)
+
+2023-10-14 Bob Rogers <rogers@rgrjr.com>
+
+ Document that time-to-days and days-to-time use different epochs
+
+ * doc/lispref/os.texi (Time Calculations):
+ * lisp/calendar/time-date.el (days-to-time, time-to-days): Doc fixes.
+ (Bug#66502)
+
+2023-10-14 Michael Albinus <michael.albinus@gmx.de>
+
+ * lisp/files.el (file-name-non-special): Handle quoted tilde.
+
+ (Bug#65685)
+
+ * test/lisp/files-tests.el
+ (files-tests-file-name-non-special-expand-file-name-tilde):
+ New test.
+
+2023-10-13 Michael Albinus <michael.albinus@gmx.de>
+
+ Handle quoted tilde in Tramp
+
+ * lisp/net/tramp.el (tramp-handle-expand-file-name):
+ * lisp/net/tramp-gvfs.el (tramp-gvfs-handle-expand-file-name):
+ * lisp/net/tramp-sh.el (tramp-sh-handle-expand-file-name):
+ * lisp/net/tramp-smb.el (tramp-smb-handle-expand-file-name):
+ * lisp/net/tramp-sudoedit.el (tramp-sudoedit-handle-expand-file-name):
+ Handle quoted tilde. (Bug#65685)
+
+ * test/lisp/net/tramp-tests.el (tramp-test05-expand-file-name-tilde):
+ New test.
+
+2023-10-09 Kyle Meyer <kyle@kyleam.com>
+
+ Update to Org 9.6.10
+
+2023-10-09 Yuan Fu <casouri@gmail.com>
+
+ Don't call font-lock-mode in treesit-major-mode-setup (bug#66223)
+
+ * lisp/treesit.el (treesit-major-mode-setup): Remove.
+
+ (cherry picked from commit a3a840c80a217db7d4d125c667ff7d4946507fbb)
+
+2023-10-09 Noah Peart <noah.v.peart@gmail.com>
+
+ Fix treesit-query-validate for string input (bug#66400)
+
+ * lisp/treesit.el (treesit-query-validate): Don't expand if QUERY is
+ string.
+
+2023-10-07 Stefan Kangas <stefankangas@gmail.com>
+
+ Recommend `M-x man` in woman.el docs
+
+ * lisp/woman.el (Commentary, woman): Recommend using 'M-x man' where
+ available. The added sentence is copied from the emacs manual.
+ Ref: https://lists.gnu.org/r/emacs-devel/2023-10/msg00090.html
+
+2023-10-07 Eli Zaretskii <eliz@gnu.org>
+
+ Fix updating process-mark position in 'set-process-buffer'
+
+ * src/process.c (update_process_mark): Update marker position only
+ if P's process-mark is not already associated with P's buffer.
+ (Bug#66313)
+
+2023-10-07 Mauro Aranda <maurooaranda@gmail.com>
+
+ Fix a defcustom :type
+
+ * lisp/cedet/srecode/map.el (srecode-map-save-file): Expand :type to
+ allow nil. (Bug#66377)
+
+2023-10-07 Eli Zaretskii <eliz@gnu.org>
+
+ Fix 'ido--ffap-find-file'
+
+ * lisp/ido.el (ido--ffap-find-file): Make the signature consistent
+ with that of 'find-file', and pass the optional second argument to
+ 'find-file'. (Bug#66382)
+
+2023-10-06 Eli Zaretskii <eliz@gnu.org>
+
+ Fix setting the pipe capacity for subprocesses
+
+ * src/process.c (create_process) [F_SETPIPE_SZ]: Set the pipe
+ capacity only if the required read-process-max is larger than the
+ default capacity of the pipe. (Bug#66288)
+
+2023-10-05 Gerd Möllmann <gerd@gnu.org>
+
+ Handle LANG on macOS differently (bug#65908)
+
+ * src/nsterm.m (ns_init_locale): If LANG is set, try to use that,
+ otherwise try to deduce what LANG should be. Check is the result is
+ valid, and use LANG="en_US.UTF-8" if not.
+
+2023-10-05 Jens Schmidt <jschmidt4gnu@vodafonemail.de>
+
+ Silence macro expansion during completion at point
+
+ To keep risk in the current release branch low, do not avoid compiler
+ macros as suggested by Stefan in the bug, but rather suppress all errors.
+
+ * lisp/progmodes/elisp-mode.el (elisp--local-variables): Silence
+ messages. Suppress all errors during macro expansion. (Bug#58148)
+
+ Do not merge to master.
+
+2023-10-05 Mauro Aranda <maurooaranda@gmail.com>
+
+ Fix a defcustom :type
+
+ * lisp/cedet/ede/base.el (ede-project-placeholder-cache-file): Expand
+ :type to allow nil. (Bug#66361)
+
+2023-10-04 Mauro Aranda <maurooaranda@gmail.com>
+
+ Fix pulse-flag :type
+
+ * lisp/cedet/pulse.el (pulse-flag): Expand :type to allow 'never as
+ value. (Bug#66341)
+
+2023-10-03 Mauro Aranda <maurooaranda@gmail.com>
+
+ Fix defcustoms in timeclock.el
+
+ * lisp/calendar/timeclock.el (timeclock-get-project-function)
+ (timeclock-get-reason-function): Fix :type to allow nil. (Bug#66320)
+
+2023-10-01 Stefan Kangas <stefankangas@gmail.com>
+
+ Improve documentation of `ns-use-proxy-icon`
+
+ * doc/emacs/macos.texi (Mac / GNUstep Customization):
+ * src/nsfns.m (syms_of_nsfns): Fix documentation of
+ 'ns-use-proxy-icon'; explain what it does and how it's
+ used. (Bug#66190)
+
+2023-10-01 Stefan Kangas <stefankangas@gmail.com>
+
+ Document assigning libraries to packages in make-tarball.txt
+
+ * admin/make-tarball.txt: Add new step to ensure that new libraries
+ are assigned to packages.
+
+2023-10-01 Stefan Kangas <stefankangas@gmail.com>
+
+ Doc fix; more consistently refer to "text terminals"
+
+ In the Emacs Lisp manual, we refer to "text terminals" and "graphical
+ terminals" (see Info node `(elisp) Frames'). But in some places,
+ including the user manual, the alternative terminology "non-window
+ terminals" is used instead.
+
+ In other places, we use the terminology "non-windowing display"
+ instead of the more canonical "non-graphical display".
+
+ This is less clear than it could be. Let's consolidate our
+ terminology to prefer the wording from the Emacs Lisp manual; in other
+ words, prefer "text" and "non-graphical" to "non-window".
+
+ * doc/emacs/frames.texi (Non-Window Terminals): Rename node from this...
+ (Text Terminals): ...to this. (Bug#66282)
+ * doc/emacs/display.texi (Standard Faces):
+ * doc/emacs/emacs.texi (Top):
+ * doc/emacs/misc.texi (emacsclient Options):
+ * doc/misc/viper.texi (Rudimentary Changes)
+ (Packages that Change Keymaps):
+ * doc/emacs/frames.texi (Frames, Frame Commands, Mouse Avoidance):
+ Replace instances of "non-window terminals" with "text terminals".
+ * doc/misc/ediff.texi (Quick Help Customization):
+ (Window and Frame Configuration):
+ * lisp/vc/ediff.el (ediff-windows-wordwise)
+ (ediff-windows-linewise): Prefer saying 'non-graphical display' to
+ 'non-windowing display'.
+ * lisp/net/tramp.el (tramp-default-method):
+ * lisp/printing.el (pr-find-command): Capitalize 'Windows' where it
+ clearly refers to the non-free operating system with that name.
+
+2023-09-30 Mauro Aranda <maurooaranda@gmail.com>
+
+ Fix defcustoms in type-break.el (Bug#66210)
+
+ * lisp/type-break.el (type-break-good-rest-interval)
+ (type-break-file-name): Allow nil.
+
+2023-09-30 Mauro Aranda <maurooaranda@gmail.com>
+
+ Fix term-scroll-to-bottom-on-output :type
+
+ * lisp/term.el (term-scroll-to-bottom-on-output): Add missing choices.
+ Don't advertise the value 'all' in docstring. (Bug#66071)
+
+2023-09-28 Stefan Kangas <stefankangas@gmail.com>
+
+ Doc fix in let-alist for keys with nil value
+
+ * lisp/emacs-lisp/let-alist.el (let-alist): Clarify that keys with a
+ nil value will give the same result as if they were missing.
+
+2023-09-28 Michael Albinus <michael.albinus@gmx.de>
+
+ Fix tramp-test.el (don't merge with master)
+
+ * test/lisp/net/tramp-tests.el (tramp--test-check-files):
+ Don't err out when "printenv" doesn't exist on remote side.
+
+2023-09-25 Michael Albinus <michael.albinus@gmx.de>
+
+ Improve Emacs 30 compatibility in tramp-tests.el (don't merge)
+
+ * test/lisp/net/tramp-tests.el (tramp--test-deftest-direct-async-process)
+ (tramp-test30-make-process): Improve Emacs 30 compatibility.
+
+2023-09-25 Michael Albinus <michael.albinus@gmx.de>
+
+ Add new Tramp test
+
+ * test/lisp/net/tramp-tests.el (tramp-test46-read-password):
+ Use `copy-tree' but `copy-sequence'.
+ (tramp-test46-read-otp-password): New test.
+
+2023-09-25 Mauro Aranda <maurooaranda@gmail.com>
+
+ Fix tmm-mid-prompt :type (Bug#66179)
+
+ * lisp/tmm.el (tmm-mid-prompt): Allow nil.
+
+2023-09-24 Augustin Chéneau <btuin@mailo.com> (tiny change)
+
+ Fix tree-sitter indentation conflict with multiple languages
+
+ * lisp/treesit.el (treesit--indent-1): Use bol instead of point.
+
+2023-09-24 Michael Albinus <michael.albinus@gmx.de>
+
+ Fix bug#66093 in Tramp
+
+ * lisp/net/tramp-sshfs.el (tramp-methods): Use "%a".
+ (tramp-sshfs-handle-process-file): Replace ?a by "-t".
+
+ * lisp/net/tramp.el (tramp-methods): Adapt docstring. (Bug#66093)
+ (tramp-handle-make-process): Replace ?a by "-t" if indicated.
+
+2023-09-24 Eli Zaretskii <eliz@gnu.org>
+
+ Support regeneration of ja-dic.el under '--with-small-ja-dic'
+
+ * lisp/international/ja-dic-cnv.el (skkdic-convert): Record the
+ value of SMALL_JA_DIC option used to produce ja-dic.el.
+ * leim/Makefile.in (small-ja-dic-option): New target, triggers
+ regeneration of ja-dic.el when the value of SMALL_JA_DIC option
+ changes by the configure script. Suggested by Ulrich Müller
+ <ulm@gentoo.org>.
+ (${leimdir}/ja-dic/ja-dic.el): Depend on 'small-ja-dic-option'.
+ (Bug#66125)
+
+ * make-dist (possibly_non_vc_files):
+ * .gitignore: Add 'leim/small-ja-dic-option'.
+
+2023-09-22 Basil L. Contovounesios <contovob@tcd.ie>
+
+ Improve remote-file-name-inhibit-cache :type
+
+ * lisp/files.el (remote-file-name-inhibit-cache)
+ (shell-highlight-undef-remote-file-name-inhibit-cache): Avoid
+ duplicated :tag string. Try to clarify wording and
+ formatting (bug#66150).
+ * lisp/shell.el (shell--highlight-undef-exec-cache): Reference
+ correct user option in docstring.
+
+2023-09-22 Stefan Kangas <stefankangas@gmail.com>
+
+ Ensure bind-key is its own package
+
+ * lisp/finder.el (finder--builtins-alist): Remove "use-package"
+ directory.
+ * lisp/use-package/bind-key.el: Declare library as part of the
+ 'bind-key' package.
+ * lisp/use-package/use-package-bind-key.el:
+ * lisp/use-package/use-package-core.el:
+ * lisp/use-package/use-package-delight.el:
+ * lisp/use-package/use-package-diminish.el:
+ * lisp/use-package/use-package-ensure-system-package.el:
+ * lisp/use-package/use-package-ensure.el:
+ * lisp/use-package/use-package-jump.el:
+ * lisp/use-package/use-package-lint.el: Declare library as part of the
+ 'use-package' package. (Bug#62751)
+
+ Do not merge to master.
+
+2023-09-21 Michael Albinus <michael.albinus@gmx.de>
+
+ * lisp/net/tramp.el (tramp-skeleton-write-region): Fix missing comma.
+
+ (Bug#66123)
+
+2023-09-18 Yuan Fu <casouri@gmail.com>
+
+ Fix tree-sitter range update function
+
+ * lisp/treesit.el (treesit-update-ranges): If an embedded language
+ doesn't have any range, don't set its range to nil (which means whole
+ buffer), instead, set its range to a dummy (1 . 1) zero range.
+
+2023-09-18 Ihor Radchenko <yantar92@posteo.net>
+
+ Announce handling 'org-protocol' URI scheme in NEWS
+
+ * etc/NEWS: Document handling 'org-protocol' URI scheme. The commit
+ implementing the new functionality is 05a7c91b91c. (Bug#65469)
+
+2023-09-18 Ihor Radchenko <yantar92@posteo.net>
+
+ Make emacsclient handle org-protocol:// links
+
+ Org mode provides a way to quickly capture bookmarks, notes, and links
+ using emacsclient:
+
+ emacsclient "org-protocol://store-link?url=URL&title=TITLE"
+
+ * etc/emacsclient.desktop: Make Emacs the default application for
+ org-protocol. (Bug#65469)
+
+ (cherry picked from commit 05a7c91b91c02c34ec6527119a465e5408dea2b1)
+
+2023-09-18 Robert Pluim <rpluim@gmail.com>
+
+ Ensure ucs-names is consistent with Unicode names
+
+ * lisp/international/mule-cmds.el (ucs-names): Skip adding an old-name
+ if it conflicts with the official name of a codepoint. Adjust the
+ ranges iterated over to account for new Unicode codepoints.
+ * test/lisp/international/mule-tests.el
+ (mule-cmds-tests--ucs-names-old-name-override,
+ mule-cmds-tests--ucs-names-missing-names): New tests for checking
+ 'ucs-names' consistency.
+
+ Bug#65997
+
+2023-09-18 Shynur <one.last.kiss@outlook.com>
+
+ Make key-translate actually work
+
+ * lisp/keymap.el (key-translate): Use the first element of the parsed
+ keys rather than the whole vector. (Bug#65735)
+
+2023-09-17 Kyle Meyer <kyle@kyleam.com>
+
+ Update to Org 9.6.9
+
+2023-09-17 Stefan Kangas <stefankangas@gmail.com>
+
+ Add leim subdirectories to emacs package
+
+ * lisp/finder.el (finder--builtins-alist): Add subdirectories
+ 'leim/ja-dic' and 'leim/quail' as part of the 'emacs'
+ package. (Bug#62751)
+
+2023-09-17 Stefan Kangas <stefankangas@gmail.com>
+
+ Add missing builtin package declarations
+
+ * lisp/finder.el (finder--builtins-alist): Add new package
+ directories 'leim' and 'obsolete' as part of the 'emacs' package.
+ Add new package directory 'use-package' as part of the
+ 'use-package' package.
+ * lisp/net/eudc-capf.el:
+ * lisp/net/eudcb-ecomplete.el:
+ * lisp/net/eudcb-macos-contacts.el:
+ * lisp/net/eudcb-mailabbrev.el: Declare library as part of the
+ 'eudc' package.
+ * lisp/mail/ietf-drums-date.el: Declare library as part of the
+ 'ietf-drums' package.
+ * lisp/image/image-dired-dired.el:
+ * lisp/image/image-dired-external.el:
+ * lisp/image/image-dired-tags.el:
+ * lisp/image/image-dired-util.el: Declare library as part of the
+ 'image-dired' package.
+ * lisp/emacs-lisp/oclosure.el:
+ * lisp/keymap.el:
+ * lisp/progmodes/c-ts-common.el: Declare library as part of the
+ 'emacs' package. (Bug#62751)
+
+ (cherry picked from commit 94b1de2774b5c1fa3c28285229900657638f5c3f)
+
+2023-09-17 Stefan Kangas <stefankangas@gmail.com>
+
+ Add more missing builtin package declarations
+
+ * lisp/emacs-lisp/shorthands.el: Declare library as part of the
+ 'emacs' package.
+ * lisp/epa-ks.el: Declare library as part of the 'epa'
+ package. (Bug#55388)
+
+2023-09-17 Stefan Kangas <stefankangas@gmail.com>
+
+ Document shell-command-to-string security considerations
+
+ * lisp/simple.el (shell-command-to-string): Document security
+ considerations in docstring.
+
+2023-09-17 Mauro Aranda <maurooaranda@gmail.com>
+
+ Fix shell-indirect-setup-hook :type (Bug#66051)
+
+ * lisp/shell.el (shell-indirect-setup-hook): It's a hook, not a
+ boolean.
+
+2023-09-17 Thomas Hilke <t.hilke@rollomatic.ch> (tiny change)
+
+ Remove column quoting from sqlite-mode
+
+ * lisp/sqlite-mode.el (sqlite-mode--column-names): Unquote column
+ name. (Bug#65998)
+
+2023-09-17 Theodor Thornhill <theo@thornhill.no>
+
+ Add indentation rules for type_arguments
+
+ * lisp/progmodes/java-ts-mode.el (java-ts-mode--indent-rules): Indent
+ as opening braces.
+
+2023-09-16 Dmitry Gutov <dmitry@gutov.dev>
+
+ typescript-ts-mode.el: Minor touches
+
+ * lisp/progmodes/typescript-ts-mode.el
+ (tsx-ts-mode--indent-compatibility-b893426)
+ (tsx-ts-mode--font-lock-compatibility-bb1f97b):
+ Catch specific error.
+ (typescript-ts-base-mode): Improve docstring (bug#65470).
+
+2023-09-16 Dmitry Gutov <dmitry@gutov.dev>
+
+ Improve namespacing situation WRT to recent change in typescript-ts-mode.el
+
+ * lisp/progmodes/typescript-ts-mode.el
+ (typescript-ts--syntax-propertize):
+ Rename from ts-ts--syntax-propertize.
+ (tsx-ts--syntax-propertize-captures):
+ Rename from ts-ts--syntax-propertize-captures.
+ (typescript-ts--s-p-query):
+ Rename from ts-ts--s-p-query.
+ Update all references (bug#65470).
+
+2023-09-16 Stephen Berman <stephen.berman@gmx.net>
+
+ Make move-end-of-line in minibuffer consistent (bug#65980)
+
+ * lisp/simple.el (move-end-of-line): Always move to eol when
+ invoking `C-e' from within the minibuffer's prompt string.
+
+2023-09-16 Jens Schmidt <jschmidt4gnu@vodafonemail.de>
+
+ Fix loss of encrypted data in plstore.el
+
+ * lisp/plstore.el (plstore--insert-buffer): Fix loss of encrypted
+ data when a plstore gets opened and saved without being decrypted
+ between these steps. (Bug#63627)
+
+2023-09-16 Thomas Hilke <t.hilke@rollomatic.ch> (tiny change)
+
+ Close SQL database when corresponding 'sqlite-mode' buffer is killed
+
+ * lisp/sqlite-mode.el (sqlite-mode-open-file): Close DB when the
+ buffer is killed. (Bug#65998)
+
+2023-09-16 Eli Zaretskii <eliz@gnu.org>
+
+ Fix Unicode normalization of characters
+
+ * lisp/international/ucs-normalize.el
+ (ucs-normalize-composition-exclusions, check-range): Update from
+ Unicode 15.0 data. (Bug#65996)
+
+ * test/lisp/international/ucs-normalize-tests.el
+ (ucs-normalize-tests--failing-lines-part1)
+ (ucs-normalize-tests--failing-lines-part2): Update to reflect
+ changes in ucs-normalize.el.
+
+ * admin/notes/unicode: Mention the updates in ucs-normalize.el.
+
+2023-09-16 Michael Albinus <michael.albinus@gmx.de>
+
+ Support one-time passwords in Tramp
+
+ * doc/misc/tramp.texi (Remote shell setup):
+ Describe tramp-otp-password-prompt-regexp.
+
+ * lisp/net/tramp-sh.el (tramp-actions-before-shell)
+ (tramp-actions-copy-out-of-band):
+ Use `tramp-otp-password-prompt-regexp'.
+
+ * lisp/net/tramp.el (tramp-otp-password-prompt-regexp): New defcustom.
+ (tramp-action-otp-password): New defun.
+
+2023-09-16 Eli Zaretskii <eliz@gnu.org>
+
+ Fix the 'C' and 'c' categories of characters
+
+ * lisp/international/characters.el: Fix categories of Chinese
+ characters. (Bug65995)
+
+2023-09-16 Eli Zaretskii <eliz@gnu.org>
+
+ Fix Emoji zooming commands
+
+ * lisp/international/emoji.el (emoji-zoom-increase): Handle the
+ case where face property at point is a list of faces. (Bug#65994)
+
+2023-09-15 Dmitry Gutov <dmitry@gutov.dev>
+
+ tsx-ts-mode--font-lock-compatibility-bb1f97b: Improve
+
+ * lisp/progmodes/typescript-ts-mode.el
+ (tsx-ts-mode--font-lock-compatibility-bb1f97b):
+ Test the more complex query, because the current one leads to
+ false positives (mentioned in bug#65470).
+
+2023-09-15 Davide Masserut <dm@mssdvd.com>
+
+ Avoid using --display in emacsclient to reuse frames on PGTK
+
+ Using hard-coded display values can cause PGTK graphical frames to
+ open using the wrong backend or not open at all.
+ * Makefile.in (install-etc): Use --reuse-frame instead of
+ --display=$DISPLAY. (Bug#65509)
+
+2023-09-15 Eli Zaretskii <eliz@gnu.org>
+
+ Support emacsclient on Windows with server on GNU or Unix systems
+
+ * lisp/server.el (server-process-filter): If 'tty-name' is literally
+ "CONOUT$", assume the client runs on MS-Windows and force the
+ frame type to GUI. This allows to run emacsclient on MS-Windows
+ when the server runs on a Posix host. (Bug#65812)
+
+2023-09-14 Mauro Aranda <maurooaranda@gmail.com>
+
+ Fix defcustom in saveplace.el (Bug#65977)
+
+ * lisp/saveplace.el (save-place-ignore-files-regexp): Allow nil.
+
+2023-09-14 Eli Zaretskii <eliz@gnu.org>
+
+ Fix 'window-text-pixel-size' when there are several images at START
+
+ * src/xdisp.c (window_text_pixel_size): Remove unnecessary call to
+ 'move_it_to'. (Bug#65899) (Bug#54862)
+
+2023-09-14 Eli Zaretskii <eliz@gnu.org>
+
+ : Doc fix.
+
+ * lisp/progmodes/prog-mode.el
+ (prettify-symbols-unprettify-at-point): Doc fix.
+
+2023-09-14 Stefan Kangas <stefankangas@gmail.com>
+
+ Doc fix for prettify-symbols-unprettify-at-point
+
+ * lisp/progmodes/prog-mode.el
+ (prettify-symbols-unprettify-at-point): Document that it has to be
+ set before enabling 'prettify-symbols-mode'. (Bug#65884)
+
+2023-09-13 Stefan Monnier <monnier@iro.umontreal.ca>
+
+ (report_overlay_modification): Fix bug#65929
+
+ Somehow the new overlay code in Emacs-29 changed slightly
+ the test to decide when to run the `modification-hooks` of overlays,
+ with the consequence that these hook functions end up being executed
+ also when text is deleted right after an empty overlay, which is
+ contrary to Emacs-28 behavior as well as contrary to the Texinfo doc.
+
+ * src/buffer.c (report_overlay_modification): Better reproduce the
+ Emacs-28 code.
+
+ * test/src/buffer-tests.el (overlay-modification-hooks):
+ Add corresponding test.
+
+2023-09-13 Alan Third <alan@idiocy.org>
+
+ Fix SVG colors (bug#56182)
+
+ * src/image.c (svg_load_image): Reverse the R and B bytes in the
+ Windows colors before using them to generate the SVG.
+
+2023-09-13 Juri Linkov <juri@linkov.net>
+
+ * doc/emacs/text.texi (Outline Minor Mode): Add a note about value 'insert'.
+
+ * lisp/outline.el (outline-minor-mode-use-buttons): Add a note and
+ a comment about the value 'insert' (bug#65874).
+
+2023-09-13 Eli Zaretskii <eliz@gnu.org>
+
+ Improve documentation of 'list-abbrevs'
+
+ * doc/emacs/abbrevs.texi (Editing Abbrevs): Describe how system
+ abbrevs are shown by 'list-abbrevs'. Suggested by Shynur Xie
+ <one.last.kiss@outlook.com>. (Bug#65907)
+
+2023-09-12 Dmitry Gutov <dmitry@gutov.dev>
+
+ Tweak s-p-f for js-ts-mode
+
+ * lisp/progmodes/js.el (js-ts--s-p-query):
+ Consider two more contexts (bug#65470).
+
+2023-09-12 Jostein Kjønigsen <jostein@kjonigsen.net>
+
+ typescript-ts-mode, tsx-ts-mode: Fix syntax properties for regexp and jsx
+
+ Propertize regexps as strings and JSX elements as generic strings.
+
+ * lisp/progmodes/typescript-ts-mode.el (ts-ts--s-p-query)
+ (tsx-ts--s-p-query): New variables.
+ (ts-ts--syntax-propertize, tsx-ts--syntax-propertize)
+ (ts-ts--syntax-propertize-captures): New functions.
+ (typescript-ts-mode, tsx-ts-mode): Use them (bug#65470).
+
+2023-09-12 Eli Zaretskii <eliz@gnu.org>
+
+ * lisp/progmodes/c-ts-mode.el (c++-ts-mode): Provide (bug#65895).
+
+2023-09-11 Yuan Fu <casouri@gmail.com>
+
+ Fix regression of treesit_cursor_helper_1
+
+ * src/treesit.c (treesit_cursor_helper_1)
+ (treesit_cursor_first_child_for_byte): Use
+ ts_tree_cursor_goto_first_child_for_byte first, and
+ ts_tree_cursor_goto_first_child second.
+
+2023-09-10 Stefan Kangas <stefankangas@gmail.com>
+
+ Update docs for passing of Thien-Thi Nguyen
+
+ * doc/emacs/ack.texi (Acknowledgments): Add Thien-Thi Nguyen.
+ * lisp/play/zone.el: Set maintainer to emacs-devel.
+
+2023-09-10 Stefan Kangas <stefankangas@gmail.com>
+
+ Update defvar usage tips example in manual
+
+ * doc/lispref/variables.texi (Tips for Defining): Change example
+ to be about syntax tables instead of old way of defining keymaps
+ using 'defvar' and 'make-sparse-keymap'. (Bug#59224)
+
+2023-09-10 Stefan Kangas <stefankangas@gmail.com>
+
+ Document using Flymake together with Eglot
+
+ * doc/misc/flymake.texi (Top, Using Flymake): Document using
+ Flymake together with Eglot. (Bug#60040)
+
+2023-09-08 Mauro Aranda <maurooaranda@gmail.com>
+
+ Fix defcustom :type of ielm-indirect-setup-hook
+
+ * lisp/ielm.el (ielm-indirect-setup-hook): Fix :type and remove :safe
+ property, since it was probably a copy-pasta. (Bug#65821)
+
+2023-09-08 Stefan Kangas <stefankangas@gmail.com>
+
+ Document NonGNU ELPA in FAQ
+
+ * doc/misc/efaq.texi (Packages that do not come with Emacs):
+ Document NonGNU ELPA. (Bug#65818)
+
+2023-09-07 Jim Porter <jporterbugs@gmail.com>
+
+ Fix remote path setting in Eshell
+
+ This ensures that we supply Tramp with the local PATH so that it can
+ do its job of starting the local "ssh", or whatever the method uses
+ (bug#65551).
+
+ * lisp/eshell/esh-proc.el (eshell-gather-process-output): Add special
+ handling for remote processes.
+
+ * test/lisp/eshell/esh-proc-tests.el
+ (esh-var-test/remote/remote-path): New test.
+
+2023-09-07 Stefan Kangas <stefankangas@gmail.com>
+
+ Update docs for (co-)maintainer changes
+
+ * admin/MAINTAINERS: Add information on current maintainers as a
+ canonical place to find this information.
+ * doc/emacs/ack.texi (Acknowledgments): Update for recent
+ Emacs (co-)maintainer changes.
+ * admin/make-tarball.txt: Add note as a reminder to update the above
+ before making a new release.
+
+2023-09-07 Sebastian Miele <iota@whxvd.name>
+
+ * doc/lispref/strings.texi (Text Comparison): Fix typo (bug#65799).
+
+2023-09-07 Michael Albinus <michael.albinus@gmx.de>
+
+ Adapt Tramp manual
+
+ * doc/misc/tramp.texi (Frequently Asked Questions): Do not use
+ `defadvice'. Add indices. (Bug#65481)
+
+2023-09-07 Stefan Kangas <stefankangas@gmail.com>
+
+ Improve docstring of message-sendmail-envelope-from
+
+ * lisp/gnus/message.el (message-sendmail-envelope-from): Doc fix.
+
+2023-09-07 Philipp Stephani <phst@google.com>
+
+ Unbreak builds with CHECK_STRUCTS.
+
+ * src/pdumper.c (dump_buffer): Fix hash for 'struct buffer'. The
+ recent changes to that structure where commits
+ 8f3091defb3ec4396ccea563f67c005044b822ca and
+ 0bd46619413e83fe3c85c8a1dfbf5e20dfce8605, both of which just affected
+ comments.
+
+2023-09-07 Jens Schmidt <jschmidt4gnu@vodafonemail.de>
+
+ Improve documentation of EPG
+
+ * lisp/epg.el (epg-context-set-passphrase-callback): Update
+ GnuPG-version-dependent information in docstring and refer to
+ Info node `(epa)' for details.
+ (epg-start-edit-key): Replace description of arguments by a
+ reference to `epg-edit-key'.
+ (epg-edit-key): More precisely describe callback operation and
+ arguments and provide an example of how to edit a key. (Bug#65603)
+
+2023-09-07 Daniel Martín <mardani29@yahoo.es>
+
+ Avoid crashes on macOS with context menus
+
+ * src/nsmenu.m ([EmacsMenu menuNeedsUpdate:]): Avoid crashes with
+ context menus. (Bug#63495)
+
+2023-09-07 Yuan Fu <casouri@gmail.com>
+
+ Fix c-ts-mode BSD style indentation
+
+ * lisp/progmodes/c-ts-mode.el (c-ts-mode--indent-styles):
+ Add else_clause.
+
+ (cherry picked from commit d392a5d3c11b7e7479d31421f8237f29952c909e)
+
+2023-09-06 David Ponce <da_vid@orange.fr>
+
+ Fix regexp for recognizing PBM images
+
+ * lisp/image.el (image-type-header-regexps): Don't use [:space:],
+ as its meaning depends on the current buffer's syntax tables.
+ (Bug#65496)
+
+2023-09-06 Eli Zaretskii <eliz@gnu.org>
+
+ Improve wording in ELisp manual
+
+ * doc/lispref/objects.texi (Printed Representation): Improve
+ wording. Suggested by Xie Shynur <one.last.kiss@outlook.com>.
+ (Bug# 60639)
+
+2023-09-06 Joseph Turner <joseph@breatheoutbreathe.in>
+
+ Fix typo (Bug#65764)
+
+ * lisp/subr.el (backward-word-strictly): Fix typo.
+
+2023-09-05 Po Lu <luangruo@yahoo.com>
+
+ Fix libgccjit build on Haiku
+
+ * configure.ac (LIBGCCJIT_LIBS): Link only with -lgccjit under
+ Haiku.
+
+2023-09-05 Stefan Monnier <monnier@iro.umontreal.ca>
+
+ (regexp-tests-backtrack-optimization): Mark it as failing
+
+ * test/src/regex-emacs-tests.el (regexp-tests-backtrack-optimization):
+ The fix for bug#65726 broke some of the optimization added for bug#61514.
+
+2023-09-04 Stefan Monnier <monnier@iro.umontreal.ca>
+
+ * src/regex-emacs.c (mutually_exclusive_p): Fix inf-loop (bug#65726)
+
+2023-09-04 Stefan Kangas <stefankangas@gmail.com>
+
+ Bump seq version to 2.24
+
+ * lisp/emacs-lisp/seq.el: Bump version to 2.24. (Bug#60990)
+
+2023-09-04 Stefan Kangas <stefankangas@gmail.com>
+
+ Add note on ELPA to admin/notes/bug-triage
+
+ * admin/notes/bug-triage: Add section on (Non-)GNU ELPA packages and
+ do some copy editing.
+
+2023-09-02 Po Lu <luangruo@yahoo.com>
+
+ * etc/PROBLEMS: Mention bug#65432 and its remedy.
+
+2023-09-02 Theodor Thornhill <theo@thornhill.no>
+
+ Ignore errors when checking for object initializers (bug#63379)
+
+ Since this is merely a check for syntax, we don't really care about
+ any internal errors inside of backward-up-list.
+
+ * lisp/progmodes/csharp-mode.el (csharp-guess-basic-syntax): Wrap
+ command in ignore-errors.
+
+2023-09-02 Stefan Kangas <stefankangas@gmail.com>
+
+ * CONTRIBUTE: Document making ChangeLogs with Magit.
+
+2023-09-02 Stefan Kangas <stefankangas@gmail.com>
+
+ Doc fixes for obsolete functions and variables
+
+ * admin/notes/multi-tty:
+ * doc/emacs/building.texi (Debugger Operation):
+ * doc/misc/efaq-w32.texi (Line ends by file system):
+ * doc/misc/gnus.texi (Hashcash):
+ * lisp/emacs-lisp/eieio.el (eieio-class-parents)
+ (eieio-class-children):
+ * lisp/progmodes/perl-mode.el:
+ * lisp/textmodes/ispell.el (ispell-lookup-words):
+ * src/buffer.h: Update or delete references to variables and functions
+ made obsolete in Emacs 24.4.
+
+2023-09-02 Mauro Aranda <maurooaranda@gmail.com>
+
+ A revision to the Widget manual
+
+ * doc/misc/widget.texi (Widgets Basics, Working with Widgets)
+ (Widgets and the Buffer, Widget Gallery, Customization): New chapters.
+ (Basic Types, Sexp Types): Demote to subsections.
+ (Widget Browser): Rename to Inspecting Widgets.
+ (Widget Properties): Remove.
+
+ (Top): Adapt menu to changes.
+ (Introduction): Rearrange text. Move warnings to a better place, and
+ user options to the Customization chapter.
+ (User Interface): Don't fully describe commands and customization
+ options here.
+ (Setting Up the Buffer): Expand on widget creation process and add
+ documentation for useful functions which deal with
+ creation/conversion.
+ (Defining New Widgets): Expand the documentation on define-widget.
+ All relevant properties moved to the description of the default
+ widget, in Widget Gallery.
+ (Utilities): Add some more useful functions not previously documented.
+ (Wishlist): Remove out-of-date items.
+
+2023-09-02 Stefan Kangas <stefankangas@gmail.com>
+
+ Fix fontification of " in edit-kbd-macro
+
+ * lisp/edmacro.el (edit-kbd-macro): Fix fontification when editing
+ keyboard macros containing the " character.
+
+2023-09-02 Eli Zaretskii <eliz@gnu.org>
+
+ * lisp/emacs-lisp/gv.el (buffer-local-value): Unobsolete (bug#65555).
+
+2023-09-02 Jens Schmidt <jschmidt4gnu@vodafonemail.de>
+
+ Add documentation to plstore.el
+
+ * lisp/plstore.el: Add link to epa manual. Describe more
+ restrictions. Fix a typo in the examples. Fix terminology. Mark
+ FIXMEs as such.
+ * lisp/plstore.el (plstore-save): Describe edge case when no recipient
+ matches and mark as FIXME. (Bug#63627)
+
+2023-09-01 Stefan Kangas <stefankangas@gmail.com>
+
+ * lisp/help.el (substitute-quotes): Improve docstring.
+
+2023-09-01 Stefan Kangas <stefankangas@gmail.com>
+
+ Fix two defcustom :types
+
+ * lisp/frame.el (blink-cursor-blinks):
+ * lisp/url/url-vars.el (url-max-redirections): Revert defcustom :types
+ back to integer. (Bug#65655)
+
+2023-09-01 Manuel Giraud <manuel@ledu-giraud.fr>
+
+ Fix `image-auto-resize-on-window-resize' custom :type
+
+ * lisp/image-mode.el (image-auto-resize-on-window-resize): Change
+ custom :type from integer to number to be able to set below 1
+ second. (Bug#65626)
+
+2023-09-01 Ross Timson <me@rosstimson.com> (tiny change)
+
+ Add "terraform-ls" LSP server to Eglot
+
+ * lisp/progmodes/eglot.el (eglot-server-programs): Add "terraform-ls",
+ the official Terraform LSP server. (Bug#65671)
+
+2023-09-01 Eli Zaretskii <eliz@gnu.org>
+
+ Fix minor bugs in vc-git and vc-hg on Windows uncovered by vc-tests
+
+ * lisp/vc/vc-hg.el (vc-hg-state-slow): Non-existing files emit a
+ different message on MS-Windows; support that.
+ * lisp/vc/vc-git.el (vc-git-checkin): Make sure
+ 'default-directory' is not nil when calling
+ 'make-nearby-temp-file' on MS-Windows.
+
+ * test/lisp/vc/vc-tests.el (vc-test--version-diff): Run
+ 'default-directory' through 'file-truename', otherwise the
+ 'vc-test-cvs06-version-diff' test might fail on MS-Windows.
+
+2023-08-31 Dmitry Gutov <dmitry@gutov.dev>
+
+ Add syntax-propertize-function to js-ts-mode
+
+ * lisp/progmodes/js.el (js-ts--s-p-query):
+ New variable (bug#65470).
+ (js-ts--syntax-propertize): New function.
+ (js-ts-mode): Use it.
+
+2023-08-30 Yuan Fu <casouri@gmail.com>
+
+ Improve performance of treesit_cursor_helper_1
+
+ * src/treesit.c: (treesit_cursor_helper_1): Use
+ ts_tree_cursor_goto_first_child_for_byte to speed up traversing among
+ siblings. The "while (ts_node_end_byte (cursor_node) < end_pos)" can
+ be removed with the check added in the loop below.
+
+2023-08-28 Stefan Monnier <monnier@iro.umontreal.ca>
+
+ * lisp/subr.el (combine-change-calls-1): Fix bug#64989
+
+ Silence the spurious warning, and improve the warning while at it.
+ Do not merge to master.
+
+2023-08-27 Kyle Meyer <kyle@kyleam.com>
+
+ Update to Org 9.6.8-3-g21171d
+
+2023-08-27 Yuan Fu <casouri@gmail.com>
+
+ Escape percent character in treesit--inspect-name (bug#65540)
+
+ * lisp/treesit.el (treesit-inspect-node-at-point): Escape percent.
+
+2023-08-27 Jim Porter <jporterbugs@gmail.com>
+
+ Don't add an extraneous slash in remote PATH list in Eshell
+
+ Previously, in a remote directory, '(eshell-get-path)' would return a
+ list of strings like "/ssh:localhost://usr/bin". While that shouldn't
+ break most things, it's not strictly correct either. See bug#65551.
+
+ * lisp/eshell/esh-util.el (eshell-get-path): Use 'concat' instead of
+ 'file-name-concat'.
+
+ * test/lisp/eshell/esh-util-tests.el: Require 'tramp' and
+ 'eshell-tests-helpers'.
+ (esh-util-test/path/get, eshell-util-test/path/get-remote): New tests.
+
+2023-08-27 Michael Albinus <michael.albinus@gmx.de>
+
+ Fix Tramp on MS Windows
+
+ * lisp/net/tramp-sh.el (tramp-sh-handle-expand-file-name):
+ Apply `tramp-drop-volume-letter' consequently.
+
+2023-08-27 Andrea Corallo <acorallo@gnu.org>
+
+ * Fix native disassemble on Windows platforms (bug#65455)
+
+ * lisp/emacs-lisp/disass.el (disassemble-internal): Improve regexp.
+
+2023-08-27 Andrea Corallo <acorallo@gnu.org>
+
+ * Handle missing eln file when trying to disassble (bug#65455)
+
+ * lisp/emacs-lisp/disass.el (disassemble-internal): Handle missing
+ eln file.
+
+2023-08-27 Andrea Corallo <acorallo@gnu.org>
+
+ * lisp/emacs-lisp/comp.el (comp--native-compile): Fix OUTPUT for non abs paths
+
+2023-08-27 Jonas Bernoulli <jonas@bernoul.li>
+
+ Update to Transient v0.4.3
+
+2023-08-27 Michael Albinus <michael.albinus@gmx.de>
+
+ Adapt Eshell manual
+
+ * doc/misc/eshell.texi (Arguments): Mention more special
+ characters to be quoted in remote file names. (Bug#65431)
+
+2023-08-27 Eli Zaretskii <eliz@gnu.org>
+
+ Fix applying patches with Git on MS-Windows
+
+ * lisp/vc/vc.el (vc-diff-internal): For Git, always suppress EOL
+ conversion when reading the diffs into a buffer. Doc fix.
+ * lisp/vc/vc-git.el (vc-git-checkin): Make sure to suppress EOL
+ conversion when the patch file is written. (Bug#65049)
+
+2023-08-26 Po Lu <luangruo@yahoo.com>
+
+ Repair bug#65068 on Emacs 29
+
+ * src/xterm.c (x_term_init): Disable ControlFallback library
+ control wherever present. (bug#65068)
+
+ Do not merge to master.
+
+2023-08-24 Stefan Kangas <stefankangas@gmail.com>
+
+ Fix custom :type of dired-mouse-drag-files
+
+ * lisp/dired.el (dired-mouse-drag-files): Fix :type to allow
+ specifying 'move'. (Bug#65497)
+
+2023-08-24 James Thomas <jimjoe@gmx.net>
+
+ Account for string names in active file
+
+ Account also for strings when reading in group names from an active
+ file (bug#62812).
+ * lisp/gnus/nnmail.el (nnmail-parse-active): Make it similar to
+ gnus-active-to-gnus-format
+
+2023-08-24 Christoph Göttschkes <just.mychris@googlemail.com> (tiny change)
+
+ Fix 'makefile-browser-client' variable initialization
+
+ * lisp/progmodes/make-mode.el (makefile-browser-client):
+ Initialize to nil. (Bug#65487)
+
+2023-08-19 Yuan Fu <casouri@gmail.com>
+
+ Support defun navigation for DEFUN in c-ts-mode (bug#64442)
+
+ Before this change, beginning/end-of-defun just ignores DEFUN in
+ c-ts-mode. After this change, beginning/end-of-defun can recognize
+ DEFUN, but a DEFUN definition is considered two defuns. Eg,
+ beginning/end-of-defun will stop at (1) (2) and (3) in the following
+ snippet:
+
+ (1)DEFUN ("treesit-node-parser",
+ Ftreesit_node_parser, Streesit_node_parser,
+ 1, 1, 0,
+ doc: /* Return the parser to which NODE belongs. */)
+ (Lisp_Object node)
+ (2){
+ CHECK_TS_NODE (node);
+ return XTS_NODE (node)->parser;
+ }
+ (3)
+
+ Ideally we want point to only stop at (1) and (3), but that'll be a
+ lot harder to do.
+
+ * lisp/progmodes/c-ts-mode.el:
+ (c-ts-mode--defun-valid-p): Refactor to take in account of DEFUN body.
+ (c-ts-mode--emacs-defun-body-p): New function.
+ (c-ts-base-mode): Add DEFUN and DEFUN body to recognized types.
+ (c-ts-mode--emacs-defun-at-point): Now that we recognize both parts of
+ a DEFUN as defun, c-ts-mode--emacs-defun-at-point needs to be updated
+ to adapt to it.
+
+2023-08-19 Eli Zaretskii <eliz@gnu.org>
+
+ Fix touchpad scrolling on MS-Windows
+
+ * src/w32term.c (w32_construct_mouse_wheel): The number of lines
+ to scroll should always be positive in wheel-scroll events.
+ Whether to scroll up or down is encoded in the modifiers, which
+ produce either wheel-up or wheel-down event. (Bug#65070)
+
+ * doc/lispref/commands.texi (Misc Events): Clarify the
+ documentation of 'wheel-up' and 'wheel-down' events.
+
+2023-08-19 Philip Kaludercic <philipk@posteo.net>
+
+ Fix order in which package-vc dependencies are resolved
+
+ * lisp/emacs-lisp/package-vc.el (package-vc-install-dependencies):
+ Avoid a type-mismatch when comparing two packages. (Bug#65283)
+
+2023-08-19 Joseph Turner <joseph@breatheoutbreathe.in>
+
+ Fix building of VC package manuals with relative org links/includes
+
+ * lisp/emacs-lisp/package-vc.el (package-vc--build-documentation):
+ Ensure that default-default is the docs-directory around
+ org-export-to-file to ensure that links to relative files work
+ correctly. (Bug#65243)
+
+2023-08-19 Eli Zaretskii <eliz@gnu.org>
+
+ Fix the documentation of 'cl-flet'
+
+ * doc/misc/cl.texi (Function Bindings): Update the description.
+ (Bug#65362)
+
+2023-08-17 Jens Schmidt <jschmidt4gnu@vodafonemail.de>
+
+ Avoid false "wrong passphrase" messages in EPA
+
+ * lisp/epa-file.el (epa--wrong-password-p): Use a stricter regexp
+ to match "wrong passphrase" errors generated by GnuPG. (Bug#65316)
+
+2023-08-17 dannyfreeman <danny@dfreeman.email>
+
+ Fix jsx font-lock in older tree-sitter-js grammars
+
+ * lisp/progmodes/js.el (js--treesit-font-lock-settings): Use
+ queries that are backwards compatible with
+ tree-sitter-javascript bb1f97b.
+ * lisp/progmodes/js.el
+ (-jsx--treesit-font-lock-compatibility-bb1f97b): Delete unused
+ function. (Bug#65234)
+
+2023-08-17 Eli Zaretskii <eliz@gnu.org>
+
+ Fix cloning 'face-remapping-alist' for indirect buffers
+
+ * lisp/face-remap.el (face-remap--copy-face): Remove.
+ (face-attrs--make-indirect-safe): Use 'copy-tree'. Suggested by
+ Stefan Monnier <monnier@iro.umontreal.ca>.
+
+2023-08-17 Eli Zaretskii <eliz@gnu.org>
+
+ Improve documentation of case transfer in replacement commands
+
+ * doc/emacs/search.texi (Replacement and Lax Matches):
+ * src/search.c (Freplace_match):
+ * lisp/replace.el (query-replace, query-replace-regexp): Clarify
+ in the doc string and the manual how letter-case is transferred
+ from the replaced text to the replacement text. (Bug#65347)
+
+2023-08-16 Eli Zaretskii <eliz@gnu.org>
+
+ Fix horizontal scrolling of images with C-f
+
+ * lisp/image-mode.el (image-forward-hscroll): Calculate the
+ window-width more accurately, as the number of full columns that
+ fits in the window's text-area. (Bug#65187)
+
+2023-08-16 Eli Zaretskii <eliz@gnu.org>
+
+ Fix unpacking ZIP archives on MS-Windows
+
+ * lisp/arc-mode.el (archive-zip-summarize): Decode file names as
+ UTF-8 when bit 11 of flags is set, even on MS-Windows.
+ (Bug#65305)
+
+2023-08-16 Jim Porter <jporterbugs@gmail.com>
+
+ Fix command example in Eshell manual
+
+ * doc/misc/eshell.texi (Introduction): Fix example (bug#65303).
+
+ Reported by Eric Gillespie <brickviking@gmail.com>.
+
+2023-08-14 Jim Porter <jporterbugs@gmail.com>
+
+ Add user options mentioned in the Eshell manual to the variable index
+
+ * doc/misc/eshell.texi: Make variable index entries use "code" style,
+ and add indexing for any options already in the manual.
+
+2023-08-14 Andrea Corallo <acorallo@gnu.org>
+
+ * Add missing alias to `native-comp-enable-subr-trampolines'.
+
+ * lisp/subr.el (native-comp-deferred-compilation): Alias to
+ native-comp-jit-compilation.
+
+2023-08-14 Andrea Corallo <acorallo@gnu.org>
+
+ * Add missing alias to `native-comp-enable-subr-trampolines'.
+
+ * lisp/subr.el (comp-enable-subr-trampolines): Alias to
+ native-comp-enable-subr-trampolines.
+
+2023-08-13 Kyle Meyer <kyle@kyleam.com>
+
+ Update to Org 9.6.7-13-g99cc96
+
+2023-08-13 Michael Albinus <michael.albinus@gmx.de>
+
+ Handle last-coding-system-used in Tramp for all backends
+
+ * lisp/net/tramp.el (tramp-skeleton-write-region):
+ Handle `last-coding-system-used'.
+ (tramp-handle-write-region):
+ * lisp/net/tramp-adb.el (tramp-adb-handle-write-region):
+ * lisp/net/tramp-smb.el (tramp-smb-handle-write-region):
+ * lisp/net/tramp-sshfs.el (tramp-sshfs-handle-write-region):
+ Set `coding-system-used'. (Bug#65022)
+
+ * lisp/net/tramp-sh.el (tramp-sh-handle-write-region):
+ Move `last-coding-system-used' handling to
+ `tramp-skeleton-write-region'.
+
+2023-08-13 Devon Sean McCullough <emacs-hacker2017@jovi.net>
+
+ Add 2 Welsh characters to iso-transl.el
+
+ * lisp/international/iso-transl.el (iso-transl-char-map): Add two
+ Welsh characters. (Bug#65248)
+
+2023-08-12 Andrea Corallo <acorallo@gnu.org>
+
+ * Fix `batch-byte+native-compile' target directory.
+
+ * lisp/emacs-lisp/comp.el (batch-native-compile): Don't shadow
+ `native-compile-target-directory' unless necessary.
+
+2023-08-12 Eli Zaretskii <eliz@gnu.org>
+
+ Avoid crashes in 'display_count_lines' when current buffer was killed
+
+ * src/xdisp.c (Fformat_mode_line):
+ * src/fns.c (Fline_number_at_pos): Don't allow to count lines in a
+ dead buffer. (Bug#65060)
+
+2023-08-12 J M <jean@tbm.email>
+
+ Update csharp tree-sitter support due to upstream changes
+
+ A change in tree-sitter-c-sharp grammar for csharp (commit
+ 18a531), has removed the keyword void_keyword and advised
+ we should use predefined_type.
+ * lisp/progmodes/csharp-mode.el (csharp-ts-mode--font-lock-settings):
+ Support both old and new style of keywords in tree-sitter-c-sharp
+ grammar. (Bug#65113)
+
+2023-08-12 Matthew Tromp <matthewktromp@gmail.com> (tiny change)
+
+ Substitute command keys in 'ielm-header' at use time
+
+ Before, command keys were substituted into the ielm-header when
+ ielm.el was loaded, which resulted in the substitutions depending on
+ the user's current buffer instead of the ielm buffer.
+ For example, if the user was in an info-mode buffer, the key would
+ appear as 'H' instead of 'C-h m'.
+ Now, the command key is substituted after the ielm buffer has been
+ created.
+ * lisp/ielm.el (ielm-header): Remove substitute-command-keys.
+ (inferior-emacs-lisp-mode): Add substitute-command-keys. (Bug#65213)
+
+2023-08-12 Eli Zaretskii <eliz@gnu.org>
+
+ Fix rare crashes in redisplay due to problems with fontsets
+
+ * src/xdisp.c (get_next_display_element): If we have no usable
+ face to display a character/composition, treat that as glyphless.
+ (produce_glyphless_glyph): If neither it->face nor its ASCII face
+ are usable, fall back to the frame's default font. (Bug#65198)
+
+2023-08-12 Eli Zaretskii <eliz@gnu.org>
+
+ Fix a typo in 'leuven-dark-theme.el'
+
+ * etc/themes/leuven-dark-theme.el (leuven-dark): Fix a typo.
+ Reported by John Poole <saxcos@posteo.es>. (Bug#65239)
+
+2023-08-10 Michael Albinus <michael.albinus@gmx.de>
+
+ Adapt Tramp test
+
+ * test/lisp/net/tramp-tests.el (tramp-test41-special-characters):
+ Skip for macOS.
+
+2023-08-10 dannyfreeman <danny@dfreeman.email>
+
+ Properly expand the JSX indentation rules in 'js-ts-mode'
+
+ * lisp/progmodes/js.el (js--treesit-indent-rules): Fix
+ 'js-ts-mode' indent bug in JSX expressions. Before this
+ change, treesit indent mechanisms were trying to call this
+ compatibility function like a matching or anchor rule.
+ This resulted in an error when running `indent-for-tab-command`
+ while the cursor was in a JSX expression:
+
+ treesit--simple-indent-eval: Wrong number of
+ arguments: ((cl-struct-js--pitem-tags ido-cur-list t) nil "Indent rules
+ helper, to handle different releases of tree-sitter-javascript."
+
+ (Bug#65134)
+
+2023-08-10 Andrea Corallo <acorallo@gnu.org>
+
+ * Add `emacs-lisp-native-compile' to easy-menu.
+
+ * lisp/progmodes/elisp-mode.el (emacs-lisp-mode-menu): Add menu
+ item for emacs-lisp-native-compile.
+
+2023-08-10 Andrea Corallo <acorallo@gnu.org>
+
+ * lisp/progmodes/elisp-mode.el (emacs-lisp-mode-menu): Simplify condition.
+
+2023-08-10 Andrea Corallo <acorallo@gnu.org>
+
+ * Introduce `emacs-lisp-native-compile'.
+
+ * lisp/progmodes/elisp-mode.el (emacs-lisp-native-compile): New command.
+ (emacs-lisp-native-compile-and-load): Make use of.
+
+2023-08-10 Eli Zaretskii <eliz@gnu.org>
+
+ Fix the -x switch in non-X builds
+
+ * src/emacs.c (main): Move the handling of the -x switch out of
+ the HAVE_X_WINDOWS condition, and simplify the rest of the code by
+ avoiding code duplication in HAVE_X_WINDOWS and !HAVE_X_WINDOWS
+ cases. (Bug#65048)
+
+2023-08-10 Po Lu <luangruo@yahoo.com>
+
+ Document that `set-mouse-color' does not work everywhere
+
+ * etc/PROBLEMS (Miscellaneous Problems): Mention where
+ `set-mouse-color' does not work.
+
+2023-08-10 Eli Zaretskii <eliz@gnu.org>
+
+ Fix the effects and documentation of 'dired-free-space'
+
+ * lisp/dired.el (dired-free-space): Fix doc string and Custom tags.
+ (dired--insert-disk-space): When 'dired-free-space' is 'separate',
+ return the position of the beginning of the disk-space line, to be
+ compatible with pre-Emacs 29 behavior under
+ 'dired-hide-details-mode'. (Bug#65186)
+
+ * doc/emacs/dired.texi (Misc Dired Features): Fix wording in
+ documentation of 'dired-free-space'.
+
+2023-08-09 Stefan Kangas <stefankangas@gmail.com>
+
+ Fix cross-reference to eldoc in eglot manual
+
+ * doc/misc/eglot.texi (Eglot Features): Fix cross-reference to eldoc
+ node in the Emacs manual.
+
+2023-08-09 Eli Zaretskii <eliz@gnu.org>
+
+ Add native-compilation to Emacs Lisp mode menu
+
+ * lisp/progmodes/elisp-mode.el (emacs-lisp-mode-menu): Add menu
+ item for emacs-lisp-native-compile-and-load.
+
+2023-08-09 Andrea Corallo <acorallo@gnu.org>
+
+ Fix emacs-lisp-native-compile-and-load eln target directory (bug#64226)
+
+ * lisp/emacs-lisp/comp.el (comp-spill-lap-function): Don't use
+ `byte+native-compile' to select output directory but always axpect
+ it explicit through `native-compile-target-directory'.
+ (batch-byte+native-compile): Set `native-compile-target-directory'.
+ * test/src/comp-tests.el (comp-tests-bootstrap): Set
+ `native-compile-target-directory'.
+
+2023-08-09 Mattias Engdegård <mattiase@acm.org>
+
+ Disable failing test (bug#65156)
+
+ * test/src/fileio-tests.el (fileio-tests--non-regular-insert):
+ Mark as :unstable, since /dev/urandom is seekable.
+
+ Do not merge to master.
+
+2023-08-08 Po Lu <luangruo@yahoo.com>
+
+ Better fix for bug#65156
+
+ * src/fileio.c (Finsert_file_contents): Correct seek-ability
+ test, since lseek returns -1 upon failure. (Bug#65156)
+
+2023-08-08 Eli Zaretskii <eliz@gnu.org>
+
+ Fix insert-file-contents with pipes and /dev/stdin
+
+ * src/fileio.c (Finsert_file_contents): Restore logic of
+ non-regular but seekable files. (Bug#65156)
+
+2023-08-07 Po Lu <luangruo@yahoo.com>
+
+ Fix bug#65042
+
+ * src/pgtkterm.c (fill_background_by_face): Respect the frame's
+ background alpha property.
+
+2023-08-07 Eli Zaretskii <eliz@gnu.org>
+
+ * configure.ac (HAVE_TREE_SITTER): Set NEED_DYNLIB=yes (bug#65123).
+
+2023-08-06 Michael Albinus <michael.albinus@gmx.de>
+
+ * etc/NEWS: Mention tramp-show-ad-hoc-proxies.
+
+ * test/lisp/net/tramp-tests.el (tramp-test42-utf8): Skip for macOS.
+
+ * test/lisp/net/tramp-tests.el (tramp-test10-write-region): Extend test.
+
+2023-08-06 Eli Zaretskii <eliz@gnu.org>
+
+ Fix reverting Rmail buffers
+
+ This bug happened because rmail.el relied on 'revert-buffer' to
+ return non-nil when it succeeds to revert, but a recent change
+ in 'revert-buffer' broke that promise in Emacs 29.1.
+ * lisp/files.el (revert-buffer--default, revert-buffer): Doc fix.
+ (revert-buffer): Return whatever 'revert-buffer-function' returns.
+ (Bug#65071)
+
+2023-08-05 Jim Porter <jporterbugs@gmail.com>
+
+ Fix handling of 'byte-compile-ignore-files' when nil
+
+ Before this fix, when 'byte-compile-ignore-files' was nil,
+ 'byte-recompile-directory' would ignore every file (bug#64985).
+
+ * lisp/emacs-lisp/bytecomp.el (byte-recompile-directory): Handle case
+ when 'byte-compile-ignore-files' is nil.
+
+2023-08-05 Michael Albinus <michael.albinus@gmx.de>
+
+ Sync with Tramp 2.6.2-pre
+
+ * doc/misc/tramp.texi (Overview): Use "scp" in example.
+ (Obtaining @value{tramp}): Prefer https: to git: URIs on Savannah.
+ (Ssh setup): Extend for MS Windows and ssh. Explain
+ tramp-use-ssh-controlmaster-options value `suppress'.
+ (File name completion): Remove completion styles restrictions.
+ (Ad-hoc multi-hops): Describe tramp-show-ad-hoc-proxies.
+ (Remote processes): Add reference to "Using ssh connection sharing".
+
+ * doc/misc/trampver.texi:
+ * lisp/net/trampver.el (tramp-version): Set to "2.6.2-pre".
+
+ * lisp/net/tramp-adb.el (tramp-adb-handle-file-name-all-completions):
+ * lisp/net/tramp-archive.el
+ (tramp-archive-handle-file-name-all-completions):
+ * lisp/net/tramp-crypt.el (tramp-crypt-handle-file-name-all-completions):
+ * lisp/net/tramp-fuse.el (tramp-fuse-handle-file-name-all-completions):
+ * lisp/net/tramp-gvfs.el (tramp-gvfs-handle-file-name-all-completions):
+ * lisp/net/tramp-sh.el (tramp-sh-handle-file-name-all-completions):
+ * lisp/net/tramp-smb.el (tramp-smb-handle-file-name-all-completions):
+ * lisp/net/tramp-sudoedit.el
+ (tramp-sudoedit-handle-file-name-all-completions): Return nil when
+ DIRECTORY is missing. (Bug#61890)
+
+ * lisp/net/tramp.el (tramp-accept-process-output): Don't use TIMEOUT
+ anymore, default it to 0. When the connection uses a shared
+ socket possibly, accept also the output from other processes over
+ the same connection. (Bug#61350)
+ (tramp-handle-file-notify-rm-watch, tramp-action-process-alive)
+ (tramp-action-out-of-band, tramp-process-one-action)
+ (tramp-interrupt-process):
+ * lisp/net/tramp-adb.el (tramp-adb-handle-make-process):
+ * lisp/net/tramp-gvfs.el (tramp-gvfs-handle-file-notify-add-watch):
+ * lisp/net/tramp-sh.el (tramp-sh-handle-file-notify-add-watch):
+ * lisp/net/tramp-smb.el (tramp-smb-action-get-acl)
+ (tramp-smb-action-set-acl, tramp-smb-wait-for-output):
+ * lisp/net/tramp-sudoedit.el (tramp-sudoedit-action-sudo): Adapt callees.
+
+ * lisp/net/tramp.el (tramp-get-process, tramp-message)
+ (tramp-handle-make-process, tramp-handle-file-notify-valid-p)
+ (tramp-process-actions, tramp-accept-process-output)
+ (tramp-process-sentinel, tramp-read-passwd)
+ (tramp-interrupt-process, tramp-signal-process):
+ * lisp/net/tramp-adb.el (tramp-adb-maybe-open-connection):
+ * lisp/net/tramp-cmds.el (tramp-cleanup-connection):
+ * lisp/net/tramp-crypt.el (tramp-crypt-maybe-open-connection):
+ * lisp/net/tramp-gvfs.el (tramp-gvfs-handle-file-notify-add-watch)
+ (tramp-gvfs-monitor-process-filter)
+ (tramp-gvfs-maybe-open-connection):
+ * lisp/net/tramp-rclone.el (tramp-rclone-maybe-open-connection):
+ * lisp/net/tramp-sh.el (tramp-do-copy-or-rename-file-out-of-band)
+ (tramp-sh-handle-file-notify-add-watch)
+ (tramp-sh-gio-monitor-process-filter)
+ (tramp-sh-inotifywait-process-filter)
+ (tramp-barf-if-no-shell-prompt, tramp-maybe-open-connection):
+ * lisp/net/tramp-smb.el (tramp-smb-handle-copy-directory)
+ (tramp-smb-handle-file-acl, tramp-smb-handle-set-file-acl)
+ (tramp-smb-maybe-open-connection):
+ * lisp/net/tramp-sshfs.el (tramp-sshfs-maybe-open-connection):
+ * lisp/net/tramp-sudoedit.el (tramp-sudoedit-maybe-open-connection)
+ (tramp-sudoedit-send-command): Prefix internal process properties
+ with "tramp-".
+
+ * lisp/net/tramp.el (tramp-skeleton-file-exists-p): New defmacro,
+ which also handles host name completion.
+ (tramp-handle-file-exists-p):
+ * lisp/net/tramp-adb.el (tramp-adb-handle-file-exists-p):
+ * lisp/net/tramp-sh.el (tramp-sh-handle-file-exists-p):
+ * lisp/net/tramp-sudoedit.el (tramp-sudoedit-handle-file-exists-p): Use it.
+
+ * lisp/net/tramp.el (tramp-wrong-passwd-regexp):
+ * lisp/net/tramp-adb.el (tramp-adb-prompt):
+ * lisp/net/tramp-sh.el (tramp-sh-inotifywait-process-filter):
+ * lisp/net/tramp-smb.el (tramp-smb-maybe-open-connection): Unify regexps.
+
+ * lisp/net/tramp.el:
+ * lisp/net/tramp-cmds.el:
+ * lisp/net/tramp-crypt.el:
+ * lisp/net/tramp-gvfs.el:
+ * lisp/net/tramp-sh.el:
+ * lisp/net/tramp-smb.el: Fix error messages.
+
+ * lisp/net/tramp-cmds.el (tramp-cleanup-connection):
+ Protect `delete-process'.
+
+ * lisp/net/tramp.el (tramp-prefix-format, tramp-prefix-regexp)
+ (tramp-method-regexp, tramp-postfix-method-format)
+ (tramp-postfix-method-regexp, tramp-prefix-ipv6-format)
+ (tramp-prefix-ipv6-regexp, tramp-postfix-ipv6-format)
+ (tramp-postfix-ipv6-regexp, tramp-postfix-host-format)
+ (tramp-postfix-host-regexp, tramp-remote-file-name-spec-regexp)
+ (tramp-file-name-structure, tramp-file-name-regexp)
+ (tramp-completion-method-regexp)
+ (tramp-completion-file-name-regexp):
+ * lisp/net/tramp-compat.el (tramp-syntax):
+ * lisp/net/tramp-gvfs.el (tramp-gvfs-dbus-event-vector):
+ Rearrange declarations.
+
+ * lisp/net/tramp-compat.el (ansi-color): Require.
+ (ls-lisp): Don't require. (Bug#64124)
+ (tramp-compat-replace-regexp-in-region): Move up.
+ (tramp-compat-length<, tramp-compat-length>)
+ (tramp-compat-length=): New defaliases.
+ (tramp-compat-file-name-unquote, tramp-compat-take)
+ (tramp-compat-ntake): Use them.
+
+ * lisp/net/tramp-container.el (tramp-container--completion-function):
+ Rename from `tramp-docker--completion-function'. Add argument
+ PROGRAM. Use it for "docker" and "podman" host name completion.
+
+ * lisp/net/tramp-crypt.el (tramp-crypt-handle-file-exists-p):
+ New defun.
+ (tramp-crypt-file-name-handler-alist): Add it.
+
+ * lisp/net/tramp-fuse.el (tramp-fuse-handle-file-exists-p): New defun.
+ (tramp-fuse-mount-timeout): Move up.
+ (tramp-fuse-mount-point): Use `tramp-fuse-mount-timeout'.
+ (tramp-fuse-unmount): Flush "mount-point" file property.
+ (tramp-fuse-mount-point, tramp-fuse-mounted-p): Support existing
+ mount points.
+ (tramp-fuse-mounted-p): The mount-spec could contain an optional
+ trailing slash. (Bug#64278)
+
+ * lisp/net/tramp-gvfs.el (tramp-gvfs-do-copy-or-rename-file)
+ * lisp/net/tramp-rclone.el (tramp-rclone-do-copy-or-rename-file):
+ Improve stability for WebDAV.
+ (tramp-rclone-handle-file-system-info): Check return code of
+ command.
+
+ * lisp/net/tramp-gvfs.el (while-no-input-ignore-events):
+ Add `dbus-event' for older Emacs versions.
+ (tramp-gvfs-parse-device-names): Ignore errors.
+
+ * lisp/net/tramp-sh.el (tramp-display-escape-sequence-regexp)
+ (tramp-device-escape-sequence-regexp): Delete.
+ (tramp-sh-handle-insert-directory, tramp-barf-if-no-shell-prompt)
+ (tramp-wait-for-output): Use `ansi-color-control-seq-regexp'.
+ (tramp-use-ssh-controlmaster-options): Allow new value `suppress'.
+ (tramp-ssh-option-exists-p): New defun.
+ (tramp-ssh-controlmaster-options): Implement `suppress' actions.
+ Should never return nil, but empty string.
+ (tramp-perl-file-name-all-completions): Don't print status message.
+ (tramp-sh-handle-file-name-all-completions): Return nil when check
+ fails. (Bug#61890)
+ (tramp-run-test): Add VEC argument.
+ (tramp-sh-handle-file-executable-p)
+ (tramp-sh-handle-file-readable-p)
+ (tramp-sh-handle-file-directory-p)
+ (tramp-sh-handle-file-writable-p): Adapt callees.
+ (tramp-sh-handle-insert-directory):
+ (tramp-sh-handle-insert-directory): Test whether -N is understood
+ by ls since that option is used along with --dired. Remove -N
+ when we remove --dired. (Bug#63142)
+ (tramp-sh-handle-insert-directory, tramp-barf-if-no-shell-prompt)
+ (tramp-wait-for-output): Use `ansi-color-control-seq-regexp'.
+ (tramp-sh-handle-expand-file-name): `null-device' could be nil.
+ Reported by Richard Copley <rcopley@gmail.com>.
+ (tramp-sh-handle-make-process): Improve handling of
+ connection-type `pipe'. (Bug#61341)
+
+ * lisp/net/tramp-smb.el (tramp-smb-handle-make-symbolic-link):
+ * lisp/net/tramp-sudoedit.el (tramp-sudoedit-handle-make-symbolic-link):
+ Flush TARGET file properties.
+
+ * lisp/net/tramp-smb.el (tramp-smb-handle-copy-file): Flush proper
+ file properties.
+ (tramp-smb-handle-file-acl, tramp-smb-handle-set-file-acl):
+ Remove superfluous `unwind-protect'.
+
+ * lisp/net/tramp-sshfs.el (tramp-sshfs-file-name-handler-alist):
+ Use `tramp-fuse-handle-file-exists-p'.
+ (tramp-sshfs-handle-insert-file-contents): Move result out of
+ unwindform.
+
+ * lisp/net/tramp.el (tramp-string-empty-or-nil-p): New defsubst.
+ Use it everywhere when appropriate.
+
+ * lisp/net/tramp.el (tramp-methods) <->: Add.
+ (tramp-completion-file-name-handler-alist):
+ Add `expand-file-name', `file-exists-p', `file-name-directory' and
+ `file-name-nondirectory'.
+ (tramp-dissect-file-name): Do not extra check for
+ `tramp-default-method-marker'.
+ (tramp-completion-handle-expand-file-name)
+ (tramp-completion-handle-file-exists-p)
+ (tramp-completion-handle-file-name-directory)
+ (tramp-completion-handle-file-name-nondirectory): New defuns.
+ (tramp-completion-handle-file-name-all-completions): Remove duplicates.
+ (tramp-show-ad-hoc-proxies): New defcustom.
+ (tramp-make-tramp-file-name): Use it.
+ (tramp-make-tramp-hop-name): Don't add hop twice.
+ (tramp-shell-prompt-pattern): Remove escape characters.
+ (tramp-process-one-action, tramp-convert-file-attributes):
+ Use `ansi-color-control-seq-regexp'. (Bug#63539)
+ (tramp-wrong-passwd-regexp): Add "Authentication failed" string
+ (from doas).
+ (tramp-terminal-type): Fix docstring.
+ (tramp-process-one-action): Delete ANSI control escape sequences
+ in buffer. (Bug#63539)
+ (tramp-build-completion-file-name-regexp): Support user name
+ completion.
+ (tramp-make-tramp-file-name): Keep hop while in file
+ (tramp-set-completion-function): Check, that cdr of FUNCTION-LIST
+ entries is a string.
+ (tramp-completion-file-name-handler): Run only when
+ `minibuffer-completing-file-name' is non-nil.
+ (tramp-skeleton-write-region): Fix scoping. (Bug#65022)
+ (tramp-handle-memory-info): Work on newly created objects, or use
+ non-destructive operations.
+ (tramp-accept-process-output): Use `with-local-quit'.
+ (tramp-call-process, tramp-call-process-region):
+ Let-bind `temporary-file-directory'.
+
+ * test/lisp/net/tramp-archive-tests.el (tramp-archive--test-emacs28-p):
+ New defun.
+ (tramp-archive-test16-directory-files): Don't mutate.
+ (tramp-archive-test47-auto-load): Adapt test.
+
+ * test/lisp/net/tramp-tests.el (tramp-display-escape-sequence-regexp):
+ Don't declare.
+ (tramp-action-yesno): Suppress run in tests.
+ (tramp-test02-file-name-dissect):
+ (tramp-test02-file-name-dissect-simplified)
+ (tramp-test02-file-name-dissect-separate): Adapt tests.
+ (tramp-test21-file-links):
+ (tramp-test21-file-links, tramp-test26-file-name-completion)
+ (tramp-test28-process-file, tramp-test29-start-file-process)
+ (tramp-test30-make-process, tramp-test33-environment-variables)
+ (tramp-test38-find-backup-file-name, tramp-test47-auto-load)
+ (tramp-test39-detect-external-change, tramp-test42-utf8)
+ (tramp-test47-auto-load, tramp-test47-delay-load)
+ (tramp-test48-unload): Adapt tests.
+ (tramp-test26-file-name-completion-with-perl):
+ (tramp-test26-file-name-completion-with-ls)
+ (tramp-test26-interactive-file-name-completion): New tests.
+ (tramp-test44-asynchronous-requests): Mark as :unstable.
+
+2023-08-05 Eli Zaretskii <eliz@gnu.org>
+
+ Fix documentation of saveplace facilities for Dired
+
+ * lisp/saveplace.el (save-place-dired-hook, save-place-alist):
+ * lisp/dired.el (dired-initial-position-hook)
+ (dired-initial-position): Doc fixes. (Bug#65055)
+
+2023-08-04 Jim Porter <jporterbugs@gmail.com>
+
+ Fix loaddef generation with ";;;foo-autoload" cookies in external packages
+
+ This caused an issue where package-specific autoload cookies weren't
+ being correctly recognized, so they got dumped into the package's main
+ "<pkg>-autoloads.el" file, instead of "<pkg>-loaddefs.el" as they
+ should (bug#65023).
+
+ * lisp/emacs-lisp/loaddefs-gen.el (loaddefs-generate--parse-file):
+ Save match data when checking syntax.
+
+2023-08-04 Stefan Kangas <stefankangas@gmail.com>
+
+ Delete comment saying that project.el is experimental
+
+ * lisp/progmodes/project.el (Commentary): Delete comment saying that
+ the API is "still experimental". It is to be considered stable
+ starting with the version released with Emacs 29.
+ Ref: https://lists.gnu.org/r/emacs-devel/2023-07/msg00415.html
+
+2023-08-04 Eli Zaretskii <eliz@gnu.org>
+
+ Fix byte-compiled files that use 'bind-key' from use-package
+
+ * lisp/use-package/bind-key.el (bind-key): Ensure 'bind-key' is
+ loaded at run time. Patch by John Wiegley <johnw@gnu.org>.
+ (Bug#64901)
+
+2023-08-04 Eli Zaretskii <eliz@gnu.org>
+
+ Fix "Paste from Kill Menu" in non X toolkit builds
+
+ * src/keymap.c (possibly_translate_key_sequence): Don't signal an
+ error if 'key-valid-p' returns nil. Suggested by Stefan Monnier
+ <monnier@iro.umontreal.ca>. (Bug#64927)
+
+2023-08-03 john muhl <jm@pub.pink>
+
+ Handle tabs in the SQL shown in the column listing
+
+ * lisp/sqlite-mode.el (sqlite-mode-list-columns): Handle tabs.
+ (Bug#64964)
+
+2023-08-03 Eli Zaretskii <eliz@gnu.org>
+
+ Add new keyword to 'typescript-ts-mode'
+
+ * lisp/progmodes/typescript-ts-mode.el
+ (typescript-ts-mode--keywords): Add "satisfies", a new operator in
+ Typescript 4.9. (Bug#64924)
+
+2023-08-03 Stefan Kangas <stefankangas@gmail.com>
+
+ Fix link to info node in prin1 docstring
+
+ * src/print.c (Fprin1): Fix linking to info node in docstring.
+
+ (cherry picked from commit 4b73edb8d1da74fd1bda8894e982d9768fd1f18c)
+
+2023-08-03 Eli Zaretskii <eliz@gnu.org>
+
+ Clarify the meaning of the argument of ':align-to' space spec
+
+ * doc/lispref/display.texi (Specified Space): Clarify the meaning
+ and measurement of HPOS in ':align-to' space specs. (Bug#65015)
+
+2023-08-01 Jim Porter <jporterbugs@gmail.com>
+
+ Fix handling of ".elpaignore" file when compiling packages
+
+ * lisp/emacs-lisp/bytecomp.el (byte-recompile-directory): Treat
+ 'byte-compile-ignore-files' as a list of regexps per its docstring
+ (bug#64985).
+
+2023-08-01 Amritpal Singh <sysgrammer@protonmail.com> (tiny change)
+
+ Support files compressed by 'pigz'
+
+ * src/decompress.c (md5_gz_stream): Check 'stream.avail_in' as
+ well. (Bug#63832)
+
+ (cherry picked from commit 46b6d175054e8f6bf7cb45e112048c0cf02bfee9)
+
+2023-07-31 Eli Zaretskii <eliz@gnu.org>
+
+ Fix 'string-pixel-width' under 'line-prefix'
+
+ * lisp/emacs-lisp/subr-x.el (string-pixel-width): Disable
+ 'line-prefix' and 'wrap-prefix' to avoid their effect on the
+ calculated string width. (Bug#64971)
+
+2023-07-31 Michael Albinus <michael.albinus@gmx.de>
+
+ Fix find-dired-with-command for remote directories
+
+ * lisp/find-dired.el (find-dired-with-command):
+ Use `start-file-process-shell-command'. (Bug#64897)
+
+2023-07-30 Kyle Meyer <kyle@kyleam.com>
+
+ Update to Org 9.6.7-5-gd1d0c3
+
+2023-07-30 Mattias Engdegård <mattiase@acm.org>
+
+ Fix rx wrong-code bug: ranges starting with ^
+
+ (rx (in (?^ . ?a))) was incorrectly translated to "[^-a]".
+ Change it so that we get "[_-a^]" instead.
+
+ * lisp/emacs-lisp/rx.el (rx--generate-alt): Split ranges starting with
+ `^` occurring first in a non-negated character alternative.
+ * test/lisp/emacs-lisp/rx-tests.el (rx-any): Add and adapt tests.
+
+ (cherry picked from commit 5f5d668ac7917d61e9366fe0c3efd7b542671c3d)
+
+2023-07-30 Basil L. Contovounesios <contovob@tcd.ie>
+
+ Backport: Fix some tree-sitter :match regexps
+
+ This was originally installed on 2023-06-17 in the emacs-29 release
+ branch and later reverted. This backport follows the Emacs 29.1
+ release (bug#64019).
+
+ The shy groups were caught by modified versions of the GNU ELPA
+ packages xr and relint:
+ - https://github.com/mattiase/xr/pull/6
+ - https://github.com/mattiase/relint/pull/14
+
+ * lisp/progmodes/ruby-ts-mode.el (ruby-ts--s-p-query): Quote special
+ character in regexp.
+ * lisp/progmodes/java-ts-mode.el (java-ts-mode--font-lock-settings):
+ * lisp/progmodes/js.el (js--plain-method-re):
+ (js--treesit-font-lock-settings):
+ * lisp/progmodes/rust-ts-mode.el (rust-ts-mode--font-lock-settings):
+ * lisp/progmodes/typescript-ts-mode.el
+ (typescript-ts-mode--font-lock-settings): Replace character
+ alternative [\\d], which matches '\' or 'd', with the most likely
+ intention [0-9]. Fix shy groups mistyped as optional colons.
+ Remove unneeded numbered :match group in rust-ts-mode.
+
+ (cherry picked from commit cd8d3f3379ec7179fac4bb8e9c40658be15a64f6)
+
+2023-07-30 Po Lu <luangruo@yahoo.com>
+
+ Fix bug#64923
+
+ * src/xfns.c (Fx_create_frame): Prevent cairo surface from being
+ left without a desired size. (bug#64923)
+
+2023-07-30 Ulrich Müller <ulm@gentoo.org>
+
+ Avoid spurious whitespace in the modeline of emacsclient frames
+
+ * lisp/bindings.el (mode-line-client): Compute 'help-echotext
+ property in advance. (Bug#58183)
+
+ (cherry picked from commit 8c3338f6ba354218aee12c223d778be4180f892b)
+
+2023-07-30 Mattias Engdegård <mattiase@acm.org>
+
+ Fix function help for advised aliases (bug#64797)
+
+ * lisp/help-fns.el (help-fns--analyze-function):
+ For aliases, use the base function name if at the end of the chain.
+ This fixes a regression introduced in d30fde6b0cc.
+
+ Reported by Michael Heerdegen.
+
+ (cherry picked from commit 024bd1f09099ae186442001a75e578638070e296)
+
+2023-07-30 Eli Zaretskii <eliz@gnu.org>
+
+ Avoid crashes due to invalid 'mode-line-format'
+
+ * src/xdisp.c (display_mode_element, redisplay_window_error):
+ Don't take XCAR of what can be Qnil. (Bug#64893)
+
+ (cherry picked from commit 7ea3f39deec3d54914077455e70605a14eb7d200)
+
+2023-07-30 Eli Zaretskii <eliz@gnu.org>
+
+ Avoid crashes under 'which-key-mode'
+
+ * src/keyboard.c (Fthis_single_command_keys): Don't allow calls to
+ Fvector with negative first argument. (Bug#64857)
+
+ (cherry picked from commit 65834b8f8d53402517da7fe2446f5bac0aa30c39)
+
+2023-07-30 Eli Zaretskii <eliz@gnu.org>
+
+ Bump Emacs version
+
+ * README:
+ * configure.ac:
+ * nt/README.W32:
+ * msdos/sed2v2.inp:
+ * etc/NEWS: Bump Emacs version to 29.1.50.
+
+2023-07-29 Vincenzo Pupillo <v.pupillo@gmail.com>
+
+ Update CMake support due to upstream changes (bug#64922)
+
+ A recent change in tree-sitter-cmake grammar support for CMake (commit
+ fe9b5e0), now put arguments are wrapped in a new argument_list node.
+ To support the old and new version of the grammar, a new function was
+ added on which string syntax highlighting now depends.
+
+ * lisp/progmodes/cmake-ts-mode.el
+ (cmake-ts-mode--font-lock-compatibility-fe9b5e0): Indent helper
+ function to handle different tree-sitter-cmake version.
+ * lisp/progmodes/cmake-ts-mode.el
+ (cmake-ts-mode--font-lock-settings): Use the new function to handle
+ the new argument_list node.
+
+2023-07-24 Theodor Thornhill <theo@thornhill.no>
+
+ Remove nullptr named node from c++-ts-mode (bug#64818)
+
+ The nullptr node was changed from a named node to an unnamed node
+ upstream[0], which caused font locking to break. As this is a small
+ enough regression, no compat code is required.
+
+ * lisp/progmodes/c-ts-mode.el (c-ts-mode--font-lock-settings): Remove
+ node no longer in use.
+
+ [0]:
+ https://github.com/tree-sitter/tree-sitter-c/commit/c75868f8b508ae32a0c8490da91bb31b2b96430e
+
+2023-07-24 Theodor Thornhill <theo@thornhill.no>
+
+ Make compat check also check typescript
+
+ * lisp/progmodes/typescript-ts-mode.el
+ (tsx-ts-mode--font-lock-compatibility-bb1f97b):
+ Add argument so that we run the 'treesit-query-capture' when the
+ language is 'typescript', not only 'tsx'.
+
+ * lisp/progmodes/typescript-ts-mode.el
+ (typescript-ts-mode--font-lock-settings): Use supplied argument.
+
+2023-07-23 Eli Zaretskii <eliz@gnu.org>
+
+ Update HISTORY and ChangeLog.4
+
+ * etc/HISTORY:
+ * ChangeLog.4: Update for the Emacs 29.1 release.
+
2023-07-30 Eli Zaretskii <eliz@maintain0p.gnu.org>
* Version 29.1 released.
@@ -174,7 +2155,7 @@
selection from hanging owner, we will proceed to take ownership of the
selection as normal, resolving the problem.
- (One example of a selction owner that might not be responding to
+ (One example of a selection owner that might not be responding to
selection requests is another instance of Emacs itself; while Emacs is
blocked in call-process or Lisp execution, it currently does not
respond to selection requests.)
@@ -1069,7 +3050,7 @@
Revert changes to the order in which package descs are loaded
* lisp/emacs-lisp/package.el (package-load-all-descriptors): Remove
- NOSORT argument to 'directory-files', reverting back to the behaviour
+ NOSORT argument to 'directory-files', reverting back to the behavior
as of Emacs 28. (Bug#63757)
2023-06-04 Spencer Baugh <sbaugh@janestreet.com>
@@ -1252,7 +3233,7 @@
(plstore-save, plstore--encode, plstore--decode)
(plstore--write-contents-functions, plstore-mode-decoded)
(plstore-mode): Brush up doc strings and documentation in general.
- Fix terminology, in particular spurious occurences of all uppercase
+ Fix terminology, in particular spurious occurrences of all uppercase
"PLSTORE". (Bug#63627)
2023-05-31 Jens Schmidt <jschmidt4gnu@vodafonemail.de>
@@ -2217,7 +4198,7 @@
Prevent generating empty autoload files
* lisp/emacs-lisp/loaddefs-gen.el (loaddefs-generate): Remove
- optimisation that would mistakenly discard old loaddefs in case a file
+ optimization that would mistakenly discard old loaddefs in case a file
was not modified by EXTRA-DATA is non-nil. (Bug#62734)
2023-04-30 Stefan Monnier <monnier@iro.umontreal.ca>
@@ -3434,7 +5415,7 @@
2023-03-29 Andrea Corallo <akrl@sdf.org>
- Comp fix calls to redefined primtives with op-bytecode (bug#61917)
+ Comp fix calls to redefined primitives with op-bytecode (bug#61917)
* test/src/comp-tests.el (61917-1): New test.
* src/comp.c (syms_of_comp): New variable.
@@ -3472,7 +5453,7 @@
2023-03-28 Andrea Corallo <akrl@sdf.org>
- Revert "Comp fix calls to redefined primtives with op-bytecode (bug#61917)"
+ Revert "Comp fix calls to redefined primitives with op-bytecode (bug#61917)"
This reverts commit 263d6c38539691c954f4c3057cbe8d5468499b91.
@@ -3810,10 +5791,10 @@
2023-03-20 Andrea Corallo <akrl@sdf.org>
- Comp fix calls to redefined primtives with op-bytecode (bug#61917)
+ Comp fix calls to redefined primitives with op-bytecode (bug#61917)
* lisp/emacs-lisp/comp.el (comp-emit-set-call-subr): Fix compilation
- of calls to redefined primtives with dedicated op-bytecode.
+ of calls to redefined primitives with dedicated op-bytecode.
* test/src/comp-tests.el (61917-1): New test.
2023-03-20 Robert Pluim <rpluim@gmail.com>
@@ -3933,7 +5914,7 @@
CC Mode: Eliminate duplicate function c-list-of-strings
Replace it with the existing c-string-list-p. Also put an autoload cookie in
- front of c-string-list-p so that it will not be signalled as undefined by
+ front of c-string-list-p so that it will not be signaled as undefined by
loaddefs.el.
lisp/progmodes/cc-vars.el (c-string-list-p): Make this autoload.
@@ -3951,7 +5932,7 @@
(c-font-lock-extra-types, c++-font-lock-extra-types)
(objc-font-lock-extra-types, java-font-lock-extra-types)
(idl-font-lock-extra-types, pike-font-lock-extra-types): Add a :safe entry
- into each of thes defcustoms for c-list-of-string.
+ into each of these defcustoms for c-list-of-string.
(Top level): Add an autoload entry for each of the above.
2023-03-18 Robert Pluim <rpluim@gmail.com>
@@ -3974,7 +5955,7 @@
Enhance section about troubleshooting in Eglot manual.
- * doc/misc/eglot.texi (Troubleshooting Eglot): Parially rewrite.
+ * doc/misc/eglot.texi (Troubleshooting Eglot): Partially rewrite.
2023-03-17 João Távora <joaotavora@gmail.com>
@@ -3984,8 +5965,8 @@
Before this change, it would only work if the user happened to have
manually activated it before with 'yas-global-mode' or somesuch.
- This makes Eglot's Yasnippet-activating behaviour similar to its
- Flymake-activating behaviour.
+ This makes Eglot's Yasnippet-activating behavior similar to its
+ Flymake-activating behavior.
* lisp/progmodes/eglot.el (eglot-client-capabilities): Consult
eglot--stay-out-of.
@@ -4424,7 +6405,7 @@
2023-03-09 João Távora <joaotavora@gmail.com>
- Autoload Eglot helper funtion eglot--debbugs-or-github-bug-uri
+ Autoload Eglot helper function eglot--debbugs-or-github-bug-uri
This isn't a typical autoload: the progn block is plced in the
autoloads file, but the eglot.el file itself isn't loaded as a result
@@ -4638,7 +6619,7 @@
For example, in the 'buffer' category, the default value has the
styles list '(basic substring)'. This means that if a pattern matches
- accoring to the 'basic' style, 'substring' will not be tried. And
+ according to the 'basic' style, 'substring' will not be tried. And
neither will 'completion-styles' which in Fido mode's case happens to
be 'flex'.
@@ -4654,7 +6635,7 @@
* Fix `emacs-lisp-native-compile-and-load' for (bug#61917)
* lisp/progmodes/elisp-mode.el (emacs-lisp-native-compile-and-load):
- Don't load if no compialtion happened.
+ Don't load if no compilation happened.
2023-03-06 Andrea Corallo <akrl@sdf.org>
@@ -4769,7 +6750,7 @@
"unspoffing" HOME just for the invocations of LSP server but it
stopped working a while back. So make it more robust.
- Eventually, we'll want to decide wether these local servers should be
+ Eventually, we'll want to decide whether these local servers should be
considered in 'make check' runs at all, or whether there is a way to
use them with a spoofed HOME.
@@ -4854,7 +6835,7 @@
Fix go-ts-mode multi-line string indentation (bug#61923)
* lisp/progmodes/go-ts-mode.el:
- (go-ts-mode--indent-rules): Add indent rule for multi-line sting.
+ (go-ts-mode--indent-rules): Add indent rule for multi-line string.
2023-03-03 João Távora <joaotavora@gmail.com>
@@ -4954,7 +6935,7 @@
Originally our c-ts-mode--anchor-prev-sibling only specially handled
labeled_statements, now we add special case for preproc in the similar
- fasion: instead of using the preproc directive as anchor, use the last
+ fashion: instead of using the preproc directive as anchor, use the last
statement in that preproc as the anchor. Thus effectively ignore the
preproc.
@@ -5007,7 +6988,7 @@
([XwWebView initWithFrame:configuration:xwidget:])
(nsxwidget_init): Fixed memory leaks: when sending an alloc
message to an object, send an autorelease message to any objects
- we won't explictly release.
+ we won't explicitly release.
([XwWebView webView:didFinishNavigation:]): Second string to
store in 'store_xwidget_event_string' is "load finished" rather
than empty string.
@@ -5677,7 +7658,7 @@
Eglot doesn't always show the LSP :label property of a CompletionItem
in the completion candidates. That is because label is sometimes not
what should be inserted in the buffer in the end, the :insertText
- property supercedes it.
+ property supersedes it.
But the label is usually more suitable for display nevertheless and if
the LSP CompletionItem contains either a snippet or a textEdit, it's
@@ -5739,7 +7720,7 @@
occurs. This is a much simpler mode of operation which may avoid
problems, but is also likely much slower in large buffers.
- Also, because the inlay feature is probably visually suprising to
+ Also, because the inlay feature is probably visually surprising to
some, it is turned OFF by default, which is not the usual practice of
Eglot (at least not when the necessary infrastructure is present).
This decision may be changed soon. Here's a good one-liner for
@@ -5750,7 +7731,7 @@
I haven't tested inlay hints extensively across many LSP servers, so I
would appreciate any testing, both for functional edge cases and
regarding performance. There are possibly more optimization
- oportunities in the "lazy" mode of operation, like more aggressively
+ opportunities in the "lazy" mode of operation, like more aggressively
deleting buffer overlays that are not in visible parts of the buffer.
Though I ended up writing this one from scratch, I want to thank
@@ -5822,9 +7803,9 @@
In that commit, I did what many longstanding issues and users were
suggesting and removed Eglot's override of two Eldoc user
- configuration varibles.
+ configuration variables.
- I verified that Eglot's behaviour would stay mostly unaltered but my
+ I verified that Eglot's behavior would stay mostly unaltered but my
tests were very incomplete. In short there is no way that Eglot can
work acceptably with the default setting of
'eldoc-documentation-strategy', which is
@@ -6227,7 +8208,7 @@
Fix 'display-buffer-use-least-recent-window'
* src/window.c (Fwindow_use_time): Doc fix.
- (Fwindow_bump_use_time): Bump use time of the seleceted window as
+ (Fwindow_bump_use_time): Bump use time of the selected window as
well. Doc fix.
* lisp/window.el (display-buffer-avoid-small-windows): Remove.
@@ -6497,7 +8478,7 @@
2023-02-16 Philip Kaludercic <philipk@posteo.net>
- Attempt to recognise if a VC package has no Elisp files
+ Attempt to recognize if a VC package has no Elisp files
* lisp/emacs-lisp/package-vc.el (package-vc-non-code-file-names): Add
new variable used to avoid false-positives.
@@ -6811,7 +8792,7 @@
package specifications have been having issues with package-vc, when
toggle-on-error is enabled. In their case, package-vc would raise an
error in its first invocation, but it would go on working normally
- afterwards. As this behaviour is confusing and the user can't do much
+ afterwards. As this behavior is confusing and the user can't do much
about a missing elpa-packages.eld to begin with, we satisfy ourselves
with printing out a message and continuing on.
@@ -8335,7 +10316,7 @@
Fix typo in c-ts-mode (bug#60932)
* lisp/progmodes/c-ts-mode.el (c-ts-mode-indent-block-type-regexp):
- enumerator, not enumeratior.
+ enumerator, not enumerator.
2023-01-20 Mike Kupfer <kupfer@rawbw.com>
@@ -9179,7 +11160,7 @@
(treesit_load_language):
(Ftreesit_pattern_expand):
(Ftreesit_query_expand):
- (treesit_eval_predicates): Use new varaibles.
+ (treesit_eval_predicates): Use new variables.
(treesit_check_buffer_size):
(treesit_compose_query_signal_data):
@@ -9918,7 +11899,7 @@
* lisp/progmodes/ruby-ts-mode.el
(ruby-ts-add-log-current-function): Fix the case when point is
- between two methods. 'treesit-node-at' returs the 'def' node of
+ between two methods. 'treesit-node-at' returns the 'def' node of
the method after point in such case, so it behaved like point was
inside the method below.
@@ -10594,7 +12575,7 @@
* doc/lispref/modes.texi (Imenu): Add manual.
* doc/lispref/parsing.texi (Tree-sitter major modes): Update manual.
- * lisp/treesit.el (treesit-simple-imenu-settings): New varaible.
+ * lisp/treesit.el (treesit-simple-imenu-settings): New variable.
(treesit--simple-imenu-1)
(treesit-simple-imenu): New functions.
(treesit-major-mode-setup): Setup Imenu.
@@ -10859,7 +12840,7 @@
(treesit--top-level-defun): Generalize into treesit--top-level-thing.
(treesit--navigate-defun): Generalize into treesit--navigate-thing.
(treesit-thing-at-point): Generalized from treesit-defun-at-point.
- (treesit-defun-at-point): Use treesit-thing-at-point to do tht work.
+ (treesit-defun-at-point): Use treesit-thing-at-point to do the work.
2022-12-25 Philip Kaludercic <philipk@posteo.net>
@@ -11054,7 +13035,7 @@
One way to solve it is to go back up the tree if we are at a leaf node
and still haven't matched the target node. That's too ugly and
finicky so I resorted to recursion. Now one more functions will
- return give up (treesit_node_parent) if we are in a werid parse tree
+ return give up (treesit_node_parent) if we are in a weird parse tree
that is super deep. But since we already kind of give up on this kind
of parse trees (bug#59426), it doesn't really hurt.
@@ -11306,7 +13287,7 @@
2022-12-21 Andrea Corallo <akrl@sdf.org>
- * Invoke spawed Emacs processes with '-Q' when native compiling (bug#60208)
+ * Invoke spawned Emacs processes with '-Q' when native compiling (bug#60208)
* lisp/emacs-lisp/comp.el (comp-final): Invoke spawned Emacs with '-Q'.
(comp-run-async-workers): Likewise.
@@ -11474,7 +13455,7 @@
Repair setopt test after error demotion to warning
* test/lisp/cus-edit-tests.el (test-setopt):
- Check for a warrning instead of an error in attempt to call `setopt`
+ Check for a warning instead of an error in attempt to call `setopt`
with a value that does not match the declared type (bug#60162).
2022-12-18 Dmitry Gutov <dgutov@yandex.ru>
@@ -11542,13 +13523,13 @@
2022-12-18 Philip Kaludercic <philipk@posteo.net>
- * lisp/cus-edit.el (setopt--set): Warn instead of rasing an error
+ * lisp/cus-edit.el (setopt--set): Warn instead of raising an error
(Bug#60162)
2022-12-18 Philip Kaludercic <philipk@posteo.net>
- Allow customising windmove user options with an empty prefix
+ Allow customizing windmove user options with an empty prefix
* lisp/windmove.el (windmove--default-keybindings-type): Handle nil
as a prefix value. (Bug#60161)
@@ -11695,7 +13676,7 @@
Add treesit_assume_true and treesit_cursor_helper
This is part 1 of the change to change node API to cursor API. See
- the second part for more detail. (I splitted the change to make the
+ the second part for more detail. (I split the change to make the
diff more sane.)
* src/treesit.c (treesit_assume_true)
@@ -11879,7 +13860,7 @@
2022-12-16 Eli Zaretskii <eliz@gnu.org>
- Revert "Elide broken but unnecessary `if` optimisations"
+ Revert "Elide broken but unnecessary `if` optimizations"
This reverts commit 13aa376e93564a8cf2ddbbcf0968c6666620db89.
@@ -11893,7 +13874,7 @@
This reverts commit f4b430140f0866f98bbf18b7094348dc64032813.
Please don't install anything on the release branch that is not
- strictly necessary fro Emacs 29.
+ strictly necessary for Emacs 29.
2022-12-16 Mattias Engdegård <mattiase@acm.org>
@@ -11915,7 +13896,7 @@
2022-12-16 Mattias Engdegård <mattiase@acm.org>
- Elide broken but unnecessary `if` optimisations
+ Elide broken but unnecessary `if` optimizations
* lisp/emacs-lisp/byte-opt.el (byte-optimize-if):
Remove explicit clauses purposing to simplify
@@ -12045,7 +14026,7 @@
1. the client code invoked by its jsonrpc--connection-receive inside
the process filter callee immediately sends follow-up input to
process within the same Lisp stack. This is a common scenario,
- especially during LSP initialiation sequence used by Eglot, a
+ especially during LSP initialization sequence used by Eglot, a
jsonrpc.el client.
2. that follow-up message is large enough for process-send-string to
@@ -12461,7 +14442,7 @@
* lisp/emacs-lisp/shortdoc.el (shortdoc--display-function):
If the parameter of :eval is a string then read, evaluate and print
- the result. This was always the intention and is documented behaviour.
+ the result. This was always the intention and is documented behavior.
2022-12-14 Michael Albinus <michael.albinus@gmx.de>
@@ -12579,7 +14560,7 @@
This new set of functions (and tests) should eliminate
defun-navigation bugs and limitations we currently have. This commit
- doesn't change any existing bahavior: treesit-beginning/end-of-defun
+ doesn't change any existing behavior: treesit-beginning/end-of-defun
and friends are unchanged. The plan is to later switch gear and
replace the current functions with the new ones introduced in this
change.
@@ -12796,7 +14777,7 @@
Eglot: allow skipping compile-time warnings about LSP interfaces
* lisp/progmodes/eglot.el (eglot-strict-mode): Add 'no-unknown-interfaces'.
- (eglot--check-object): Honour new eglot-strict-mode value.
+ (eglot--check-object): Honor new eglot-strict-mode value.
2022-12-11 Yuan Fu <casouri@gmail.com>
@@ -13042,7 +15023,7 @@
Bring back the project--value-in-dir logic
- Essentialy revert commit 2389158a31b4a12, restoring the changes
+ Essentially revert commit 2389158a31b4a12, restoring the changes
and fixing the conflicts. Motivated by the problem brought up in
bug#59722 (behavior of project-find-files/regexp when switching
projects). We should find other ways to improve performance.
@@ -13419,10 +15400,10 @@
table.
When the 'external' is in use, the usual styles configured by the user
- or other in 'completion-styles' are completely overriden. This
+ or other in 'completion-styles' are completely overridden. This
relatively minor inconvenience is the price to pay for responsive
completion where the full set of completion candidates doesn't need to
- be transfered into Emacs's address space.
+ be transferred into Emacs's address space.
* lisp/external-completion.el: New file.
@@ -13540,7 +15521,7 @@
2022-12-06 Mattias Engdegård <mattiase@acm.org>
- Lisp reader undefined behaviour excision
+ Lisp reader undefined behavior excision
* src/lread.c (read_bool_vector, skip_lazy_string):
Replace `|` with `||` to explicitly introduce sequence points since
@@ -13687,7 +15668,7 @@
2022-12-03 Mattias Engdegård <mattiase@acm.org>
- Speed up Unicode normalisation tests by a factor of 5
+ Speed up Unicode normalization tests by a factor of 5
After this change, ucs-normalize-tests are still very slow but
somewhat less disastrously so (from 100 to 20 min on this machine).
@@ -13847,10 +15828,10 @@
be as correct as possible we enable using both.
* lisp/progmodes/typescript-ts-mode.el
- (typescript-ts-mode--indent-rules): Change to a function to accomodate
+ (typescript-ts-mode--indent-rules): Change to a function to accommodate
the two languages.
(typescript-ts-mode--font-lock-settings): Change to a function to
- accomodate the two languages.
+ accommodate the two languages.
(typescript-ts-base-mode): Parent mode for typescript-ts-mode
and tsx-ts-mode.
(typescript-ts-mode): Derive from typescript-ts-base-mode and
@@ -14861,7 +16842,7 @@
reverting the current buffer. It made working in remote buffers with
enable-remote-dir-locals non-nil slower, which doesn't seem worth it
for a minor improvement of an infrequent operation. Also less
- compexity overall.
+ complexity overall.
* lisp/progmodes/project.el (project-try-vc, project-files)
(project--vc-list-files, project-ignores, project-buffers):
@@ -14948,7 +16929,7 @@
This fixes bug #59427. We now handle correctly the case when a parenthesis
follows the * which is ambiguously a multiplication or indirection operator.
- Also, we don't recognise a type thus found as a found type - the evidence is
+ Also, we don't recognize a type thus found as a found type - the evidence is
too weak.
* lisp/progmodes/cc-engine.el (c-forward-decl-or-cast-1): Fix CASE 17.5 as
@@ -15865,7 +17846,7 @@
Previously applied heuristic 2 sometimes invalidates heuristic 1, add
a guard so it doesn't.
- The new function is just for clearity of the code and has nothing to
+ The new function is just for clarity of the code and has nothing to
do with the change itself.
* lisp/treesit.el (treesit--node-length): New function
@@ -16399,7 +18380,7 @@
* test/lisp/simple-tests.el
(simple-execute-extended-command--describe-binding-msg):
- Bind text-quoting-style explicitly to ensure consistent behaviour
+ Bind text-quoting-style explicitly to ensure consistent behavior
whether or not the test is run interactively.
2022-11-18 Stefan Kangas <stefankangas@gmail.com>
@@ -16550,7 +18531,7 @@
2022-11-17 Philip Kaludercic <philipk@posteo.net>
- Fix the behaviour of 'byte-compile-ignore-files'
+ Fix the behavior of 'byte-compile-ignore-files'
* lisp/emacs-lisp/bytecomp.el (byte-recompile-directory): Negate the
'string-match-p' check. (Bug#59139)
@@ -16713,7 +18694,7 @@
* lisp/emacs-lisp/package-vc.el (package-vc-repository-store):
Unmention 'package-vc--unpack'.
- (package-vc-install): Unmention 'package-vc--guess-backend' in favour
+ (package-vc-install): Unmention 'package-vc--guess-backend' in favor
of 'package-vc-heuristic-alist'.
2022-11-17 Philip Kaludercic <philipk@posteo.net>
@@ -16755,7 +18736,7 @@
Mark 'package-vc-update' as interactive
* lisp/emacs-lisp/package-vc.el (package-vc--sourced-packages-list):
- Remove function in favour of 'package-vc--read-package-name'.
+ Remove function in favor of 'package-vc--read-package-name'.
(package-vc--read-package-name):
Extract out common functionality.
(package-vc--read-package-desc): Add auxiliary function based on
@@ -16764,7 +18745,7 @@
'package-vc--read-package-desc'.
(package-vc-install): Use 'package-vc--read-package-desc'.
(package-vc-checkout): Use 'package-vc--read-package-desc'.
- (package-vc--read-pkg): Remove in favour of 'package-vc--read-package-desc'.
+ (package-vc--read-pkg): Remove in favor of 'package-vc--read-package-desc'.
(package-vc-refresh): Use 'package-vc--read-package-desc'.
(package-vc-prepare-patch): Use 'package-vc--read-package-desc'.
@@ -16798,7 +18779,7 @@
Handle strings as keys in 'package-vc-ensure-packages'
* lisp/emacs-lisp/package-vc.el (package-vc-ensure-packages): Inter
- sting keys while processing 'package-vc-selected-packages'.
+ string keys while processing 'package-vc-selected-packages'.
As requested by Rudolf Adamkovič.
@@ -18753,10 +20734,10 @@
* doc/lispref/modes.texi (Parser-based Indentation): Update manual.
* lisp/progmodes/js.el (js--treesit-indent-rules): Change all
- occurance of ,js-indent-level to js-indent-level.
+ occurrence of ,js-indent-level to js-indent-level.
* lisp/progmodes/ts-mode.el (ts-mode--indent-rules): Change all
- occurance of ,ts-mode-indent-offset to ts-mode-indent-offset.
+ occurrence of ,ts-mode-indent-offset to ts-mode-indent-offset.
* lisp/treesit.el (treesit-simple-indent-rules): Change docstring.
(treesit-simple-indent): Allow offset to be a variable.
@@ -19050,7 +21031,7 @@
Print "decrypted" rot13 text is buffer is read-only
* lisp/rot13.el (rot13-region): Add fallback if buffer is read-only
- * doc/emacs/rmail.texi (Rmail Rot13): Document new behaviour.
+ * doc/emacs/rmail.texi (Rmail Rot13): Document new behavior.
2022-11-04 Philip Kaludercic <philipk@posteo.net>
@@ -19334,7 +21315,7 @@
* lisp/progmodes/js.el (js--treesit-font-lock-settings)
* lisp/progmodes/ts-mode.el (ts-mode--font-lock-settings): Capture
- commend and strings. Add empty lines.
+ comment and strings. Add empty lines.
2022-11-03 Jim Porter <jporterbugs@gmail.com>
@@ -19758,7 +21739,7 @@
2022-11-01 Gerd Möllmann <gerd@gnu.org>
- Preven a buffer-overflow (bug#58850)
+ Prevent a buffer-overflow (bug#58850)
* src/print.c (print_vectorlike): Don't use sprintf.
@@ -19850,7 +21831,7 @@
* doc/lispref/modes.texi (Parser-based Font Lock): Reflect the change
in manual.
* lisp/font-lock.el (font-lock-fontify-syntactically-function): New
- varaible.
+ variable.
(font-lock-default-fontify-region): Call
font-lock-fontify-syntactically-function rather.
(font-lock-fontify-syntactically-region): Rename to
@@ -20003,7 +21984,7 @@
Unmention :release-rev
(package-vc-desc->spec): Fall back on other archives if a
specification is missing.
- (package-vc-main-file): Add new function, copying the behaviour of
+ (package-vc-main-file): Add new function, copying the behavior of
elpa-admin.el.
(package-vc-generate-description-file): Use 'package-vc-main-file'.
(package-vc-unpack): Handle special value ':last-release'.
@@ -20015,7 +21996,7 @@
* lisp/vc/vc.el (vc-default-last-change): Add default 'last-change'
implementation.
- This attempts to replicate the behaviour of elpa-admin.el's
+ This attempts to replicate the behavior of elpa-admin.el's
"elpaa--get-last-release-commit".
2022-10-30 Damien Cassou <damien@cassou.me>
@@ -21447,10 +23428,10 @@
2022-10-24 Mattias Engdegård <mattiase@acm.org>
- Fix regexp matching with atomic strings and optimised backtracking
+ Fix regexp matching with atomic strings and optimized backtracking
This bug occurs when an atomic pattern is matched at the end of
- a string and the on-failure-keep-string-jump optimisation is
+ a string and the on-failure-keep-string-jump optimization is
in effect, as in:
(string-match "\\'\\(?:ab\\)*\\'" "a")
@@ -21552,7 +23533,7 @@
2022-10-23 Yuan Fu <casouri@gmail.com>
- Change function signiture of treesit search functions
+ Change function signature of treesit search functions
Justification: We want to make the SIDE argument in
treesit-search-forward-goto optional, so I changed it to START.
@@ -21568,7 +23549,7 @@
will probably be used more frequently than ALL anyway.
* doc/lispref/parsing.texi (Retrieving Node): Resolve FIXME and update
- function signitures.
+ function signatures.
* lisp/treesit.el (treesit-search-forward-goto): Change SIDE to
START, swap BACKWARD and ALL.
(treesit-beginning-of-defun)
@@ -21600,7 +23581,7 @@
2022-10-23 Philip Kaludercic <philipk@posteo.net>
- ;Fix typo "pacakge" -> "package"
+ ; Fix typo for "package"
2022-10-23 Philip Kaludercic <philipk@posteo.net>
@@ -21614,7 +23595,7 @@
2022-10-23 Philip Kaludercic <philipk@posteo.net>
- ;Fix typo "heusitic" -> "heuristic"
+ ; Fix typo for "heuristic"
2022-10-23 Philip Kaludercic <philipk@posteo.net>
@@ -22320,7 +24301,7 @@
from an identifier before passing it to c-add-type.
(c-forward-decl-or-cast-1): CASE 3: Do not recognize two consecutive
identifiers as type + variable/function unless certain conditions are met.
- CASE 10: Do not recognize the "type" as a found type unless certain condtions
+ CASE 10: Do not recognize the "type" as a found type unless certain conditions
are met. (Near end): Do not recognize the identifier in a cast as a type
unless certain conditions are met.
@@ -22938,9 +24919,9 @@
Delete the itree_null sentinel node, use NULL everywhere.
- This effort caught a few (already commited) places that were
+ This effort caught a few (already committed) places that were
dereferencing through ITREE_NULL in a confusing way. It makes some
- functions have to check for NULL in more places, but in my experinece
+ functions have to check for NULL in more places, but in my experience
this is worth it from a code clarity point of view.
In doing this I rewrote `interval_tree_remove` completely. There
@@ -23998,7 +25979,7 @@
* src/itree.c (itree_null): Statically initialize itree_null.parent to
NULL. It is never accessed.
(null_is_sane): Assert parent == NULL.
- (interval_tree_remove_fix): Remove unecessary assignments to parent
+ (interval_tree_remove_fix): Remove unnecessary assignments to parent
from node->parent. These were the last places itree_null.parent were
read.
(interval_tree_remove): Avoid an assignment to itree_null.parent
@@ -24161,7 +26142,7 @@
2022-10-10 Yuan Fu <casouri@gmail.com>
- Improve treesit-search-forward-goto so it doens't stuck at EOF
+ Improve treesit-search-forward-goto so it doesn't stuck at EOF
* lisp/treesit.el (treesit-search-forward-goto): Handle the edge case.
@@ -24217,7 +26198,7 @@
Fix tree-sitter build script in admin/notes
- * admin/notes/tree-sitter/build-module/README: Add explaination.
+ * admin/notes/tree-sitter/build-module/README: Add explanation.
* admin/notes/tree-sitter/build-module/build.sh: change
typescript to tsx.
@@ -24323,14 +26304,14 @@
Remove redundant check of the `limit` value.
(interval_node_init): Remove `begin` and `end` args.
(interval_tree_insert): Mark it as static.
- Assert that the new node's `otick` should already be uptodate and its
+ Assert that the new node's `otick` should already be up-to-date and its
new parent as well.
(itree_insert_node): New function.
(interval_tree_insert_gap): Assert the otick of the removed+added nodes
- were uptodate and mark them as uptodate again after adjusting
+ were up-to-date and mark them as up-to-date again after adjusting
their positions.
(interval_tree_inherit_offset): Check that the parent is at least as
- uptodate as the child.
+ up-to-date as the child.
* src/lisp.h (build_overlay): Move to `buffer.h`.
@@ -24355,7 +26336,7 @@
* lisp/simple.el (execute-extended-command--shorter): Compute a
complete list of `commandp' symbols once. This significantly speeds
up complicated cases while the slowdown of simple cases is still
- accetable.
+ acceptable.
2022-10-09 समीर सिंह Sameer Singh <lumarzeli30@gmail.com>
@@ -24438,7 +26419,7 @@
2022-10-08 Mattias Engdegård <mattiase@acm.org>
- Restrict string-lessp vectorisation to safe architectures
+ Restrict string-lessp vectorization to safe architectures
* src/fns.c (HAVE_FAST_UNALIGNED_ACCESS): New.
(Fstring_lessp): Only use word operations where safe, because string
@@ -25128,7 +27109,7 @@
(interval_tree_propagate_limit): Use it.
(null_is_sane): Remove `inline` annotation; it's not needed.
(interval_tree_inherit_offset): Sanity check that `offset` is 0 when
- `otick` is uptodate. Skip the unneeded increments when the offset is 0.
+ `otick` is up-to-date. Skip the unneeded increments when the offset is 0.
(interval_tree_insert_fix): Add sanity check that we indeed have 2 reds.
2022-10-05 Po Lu <luangruo@yahoo.com>
@@ -25277,7 +27258,7 @@
Fix bug in "macintization" of x_draw_glyph_string
* src/nsterm.m (ns_draw_stretch_glyph_string): Restore text decoration
- drawing code ommitted during "macintization" to convert the X function
+ drawing code omitted during "macintization" to convert the X function
into NS code. Reported by Qiantan Hong <qthong@stanford.edu>.
2022-10-04 Filipp Gunbin <fgunbin@fastmail.fm>
@@ -25412,7 +27393,7 @@
Merge from origin/emacs-28
- a78af3018e * src/emacs.c (load_pdump): Propery handle case when execu...
+ a78af3018e * src/emacs.c (load_pdump): Properly handle case when execu...
# Conflicts:
# src/emacs.c
@@ -25448,7 +27429,7 @@
2022-10-04 Andreas Schwab <schwab@linux-m68k.org>
- * src/emacs.c (load_pdump): Propery handle case when executable
+ * src/emacs.c (load_pdump): Properly handle case when executable
wasn't found.
2022-10-04 Alan Mackenzie <acm@muc.de>
@@ -25645,7 +27626,7 @@
* src/xterm.c (x_handle_wm_state): New function.
(handle_one_xevent): Handle window state changes in WM_STATE
- messages, and use them for signalling deiconification.
+ messages, and use them for signaling deiconification.
(bug#58164)
2022-10-03 Stefan Kangas <stefankangas@gmail.com>
@@ -26405,7 +28386,7 @@
Rectify string= documentation
* doc/lispref/strings.texi (Text Comparison): Describe the current
- behaviour since about 20 years back.
+ behavior since about 20 years back.
2022-09-30 Mattias Engdegård <mattiase@acm.org>
@@ -26419,7 +28400,7 @@
Speed up string-lessp further
* src/fns.c (Fstring_lessp): Use the memcmp fast path for ASCII-only
- multibyte strings as well. Specialise loops on argument
+ multibyte strings as well. Specialize loops on argument
multibyteness.
2022-09-30 Lars Ingebrigtsen <larsi@gnus.org>
@@ -26489,7 +28470,7 @@
Remove the per-tree null node
- "make check" shows 0 unexpcted.
+ "make check" shows 0 unexpected.
* src/itree.h (itree_null): Declare extern.
(ITREE_NULL): New macro
@@ -27363,7 +29344,7 @@
"c++-or-c-but-not-both-at-once" server, this commit now breaks that
person's configuration.
- After analysing the entries of this variable, an educated guess was
+ After analyzing the entries of this variable, an educated guess was
made that this situation is rare. If it's not rare, then some change
to the syntax of eglot-server-programs will have to ensue.
@@ -27921,7 +29902,7 @@
variable.
(c-after-change-mark-abnormal-strings): Set c-open-string-opener when an
unbalanced string is detected.
- (c-before-change): Initilize c-open-string-opener to nil, each buffer change.
+ (c-before-change): Initialize c-open-string-opener to nil, each buffer change.
(c-electric-pair-inhibit-predicate): Use the value of c-open-string-opener to
flag an unbalaced string rather than trying to calculate it again.
@@ -28222,7 +30203,7 @@
Make bounding box of 'image-crop' more noticeable
* lisp/image/image-crop.el (image-crop--crop-image-1): Darken the
- selected region to make the bounding-box more noticable in images
+ selected region to make the bounding-box more noticeable in images
which are mostly white (bug#58004).
2022-09-23 Lars Ingebrigtsen <larsi@gnus.org>
@@ -28464,7 +30445,7 @@
Work around rare crash when turning scroll wheel
* src/xterm.c (handle_one_xevent): Don't allow devices to be
- added twice handling hierarcy events.
+ added twice handling hierarchy events.
2022-09-21 Sean Whitton <spwhitton@spwhitton.name>
@@ -29152,7 +31133,7 @@
2022-09-19 Po Lu <luangruo@yahoo.com>
- * Makefile.in: Readd warnings about "git clean -fdx"
+ * Makefile.in: Re-add warnings about "git clean -fdx"
2022-09-19 Po Lu <luangruo@yahoo.com>
@@ -32181,7 +34162,7 @@
Fix (mostly multibyte) issues in sieve-manage.el (Bug#54154)
- The managesieve protocol (s. RFC5804) requires support for (a sightly
+ The managesieve protocol (s. RFC5804) requires support for (a slightly
restricted variant of) UTF-8 in script content and script names. This
commit fixes/improves the handling of multibyte characters.
@@ -32229,7 +34210,7 @@
2022-09-06 Kai Tetzlaff <emacs@tetzco.de>
- Improve robustnes of `sieve-manage-quit' in case of errors
+ Improve robustness of `sieve-manage-quit' in case of errors
* lisp/net/sieve.el (sieve-manage-quit): Avoid killing buffers it's
not supposed to touch (bug#54154).
@@ -32323,7 +34304,7 @@
* lisp/ffap.el (find-file-at-point): Allow people to set
ffap-file-finder again (bug#50279).
- * lisp/ido.el (ido-everywhere): Add an interstitial to fulfil
+ * lisp/ido.el (ido-everywhere): Add an interstitial to fulfill
ffap-file-handler semantics.
2022-09-06 Stefan Kangas <stefankangas@gmail.com>
@@ -33501,7 +35482,7 @@
* lisp/t-mouse.el (gpm-mouse-tty-setup): New function.
(gpm-mouse-mode): Use it as well as `tty-setup-hook`.
* lisp/term/linux.el (terminal-init-linux): Remove gpm-specific code,
- not neded any more.
+ not needed any more.
2022-08-30 Gregory Heytings <gregory@heytings.org>
@@ -34862,7 +36843,7 @@
2022-08-21 Mattias Engdegård <mattiase@acm.org>
- Fix eshell-pipe-broken signalling
+ Fix eshell-pipe-broken signaling
* lisp/eshell/esh-io.el (eshell-output-object-to-target):
Second argument to `signal` should be a list.
@@ -34946,12 +36927,12 @@
2022-08-21 Mattias Engdegård <mattiase@acm.org>
- Update function properties and optimisations
+ Update function properties and optimizations
* lisp/emacs-lisp/byte-opt.el (byte-opt--bool-value-form):
- Recognise boolean identity in aset, put, function-put and puthash.
+ Recognize boolean identity in aset, put, function-put and puthash.
* lisp/emacs-lisp/byte-opt.el (byte-compile-trueconstp):
- Mark more functins as non-nil-returning, including the new
+ Mark more functions as non-nil-returning, including the new
pos-bol and pos-eol.
* lisp/emacs-lisp/byte-opt.el (side-effect-free-fns):
Mark pos-bol and pos-eol as side-effect-free.
@@ -35084,7 +37065,7 @@
2022-08-19 Mattias Engdegård <mattiase@acm.org>
- Move `while` syntax check from optimiser to macroexpand
+ Move `while` syntax check from optimizer to macroexpand
* lisp/emacs-lisp/byte-opt.el (byte-optimize-while): Move check...
* lisp/emacs-lisp/macroexp.el (macroexp--expand-all): ...here.
@@ -35245,7 +37226,7 @@
python.el: Adjustments to Flymake backend
* lisp/progmodes/python.el (python-flymake-command): Advertise
- possiblity to use pylint.
+ possibility to use pylint.
(python-flymake-command-output-pattern): Make compatible with recent
versions of pyflakes. (Bug#53913)
@@ -35496,7 +37477,7 @@
2022-08-18 Mattias Engdegård <mattiase@acm.org>
- More non-nil-returning functions in source optimisation
+ More non-nil-returning functions in source optimization
This change was partially generated and mechanically cross-validated
with function type information from comp-known-type-specifiers in
@@ -35804,7 +37785,7 @@
2022-08-16 Mattias Engdegård <mattiase@acm.org>
- Improved `null` (alias `not`) optimisation
+ Improved `null` (alias `not`) optimization
Take static boolean information of the argument into account.
@@ -35812,7 +37793,7 @@
2022-08-16 Mattias Engdegård <mattiase@acm.org>
- Improved `and` and `or` optimisation
+ Improved `and` and `or` optimization
* lisp/emacs-lisp/byte-opt.el (byte-optimize-and, byte-optimize-or):
Rewrite. Avoid branching on arguments statically known to be true or
@@ -35820,9 +37801,9 @@
2022-08-16 Mattias Engdegård <mattiase@acm.org>
- Improved `if` and `while` optimisation
+ Improved `if` and `while` optimization
- Recognise some more special cases:
+ Recognize some more special cases:
(if X nil t) -> (not X)
(if X t) -> (not (not X))
@@ -36538,7 +38519,7 @@
Make htmlfontify-version variable obsolete
- * lisp/htmlfontify.el (htmlfontify-version): Make obolete.
+ * lisp/htmlfontify.el (htmlfontify-version): Make obsolete.
(hfy-meta-tags): Don't use above obsolete variable.
2022-08-13 Stefan Kangas <stefan@marxist.se>
@@ -36564,7 +38545,7 @@
2022-08-13 Po Lu <luangruo@yahoo.com>
- Prevent selection converter from signalling if buffer is narrowed
+ Prevent selection converter from signaling if buffer is narrowed
* lisp/select.el (xselect-convert-to-string): If positions are
outside the accessible portion of the buffer, don't return
@@ -36999,7 +38980,7 @@
Add "send patches" note to package-vc TODO section
- * package.el (describe-package-1): Add news if avaliable
+ * package.el (describe-package-1): Add news if available
* package.el (package--get-activatable-pkg): Prefer source packages
@@ -37120,14 +39101,14 @@
2022-08-10 Mattias Engdegård <mattiase@acm.org>
- Extend LAP optimisations to more operations
+ Extend LAP optimizations to more operations
Extend the set of eligible opcodes for certain peephole
- transformations, which then provide further optimisation
+ transformations, which then provide further optimization
opportunities.
* lisp/emacs-lisp/byte-opt.el (byte-optimize-lapcode):
- Optimise empty save-current-buffer in the same way as we already
+ Optimize empty save-current-buffer in the same way as we already
do for save-excursion and save-restriction. This is safe
because (save-current-buffer) is a no-op.
(byte-compile-side-effect-and-error-free-ops): Add list3, list4 and
@@ -38903,7 +40884,7 @@
* lisp/auth-source.el (auth-source-netrc-parse-all): New function
(bug#56976).
- (auth-source-netrc-parse): Partially revert behaviour in previous
+ (auth-source-netrc-parse): Partially revert behavior in previous
change -- require :allow-null to match.
2022-08-04 Lars Ingebrigtsen <larsi@gnus.org>
@@ -38919,7 +40900,7 @@
* lisp/emacs-lisp/package.el
(package-autoload-ensure-default-file): Don't warn about
- soon-to-be obsolete functon.
+ soon-to-be obsolete function.
2022-08-04 Lars Ingebrigtsen <larsi@gnus.org>
@@ -39209,7 +41190,7 @@
Adjust src/Makefile.in comments about make-docfile
- * src/Makefile.in ($(etc)/DOC): Remove comment aboout make-docfile
+ * src/Makefile.in ($(etc)/DOC): Remove comment about make-docfile
being run twice (because it no longer is).
2022-08-04 Po Lu <luangruo@yahoo.com>
@@ -39263,7 +41244,7 @@
Avoid redundant calls to XFlush in x_make_frame_visible
* src/xterm.c (x_make_frame_visible): Keep track of whether or
- not the output buffer was implictly flushed before issuing
+ not the output buffer was implicitly flushed before issuing
XFlush.
2022-08-03 Stefan Monnier <monnier@iro.umontreal.ca>
@@ -39806,7 +41787,7 @@
same key is specified twice. (Bug#56873)
* doc/lispref/keymaps.texi (Creating Keymaps): Document error
- signaling behaviour.
+ signaling behavior.
* test/src/keymap-tests.el (keymap-test-duplicate-definitions): Test
duplicate definition detection.
@@ -40517,7 +42498,7 @@
Remove loaddefs debug code
* lisp/emacs-lisp/loaddefs-gen.el (loaddefs-generate--rubric):
- Remove code inadvertantly checked in.
+ Remove code inadvertently checked in.
2022-07-31 Lars Ingebrigtsen <larsi@gnus.org>
@@ -40848,7 +42829,7 @@
Minor improvements to precision scroll interpolation
* lisp/pixel-scroll.el (pixel-scroll-start-momentum): Bump GC
- cons threshold temporarily. This leads to a very noticable
+ cons threshold temporarily. This leads to a very noticeable
improvement to animation speed.
2022-07-29 Po Lu <luangruo@yahoo.com>
@@ -40973,7 +42954,7 @@
(XTframe_up_to_date): Set FRAME_X_WAITING_FOR_DRAW if bumped.
(handle_one_xevent): Handle frame drawn events.
- * src/xterm.h (struct x_output): New fields for frame dirtyness
+ * src/xterm.h (struct x_output): New fields for frame dirtiness
and vsync.
2022-07-29 Gregory Heytings <gregory@heytings.org>
@@ -41793,7 +43774,7 @@
2022-07-25 Robert Pluim <rpluim@gmail.com>
- Make package-archives URL treatment slighty laxer
+ Make package-archives URL treatment slightly laxer
'package-archives' URLs are expected to end in '/', but we can
cater for people typoing that by using 'url-expand-file-name'.
@@ -42559,7 +44540,7 @@
Merge from origin/emacs-28
- ea44d7ddfc ; * lisp/mail/smtpmail.el (smtpmail-via-smtp): Explain wit...
+ ea44d7ddfc ; * lisp/mail/smtpmail.el (smtpmail-via-smtp): Explain with...
2022-07-20 Po Lu <luangruo@yahoo.com>
@@ -43313,7 +45294,7 @@
2022-07-16 Mattias Engdegård <mattiase@acm.org>
- Optimise `append` calls
+ Optimize `append` calls
Add the transforms
@@ -43336,7 +45317,7 @@
2022-07-16 Mattias Engdegård <mattiase@acm.org>
- Improved cons optimisation
+ Improved cons optimization
* lisp/emacs-lisp/byte-opt.el (byte-optimize-cons):
Add the transform
@@ -43345,10 +45326,10 @@
2022-07-16 Mattias Engdegård <mattiase@acm.org>
- Transform (list) -> nil in source optimiser
+ Transform (list) -> nil in source optimizer
- This optimisation is already done in the code generator but performing
- it at this earlier stage is a useful normalising step that uncovers
+ This optimization is already done in the code generator but performing
+ it at this earlier stage is a useful normalizing step that uncovers
more opportunities.
* lisp/emacs-lisp/byte-opt.el (byte-optimize-list): New.
@@ -43721,7 +45702,7 @@
(xref-backend-definitions): Complicate.
(completion-category-overrides): Register a category and a style here.
(completion-styles-alist): Add eglot--lsp-backend-style style
- (eglot--lsp-backend-style-call): New funtion.
+ (eglot--lsp-backend-style-call): New function.
(eglot--lsp-backend-style-all-completions): New function.
(eglot--lsp-backend-style-try-completion): New function.
@@ -44150,7 +46131,7 @@
2022-07-12 Mattias Engdegård <mattiase@acm.org>
- Better gomoku X colour with bright background
+ Better gomoku X color with bright background
* lisp/play/gomoku.el (gomoku-X): Use blue rather than green for
crosses on bright background for better legibility.
@@ -44174,7 +46155,7 @@
* src/pgtkmenu.c (set_frame_menubar)
* src/xdisp.c (update_menu_bar)
* src/xmenu.c (set_frame_menubar): Remove calls to Qrecompute_lucid_menubar
- contitional on Vlucid_menu_bar_dirty_flag.
+ conditional on Vlucid_menu_bar_dirty_flag.
2022-07-12 Po Lu <luangruo@yahoo.com>
@@ -44948,7 +46929,7 @@
* src/dispextern.h (WITH_NARROWED_BEGV): New macro.
* src/xdisp.c (get_narrowed_begv): New function.
- (init_iterator): Initilize the 'narrowed_begv' field.
+ (init_iterator): Initialize the 'narrowed_begv' field.
(back_to_previous_line_start, get_visually_first_element,
move_it_vertically_backward): Use the new macro.
@@ -45361,7 +47342,7 @@
* src/fns.c (concat_strings): Rename to...
(concat_to_string): ...this.
(concat): Split into concat_to_list and concat_to_vector.
- (concat_to_list, concat_to_vector): New, specialised and
+ (concat_to_list, concat_to_vector): New, specialized and
streamlined from earlier combined code.
(concat2, concat3, Fappend, Fconcat, Fvconcat): Adjust calls.
@@ -46055,7 +48036,7 @@
2022-07-05 Lars Ingebrigtsen <larsi@gnus.org>
- Documnt left/right mwheel events
+ Document left/right mwheel events
* doc/lispref/commands.texi (Misc Events): Document left/right
mwheel events (bug#41722).
@@ -46746,7 +48727,7 @@
2022-07-03 Eli Zaretskii <eliz@gnu.org>
- Implement pseudo-value 'reset' of face attrributes
+ Implement pseudo-value 'reset' of face attributes
* doc/lispref/display.texi (Face Attributes):
* etc/NEWS: Document the new pseudo-value 'reset'.
@@ -47190,7 +49171,7 @@
2022-07-01 Lars Ingebrigtsen <larsi@gnus.org>
- Make time-stamp-tests.el work in a Norwegian language enviroment
+ Make time-stamp-tests.el work in a Norwegian language environment
The short version of names for days/month is not necessary the same as
limiting the string with a #n operator. For instance:
@@ -48178,7 +50159,7 @@
2022-06-30 Lars Ingebrigtsen <larsi@gnus.org>
- Restore temp-buffer-resize-mode behaviour wrt. [back] buttons
+ Restore temp-buffer-resize-mode behavior wrt. [back] buttons
* lisp/help.el (help--window-setup): If temp-buffer-resize-mode, do
the window setup after adding [back] buttons (bug#56306).
@@ -48981,7 +50962,7 @@
2022-06-26 Mattias Engdegård <mattiase@acm.org>
- Optimise away functions in for-effect context
+ Optimize away functions in for-effect context
* lisp/emacs-lisp/byte-opt.el (byte-optimize-form-code-walker):
Turn functions into nil when compiled for-effect since they have no
@@ -48989,7 +50970,7 @@
as the elimination of variable bindings.
`unwind-protect` forms can be treated as plain function call at this
point. In particular, their unwind function argument should be
- not optimised for effect since it's a function.
+ not optimized for effect since it's a function.
2022-06-26 Stefan Monnier <monnier@iro.umontreal.ca>
@@ -49160,7 +51141,7 @@
* lisp/files.el (locate-user-emacs-file): Don't create HOME if it
doesn't exist (bug#47298). This returns us to Emacs 26.3
- behaviour here.
+ behavior here.
2022-06-26 Michael Albinus <michael.albinus@gmx.de>
@@ -49543,7 +51524,7 @@
Bytecode opcode comments update
- This is a cosmetic change only; there is no change in behaviour.
+ This is a cosmetic change only; there is no change in behavior.
* lisp/emacs-lisp/bytecomp.el:
* src/bytecode.c (BYTE_CODES, exec_byte_code):
@@ -50018,7 +51999,7 @@
A trivial optimization and a formatting fix
- * lisp/subr.el (internal--compiler-macro-cXXr): Re-use `head' for `n'.
+ * lisp/subr.el (internal--compiler-macro-cXXr): Reuse `head' for `n'.
Fix indentation and line length.
2022-06-21 Tassilo Horn <tsdh@gnu.org>
@@ -51567,7 +53548,7 @@
2022-06-16 Mattias Engdegård <mattiase@acm.org>
- * src/fns.c (mapcar1): Test types in rough order of likelyhood.
+ * src/fns.c (mapcar1): Test types in rough order of likelihood.
2022-06-16 Mattias Engdegård <mattiase@acm.org>
@@ -51805,7 +53786,7 @@
Improve drag atom computation
- * src/xterm.c (xm_get_drag_window): Avoid leak if error occured
+ * src/xterm.c (xm_get_drag_window): Avoid leak if error occurred
creating drag window. Also use StructureNotifyMask instead of
ButtonPressMask.
(xm_get_drag_atom_1): Update. Make EMACS_DRAG_ATOM a list of
@@ -52129,7 +54110,7 @@
(Ftreesit_query_compile): New function.
(Ftreesit_query_capture): Remove code that creates a query object and
instead either use make_ts_query or use the give compiled query. Free
- the query object conditonally.
+ the query object conditionally.
(syms_of_treesit): New symbol.
2022-06-14 Yuan Fu <casouri@gmail.com>
@@ -52140,7 +54121,7 @@
Add new type treesit-compiled-query
- No intergration/interaction with the new type, just adding it.
+ No integration/interaction with the new type, just adding it.
* lisp/emacs-lisp/cl-preloaded.el (cl--typeof-types): Add new type.
* src/alloc.c (cleanup_vector): Add gc for the new type.
@@ -52161,8 +54142,8 @@
* lisp/emacs-lisp/byte-opt.el (byte-optimize-form-code-walker)
(byte-optimize-let-form, byte-optimize-letX):
* lisp/emacs-lisp/bytecomp.el (byte-compile-unwind-protect):
- Simplify source optimisation and codegen code that can now rely on
- normalised let/let* and unwind-protect forms.
+ Simplify source optimization and codegen code that can now rely on
+ normalized let/let* and unwind-protect forms.
2022-06-14 Mattias Engdegård <mattiase@acm.org>
@@ -52180,14 +54161,14 @@
2022-06-14 Mattias Engdegård <mattiase@acm.org>
- Normalise setq during macro-expansion
+ Normalize setq during macro-expansion
- Early normalisation of setq during macroexpand-all allows later
+ Early normalization of setq during macroexpand-all allows later
stages, cconv, byte-opt and codegen, to be simplified and duplicated
checks to be eliminated.
* lisp/emacs-lisp/macroexp.el (macroexp--expand-all):
- Normalise all setq forms to a sequence of (setq VAR EXPR).
+ Normalize all setq forms to a sequence of (setq VAR EXPR).
Emit warnings if necessary.
* lisp/emacs-lisp/cconv.el (cconv-convert, cconv-analyze-form):
* lisp/emacs-lisp/byte-opt.el (byte-optimize-form-code-walker):
@@ -53034,7 +55015,7 @@
2022-06-10 Po Lu <luangruo@yahoo.com>
- Fix cancelling DND upon a regular X error
+ Fix canceling DND upon a regular X error
* src/xterm.c (x_connection_closed): The display isn't dead upon
a non-IO error, so don't avoid sending messages to clean stuff
@@ -53572,7 +55553,7 @@
Add more super and subscript characters to latin input methods
* lisp/leim/quail/latin-post.el ("latin-postfix", "latin-prefix"): Add
- mssing super and subscript characters. (Bug#55722)
+ missing super and subscript characters. (Bug#55722)
2022-06-08 Robert Pluim <rpluim@gmail.com>
@@ -53906,7 +55887,7 @@
* src/xterm.c (x_defer_selection_requests)
(x_release_selection_requests): New functions.
(x_dnd_begin_drag_and_drop): Use those functions to defer
- selections instead. Fix error signalled when ownership of
+ selections instead. Fix error signaled when ownership of
XdndSelection is lost.
(handle_one_xevent): Likewise.
@@ -54731,7 +56712,7 @@
(dnd-remove-last-dragged-remote-file): Handle list values.
(dnd-begin-file-drag): Fix file name expansion.
(dnd-begin-drag-files): New function.
- * lisp/select.el (xselect-convert-to-filename): Handle mutiple
+ * lisp/select.el (xselect-convert-to-filename): Handle multiple
files
(a vector of file names):.
@@ -54769,7 +56750,7 @@
Use a space since that is clearly what was meant.
?\ at the end of a line (ie, ?\LF) never was well-defined and produced
-1 most of the time, but will soon raise an error (bug#55738).
- This doesn't matter much becaue this variable is unused.
+ This doesn't matter much because this variable is unused.
2022-06-03 Po Lu <luangruo@yahoo.com>
@@ -54832,7 +56813,7 @@
2022-06-02 Po Lu <luangruo@yahoo.com>
- Don't call XSelectInput on a dying display when cancelling drag-and-drop
+ Don't call XSelectInput on a dying display when canceling drag-and-drop
* src/xterm.c (x_dnd_free_toplevels): New argument
`display_alive'.
@@ -54860,7 +56841,7 @@
Make ?\LF generate 10, not -1 (bug#55738)
- The old -1 value was an artefact of the reader implementation.
+ The old -1 value was an artifact of the reader implementation.
* src/lread.c (read_escape): Remove the `stringp` argument; assume
character literal syntax. Never return -1.
@@ -54870,7 +56851,7 @@
2022-06-02 Mattias Engdegård <mattiase@acm.org>
- * src/lread.c (skip_lazy_string): Fix uninitialised variable.
+ * src/lread.c (skip_lazy_string): Fix uninitialized variable.
2022-06-02 Stefan Kangas <stefan@marxist.se>
@@ -56133,7 +58114,7 @@
This fixes bug#55684. There, with a minibuffer-only frame at start up,
Emacs tried to switch to this frame, whose selected window was the
mini-window. There is no other active window in this frame, so the
- attempt to swith to another window failed.
+ attempt to switch to another window failed.
* src/frame.c (do_switch_frame): On switching to a frame whose selected
window is as above, before selecting the most recently used window, check
@@ -56636,7 +58617,7 @@
* lisp/emacs-lisp/bytecomp.el (byte-compile--first-symbol-with-pos)
(byte-compile--warning-source-offset):
- Remove recursion for cdr-traversal of lists, and optimise (bug#55414).
+ Remove recursion for cdr-traversal of lists, and optimize (bug#55414).
2022-05-26 Po Lu <luangruo@yahoo.com>
@@ -57687,7 +59668,7 @@
* src/haiku_support.cc (movement_locker, class EmacsWindow)
(MouseMoved): Delete `movement_locker' and associated hack,
- since it's superseeded by some code in haiku_read_socket.
+ since it's superseded by some code in haiku_read_socket.
(key_map, key_chars, dpy_color_space, popup_track_message)
(alert_popup_value, grab_view, grab_view_locker)
(drag_and_drop_in_progress): Write comments and fix
@@ -58321,7 +60302,7 @@
Also per https://github.com/joaotavora/eglot/issues/957.
- Only actually and eagerly report LSP diagnotics if the user has
+ Only actually and eagerly report LSP diagnostics if the user has
Flymake starting automatically on a timer (flymake-no-changes-timeout
is a number).
@@ -58678,7 +60659,7 @@
decorator dimensions. Update prototypes.
* src/haikufns.c (haiku_update_after_decoration_change): Ask for
- a move frame event and don't do anything if configury is not yet
+ a move frame event and don't do anything if configurable is not yet
complete.
* src/haikuterm.c (haiku_read_socket): Adjust accordingly.
@@ -59069,7 +61050,7 @@
2022-05-15 Lars Ingebrigtsen <larsi@gnus.org>
- Don't freeze Emacs on colour codes in sccs-mode
+ Don't freeze Emacs on color codes in sccs-mode
* lisp/textmodes/css-mode.el (css--font-lock-keywords): Don't
freeze Emacs on #ffffff #ffffff, and be more strict in parsing
@@ -60227,7 +62208,7 @@
2022-05-11 Yoav Marco <yoavm448@gmail.com> (tiny change)
- (sqlite-mode--column-names): Suppport nested parens
+ (sqlite-mode--column-names): Support nested parens
* lisp/sqlite-mode.el (sqlite-mode--column-names): Make parsing
more resilient (bug#55363).
@@ -60423,7 +62404,7 @@
2022-05-10 Lars Ingebrigtsen <larsi@gnus.org>
- Use fields on log-edit headers (which changes `C-a' behaviour)
+ Use fields on log-edit headers (which changes `C-a' behavior)
* lisp/vc/log-edit.el (log-edit-insert-message-template): Fieldify
headers so that `C-a' takes us to the start of the string, not the
@@ -61335,7 +63316,7 @@
2022-05-07 Lars Ingebrigtsen <larsi@gnus.org>
- Improve inferior-python-mode scroll behaviour
+ Improve inferior-python-mode scroll behavior
* lisp/progmodes/python.el (inferior-python-mode): Use
scroll-convervatively instead of trying to do this with a comint
@@ -61400,7 +63381,7 @@
2022-05-07 Yuan Fu <casouri@gmail.com>
- Add tree-sitter intergration
+ Add tree-sitter integration
* configure.ac (HAVE_TREE_SITTER, TREE_SITTER_OBJ): New variables.
(DYNAMIC_LIB_SUFFIX): new variable, I copied code from MODULES_SUFFIX
@@ -64814,7 +66795,7 @@
* doc/misc/info.texi (Search Index): Mention it.
- * lisp/info.el (Info-find-node): Allow not signalling errors.
+ * lisp/info.el (Info-find-node): Allow not signaling errors.
(Info-apropos-matches): Allow taking a regexp.
(info-apropos): Prefix now means looking for a regexp.
@@ -64822,7 +66803,7 @@
Fix indentation in copy-region-as-kill
- * lisp/simple.el (copy-region-as-kill): Fix indendation.
+ * lisp/simple.el (copy-region-as-kill): Fix indentation.
2022-04-21 Lars Ingebrigtsen <larsi@gnus.org>
@@ -65322,11 +67303,11 @@
2022-04-18 Nacho Barrientos <nacho.barrientos@cern.ch> (tiny change)
- Unify local variable initialisation in url-http
+ Unify local variable initialization in url-http
* lisp/url/url-http.el (url-http-chunked-last-crlf-missing): Treat
url-http-chunked-last-crlf-missing as any other buffer variable by
- declaring and initialising it the same way as the other related
+ declaring and initializing it the same way as the other related
ones (bug#54989).
2022-04-18 Lars Ingebrigtsen <larsi@gnus.org>
@@ -65867,7 +67848,7 @@
Make sure the ftcr font driver is used on Haiku when Cairo is enabled
* src/haikufont.c (syms_of_haikufont): [USE_BE_CAIRO]: Make sure
- `ftcr' superseeds `haiku'.
+ `ftcr' supersedes `haiku'.
2022-04-16 Paul Eggert <eggert@cs.ucla.edu>
@@ -66472,7 +68453,7 @@
2022-04-15 Philip Kaludercic <philipk@posteo.net>
- Generalise buffer matching from project.el
+ Generalize buffer matching from project.el
* subr.el (buffer-match): Add function to check if a buffer satisfies
a condition.
@@ -66641,7 +68622,7 @@
* lisp/net/ldap.el (ldap-ldapsearch-args): Change -LL to -LLL to
suppress ldif version output.
(ldap-search-internal): Remove skipping of version output. Remove
- redundand ws skipping.
+ redundant ws skipping.
2022-04-14 Filipp Gunbin <fgunbin@fastmail.fm>
@@ -66957,7 +68938,7 @@
This reverts commit 78f76fe16e2737b40694f82af28d17a90a21ed7b.
The commit made calls to cl-concatenate bug out, since
- autoloading defalises doesn't work very well (bug#54901).
+ autoloading defaliases doesn't work very well (bug#54901).
2022-04-12 Po Lu <luangruo@yahoo.com>
@@ -67177,10 +69158,10 @@
2022-04-12 Olaf Trygve Berglihn <olafb@pvv.org> (tiny change)
- Add biblatex alias entry types for compability with bibtex
+ Add biblatex alias entry types for compatibility with bibtex
* lisp/textmodes/bibtex.el (bibtex-biblatex-entry-alist): Add
- biblatex alias entry types for compability with bibtex (bug#54877).
+ biblatex alias entry types for compatibility with bibtex (bug#54877).
2022-04-12 Lars Ingebrigtsen <larsi@gnus.org>
@@ -67197,7 +69178,7 @@
* src/xterm.c (x_dnd_cleanup_drag_and_drop): Always free DND
targets even if waiting for finish.
(x_dnd_begin_drag_and_drop): Free targets correctly when
- signalling error and prevent activating drag-and-drop inside a
+ signaling error and prevent activating drag-and-drop inside a
menu or popup. (It doesn't work.)
2022-04-12 Michael Albinus <michael.albinus@gmx.de>
@@ -67320,10 +69301,10 @@
2022-04-11 Mattias Engdegård <mattiase@acm.org>
- Recognise hybrid IPv6/IPv4 addresses in textsec (bug#54624)
+ Recognize hybrid IPv6/IPv4 addresses in textsec (bug#54624)
* lisp/international/textsec.el (textsec--ipvx-address-p):
- Recognise hybrid addresses like "::ffff:129.55.2.201".
+ Recognize hybrid addresses like "::ffff:129.55.2.201".
Combine to a single regexp and translate to rx.
Remove some regexp ambiguity (relint complaint).
* test/lisp/international/textsec-tests.el (test-suspiction-domain):
@@ -67647,7 +69628,7 @@
Fix DND leave events not being sent to toplevel after returning frame
* src/xterm.c (x_dnd_update_state, handle_one_xevent): Make sure
- to send leave events to the previous toplevel when cancelling to
+ to send leave events to the previous toplevel when canceling to
return a frame.
2022-04-08 Po Lu <luangruo@yahoo.com>
@@ -68166,7 +70147,7 @@
* src/xterm.c (x_dnd_begin_drag_and_drop): Verify
x_dnd_movement_x and x_dnd_movement_y are wholenums before
- caling posn-at-x-y.
+ calling posn-at-x-y.
2022-04-07 Po Lu <luangruo@yahoo.com>
@@ -68259,7 +70240,7 @@
like server latency), then Flymake sometimes doesn't request any
diagnostics at all.
- The reason for the Flymake behaviour wasn't investigated, but that
+ The reason for the Flymake behavior wasn't investigated, but that
wasn't a very good solution either
Rather this change makes it so that when such a Flymake request comes
@@ -68754,7 +70735,7 @@
Reduce GC mark-phase recursion by using explicit stack (bug#54698)
- An explict stack of objects to be traversed for marking replaces
+ An explicit stack of objects to be traversed for marking replaces
recursion for most common object types: conses, vectors, records, hash
tables, symbols, functions etc. Recursion is still used for other
types but those are less common and thus not as likely to cause a
@@ -68878,7 +70859,7 @@
Rework eglot's mode-line
Mimic flymake by replacing the old menus of the mode-line with
- "context menus". List all usefull commands under the main menu
+ "context menus". List all useful commands under the main menu
(eglot-menu-map), and commands related to LSP debugging under the
project menu (eglot-debug-map).
@@ -68922,7 +70903,7 @@
Since <, <=, > and >= have their own byte-ops, the corresponding
functions are mostly used as arguments to higher-order functions.
- This optimisation is particularly beneficial for sorting, where the
+ This optimization is particularly beneficial for sorting, where the
comparison function is time-critical.
* src/data.c (Flss, Fgtr, Fleq, Fgeq):
@@ -68945,7 +70926,7 @@
Faster `string-lessp` for unibyte arguments
Since this function is commonly used as a sorting predicate
- where it is time-critical, this is a useful optimisation.
+ where it is time-critical, this is a useful optimization.
* src/fns.c (Fstring_lessp): Add fast path for the common case
when both arguments are unibyte.
@@ -69049,7 +71030,7 @@
echo "\\"
* lisp/eshell/esh-util.el (eshell-find-delimiter): Correct docstring
- and treat '\' as an escapeable character when using backslash escapes.
+ and treat '\' as an escapable character when using backslash escapes.
* test/lisp/eshell/eshell-tests.el
(eshell-test/escape-special-quoted): Adapt test.
@@ -69177,7 +71158,7 @@
Fix incorrect usage of XM_DRAG_SIDE_EFFECT
* src/xterm.c (xm_send_top_level_leave_message)
- (handle_one_xevent): Pass corret alt side effects and flags to
+ (handle_one_xevent): Pass correct alt side effects and flags to
XM_DRAG_SIDE_EFFECT.
2022-04-02 Lars Ingebrigtsen <larsi@gnus.org>
@@ -69460,10 +71441,10 @@
* etc/themes/modus-operandi-theme.el:
* etc/themes/modus-vivendi-theme.el: Ensure that the theme is reified
- as expected both at compiletime and runtime.
+ as expected both at compile time and runtime.
* etc/themes/modus-themes.el (require): Require 'cl-lib' and 'subr-x'
- at compiletime.
+ at compile time.
(seq): Require the 'seq' library.
(modus-themes-completion-standard-first-match)
(modus-themes-completion-standard-selected)
@@ -69702,7 +71683,7 @@
* src/pdumper.c (dump_get_max_page_size): Rename from 'dump_get_page_size'.
- * src/pdumper.c: Remove getpagesize.h dependecy.
+ * src/pdumper.c: Remove getpagesize.h dependency.
2022-03-30 Michael Albinus <michael.albinus@gmx.de>
@@ -70137,7 +72118,7 @@
Make sure that the value added to the `read_objects_completed` set is
the one we actually return; previously this wasn't the case for conses
- because of an optimisation (bug#54501).
+ because of an optimization (bug#54501).
Also add a check for vacuous self-references such as #1=#1# instead of
returning a nonsense value from thin air.
@@ -70867,7 +72848,7 @@
by RFC 5322.
When eudc-inline-expansion-format remains set to a list as previously,
- the old behaviour is fully retained.
+ the old behavior is fully retained.
2022-03-22 Lars Ingebrigtsen <larsi@gnus.org>
@@ -71388,7 +73369,7 @@
2022-03-19 Po Lu <luangruo@yahoo.com>
- Improve behaviour of drag-n-drop during window manager operations
+ Improve behavior of drag-n-drop during window manager operations
* src/xterm.c (x_dnd_begin_drag_and_drop): Select for some
events on the root window.
@@ -72089,7 +74070,7 @@
generation of random bignums without using Frem etc.
* src/fns.c (get_random_fixnum): New function.
(Frandom): Use it, and get_random_bignum.
- Be consistent about signalling nonpositive integer arguments;
+ Be consistent about signaling nonpositive integer arguments;
since zero is invalid, Qnatnump is not quite right here.
* src/sysdep.c (get_random_ulong): New function.
@@ -72703,7 +74684,7 @@
This results in better performance, and bytecode recursion is no
longer limited by the size of the C stack. The bytecode stack is
currently of fixed size but overflow is handled gracefully by
- signalling a Lisp error instead of the hard crash that we get now.
+ signaling a Lisp error instead of the hard crash that we get now.
In addition, GC marking of the stack is now faster and more precise.
Full precision could be attained if desired.
@@ -72930,7 +74911,7 @@
Return the same file from locate-file in nativecomp and non
* lisp/files.el (locate-file): Return the .elc file (if it exists)
- in nativecomp, too, to mimic the behaviour from non-nativecomp
+ in nativecomp, too, to mimic the behavior from non-nativecomp
builds (bug#51308).
2022-03-12 Lars Ingebrigtsen <larsi@gnus.org>
@@ -72950,7 +74931,7 @@
2022-03-12 Alexander Adolf <alexander.adolf@condition-alpha.com>
- Facilitate Customisation of Message-Mode Header Completion Behaviour
+ Facilitate Customization of Message-Mode Header Completion Behavior
* lisp/gnus/message.el (message-email-recipient-header-regexp):
New user option.
@@ -72985,7 +74966,7 @@
* src/bytecode.c (FETCH2):
Use `|` instead of `+` to combine the bytes forming a 16-bit immediate
- argument so that GCC (prior to version 12) recognises the idiom and
+ argument so that GCC (prior to version 12) recognizes the idiom and
generates a 16-bit load. This applies for little-endian machines with
cheap unaligned accesses such as x86[-64], arm64 and power64le.
@@ -72993,7 +74974,7 @@
kinds of Lisp code, as 16-bit immediates are used by all jump
instructions.
- Clang performs this optimisation for both `+` and `|` from version 10.
+ Clang performs this optimization for both `+` and `|` from version 10.
2022-03-12 Mattias Engdegård <mattiase@acm.org>
@@ -73303,7 +75284,7 @@
Support remote home directories via connection property
* doc/misc/tramp.texi (Home directories): New section.
- (Top, Usage): Add it to the menue.
+ (Top, Usage): Add it to the menu.
(Predefined connection information): Mention "~".
(Multi-hops, File name syntax): Fix typos.
@@ -73723,7 +75704,7 @@
Merge from origin/emacs-28
73f28fbde8 Add a comment for previous browse-url-of-dired-file change
- 9b74e84857 Restore documented Emacs 27.2 behaviour of browse-url-of-d...
+ 9b74e84857 Restore documented Emacs 27.2 behavior of browse-url-of-d...
cd77fd3b85 Update to Org 9.5.2-24-g668205
2022-03-07 Manuel Giraud <manuel@ledu-giraud.fr>
@@ -73886,7 +75867,7 @@
2022-03-06 Mattias Engdegård <mattiase@acm.org>
- Don't accept whitespace or hex floats in rgbi: colour specs
+ Don't accept whitespace or hex floats in rgbi: color specs
`color-values-from-color-spec` (new in Emacs 28) erroneously accepted
leading whitespace and hex floats in rgbi: components.
@@ -76400,7 +78381,7 @@
Fix SIGFPE on some fonts when calculating their average width on Haiku
- * src/haiku_font_support.cc (estimate_font_ascii): Avoid divison
+ * src/haiku_font_support.cc (estimate_font_ascii): Avoid division
by zero.
2022-02-16 Po Lu <luangruo@yahoo.com>
@@ -76485,7 +78466,7 @@
* src/character.c (count_size_as_multibyte): Move the overflow test
outside the loop, which makes it much faster. Standard compilers
- will even vectorise it if asked to (-O2 in Clang, -O3 in GCC).
+ will even vectorize it if asked to (-O2 in Clang, -O3 in GCC).
2022-02-16 Mattias Engdegård <mattiase@acm.org>
@@ -76713,7 +78694,7 @@
(vc-clone): Declare function for package-unpack.
(package-unpack): Handle source packages.
(package-generate-description-file): Handle source packages by
- ommiting a version number.
+ omitting a version number.
(package-install-from-archive): Check if a package is a source
package.
(package-fetch): Add new command
@@ -76810,7 +78791,7 @@
2022-02-14 Po Lu <luangruo@yahoo.com>
- * etc/TODO: Update some entires related to macOS and NS.
+ * etc/TODO: Update some entries related to macOS and NS.
Xwidgets have worked on NS for a long time, "smooth scrolling"
is now available as `pixel-scroll-precision-mode' for all GUI
@@ -76840,7 +78821,7 @@
2022-02-13 Po Lu <luangruo@yahoo.com>
- Improve efficency of handling DeviceChanged events
+ Improve efficiency of handling DeviceChanged events
* src/xterm.c (handle_one_xevent): Just update the device that
was changed on DeviceChanged and only do hierarchy recalculation
@@ -76993,7 +78974,7 @@
2022-02-12 Po Lu <luangruo@yahoo.com>
- Stop quering for Xinerama inside x_get_monitor_attributes
+ Stop querying for Xinerama inside x_get_monitor_attributes
* src/xfns.c (x_get_monitor_attributes): Remove Xinerama check
and use xinerama_supported_p instead.
@@ -77115,7 +79096,7 @@
specpdl refs has been converted.
We only do this on 64-bit platforms, since those tend to have modern
- ABIs where small structs are optimised as scalars. In other words,
+ ABIs where small structs are optimized as scalars. In other words,
this change should not affect the compiled code.
* src/lisp.h (specpdl_ref): Now a struct on 64-bit platforms.
@@ -77351,7 +79332,7 @@
2022-02-11 Mattias Engdegård <mattiase@acm.org>
- Modernise byte-compilation chapters in manual
+ Modernize byte-compilation chapters in manual
* doc/lispref/compile.texi (Speed of Byte-Code): More representative
numbers for byte code; the difference is much greater today.
@@ -77503,7 +79484,7 @@
Restore command-line--load-script messaging
* lisp/startup.el (command-line--load-script): Restore previous
- non-messaging behaviour.
+ non-messaging behavior.
2022-02-10 Michael Albinus <michael.albinus@gmx.de>
@@ -77700,14 +79681,14 @@
2022-02-09 Po Lu <luangruo@yahoo.com>
- Explictly specify whether or not to respect alpha-background on Cairo
+ Explicitly specify whether or not to respect alpha-background on Cairo
* src/ftcrfont.c (ftcrfont_draw): Don't respect
`alpha-background' if drawing cursor. (bug#53890)
* src/xterm.c (x_set_cr_source_with_gc_foreground):
(x_set_cr_source_with_gc_background): New parameters
`respect_alpha_background'. All callers changed.
- * src/xterm.h: Update protoypes.
+ * src/xterm.h: Update prototypes.
2022-02-09 Tassilo Horn <tsdh@gnu.org>
@@ -77964,7 +79945,7 @@
* src/widget.c (update_wm_hints): Accept frame separately from
the shell widget.
- (widget_update_wm_size_hints): Require WM shell to be explictly
+ (widget_update_wm_size_hints): Require WM shell to be explicitly
specified.
(EmacsFrameRealize):
(EmacsFrameResize): Update callers to `update_wm_hints'.
@@ -78430,7 +80411,7 @@
Add a :distant-foreground to the lazy-highlight face
* lisp/isearch.el (lazy-highlight): Add a :distant-foreground
- colour so that the text is always legible (bug#16969).
+ color so that the text is always legible (bug#16969).
2022-02-05 Lars Ingebrigtsen <larsi@gnus.org>
@@ -78860,7 +80841,7 @@
error will occur in x_composite_image as libXpm will load
pixmaps of depth 16 instead of depth 32.
- * src/image.c (x_create_x_image_and_pixmap): Explictly specify
+ * src/image.c (x_create_x_image_and_pixmap): Explicitly specify
display depth.
(x_create_xrender_picture):
(xpm_load):
@@ -79116,7 +81097,7 @@
of not being in dumping or bootstrap, since it is no longer needed. Test that
'debug-early's symbol-function is bound. Ensure there is enough working space
in specpdl and eval_depth.
- (syms_of_eval): New DEFSYM for Qdebug_early. Initialise Vdebugger to
+ (syms_of_eval): New DEFSYM for Qdebug_early. Initialize Vdebugger to
Qdebug_early rather than Qnil.
2022-02-02 Juri Linkov <juri@linkov.net>
@@ -79188,7 +81169,7 @@
2022-02-02 Po Lu <luangruo@yahoo.com>
- Make behaviour of `mouse-autoselect-window' consistent with X on NS
+ Make behavior of `mouse-autoselect-window' consistent with X on NS
* src/nsterm.m ([EmacsView mouseMoved:]): Ignore if
`selected_window' is a minibuffer window.
@@ -79204,7 +81185,7 @@
2022-02-01 Po Lu <luangruo@yahoo.com>
- Improve behaviour of `mouse-autoselect-window' on Haiku
+ Improve behavior of `mouse-autoselect-window' on Haiku
* src/haikuterm.c (haiku_read_socket): Don't select windows if
the selected window is a minibuffer window or a popup is
@@ -79464,7 +81445,7 @@
We used to store in `load-history` when an autoload is redefined as
a non-autoload and in the `autoload` symbol property we used to store
- the autoload data that used to be used before it got overriden.
+ the autoload data that used to be used before it got overridden.
Instead, store the history of the function definition of
a symbol in its `function-history` symbol property.
@@ -79829,7 +81810,7 @@
Some adjustments to last change
* src/gtkutil.c (xg_set_undecorated): Only set ARGB visual on
- Cairo builds wtihout PGTK.
+ Cairo builds without PGTK.
* src/xfns.c (select_visual): Likewise.
2022-01-29 Håkon Flatval <hkon20@hotmail.com>
@@ -79858,7 +81839,7 @@
2022-01-29 Lars Ingebrigtsen <larsi@gnus.org>
- Modernise the security section in the efaq a bit
+ Modernize the security section in the efaq a bit
* doc/misc/efaq.texi (Security risks with Emacs): Remove the X
bit, and add a bit about browsing the web (bug#24489).
@@ -80496,7 +82477,7 @@
Minor `concat` tweaks
* src/fns.c (concat): Do things in the right order for speed.
- (concat_strings): Initialise variable.
+ (concat_strings): Initialize variable.
2022-01-26 Lars Ingebrigtsen <larsi@gnus.org>
@@ -80667,7 +82648,7 @@
(Fappend, Fvconcat): Adapt to changed signature of concat.
(Fcopy_sequence): Faster implementation for lists, strings, and vectors.
(concat_strings): New.
- (concat): Strip code for string target, simplify, optimise.
+ (concat): Strip code for string target, simplify, optimize.
(Fcopy_alist): Use Fcopy_sequence.
2022-01-25 Lars Ingebrigtsen <larsi@gnus.org>
@@ -81931,7 +83912,7 @@
Make diff--iterate-hunks more resilient
* lisp/vc/diff-mode.el (diff--iterate-hunks): Ignore malformed
- hunks instead of signalling errors (bug#53343).
+ hunks instead of signaling errors (bug#53343).
2022-01-21 Shuguang Sun <shuguang79@qq.com>
@@ -81955,7 +83936,7 @@
than before, for example when a subcommand is concatenated in an
argument.
- * lisp/eshell/esh-cmd.el (eshell--find-subcommands): New fuction.
+ * lisp/eshell/esh-cmd.el (eshell--find-subcommands): New function.
(eshell--invoke-command-directly): Use 'eshell-find-subcommands'.
* test/lisp/eshell/eshell-tests.el
@@ -82681,7 +84662,7 @@
Fix event timestamp generation on Haiku
- * src/haikuterm.c (haiku_read_socket): Use miliseconds for event
+ * src/haikuterm.c (haiku_read_socket): Use milliseconds for event
time.
2022-01-18 Stefan Monnier <monnier@iro.umontreal.ca>
@@ -82868,7 +84849,7 @@
This fixes several issues: tooltips having no right internal
border, reusing tooltips occasionally freezing Emacs, and
- inconsistent behaviour when compared to X.
+ inconsistent behavior when compared to X.
* src/haiku_support.cc (BWindow_resize): Revert a recent change.
(BView_move_frame):
@@ -83314,7 +85295,7 @@
* src/haiku_support.c (be_popup_file_dialog): Reduce idle
processor load by increasing timeout. The timeout is still too
- low to be noticable by the user.
+ low to be noticeable by the user.
2022-01-16 Po Lu <luangruo@yahoo.com>
@@ -83438,7 +85419,7 @@
mechanism.
(byte-compile-function-warn): Replace byte-compile-last-position by a
symbol-with-pos-pos call.
- (compile-defun): Use local variable start-read-position to fulfil purpose of
+ (compile-defun): Use local variable start-read-position to fulfill purpose of
old byte-compile-read-position. Push the just read FORM onto
byte-compile-form-stack.
@@ -83659,7 +85640,7 @@
No longer strip positions from symbols before each use of a form, instead
relying on the low level C routines to do the right thing. Instead strip them
- from miscellaneous places where this is needed. Stip them alson in
+ from miscellaneous places where this is needed. Strip them also in
`function-put'.
Push forms onto byte-compile-form-stack and pop them "by hand" rather than by
@@ -83835,7 +85816,7 @@
* lisp/battery.el (battery-status-function): In Termux, neither
/sys/ or /proc/ are readable on phones that are not rooted. This
- patch makes Emacs verify if they are readable before it attemps
+ patch makes Emacs verify if they are readable before it attempts
reading them (bug#53026).
2022-01-14 Robert Pluim <rpluim@gmail.com>
@@ -83894,7 +85875,7 @@
* lisp/progmodes/python.el (python-shell-send-string-no-output): Don't
let-bind comint-preoutput-filter-functions globally for all comint
- processes. Modify the behaviour of only the current python
+ processes. Modify the behavior of only the current python
process (bug#53219).
2022-01-14 Robert Pluim <rpluim@gmail.com>
@@ -83923,7 +85904,7 @@
Merge from origin/emacs-28
34ca4ff9a5 Fix Edebug specification for inline functions (Bug#53068).
- 3c06c37a8b Remove mention of removed `gnus-treat-play-sounds' variabl...
+ 3c06c37a8b Remove mention of removed `gnus-treat-play-sounds' variable...
2022-01-13 Po Lu <luangruo@yahoo.com>
@@ -84796,7 +86777,7 @@
This was found during the investigation surrounding bug#53136,
but is not directly related.
- * src/filelock.c (lock_if_free): Explictly test err against -1
+ * src/filelock.c (lock_if_free): Explicitly test err against -1
or -2, and reverse sign of system errors on Haiku. (No Haiku
error occupies -1 or -2.)
@@ -85250,7 +87231,7 @@
2022-01-07 Po Lu <luangruo@yahoo.com>
- Disable new input method behaviour by default on X
+ Disable new input method behavior by default on X
* src/xfns.c (supported_xim_styles): Default to STYLE_NONE.
@@ -85837,7 +87818,7 @@
here.
* src/haikufns.c (haiku_visualize_frame):
- (haiku_unvisualize_frame): Sychronize after visibility changes.
+ (haiku_unvisualize_frame): Synchronize after visibility changes.
2022-01-03 Po Lu <luangruo@yahoo.com>
@@ -86577,9 +88558,9 @@
(emit_ctxt_code): Export the global F_SYMBOLS_WITH_POS_ENABLED_RELOC_SYM.
(define_lisp_symbol_with_position, define_GET_SYMBOL_WITH_POSITION): New
functions.
- (Fcomp__init_ctxt): Initialise comp.bool_ptr_type, call the two new
+ (Fcomp__init_ctxt): Initialize comp.bool_ptr_type, call the two new
define_.... functions.
- (load_comp_unit): Initialise **f_symbols_with_pos_enabled_reloc.
+ (load_comp_unit): Initialize **f_symbols_with_pos_enabled_reloc.
* src/fns.c (Fput): Strip positions from symbols in PROPNAME and VALUE.
@@ -87064,7 +89045,7 @@
2021-12-27 Michael Albinus <michael.albinus@gmx.de>
- The temprary "session" collection might not exist in Secret Service
+ The temporary "session" collection might not exist in Secret Service
* doc/misc/auth.texi (Secret Service API):
* test/lisp/net/secrets-tests.el (secrets--test-delete-all-session-items)
@@ -87619,7 +89600,7 @@
Changes:
- structure the result of mm-dissect-buffer of application/pkcs7-mime
- like a multipart mail so there is no loosing of information of
+ like a multipart mail so there is no losing of information of
verification and decryption results which can now be displayed by
gnus-mime-display-security
@@ -87635,7 +89616,7 @@
to print "Encrypted" or "Signed" accordingly in the security button
- adjust mm-possibly-verify-or-decrypt to check for smime-type to ask
- wether to verify or decrypt the part and not to always ask to decrypt
+ whether to verify or decrypt the part and not to always ask to decrypt
- adjust mm-view-pkcs7-decrypt and verify to call mm-sec-status so
success information can be displayed by gnus-mime-display-security
@@ -88011,7 +89992,7 @@
* src/xfns.c (Fx_set_mouse_absolute_pixel_position):
* src/xterm.c (frame_set_mouse_pixel_position): Replace
calls to XWarpPointer with calls to XIWarpPointer with
- the client pointer explictly specified. This avoids the
+ the client pointer explicitly specified. This avoids the
odd situation where the client pointer of the root window
is not the client pointer of the frame.
@@ -88674,7 +90655,7 @@
Remove incorrect byte-hunk-handler for `eval`
- This optimisation is of very limited utility and miscompiles top-level
+ This optimization is of very limited utility and miscompiles top-level
code having the form (eval 'CODE t) by replacing it with CODE which
will then, as things currently stand, be evaluated with dynamic binding.
@@ -90024,7 +92005,7 @@
be860c1385 Fix manual entry of 'quit-restore-window' (Bug#52328)
35a96139df Clarify a comment in xdisp.c
6ba2f028cf Revert "Grep alias `all' shall not match parent directory"
- eb9e33e238 ; * etc/NEWS: Non-nil repeat-keep-prefix is not the defaul...
+ eb9e33e238 ; * etc/NEWS: Non-nil repeat-keep-prefix is not the default...
538fc1d0e0 Fix mode-line display in Calendar mode
# Conflicts:
@@ -91549,14 +93530,14 @@
Remove separators at the beginning and end of the context menu
* lisp/mouse.el (context-menu-map): Remove beginning/end
- seperators (bug#52237).
+ separators (bug#52237).
2021-12-03 Lars Ingebrigtsen <larsi@gnus.org>
Improve how dired-mark-sexp interprets file sizes in non-C locales
* lisp/dired-x.el (dired-x--string-to-number): Try to understand
- localised numbers (with "." separators or the like) (bug#23373).
+ localized numbers (with "." separators or the like) (bug#23373).
2021-12-03 Stefan Kangas <stefan@marxist.se>
@@ -91591,7 +93572,7 @@
2021-12-03 Stefan Kangas <stefan@marxist.se>
- image-mode: Advertize viewing as text less eagerly
+ image-mode: Advertise viewing as text less eagerly
* lisp/image-mode.el (image-text-based-formats): New defcustom.
(image-mode--setup-mode): Don't show message to show image as text
@@ -91735,7 +93716,7 @@
2be090d5d3 ; * ChangeLog.3: Minor fixes.
9963b11bf7 ; * admin/authors.el (authors-aliases): Further updates.
50b40e1d4f ; * lisp/org/ob-julia.el: Fix Author header for authors.el.
- 84166ea2e6 CC Mode: Recognise "struct foo {" as introducing a type de...
+ 84166ea2e6 CC Mode: Recognize "struct foo {" as introducing a type de...
2021-12-02 Lars Ingebrigtsen <larsi@gnus.org>
@@ -91962,7 +93943,7 @@
* lisp/pixel-scroll.el (pixel-scroll-precision-scroll-down)
(pixel-scroll-precision-scroll-up): Take scroll margin into
- accout.
+ account.
2021-12-01 Po Lu <luangruo@yahoo.com>
@@ -92379,7 +94360,7 @@
2021-11-30 Andrea Corallo <akrl@sdf.org>
- Improve native compiler startup circular dependecy prevention mechanism
+ Improve native compiler startup circular dependency prevention mechanism
* src/comp.c (maybe_defer_native_compilation): Update to accumulate
delayed objects in `comp--delayed-sources'.
@@ -92401,7 +94382,7 @@
2021-11-30 Mattias Engdegård <mattiase@acm.org>
- Generalise CPS-conversion let optimisation
+ Generalize CPS-conversion let optimization
* lisp/emacs-lisp/generator.el (cps--transform-1):
Eliminate a temporary for the last of any `let` form, not just for
@@ -92471,7 +94452,7 @@
30553d889d Merge branch 'emacs-28' of git.savannah.gnu.org:/srv/git/e...
ecf3bf66ba Remove problematic characters from modus-themes.org (bug#5...
- de9d27f679 Avoid undefined behaviour when copying part of structure
+ de9d27f679 Avoid undefined behavior when copying part of structure
# Conflicts:
# doc/misc/modus-themes.org
@@ -92944,7 +94925,7 @@
2021-11-29 Andreas Schwab <schwab@linux-m68k.org>
- Avoid undefined behaviour when copying part of structure
+ Avoid undefined behavior when copying part of structure
* src/dispnew.c (copy_row_except_pointers): Don't use address of
subobject as starting point.
@@ -95352,7 +97333,7 @@
* lisp/emacs-lisp/ert.el (ert-batch-backtrace-line-length): Fix
docstring.
- (ert-run-tests-batch): Remove redundand let-binding.
+ (ert-run-tests-batch): Remove redundant let-binding.
(ert-run-tests-interactively): Fix interactive spec.
2021-11-18 Mattias Engdegård <mattiase@acm.org>
@@ -96194,7 +98175,7 @@
Merge from origin/emacs-28
5dbad52 gnus-summary-line-format doc string clarification
- d4536ff Fix follow-scroll-down in a small buffer which starts slightl...
+ d4536ff Fix follow-scroll-down in a small buffer which starts slightly...
2021-11-14 Eli Zaretskii <eliz@gnu.org>
@@ -96354,7 +98335,7 @@
2021-11-13 Michael Albinus <michael.albinus@gmx.de>
- Revert accidential commit in icomplete.el
+ Revert accidental commit in icomplete.el
2021-11-13 Michael Albinus <michael.albinus@gmx.de>
@@ -96420,7 +98401,7 @@
Where c-record-found-types gets "bound" to itself, we postpone the calling of
c-fontify-new-type on possible new found types until these are confirmed by
- the return from the function tentatively finding these types, for exmaple
+ the return from the function tentatively finding these types, for example
c-forward-<>-arglist. We check this "binding" by testing the value of
c-record-found-types.
@@ -98953,7 +100934,7 @@
5e9b4e70ab Fix dbus-test04-register-method on CentOS (Bug#51369)
d96de23510 * lisp/transient.el: Update to package version v0.3.7-11-g...
7343b0d0e4 ; * etc/NEWS: Native compilation is more picky about missi...
- 0d6b2b0b9d ; * etc/PROBLEMS: Move entry about LLVM plugin to the righ...
+ 0d6b2b0b9d ; * etc/PROBLEMS: Move entry about LLVM plugin to the right...
# Conflicts:
# etc/NEWS
@@ -99010,7 +100991,7 @@
(ns_glyph_metrics): Stop escaping names.
(ns_spec_to_descriptor): Fix font descriptor creation for symbolic
- font spec entires.
+ font spec entries.
(ns_descriptor_to_entity): Create entries with the correct symbolic
styles.
@@ -99782,11 +101763,11 @@
2021-11-02 Mattias Engdegård <mattiase@acm.org>
- Optimise (cond) => nil at source level
+ Optimize (cond) => nil at source level
* lisp/emacs-lisp/byte-opt.el (byte-optimize-cond):
- Optimise clause-free `cond`, which can arise from earlier
- transformations. This enables further optimisations.
+ Optimize clause-free `cond`, which can arise from earlier
+ transformations. This enables further optimizations.
* test/lisp/emacs-lisp/bytecomp-tests.el (bytecomp-tests--test-cases):
Add test cases.
@@ -100663,10 +102644,10 @@
2021-10-26 Stefan Kangas <stefan@marxist.se>
- image-dired: Improve mouse behaviour
+ image-dired: Improve mouse behavior
* lisp/image-dired.el (image-dired-thumbnail-mode-map): Improve mouse
- behaviour: ignore dragging, as it currently doesn't do anything
+ behavior: ignore dragging, as it currently doesn't do anything
useful, and make all clicks just select the thumbnail.
(image-dired-mouse-display-image)
(image-dired-mouse-select-thumbnail): Move point to closest image
@@ -100777,7 +102758,7 @@
strings. The code originally set that charset for any server with
literal+ capability, borking all searches on an Exchange server. This
code only sets utf-8 for multibyte search strings in particular, which
- would be borken for Exchange anyway.
+ would be broken for Exchange anyway.
* lisp/gnus/gnus-search.el (gnus-search-imap-search-command): Ensure
we're only doing the literal+ dance for multibyte strings (multibyte
@@ -100952,7 +102933,7 @@
2021-10-24 Lars Ingebrigtsen <larsi@gnus.org>
- Display a message if HMTL rendering takes a long time
+ Display a message if HTML rendering takes a long time
* lisp/net/eww.el (eww-display-html): Display a message if HTML
rendering takes a long time (bug#19776).
@@ -100975,7 +102956,7 @@
This aims to fix the scenario where on jit-lock's first scan of a type, it is
not recognized as such, and only later does this happen. The fontification of
such found types is now done by background scanning in short time slices
- immediately after initialising the mode.
+ immediately after initializing the mode.
* lisp/progmodes/cc-engine.el (c-add-type-1): New function.
(c-add-type): Extract c-add-type-1 from it, and reformulate the mechanism for
@@ -101191,7 +103172,7 @@
Make dired-x-guess-file-name-at-point obsolete
* lisp/dired-x.el (dired-x-guess-file-name-at-point): Make
- obsolete in favour of 'thing-at-point'.
+ obsolete in favor of 'thing-at-point'.
(dired-x-read-filename-at-point): Use 'thing-at-point' instead of
above obsolete function.
@@ -101228,7 +103209,7 @@
* lisp/image-dired.el (exif): Require.
(image-dired-cmd-read-exif-data-program)
(image-dired-cmd-read-exif-data-options)
- (image-dired-get-exif-data): Make obsolete in favour of using
+ (image-dired-get-exif-data): Make obsolete in favor of using
exif.el. This removes a dependency on external exiftool for some
operations.
(image-dired-get-exif-file-name)
@@ -101273,7 +103254,7 @@
This aims to fix the scenario where on jit-lock's first scan of a type, it is
not recognized as such, and only later does this happen. The fontification of
such found types is now done by background scanning in short time slices
- immediately after initialising the mode.
+ immediately after initializing the mode.
* lisp/progmodes/cc-engine.el (c-add-type-1): New function.
(c-add-type): Extract c-add-type-1 from it, and reformulate the mechanism for
@@ -102605,7 +104586,7 @@
Merge from origin/emacs-28
- 47e09d1855 Copy parent face attributes to tab-line-tab-current instea...
+ 47e09d1855 Copy parent face attributes to tab-line-tab-current instead...
d96f8b22c0 Another fix for 'ibuffer-shrink-to-fit' (Bug#7218, Bug#51029)
2021-10-12 Glenn Morris <rgm@gnu.org>
@@ -102937,7 +104918,7 @@
315fe20086 ; * src/Makefile.in (../native-lisp): Add comment.
47cbd103f5 * lisp/bindings.el (mode-line-position): Improve tooltip.
35a752863a * lisp/progmodes/xref.el: Bump the version.
- bbcd8cc1a9 Slight simplificaiton
+ bbcd8cc1a9 Slight simplification
e139dd1b1e Fix doc strings of 2 categories
59782839cb (xref--collect-matches-1): Remove some intermediate alloca...
1c7d056f4d ; Fix two typos where em dash was written as en dash
@@ -103604,7 +105585,7 @@
(term-ansi-face-already-done): Make obsolete
(term--maybe-brighten-color): Remove
(term--color-as-hex): New function
- (term-handle-colors-array): Make obsolete in favour of the new
+ (term-handle-colors-array): Make obsolete in favor of the new
function 'term--handle-colors-list'.
(term--handle-colors-list): New function, that can also handle ANSI
codes 38 and 48.
@@ -104445,7 +106426,7 @@
Use project-files to know which directory watchers to skip
The directory-finding logic is probably a bit slower than using
- eglot--directories-recursively, but since it honours `.gitignores` and
+ eglot--directories-recursively, but since it honors `.gitignores` and
ignores more directories it's much faster overall. And guaranteed to
create less watchers.
@@ -104457,7 +106438,7 @@
2021-05-26 João Távora <joaotavora@gmail.com>
- Hard code an exception to "node_modules" directores
+ Hard code an exception to "node_modules" directories
* eglot.el (eglot--directories-recursively): Fix.
@@ -104852,7 +106833,7 @@
tremendeously slow down the process. But this is only a suspicion.
This commit tries some simple optimizations: if a directory is known
- to be watch-worthy becasue one of its files matched a single glob, no
+ to be watch-worthy because one of its files matched a single glob, no
more files under that directory are tried. This should help somewhat.
Also fixed a bug in 'eglot--files-recursively', though I suspect that
@@ -105265,7 +107246,7 @@
Simplify dir-watching strategy of w/didchangewatchedfiles
Instead of massaging the globPattern to match directories instead of
- files, which is fragile, gather the list of directoris to watch by
+ files, which is fragile, gather the list of directories to watch by
matching the globPattern against every file recursively (except hidden
files and dirs).
@@ -105802,7 +107783,7 @@
Only makes two changes: a deletion of the "// " and a replacement of a
newline with a space character. The second change fooled Eglot's fix
for https://github.com/joaotavora/eglot/issues/259, by making a change similar to the one it is made to detect
- and correct. That fix should taget things that happen on the same
+ and correct. That fix should target things that happen on the same
line, this not being one of those things.
* eglot.el (eglot--after-change): Only apply fix to https://github.com/joaotavora/eglot/issues/259 if
@@ -105916,7 +107897,7 @@
* src/pgtkselect.c:
* src/pgtkselect.h:
* src/pgtkterm.c:
- * src/pgtkterm.h: Update copyright dates - No Funtional Changes
+ * src/pgtkterm.h: Update copyright dates - No Functional Changes
2020-11-23 Yuuki Harano <masm+github@masm11.me>
@@ -106315,7 +108296,7 @@
minimize gtkutil.c differences.
- * src/pgtkterm.h: remove compiletime ifdefs
+ * src/pgtkterm.h: remove compile time ifdefs
* src/gtkutil.h: block out unused decl
@@ -106364,7 +108345,7 @@
* src/gtkutil.c (xg_create_frame_widgets):
- hacky GTK offsets taht will need better calculations
+ hacky GTK offsets that will need better calculations
Get parent frame's editor widget allocation for the offset
@@ -106530,7 +108511,7 @@
2020-11-21 Yuuki Harano <masm+github@masm11.me>
- Make multipdisplay work by limiting selection while enabed
+ Make multipdisplay work by limiting selection while enabled
* src/pgtkterm.c (pgtk_mouse_position):
@@ -106547,12 +108528,12 @@
2020-11-21 Yuuki Harano <masm+github@masm11.me>
- Improve drawing efficency by refactoring code
+ Improve drawing efficiency by refactoring code
* ../src/pgtkterm.c (fill_background, fill_background_by_face)
(x_draw_glyph_string_background, x_draw_glyph_string_bg_rect)
(x_draw_image_glyph_string, x_draw_stretch_glyph_string)
- (pgtk_clear_under_internal_border): Refator duplcate code
+ (pgtk_clear_under_internal_border): Refator duplicate code
更に効率化。
@@ -106868,7 +108849,7 @@
2020-11-21 Yuuki Harano <masm+github@masm11.me>
- Simplify compilaiton condtion
+ Simplify compilation condition
* ../src/menu.c (single_menu_item):
@@ -107240,7 +109221,7 @@
Uses Eldoc's eldoc-documentation-functions variable. In Eldoc v1.0.0
that variable was already available as a way of handling/composing
multiple docstrings from different sources, but it didn't work
- practically with mutiple concurrent async sources. This was fixed in
+ practically with multiple concurrent async sources. This was fixed in
1.1.0, which Eglot now requires.
This fixes the synchronization problems reported in https://github.com/joaotavora/eglot/issues/494 and also
@@ -107486,7 +109467,7 @@
use-package--foo--post-config-hook
This should make config customisations more predictable (for example, spacemacs
- uses these hooks extensively to allow 'layers' to be customised).
+ uses these hooks extensively to allow 'layers' to be customized).
I got rid of the "special" default value for :config, because it doesn't seem to
be treated any differently than nil.
@@ -107584,14 +109565,14 @@
2020-05-02 João Távora <joaotavora@gmail.com>
- Kind of honour eldoc-echo-area-use-multiline-p
+ Kind of honor eldoc-echo-area-use-multiline-p
A reworking of an idea and original implementation by Andrii
Kolomoiets <andreyk.mad@gmail.com>. It doesn't honor it completely
because the semantics for a non-t, non-nil value are tricky. And we
don't always exactly know what the symbol prefix reliably.
- * eglot.el (eglot--update-doc): Kind of honour
+ * eglot.el (eglot--update-doc): Kind of honor
eldoc-echo-area-use-multiline-p.
GitHub-reference: close https://github.com/joaotavora/eglot/issues/443
@@ -108223,7 +110204,7 @@
Support markdown for textdocument/hover ()
- * eglot.el (eglot-client-capabilities): annouce markdown support for hover.
+ * eglot.el (eglot-client-capabilities): announce markdown support for hover.
(eglot--format-markup): Format hover info with Markdown.
Fixes: https://github.com/joaotavora/eglot/issues/328
@@ -108420,7 +110401,7 @@
completion. When the completion is close to done, the :exit-function
is called, to potentially rework the inserted text so that the final
result might be quite different from the proxy (it might be a snippet,
- or even a suprising text edit).
+ or even a surprising text edit).
The most important change in this commit reworks the way the
completion "bounds" are calculated in the buffer. This is the region
@@ -108437,7 +110418,7 @@
https://github.com/microsoft/language-server-protocol/issues/651, we
have no choice but to play along with that inneficient and grotesque
strategy to implement flex-style matching. Like ever in LSP, we do so
- while being backward-compatible to all previously supported behaviour.
+ while being backward-compatible to all previously supported behavior.
* eglot.el (eglot-completion-at-point): rework.
@@ -108448,8 +110429,8 @@
Always filter completions client-side by prefix
Prefix completion is all we get in LSP because there are some servers
- that send *all* completions everytime. This is horrible, but it's the
- currently defined behaviour. See
+ that send *all* completions every time. This is horrible, but it's the
+ currently defined behavior. See
https://github.com/microsoft/language-server-protocol/issues/651.
* eglot.el (eglot-completion-at-point): Use all-completions.
@@ -108603,7 +110584,7 @@
Unbreak elm language server which does use :triggercharacters
Only query completionProvider -> triggerCharacter information if the
- server has provided it. Elm's, and probaly other's, do not provide
+ server has provided it. Elm's, and probably other's, do not provide
it, which doesn't mean they don't support completion.
* eglot.el (eglot-completion-at-point): Check that completion
@@ -109390,7 +111371,7 @@
Use eglot--dbind and eglot--lambda throughout
- The default behaviour of these macros is to be lenient towards servers
+ The default behavior of these macros is to be lenient towards servers
sending unknown keys, which should fix the issue.
* eglot.el (eglot--lsp-interface-alist): Add a bunch of new interfaces.
@@ -109475,7 +111456,7 @@
Support completioncontext to help servers like ccls
- * eglot.el (eglot-client-capabilities): Annouce
+ * eglot.el (eglot-client-capabilities): Announce
textDocument/completion/contextSupport.
(eglot--CompletionParams): New helper.
(eglot-completion-at-point): Use it.
@@ -110043,7 +112024,7 @@
:ensure-system-package was installing packages by running
system-packages-get-command via async-shell-command. This meant that
- system-packages-use-sudo wasn't being honoured.
+ system-packages-use-sudo wasn't being honored.
This patch makes :ensure-system-package use system-packages-install
for all cases, except where a custom install command is supplied, in
@@ -110051,7 +112032,7 @@
This issue was introduced in 9f034a0bcfdd8c4 [https://github.com/jwiegley/use-package/issues/673], as a fix for
[https://github.com/jwiegley/use-package/issues/661]. Prior to that commit, system-packages-use-sudo was being
- honoured.
+ honored.
This patch also fixes a bug where a cons containing a lone symbol in a
list of conses causes nil to used as the package to install.
@@ -110136,7 +112117,7 @@
Ignore extra keys in textdocument/publishdiagnostics ()
- Accoding to the "discussion" in https://reviews.llvm.org/D50571, it
+ According to the "discussion" in https://reviews.llvm.org/D50571, it
was deemed sufficient that VSCode is fine with the non-standard
extension -- jt
@@ -110296,7 +112277,7 @@
* eglot.el (eglot-sync-connect): New defcustom.
(eglot-ensure, eglot): Simplify.
- (eglot--connect): Honour eglot-sync-connect. Complicate
+ (eglot--connect): Honor eglot-sync-connect. Complicate
considerably.
(eglot-connect-timeout): New defcustom.
(Package-requires): Require jsonrpc 1.0.6
@@ -110383,7 +112364,7 @@
requiring command-line invocations that depend on the specific
momentary environment.
- * eglot.el (eglot-server-programs): CONTACT can be a fucntion of no
+ * eglot.el (eglot-server-programs): CONTACT can be a function of no
arguments.
(eglot--guess-contact, eglot--connect): Accept function
CONTACTs.
@@ -110584,7 +112565,7 @@
2018-07-09 João Távora <joaotavora@gmail.com>
- Jsonrpc.el is now a gnu elpa depedency
+ Jsonrpc.el is now a gnu elpa dependency
* Makefile (ELFILES): Don't include jsonrpc.
(jsonrpc-check): Remove target.
@@ -111054,7 +113035,7 @@
Fix indentation f@#$%^ by previous commit
- Courtesy of aggressive-indent-mode... Agressive it is...
+ Courtesy of aggressive-indent-mode... Aggressive it is...
2018-06-09 João Távora <joaotavora@gmail.com>
@@ -111194,7 +113175,7 @@
2018-06-04 João Távora <joaotavora@gmail.com>
- Support purposedly ignoring a server capability
+ Support purposely ignoring a server capability
* eglot.el (eglot-ignored-server-capabilites): New defcustom.
(eglot--server-capable): Use it.
@@ -111491,7 +113472,7 @@
2018-05-26 João Távora <joaotavora@gmail.com>
- Simpify eglot--server-receive
+ Simplify eglot--server-receive
* eglot.el (eglot--obj): Cleanup whitespace.
(eglot--server-receive): Simplify.
@@ -111873,16 +113854,16 @@
Robustify timer handling for eglot--async-request
- This basically cherry-picks an ealier commit for the jsonrpc-refactor
+ This basically cherry-picks an earlier commit for the jsonrpc-refactor
branch:
a2aa1ed..: João Távora 2018-05-18 Robustify timer handling for jrpc-async-request
* jrpc.el (jrpc--async-request): Improve timeout handling. Return a list (ID TIMER)
- (jrpc--request): Protect against user-quits, cancelling timer
+ (jrpc--request): Protect against user-quits, canceling timer
2018-05-19 João Távora <joaotavora@gmail.com>
- Simplify some infrastructure fucntions
+ Simplify some infrastructure functions
* eglot.el (eglot--contact): Simplify docstring.
(eglot--make-process): Simplify.
@@ -111993,7 +113974,7 @@
Instead of introspecting the :params or :result object to discover if
an object is present, and changing the Elisp function call type
- (funcall vs apply) accordingly, alway funcall. It's up to the
+ (funcall vs apply) accordingly, always funcall. It's up to the
application to destructure if it wishes. jrpc-lambda can help with
that and keep the application code simple.
@@ -112292,7 +114273,7 @@
2018-05-10 João Távora <joaotavora@gmail.com>
- Prepare to sumbit to gnu elpa
+ Prepare to submit to gnu elpa
* eglot.el: Update headers.
@@ -112333,7 +114314,7 @@
(eglot--TextDocumentIdentifier)
(eglot--VersionedTextDocumentIdentifier)
(eglot--TextDocumentPositionParams, eglot--TextDocumentItem):
- Renamed from the more verbose eglot--current-buffer-* variante.
+ Renamed from the more verbose eglot--current-buffer-* variant.
(eglot-rename, eglot-imenu, eglot-eldoc-function)
(eglot-completion-at-point, xref-backend-definitions)
(xref-backend-identifier-at-point)
@@ -112426,7 +114407,7 @@
Adjust flymake integration
- When opening a new file (signalling textDocument/didOpen) it makes
+ When opening a new file (signaling textDocument/didOpen) it makes
sense to call the flymake callback (if it exists) with no diagnostics,
just to get rid of that "Wait", since we don't know if later in this
callback cycle the server will ever report new diagnostics.
@@ -112841,9 +114822,9 @@
2018-05-04 João Távora <joaotavora@gmail.com>
- Honour textdocumentsync
+ Honor textdocumentsync
- * eglot.el (eglot--signal-textDocument/didChange): Honour textDocumentSync
+ * eglot.el (eglot--signal-textDocument/didChange): Honor textDocumentSync
2018-05-04 João Távora <joaotavora@gmail.com>
@@ -113243,7 +115224,7 @@
2018-05-02 João Távora <joaotavora@gmail.com>
- Change status to error everytime an error is found
+ Change status to error every time an error is found
* eglot.el (eglot--process-receive): Also set error status.
(eglot--request): Fix a compilation warning.
@@ -114575,7 +116556,7 @@
(next-overlay-change, previous-overlay-change, overlay-put)
(overlay-get, report_overlay_modification, evaporate_overlays)
(init_buffer_once): Adapt to changes and tree data-structure.
- (overlay-lists, overlay-recenter): Funtions are now obsolete, but
+ (overlay-lists, overlay-recenter): Functions are now obsolete, but
kept anyway.
(set_buffer_overlays_before, set_buffer_overlays_after)
(recenter_overlay_lists,fix_start_end_in_overlays,fix_overlays_before)
@@ -115229,7 +117210,7 @@
This means (use-package foopkg :mode (".foo")) will add (".foo"
. foopkg) into auto-mode-alist instead of the broken (".foo" . nil),
- this is more consistent with the behaviour of (use-package foopkg
+ this is more consistent with the behavior of (use-package foopkg
:mode (".foo" ".bar")).
2016-10-31 Noam Postavsky <npostavs@gmail.com>
@@ -115697,12 +117678,12 @@
Merge pull request from waymondo/extend-bind-handler
- Pass in symbol of bind macro, for more extensible re-use of same handler
+ Pass in symbol of bind macro, for more extensible reuse of same handler
GitHub-reference: https://github.com/jwiegley/use-package/issues/259
2015-09-23 Justin Talbott <justin@waymondo.com>
- pass in symbol of bind macro, for more extensible re-use of same handler
+ pass in symbol of bind macro, for more extensible reuse of same handler
related to https://github.com/jwiegley/use-package/issues/258
@@ -116493,7 +118474,7 @@
Lower-priority idle functions are run first. Idle functions with no
specified priority default to 5 and all functions with the same priority
- are run in the order in which they are evaluated, meaning the behaviour
+ are run in the order in which they are evaluated, meaning the behavior
is backwards compatible.
Updated documentation as well.
@@ -116625,7 +118606,7 @@
Merge pull request from aspiers/docs
- Synchronise docs and then remove one copy to prevent future issues.
+ Synchronize docs and then remove one copy to prevent future issues.
GitHub-reference: https://github.com/jwiegley/use-package/issues/78
2014-01-06 Adam Spiers <emacs@adamspiers.org>
@@ -117380,14 +119361,14 @@
This file records repository revisions from
commit f2ae39829812098d8269eafbc0fcb98959ee5bb7 (exclusive) to
-commit 7d1737071fba1fd83039aac34f34f6b90c9579b8 (inclusive).
+commit d9e1605122b4ba70a55f7b168505b7d7f8d2bdd6 (inclusive).
See ChangeLog.3 for earlier changes.
;; Local Variables:
;; coding: utf-8
;; End:
- Copyright (C) 2022 Free Software Foundation, Inc.
+ Copyright (C) 2022, 2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/ChangeLog.android b/ChangeLog.android
index f56c0469408..e86ef7a2a77 100644
--- a/ChangeLog.android
+++ b/ChangeLog.android
@@ -90,10 +90,10 @@
2023-08-02 Po Lu <luangruo@yahoo.com>
- * doc/emacs/android.texi (Android, What is Android?, Android
- Startup, Android File System, Android Environment,Android
- Windowing, Android Fonts, Android Troubleshooting): Improve
- section titles.
+ * doc/emacs/android.texi (Android, What is Android?)
+ (Android Startup, Android File System, Android Environment)
+ (Android Windowing, Android Fonts, Android Troubleshooting):
+ Improve section titles.
(Android Windowing): Describe the relation between keyboard
modifiers reported by Android and those in key events.
@@ -203,6 +203,7 @@
argument NAME.
* src/android.c (android_init_emacs_service): Add new argument.
+
* src/androidvfs.c (android_saf_delete_document)
(android_saf_tree_rmdir, android_saf_file_unlink): Pass name of
file being deleted to `deleteDocument'.
@@ -699,7 +700,7 @@
(build-counter.c): New target. Generate this file using
makecounter.sh upon changes to lisp.mk or shortlisp.
(lisp.mk): Make and load relative to abs_top_builddir.
- (emacs$(EXEEXT)): Adjust acordingly.
+ (emacs$(EXEEXT)): Adjust accordingly.
(mostlyclean): Remove build-counter.c.
2023-07-18 Po Lu <luangruo@yahoo.com>
@@ -734,7 +735,7 @@
prototypes.
* java/org/gnu/emacs/EmacsWindow.java (motionEvent): Set
- cancelation flag in events sent where appropriate.
+ cancellation flag in events sent where appropriate.
* lisp/touch-screen.el (touch-screen-handle-point-update):
Improve treatment of horizontal scrolling near window edges.
@@ -748,7 +749,7 @@
(struct android_touch_event): New field `flags'.
* src/androidterm.c (handle_one_android_event): Report
- cancelation in TOUCHSCREEN_END_EVENTs.
+ cancellation in TOUCHSCREEN_END_EVENTs.
* src/keyboard.c (make_lispy_event): Fix botched merge.
@@ -1004,7 +1005,7 @@
* java/org/gnu/emacs/EmacsWindow.java (Coordinate): New fields
`button' and `id'.
- (<init>): Add new arguments to the construtor.
+ (<init>): Add new arguments to the constructor.
(whatButtonWasIt): Return 0 if the button state has not changed.
(buttonForEvent): New function.
(figureChange): Return the Coordinate object associated to EVENT.
@@ -2383,7 +2384,7 @@
(sfnt_read_avar_table): Fix sequencing problem.
* src/sfntfont.c (sfntfont_setup_interpreter): Don't create
- interpreter for blatently broken fonts.
+ interpreter for blatantly broken fonts.
(sfntfont_open): Avoid specifying redundant blends.
* src/sfnt.c (sfnt_validate_gs): Fix validation of projection
@@ -3465,7 +3466,7 @@
(src/verbose.mk): Depend on verbose.mk.android in srcdir.
(lib/Makefile): Edit srcdir and VPATH to LIB_SRCDIR.
(src/Makefile): Edit -I$$(top_srcdir) to -I../$(srcdir)/lib,
- instead of ommitting it.
+ instead of omitting it.
(clean): Allow ndk-build clean to fail.
* java/Makefile.in (builddir): New variable.
@@ -3713,7 +3714,7 @@
module detection.
* src/android.c (android_run_select_thread): Fix typos.
- (android_run_select_thread): Lock select_mutex before signalling
+ (android_run_select_thread): Lock select_mutex before signaling
condition variable.
(android_select): Unlock event queue mutex prior to waiting for
it.
@@ -4662,7 +4663,7 @@
(ndk_CONFIG_FILES): Export NDK_BUILD_CFLAGS.
* java/AndroidManifest.xml.in: Prevent the Emacs activity from
- being overlayed by the emacsclient wrapper.
+ being overlaid by the emacsclient wrapper.
* java/org/gnu/emacs/EmacsOpenActivity.java (run): Likewise.
(onCreate): Set an appropriate theme on ICS and up.
@@ -5150,7 +5151,7 @@
* m4/ndk-build.m4 (ndk_package_mape): Add package mapping for
sqlite3.
- * src/Makefile.in (SQLITE3_CFLAGS): New substition.
+ * src/Makefile.in (SQLITE3_CFLAGS): New substitution.
(EMACS_CFLAGS): Add that variable.
* src/android.c (android_api_level): New variable.
@@ -5531,7 +5532,7 @@
(touch-screen-precision-scroll): New user option.
(touch-screen-handle-scroll): Use traditional scrolling by
default.
- (touch-screen-handle-touch): Adust format of
+ (touch-screen-handle-touch): Adjust format of
touch-screen-current-tool.
(touch-screen-track-tap): Don't print waiting for events.
(touch-screen-track-drag): Likewise. Also, don't call UPDATE
@@ -5554,7 +5555,7 @@
* lisp/ls-lisp.el (ls-lisp-use-insert-directory-program): Default
to off on Android.
- * src/android.c (android_is_directory): New fucntion.
+ * src/android.c (android_is_directory): New function.
(android_fstatat): Handle directories created by
`android_opendir'.
(android_open): Return meaningful file mode.
@@ -5644,7 +5645,7 @@
* java/org/gnu/emacs/EmacsNative.java (EmacsNative): Make all
event sending functions return long.
- * java/org/gnu/emacs/EmacsPreferencesActivity.java: New fle.
+ * java/org/gnu/emacs/EmacsPreferencesActivity.java: New file.
* java/org/gnu/emacs/EmacsService.java (EmacsService)
(onStartCommand, onCreate, startEmacsService): Start as a
@@ -6309,7 +6310,7 @@
and `detectMouse'.
(struct android_event_queue, android_init_events)
(android_next_event, android_write_event): Remove write limit.
- (android_file_access_p): Handle directories correcty.
+ (android_file_access_p): Handle directories correctly.
(android_close): Fix coding style.
(android_fclose): New function.
(android_init_emacs_service): Initialize new methods.
@@ -7260,7 +7261,7 @@ and those made after the Android port was installed.
;; coding: utf-8
;; End:
- Copyright (C) 2023 Free Software Foundation, Inc.
+ Copyright (C) 2023-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/GNUmakefile b/GNUmakefile
index 014a98ca32e..16064672c65 100644
--- a/GNUmakefile
+++ b/GNUmakefile
@@ -1,6 +1,6 @@
# Build Emacs from a fresh tarball or version-control checkout.
-# Copyright (C) 2011-2023 Free Software Foundation, Inc.
+# Copyright (C) 2011-2024 Free Software Foundation, Inc.
#
# This file is part of GNU Emacs.
#
diff --git a/INSTALL b/INSTALL
index d09216739f6..2aaa02f37d7 100644
--- a/INSTALL
+++ b/INSTALL
@@ -1,5 +1,5 @@
GNU Emacs Installation Guide
-Copyright (C) 1992, 1994, 1996-1997, 2000-2023 Free Software Foundation,
+Copyright (C) 1992, 1994, 1996-1997, 2000-2024 Free Software Foundation,
Inc.
See the end of the file for license conditions.
@@ -495,12 +495,12 @@ shell such as Bash, which uses these variables:
./configure \
CPPFLAGS='-I/foo/myinclude' LDFLAGS='-L/bar/mylib' \
- CFLAGS='-O3' LIBS='-lfoo -lbar'
+ CFLAGS='-Og' LIBS='-lfoo -lbar'
(this is all one shell command). This tells 'configure' to instruct the
preprocessor to look in the '/foo/myinclude' directory for header
files (in addition to the standard directories), instruct the linker
-to look in '/bar/mylib' for libraries, pass the -O3 optimization
+to look in '/bar/mylib' for libraries, pass the -Og optimization
switch to the compiler, and link against libfoo and libbar
libraries in addition to the standard ones.
diff --git a/INSTALL.REPO b/INSTALL.REPO
index ea88842cfa9..77d8153a5a8 100644
--- a/INSTALL.REPO
+++ b/INSTALL.REPO
@@ -98,7 +98,7 @@ never platform-specific.
-Copyright (C) 2002-2023 Free Software Foundation, Inc.
+Copyright (C) 2002-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/Makefile.in b/Makefile.in
index fdd9353e254..5f3227a9ad5 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -1,6 +1,6 @@
### @configure_input@
-# Copyright (C) 1992-2023 Free Software Foundation, Inc.
+# Copyright (C) 1992-2024 Free Software Foundation, Inc.
# This file is part of GNU Emacs.
@@ -421,7 +421,7 @@ advice-on-failure:
sanity-check:
@[ -f .no-advice-on-failure ] && exit 0; true
- @v=`src/emacs${EXEEXT} --batch --eval \
+ @v=`src/emacs${EXEEXT} --batch -Q --eval \
'(progn (defun f (n) (if (= 0 n) 1 (* n (f (- n 1))))) (princ (f 10)))' \
2> /dev/null`; \
[ "X$$v" = "X3628800" ] && exit 0; \
@@ -643,6 +643,7 @@ ifndef NO_BIN_LINK
cd "$(DESTDIR)${bindir}" && $(LN_S_FILEONLY) "$(EMACSFULL)" "$(EMACS)"
endif
else
+ ${INSTALL_DATA} src/emacs.pdmp "$(DESTDIR)${libexecdir}/Emacs.pdmp"
subdir=${ns_appresdir}/site-lisp && ${write_subdir}
rm -rf ${ns_appresdir}/share
endif
@@ -843,6 +844,9 @@ EMACS_ICON=emacs
ifeq (${USE_STARTUP_NOTIFICATION},no)
USE_STARTUP_NOTIFICATION_SED_CMD=-e "/^StartupNotify=true$$/d"
endif
+ifeq ($(HAVE_PGTK),yes)
+USE_WAYLAND_DISPLAY_SED_CMD=-e "s/display=[^ ]*/reuse-frame/"
+endif
install-etc:
umask 022; ${MKDIR_P} "$(DESTDIR)${desktopdir}"
tmp=etc/emacs.tmpdesktop; rm -f $${tmp}; \
@@ -857,6 +861,7 @@ install-etc:
sed -e "/^Exec=/ s|emacsclient|${bindir}/$${client_name}|" \
-e "/^Icon=emacs/ s/emacs/${EMACS_NAME}/" \
$(USE_STARTUP_NOTIFICATION_SED_CMD) \
+ $(USE_WAYLAND_DISPLAY_SED_CMD) \
${srcdir}/etc/emacsclient.desktop > $${tmp}; \
${INSTALL_DATA} $${tmp} "$(DESTDIR)${desktopdir}/$${client_name}.desktop"; \
rm -f $${tmp}
@@ -870,6 +875,7 @@ install-etc:
client_name=`echo emacsclient | sed '$(TRANSFORM)'`${EXEEXT}; \
sed -e "/^Exec=/ s|emacsclient|${bindir}/$${client_name}|" \
-e "/^Icon=emacs/ s/emacs/${EMACS_NAME}/" \
+ $(USE_WAYLAND_DISPLAY_SED_CMD) \
${srcdir}/etc/emacsclient-mail.desktop > $${tmp}; \
${INSTALL_DATA} $${tmp} "$(DESTDIR)${desktopdir}/$${client_name}-mail.desktop"; \
rm -f $${tmp}
diff --git a/README b/README
index 694b3aa4c94..c0b4df650e1 100644
--- a/README
+++ b/README
@@ -1,4 +1,4 @@
-Copyright (C) 2001-2023 Free Software Foundation, Inc.
+Copyright (C) 2001-2024 Free Software Foundation, Inc.
See the end of the file for license conditions.
diff --git a/admin/ChangeLog.1 b/admin/ChangeLog.1
index ed8b148b99b..65f0b94c071 100644
--- a/admin/ChangeLog.1
+++ b/admin/ChangeLog.1
@@ -2577,7 +2577,7 @@
;; coding: utf-8
;; End:
- Copyright (C) 2001-2023 Free Software Foundation, Inc.
+ Copyright (C) 2001-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/admin/MAINTAINERS b/admin/MAINTAINERS
index cea1aa56cde..f59c684e81f 100644
--- a/admin/MAINTAINERS
+++ b/admin/MAINTAINERS
@@ -5,6 +5,11 @@ what parts of the Emacs distribution. The areas can be defined
"arbitrarily", but should provide fairly well-defined boundaries so
that there are not too many ambiguities.
+The (co-)maintainers of Emacs are:
+
+ Eli Zaretskii <eliz@gnu.org>
+ Stefan Kangas <stefankangas@gmail.com>
+
==============================================================================
1. Areas that someone wants to be maintaining (i.e. has a particularly
keen interest in). There's no need to list files where you are
@@ -119,10 +124,6 @@ Ulf Jasper
lisp/net/newsticker.el
test/lisp/net/newsticker-tests.el
- Icalendar
- lisp/calendar/icalendar.el
- test/lisp/calendar/icalendar-tests.el
-
Amin Bandali
ERC
lisp/erc/*
@@ -132,6 +133,8 @@ Andrea Corallo
Lisp native compiler
src/comp.c
lisp/emacs-lisp/comp.el
+ lisp/emacs-lisp/comp-common.el
+ lisp/emacs-lisp/comp-run.el
lisp/emacs-lisp/comp-cstr.el
test/src/comp-*.el
@@ -160,6 +163,69 @@ Po Lu
Haiku battery support in lisp/battery.el
+ The Android port:
+ src/android-asset.h
+ src/android.c
+ src/android-emacs.c
+ src/androidfns.c
+ src/androidfont.c
+ src/androidgui.h
+ src/android.h
+ src/androidmenu.c
+ src/androidselect.c
+ src/androidterm.c
+ src/androidterm.h
+ src/androidvfs.c
+ src/sfnt.c
+ src/sfntfont-android.c
+ src/sfntfont.c
+ src/sfntfont.h
+ src/sfnt.h
+ java/org/gnu/emacs/EmacsActivity.java
+ java/org/gnu/emacs/EmacsApplication.java
+ java/org/gnu/emacs/EmacsClipboard.java
+ java/org/gnu/emacs/EmacsContextMenu.java
+ java/org/gnu/emacs/EmacsCursor.java
+ java/org/gnu/emacs/EmacsDesktopNotification.java
+ java/org/gnu/emacs/EmacsDialogButtonLayout.java
+ java/org/gnu/emacs/EmacsDialog.java
+ java/org/gnu/emacs/EmacsDirectoryEntry.java
+ java/org/gnu/emacs/EmacsDocumentsProvider.java
+ java/org/gnu/emacs/EmacsDrawable.java
+ java/org/gnu/emacs/EmacsDrawLine.java
+ java/org/gnu/emacs/EmacsDrawPoint.java
+ java/org/gnu/emacs/EmacsDrawRectangle.java
+ java/org/gnu/emacs/EmacsFillPolygon.java
+ java/org/gnu/emacs/EmacsFillRectangle.java
+ java/org/gnu/emacs/EmacsFontDriver.java
+ java/org/gnu/emacs/EmacsGC.java
+ java/org/gnu/emacs/EmacsHandleObject.java
+ java/org/gnu/emacs/EmacsHolder.java
+ java/org/gnu/emacs/EmacsInputConnection.java
+ java/org/gnu/emacs/EmacsLauncherPreferencesActivity.java
+ java/org/gnu/emacs/EmacsMultitaskActivity.java
+ java/org/gnu/emacs/EmacsNative.java
+ java/org/gnu/emacs/EmacsNoninteractive.java
+ java/org/gnu/emacs/EmacsOpenActivity.java
+ java/org/gnu/emacs/EmacsPixmap.java
+ java/org/gnu/emacs/EmacsPreferencesActivity.java
+ java/org/gnu/emacs/EmacsSafThread.java
+ java/org/gnu/emacs/EmacsSdk11Clipboard.java
+ java/org/gnu/emacs/EmacsSdk23FontDriver.java
+ java/org/gnu/emacs/EmacsSdk7FontDriver.java
+ java/org/gnu/emacs/EmacsSdk8Clipboard.java
+ java/org/gnu/emacs/EmacsService.java
+ java/org/gnu/emacs/EmacsSurfaceView.java
+ java/org/gnu/emacs/EmacsThread.java
+ java/org/gnu/emacs/EmacsView.java
+ java/org/gnu/emacs/EmacsWindowAttachmentManager.java
+ java/org/gnu/emacs/EmacsWindow.java
+ java/org/gnu/emacs/R.java
+ m4/ndk-build.m4
+ cross
+
+ Android battery support in lisp/battery.el
+
Jim Porter
Eshell
lisp/eshell/*
diff --git a/admin/README b/admin/README
index 37e55005571..c7dec63875a 100644
--- a/admin/README
+++ b/admin/README
@@ -1,4 +1,4 @@
-Copyright (C) 2001-2023 Free Software Foundation, Inc.
+Copyright (C) 2001-2024 Free Software Foundation, Inc.
See the end of the file for license conditions.
diff --git a/admin/admin.el b/admin/admin.el
index 1f4c6986b0e..7fa2727aeb7 100644
--- a/admin/admin.el
+++ b/admin/admin.el
@@ -1,6 +1,6 @@
;;; admin.el --- utilities for Emacs administration -*- lexical-binding: t; -*-
-;; Copyright (C) 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/admin/alloc-colors.c b/admin/alloc-colors.c
index 6bd857e393b..25910ad9148 100644
--- a/admin/alloc-colors.c
+++ b/admin/alloc-colors.c
@@ -1,6 +1,6 @@
/* Allocate X colors. Used for testing with dense colormaps.
-Copyright (C) 2001-2023 Free Software Foundation, Inc.
+Copyright (C) 2001-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/admin/authors.el b/admin/authors.el
index f1c988cc776..9fa8036ff23 100644
--- a/admin/authors.el
+++ b/admin/authors.el
@@ -1,6 +1,6 @@
;;; authors.el --- utility for maintaining Emacs's AUTHORS file -*- lexical-binding: t; -*-
-;; Copyright (C) 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2000-2024 Free Software Foundation, Inc.
;; Author: Gerd Moellmann <gerd@gnu.org>
;; Maintainer: emacs-devel@gnu.org
@@ -78,7 +78,7 @@ files.")
("David M. Koppelman" "David Koppelman")
("David M. Smith" "David Smith" "David M Smith")
("David O'Toole" "David T. O'Toole")
- (nil "dalanicolai")
+ ("Daniel Laurens Nicolai" "dalanicolai")
(nil "deech@deech")
("Deepak Goel" "D. Goel")
("Earl Hyatt" "Earl" "ej32u@protonmail.com")
@@ -90,6 +90,8 @@ files.")
("Etienne Prud’Homme" "Etienne Prud'Homme")
("Fabián Ezequiel Gallina" "Fabian Ezequiel Gallina" "Fabi.n E\\. Gallina")
(nil "felix.*EmacsWiki")
+ (nil "felix\\.dick@web\\.de")
+ ("Felicián Németh" "Felician Nemeth")
(nil "foudfou")
("Francis Litterio" "Fran Litterio")
("Francis J. Wright" "Dr Francis J. Wright" "Francis Wright")
@@ -98,6 +100,8 @@ files.")
("Frederic Pierresteguy" "Fred Pierresteguy")
(nil "^FSF")
("Gerd Möllmann" "Gerd Moellmann")
+ (nil "haqle314")
+ ("Grégoire Jadi" "Gregoire Jadi")
("Hallvard B. Furuseth" "Hallvard B Furuseth" "Hallvard Furuseth")
("Hrvoje Nikšić" "Hrvoje Niksic")
("Ian Dunn" "^Ian D\\>")
@@ -109,6 +113,7 @@ files.")
("J. Alexander Branham" "Alex Branham")
("Jaeyoun Chung" "Jae-youn Chung" "Jae-you Chung" "Chung Jae-youn")
("Jan Djärv" "Jan D\\>" "Jan Djarv")
+ ("Jan Synáček" "Jan Synacek")
("João Távora" "João Tãvora")
("Jay K. Adams" "Jay Adams")
("J.D. Smith" "Jd Smith")
@@ -119,6 +124,7 @@ files.")
("Jeremy Bertram Maitin-Shepard" "Jeremy Maitin-Shepard")
("Jérémy Compostella" "Jeremy Compostella")
("Jimmy Aguilar Mena" "Ergus")
+ ("Jindřich Makovička" "Jindrich Makovicka")
("Johan Bockgård" "Johan Bockgard")
("John F. Carr" "John F Carr")
("John J Foerch" "John Foerch")
@@ -140,6 +146,10 @@ files.")
("Kenichi Handa" "Ken'ichi Handa" "Kenichi HANDA" "K\\. Handa")
("Kevin Greiner" "Kevin J. Greiner")
("Kim F. Storm" "Kim Storm")
+ ("Kjartan Óli Ágústsson" "Kjartan Oli Agustsson")
+ ;; The dash is a kludge, so this contributor is not ignored.
+ ("kobarity-" "kobarity@gmail\\.com")
+ ("Koen van Greevenbroek" "realcomplex" "koenvg@posteo\\.net")
("Kyle Jones" "Kyle E. Jones")
("Lars Magne Ingebrigtsen" "Lars Ingebrigtsen")
(nil "LynX@bk.ru")
@@ -166,6 +176,7 @@ files.")
("Miha Rihtaršič" "Miha Rihtarsic")
("Mikio Nakajima" "Nakajima Mikio")
("Nelson Jose dos Santos Ferreira" "Nelson Ferreira")
+ ("Noah Peart" "noah\\.v\\.peart@gmail\\.com")
("Noorul Islam" "Noorul Islam K M")
;;; ("Tetsurou Okazaki" "OKAZAKI Tetsurou") ; FIXME?
("Óscar Fuentes" "Oscar Fuentes")
diff --git a/admin/automerge b/admin/automerge
index b01e866ab61..e751183f5f4 100755
--- a/admin/automerge
+++ b/admin/automerge
@@ -1,7 +1,7 @@
#!/bin/bash
### automerge - automatically merge the Emacs release branch to master
-## Copyright (C) 2018-2023 Free Software Foundation, Inc.
+## Copyright (C) 2018-2024 Free Software Foundation, Inc.
## Author: Glenn Morris <rgm@gnu.org>
## Maintainer: Stefan Kangas <stefankangas@gmail.com>
diff --git a/admin/build-configs b/admin/build-configs
index 5447a7a3476..74418c5c090 100755
--- a/admin/build-configs
+++ b/admin/build-configs
@@ -1,7 +1,7 @@
#! /usr/bin/perl
# Build Emacs in several different configurations.
-# Copyright (C) 2001-2023 Free Software Foundation, Inc.
+# Copyright (C) 2001-2024 Free Software Foundation, Inc.
# This file is part of GNU Emacs.
diff --git a/admin/charsets/Makefile.in b/admin/charsets/Makefile.in
index efb9106adad..0a3f334a978 100644
--- a/admin/charsets/Makefile.in
+++ b/admin/charsets/Makefile.in
@@ -1,6 +1,6 @@
### @configure_input@
-# Copyright (C) 2015-2023 Free Software Foundation, Inc.
+# Copyright (C) 2015-2024 Free Software Foundation, Inc.
# Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
# National Institute of Advanced Industrial Science and Technology (AIST)
diff --git a/admin/charsets/mapconv b/admin/charsets/mapconv
index 19e2ff8d8f7..91d580e89d1 100755
--- a/admin/charsets/mapconv
+++ b/admin/charsets/mapconv
@@ -1,6 +1,6 @@
#!/bin/sh
-# Copyright (C) 2015-2023 Free Software Foundation, Inc.
+# Copyright (C) 2015-2024 Free Software Foundation, Inc.
# Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
# National Institute of Advanced Industrial Science and Technology (AIST)
diff --git a/admin/charsets/mapfiles/README b/admin/charsets/mapfiles/README
index 30889c9e9ef..81dad59290d 100644
--- a/admin/charsets/mapfiles/README
+++ b/admin/charsets/mapfiles/README
@@ -1,4 +1,4 @@
-Copyright (C) 2009-2023 Free Software Foundation, Inc.
+Copyright (C) 2009-2024 Free Software Foundation, Inc.
Copyright (C) 2009, 2010, 2011
National Institute of Advanced Industrial Science and Technology (AIST)
Registration Number H13PRO009
diff --git a/admin/check-man-pages b/admin/check-man-pages
index 3fb87dd1b89..8f05b75d81c 100755
--- a/admin/check-man-pages
+++ b/admin/check-man-pages
@@ -1,7 +1,7 @@
#!/bin/bash
### check-man-pages - check man pages for errors
-## Copyright (C) 2022-2023 Free Software Foundation, Inc.
+## Copyright (C) 2022-2024 Free Software Foundation, Inc.
## Author: Stefan Kangas <stefankangas@gmail.com>
diff --git a/admin/cus-test.el b/admin/cus-test.el
index c833ddacd84..37ff4a7e9c5 100644
--- a/admin/cus-test.el
+++ b/admin/cus-test.el
@@ -1,6 +1,6 @@
;;; cus-test.el --- tests for custom types and load problems -*- lexical-binding: t; -*-
-;; Copyright (C) 1998, 2000, 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998, 2000, 2002-2024 Free Software Foundation, Inc.
;; Author: Markus Rost <rost@math.uni-bielefeld.de>
;; Created: 13 Sep 1998
diff --git a/admin/diff-tar-files b/admin/diff-tar-files
index 89abc7fa382..9b34d9c4538 100755
--- a/admin/diff-tar-files
+++ b/admin/diff-tar-files
@@ -1,6 +1,6 @@
#!/bin/bash
-# Copyright (C) 2001-2023 Free Software Foundation, Inc.
+# Copyright (C) 2001-2024 Free Software Foundation, Inc.
# This file is part of GNU Emacs.
diff --git a/admin/emacs-shell-lib b/admin/emacs-shell-lib
index 67f76f61300..1c4d895fdb4 100644
--- a/admin/emacs-shell-lib
+++ b/admin/emacs-shell-lib
@@ -1,7 +1,7 @@
#!/bin/bash
### emacs-shell-lib - shared code for Emacs shell scripts
-## Copyright (C) 2022-2023 Free Software Foundation, Inc.
+## Copyright (C) 2022-2024 Free Software Foundation, Inc.
## Author: Stefan Kangas <stefankangas@gmail.com>
diff --git a/admin/emake b/admin/emake
index c9e59d34067..93958740dc2 100755
--- a/admin/emake
+++ b/admin/emake
@@ -1,6 +1,6 @@
#!/bin/bash
-# Copyright (C) 2022-2023 Free Software Foundation, Inc.
+# Copyright (C) 2022-2024 Free Software Foundation, Inc.
# This file is part of GNU Emacs.
diff --git a/admin/find-gc.el b/admin/find-gc.el
index 7cb319d867a..7c5672f4a46 100644
--- a/admin/find-gc.el
+++ b/admin/find-gc.el
@@ -1,6 +1,6 @@
;;; find-gc.el --- detect functions that call the garbage collector -*- lexical-binding: t; -*-
-;; Copyright (C) 1992, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1992, 2001-2024 Free Software Foundation, Inc.
;; Maintainer: emacs-devel@gnu.org
diff --git a/admin/git-bisect-start b/admin/git-bisect-start
index 8eb5328a1a1..069f66515ba 100755
--- a/admin/git-bisect-start
+++ b/admin/git-bisect-start
@@ -2,9 +2,11 @@
### Start a git bisection, ensuring that commits in branches that are
### the result of merging external trees into the Emacs repository, as
-### well as certain commits on which Emacs fails to build, are skipped.
+### well as certain commits on which Emacs fails to build (with the
+### default options, on a GNU/Linux computer and with GCC; see below),
+### are skipped.
-## Copyright (C) 2022-2023 Free Software Foundation, Inc.
+## Copyright (C) 2022-2024 Free Software Foundation, Inc.
## This file is part of GNU Emacs.
@@ -82,7 +84,7 @@ done
# SKIP-BRANCH 58cc931e92ece70c3e64131ee12a799d65409100
## The list below is the exhaustive list of all commits between Dec 1
-## 2016 and Aug 10 2023 on which building Emacs with the default
+## 2016 and Oct 2 2023 on which building Emacs with the default
## options, on a GNU/Linux computer and with GCC, fails. It is
## possible (though unlikely) that building Emacs with non-default
## options, with other compilers, or on other platforms, would succeed
@@ -1776,3 +1778,13 @@ $REAL_GIT bisect skip $(cat $0 | grep '^# SKIP-SINGLE ' | sed 's/^# SKIP-SINGLE
# SKIP-SINGLE 2752573dfb76873dbe783e89a1fbf01d157c54e3
# SKIP-SINGLE 62e990db7a2fad16756e019b331c28ad5a5a89fe
# SKIP-SINGLE 6253e7e74249c7cdfa86723f0b91a1d207cb143e
+# SKIP-SINGLE 1f7113e68988fa0bcbdeca5ae364cba8d6db3637
+# SKIP-SINGLE 6e44d6e18438ea2665ae6252a6ec090963dd7e42
+# SKIP-SINGLE 168cc0aff0bfbc1d67a7e8a72b88a1bf10ad019e
+# SKIP-SINGLE efb276fef1f580eafa8458fc262a4b35eb3abd5e
+# SKIP-SINGLE cc0d7d7a3867e4554f89262e4641c9845ee0d647
+# SKIP-SINGLE 012f9c28053d06b6d527d77530605aedbd55d5b4
+# SKIP-SINGLE e61a03984335b4ffb164280b2df80668b2a92c23
+# SKIP-SINGLE f7fd21b06865d20a16c11e20776e843db24d4b14
+# SKIP-SINGLE 35fbf6f15830f576fd1909f4a8d30e7ba1d777bd
+# SKIP-SINGLE 0e44ab5f061c81874dd8298a0f3318f14ef95a24
diff --git a/admin/gitmerge.el b/admin/gitmerge.el
index 396d2fe2ac5..7c815c729e5 100644
--- a/admin/gitmerge.el
+++ b/admin/gitmerge.el
@@ -1,6 +1,6 @@
;;; gitmerge.el --- help merge one Emacs branch into another -*- lexical-binding: t; -*-
-;; Copyright (C) 2010-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2010-2024 Free Software Foundation, Inc.
;; Authors: David Engster <deng@randomsample.de>
;; Stefan Monnier <monnier@iro.umontreal.ca>
diff --git a/admin/grammars/Makefile.in b/admin/grammars/Makefile.in
index 04a5e0d7205..5904c07dfcd 100644
--- a/admin/grammars/Makefile.in
+++ b/admin/grammars/Makefile.in
@@ -1,6 +1,6 @@
### @configure_input@
-## Copyright (C) 2013-2023 Free Software Foundation, Inc.
+## Copyright (C) 2013-2024 Free Software Foundation, Inc.
## This file is part of GNU Emacs.
diff --git a/admin/grammars/c.by b/admin/grammars/c.by
index a152e3d8696..b3ebd3324fb 100644
--- a/admin/grammars/c.by
+++ b/admin/grammars/c.by
@@ -1,5 +1,5 @@
;;; c.by -- LL grammar for C/C++ language specification
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
;;
;; Author: Eric M. Ludlam <zappo@gnu.org>
;; David Ponce <david@dponce.com>
diff --git a/admin/grammars/grammar.wy b/admin/grammars/grammar.wy
index 1821948ffcb..a81a2df4a6f 100644
--- a/admin/grammars/grammar.wy
+++ b/admin/grammars/grammar.wy
@@ -1,6 +1,6 @@
;;; semantic-grammar.wy -- LALR grammar of Semantic input grammars
;;
-;; Copyright (C) 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2024 Free Software Foundation, Inc.
;;
;; Author: David Ponce <david@dponce.com>
;; Created: 26 Aug 2002
diff --git a/admin/grammars/java-tags.wy b/admin/grammars/java-tags.wy
index 578172c0b7b..0f8f50fd606 100644
--- a/admin/grammars/java-tags.wy
+++ b/admin/grammars/java-tags.wy
@@ -1,6 +1,6 @@
;;; java-tags.wy -- Semantic LALR grammar for Java
-;; Copyright (C) 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2024 Free Software Foundation, Inc.
;;
;; Author: David Ponce <david@dponce.com>
;; Created: 26 Aug 2002
diff --git a/admin/grammars/js.wy b/admin/grammars/js.wy
index fc68471face..13e8b756e47 100644
--- a/admin/grammars/js.wy
+++ b/admin/grammars/js.wy
@@ -1,6 +1,6 @@
;;; javascript-jv.wy -- LALR grammar for Javascript
-;; Copyright (C) 2005-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2005-2024 Free Software Foundation, Inc.
;; Copyright (C) 1998-2011 Ecma International.
;; Author: Joakim Verona
diff --git a/admin/grammars/make.by b/admin/grammars/make.by
index 7bee4ed0ab4..f7a8023b1cf 100644
--- a/admin/grammars/make.by
+++ b/admin/grammars/make.by
@@ -1,6 +1,6 @@
;;; make.by -- BY notation for Makefiles.
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
;;
;; Author: Eric M. Ludlam <zappo@gnu.org>
;; David Ponce <david@dponce.com>
diff --git a/admin/grammars/python.wy b/admin/grammars/python.wy
index 081a4d7ea3f..cf01ff6f5f9 100644
--- a/admin/grammars/python.wy
+++ b/admin/grammars/python.wy
@@ -1,6 +1,6 @@
;;; python.wy -- LALR grammar for Python
-;; Copyright (C) 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2024 Free Software Foundation, Inc.
;; Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
;; 2009, 2010 Python Software Foundation; All Rights Reserved
diff --git a/admin/grammars/scheme.by b/admin/grammars/scheme.by
index 288557db54e..d96529e6389 100644
--- a/admin/grammars/scheme.by
+++ b/admin/grammars/scheme.by
@@ -1,6 +1,6 @@
;;; scheme.by -- Scheme BNF language specification
-;; Copyright (C) 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/admin/grammars/srecode-template.wy b/admin/grammars/srecode-template.wy
index 957c00ab1b9..3dc8b533f33 100644
--- a/admin/grammars/srecode-template.wy
+++ b/admin/grammars/srecode-template.wy
@@ -1,6 +1,6 @@
;;; srecode-template.wy --- Semantic Recoder Template parser
-;; Copyright (C) 2005-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2005-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
;; Keywords: syntax
diff --git a/admin/last-chance.el b/admin/last-chance.el
index a9aaa400b75..c9cc88031f2 100644
--- a/admin/last-chance.el
+++ b/admin/last-chance.el
@@ -1,6 +1,6 @@
;;; last-chance.el --- dangling deterrence -*- lexical-binding: t; -*-
-;; Copyright (C) 2016-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2016-2024 Free Software Foundation, Inc.
;; Author: Thien-Thi Nguyen <ttn@gnu.org>
;; Maintainer: emacs-devel@gnu.org
diff --git a/admin/make-emacs b/admin/make-emacs
index f31c2383fc0..e6ab6a51f7b 100755
--- a/admin/make-emacs
+++ b/admin/make-emacs
@@ -2,7 +2,7 @@
# Build Emacs with various options for profiling, debugging,
# with and without warnings enabled etc.
-# Copyright (C) 2001-2023 Free Software Foundation, Inc.
+# Copyright (C) 2001-2024 Free Software Foundation, Inc.
# This file is part of GNU Emacs.
diff --git a/admin/make-manuals b/admin/make-manuals
index f1a46861533..477daa09a4c 100755
--- a/admin/make-manuals
+++ b/admin/make-manuals
@@ -1,7 +1,7 @@
#!/bin/bash
### make-manuals - create the Emacs manuals to upload to the gnu.org website
-## Copyright 2018-2023 Free Software Foundation, Inc.
+## Copyright 2018-2024 Free Software Foundation, Inc.
## Author: Glenn Morris <rgm@gnu.org>
## Maintainer: emacs-devel@gnu.org
diff --git a/admin/make-tarball.txt b/admin/make-tarball.txt
index fddf8444067..5704e8e8922 100644
--- a/admin/make-tarball.txt
+++ b/admin/make-tarball.txt
@@ -22,6 +22,11 @@ Steps to take before starting on the first pretest in any release sequence:
You can use 'gnupload --delete' (see below for more gnupload details).
(We currently don't bother with this.)
+4. Check that all new Lisp libraries belong to sensible packages.
+ Run "make -C lisp finder-data" and check the diff of the generated
+ file against the previously released Emacs version to see what has
+ changed.
+
General steps (for each step, check for possible errors):
1. git pull # fetch from the repository
@@ -205,7 +210,11 @@ General steps (for each step, check for possible errors):
you need to repeat from step 4 onwards. (You can commit the files
from step 2 and 3 earlier to reduce the chance of this.)
-6. ./make-dist --snapshot --no-compress
+6. If there has been a change in who is the Emacs maintainer since
+ the last release, update doc/misc/ack.texi and admin/MAINTAINERS
+ to reflect this. You can commit this separately.
+
+7. ./make-dist --snapshot --no-compress
Check the contents of the new tar with admin/diff-tar-files
against the previous release (if this is the first pretest) or the
@@ -234,7 +243,7 @@ General steps (for each step, check for possible errors):
The output of this command might be easier to compare to the
tarball than the one you get from find.
-7. tar xf emacs-NEW.tar; cd emacs-NEW
+8. tar xf emacs-NEW.tar; cd emacs-NEW
./configure --prefix=/tmp/emacs && make check && make install
Use 'script' or M-x compile to save the compilation log in
@@ -244,7 +253,7 @@ General steps (for each step, check for possible errors):
M-x ediff. Especially check that Info files aren't built, and that
no autotools (autoconf etc) run.
-8. You can now tag the release/pretest and push it together with the
+9. You can now tag the release/pretest and push it together with the
last commit:
cd EMACS_ROOT_DIR && git tag -a TAG -m "Emacs TAG"
@@ -270,7 +279,7 @@ General steps (for each step, check for possible errors):
git tag -a emacs-28.1-rc1 -m "Emacs 28.1 RC1"
git tag -a emacs-28.1 -m "Emacs 28.1 release"
-9. Decide what compression schemes to offer.
+10. Decide what compression schemes to offer.
For a release, at least gz and xz:
gzip --best --no-name -c emacs-NEW.tar > emacs-NEW.tar.gz
xz -c emacs-NEW.tar > emacs-NEW.tar.xz
@@ -314,14 +323,14 @@ General steps (for each step, check for possible errors):
For a pretest, place the files in /incoming/alpha instead, so that
they appear on https://alpha.gnu.org/.
-10. After five minutes, verify that the files are visible at
+11. After five minutes, verify that the files are visible at
https://alpha.gnu.org/gnu/emacs/pretest/ for a pretest, or
https://ftp.gnu.org/gnu/emacs/ for a release.
Download them and check the signatures and SHA1/SHA256 checksums.
Check they build (./configure --with-native-compilation).
-11. Send an announcement to: emacs-devel, and bcc: info-gnu-emacs@gnu.org.
+12. Send an announcement to: emacs-devel, and bcc: info-gnu-emacs@gnu.org.
For a pretest, also bcc: platform-testers@gnu.org.
For a release, also bcc: info-gnu@gnu.org.
(The reason for using bcc: is to make it less likely that people
@@ -345,9 +354,9 @@ General steps (for each step, check for possible errors):
(Use e.g. `M-x mml-secure-message-sign' in `message-mode' to sign
an email.)
-12. After a release, update the Emacs pages as described below.
+13. After a release, update the Emacs pages as described below.
-13. After a release, bump the Emacs version on the release branch.
+14. After a release, bump the Emacs version on the release branch.
There is no need to bump the version after a pretest; the version
is bumped before the next pretest or release instead.
diff --git a/admin/merge-gnulib b/admin/merge-gnulib
index fe88d1106ae..6378a5f9a22 100755
--- a/admin/merge-gnulib
+++ b/admin/merge-gnulib
@@ -4,7 +4,7 @@
#
# admin/merge-gnulib
-# Copyright 2012-2023 Free Software Foundation, Inc.
+# Copyright 2012-2024 Free Software Foundation, Inc.
# This file is part of GNU Emacs.
diff --git a/admin/merge-pkg-config b/admin/merge-pkg-config
index ba3c48b546b..8bceb0ba2ca 100755
--- a/admin/merge-pkg-config
+++ b/admin/merge-pkg-config
@@ -4,7 +4,7 @@
#
# admin/merge-pkg-config
-# Copyright 2014-2023 Free Software Foundation, Inc.
+# Copyright 2014-2024 Free Software Foundation, Inc.
# This file is part of GNU Emacs.
diff --git a/admin/notes/bug-triage b/admin/notes/bug-triage
index bee7242337d..6fad55dc1e3 100644
--- a/admin/notes/bug-triage
+++ b/admin/notes/bug-triage
@@ -1,10 +1,10 @@
HOW TO TRIAGE EMACS BUGS -*- outline -*-
-This document just describes the procedure of triaging bugs, for information on
-how to work with the bug tracker, see the bugtracker file in this same directory
-for the basics. You can also install the debbugs ELPA package for access to M-x
-debbugs-gnu, an emacs interface to debbugs, and M-x debbugs-org, an emacs
-interface via org-mode.
+This document describes the procedure of triaging bugs. For information on how
+to work with the bug tracker, see the file "bugtracker" in the same directory as
+this file for the basics. You can also install the GNU ELPA package 'debbugs'
+for access to 'M-x debbugs-gnu', an Emacs interface to the debbugs bug tracker,
+and 'M-x debbugs-org', an Emacs interface via org-mode.
* Bug backlog triage procedure
@@ -15,9 +15,10 @@ the ones that are not reproducible on the current release.
calling debbugs-gnu-emacs-release-blocking-reports. If you want
to check this for another Emacs version but the next-to-be-released-one,
use the "C-u" prefix.
- 1. After that, enter debbugs mode (either debbugs-gnu, debbugs-org, or via the
- web browser), and accept the default list option of bugs that have severity
- serious, important, or normal.
+ 1. After that, enter debbugs mode (either using 'M-x debbugs-gnu',
+ 'M-x debbugs-org', or via the web browser), and accept the
+ default list option of bugs that have severity "serious",
+ "important", or "normal".
2. For each bug, we want to primarily make sure it is still
reproducible. A bug can and should stay open as long as it is
still a bug and no one has fixed it. The following is a
@@ -90,21 +91,51 @@ necessary information for others to act on.
For each new bug, ask the following questions:
- 1. Is the bug report written in a way to be easy to reproduce (starts from
- "emacs -Q", etc.)? If not, ask the reporter to try and reproduce it on an
- emacs without customization.
- 2. Is the bug report written against the latest emacs? If not, try to
- reproduce on the latest version, and if it can't be reproduced, ask the
- reporter to try again with the latest version.
+ 1. Is the bug report written in a way to be easy to reproduce
+ (starts from "emacs -Q", etc.)? If not, ask the reporter to try
+ and reproduce it on an emacs without customization.
+ 2. Is the bug report written against the latest emacs? If not, try
+ to reproduce on the latest version, and if it can't be
+ reproduced, ask the reporter to try again with the latest
+ version.
3. Is the bug the same as another bug? If so, merge the bugs.
- 4. What is the priority of the bug? Add a priority: serious, important,
- normal, minor, or wishlist.
- 5. Who should be the owner? This depends on what component the bug is part
- of. You can look at the admin/MAINTAINERS file (then you can just search
- emacs-devel to match the name with an email address).
+ 4. What is the priority of the bug? Add a priority: "serious",
+ "important", "normal", "minor, or "wishlist".
+ 5. Who should be the owner? This depends on what component the bug
+ is part of. You can look at the "Maintainer" comment header in
+ the relevant Lisp files. If you can't find the name there, look
+ at admin/MAINTAINERS file (then you can just search emacs-devel
+ to match the name with an email address).
In the debbugs-gnu buffer, bugs are marked in the "State" column
according to the communication flow. Red bugs mean that nobody has
-answered, these bugs need primary attention. Green bugs flag that
+answered; these bugs need primary attention. Green bugs flag that
there is a recent communication about, and orange bugs flag that the
bug hasn't been touched for at least two weeks.
+
+* Bugs in GNU ELPA and NonGNU ELPA packages
+
+The goal here is to ping the relevant maintainers, as Emacs core
+developers aren't always up-to-date with recent developments in all
+GNU ELPA packages, and can't do anything with reports about bugs in
+NonGNU ELPA packages.
+
+This is how we deal with them:
+
+ 1. Bugs in GNU ELPA packages can always be reported to our bug
+ tracker, even if they are usually tracked by other means. Search
+ for the maintainer of that package, e.g. on
+ https://elpa.gnu.org/packages and take note of their email
+ address. Send a reply with an email body like "<name> is the
+ maintainer of <package>, so I'm copying them in here.", and
+ include their email address in Cc.
+ 2. Bugs in NonGNU ELPA packages should be sent to their maintainers,
+ because we can't do anything to fix them. If you suspect that
+ the bug is about a NonGNU ELPA package, it's usually polite to
+ ask the reporter if this is indeed the case (in case you
+ misunderstood something), and then to point them in the right
+ direction. Such bugs can be closed once the confusion has been
+ resolved.
+ 3. Bugs in third-party packages that are not in any of the above
+ repositories are handled in the same way as packages in NonGNU
+ ELPA.
diff --git a/admin/notes/copyright b/admin/notes/copyright
index a06d92a2c5f..55924157e9a 100644
--- a/admin/notes/copyright
+++ b/admin/notes/copyright
@@ -1,4 +1,4 @@
-Copyright (C) 2007-2023 Free Software Foundation, Inc.
+Copyright (C) 2007-2024 Free Software Foundation, Inc.
See the end of the file for license conditions.
diff --git a/admin/notes/emba b/admin/notes/emba
index cad7a2e121c..2e61ec49ae5 100644
--- a/admin/notes/emba
+++ b/admin/notes/emba
@@ -1,6 +1,6 @@
-*- mode: outline; coding: utf-8 -*-
-Copyright (C) 2019-2023 Free Software Foundation, Inc.
+Copyright (C) 2019-2024 Free Software Foundation, Inc.
See the end of the file for license conditions.
NOTES FOR EMACS CONTINUOUS BUILD ON EMBA
@@ -21,7 +21,7 @@ If you want to receive these notifications, please subscribe at
<https://lists.gnu.org/mailman/listinfo/emacs-buildstatus>.
Alternatively, these notifications can be read via gmane at
-<nntp+news.gmane.org:gmane.emacs.buildstatus>.
+<nntp+news.gmane.io:gmane.emacs.buildstatus>.
The messages contain a URL to the log file of the failed job, like
<https://emba.gnu.org/emacs/emacs/-/jobs/739/raw>.
diff --git a/admin/notes/hydra b/admin/notes/hydra
index 12d3f356020..8ee32df07a7 100644
--- a/admin/notes/hydra
+++ b/admin/notes/hydra
@@ -1,6 +1,6 @@
-*- mode: outline; coding: utf-8 -*-
-Copyright (C) 2013-2023 Free Software Foundation, Inc.
+Copyright (C) 2013-2024 Free Software Foundation, Inc.
See the end of the file for license conditions.
NOTES FOR EMACS CONTINUOUS BUILD ON HYDRA
diff --git a/admin/notes/java b/admin/notes/java
new file mode 100644
index 00000000000..891096cd406
--- /dev/null
+++ b/admin/notes/java
@@ -0,0 +1,1097 @@
+Installation instructions for Android
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
+See the end of the file for license conditions.
+
+
+
+OVERVIEW OF JAVA
+
+Emacs developers do not know Java, and there is no reason they should
+have to. Thus, the code in this directory is confined to what is
+strictly necessary to support Emacs, and only uses a subset of Java
+written in a way that is easily understandable to C programmers.
+
+Java is required because the entire Android runtime is based around
+Java, and there is no way to write an Android program which runs
+without Java.
+
+This text exists to prime other Emacs developers, already familiar with
+C, on the basic architecture of the Android port, and to teach them
+how to read and write the Java code found in this directory.
+
+Java is an object oriented language with automatic memory management
+compiled down to bytecode, which is then subject to interpretation by
+a Java virtual machine.
+
+What that means, is that:
+
+struct emacs_window
+{
+ int some_fields;
+ int of_emacs_window;
+};
+
+static void
+do_something_with_emacs_window (struct emacs_window *a, int n)
+{
+ a->some_fields = a->of_emacs_window + n;
+}
+
+would be written:
+
+public class EmacsWindow
+{
+ public int someFields;
+ public int ofEmacsWindow;
+
+ public void
+ doSomething (int n)
+ {
+ someFields = ofEmacsWindow + n;
+ }
+}
+
+and instead of doing:
+
+do_something_with_emacs_window (my_window, 1);
+
+you say:
+
+myWindow.doSomething (1);
+
+In addition to functions associated with an object of a given class
+(such as EmacsWindow), Java also has two other kinds of functions.
+
+The first are so-called ``static'' functions (the static means
+something entirely different from what it does in C.)
+
+A static function, while still having to be defined within a class,
+can be called without any object. Instead of the object, you write
+the name of the Java class within which it is defined. For example,
+the following C code:
+
+int
+multiply_a_with_b_and_then_add_c (int a, int b, int c)
+{
+ return a * b + c;
+}
+
+would be:
+
+public class EmacsSomething
+{
+ public static int
+ multiplyAWithBAndThenAddC (int a, int b, int c)
+ {
+ return a * b + c;
+ }
+};
+
+Then, instead of calling:
+
+int foo;
+
+foo = multiply_a_with_b_then_add_c (1, 2, 3);
+
+you say:
+
+int foo;
+
+foo = EmacsSomething.multiplyAWithBAndThenAddC (1, 2, 3);
+
+In Java, ``static'' does not mean that the function is only used
+within its compilation unit! Instead, the ``private'' qualifier is
+used to mean more or less the same thing:
+
+static void
+this_procedure_is_only_used_within_this_file (void)
+{
+ do_something ();
+}
+
+becomes
+
+public class EmacsSomething
+{
+ private static void
+ thisProcedureIsOnlyUsedWithinThisClass ()
+ {
+
+ }
+}
+
+the other kind are called ``constructors''. They are functions that
+must be called to allocate memory to hold a class:
+
+public class EmacsFoo
+{
+ int bar;
+
+ public
+ EmacsFoo (int tokenA, int tokenB)
+ {
+ bar = tokenA + tokenB;
+ }
+}
+
+now, the following statement:
+
+EmacsFoo foo;
+
+foo = new EmacsFoo (1, 2);
+
+becomes more or less equivalent to the following C code:
+
+struct emacs_foo
+{
+ int bar;
+};
+
+struct emacs_foo *
+make_emacs_foo (int token_a, int token_b)
+{
+ struct emacs_foo *foo;
+
+ foo = xmalloc (sizeof *foo);
+ foo->bar = token_a + token_b;
+
+ return foo;
+}
+
+/* ... */
+
+struct emacs_foo *foo;
+
+foo = make_emacs_foo (1, 2);
+
+A class may have any number of constructors, or no constructors at
+all, in which case the compiler inserts an empty constructor.
+
+
+
+Sometimes, you will see Java code that looks like this:
+
+ allFiles = filesDirectory.listFiles (new FileFilter () {
+ @Override
+ public boolean
+ accept (File file)
+ {
+ return (!file.isDirectory ()
+ && file.getName ().endsWith (".pdmp"));
+ }
+ });
+
+This is Java's version of GCC's nested function extension. The major
+difference is that the nested function may still be called even after
+it goes out of scope, and always retains a reference to the class and
+local variables around where it was called.
+
+Being an object-oriented language, Java also allows defining that a
+class ``extends'' another class. The following C code:
+
+struct a
+{
+ long thirty_two;
+};
+
+struct b
+{
+ struct a a;
+ long long sixty_four;
+};
+
+extern void do_something (struct a *);
+
+void
+my_function (struct b *b)
+{
+ do_something (&b->a);
+}
+
+is roughly equivalent to the following Java code, split into two
+files:
+
+ A.java
+
+public class A
+{
+ int thirtyTwo;
+
+ public void
+ doSomething ()
+ {
+ etcEtcEtc ();
+ }
+};
+
+ B.java
+
+public class B extends A
+{
+ long sixty_four;
+
+ public static void
+ myFunction (B b)
+ {
+ b.doSomething ();
+ }
+}
+
+the Java runtime has transformed the call to ``b.doSomething'' to
+``((A) b).doSomething''.
+
+However, Java also allows overriding this behavior, by specifying the
+@Override keyword:
+
+public class B extends A
+{
+ long sixty_four;
+
+ @Override
+ public void
+ doSomething ()
+ {
+ Something.doSomethingTwo ();
+ super.doSomething ();
+ }
+}
+
+now, any call to ``doSomething'' on a ``B'' created using ``new B ()''
+will end up calling ``Something.doSomethingTwo'', before calling back
+to ``A.doSomething''. This override also applies in reverse; that is
+to say, even if you write:
+
+ ((A) b).doSomething ();
+
+B's version of doSomething will still be called, if ``b'' was created
+using ``new B ()''.
+
+This mechanism is used extensively throughout the Java language and
+Android windowing APIs.
+
+Elsewhere, you will encounter Java code that defines arrays:
+
+public class EmacsFrobinicator
+{
+ public static void
+ emacsFrobinicate (int something)
+ {
+ int[] primesFromSomething;
+
+ primesFromSomething = new int[numberOfPrimes];
+ /* ... */
+ }
+}
+
+Java arrays are similar to C arrays in that they can not grow. But
+they are very much unlike C arrays in that they are always references
+(as opposed to decaying into pointers in only some situations), and
+contain information about their length.
+
+If another function named ``frobinicate1'' takes an array as an
+argument, then it need not take the length of the array.
+
+Instead, it may simply iterate over the array like so:
+
+int i, k;
+
+for (i = 0; i < array.length; ++i)
+ {
+ k = array[i];
+
+ Whatever.doSomethingWithK (k);
+ }
+
+The syntax used to define arrays is also slightly different. As
+arrays are always references, there is no way for you to tell the
+runtime to allocate an array of size N in a structure (class.)
+
+Instead, if you need an array of that size, you must declare a field
+with the type of the array, and allocate the array inside the class's
+constructor, like so:
+
+public class EmacsArrayContainer
+{
+ public int[] myArray;
+
+ public
+ EmacsArrayContainer ()
+ {
+ myArray = new array[10];
+ }
+}
+
+while in C, you could just have written:
+
+struct emacs_array_container
+{
+ int my_array[10];
+};
+
+or, possibly even better,
+
+typedef int emacs_array_container[10];
+
+Alas, Java has no equivalent of `typedef'.
+
+Like in C, Java string literals are delimited by double quotes.
+Unlike C, however, strings are not NULL-terminated arrays of
+characters, but a distinct type named ``String''. They store their
+own length, characters in Java's 16-bit ``char'' type, and are capable
+of holding NULL bytes.
+
+Instead of writing:
+
+wchar_t character;
+extern char *s;
+size_t s;
+
+ for (/* determine n, s in a loop. */)
+ s += mbstowc (&character, s, n);
+
+or:
+
+const char *byte;
+
+for (byte = my_string; *byte; ++byte)
+ /* do something with *byte. */;
+
+or perhaps even:
+
+size_t length, i;
+char foo;
+
+length = strlen (my_string);
+
+for (i = 0; i < length; ++i)
+ foo = my_string[i];
+
+you write:
+
+char foo;
+int i;
+
+for (i = 0; i < myString.length (); ++i)
+ foo = myString.charAt (0);
+
+Java also has stricter rules on what can be used as a truth value in a
+conditional. While in C, any non-zero value is true, Java requires
+that every truth value be of the boolean type ``boolean''.
+
+What this means is that instead of simply writing:
+
+ if (foo || bar)
+
+where foo can either be 1 or 0, and bar can either be NULL or a
+pointer to something, you must explicitly write:
+
+ if (foo != 0 || bar != null)
+
+in Java.
+
+JAVA NATIVE INTERFACE
+
+Java also provides an interface for C code to interface with Java.
+
+C functions exported from a shared library become static Java
+functions within a class, like so:
+
+public class EmacsNative
+{
+ /* Obtain the fingerprint of this build of Emacs. The fingerprint
+ can be used to determine the dump file name. */
+ public static native String getFingerprint ();
+
+ /* Set certain parameters before initializing Emacs.
+
+ assetManager must be the asset manager associated with the
+ context that is loading Emacs. It is saved and remains for the
+ remainder the lifetime of the Emacs process.
+
+ filesDir must be the package's data storage location for the
+ current Android user.
+
+ libDir must be the package's data storage location for native
+ libraries. It is used as PATH.
+
+ cacheDir must be the package's cache directory. It is used as
+ the `temporary-file-directory'.
+
+ pixelDensityX and pixelDensityY are the DPI values that will be
+ used by Emacs.
+
+ classPath must be the classpath of this app_process process, or
+ NULL.
+
+ emacsService must be the EmacsService singleton, or NULL. */
+ public static native void setEmacsParams (AssetManager assetManager,
+ String filesDir,
+ String libDir,
+ String cacheDir,
+ float pixelDensityX,
+ float pixelDensityY,
+ String classPath,
+ EmacsService emacsService);
+}
+
+Where the corresponding C functions are located in android.c, and
+loaded by the special invocation:
+
+ static
+ {
+ System.loadLibrary ("emacs");
+ };
+
+where ``static'' defines a section of code which will be run upon the
+object (containing class) being loaded. This is like:
+
+ __attribute__((constructor))
+
+on systems where shared object constructors are supported.
+
+See http://docs.oracle.com/en/java/javase/19/docs/specs/jni/intro.html
+for more details.
+
+
+
+OVERVIEW OF ANDROID
+
+When the Android system starts an application, it does not actually
+call the application's ``main'' function. It may not even start the
+application's process if one is already running.
+
+Instead, Android is organized around components. When the user opens
+the ``Emacs'' icon, the Android system looks up and starts the
+component associated with the ``Emacs'' icon. In this case, the
+component is called an activity, and is declared in
+the AndroidManifest.xml in this directory:
+
+ <activity android:name="org.gnu.emacs.EmacsActivity"
+ android:launchMode="singleTop"
+ android:windowSoftInputMode="adjustResize"
+ android:exported="true"
+ android:configChanges="orientation|screenSize|screenLayout|keyboardHidden">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.DEFAULT" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+
+This tells Android to start the activity defined in ``EmacsActivity''
+(defined in org/gnu/emacs/EmacsActivity.java), a class extending the
+Android class ``Activity''.
+
+To do so, the Android system creates an instance of ``EmacsActivity''
+and the window system window associated with it, and eventually calls:
+
+ Activity activity;
+
+ activity.onCreate (...);
+
+But which ``onCreate'' is really called?
+It is actually the ``onCreate'' defined in EmacsActivity.java, as
+it overrides the ``onCreate'' defined in Android's own Activity class:
+
+ @Override
+ public void
+ onCreate (Bundle savedInstanceState)
+ {
+ FrameLayout.LayoutParams params;
+ Intent intent;
+
+Then, this is what happens step-by-step within the ``onCreate''
+function:
+
+ /* See if Emacs should be started with -Q. */
+ intent = getIntent ();
+ EmacsService.needDashQ
+ = intent.getBooleanExtra ("org.gnu.emacs.START_DASH_Q",
+ false);
+
+Here, Emacs obtains the intent (a request to start a component) which
+was used to start Emacs, and sets a special flag if it contains a
+request for Emacs to start with the ``-Q'' command-line argument.
+
+ /* Set the theme to one without a title bar. */
+
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH)
+ setTheme (android.R.style.Theme_DeviceDefault_NoActionBar);
+ else
+ setTheme (android.R.style.Theme_NoTitleBar);
+
+Next, Emacs sets an appropriate theme for the activity's associated
+window decorations.
+
+ params = new FrameLayout.LayoutParams (LayoutParams.MATCH_PARENT,
+ LayoutParams.MATCH_PARENT);
+
+ /* Make the frame layout. */
+ layout = new FrameLayout (this);
+ layout.setLayoutParams (params);
+
+ /* Set it as the content view. */
+ setContentView (layout);
+
+Then, Emacs creates a ``FrameLayout'', a widget that holds a single
+other widget, and makes it the activity's ``content view''.
+
+The activity itself is a ``FrameLayout'', so the ``layout parameters''
+here apply to the FrameLayout itself, and not its children.
+
+ /* Maybe start the Emacs service if necessary. */
+ EmacsService.startEmacsService (this);
+
+And after that, Emacs calls the static function ``startEmacsService'',
+defined in the class ``EmacsService''. This starts the Emacs service
+component if necessary.
+
+ /* Add this activity to the list of available activities. */
+ EmacsWindowAttachmentManager.MANAGER.registerWindowConsumer (this);
+
+ super.onCreate (savedInstanceState);
+
+Finally, Emacs registers that this activity is now ready to receive
+top-level frames (windows) created from Lisp.
+
+Activities come and go, but Emacs has to stay running in the mean
+time. Thus, Emacs also defines a ``service'', which is a long-running
+component that the Android system allows to run in the background.
+
+Let us go back and review the definition of ``startEmacsService'':
+
+ public static void
+ startEmacsService (Context context)
+ {
+ if (EmacsService.SERVICE == null)
+ {
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O)
+ /* Start the Emacs service now. */
+ context.startService (new Intent (context,
+ EmacsService.class));
+ else
+ /* Display the permanent notification and start Emacs as a
+ foreground service. */
+ context.startForegroundService (new Intent (context,
+ EmacsService.class));
+ }
+ }
+
+If ``EmacsService.SERVICE'' does not yet exist, what this does is to
+tell the ``context'' (the equivalent of an Xlib Display *) to start a
+service defined by the class ``EmacsService''. Eventually, this
+results in ``EmacsService.onCreate'' being called:
+
+ @Override
+ public void
+ onCreate ()
+ {
+ AssetManager manager;
+ Context app_context;
+ String filesDir, libDir, cacheDir, classPath;
+ double pixelDensityX;
+ double pixelDensityY;
+
+Here is what this function does, step-by-step:
+
+ SERVICE = this;
+
+First, it sets the special static variable ``SERVICE'' to ``this'',
+which is a pointer to the ``EmacsService' object that was created.
+
+ handler = new Handler (Looper.getMainLooper ());
+
+Next, it creates a ``Handler'' object for the ``main looper''.
+This is a helper structure which allows executing code on the Android
+user interface thread.
+
+ manager = getAssets ();
+ app_context = getApplicationContext ();
+ metrics = getResources ().getDisplayMetrics ();
+ pixelDensityX = metrics.xdpi;
+ pixelDensityY = metrics.ydpi;
+
+Finally, it obtains:
+
+ - the asset manager, which is used to retrieve assets packaged
+ into the Emacs application package.
+
+ - the application context, used to obtain application specific
+ information.
+
+ - the display metrics, and from them, the X and Y densities in dots
+ per inch.
+
+Then, inside a ``try'' block:
+
+ try
+ {
+ /* Configure Emacs with the asset manager and other necessary
+ parameters. */
+ filesDir = app_context.getFilesDir ().getCanonicalPath ();
+ libDir = getLibraryDirectory ();
+ cacheDir = app_context.getCacheDir ().getCanonicalPath ();
+
+It obtains the names of the Emacs home, shared library, and temporary
+file directories.
+
+ /* Now provide this application's apk file, so a recursive
+ invocation of app_process (through android-emacs) can
+ find EmacsNoninteractive. */
+ classPath = getApkFile ();
+
+The name of the Emacs application package.
+
+ Log.d (TAG, "Initializing Emacs, where filesDir = " + filesDir
+ + ", libDir = " + libDir + ", and classPath = " + classPath);
+
+Prints a debug message to the Android system log with this
+information.
+
+ EmacsNative.setEmacsParams (manager, filesDir, libDir,
+ cacheDir, (float) pixelDensityX,
+ (float) pixelDensityY,
+ classPath, this);
+
+And calls the native function ``setEmacsParams'' (defined in
+android.c) to configure Emacs with this information.
+
+ /* Start the thread that runs Emacs. */
+ thread = new EmacsThread (this, needDashQ);
+ thread.start ();
+
+Then, it allocates an ``EmacsThread'' object, and starts that thread.
+Inside that thread is where Emacs's C code runs.
+
+ }
+ catch (IOException exception)
+ {
+ EmacsNative.emacsAbort ();
+ return;
+
+And here is the purpose of the ``try'' block. Functions related to
+file names in Java will signal errors of various types upon failure.
+
+This ``catch'' block means that the Java virtual machine will abort
+execution of the contents of the ``try'' block as soon as an error of
+type ``IOException'' is encountered, and begin executing the contents
+of the ``catch'' block.
+
+Any failure of that type here is a crash, and
+``EmacsNative.emacsAbort'' is called to quickly abort the process to
+get a useful backtrace.
+ }
+ }
+
+Now, let us look at the definition of the class ``EmacsThread'', found
+in org/gnu/emacs/EmacsThread.java:
+
+public class EmacsThread extends Thread
+{
+ /* Whether or not Emacs should be started -Q. */
+ private boolean startDashQ;
+
+ public
+ EmacsThread (EmacsService service, boolean startDashQ)
+ {
+ super ("Emacs main thread");
+ this.startDashQ = startDashQ;
+ }
+
+ @Override
+ public void
+ run ()
+ {
+ String args[];
+
+ if (!startDashQ)
+ args = new String[] { "libandroid-emacs.so", };
+ else
+ args = new String[] { "libandroid-emacs.so", "-Q", };
+
+ /* Run the native code now. */
+ EmacsNative.initEmacs (args, EmacsApplication.dumpFileName);
+ }
+};
+
+The class itself defines a single field, ``startDashQ'', a constructor
+with an unused argument of the type ``EmacsService'' (which is useful
+while debugging) and a flag ``startDashQ'', and a single function
+``run'', overriding the same function in the class ``Thread''.
+
+When ``thread.start'' is called, the Java virtual machine creates a
+new thread, and then calls the function ``run'' within that thread.
+
+This function then computes a suitable argument vector, and calls
+``EmacsNative.initEmacs'' (defined in android.c), which then calls a
+modified version of the regular Emacs ``main'' function.
+
+At that point, Emacs initialization proceeds as usual:
+Vinitial_window_system is set, loadup.el calls `normal-top-level',
+which calls `command-line', and finally
+`window-system-initialization', which initializes the `android'
+terminal interface as usual.
+
+What happens here is the same as on other platforms. Now, here is
+what happens when the initial frame is created: Fx_create_frame calls
+`android_create_frame_window' to create a top level window:
+
+static void
+android_create_frame_window (struct frame *f)
+{
+ struct android_set_window_attributes attributes;
+ enum android_window_value_mask attribute_mask;
+
+ attributes.background_pixel = FRAME_BACKGROUND_PIXEL (f);
+ attribute_mask = ANDROID_CW_BACK_PIXEL;
+
+ block_input ();
+ FRAME_ANDROID_WINDOW (f)
+ = android_create_window (FRAME_DISPLAY_INFO (f)->root_window,
+ f->left_pos,
+ f->top_pos,
+ FRAME_PIXEL_WIDTH (f),
+ FRAME_PIXEL_HEIGHT (f),
+ attribute_mask, &attributes);
+ unblock_input ();
+}
+
+This calls the function `android_create_window' with some arguments
+whose meanings are identical to the arguments to `XCreateWindow'.
+
+Here is the definition of `android_create_window', in android.c:
+
+android_window
+android_create_window (android_window parent, int x, int y,
+ int width, int height,
+ enum android_window_value_mask value_mask,
+ struct android_set_window_attributes *attrs)
+{
+ static jclass class;
+ static jmethodID constructor;
+ jobject object, parent_object, old;
+ android_window window;
+ android_handle prev_max_handle;
+ bool override_redirect;
+
+What does it do? First, some context:
+
+At any time, there can be at most 65535 Java objects referred to by
+the rest of Emacs through the Java native interface. Each such object
+is assigned a ``handle'' (similar to an XID on X) and given a unique
+type. The function `android_resolve_handle' returns the JNI `jobject'
+associated with a given handle.
+
+ parent_object = android_resolve_handle (parent, ANDROID_HANDLE_WINDOW);
+
+Here, it is being used to look up the `jobject' associated with the
+`parent' handle.
+
+ prev_max_handle = max_handle;
+ window = android_alloc_id ();
+
+Next, `max_handle' is saved, and a new handle is allocated for
+`window'.
+
+ if (!window)
+ error ("Out of window handles!");
+
+An error is signaled if Emacs runs out of available handles.
+
+ if (!class)
+ {
+ class = (*android_java_env)->FindClass (android_java_env,
+ "org/gnu/emacs/EmacsWindow");
+ assert (class != NULL);
+
+Then, if this initialization has not yet been completed, Emacs
+proceeds to find the Java class named ``EmacsWindow''.
+
+ constructor
+ = (*android_java_env)->GetMethodID (android_java_env, class, "<init>",
+ "(SLorg/gnu/emacs/EmacsWindow;"
+ "IIIIZ)V");
+ assert (constructor != NULL);
+
+And it tries to look up the constructor, which should take seven
+arguments:
+
+ S - a short. (the handle ID)
+ Lorg/gnu/Emacs/EmacsWindow; - an instance of the EmacsWindow
+ class. (the parent)
+ IIII - four ints. (the window geometry.)
+ Z - a boolean. (whether or not the
+ window is override-redirect; see
+ XChangeWindowAttributes.)
+
+ old = class;
+ class = (*android_java_env)->NewGlobalRef (android_java_env, class);
+ (*android_java_env)->ExceptionClear (android_java_env);
+ ANDROID_DELETE_LOCAL_REF (old);
+
+Next, it saves a global reference to the class and deletes the local
+reference. Global references will never be deallocated by the Java
+virtual machine as long as they still exist.
+
+ if (!class)
+ memory_full (0);
+ }
+
+ /* N.B. that ANDROID_CW_OVERRIDE_REDIRECT can only be set at window
+ creation time. */
+ override_redirect = ((value_mask
+ & ANDROID_CW_OVERRIDE_REDIRECT)
+ && attrs->override_redirect);
+
+ object = (*android_java_env)->NewObject (android_java_env, class,
+ constructor, (jshort) window,
+ parent_object, (jint) x, (jint) y,
+ (jint) width, (jint) height,
+ (jboolean) override_redirect);
+
+Then, it creates an instance of the ``EmacsWindow'' class with the
+appropriate arguments and previously determined constructor.
+
+ if (!object)
+ {
+ (*android_java_env)->ExceptionClear (android_java_env);
+
+ max_handle = prev_max_handle;
+ memory_full (0);
+
+If creating the object fails, Emacs clears the ``pending exception''
+and signals that it is out of memory.
+ }
+
+ android_handles[window].type = ANDROID_HANDLE_WINDOW;
+ android_handles[window].handle
+ = (*android_java_env)->NewGlobalRef (android_java_env,
+ object);
+ (*android_java_env)->ExceptionClear (android_java_env);
+ ANDROID_DELETE_LOCAL_REF (object);
+
+Otherwise, it associates a new global reference to the object with the
+handle, and deletes the local reference returned from the JNI
+NewObject function.
+
+ if (!android_handles[window].handle)
+ memory_full (0);
+
+If allocating the global reference fails, Emacs signals that it is out
+of memory.
+
+ android_change_window_attributes (window, value_mask, attrs);
+ return window;
+
+Otherwise, it applies the specified window attributes and returns the
+handle of the new window.
+}
+
+
+
+DRAWABLES, CURSORS AND HANDLES
+
+Each widget created by Emacs corresponds to a single ``window'', which
+has its own backing store. This arrangement is quite similar to X.
+
+C code does not directly refer to the EmacsView widgets that implement
+the UI logic behind windows. Instead, its handles refer to
+EmacsWindow structures, which contain the state necessary to interact
+with the widgets in an orderly and synchronized manner.
+
+Like X, both pixmaps and windows are drawable resources, and the same
+graphics operations can be applied to both. Thus, a separate
+EmacsPixmap structure is used to wrap around Android Bitmap resources,
+and the Java-level graphics operation functions are capable of
+operating on them both.
+
+Finally, graphics contexts are maintained on both the C and Java
+levels; the C state recorded in `struct android_gc' is kept in sync
+with the Java state in the GContext handle's corresponding EmacsGC
+structure, and cursors are used through handles that refer to
+EmacsCursor structures that hold system PointerIcons.
+
+In all cases, the interfaces provided are identical to X.
+
+
+
+EVENT LOOP
+
+In a typical Android application, the event loop is managed by the
+operating system, and callbacks (implemented through overriding
+separate functions in widgets) are run by the event loop wherever
+necessary. The thread which runs the event loop is also the only
+thread capable of creating and manipulating widgets and activities,
+and is referred to as the ``UI thread''.
+
+These callbacks are used by Emacs to write representations of X-like
+events to a separate event queue, which are then read from Emacs's own
+event loop running in a separate thread. This is accomplished through
+replacing `select' by a function which waits for the event queue to be
+occupied, in addition to any file descriptors that `select' would
+normally wait for.
+
+Conversely, Emacs's event loop sometimes needs to send events to the
+UI thread. These events are implemented as tiny fragments of code,
+which are run as they are received by the main thread.
+
+A typical example is `displayToast', which is implemented in
+EmacsService.java:
+
+ public void
+ displayToast (final String string)
+ {
+ runOnUiThread (new Runnable () {
+ @Override
+ public void
+ run ()
+ {
+ Toast toast;
+
+ toast = Toast.makeText (getApplicationContext (),
+ string, Toast.LENGTH_SHORT);
+ toast.show ();
+ }
+ });
+ }
+
+Here, the variable `string' is used by a nested function. This nested
+function contains a copy of that variable, and is run on the main
+thread using the function `runOnUiThread', in order to display a short
+status message on the display.
+
+When Emacs needs to wait for the nested function to finish, it uses a
+mechanism implemented in `syncRunnable'. This mechanism first calls a
+deadlock avoidance mechanism, then runs a nested function on the UI
+thread, which is expected to signal itself as a condition variable
+upon completion. It is typically used to allocate resources that can
+only be allocated from the UI thread, or to obtain non-thread-safe
+information. The following function is an example; it returns a new
+EmacsView widget corresponding to the provided window:
+
+ public EmacsView
+ getEmacsView (final EmacsWindow window, final int visibility,
+ final boolean isFocusedByDefault)
+ {
+ Runnable runnable;
+ final EmacsHolder<EmacsView> view;
+
+ view = new EmacsHolder<EmacsView> ();
+
+ runnable = new Runnable () {
+ public void
+ run ()
+ {
+ synchronized (this)
+ {
+ view.thing = new EmacsView (window);
+ view.thing.setVisibility (visibility);
+
+ /* The following function is only present on Android 26
+ or later. */
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
+ view.thing.setFocusedByDefault (isFocusedByDefault);
+
+ notify ();
+ }
+ }
+ };
+
+ syncRunnable (runnable);
+ return view.thing;
+ }
+
+As no value can be directly returned from the nested function, a
+separate container object is used to hold the result after the
+function finishes execution. Note the type name inside the angle
+brackets: this type is substituted into the class definition as it is
+used; a definition such as:
+
+public class Foo<T>
+{
+ T bar;
+};
+
+can not be used alone:
+
+ Foo holder; /* Error! */
+
+but must have a type specified:
+
+ Foo<Object> holder;
+
+in which case the effective definition is:
+
+public class Foo
+{
+ Object bar;
+};
+
+
+
+COMPATIBILITY
+
+There are three variables set within every Android application that
+extert influence over the set of Android systems it supports, and the
+measures it must take to function faithfully on each of those systems:
+the minimum API level, compile SDK version and target API level.
+
+The minimum API level is the earliest version of Android that is
+permitted to install and run the application. For Emacs, this is
+established by detecting the __ANDROID_API__ preprocessor macro
+defined within the Android C compiler.
+
+Before Java code executes any Android API calls that are not present
+within Android 2.2 (API level 8), the lowest API level supported by
+Emacs as a whole, it must first check the value of the:
+
+ Build.VERSION.SDK_INT
+
+variable, which is always set to the API level of the system Emacs is
+presently installed within. For example, before calling
+`dispatchKeyEventFromInputMethod', a function absent from Android 6.0
+(API level 23) or earlier, check:
+
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
+ view.imManager.dispatchKeyEventFromInputMethod (view, key);
+ else
+ {
+
+where `N' is a constant defined to 24.
+
+The compile SDK version is the version of the Android SDK headers Java
+code is compiled against. Because Java does not provide conditional
+compilation constructs, Emacs can't be compiled with any version of
+these headers other than the version mentioned in `java/INSTALL', but
+the headers used do not affect the set of supported systems provided
+that the version checks illustrated above are performed where
+necessary.
+
+The target API level is a number within java/AndroidManifest.xml.in
+the system refers to when deciding whether to enable
+backwards-incompatible modifications to the behavior of various system
+APIs. For any given Android version, backwards incompatible changes
+in that version will be disabled for applications whose target API
+levels don't exceed its own.
+
+The target API should nevertheless be updated to match every major
+Android update, as Google has stated their intentions to prohibit
+users from installing applications targeting ``out-of-date'' versions
+of Android, though this threat has hitherto been made good on.
+
+
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
diff --git a/admin/notes/multi-tty b/admin/notes/multi-tty
index d0b63f166fd..f021799b294 100644
--- a/admin/notes/multi-tty
+++ b/admin/notes/multi-tty
@@ -1,6 +1,6 @@
-*- coding: utf-8; mode: text; -*-
-Copyright (C) 2007-2023 Free Software Foundation, Inc.
+Copyright (C) 2007-2024 Free Software Foundation, Inc.
See the end of the file for license conditions.
From README.multi-tty in the multi-tty branch.
@@ -480,8 +480,6 @@ THINGS TO DO
** Have a look at set_frame_matrix_frame.
-** Check if we got term-setup-hook right.
-
** I think tip_frame should be display-local.
** Check display reference count handling in x_create_tip_frame.
diff --git a/admin/notes/tree-sitter/build-module/batch.sh b/admin/notes/tree-sitter/build-module/batch.sh
index 1d4076564dc..9988d1eae4e 100755
--- a/admin/notes/tree-sitter/build-module/batch.sh
+++ b/admin/notes/tree-sitter/build-module/batch.sh
@@ -13,8 +13,10 @@ languages=(
'go-mod'
'heex'
'html'
+ 'java'
'javascript'
'json'
+ 'lua'
'python'
'rust'
'toml'
diff --git a/admin/notes/tree-sitter/build-module/build.sh b/admin/notes/tree-sitter/build-module/build.sh
index 0832875168b..969187b7f92 100755
--- a/admin/notes/tree-sitter/build-module/build.sh
+++ b/admin/notes/tree-sitter/build-module/build.sh
@@ -42,6 +42,9 @@ case "${lang}" in
"heex")
org="phoenixframework"
;;
+ "lua")
+ org="MunifTanjim"
+ ;;
"typescript")
sourcedir="tree-sitter-typescript/typescript/src"
grammardir="tree-sitter-typescript/typescript"
diff --git a/admin/notes/tree-sitter/performance b/admin/notes/tree-sitter/performance
new file mode 100644
index 00000000000..23f84743ced
--- /dev/null
+++ b/admin/notes/tree-sitter/performance
@@ -0,0 +1,25 @@
+TREE-SITTER PERFORMANCE NOTES -*- org -*-
+
+* Facts
+
+Incremental parsing of a few characters worth of edit usually takes
+less than 0.1ms. If it takes longer than that, something is wrong.
+There’s one time where I found tree-sitter-c takes ~30ms to
+incremental parse. Updating to the latest version of tree-sitter-c
+solves it, so I didn’t investigate further.
+
+The ranges set for a parser doesn’t grow when you insert text into a
+range, so you have to update the ranges every time before
+parsing. Fortunately, changing ranges doesn’t invalidate incremental
+parsing, so there isn’t any performance lost in update ranges
+frequently.
+
+* Experiments
+
+Using regexp by default in treesit-simple-indent-rules seems wasteful,
+so I tried replacing all string-match-p to equal in
+treesit-simple-indent-presets, and indent xdisp.c for a comparison.
+Turns out using regexp by default is faster: regexp-based indent took
+45s and equal-based indent took 75s.
+
+I could be missing something, further experiments are welcome.
diff --git a/admin/notes/unicode b/admin/notes/unicode
index da4736c43c6..4a25d8159cb 100644
--- a/admin/notes/unicode
+++ b/admin/notes/unicode
@@ -1,6 +1,6 @@
-*-mode: text; coding: utf-8;-*-
-Copyright (C) 2002-2023 Free Software Foundation, Inc.
+Copyright (C) 2002-2024 Free Software Foundation, Inc.
See the end of the file for license conditions.
Importing a new Unicode Standard version into Emacs
@@ -39,9 +39,9 @@ repository).
Next, review the assignment of default values of the Bidi Class
property to blocks in the file extracted/DerivedBidiClass.txt from the
-UCD (search for "unassigned" in that file). Any changes should be
-reflected in the unidata-gen.el file, where it sets up the default
-values around line 210.
+UCD (search for "unassigned" and "@missing" in that file). Any
+changes should be reflected in the unidata-gen.el file, where it sets
+up the default values around line 210.
Then Emacs should be rebuilt for them to take effect. Rebuilding
Emacs updates several derived files elsewhere in the Emacs source
@@ -61,9 +61,10 @@ Next, review the changes in UnicodeData.txt vs the previous version
used by Emacs. Any changes, be it introduction of new scripts or
addition of codepoints to existing scripts, might need corresponding
changes in the data used for filling the category-table, case-table,
-and char-width-table. The additional scripts should cause automatic
-updates in charscript.el, but it is a good idea to look at the results
-and see if any changes in admin/unidata/blocks.awk are required.
+and char-width-table in characters.el. The additional scripts should
+cause automatic updates in charscript.el, but it is a good idea to
+look at the results and see if any changes in admin/unidata/blocks.awk
+are required.
The setting of char-width-table around line 1200 of characters.el
should be checked against the latest version of the Unicode file
@@ -93,6 +94,11 @@ might need to be updated because it knows about used and unused ranges
of Unicode codepoints, which a new release of the Unicode Standard
could change.
+The data used by ucs-normalize.el might need to be updated.
+Specifically, the values of 'ucs-normalize-composition-exclusions' and
+'check-range", defined at the beginning of ucs-normalize.el, should be
+verified against the latest Unicode data files.
+
Next, test normalization functions against NormalizationTests.txt,
in the test/ directory run:
diff --git a/admin/notes/www b/admin/notes/www
index d6e15ffe955..0a2d4aa9859 100644
--- a/admin/notes/www
+++ b/admin/notes/www
@@ -1,6 +1,6 @@
-*- outline -*-
-Copyright (C) 2013-2023 Free Software Foundation, Inc.
+Copyright (C) 2013-2024 Free Software Foundation, Inc.
See the end of the file for license conditions.
NOTES FOR EMACS WWW PAGES
diff --git a/admin/notes/years b/admin/notes/years
index 113e6608d3f..0510cb24b81 100644
--- a/admin/notes/years
+++ b/admin/notes/years
@@ -24,6 +24,8 @@ A few known problems with the build-aux/update-copyright script:
. several README and XPM files under etc/images/, and also
etc/refcards/README, msdos/README, and nt/icons/README aren't
updated either
+ - the copyright notice for headers generated by exec/configure.ac is
+ not updated as the file already bears a notice above it
These files need to be updated by hand.
diff --git a/admin/nt/README-UNDUMP.W32 b/admin/nt/README-UNDUMP.W32
index b151df1eb0f..8b13d10159b 100644
--- a/admin/nt/README-UNDUMP.W32
+++ b/admin/nt/README-UNDUMP.W32
@@ -1,4 +1,4 @@
-Copyright (C) 2001-2023 Free Software Foundation, Inc.
+Copyright (C) 2001-2024 Free Software Foundation, Inc.
See the end of the file for license conditions.
Emacs for Windows
diff --git a/admin/nt/dist-build/README-windows-binaries b/admin/nt/dist-build/README-windows-binaries
index f53558960c4..c51cea73333 100644
--- a/admin/nt/dist-build/README-windows-binaries
+++ b/admin/nt/dist-build/README-windows-binaries
@@ -1,4 +1,4 @@
-Copyright (C) 2001-2023 Free Software Foundation, Inc.
+Copyright (C) 2001-2024 Free Software Foundation, Inc.
See the end of the file for license conditions.
Precompiled Distributions of
diff --git a/admin/nt/dist-build/build-dep-zips.py b/admin/nt/dist-build/build-dep-zips.py
index 71105a071ec..fb0aca87731 100755
--- a/admin/nt/dist-build/build-dep-zips.py
+++ b/admin/nt/dist-build/build-dep-zips.py
@@ -1,6 +1,6 @@
#!/usr/bin/python3
-## Copyright (C) 2017-2023 Free Software Foundation, Inc.
+## Copyright (C) 2017-2024 Free Software Foundation, Inc.
## This file is part of GNU Emacs.
diff --git a/admin/nt/dist-build/build-zips.sh b/admin/nt/dist-build/build-zips.sh
index 28aee4a0b67..3b9db3deef5 100755
--- a/admin/nt/dist-build/build-zips.sh
+++ b/admin/nt/dist-build/build-zips.sh
@@ -1,6 +1,6 @@
#!/bin/bash
-## Copyright (C) 2017-2023 Free Software Foundation, Inc.
+## Copyright (C) 2017-2024 Free Software Foundation, Inc.
## This file is part of GNU Emacs.
diff --git a/admin/quick-install-emacs b/admin/quick-install-emacs
index 4ca8cee5d7a..985e71d9977 100755
--- a/admin/quick-install-emacs
+++ b/admin/quick-install-emacs
@@ -1,7 +1,7 @@
#!/bin/sh
### quick-install-emacs --- do a halfway-decent job of installing emacs quickly
-## Copyright (C) 2001-2023 Free Software Foundation, Inc.
+## Copyright (C) 2001-2024 Free Software Foundation, Inc.
## Author: Miles Bader <miles@gnu.org>
diff --git a/admin/unidata/BidiBrackets.txt b/admin/unidata/BidiBrackets.txt
index e138e7f5bea..8cebea41544 100644
--- a/admin/unidata/BidiBrackets.txt
+++ b/admin/unidata/BidiBrackets.txt
@@ -1,6 +1,6 @@
-# BidiBrackets-15.0.0.txt
-# Date: 2022-05-03, 18:42:00 GMT [AG, LI, KW]
-# © 2022 Unicode®, Inc.
+# BidiBrackets-15.1.0.txt
+# Date: 2023-01-18
+# © 2023 Unicode®, Inc.
# Unicode and the Unicode Logo are registered trademarks of Unicode, Inc. in the U.S. and other countries.
# For terms of use, see https://www.unicode.org/terms_of_use.html
#
@@ -12,11 +12,11 @@
# This file is a normative contributory data file in the Unicode
# Character Database.
#
-# Bidi_Paired_Bracket is a normative property of type Miscellaneous,
+# Bidi_Paired_Bracket is a normative property
# which establishes a mapping between characters that are treated as
# bracket pairs by the Unicode Bidirectional Algorithm.
#
-# Bidi_Paired_Bracket_Type is a normative property of type Enumeration,
+# Bidi_Paired_Bracket_Type is a normative property
# which classifies characters into opening and closing paired brackets
# for the purposes of the Unicode Bidirectional Algorithm.
#
diff --git a/admin/unidata/BidiMirroring.txt b/admin/unidata/BidiMirroring.txt
index 5861d6e7f4b..7e58cc4d715 100644
--- a/admin/unidata/BidiMirroring.txt
+++ b/admin/unidata/BidiMirroring.txt
@@ -1,6 +1,6 @@
-# BidiMirroring-15.0.0.txt
-# Date: 2022-05-03, 18:47:00 GMT [KW, RP]
-# © 2022 Unicode®, Inc.
+# BidiMirroring-15.1.0.txt
+# Date: 2023-01-05
+# © 2023 Unicode®, Inc.
# For terms of use, see https://www.unicode.org/terms_of_use.html
#
# Unicode Character Database
@@ -15,7 +15,7 @@
# value, for which there is another Unicode character that typically has a glyph
# that is the mirror image of the original character's glyph.
#
-# The repertoire covered by the file is Unicode 15.0.0.
+# The repertoire covered by the file is Unicode 15.1.0.
#
# The file contains a list of lines with mappings from one code point
# to another one for character-based mirroring.
diff --git a/admin/unidata/Blocks.txt b/admin/unidata/Blocks.txt
index 12684594c9f..8fa3eaad04a 100644
--- a/admin/unidata/Blocks.txt
+++ b/admin/unidata/Blocks.txt
@@ -1,6 +1,6 @@
-# Blocks-15.0.0.txt
-# Date: 2022-01-28, 20:58:00 GMT [KW]
-# © 2022 Unicode®, Inc.
+# Blocks-15.1.0.txt
+# Date: 2023-07-28, 15:47:20 GMT
+# © 2023 Unicode®, Inc.
# For terms of use, see https://www.unicode.org/terms_of_use.html
#
# Unicode Character Database
@@ -352,6 +352,7 @@ FFF0..FFFF; Specials
2B740..2B81F; CJK Unified Ideographs Extension D
2B820..2CEAF; CJK Unified Ideographs Extension E
2CEB0..2EBEF; CJK Unified Ideographs Extension F
+2EBF0..2EE5F; CJK Unified Ideographs Extension I
2F800..2FA1F; CJK Compatibility Ideographs Supplement
30000..3134F; CJK Unified Ideographs Extension G
31350..323AF; CJK Unified Ideographs Extension H
diff --git a/admin/unidata/IdnaMappingTable.txt b/admin/unidata/IdnaMappingTable.txt
index e4c06117929..3bf6b2668a4 100644
--- a/admin/unidata/IdnaMappingTable.txt
+++ b/admin/unidata/IdnaMappingTable.txt
@@ -1,11 +1,11 @@
# IdnaMappingTable.txt
-# Date: 2022-05-02, 19:29:26 GMT
-# © 2022 Unicode®, Inc.
+# Date: 2023-08-10, 22:32:27 GMT
+# © 2023 Unicode®, Inc.
# Unicode and the Unicode Logo are registered trademarks of Unicode, Inc. in the U.S. and other countries.
# For terms of use, see https://www.unicode.org/terms_of_use.html
#
# Unicode IDNA Compatible Preprocessing for UTS #46
-# Version: 15.0.0
+# Version: 15.1.0
#
# For documentation and usage, see https://www.unicode.org/reports/tr46
#
@@ -2036,7 +2036,7 @@
1E9A ; mapped ; 0061 02BE # 1.1 LATIN SMALL LETTER A WITH RIGHT HALF RING
1E9B ; mapped ; 1E61 # 2.0 LATIN SMALL LETTER LONG S WITH DOT ABOVE
1E9C..1E9D ; valid # 5.1 LATIN SMALL LETTER LONG S WITH DIAGONAL STROKE..LATIN SMALL LETTER LONG S WITH HIGH STROKE
-1E9E ; mapped ; 0073 0073 # 5.1 LATIN CAPITAL LETTER SHARP S
+1E9E ; mapped ; 00DF # 5.1 LATIN CAPITAL LETTER SHARP S
1E9F ; valid # 5.1 LATIN SMALL LETTER DELTA
1EA0 ; mapped ; 1EA1 # 1.1 LATIN CAPITAL LETTER A WITH DOT BELOW
1EA1 ; valid # 1.1 LATIN SMALL LETTER A WITH DOT BELOW
@@ -2565,11 +2565,7 @@
222E ; valid ; ; NV8 # 1.1 CONTOUR INTEGRAL
222F ; mapped ; 222E 222E # 1.1 SURFACE INTEGRAL
2230 ; mapped ; 222E 222E 222E #1.1 VOLUME INTEGRAL
-2231..225F ; valid ; ; NV8 # 1.1 CLOCKWISE INTEGRAL..QUESTIONED EQUAL TO
-2260 ; disallowed_STD3_valid # 1.1 NOT EQUAL TO
-2261..226D ; valid ; ; NV8 # 1.1 IDENTICAL TO..NOT EQUIVALENT TO
-226E..226F ; disallowed_STD3_valid # 1.1 NOT LESS-THAN..NOT GREATER-THAN
-2270..22F1 ; valid ; ; NV8 # 1.1 NEITHER LESS-THAN NOR EQUAL TO..DOWN RIGHT DIAGONAL ELLIPSIS
+2231..22F1 ; valid ; ; NV8 # 1.1 CLOCKWISE INTEGRAL..DOWN RIGHT DIAGONAL ELLIPSIS
22F2..22FF ; valid ; ; NV8 # 3.2 ELEMENT OF WITH LONG HORIZONTAL STROKE..Z NOTATION BAG MEMBERSHIP
2300 ; valid ; ; NV8 # 1.1 DIAMETER SIGN
2301 ; valid ; ; NV8 # 3.0 ELECTRIC ARROW
@@ -3273,7 +3269,7 @@
2FD5 ; mapped ; 9FA0 # 3.0 KANGXI RADICAL FLUTE
2FD6..2FEF ; disallowed # NA <reserved-2FD6>..<reserved-2FEF>
2FF0..2FFB ; disallowed # 3.0 IDEOGRAPHIC DESCRIPTION CHARACTER LEFT TO RIGHT..IDEOGRAPHIC DESCRIPTION CHARACTER OVERLAID
-2FFC..2FFF ; disallowed # NA <reserved-2FFC>..<reserved-2FFF>
+2FFC..2FFF ; disallowed # 15.1 IDEOGRAPHIC DESCRIPTION CHARACTER SURROUND FROM RIGHT..IDEOGRAPHIC DESCRIPTION CHARACTER ROTATION
3000 ; disallowed_STD3_mapped ; 0020 # 1.1 IDEOGRAPHIC SPACE
3001 ; valid ; ; NV8 # 1.1 IDEOGRAPHIC COMMA
3002 ; mapped ; 002E # 1.1 IDEOGRAPHIC FULL STOP
@@ -3425,7 +3421,8 @@
31BB..31BF ; valid # 13.0 BOPOMOFO FINAL LETTER G..BOPOMOFO LETTER AH
31C0..31CF ; valid ; ; NV8 # 4.1 CJK STROKE T..CJK STROKE N
31D0..31E3 ; valid ; ; NV8 # 5.1 CJK STROKE H..CJK STROKE Q
-31E4..31EF ; disallowed # NA <reserved-31E4>..<reserved-31EF>
+31E4..31EE ; disallowed # NA <reserved-31E4>..<reserved-31EE>
+31EF ; disallowed # 15.1 IDEOGRAPHIC DESCRIPTION CHARACTER SUBTRACTION
31F0..31FF ; valid # 3.2 KATAKANA LETTER SMALL KU..KATAKANA LETTER SMALL RO
3200 ; disallowed_STD3_mapped ; 0028 1100 0029 #1.1 PARENTHESIZED HANGUL KIYEOK
3201 ; disallowed_STD3_mapped ; 0028 1102 0029 #1.1 PARENTHESIZED HANGUL NIEUN
@@ -8450,7 +8447,9 @@ FFFE..FFFF ; disallowed # 1.1 <noncharacter-FFFE
2B820..2CEA1 ; valid # 8.0 CJK UNIFIED IDEOGRAPH-2B820..CJK UNIFIED IDEOGRAPH-2CEA1
2CEA2..2CEAF ; disallowed # NA <reserved-2CEA2>..<reserved-2CEAF>
2CEB0..2EBE0 ; valid # 10.0 CJK UNIFIED IDEOGRAPH-2CEB0..CJK UNIFIED IDEOGRAPH-2EBE0
-2EBE1..2F7FF ; disallowed # NA <reserved-2EBE1>..<reserved-2F7FF>
+2EBE1..2EBEF ; disallowed # NA <reserved-2EBE1>..<reserved-2EBEF>
+2EBF0..2EE5D ; valid # 15.1 CJK UNIFIED IDEOGRAPH-2EBF0..CJK UNIFIED IDEOGRAPH-2EE5D
+2EE5E..2F7FF ; disallowed # NA <reserved-2EE5E>..<reserved-2F7FF>
2F800 ; mapped ; 4E3D # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F800
2F801 ; mapped ; 4E38 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F801
2F802 ; mapped ; 4E41 # 3.1 CJK COMPATIBILITY IDEOGRAPH-2F802
diff --git a/admin/unidata/Makefile.in b/admin/unidata/Makefile.in
index c7737583700..a5fd927f548 100644
--- a/admin/unidata/Makefile.in
+++ b/admin/unidata/Makefile.in
@@ -1,6 +1,6 @@
### @configure_input@
-# Copyright (C) 2012-2023 Free Software Foundation, Inc.
+# Copyright (C) 2012-2024 Free Software Foundation, Inc.
# Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011
# National Institute of Advanced Industrial Science and Technology (AIST)
diff --git a/admin/unidata/NormalizationTest.txt b/admin/unidata/NormalizationTest.txt
index e75b4801c9b..2e88574243d 100644
--- a/admin/unidata/NormalizationTest.txt
+++ b/admin/unidata/NormalizationTest.txt
@@ -1,6 +1,6 @@
-# NormalizationTest-15.0.0.txt
-# Date: 2022-04-02, 01:29:09 GMT
-# © 2022 Unicode®, Inc.
+# NormalizationTest-15.1.0.txt
+# Date: 2023-01-05, 20:34:44 GMT
+# © 2023 Unicode®, Inc.
# Unicode and the Unicode Logo are registered trademarks of Unicode, Inc. in the U.S. and other countries.
# For terms of use, see https://www.unicode.org/terms_of_use.html
#
diff --git a/admin/unidata/PropertyValueAliases.txt b/admin/unidata/PropertyValueAliases.txt
index 9346fcf03ee..6d308108818 100644
--- a/admin/unidata/PropertyValueAliases.txt
+++ b/admin/unidata/PropertyValueAliases.txt
@@ -1,6 +1,6 @@
-# PropertyValueAliases-15.0.0.txt
-# Date: 2022-08-05, 23:42:17 GMT
-# © 2022 Unicode®, Inc.
+# PropertyValueAliases-15.1.0.txt
+# Date: 2023-08-07, 15:21:34 GMT
+# © 2023 Unicode®, Inc.
# Unicode and the Unicode Logo are registered trademarks of Unicode, Inc. in the U.S. and other countries.
# For terms of use, see https://www.unicode.org/terms_of_use.html
#
@@ -91,6 +91,7 @@ age; 12.1 ; V12_1
age; 13.0 ; V13_0
age; 14.0 ; V14_0
age; 15.0 ; V15_0
+age; 15.1 ; V15_1
age; NA ; Unassigned
# Alphabetic (Alpha)
@@ -208,6 +209,7 @@ blk; CJK_Ext_E ; CJK_Unified_Ideographs_Extension_E
blk; CJK_Ext_F ; CJK_Unified_Ideographs_Extension_F
blk; CJK_Ext_G ; CJK_Unified_Ideographs_Extension_G
blk; CJK_Ext_H ; CJK_Unified_Ideographs_Extension_H
+blk; CJK_Ext_I ; CJK_Unified_Ideographs_Extension_I
blk; CJK_Radicals_Sup ; CJK_Radicals_Supplement
blk; CJK_Strokes ; CJK_Strokes
blk; CJK_Symbols ; CJK_Symbols_And_Punctuation
@@ -817,6 +819,21 @@ IDSB; Y ; Yes ; T
IDST; N ; No ; F ; False
IDST; Y ; Yes ; T ; True
+# IDS_Unary_Operator (IDSU)
+
+IDSU; N ; No ; F ; False
+IDSU; Y ; Yes ; T ; True
+
+# ID_Compat_Math_Continue (ID_Compat_Math_Continue)
+
+ID_Compat_Math_Continue; N ; No ; F ; False
+ID_Compat_Math_Continue; Y ; Yes ; T ; True
+
+# ID_Compat_Math_Start (ID_Compat_Math_Start)
+
+ID_Compat_Math_Start; N ; No ; F ; False
+ID_Compat_Math_Start; Y ; Yes ; T ; True
+
# ID_Continue (IDC)
IDC; N ; No ; F ; False
@@ -836,6 +853,13 @@ IDS; Y ; Yes ; T
Ideo; N ; No ; F ; False
Ideo; Y ; Yes ; T ; True
+# Indic_Conjunct_Break (InCB)
+
+InCB; Consonant ; Consonant
+InCB; Extend ; Extend
+InCB; Linker ; Linker
+InCB; None ; None
+
# Indic_Positional_Category (InPC)
InPC; Bottom ; Bottom
@@ -1074,7 +1098,10 @@ jt ; U ; Non_Joining
# Line_Break (lb)
lb ; AI ; Ambiguous
+lb ; AK ; Aksara
lb ; AL ; Alphabetic
+lb ; AP ; Aksara_Prebase
+lb ; AS ; Aksara_Start
lb ; B2 ; Break_Both
lb ; BA ; Break_After
lb ; BB ; Break_Before
@@ -1112,6 +1139,8 @@ lb ; SA ; Complex_Context
lb ; SG ; Surrogate
lb ; SP ; Space
lb ; SY ; Break_Symbols
+lb ; VF ; Virama_Final
+lb ; VI ; Virama
lb ; WJ ; Word_Joiner
lb ; XX ; Unknown
lb ; ZW ; ZWSpace
@@ -1156,6 +1185,9 @@ NFKC_QC; M ; Maybe
NFKC_QC; N ; No
NFKC_QC; Y ; Yes
+# NFKC_Simple_Casefold (NFKC_SCF)
+
+
# NFKD_Quick_Check (NFKD_QC)
NFKD_QC; N ; No
diff --git a/admin/unidata/ScriptExtensions.txt b/admin/unidata/ScriptExtensions.txt
index 2f5a1727e33..23141fb8241 100644
--- a/admin/unidata/ScriptExtensions.txt
+++ b/admin/unidata/ScriptExtensions.txt
@@ -1,6 +1,6 @@
-# ScriptExtensions-15.0.0.txt
-# Date: 2022-02-02, 00:57:11 GMT
-# © 2022 Unicode®, Inc.
+# ScriptExtensions-15.1.0.txt
+# Date: 2023-02-01, 23:02:24 GMT
+# © 2023 Unicode®, Inc.
# Unicode and the Unicode Logo are registered trademarks of Unicode, Inc. in the U.S. and other countries.
# For terms of use, see https://www.unicode.org/terms_of_use.html
#
@@ -136,20 +136,20 @@
# ================================================
-# Script_Extensions=Arab Rohg
+# Script_Extensions=Arab Nkoo
-06D4 ; Arab Rohg # Po ARABIC FULL STOP
+FD3E ; Arab Nkoo # Pe ORNATE LEFT PARENTHESIS
+FD3F ; Arab Nkoo # Ps ORNATE RIGHT PARENTHESIS
-# Total code points: 1
+# Total code points: 2
# ================================================
-# Script_Extensions=Arab Nkoo
+# Script_Extensions=Arab Rohg
-FD3E ; Arab Nkoo # Pe ORNATE LEFT PARENTHESIS
-FD3F ; Arab Nkoo # Ps ORNATE RIGHT PARENTHESIS
+06D4 ; Arab Rohg # Po ARABIC FULL STOP
-# Total code points: 2
+# Total code points: 1
# ================================================
@@ -553,17 +553,17 @@ FF64..FF65 ; Bopo Hang Hani Hira Kana Yiii # Po [2] HALFWIDTH IDEOGRAPHIC C
# ================================================
-# Script_Extensions=Beng Deva Gran Knda Nand Orya Telu Tirh
+# Script_Extensions=Adlm Arab Mand Mani Ougr Phlp Rohg Sogd Syrc
-1CF2 ; Beng Deva Gran Knda Nand Orya Telu Tirh # Lo VEDIC SIGN ARDHAVISARGA
+0640 ; Adlm Arab Mand Mani Ougr Phlp Rohg Sogd Syrc # Lm ARABIC TATWEEL
# Total code points: 1
# ================================================
-# Script_Extensions=Adlm Arab Mand Mani Ougr Phlp Rohg Sogd Syrc
+# Script_Extensions=Beng Deva Gran Knda Mlym Nand Orya Sinh Telu Tirh
-0640 ; Adlm Arab Mand Mani Ougr Phlp Rohg Sogd Syrc # Lm ARABIC TATWEEL
+1CF2 ; Beng Deva Gran Knda Mlym Nand Orya Sinh Telu Tirh # Lo VEDIC SIGN ARDHAVISARGA
# Total code points: 1
@@ -572,10 +572,9 @@ FF64..FF65 ; Bopo Hang Hani Hira Kana Yiii # Po [2] HALFWIDTH IDEOGRAPHIC C
# Script_Extensions=Deva Dogr Gujr Guru Khoj Kthi Mahj Modi Sind Takr Tirh
A836..A837 ; Deva Dogr Gujr Guru Khoj Kthi Mahj Modi Sind Takr Tirh # So [2] NORTH INDIC QUARTER MARK..NORTH INDIC PLACEHOLDER MARK
-A838 ; Deva Dogr Gujr Guru Khoj Kthi Mahj Modi Sind Takr Tirh # Sc NORTH INDIC RUPEE MARK
A839 ; Deva Dogr Gujr Guru Khoj Kthi Mahj Modi Sind Takr Tirh # So NORTH INDIC QUANTITY MARK
-# Total code points: 4
+# Total code points: 3
# ================================================
@@ -587,6 +586,14 @@ A839 ; Deva Dogr Gujr Guru Khoj Kthi Mahj Modi Sind Takr Tirh # So
# ================================================
+# Script_Extensions=Deva Dogr Gujr Guru Khoj Kthi Mahj Modi Shrd Sind Takr Tirh
+
+A838 ; Deva Dogr Gujr Guru Khoj Kthi Mahj Modi Shrd Sind Takr Tirh # Sc NORTH INDIC RUPEE MARK
+
+# Total code points: 1
+
+# ================================================
+
# Script_Extensions=Beng Deva Gran Gujr Guru Knda Latn Mlym Orya Shrd Taml Telu Tirh
0951 ; Beng Deva Gran Gujr Guru Knda Latn Mlym Orya Shrd Taml Telu Tirh # Mn DEVANAGARI STRESS SIGN UDATTA
@@ -595,17 +602,17 @@ A839 ; Deva Dogr Gujr Guru Khoj Kthi Mahj Modi Sind Takr Tirh # So
# ================================================
-# Script_Extensions=Deva Dogr Gujr Guru Khoj Knda Kthi Mahj Modi Nand Sind Takr Tirh
+# Script_Extensions=Deva Dogr Gujr Guru Khoj Knda Kthi Mahj Modi Nand Shrd Sind Takr Tirh
-A833..A835 ; Deva Dogr Gujr Guru Khoj Knda Kthi Mahj Modi Nand Sind Takr Tirh # No [3] NORTH INDIC FRACTION ONE SIXTEENTH..NORTH INDIC FRACTION THREE SIXTEENTHS
+A833..A835 ; Deva Dogr Gujr Guru Khoj Knda Kthi Mahj Modi Nand Shrd Sind Takr Tirh # No [3] NORTH INDIC FRACTION ONE SIXTEENTH..NORTH INDIC FRACTION THREE SIXTEENTHS
# Total code points: 3
# ================================================
-# Script_Extensions=Deva Dogr Gujr Guru Khoj Knda Kthi Mahj Mlym Modi Nand Sind Takr Tirh
+# Script_Extensions=Deva Dogr Gujr Guru Khoj Knda Kthi Mahj Mlym Modi Nand Shrd Sind Takr Tirh
-A830..A832 ; Deva Dogr Gujr Guru Khoj Knda Kthi Mahj Mlym Modi Nand Sind Takr Tirh # No [3] NORTH INDIC FRACTION ONE QUARTER..NORTH INDIC FRACTION THREE QUARTERS
+A830..A832 ; Deva Dogr Gujr Guru Khoj Knda Kthi Mahj Mlym Modi Nand Shrd Sind Takr Tirh # No [3] NORTH INDIC FRACTION ONE QUARTER..NORTH INDIC FRACTION THREE QUARTERS
# Total code points: 3
diff --git a/admin/unidata/Scripts.txt b/admin/unidata/Scripts.txt
index 2b138bffb88..0b3f717cb20 100644
--- a/admin/unidata/Scripts.txt
+++ b/admin/unidata/Scripts.txt
@@ -1,6 +1,6 @@
-# Scripts-15.0.0.txt
-# Date: 2022-04-26, 23:15:02 GMT
-# © 2022 Unicode®, Inc.
+# Scripts-15.1.0.txt
+# Date: 2023-07-28, 16:01:07 GMT
+# © 2023 Unicode®, Inc.
# Unicode and the Unicode Logo are registered trademarks of Unicode, Inc. in the U.S. and other countries.
# For terms of use, see https://www.unicode.org/terms_of_use.html
#
@@ -357,7 +357,7 @@
2E5B ; Common # Ps BOTTOM HALF LEFT PARENTHESIS
2E5C ; Common # Pe BOTTOM HALF RIGHT PARENTHESIS
2E5D ; Common # Pd OBLIQUE HYPHEN
-2FF0..2FFB ; Common # So [12] IDEOGRAPHIC DESCRIPTION CHARACTER LEFT TO RIGHT..IDEOGRAPHIC DESCRIPTION CHARACTER OVERLAID
+2FF0..2FFF ; Common # So [16] IDEOGRAPHIC DESCRIPTION CHARACTER LEFT TO RIGHT..IDEOGRAPHIC DESCRIPTION CHARACTER ROTATION
3000 ; Common # Zs IDEOGRAPHIC SPACE
3001..3003 ; Common # Po [3] IDEOGRAPHIC COMMA..DITTO MARK
3004 ; Common # So JAPANESE INDUSTRIAL STANDARD SYMBOL
@@ -399,6 +399,7 @@
3192..3195 ; Common # No [4] IDEOGRAPHIC ANNOTATION ONE MARK..IDEOGRAPHIC ANNOTATION FOUR MARK
3196..319F ; Common # So [10] IDEOGRAPHIC ANNOTATION TOP MARK..IDEOGRAPHIC ANNOTATION MAN MARK
31C0..31E3 ; Common # So [36] CJK STROKE T..CJK STROKE Q
+31EF ; Common # So IDEOGRAPHIC DESCRIPTION CHARACTER SUBTRACTION
3220..3229 ; Common # No [10] PARENTHESIZED IDEOGRAPH ONE..PARENTHESIZED IDEOGRAPH TEN
322A..3247 ; Common # So [30] PARENTHESIZED IDEOGRAPH MOON..CIRCLED IDEOGRAPH KOTO
3248..324F ; Common # No [8] CIRCLED NUMBER TEN ON BLACK SQUARE..CIRCLED NUMBER EIGHTY ON BLACK SQUARE
@@ -629,7 +630,7 @@ FFFC..FFFD ; Common # So [2] OBJECT REPLACEMENT CHARACTER..REPLACEMENT CHAR
E0001 ; Common # Cf LANGUAGE TAG
E0020..E007F ; Common # Cf [96] TAG SPACE..CANCEL TAG
-# Total code points: 8301
+# Total code points: 8306
# ================================================
@@ -1593,11 +1594,12 @@ FA70..FAD9 ; Han # Lo [106] CJK COMPATIBILITY IDEOGRAPH-FA70..CJK COMPATIBILI
2B740..2B81D ; Han # Lo [222] CJK UNIFIED IDEOGRAPH-2B740..CJK UNIFIED IDEOGRAPH-2B81D
2B820..2CEA1 ; Han # Lo [5762] CJK UNIFIED IDEOGRAPH-2B820..CJK UNIFIED IDEOGRAPH-2CEA1
2CEB0..2EBE0 ; Han # Lo [7473] CJK UNIFIED IDEOGRAPH-2CEB0..CJK UNIFIED IDEOGRAPH-2EBE0
+2EBF0..2EE5D ; Han # Lo [622] CJK UNIFIED IDEOGRAPH-2EBF0..CJK UNIFIED IDEOGRAPH-2EE5D
2F800..2FA1D ; Han # Lo [542] CJK COMPATIBILITY IDEOGRAPH-2F800..CJK COMPATIBILITY IDEOGRAPH-2FA1D
30000..3134A ; Han # Lo [4939] CJK UNIFIED IDEOGRAPH-30000..CJK UNIFIED IDEOGRAPH-3134A
31350..323AF ; Han # Lo [4192] CJK UNIFIED IDEOGRAPH-31350..CJK UNIFIED IDEOGRAPH-323AF
-# Total code points: 98408
+# Total code points: 99030
# ================================================
diff --git a/admin/unidata/SpecialCasing.txt b/admin/unidata/SpecialCasing.txt
index 08d04fa9421..de08450a6b9 100644
--- a/admin/unidata/SpecialCasing.txt
+++ b/admin/unidata/SpecialCasing.txt
@@ -1,6 +1,6 @@
-# SpecialCasing-15.0.0.txt
-# Date: 2022-02-02, 23:35:52 GMT
-# © 2022 Unicode®, Inc.
+# SpecialCasing-15.1.0.txt
+# Date: 2023-01-05, 20:35:03 GMT
+# © 2023 Unicode®, Inc.
# Unicode and the Unicode Logo are registered trademarks of Unicode, Inc. in the U.S. and other countries.
# For terms of use, see https://www.unicode.org/terms_of_use.html
#
diff --git a/admin/unidata/UnicodeData.txt b/admin/unidata/UnicodeData.txt
index ea963a7162c..bdcc41850d7 100644
--- a/admin/unidata/UnicodeData.txt
+++ b/admin/unidata/UnicodeData.txt
@@ -11231,6 +11231,10 @@
2FF9;IDEOGRAPHIC DESCRIPTION CHARACTER SURROUND FROM UPPER RIGHT;So;0;ON;;;;;N;;;;;
2FFA;IDEOGRAPHIC DESCRIPTION CHARACTER SURROUND FROM LOWER LEFT;So;0;ON;;;;;N;;;;;
2FFB;IDEOGRAPHIC DESCRIPTION CHARACTER OVERLAID;So;0;ON;;;;;N;;;;;
+2FFC;IDEOGRAPHIC DESCRIPTION CHARACTER SURROUND FROM RIGHT;So;0;ON;;;;;N;;;;;
+2FFD;IDEOGRAPHIC DESCRIPTION CHARACTER SURROUND FROM LOWER RIGHT;So;0;ON;;;;;N;;;;;
+2FFE;IDEOGRAPHIC DESCRIPTION CHARACTER HORIZONTAL REFLECTION;So;0;ON;;;;;N;;;;;
+2FFF;IDEOGRAPHIC DESCRIPTION CHARACTER ROTATION;So;0;ON;;;;;N;;;;;
3000;IDEOGRAPHIC SPACE;Zs;0;WS;<wide> 0020;;;;N;;;;;
3001;IDEOGRAPHIC COMMA;Po;0;ON;;;;;N;;;;;
3002;IDEOGRAPHIC FULL STOP;Po;0;ON;;;;;N;IDEOGRAPHIC PERIOD;;;;
@@ -11705,6 +11709,7 @@
31E1;CJK STROKE HZZZG;So;0;ON;;;;;N;;;;;
31E2;CJK STROKE PG;So;0;ON;;;;;N;;;;;
31E3;CJK STROKE Q;So;0;ON;;;;;N;;;;;
+31EF;IDEOGRAPHIC DESCRIPTION CHARACTER SUBTRACTION;So;0;ON;;;;;N;;;;;
31F0;KATAKANA LETTER SMALL KU;Lo;0;L;;;;;N;;;;;
31F1;KATAKANA LETTER SMALL SI;Lo;0;L;;;;;N;;;;;
31F2;KATAKANA LETTER SMALL SU;Lo;0;L;;;;;N;;;;;
@@ -34035,6 +34040,8 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;;
2CEA1;<CJK Ideograph Extension E, Last>;Lo;0;L;;;;;N;;;;;
2CEB0;<CJK Ideograph Extension F, First>;Lo;0;L;;;;;N;;;;;
2EBE0;<CJK Ideograph Extension F, Last>;Lo;0;L;;;;;N;;;;;
+2EBF0;<CJK Ideograph Extension I, First>;Lo;0;L;;;;;N;;;;;
+2EE5D;<CJK Ideograph Extension I, Last>;Lo;0;L;;;;;N;;;;;
2F800;CJK COMPATIBILITY IDEOGRAPH-2F800;Lo;0;L;4E3D;;;;N;;;;;
2F801;CJK COMPATIBILITY IDEOGRAPH-2F801;Lo;0;L;4E38;;;;N;;;;;
2F802;CJK COMPATIBILITY IDEOGRAPH-2F802;Lo;0;L;4E41;;;;N;;;;;
diff --git a/admin/unidata/blocks.awk b/admin/unidata/blocks.awk
index 80ce7478a45..122164ce5b6 100755
--- a/admin/unidata/blocks.awk
+++ b/admin/unidata/blocks.awk
@@ -1,6 +1,6 @@
#!/usr/bin/awk -f
-## Copyright (C) 2015-2023 Free Software Foundation, Inc.
+## Copyright (C) 2015-2024 Free Software Foundation, Inc.
## Author: Glenn Morris <rgm@gnu.org>
## Maintainer: emacs-devel@gnu.org
@@ -60,6 +60,7 @@ BEGIN {
alias["cjk strokes"] = "cjk-misc"
alias["cjk symbols and punctuation"] = "cjk-misc"
alias["halfwidth and fullwidth forms"] = "cjk-misc"
+ alias["yijing hexagram symbols"] = "cjk-misc"
alias["common indic number forms"] = "north-indic-number"
tohex["a"] = 10
@@ -94,7 +95,7 @@ function name2alias(name , w, w2) {
if (alias[name]) return alias[name]
else if (name ~ /for symbols/) return "symbol"
else if (name ~ /latin|combining .* marks|spacing modifier|tone letters|alphabetic presentation/) return "latin"
- else if (name ~ /cjk|yijing|enclosed ideograph|kangxi/) return "han"
+ else if (name ~ /cjk|enclosed ideograph|kangxi/) return "han"
else if (name ~ /arabic/) return "arabic"
else if (name ~ /^greek/) return "greek"
else if (name ~ /^coptic/) return "coptic"
diff --git a/admin/unidata/confusables.txt b/admin/unidata/confusables.txt
index 24b61d519af..5e056ed5a35 100644
--- a/admin/unidata/confusables.txt
+++ b/admin/unidata/confusables.txt
@@ -1,11 +1,11 @@
# confusables.txt
-# Date: 2022-08-26, 16:49:08 GMT
-# © 2022 Unicode®, Inc.
+# Date: 2023-08-11, 17:46:40 GMT
+# © 2023 Unicode®, Inc.
# Unicode and the Unicode Logo are registered trademarks of Unicode, Inc. in the U.S. and other countries.
# For terms of use, see https://www.unicode.org/terms_of_use.html
#
# Unicode Security Mechanisms for UTS #39
-# Version: 15.0.0
+# Version: 15.1.0
#
# For documentation and usage, see https://www.unicode.org/reports/tr39
#
@@ -349,8 +349,8 @@ A4FA ; 002E 002E ; MA # ( ꓺ → .. ) LISU LETTER TONE MYA CYA → FULL STOP, F
A6F4 ; A6F3 A6F3 ; MA #* ( ꛴ → ꛳꛳ ) BAMUM COLON → BAMUM FULL STOP, BAMUM FULL STOP #
-30FB ; 00B7 ; MA #* ( ・ → · ) KATAKANA MIDDLE DOT → MIDDLE DOT # →•→
-FF65 ; 00B7 ; MA #* ( ・ → · ) HALFWIDTH KATAKANA MIDDLE DOT → MIDDLE DOT # →•→
+30FB ; 00B7 ; MA # ( ・ → · ) KATAKANA MIDDLE DOT → MIDDLE DOT # →•→
+FF65 ; 00B7 ; MA # ( ・ → · ) HALFWIDTH KATAKANA MIDDLE DOT → MIDDLE DOT # →•→
16EB ; 00B7 ; MA #* ( ᛫ → · ) RUNIC SINGLE PUNCTUATION → MIDDLE DOT #
0387 ; 00B7 ; MA # ( · → · ) GREEK ANO TELEIA → MIDDLE DOT #
2E31 ; 00B7 ; MA #* ( ⸱ → · ) WORD SEPARATOR MIDDLE DOT → MIDDLE DOT #
diff --git a/admin/unidata/copyright.html b/admin/unidata/copyright.html
index 567c54e72ac..fe6dd16903e 100644
--- a/admin/unidata/copyright.html
+++ b/admin/unidata/copyright.html
@@ -13,7 +13,7 @@
<title>Unicode Terms of Use</title>
<link rel="stylesheet" type="text/css"
-href="https://www.unicode.org/webscripts/standard_styles.css">
+href="http://www.unicode.org/webscripts/standard_styles.css">
<style type="text/css">
pre {
@@ -32,8 +32,8 @@ pre {
<td colspan="2">
<table width="100%" border="0" cellpadding="0" cellspacing="0">
<tr>
- <td class="icon" style="width:38px; height:35px"><a href="https://www.unicode.org/"><img border="0"
- src="https://www.unicode.org/webscripts/logo60s2.gif" align="middle" alt="[Unicode]" width="34" height="33"></a></td>
+ <td class="icon" style="width:38px; height:35px"><a href="http://www.unicode.org/"><img border="0"
+ src="http://www.unicode.org/webscripts/logo60s2.gif" align="middle" alt="[Unicode]" width="34" height="33"></a></td>
<td class="icon" style="vertical-align:middle;"> &nbsp;<a class="bar"
href="https://www.unicode.org/copyright.html"><font size="3">Terms of Use</font></a></td>
<td class="bar"><a href="https://www.unicode.org/main.html" class="bar">Tech Site</a>
@@ -112,13 +112,13 @@ pre {
<p>For the general privacy policy governing access to this site, see
the&nbsp;
- <a href="https://www.unicode.org/policies/privacy_policy.html">
+ <a href="http://www.unicode.org/policies/privacy_policy.html">
Unicode Privacy Policy</a>.</p>
<ol type="A">
<li><u><a name="1"></a>Unicode Copyright</u>
<ol>
- <li>Copyright © 1991-2022 Unicode, Inc. All rights reserved.</li>
+ <li>Copyright © 1991-2023 Unicode, Inc. All rights reserved.</li>
</ol>
</li>
@@ -158,7 +158,7 @@ http://site.icu-project.org/download/
specifications of rights and restrictions of use. For the book
editions (Unicode 5.0 and earlier), these are found on the back
of the
- <a href="https://www.unicode.org/versions/Unicode5.0.0/Title.pdf">title page</a>.</li>
+ <a href="http://www.unicode.org/versions/Unicode5.0.0/Title.pdf">title page</a>.</li>
<li>
The Unicode PDF <a href="https://www.unicode.org/charts/">online code charts</a> carry specific restrictions. Those restrictions are incorporated as the
first page of each PDF code chart.</li>
@@ -224,7 +224,7 @@ http://site.icu-project.org/download/
<li><u><a name="5"></a>Trademarks &amp; Logos</u>
<ol>
<li>The Unicode Word Mark and the Unicode Logo are trademarks of Unicode, Inc. “The Unicode Consortium” and “Unicode, Inc.” are trade names of Unicode, Inc. Use of the information and materials found on this website indicates your acknowledgement of Unicode, Inc.’s exclusive worldwide rights in the Unicode Word Mark, the Unicode Logo, and the Unicode trade names.</li>
-<li><a href="https://www.unicode.org/policies/logo_policy.html">The Unicode Consortium Name and Trademark Usage Policy</a> (“Trademark Policy”) are incorporated herein by reference and you agree to abide by the provisions of the Trademark Policy, which may be changed from time to time in the sole discretion of Unicode, Inc.</li>
+<li><a href="http://www.unicode.org/policies/logo_policy.html">The Unicode Consortium Name and Trademark Usage Policy</a> (“Trademark Policy”) are incorporated herein by reference and you agree to abide by the provisions of the Trademark Policy, which may be changed from time to time in the sole discretion of Unicode, Inc.</li>
<li>All third party trademarks referenced herein are the property of their respective owners.</li>
</ol>
</li>
@@ -270,15 +270,15 @@ http://site.icu-project.org/download/
<center>
<table cellspacing="0" cellpadding="0" border="0" id="table2">
<tr>
- <td><a href="https://www.unicode.org/copyright.html">
- <img src="https://www.unicode.org/img/hb_notice.gif"
+ <td><a href="http://www.unicode.org/copyright.html">
+ <img src="http://www.unicode.org/img/hb_notice.gif"
border="0" alt="Access to Copyright and terms of use"
width="216" height="50"></a></td>
</tr>
</table>
<script language="Javascript" type="text/javascript"
- src="https://www.unicode.org/webscripts/lastModified.js">
+ src="http://www.unicode.org/webscripts/lastModified.js">
</script>
</center>
diff --git a/admin/unidata/emoji-data.txt b/admin/unidata/emoji-data.txt
index 7942fc89a35..ab9c04ff056 100644
--- a/admin/unidata/emoji-data.txt
+++ b/admin/unidata/emoji-data.txt
@@ -1,11 +1,11 @@
# emoji-data.txt
-# Date: 2022-08-02, 00:26:10 GMT
-# © 2022 Unicode®, Inc.
+# Date: 2023-02-01, 02:22:54 GMT
+# © 2023 Unicode®, Inc.
# Unicode and the Unicode Logo are registered trademarks of Unicode, Inc. in the U.S. and other countries.
# For terms of use, see https://www.unicode.org/terms_of_use.html
#
# Emoji Data for UTS #51
-# Used with Emoji Version 15.0 and subsequent minor revisions (if any)
+# Used with Emoji Version 15.1 and subsequent minor revisions (if any)
#
# For documentation and usage, see https://www.unicode.org/reports/tr51
#
diff --git a/admin/unidata/emoji-sequences.txt b/admin/unidata/emoji-sequences.txt
index ffd40668117..dfeae158edb 100644
--- a/admin/unidata/emoji-sequences.txt
+++ b/admin/unidata/emoji-sequences.txt
@@ -1,11 +1,11 @@
# emoji-sequences.txt
-# Date: 2022-08-15, 23:13:41 GMT
-# © 2022 Unicode®, Inc.
+# Date: 2023-06-05, 21:39:54 GMT
+# © 2023 Unicode®, Inc.
# Unicode and the Unicode Logo are registered trademarks of Unicode, Inc. in the U.S. and other countries.
# For terms of use, see https://www.unicode.org/terms_of_use.html
#
# Emoji Sequence Data for UTS #51
-# Version: 15.0
+# Version: 15.1
#
# For documentation and usage, see https://www.unicode.org/reports/tr51
#
@@ -38,7 +38,6 @@
# Basic_Emoji
-
231A..231B ; Basic_Emoji ; watch..hourglass done # E0.6 [2] (⌚..⌛)
23E9..23EC ; Basic_Emoji ; fast-forward button..fast down button # E0.6 [4] (⏩..⏬)
23F0 ; Basic_Emoji ; alarm clock # E0.6 [1] (⏰)
@@ -534,7 +533,6 @@
# Emoji_Keycap_Sequence
-
0023 FE0F 20E3; Emoji_Keycap_Sequence ; keycap: \x{23} # E0.6 [1] (#️⃣)
002A FE0F 20E3; Emoji_Keycap_Sequence ; keycap: * # E2.0 [1] (*️⃣)
0030 FE0F 20E3; Emoji_Keycap_Sequence ; keycap: 0 # E0.6 [1] (0️⃣)
@@ -553,8 +551,7 @@
# ================================================
# RGI_Emoji_Flag_Sequence: This list does not include deprecated or macroregion flags, except for UN and EU.
-# See Annex B of TR51 for more information.
-
+# See Annex B of UTS #51 for more information.
1F1E6 1F1E8 ; RGI_Emoji_Flag_Sequence ; flag: Ascension Island # E2.0 [1] (🇦🇨)
1F1E6 1F1E9 ; RGI_Emoji_Flag_Sequence ; flag: Andorra # E2.0 [1] (🇦🇩)
@@ -787,7 +784,7 @@
1F1F9 1F1F2 ; RGI_Emoji_Flag_Sequence ; flag: Turkmenistan # E2.0 [1] (🇹🇲)
1F1F9 1F1F3 ; RGI_Emoji_Flag_Sequence ; flag: Tunisia # E2.0 [1] (🇹🇳)
1F1F9 1F1F4 ; RGI_Emoji_Flag_Sequence ; flag: Tonga # E2.0 [1] (🇹🇴)
-1F1F9 1F1F7 ; RGI_Emoji_Flag_Sequence ; flag: Turkey # E2.0 [1] (🇹🇷)
+1F1F9 1F1F7 ; RGI_Emoji_Flag_Sequence ; flag: Türkiye # E2.0 [1] (🇹🇷)
1F1F9 1F1F9 ; RGI_Emoji_Flag_Sequence ; flag: Trinidad & Tobago # E2.0 [1] (🇹🇹)
1F1F9 1F1FB ; RGI_Emoji_Flag_Sequence ; flag: Tuvalu # E2.0 [1] (🇹🇻)
1F1F9 1F1FC ; RGI_Emoji_Flag_Sequence ; flag: Taiwan # E2.0 [1] (🇹🇼)
@@ -819,8 +816,7 @@
# ================================================
-# RGI_Emoji_Tag_Sequence: See Annex C of TR51 for more information.
-
+# RGI_Emoji_Tag_Sequence: See Annex C of UTS #51 for more information.
1F3F4 E0067 E0062 E0065 E006E E0067 E007F; RGI_Emoji_Tag_Sequence; flag: England # E5.0 [1] (🏴󠁧󠁢󠁥󠁮󠁧󠁿)
1F3F4 E0067 E0062 E0073 E0063 E0074 E007F; RGI_Emoji_Tag_Sequence; flag: Scotland # E5.0 [1] (🏴󠁧󠁢󠁳󠁣󠁴󠁿)
@@ -832,7 +828,6 @@
# RGI_Emoji_Modifier_Sequence
-
261D 1F3FB ; RGI_Emoji_Modifier_Sequence ; index pointing up: light skin tone # E1.0 [1] (☝🏻)
261D 1F3FC ; RGI_Emoji_Modifier_Sequence ; index pointing up: medium-light skin tone # E1.0 [1] (☝🏼)
261D 1F3FD ; RGI_Emoji_Modifier_Sequence ; index pointing up: medium skin tone # E1.0 [1] (☝🏽)
diff --git a/admin/unidata/emoji-test.txt b/admin/unidata/emoji-test.txt
index bc8b52c2fb4..1f50b23fa24 100644
--- a/admin/unidata/emoji-test.txt
+++ b/admin/unidata/emoji-test.txt
@@ -1,11 +1,11 @@
# emoji-test.txt
-# Date: 2022-08-12, 20:24:39 GMT
-# © 2022 Unicode®, Inc.
+# Date: 2023-06-05, 21:39:54 GMT
+# © 2023 Unicode®, Inc.
# Unicode and the Unicode Logo are registered trademarks of Unicode, Inc. in the U.S. and other countries.
# For terms of use, see https://www.unicode.org/terms_of_use.html
#
# Emoji Keyboard/Display Test Data for UTS #51
-# Version: 15.0
+# Version: 15.1
#
# For documentation and usage, see https://www.unicode.org/reports/tr51
#
@@ -93,6 +93,10 @@
1F62E 200D 1F4A8 ; fully-qualified # 😮‍💨 E13.1 face exhaling
1F925 ; fully-qualified # 🤥 E3.0 lying face
1FAE8 ; fully-qualified # 🫨 E15.0 shaking face
+1F642 200D 2194 FE0F ; fully-qualified # 🙂‍↔️ E15.1 head shaking horizontally
+1F642 200D 2194 ; minimally-qualified # 🙂‍↔ E15.1 head shaking horizontally
+1F642 200D 2195 FE0F ; fully-qualified # 🙂‍↕️ E15.1 head shaking vertically
+1F642 200D 2195 ; minimally-qualified # 🙂‍↕ E15.1 head shaking vertically
# subgroup: face-sleepy
1F60C ; fully-qualified # 😌 E0.6 relieved face
@@ -244,8 +248,8 @@
1F4AD ; fully-qualified # 💭 E1.0 thought balloon
1F4A4 ; fully-qualified # 💤 E0.6 ZZZ
-# Smileys & Emotion subtotal: 180
-# Smileys & Emotion subtotal: 180 w/o modifiers
+# Smileys & Emotion subtotal: 184
+# Smileys & Emotion subtotal: 184 w/o modifiers
# group: People & Body
@@ -2065,6 +2069,66 @@
1F6B6 1F3FE 200D 2640 ; minimally-qualified # 🚶🏾‍♀ E4.0 woman walking: medium-dark skin tone
1F6B6 1F3FF 200D 2640 FE0F ; fully-qualified # 🚶🏿‍♀️ E4.0 woman walking: dark skin tone
1F6B6 1F3FF 200D 2640 ; minimally-qualified # 🚶🏿‍♀ E4.0 woman walking: dark skin tone
+1F6B6 200D 27A1 FE0F ; fully-qualified # 🚶‍➡️ E15.1 person walking facing right
+1F6B6 200D 27A1 ; minimally-qualified # 🚶‍➡ E15.1 person walking facing right
+1F6B6 1F3FB 200D 27A1 FE0F ; fully-qualified # 🚶🏻‍➡️ E15.1 person walking facing right: light skin tone
+1F6B6 1F3FB 200D 27A1 ; minimally-qualified # 🚶🏻‍➡ E15.1 person walking facing right: light skin tone
+1F6B6 1F3FC 200D 27A1 FE0F ; fully-qualified # 🚶🏼‍➡️ E15.1 person walking facing right: medium-light skin tone
+1F6B6 1F3FC 200D 27A1 ; minimally-qualified # 🚶🏼‍➡ E15.1 person walking facing right: medium-light skin tone
+1F6B6 1F3FD 200D 27A1 FE0F ; fully-qualified # 🚶🏽‍➡️ E15.1 person walking facing right: medium skin tone
+1F6B6 1F3FD 200D 27A1 ; minimally-qualified # 🚶🏽‍➡ E15.1 person walking facing right: medium skin tone
+1F6B6 1F3FE 200D 27A1 FE0F ; fully-qualified # 🚶🏾‍➡️ E15.1 person walking facing right: medium-dark skin tone
+1F6B6 1F3FE 200D 27A1 ; minimally-qualified # 🚶🏾‍➡ E15.1 person walking facing right: medium-dark skin tone
+1F6B6 1F3FF 200D 27A1 FE0F ; fully-qualified # 🚶🏿‍➡️ E15.1 person walking facing right: dark skin tone
+1F6B6 1F3FF 200D 27A1 ; minimally-qualified # 🚶🏿‍➡ E15.1 person walking facing right: dark skin tone
+1F6B6 200D 2640 FE0F 200D 27A1 FE0F ; fully-qualified # 🚶‍♀️‍➡️ E15.1 woman walking facing right
+1F6B6 200D 2640 200D 27A1 FE0F ; minimally-qualified # 🚶‍♀‍➡️ E15.1 woman walking facing right
+1F6B6 200D 2640 FE0F 200D 27A1 ; minimally-qualified # 🚶‍♀️‍➡ E15.1 woman walking facing right
+1F6B6 200D 2640 200D 27A1 ; minimally-qualified # 🚶‍♀‍➡ E15.1 woman walking facing right
+1F6B6 1F3FB 200D 2640 FE0F 200D 27A1 FE0F ; fully-qualified # 🚶🏻‍♀️‍➡️ E15.1 woman walking facing right: light skin tone
+1F6B6 1F3FB 200D 2640 200D 27A1 FE0F ; minimally-qualified # 🚶🏻‍♀‍➡️ E15.1 woman walking facing right: light skin tone
+1F6B6 1F3FB 200D 2640 FE0F 200D 27A1 ; minimally-qualified # 🚶🏻‍♀️‍➡ E15.1 woman walking facing right: light skin tone
+1F6B6 1F3FB 200D 2640 200D 27A1 ; minimally-qualified # 🚶🏻‍♀‍➡ E15.1 woman walking facing right: light skin tone
+1F6B6 1F3FC 200D 2640 FE0F 200D 27A1 FE0F ; fully-qualified # 🚶🏼‍♀️‍➡️ E15.1 woman walking facing right: medium-light skin tone
+1F6B6 1F3FC 200D 2640 200D 27A1 FE0F ; minimally-qualified # 🚶🏼‍♀‍➡️ E15.1 woman walking facing right: medium-light skin tone
+1F6B6 1F3FC 200D 2640 FE0F 200D 27A1 ; minimally-qualified # 🚶🏼‍♀️‍➡ E15.1 woman walking facing right: medium-light skin tone
+1F6B6 1F3FC 200D 2640 200D 27A1 ; minimally-qualified # 🚶🏼‍♀‍➡ E15.1 woman walking facing right: medium-light skin tone
+1F6B6 1F3FD 200D 2640 FE0F 200D 27A1 FE0F ; fully-qualified # 🚶🏽‍♀️‍➡️ E15.1 woman walking facing right: medium skin tone
+1F6B6 1F3FD 200D 2640 200D 27A1 FE0F ; minimally-qualified # 🚶🏽‍♀‍➡️ E15.1 woman walking facing right: medium skin tone
+1F6B6 1F3FD 200D 2640 FE0F 200D 27A1 ; minimally-qualified # 🚶🏽‍♀️‍➡ E15.1 woman walking facing right: medium skin tone
+1F6B6 1F3FD 200D 2640 200D 27A1 ; minimally-qualified # 🚶🏽‍♀‍➡ E15.1 woman walking facing right: medium skin tone
+1F6B6 1F3FE 200D 2640 FE0F 200D 27A1 FE0F ; fully-qualified # 🚶🏾‍♀️‍➡️ E15.1 woman walking facing right: medium-dark skin tone
+1F6B6 1F3FE 200D 2640 200D 27A1 FE0F ; minimally-qualified # 🚶🏾‍♀‍➡️ E15.1 woman walking facing right: medium-dark skin tone
+1F6B6 1F3FE 200D 2640 FE0F 200D 27A1 ; minimally-qualified # 🚶🏾‍♀️‍➡ E15.1 woman walking facing right: medium-dark skin tone
+1F6B6 1F3FE 200D 2640 200D 27A1 ; minimally-qualified # 🚶🏾‍♀‍➡ E15.1 woman walking facing right: medium-dark skin tone
+1F6B6 1F3FF 200D 2640 FE0F 200D 27A1 FE0F ; fully-qualified # 🚶🏿‍♀️‍➡️ E15.1 woman walking facing right: dark skin tone
+1F6B6 1F3FF 200D 2640 200D 27A1 FE0F ; minimally-qualified # 🚶🏿‍♀‍➡️ E15.1 woman walking facing right: dark skin tone
+1F6B6 1F3FF 200D 2640 FE0F 200D 27A1 ; minimally-qualified # 🚶🏿‍♀️‍➡ E15.1 woman walking facing right: dark skin tone
+1F6B6 1F3FF 200D 2640 200D 27A1 ; minimally-qualified # 🚶🏿‍♀‍➡ E15.1 woman walking facing right: dark skin tone
+1F6B6 200D 2642 FE0F 200D 27A1 FE0F ; fully-qualified # 🚶‍♂️‍➡️ E15.1 man walking facing right
+1F6B6 200D 2642 200D 27A1 FE0F ; minimally-qualified # 🚶‍♂‍➡️ E15.1 man walking facing right
+1F6B6 200D 2642 FE0F 200D 27A1 ; minimally-qualified # 🚶‍♂️‍➡ E15.1 man walking facing right
+1F6B6 200D 2642 200D 27A1 ; minimally-qualified # 🚶‍♂‍➡ E15.1 man walking facing right
+1F6B6 1F3FB 200D 2642 FE0F 200D 27A1 FE0F ; fully-qualified # 🚶🏻‍♂️‍➡️ E15.1 man walking facing right: light skin tone
+1F6B6 1F3FB 200D 2642 200D 27A1 FE0F ; minimally-qualified # 🚶🏻‍♂‍➡️ E15.1 man walking facing right: light skin tone
+1F6B6 1F3FB 200D 2642 FE0F 200D 27A1 ; minimally-qualified # 🚶🏻‍♂️‍➡ E15.1 man walking facing right: light skin tone
+1F6B6 1F3FB 200D 2642 200D 27A1 ; minimally-qualified # 🚶🏻‍♂‍➡ E15.1 man walking facing right: light skin tone
+1F6B6 1F3FC 200D 2642 FE0F 200D 27A1 FE0F ; fully-qualified # 🚶🏼‍♂️‍➡️ E15.1 man walking facing right: medium-light skin tone
+1F6B6 1F3FC 200D 2642 200D 27A1 FE0F ; minimally-qualified # 🚶🏼‍♂‍➡️ E15.1 man walking facing right: medium-light skin tone
+1F6B6 1F3FC 200D 2642 FE0F 200D 27A1 ; minimally-qualified # 🚶🏼‍♂️‍➡ E15.1 man walking facing right: medium-light skin tone
+1F6B6 1F3FC 200D 2642 200D 27A1 ; minimally-qualified # 🚶🏼‍♂‍➡ E15.1 man walking facing right: medium-light skin tone
+1F6B6 1F3FD 200D 2642 FE0F 200D 27A1 FE0F ; fully-qualified # 🚶🏽‍♂️‍➡️ E15.1 man walking facing right: medium skin tone
+1F6B6 1F3FD 200D 2642 200D 27A1 FE0F ; minimally-qualified # 🚶🏽‍♂‍➡️ E15.1 man walking facing right: medium skin tone
+1F6B6 1F3FD 200D 2642 FE0F 200D 27A1 ; minimally-qualified # 🚶🏽‍♂️‍➡ E15.1 man walking facing right: medium skin tone
+1F6B6 1F3FD 200D 2642 200D 27A1 ; minimally-qualified # 🚶🏽‍♂‍➡ E15.1 man walking facing right: medium skin tone
+1F6B6 1F3FE 200D 2642 FE0F 200D 27A1 FE0F ; fully-qualified # 🚶🏾‍♂️‍➡️ E15.1 man walking facing right: medium-dark skin tone
+1F6B6 1F3FE 200D 2642 200D 27A1 FE0F ; minimally-qualified # 🚶🏾‍♂‍➡️ E15.1 man walking facing right: medium-dark skin tone
+1F6B6 1F3FE 200D 2642 FE0F 200D 27A1 ; minimally-qualified # 🚶🏾‍♂️‍➡ E15.1 man walking facing right: medium-dark skin tone
+1F6B6 1F3FE 200D 2642 200D 27A1 ; minimally-qualified # 🚶🏾‍♂‍➡ E15.1 man walking facing right: medium-dark skin tone
+1F6B6 1F3FF 200D 2642 FE0F 200D 27A1 FE0F ; fully-qualified # 🚶🏿‍♂️‍➡️ E15.1 man walking facing right: dark skin tone
+1F6B6 1F3FF 200D 2642 200D 27A1 FE0F ; minimally-qualified # 🚶🏿‍♂‍➡️ E15.1 man walking facing right: dark skin tone
+1F6B6 1F3FF 200D 2642 FE0F 200D 27A1 ; minimally-qualified # 🚶🏿‍♂️‍➡ E15.1 man walking facing right: dark skin tone
+1F6B6 1F3FF 200D 2642 200D 27A1 ; minimally-qualified # 🚶🏿‍♂‍➡ E15.1 man walking facing right: dark skin tone
1F9CD ; fully-qualified # 🧍 E12.0 person standing
1F9CD 1F3FB ; fully-qualified # 🧍🏻 E12.0 person standing: light skin tone
1F9CD 1F3FC ; fully-qualified # 🧍🏼 E12.0 person standing: medium-light skin tone
@@ -2125,60 +2189,228 @@
1F9CE 1F3FE 200D 2640 ; minimally-qualified # 🧎🏾‍♀ E12.0 woman kneeling: medium-dark skin tone
1F9CE 1F3FF 200D 2640 FE0F ; fully-qualified # 🧎🏿‍♀️ E12.0 woman kneeling: dark skin tone
1F9CE 1F3FF 200D 2640 ; minimally-qualified # 🧎🏿‍♀ E12.0 woman kneeling: dark skin tone
+1F9CE 200D 27A1 FE0F ; fully-qualified # 🧎‍➡️ E15.1 person kneeling facing right
+1F9CE 200D 27A1 ; minimally-qualified # 🧎‍➡ E15.1 person kneeling facing right
+1F9CE 1F3FB 200D 27A1 FE0F ; fully-qualified # 🧎🏻‍➡️ E15.1 person kneeling facing right: light skin tone
+1F9CE 1F3FB 200D 27A1 ; minimally-qualified # 🧎🏻‍➡ E15.1 person kneeling facing right: light skin tone
+1F9CE 1F3FC 200D 27A1 FE0F ; fully-qualified # 🧎🏼‍➡️ E15.1 person kneeling facing right: medium-light skin tone
+1F9CE 1F3FC 200D 27A1 ; minimally-qualified # 🧎🏼‍➡ E15.1 person kneeling facing right: medium-light skin tone
+1F9CE 1F3FD 200D 27A1 FE0F ; fully-qualified # 🧎🏽‍➡️ E15.1 person kneeling facing right: medium skin tone
+1F9CE 1F3FD 200D 27A1 ; minimally-qualified # 🧎🏽‍➡ E15.1 person kneeling facing right: medium skin tone
+1F9CE 1F3FE 200D 27A1 FE0F ; fully-qualified # 🧎🏾‍➡️ E15.1 person kneeling facing right: medium-dark skin tone
+1F9CE 1F3FE 200D 27A1 ; minimally-qualified # 🧎🏾‍➡ E15.1 person kneeling facing right: medium-dark skin tone
+1F9CE 1F3FF 200D 27A1 FE0F ; fully-qualified # 🧎🏿‍➡️ E15.1 person kneeling facing right: dark skin tone
+1F9CE 1F3FF 200D 27A1 ; minimally-qualified # 🧎🏿‍➡ E15.1 person kneeling facing right: dark skin tone
+1F9CE 200D 2640 FE0F 200D 27A1 FE0F ; fully-qualified # 🧎‍♀️‍➡️ E15.1 woman kneeling facing right
+1F9CE 200D 2640 200D 27A1 FE0F ; minimally-qualified # 🧎‍♀‍➡️ E15.1 woman kneeling facing right
+1F9CE 200D 2640 FE0F 200D 27A1 ; minimally-qualified # 🧎‍♀️‍➡ E15.1 woman kneeling facing right
+1F9CE 200D 2640 200D 27A1 ; minimally-qualified # 🧎‍♀‍➡ E15.1 woman kneeling facing right
+1F9CE 1F3FB 200D 2640 FE0F 200D 27A1 FE0F ; fully-qualified # 🧎🏻‍♀️‍➡️ E15.1 woman kneeling facing right: light skin tone
+1F9CE 1F3FB 200D 2640 200D 27A1 FE0F ; minimally-qualified # 🧎🏻‍♀‍➡️ E15.1 woman kneeling facing right: light skin tone
+1F9CE 1F3FB 200D 2640 FE0F 200D 27A1 ; minimally-qualified # 🧎🏻‍♀️‍➡ E15.1 woman kneeling facing right: light skin tone
+1F9CE 1F3FB 200D 2640 200D 27A1 ; minimally-qualified # 🧎🏻‍♀‍➡ E15.1 woman kneeling facing right: light skin tone
+1F9CE 1F3FC 200D 2640 FE0F 200D 27A1 FE0F ; fully-qualified # 🧎🏼‍♀️‍➡️ E15.1 woman kneeling facing right: medium-light skin tone
+1F9CE 1F3FC 200D 2640 200D 27A1 FE0F ; minimally-qualified # 🧎🏼‍♀‍➡️ E15.1 woman kneeling facing right: medium-light skin tone
+1F9CE 1F3FC 200D 2640 FE0F 200D 27A1 ; minimally-qualified # 🧎🏼‍♀️‍➡ E15.1 woman kneeling facing right: medium-light skin tone
+1F9CE 1F3FC 200D 2640 200D 27A1 ; minimally-qualified # 🧎🏼‍♀‍➡ E15.1 woman kneeling facing right: medium-light skin tone
+1F9CE 1F3FD 200D 2640 FE0F 200D 27A1 FE0F ; fully-qualified # 🧎🏽‍♀️‍➡️ E15.1 woman kneeling facing right: medium skin tone
+1F9CE 1F3FD 200D 2640 200D 27A1 FE0F ; minimally-qualified # 🧎🏽‍♀‍➡️ E15.1 woman kneeling facing right: medium skin tone
+1F9CE 1F3FD 200D 2640 FE0F 200D 27A1 ; minimally-qualified # 🧎🏽‍♀️‍➡ E15.1 woman kneeling facing right: medium skin tone
+1F9CE 1F3FD 200D 2640 200D 27A1 ; minimally-qualified # 🧎🏽‍♀‍➡ E15.1 woman kneeling facing right: medium skin tone
+1F9CE 1F3FE 200D 2640 FE0F 200D 27A1 FE0F ; fully-qualified # 🧎🏾‍♀️‍➡️ E15.1 woman kneeling facing right: medium-dark skin tone
+1F9CE 1F3FE 200D 2640 200D 27A1 FE0F ; minimally-qualified # 🧎🏾‍♀‍➡️ E15.1 woman kneeling facing right: medium-dark skin tone
+1F9CE 1F3FE 200D 2640 FE0F 200D 27A1 ; minimally-qualified # 🧎🏾‍♀️‍➡ E15.1 woman kneeling facing right: medium-dark skin tone
+1F9CE 1F3FE 200D 2640 200D 27A1 ; minimally-qualified # 🧎🏾‍♀‍➡ E15.1 woman kneeling facing right: medium-dark skin tone
+1F9CE 1F3FF 200D 2640 FE0F 200D 27A1 FE0F ; fully-qualified # 🧎🏿‍♀️‍➡️ E15.1 woman kneeling facing right: dark skin tone
+1F9CE 1F3FF 200D 2640 200D 27A1 FE0F ; minimally-qualified # 🧎🏿‍♀‍➡️ E15.1 woman kneeling facing right: dark skin tone
+1F9CE 1F3FF 200D 2640 FE0F 200D 27A1 ; minimally-qualified # 🧎🏿‍♀️‍➡ E15.1 woman kneeling facing right: dark skin tone
+1F9CE 1F3FF 200D 2640 200D 27A1 ; minimally-qualified # 🧎🏿‍♀‍➡ E15.1 woman kneeling facing right: dark skin tone
+1F9CE 200D 2642 FE0F 200D 27A1 FE0F ; fully-qualified # 🧎‍♂️‍➡️ E15.1 man kneeling facing right
+1F9CE 200D 2642 200D 27A1 FE0F ; minimally-qualified # 🧎‍♂‍➡️ E15.1 man kneeling facing right
+1F9CE 200D 2642 FE0F 200D 27A1 ; minimally-qualified # 🧎‍♂️‍➡ E15.1 man kneeling facing right
+1F9CE 200D 2642 200D 27A1 ; minimally-qualified # 🧎‍♂‍➡ E15.1 man kneeling facing right
+1F9CE 1F3FB 200D 2642 FE0F 200D 27A1 FE0F ; fully-qualified # 🧎🏻‍♂️‍➡️ E15.1 man kneeling facing right: light skin tone
+1F9CE 1F3FB 200D 2642 200D 27A1 FE0F ; minimally-qualified # 🧎🏻‍♂‍➡️ E15.1 man kneeling facing right: light skin tone
+1F9CE 1F3FB 200D 2642 FE0F 200D 27A1 ; minimally-qualified # 🧎🏻‍♂️‍➡ E15.1 man kneeling facing right: light skin tone
+1F9CE 1F3FB 200D 2642 200D 27A1 ; minimally-qualified # 🧎🏻‍♂‍➡ E15.1 man kneeling facing right: light skin tone
+1F9CE 1F3FC 200D 2642 FE0F 200D 27A1 FE0F ; fully-qualified # 🧎🏼‍♂️‍➡️ E15.1 man kneeling facing right: medium-light skin tone
+1F9CE 1F3FC 200D 2642 200D 27A1 FE0F ; minimally-qualified # 🧎🏼‍♂‍➡️ E15.1 man kneeling facing right: medium-light skin tone
+1F9CE 1F3FC 200D 2642 FE0F 200D 27A1 ; minimally-qualified # 🧎🏼‍♂️‍➡ E15.1 man kneeling facing right: medium-light skin tone
+1F9CE 1F3FC 200D 2642 200D 27A1 ; minimally-qualified # 🧎🏼‍♂‍➡ E15.1 man kneeling facing right: medium-light skin tone
+1F9CE 1F3FD 200D 2642 FE0F 200D 27A1 FE0F ; fully-qualified # 🧎🏽‍♂️‍➡️ E15.1 man kneeling facing right: medium skin tone
+1F9CE 1F3FD 200D 2642 200D 27A1 FE0F ; minimally-qualified # 🧎🏽‍♂‍➡️ E15.1 man kneeling facing right: medium skin tone
+1F9CE 1F3FD 200D 2642 FE0F 200D 27A1 ; minimally-qualified # 🧎🏽‍♂️‍➡ E15.1 man kneeling facing right: medium skin tone
+1F9CE 1F3FD 200D 2642 200D 27A1 ; minimally-qualified # 🧎🏽‍♂‍➡ E15.1 man kneeling facing right: medium skin tone
+1F9CE 1F3FE 200D 2642 FE0F 200D 27A1 FE0F ; fully-qualified # 🧎🏾‍♂️‍➡️ E15.1 man kneeling facing right: medium-dark skin tone
+1F9CE 1F3FE 200D 2642 200D 27A1 FE0F ; minimally-qualified # 🧎🏾‍♂‍➡️ E15.1 man kneeling facing right: medium-dark skin tone
+1F9CE 1F3FE 200D 2642 FE0F 200D 27A1 ; minimally-qualified # 🧎🏾‍♂️‍➡ E15.1 man kneeling facing right: medium-dark skin tone
+1F9CE 1F3FE 200D 2642 200D 27A1 ; minimally-qualified # 🧎🏾‍♂‍➡ E15.1 man kneeling facing right: medium-dark skin tone
+1F9CE 1F3FF 200D 2642 FE0F 200D 27A1 FE0F ; fully-qualified # 🧎🏿‍♂️‍➡️ E15.1 man kneeling facing right: dark skin tone
+1F9CE 1F3FF 200D 2642 200D 27A1 FE0F ; minimally-qualified # 🧎🏿‍♂‍➡️ E15.1 man kneeling facing right: dark skin tone
+1F9CE 1F3FF 200D 2642 FE0F 200D 27A1 ; minimally-qualified # 🧎🏿‍♂️‍➡ E15.1 man kneeling facing right: dark skin tone
+1F9CE 1F3FF 200D 2642 200D 27A1 ; minimally-qualified # 🧎🏿‍♂‍➡ E15.1 man kneeling facing right: dark skin tone
1F9D1 200D 1F9AF ; fully-qualified # 🧑‍🦯 E12.1 person with white cane
1F9D1 1F3FB 200D 1F9AF ; fully-qualified # 🧑🏻‍🦯 E12.1 person with white cane: light skin tone
1F9D1 1F3FC 200D 1F9AF ; fully-qualified # 🧑🏼‍🦯 E12.1 person with white cane: medium-light skin tone
1F9D1 1F3FD 200D 1F9AF ; fully-qualified # 🧑🏽‍🦯 E12.1 person with white cane: medium skin tone
1F9D1 1F3FE 200D 1F9AF ; fully-qualified # 🧑🏾‍🦯 E12.1 person with white cane: medium-dark skin tone
1F9D1 1F3FF 200D 1F9AF ; fully-qualified # 🧑🏿‍🦯 E12.1 person with white cane: dark skin tone
+1F9D1 200D 1F9AF 200D 27A1 FE0F ; fully-qualified # 🧑‍🦯‍➡️ E15.1 person with white cane facing right
+1F9D1 200D 1F9AF 200D 27A1 ; minimally-qualified # 🧑‍🦯‍➡ E15.1 person with white cane facing right
+1F9D1 1F3FB 200D 1F9AF 200D 27A1 FE0F ; fully-qualified # 🧑🏻‍🦯‍➡️ E15.1 person with white cane facing right: light skin tone
+1F9D1 1F3FB 200D 1F9AF 200D 27A1 ; minimally-qualified # 🧑🏻‍🦯‍➡ E15.1 person with white cane facing right: light skin tone
+1F9D1 1F3FC 200D 1F9AF 200D 27A1 FE0F ; fully-qualified # 🧑🏼‍🦯‍➡️ E15.1 person with white cane facing right: medium-light skin tone
+1F9D1 1F3FC 200D 1F9AF 200D 27A1 ; minimally-qualified # 🧑🏼‍🦯‍➡ E15.1 person with white cane facing right: medium-light skin tone
+1F9D1 1F3FD 200D 1F9AF 200D 27A1 FE0F ; fully-qualified # 🧑🏽‍🦯‍➡️ E15.1 person with white cane facing right: medium skin tone
+1F9D1 1F3FD 200D 1F9AF 200D 27A1 ; minimally-qualified # 🧑🏽‍🦯‍➡ E15.1 person with white cane facing right: medium skin tone
+1F9D1 1F3FE 200D 1F9AF 200D 27A1 FE0F ; fully-qualified # 🧑🏾‍🦯‍➡️ E15.1 person with white cane facing right: medium-dark skin tone
+1F9D1 1F3FE 200D 1F9AF 200D 27A1 ; minimally-qualified # 🧑🏾‍🦯‍➡ E15.1 person with white cane facing right: medium-dark skin tone
+1F9D1 1F3FF 200D 1F9AF 200D 27A1 FE0F ; fully-qualified # 🧑🏿‍🦯‍➡️ E15.1 person with white cane facing right: dark skin tone
+1F9D1 1F3FF 200D 1F9AF 200D 27A1 ; minimally-qualified # 🧑🏿‍🦯‍➡ E15.1 person with white cane facing right: dark skin tone
1F468 200D 1F9AF ; fully-qualified # 👨‍🦯 E12.0 man with white cane
1F468 1F3FB 200D 1F9AF ; fully-qualified # 👨🏻‍🦯 E12.0 man with white cane: light skin tone
1F468 1F3FC 200D 1F9AF ; fully-qualified # 👨🏼‍🦯 E12.0 man with white cane: medium-light skin tone
1F468 1F3FD 200D 1F9AF ; fully-qualified # 👨🏽‍🦯 E12.0 man with white cane: medium skin tone
1F468 1F3FE 200D 1F9AF ; fully-qualified # 👨🏾‍🦯 E12.0 man with white cane: medium-dark skin tone
1F468 1F3FF 200D 1F9AF ; fully-qualified # 👨🏿‍🦯 E12.0 man with white cane: dark skin tone
+1F468 200D 1F9AF 200D 27A1 FE0F ; fully-qualified # 👨‍🦯‍➡️ E15.1 man with white cane facing right
+1F468 200D 1F9AF 200D 27A1 ; minimally-qualified # 👨‍🦯‍➡ E15.1 man with white cane facing right
+1F468 1F3FB 200D 1F9AF 200D 27A1 FE0F ; fully-qualified # 👨🏻‍🦯‍➡️ E15.1 man with white cane facing right: light skin tone
+1F468 1F3FB 200D 1F9AF 200D 27A1 ; minimally-qualified # 👨🏻‍🦯‍➡ E15.1 man with white cane facing right: light skin tone
+1F468 1F3FC 200D 1F9AF 200D 27A1 FE0F ; fully-qualified # 👨🏼‍🦯‍➡️ E15.1 man with white cane facing right: medium-light skin tone
+1F468 1F3FC 200D 1F9AF 200D 27A1 ; minimally-qualified # 👨🏼‍🦯‍➡ E15.1 man with white cane facing right: medium-light skin tone
+1F468 1F3FD 200D 1F9AF 200D 27A1 FE0F ; fully-qualified # 👨🏽‍🦯‍➡️ E15.1 man with white cane facing right: medium skin tone
+1F468 1F3FD 200D 1F9AF 200D 27A1 ; minimally-qualified # 👨🏽‍🦯‍➡ E15.1 man with white cane facing right: medium skin tone
+1F468 1F3FE 200D 1F9AF 200D 27A1 FE0F ; fully-qualified # 👨🏾‍🦯‍➡️ E15.1 man with white cane facing right: medium-dark skin tone
+1F468 1F3FE 200D 1F9AF 200D 27A1 ; minimally-qualified # 👨🏾‍🦯‍➡ E15.1 man with white cane facing right: medium-dark skin tone
+1F468 1F3FF 200D 1F9AF 200D 27A1 FE0F ; fully-qualified # 👨🏿‍🦯‍➡️ E15.1 man with white cane facing right: dark skin tone
+1F468 1F3FF 200D 1F9AF 200D 27A1 ; minimally-qualified # 👨🏿‍🦯‍➡ E15.1 man with white cane facing right: dark skin tone
1F469 200D 1F9AF ; fully-qualified # 👩‍🦯 E12.0 woman with white cane
1F469 1F3FB 200D 1F9AF ; fully-qualified # 👩🏻‍🦯 E12.0 woman with white cane: light skin tone
1F469 1F3FC 200D 1F9AF ; fully-qualified # 👩🏼‍🦯 E12.0 woman with white cane: medium-light skin tone
1F469 1F3FD 200D 1F9AF ; fully-qualified # 👩🏽‍🦯 E12.0 woman with white cane: medium skin tone
1F469 1F3FE 200D 1F9AF ; fully-qualified # 👩🏾‍🦯 E12.0 woman with white cane: medium-dark skin tone
1F469 1F3FF 200D 1F9AF ; fully-qualified # 👩🏿‍🦯 E12.0 woman with white cane: dark skin tone
+1F469 200D 1F9AF 200D 27A1 FE0F ; fully-qualified # 👩‍🦯‍➡️ E15.1 woman with white cane facing right
+1F469 200D 1F9AF 200D 27A1 ; minimally-qualified # 👩‍🦯‍➡ E15.1 woman with white cane facing right
+1F469 1F3FB 200D 1F9AF 200D 27A1 FE0F ; fully-qualified # 👩🏻‍🦯‍➡️ E15.1 woman with white cane facing right: light skin tone
+1F469 1F3FB 200D 1F9AF 200D 27A1 ; minimally-qualified # 👩🏻‍🦯‍➡ E15.1 woman with white cane facing right: light skin tone
+1F469 1F3FC 200D 1F9AF 200D 27A1 FE0F ; fully-qualified # 👩🏼‍🦯‍➡️ E15.1 woman with white cane facing right: medium-light skin tone
+1F469 1F3FC 200D 1F9AF 200D 27A1 ; minimally-qualified # 👩🏼‍🦯‍➡ E15.1 woman with white cane facing right: medium-light skin tone
+1F469 1F3FD 200D 1F9AF 200D 27A1 FE0F ; fully-qualified # 👩🏽‍🦯‍➡️ E15.1 woman with white cane facing right: medium skin tone
+1F469 1F3FD 200D 1F9AF 200D 27A1 ; minimally-qualified # 👩🏽‍🦯‍➡ E15.1 woman with white cane facing right: medium skin tone
+1F469 1F3FE 200D 1F9AF 200D 27A1 FE0F ; fully-qualified # 👩🏾‍🦯‍➡️ E15.1 woman with white cane facing right: medium-dark skin tone
+1F469 1F3FE 200D 1F9AF 200D 27A1 ; minimally-qualified # 👩🏾‍🦯‍➡ E15.1 woman with white cane facing right: medium-dark skin tone
+1F469 1F3FF 200D 1F9AF 200D 27A1 FE0F ; fully-qualified # 👩🏿‍🦯‍➡️ E15.1 woman with white cane facing right: dark skin tone
+1F469 1F3FF 200D 1F9AF 200D 27A1 ; minimally-qualified # 👩🏿‍🦯‍➡ E15.1 woman with white cane facing right: dark skin tone
1F9D1 200D 1F9BC ; fully-qualified # 🧑‍🦼 E12.1 person in motorized wheelchair
1F9D1 1F3FB 200D 1F9BC ; fully-qualified # 🧑🏻‍🦼 E12.1 person in motorized wheelchair: light skin tone
1F9D1 1F3FC 200D 1F9BC ; fully-qualified # 🧑🏼‍🦼 E12.1 person in motorized wheelchair: medium-light skin tone
1F9D1 1F3FD 200D 1F9BC ; fully-qualified # 🧑🏽‍🦼 E12.1 person in motorized wheelchair: medium skin tone
1F9D1 1F3FE 200D 1F9BC ; fully-qualified # 🧑🏾‍🦼 E12.1 person in motorized wheelchair: medium-dark skin tone
1F9D1 1F3FF 200D 1F9BC ; fully-qualified # 🧑🏿‍🦼 E12.1 person in motorized wheelchair: dark skin tone
+1F9D1 200D 1F9BC 200D 27A1 FE0F ; fully-qualified # 🧑‍🦼‍➡️ E15.1 person in motorized wheelchair facing right
+1F9D1 200D 1F9BC 200D 27A1 ; minimally-qualified # 🧑‍🦼‍➡ E15.1 person in motorized wheelchair facing right
+1F9D1 1F3FB 200D 1F9BC 200D 27A1 FE0F ; fully-qualified # 🧑🏻‍🦼‍➡️ E15.1 person in motorized wheelchair facing right: light skin tone
+1F9D1 1F3FB 200D 1F9BC 200D 27A1 ; minimally-qualified # 🧑🏻‍🦼‍➡ E15.1 person in motorized wheelchair facing right: light skin tone
+1F9D1 1F3FC 200D 1F9BC 200D 27A1 FE0F ; fully-qualified # 🧑🏼‍🦼‍➡️ E15.1 person in motorized wheelchair facing right: medium-light skin tone
+1F9D1 1F3FC 200D 1F9BC 200D 27A1 ; minimally-qualified # 🧑🏼‍🦼‍➡ E15.1 person in motorized wheelchair facing right: medium-light skin tone
+1F9D1 1F3FD 200D 1F9BC 200D 27A1 FE0F ; fully-qualified # 🧑🏽‍🦼‍➡️ E15.1 person in motorized wheelchair facing right: medium skin tone
+1F9D1 1F3FD 200D 1F9BC 200D 27A1 ; minimally-qualified # 🧑🏽‍🦼‍➡ E15.1 person in motorized wheelchair facing right: medium skin tone
+1F9D1 1F3FE 200D 1F9BC 200D 27A1 FE0F ; fully-qualified # 🧑🏾‍🦼‍➡️ E15.1 person in motorized wheelchair facing right: medium-dark skin tone
+1F9D1 1F3FE 200D 1F9BC 200D 27A1 ; minimally-qualified # 🧑🏾‍🦼‍➡ E15.1 person in motorized wheelchair facing right: medium-dark skin tone
+1F9D1 1F3FF 200D 1F9BC 200D 27A1 FE0F ; fully-qualified # 🧑🏿‍🦼‍➡️ E15.1 person in motorized wheelchair facing right: dark skin tone
+1F9D1 1F3FF 200D 1F9BC 200D 27A1 ; minimally-qualified # 🧑🏿‍🦼‍➡ E15.1 person in motorized wheelchair facing right: dark skin tone
1F468 200D 1F9BC ; fully-qualified # 👨‍🦼 E12.0 man in motorized wheelchair
1F468 1F3FB 200D 1F9BC ; fully-qualified # 👨🏻‍🦼 E12.0 man in motorized wheelchair: light skin tone
1F468 1F3FC 200D 1F9BC ; fully-qualified # 👨🏼‍🦼 E12.0 man in motorized wheelchair: medium-light skin tone
1F468 1F3FD 200D 1F9BC ; fully-qualified # 👨🏽‍🦼 E12.0 man in motorized wheelchair: medium skin tone
1F468 1F3FE 200D 1F9BC ; fully-qualified # 👨🏾‍🦼 E12.0 man in motorized wheelchair: medium-dark skin tone
1F468 1F3FF 200D 1F9BC ; fully-qualified # 👨🏿‍🦼 E12.0 man in motorized wheelchair: dark skin tone
+1F468 200D 1F9BC 200D 27A1 FE0F ; fully-qualified # 👨‍🦼‍➡️ E15.1 man in motorized wheelchair facing right
+1F468 200D 1F9BC 200D 27A1 ; minimally-qualified # 👨‍🦼‍➡ E15.1 man in motorized wheelchair facing right
+1F468 1F3FB 200D 1F9BC 200D 27A1 FE0F ; fully-qualified # 👨🏻‍🦼‍➡️ E15.1 man in motorized wheelchair facing right: light skin tone
+1F468 1F3FB 200D 1F9BC 200D 27A1 ; minimally-qualified # 👨🏻‍🦼‍➡ E15.1 man in motorized wheelchair facing right: light skin tone
+1F468 1F3FC 200D 1F9BC 200D 27A1 FE0F ; fully-qualified # 👨🏼‍🦼‍➡️ E15.1 man in motorized wheelchair facing right: medium-light skin tone
+1F468 1F3FC 200D 1F9BC 200D 27A1 ; minimally-qualified # 👨🏼‍🦼‍➡ E15.1 man in motorized wheelchair facing right: medium-light skin tone
+1F468 1F3FD 200D 1F9BC 200D 27A1 FE0F ; fully-qualified # 👨🏽‍🦼‍➡️ E15.1 man in motorized wheelchair facing right: medium skin tone
+1F468 1F3FD 200D 1F9BC 200D 27A1 ; minimally-qualified # 👨🏽‍🦼‍➡ E15.1 man in motorized wheelchair facing right: medium skin tone
+1F468 1F3FE 200D 1F9BC 200D 27A1 FE0F ; fully-qualified # 👨🏾‍🦼‍➡️ E15.1 man in motorized wheelchair facing right: medium-dark skin tone
+1F468 1F3FE 200D 1F9BC 200D 27A1 ; minimally-qualified # 👨🏾‍🦼‍➡ E15.1 man in motorized wheelchair facing right: medium-dark skin tone
+1F468 1F3FF 200D 1F9BC 200D 27A1 FE0F ; fully-qualified # 👨🏿‍🦼‍➡️ E15.1 man in motorized wheelchair facing right: dark skin tone
+1F468 1F3FF 200D 1F9BC 200D 27A1 ; minimally-qualified # 👨🏿‍🦼‍➡ E15.1 man in motorized wheelchair facing right: dark skin tone
1F469 200D 1F9BC ; fully-qualified # 👩‍🦼 E12.0 woman in motorized wheelchair
1F469 1F3FB 200D 1F9BC ; fully-qualified # 👩🏻‍🦼 E12.0 woman in motorized wheelchair: light skin tone
1F469 1F3FC 200D 1F9BC ; fully-qualified # 👩🏼‍🦼 E12.0 woman in motorized wheelchair: medium-light skin tone
1F469 1F3FD 200D 1F9BC ; fully-qualified # 👩🏽‍🦼 E12.0 woman in motorized wheelchair: medium skin tone
1F469 1F3FE 200D 1F9BC ; fully-qualified # 👩🏾‍🦼 E12.0 woman in motorized wheelchair: medium-dark skin tone
1F469 1F3FF 200D 1F9BC ; fully-qualified # 👩🏿‍🦼 E12.0 woman in motorized wheelchair: dark skin tone
+1F469 200D 1F9BC 200D 27A1 FE0F ; fully-qualified # 👩‍🦼‍➡️ E15.1 woman in motorized wheelchair facing right
+1F469 200D 1F9BC 200D 27A1 ; minimally-qualified # 👩‍🦼‍➡ E15.1 woman in motorized wheelchair facing right
+1F469 1F3FB 200D 1F9BC 200D 27A1 FE0F ; fully-qualified # 👩🏻‍🦼‍➡️ E15.1 woman in motorized wheelchair facing right: light skin tone
+1F469 1F3FB 200D 1F9BC 200D 27A1 ; minimally-qualified # 👩🏻‍🦼‍➡ E15.1 woman in motorized wheelchair facing right: light skin tone
+1F469 1F3FC 200D 1F9BC 200D 27A1 FE0F ; fully-qualified # 👩🏼‍🦼‍➡️ E15.1 woman in motorized wheelchair facing right: medium-light skin tone
+1F469 1F3FC 200D 1F9BC 200D 27A1 ; minimally-qualified # 👩🏼‍🦼‍➡ E15.1 woman in motorized wheelchair facing right: medium-light skin tone
+1F469 1F3FD 200D 1F9BC 200D 27A1 FE0F ; fully-qualified # 👩🏽‍🦼‍➡️ E15.1 woman in motorized wheelchair facing right: medium skin tone
+1F469 1F3FD 200D 1F9BC 200D 27A1 ; minimally-qualified # 👩🏽‍🦼‍➡ E15.1 woman in motorized wheelchair facing right: medium skin tone
+1F469 1F3FE 200D 1F9BC 200D 27A1 FE0F ; fully-qualified # 👩🏾‍🦼‍➡️ E15.1 woman in motorized wheelchair facing right: medium-dark skin tone
+1F469 1F3FE 200D 1F9BC 200D 27A1 ; minimally-qualified # 👩🏾‍🦼‍➡ E15.1 woman in motorized wheelchair facing right: medium-dark skin tone
+1F469 1F3FF 200D 1F9BC 200D 27A1 FE0F ; fully-qualified # 👩🏿‍🦼‍➡️ E15.1 woman in motorized wheelchair facing right: dark skin tone
+1F469 1F3FF 200D 1F9BC 200D 27A1 ; minimally-qualified # 👩🏿‍🦼‍➡ E15.1 woman in motorized wheelchair facing right: dark skin tone
1F9D1 200D 1F9BD ; fully-qualified # 🧑‍🦽 E12.1 person in manual wheelchair
1F9D1 1F3FB 200D 1F9BD ; fully-qualified # 🧑🏻‍🦽 E12.1 person in manual wheelchair: light skin tone
1F9D1 1F3FC 200D 1F9BD ; fully-qualified # 🧑🏼‍🦽 E12.1 person in manual wheelchair: medium-light skin tone
1F9D1 1F3FD 200D 1F9BD ; fully-qualified # 🧑🏽‍🦽 E12.1 person in manual wheelchair: medium skin tone
1F9D1 1F3FE 200D 1F9BD ; fully-qualified # 🧑🏾‍🦽 E12.1 person in manual wheelchair: medium-dark skin tone
1F9D1 1F3FF 200D 1F9BD ; fully-qualified # 🧑🏿‍🦽 E12.1 person in manual wheelchair: dark skin tone
+1F9D1 200D 1F9BD 200D 27A1 FE0F ; fully-qualified # 🧑‍🦽‍➡️ E15.1 person in manual wheelchair facing right
+1F9D1 200D 1F9BD 200D 27A1 ; minimally-qualified # 🧑‍🦽‍➡ E15.1 person in manual wheelchair facing right
+1F9D1 1F3FB 200D 1F9BD 200D 27A1 FE0F ; fully-qualified # 🧑🏻‍🦽‍➡️ E15.1 person in manual wheelchair facing right: light skin tone
+1F9D1 1F3FB 200D 1F9BD 200D 27A1 ; minimally-qualified # 🧑🏻‍🦽‍➡ E15.1 person in manual wheelchair facing right: light skin tone
+1F9D1 1F3FC 200D 1F9BD 200D 27A1 FE0F ; fully-qualified # 🧑🏼‍🦽‍➡️ E15.1 person in manual wheelchair facing right: medium-light skin tone
+1F9D1 1F3FC 200D 1F9BD 200D 27A1 ; minimally-qualified # 🧑🏼‍🦽‍➡ E15.1 person in manual wheelchair facing right: medium-light skin tone
+1F9D1 1F3FD 200D 1F9BD 200D 27A1 FE0F ; fully-qualified # 🧑🏽‍🦽‍➡️ E15.1 person in manual wheelchair facing right: medium skin tone
+1F9D1 1F3FD 200D 1F9BD 200D 27A1 ; minimally-qualified # 🧑🏽‍🦽‍➡ E15.1 person in manual wheelchair facing right: medium skin tone
+1F9D1 1F3FE 200D 1F9BD 200D 27A1 FE0F ; fully-qualified # 🧑🏾‍🦽‍➡️ E15.1 person in manual wheelchair facing right: medium-dark skin tone
+1F9D1 1F3FE 200D 1F9BD 200D 27A1 ; minimally-qualified # 🧑🏾‍🦽‍➡ E15.1 person in manual wheelchair facing right: medium-dark skin tone
+1F9D1 1F3FF 200D 1F9BD 200D 27A1 FE0F ; fully-qualified # 🧑🏿‍🦽‍➡️ E15.1 person in manual wheelchair facing right: dark skin tone
+1F9D1 1F3FF 200D 1F9BD 200D 27A1 ; minimally-qualified # 🧑🏿‍🦽‍➡ E15.1 person in manual wheelchair facing right: dark skin tone
1F468 200D 1F9BD ; fully-qualified # 👨‍🦽 E12.0 man in manual wheelchair
1F468 1F3FB 200D 1F9BD ; fully-qualified # 👨🏻‍🦽 E12.0 man in manual wheelchair: light skin tone
1F468 1F3FC 200D 1F9BD ; fully-qualified # 👨🏼‍🦽 E12.0 man in manual wheelchair: medium-light skin tone
1F468 1F3FD 200D 1F9BD ; fully-qualified # 👨🏽‍🦽 E12.0 man in manual wheelchair: medium skin tone
1F468 1F3FE 200D 1F9BD ; fully-qualified # 👨🏾‍🦽 E12.0 man in manual wheelchair: medium-dark skin tone
1F468 1F3FF 200D 1F9BD ; fully-qualified # 👨🏿‍🦽 E12.0 man in manual wheelchair: dark skin tone
+1F468 200D 1F9BD 200D 27A1 FE0F ; fully-qualified # 👨‍🦽‍➡️ E15.1 man in manual wheelchair facing right
+1F468 200D 1F9BD 200D 27A1 ; minimally-qualified # 👨‍🦽‍➡ E15.1 man in manual wheelchair facing right
+1F468 1F3FB 200D 1F9BD 200D 27A1 FE0F ; fully-qualified # 👨🏻‍🦽‍➡️ E15.1 man in manual wheelchair facing right: light skin tone
+1F468 1F3FB 200D 1F9BD 200D 27A1 ; minimally-qualified # 👨🏻‍🦽‍➡ E15.1 man in manual wheelchair facing right: light skin tone
+1F468 1F3FC 200D 1F9BD 200D 27A1 FE0F ; fully-qualified # 👨🏼‍🦽‍➡️ E15.1 man in manual wheelchair facing right: medium-light skin tone
+1F468 1F3FC 200D 1F9BD 200D 27A1 ; minimally-qualified # 👨🏼‍🦽‍➡ E15.1 man in manual wheelchair facing right: medium-light skin tone
+1F468 1F3FD 200D 1F9BD 200D 27A1 FE0F ; fully-qualified # 👨🏽‍🦽‍➡️ E15.1 man in manual wheelchair facing right: medium skin tone
+1F468 1F3FD 200D 1F9BD 200D 27A1 ; minimally-qualified # 👨🏽‍🦽‍➡ E15.1 man in manual wheelchair facing right: medium skin tone
+1F468 1F3FE 200D 1F9BD 200D 27A1 FE0F ; fully-qualified # 👨🏾‍🦽‍➡️ E15.1 man in manual wheelchair facing right: medium-dark skin tone
+1F468 1F3FE 200D 1F9BD 200D 27A1 ; minimally-qualified # 👨🏾‍🦽‍➡ E15.1 man in manual wheelchair facing right: medium-dark skin tone
+1F468 1F3FF 200D 1F9BD 200D 27A1 FE0F ; fully-qualified # 👨🏿‍🦽‍➡️ E15.1 man in manual wheelchair facing right: dark skin tone
+1F468 1F3FF 200D 1F9BD 200D 27A1 ; minimally-qualified # 👨🏿‍🦽‍➡ E15.1 man in manual wheelchair facing right: dark skin tone
1F469 200D 1F9BD ; fully-qualified # 👩‍🦽 E12.0 woman in manual wheelchair
1F469 1F3FB 200D 1F9BD ; fully-qualified # 👩🏻‍🦽 E12.0 woman in manual wheelchair: light skin tone
1F469 1F3FC 200D 1F9BD ; fully-qualified # 👩🏼‍🦽 E12.0 woman in manual wheelchair: medium-light skin tone
1F469 1F3FD 200D 1F9BD ; fully-qualified # 👩🏽‍🦽 E12.0 woman in manual wheelchair: medium skin tone
1F469 1F3FE 200D 1F9BD ; fully-qualified # 👩🏾‍🦽 E12.0 woman in manual wheelchair: medium-dark skin tone
1F469 1F3FF 200D 1F9BD ; fully-qualified # 👩🏿‍🦽 E12.0 woman in manual wheelchair: dark skin tone
+1F469 200D 1F9BD 200D 27A1 FE0F ; fully-qualified # 👩‍🦽‍➡️ E15.1 woman in manual wheelchair facing right
+1F469 200D 1F9BD 200D 27A1 ; minimally-qualified # 👩‍🦽‍➡ E15.1 woman in manual wheelchair facing right
+1F469 1F3FB 200D 1F9BD 200D 27A1 FE0F ; fully-qualified # 👩🏻‍🦽‍➡️ E15.1 woman in manual wheelchair facing right: light skin tone
+1F469 1F3FB 200D 1F9BD 200D 27A1 ; minimally-qualified # 👩🏻‍🦽‍➡ E15.1 woman in manual wheelchair facing right: light skin tone
+1F469 1F3FC 200D 1F9BD 200D 27A1 FE0F ; fully-qualified # 👩🏼‍🦽‍➡️ E15.1 woman in manual wheelchair facing right: medium-light skin tone
+1F469 1F3FC 200D 1F9BD 200D 27A1 ; minimally-qualified # 👩🏼‍🦽‍➡ E15.1 woman in manual wheelchair facing right: medium-light skin tone
+1F469 1F3FD 200D 1F9BD 200D 27A1 FE0F ; fully-qualified # 👩🏽‍🦽‍➡️ E15.1 woman in manual wheelchair facing right: medium skin tone
+1F469 1F3FD 200D 1F9BD 200D 27A1 ; minimally-qualified # 👩🏽‍🦽‍➡ E15.1 woman in manual wheelchair facing right: medium skin tone
+1F469 1F3FE 200D 1F9BD 200D 27A1 FE0F ; fully-qualified # 👩🏾‍🦽‍➡️ E15.1 woman in manual wheelchair facing right: medium-dark skin tone
+1F469 1F3FE 200D 1F9BD 200D 27A1 ; minimally-qualified # 👩🏾‍🦽‍➡ E15.1 woman in manual wheelchair facing right: medium-dark skin tone
+1F469 1F3FF 200D 1F9BD 200D 27A1 FE0F ; fully-qualified # 👩🏿‍🦽‍➡️ E15.1 woman in manual wheelchair facing right: dark skin tone
+1F469 1F3FF 200D 1F9BD 200D 27A1 ; minimally-qualified # 👩🏿‍🦽‍➡ E15.1 woman in manual wheelchair facing right: dark skin tone
1F3C3 ; fully-qualified # 🏃 E0.6 person running
1F3C3 1F3FB ; fully-qualified # 🏃🏻 E1.0 person running: light skin tone
1F3C3 1F3FC ; fully-qualified # 🏃🏼 E1.0 person running: medium-light skin tone
@@ -2209,6 +2441,66 @@
1F3C3 1F3FE 200D 2640 ; minimally-qualified # 🏃🏾‍♀ E4.0 woman running: medium-dark skin tone
1F3C3 1F3FF 200D 2640 FE0F ; fully-qualified # 🏃🏿‍♀️ E4.0 woman running: dark skin tone
1F3C3 1F3FF 200D 2640 ; minimally-qualified # 🏃🏿‍♀ E4.0 woman running: dark skin tone
+1F3C3 200D 27A1 FE0F ; fully-qualified # 🏃‍➡️ E15.1 person running facing right
+1F3C3 200D 27A1 ; minimally-qualified # 🏃‍➡ E15.1 person running facing right
+1F3C3 1F3FB 200D 27A1 FE0F ; fully-qualified # 🏃🏻‍➡️ E15.1 person running facing right: light skin tone
+1F3C3 1F3FB 200D 27A1 ; minimally-qualified # 🏃🏻‍➡ E15.1 person running facing right: light skin tone
+1F3C3 1F3FC 200D 27A1 FE0F ; fully-qualified # 🏃🏼‍➡️ E15.1 person running facing right: medium-light skin tone
+1F3C3 1F3FC 200D 27A1 ; minimally-qualified # 🏃🏼‍➡ E15.1 person running facing right: medium-light skin tone
+1F3C3 1F3FD 200D 27A1 FE0F ; fully-qualified # 🏃🏽‍➡️ E15.1 person running facing right: medium skin tone
+1F3C3 1F3FD 200D 27A1 ; minimally-qualified # 🏃🏽‍➡ E15.1 person running facing right: medium skin tone
+1F3C3 1F3FE 200D 27A1 FE0F ; fully-qualified # 🏃🏾‍➡️ E15.1 person running facing right: medium-dark skin tone
+1F3C3 1F3FE 200D 27A1 ; minimally-qualified # 🏃🏾‍➡ E15.1 person running facing right: medium-dark skin tone
+1F3C3 1F3FF 200D 27A1 FE0F ; fully-qualified # 🏃🏿‍➡️ E15.1 person running facing right: dark skin tone
+1F3C3 1F3FF 200D 27A1 ; minimally-qualified # 🏃🏿‍➡ E15.1 person running facing right: dark skin tone
+1F3C3 200D 2640 FE0F 200D 27A1 FE0F ; fully-qualified # 🏃‍♀️‍➡️ E15.1 woman running facing right
+1F3C3 200D 2640 200D 27A1 FE0F ; minimally-qualified # 🏃‍♀‍➡️ E15.1 woman running facing right
+1F3C3 200D 2640 FE0F 200D 27A1 ; minimally-qualified # 🏃‍♀️‍➡ E15.1 woman running facing right
+1F3C3 200D 2640 200D 27A1 ; minimally-qualified # 🏃‍♀‍➡ E15.1 woman running facing right
+1F3C3 1F3FB 200D 2640 FE0F 200D 27A1 FE0F ; fully-qualified # 🏃🏻‍♀️‍➡️ E15.1 woman running facing right: light skin tone
+1F3C3 1F3FB 200D 2640 200D 27A1 FE0F ; minimally-qualified # 🏃🏻‍♀‍➡️ E15.1 woman running facing right: light skin tone
+1F3C3 1F3FB 200D 2640 FE0F 200D 27A1 ; minimally-qualified # 🏃🏻‍♀️‍➡ E15.1 woman running facing right: light skin tone
+1F3C3 1F3FB 200D 2640 200D 27A1 ; minimally-qualified # 🏃🏻‍♀‍➡ E15.1 woman running facing right: light skin tone
+1F3C3 1F3FC 200D 2640 FE0F 200D 27A1 FE0F ; fully-qualified # 🏃🏼‍♀️‍➡️ E15.1 woman running facing right: medium-light skin tone
+1F3C3 1F3FC 200D 2640 200D 27A1 FE0F ; minimally-qualified # 🏃🏼‍♀‍➡️ E15.1 woman running facing right: medium-light skin tone
+1F3C3 1F3FC 200D 2640 FE0F 200D 27A1 ; minimally-qualified # 🏃🏼‍♀️‍➡ E15.1 woman running facing right: medium-light skin tone
+1F3C3 1F3FC 200D 2640 200D 27A1 ; minimally-qualified # 🏃🏼‍♀‍➡ E15.1 woman running facing right: medium-light skin tone
+1F3C3 1F3FD 200D 2640 FE0F 200D 27A1 FE0F ; fully-qualified # 🏃🏽‍♀️‍➡️ E15.1 woman running facing right: medium skin tone
+1F3C3 1F3FD 200D 2640 200D 27A1 FE0F ; minimally-qualified # 🏃🏽‍♀‍➡️ E15.1 woman running facing right: medium skin tone
+1F3C3 1F3FD 200D 2640 FE0F 200D 27A1 ; minimally-qualified # 🏃🏽‍♀️‍➡ E15.1 woman running facing right: medium skin tone
+1F3C3 1F3FD 200D 2640 200D 27A1 ; minimally-qualified # 🏃🏽‍♀‍➡ E15.1 woman running facing right: medium skin tone
+1F3C3 1F3FE 200D 2640 FE0F 200D 27A1 FE0F ; fully-qualified # 🏃🏾‍♀️‍➡️ E15.1 woman running facing right: medium-dark skin tone
+1F3C3 1F3FE 200D 2640 200D 27A1 FE0F ; minimally-qualified # 🏃🏾‍♀‍➡️ E15.1 woman running facing right: medium-dark skin tone
+1F3C3 1F3FE 200D 2640 FE0F 200D 27A1 ; minimally-qualified # 🏃🏾‍♀️‍➡ E15.1 woman running facing right: medium-dark skin tone
+1F3C3 1F3FE 200D 2640 200D 27A1 ; minimally-qualified # 🏃🏾‍♀‍➡ E15.1 woman running facing right: medium-dark skin tone
+1F3C3 1F3FF 200D 2640 FE0F 200D 27A1 FE0F ; fully-qualified # 🏃🏿‍♀️‍➡️ E15.1 woman running facing right: dark skin tone
+1F3C3 1F3FF 200D 2640 200D 27A1 FE0F ; minimally-qualified # 🏃🏿‍♀‍➡️ E15.1 woman running facing right: dark skin tone
+1F3C3 1F3FF 200D 2640 FE0F 200D 27A1 ; minimally-qualified # 🏃🏿‍♀️‍➡ E15.1 woman running facing right: dark skin tone
+1F3C3 1F3FF 200D 2640 200D 27A1 ; minimally-qualified # 🏃🏿‍♀‍➡ E15.1 woman running facing right: dark skin tone
+1F3C3 200D 2642 FE0F 200D 27A1 FE0F ; fully-qualified # 🏃‍♂️‍➡️ E15.1 man running facing right
+1F3C3 200D 2642 200D 27A1 FE0F ; minimally-qualified # 🏃‍♂‍➡️ E15.1 man running facing right
+1F3C3 200D 2642 FE0F 200D 27A1 ; minimally-qualified # 🏃‍♂️‍➡ E15.1 man running facing right
+1F3C3 200D 2642 200D 27A1 ; minimally-qualified # 🏃‍♂‍➡ E15.1 man running facing right
+1F3C3 1F3FB 200D 2642 FE0F 200D 27A1 FE0F ; fully-qualified # 🏃🏻‍♂️‍➡️ E15.1 man running facing right: light skin tone
+1F3C3 1F3FB 200D 2642 200D 27A1 FE0F ; minimally-qualified # 🏃🏻‍♂‍➡️ E15.1 man running facing right: light skin tone
+1F3C3 1F3FB 200D 2642 FE0F 200D 27A1 ; minimally-qualified # 🏃🏻‍♂️‍➡ E15.1 man running facing right: light skin tone
+1F3C3 1F3FB 200D 2642 200D 27A1 ; minimally-qualified # 🏃🏻‍♂‍➡ E15.1 man running facing right: light skin tone
+1F3C3 1F3FC 200D 2642 FE0F 200D 27A1 FE0F ; fully-qualified # 🏃🏼‍♂️‍➡️ E15.1 man running facing right: medium-light skin tone
+1F3C3 1F3FC 200D 2642 200D 27A1 FE0F ; minimally-qualified # 🏃🏼‍♂‍➡️ E15.1 man running facing right: medium-light skin tone
+1F3C3 1F3FC 200D 2642 FE0F 200D 27A1 ; minimally-qualified # 🏃🏼‍♂️‍➡ E15.1 man running facing right: medium-light skin tone
+1F3C3 1F3FC 200D 2642 200D 27A1 ; minimally-qualified # 🏃🏼‍♂‍➡ E15.1 man running facing right: medium-light skin tone
+1F3C3 1F3FD 200D 2642 FE0F 200D 27A1 FE0F ; fully-qualified # 🏃🏽‍♂️‍➡️ E15.1 man running facing right: medium skin tone
+1F3C3 1F3FD 200D 2642 200D 27A1 FE0F ; minimally-qualified # 🏃🏽‍♂‍➡️ E15.1 man running facing right: medium skin tone
+1F3C3 1F3FD 200D 2642 FE0F 200D 27A1 ; minimally-qualified # 🏃🏽‍♂️‍➡ E15.1 man running facing right: medium skin tone
+1F3C3 1F3FD 200D 2642 200D 27A1 ; minimally-qualified # 🏃🏽‍♂‍➡ E15.1 man running facing right: medium skin tone
+1F3C3 1F3FE 200D 2642 FE0F 200D 27A1 FE0F ; fully-qualified # 🏃🏾‍♂️‍➡️ E15.1 man running facing right: medium-dark skin tone
+1F3C3 1F3FE 200D 2642 200D 27A1 FE0F ; minimally-qualified # 🏃🏾‍♂‍➡️ E15.1 man running facing right: medium-dark skin tone
+1F3C3 1F3FE 200D 2642 FE0F 200D 27A1 ; minimally-qualified # 🏃🏾‍♂️‍➡ E15.1 man running facing right: medium-dark skin tone
+1F3C3 1F3FE 200D 2642 200D 27A1 ; minimally-qualified # 🏃🏾‍♂‍➡ E15.1 man running facing right: medium-dark skin tone
+1F3C3 1F3FF 200D 2642 FE0F 200D 27A1 FE0F ; fully-qualified # 🏃🏿‍♂️‍➡️ E15.1 man running facing right: dark skin tone
+1F3C3 1F3FF 200D 2642 200D 27A1 FE0F ; minimally-qualified # 🏃🏿‍♂‍➡️ E15.1 man running facing right: dark skin tone
+1F3C3 1F3FF 200D 2642 FE0F 200D 27A1 ; minimally-qualified # 🏃🏿‍♂️‍➡ E15.1 man running facing right: dark skin tone
+1F3C3 1F3FF 200D 2642 200D 27A1 ; minimally-qualified # 🏃🏿‍♂‍➡ E15.1 man running facing right: dark skin tone
1F483 ; fully-qualified # 💃 E0.6 woman dancing
1F483 1F3FB ; fully-qualified # 💃🏻 E1.0 woman dancing: light skin tone
1F483 1F3FC ; fully-qualified # 💃🏼 E1.0 woman dancing: medium-light skin tone
@@ -3244,7 +3536,6 @@
1F469 1F3FF 200D 2764 200D 1F469 1F3FE ; minimally-qualified # 👩🏿‍❤‍👩🏾 E13.1 couple with heart: woman, woman, dark skin tone, medium-dark skin tone
1F469 1F3FF 200D 2764 FE0F 200D 1F469 1F3FF ; fully-qualified # 👩🏿‍❤️‍👩🏿 E13.1 couple with heart: woman, woman, dark skin tone
1F469 1F3FF 200D 2764 200D 1F469 1F3FF ; minimally-qualified # 👩🏿‍❤‍👩🏿 E13.1 couple with heart: woman, woman, dark skin tone
-1F46A ; fully-qualified # 👪 E0.6 family
1F468 200D 1F469 200D 1F466 ; fully-qualified # 👨‍👩‍👦 E2.0 family: man, woman, boy
1F468 200D 1F469 200D 1F467 ; fully-qualified # 👨‍👩‍👧 E2.0 family: man, woman, girl
1F468 200D 1F469 200D 1F467 200D 1F466 ; fully-qualified # 👨‍👩‍👧‍👦 E2.0 family: man, woman, girl, boy
@@ -3277,10 +3568,15 @@
1F464 ; fully-qualified # 👤 E0.6 bust in silhouette
1F465 ; fully-qualified # 👥 E1.0 busts in silhouette
1FAC2 ; fully-qualified # 🫂 E13.0 people hugging
+1F46A ; fully-qualified # 👪 E0.6 family
+1F9D1 200D 1F9D1 200D 1F9D2 ; fully-qualified # 🧑‍🧑‍🧒 E15.1 family: adult, adult, child
+1F9D1 200D 1F9D1 200D 1F9D2 200D 1F9D2 ; fully-qualified # 🧑‍🧑‍🧒‍🧒 E15.1 family: adult, adult, child, child
+1F9D1 200D 1F9D2 ; fully-qualified # 🧑‍🧒 E15.1 family: adult, child
+1F9D1 200D 1F9D2 200D 1F9D2 ; fully-qualified # 🧑‍🧒‍🧒 E15.1 family: adult, child, child
1F463 ; fully-qualified # 👣 E0.6 footprints
-# People & Body subtotal: 2998
-# People & Body subtotal: 508 w/o modifiers
+# People & Body subtotal: 3290
+# People & Body subtotal: 560 w/o modifiers
# group: Component
@@ -3395,6 +3691,7 @@
1FABD ; fully-qualified # 🪽 E15.0 wing
1F426 200D 2B1B ; fully-qualified # 🐦‍⬛ E15.0 black bird
1FABF ; fully-qualified # 🪿 E15.0 goose
+1F426 200D 1F525 ; fully-qualified # 🐦‍🔥 E15.1 phoenix
# subgroup: animal-amphibian
1F438 ; fully-qualified # 🐸 E0.6 frog
@@ -3477,8 +3774,8 @@
1FABA ; fully-qualified # 🪺 E14.0 nest with eggs
1F344 ; fully-qualified # 🍄 E0.6 mushroom
-# Animals & Nature subtotal: 159
-# Animals & Nature subtotal: 159 w/o modifiers
+# Animals & Nature subtotal: 160
+# Animals & Nature subtotal: 160 w/o modifiers
# group: Food & Drink
@@ -3488,6 +3785,7 @@
1F349 ; fully-qualified # 🍉 E0.6 watermelon
1F34A ; fully-qualified # 🍊 E0.6 tangerine
1F34B ; fully-qualified # 🍋 E1.0 lemon
+1F34B 200D 1F7E9 ; fully-qualified # 🍋‍🟩 E15.1 lime
1F34C ; fully-qualified # 🍌 E0.6 banana
1F34D ; fully-qualified # 🍍 E0.6 pineapple
1F96D ; fully-qualified # 🥭 E11.0 mango
@@ -3522,6 +3820,7 @@
1F330 ; fully-qualified # 🌰 E0.6 chestnut
1FADA ; fully-qualified # 🫚 E15.0 ginger root
1FADB ; fully-qualified # 🫛 E15.0 pea pod
+1F344 200D 1F7EB ; fully-qualified # 🍄‍🟫 E15.1 brown mushroom
# subgroup: food-prepared
1F35E ; fully-qualified # 🍞 E0.6 bread
@@ -3633,8 +3932,8 @@
1FAD9 ; fully-qualified # 🫙 E14.0 jar
1F3FA ; fully-qualified # 🏺 E1.0 amphora
-# Food & Drink subtotal: 135
-# Food & Drink subtotal: 135 w/o modifiers
+# Food & Drink subtotal: 137
+# Food & Drink subtotal: 137 w/o modifiers
# group: Travel & Places
@@ -4321,6 +4620,8 @@
2696 ; unqualified # ⚖ E1.0 balance scale
1F9AF ; fully-qualified # 🦯 E12.0 white cane
1F517 ; fully-qualified # 🔗 E0.6 link
+26D3 FE0F 200D 1F4A5 ; fully-qualified # ⛓️‍💥 E15.1 broken chain
+26D3 200D 1F4A5 ; unqualified # ⛓‍💥 E15.1 broken chain
26D3 FE0F ; fully-qualified # ⛓️ E0.7 chains
26D3 ; unqualified # ⛓ E0.7 chains
1FA9D ; fully-qualified # 🪝 E13.0 hook
@@ -4389,8 +4690,8 @@
1FAA7 ; fully-qualified # 🪧 E13.0 placard
1FAAA ; fully-qualified # 🪪 E14.0 identification card
-# Objects subtotal: 310
-# Objects subtotal: 310 w/o modifiers
+# Objects subtotal: 312
+# Objects subtotal: 312 w/o modifiers
# group: Symbols
@@ -4979,7 +5280,7 @@
1F1F9 1F1F2 ; fully-qualified # 🇹🇲 E2.0 flag: Turkmenistan
1F1F9 1F1F3 ; fully-qualified # 🇹🇳 E2.0 flag: Tunisia
1F1F9 1F1F4 ; fully-qualified # 🇹🇴 E2.0 flag: Tonga
-1F1F9 1F1F7 ; fully-qualified # 🇹🇷 E2.0 flag: Turkey
+1F1F9 1F1F7 ; fully-qualified # 🇹🇷 E2.0 flag: Türkiye
1F1F9 1F1F9 ; fully-qualified # 🇹🇹 E2.0 flag: Trinidad & Tobago
1F1F9 1F1FB ; fully-qualified # 🇹🇻 E2.0 flag: Tuvalu
1F1F9 1F1FC ; fully-qualified # 🇹🇼 E2.0 flag: Taiwan
@@ -5016,9 +5317,9 @@
# Flags subtotal: 275 w/o modifiers
# Status Counts
-# fully-qualified : 3655
-# minimally-qualified : 827
-# unqualified : 242
+# fully-qualified : 3773
+# minimally-qualified : 1009
+# unqualified : 243
# component : 9
#EOF
diff --git a/admin/unidata/emoji-variation-sequences.txt b/admin/unidata/emoji-variation-sequences.txt
index f3396ada19d..d8a3c9f431d 100644
--- a/admin/unidata/emoji-variation-sequences.txt
+++ b/admin/unidata/emoji-variation-sequences.txt
@@ -1,723 +1,757 @@
# emoji-variation-sequences.txt
-# Date: 2022-05-13, 21:54:24 GMT
-# © 2022 Unicode®, Inc.
+# Date: 2023-02-01, 02:22:54 GMT
+# © 2023 Unicode®, Inc.
# Unicode and the Unicode Logo are registered trademarks of Unicode, Inc. in the U.S. and other countries.
# For terms of use, see https://www.unicode.org/terms_of_use.html
#
# Emoji Variation Sequences for UTS #51
-# Used with Emoji Version 15.0 and subsequent minor revisions (if any)
+# Used with Emoji Version 15.1 and subsequent minor revisions (if any)
#
# For documentation and usage, see https://www.unicode.org/reports/tr51
#
-0023 FE0E ; text style; # (1.1 #︎ ) NUMBER SIGN
-0023 FE0F ; emoji style; # (1.1 #️ ) NUMBER SIGN
-002A FE0E ; text style; # (1.1 *︎ ) ASTERISK
-002A FE0F ; emoji style; # (1.1 *️ ) ASTERISK
-0030 FE0E ; text style; # (1.1 0︎ ) DIGIT ZERO
-0030 FE0F ; emoji style; # (1.1 0️ ) DIGIT ZERO
-0031 FE0E ; text style; # (1.1 1︎ ) DIGIT ONE
-0031 FE0F ; emoji style; # (1.1 1️ ) DIGIT ONE
-0032 FE0E ; text style; # (1.1 2︎ ) DIGIT TWO
-0032 FE0F ; emoji style; # (1.1 2️ ) DIGIT TWO
-0033 FE0E ; text style; # (1.1 3︎ ) DIGIT THREE
-0033 FE0F ; emoji style; # (1.1 3️ ) DIGIT THREE
-0034 FE0E ; text style; # (1.1 4︎ ) DIGIT FOUR
-0034 FE0F ; emoji style; # (1.1 4️ ) DIGIT FOUR
-0035 FE0E ; text style; # (1.1 5︎ ) DIGIT FIVE
-0035 FE0F ; emoji style; # (1.1 5️ ) DIGIT FIVE
-0036 FE0E ; text style; # (1.1 6︎ ) DIGIT SIX
-0036 FE0F ; emoji style; # (1.1 6️ ) DIGIT SIX
-0037 FE0E ; text style; # (1.1 7︎ ) DIGIT SEVEN
-0037 FE0F ; emoji style; # (1.1 7️ ) DIGIT SEVEN
-0038 FE0E ; text style; # (1.1 8︎ ) DIGIT EIGHT
-0038 FE0F ; emoji style; # (1.1 8️ ) DIGIT EIGHT
-0039 FE0E ; text style; # (1.1 9︎ ) DIGIT NINE
-0039 FE0F ; emoji style; # (1.1 9️ ) DIGIT NINE
-00A9 FE0E ; text style; # (1.1 ©︎ ) COPYRIGHT SIGN
-00A9 FE0F ; emoji style; # (1.1 ©️ ) COPYRIGHT SIGN
-00AE FE0E ; text style; # (1.1 ®︎ ) REGISTERED SIGN
-00AE FE0F ; emoji style; # (1.1 ®️ ) REGISTERED SIGN
-203C FE0E ; text style; # (1.1 ‼︎ ) DOUBLE EXCLAMATION MARK
-203C FE0F ; emoji style; # (1.1 ‼️ ) DOUBLE EXCLAMATION MARK
-2049 FE0E ; text style; # (3.0 ⁉︎ ) EXCLAMATION QUESTION MARK
-2049 FE0F ; emoji style; # (3.0 ⁉️ ) EXCLAMATION QUESTION MARK
-2122 FE0E ; text style; # (1.1 ™︎ ) TRADE MARK SIGN
-2122 FE0F ; emoji style; # (1.1 ™️ ) TRADE MARK SIGN
-2139 FE0E ; text style; # (3.0 ℹ︎ ) INFORMATION SOURCE
-2139 FE0F ; emoji style; # (3.0 ℹ️ ) INFORMATION SOURCE
-2194 FE0E ; text style; # (1.1 ↔︎ ) LEFT RIGHT ARROW
-2194 FE0F ; emoji style; # (1.1 ↔️ ) LEFT RIGHT ARROW
-2195 FE0E ; text style; # (1.1 ↕︎ ) UP DOWN ARROW
-2195 FE0F ; emoji style; # (1.1 ↕️ ) UP DOWN ARROW
-2196 FE0E ; text style; # (1.1 ↖︎ ) NORTH WEST ARROW
-2196 FE0F ; emoji style; # (1.1 ↖️ ) NORTH WEST ARROW
-2197 FE0E ; text style; # (1.1 ↗︎ ) NORTH EAST ARROW
-2197 FE0F ; emoji style; # (1.1 ↗️ ) NORTH EAST ARROW
-2198 FE0E ; text style; # (1.1 ↘︎ ) SOUTH EAST ARROW
-2198 FE0F ; emoji style; # (1.1 ↘️ ) SOUTH EAST ARROW
-2199 FE0E ; text style; # (1.1 ↙︎ ) SOUTH WEST ARROW
-2199 FE0F ; emoji style; # (1.1 ↙️ ) SOUTH WEST ARROW
-21A9 FE0E ; text style; # (1.1 ↩︎ ) LEFTWARDS ARROW WITH HOOK
-21A9 FE0F ; emoji style; # (1.1 ↩️ ) LEFTWARDS ARROW WITH HOOK
-21AA FE0E ; text style; # (1.1 ↪︎ ) RIGHTWARDS ARROW WITH HOOK
-21AA FE0F ; emoji style; # (1.1 ↪️ ) RIGHTWARDS ARROW WITH HOOK
-231A FE0E ; text style; # (1.1 ⌚︎ ) WATCH
-231A FE0F ; emoji style; # (1.1 ⌚️ ) WATCH
-231B FE0E ; text style; # (1.1 ⌛︎ ) HOURGLASS
-231B FE0F ; emoji style; # (1.1 ⌛️ ) HOURGLASS
-2328 FE0E ; text style; # (1.1 ⌨︎ ) KEYBOARD
-2328 FE0F ; emoji style; # (1.1 ⌨️ ) KEYBOARD
-23CF FE0E ; text style; # (4.0 ⏏︎ ) EJECT SYMBOL
-23CF FE0F ; emoji style; # (4.0 ⏏️ ) EJECT SYMBOL
-23E9 FE0E ; text style; # (6.0 ⏩︎ ) BLACK RIGHT-POINTING DOUBLE TRIANGLE
-23E9 FE0F ; emoji style; # (6.0 ⏩️ ) BLACK RIGHT-POINTING DOUBLE TRIANGLE
-23EA FE0E ; text style; # (6.0 ⏪︎ ) BLACK LEFT-POINTING DOUBLE TRIANGLE
-23EA FE0F ; emoji style; # (6.0 ⏪️ ) BLACK LEFT-POINTING DOUBLE TRIANGLE
-23ED FE0E ; text style; # (6.0 ⏭︎ ) BLACK RIGHT-POINTING DOUBLE TRIANGLE WITH VERTICAL BAR
-23ED FE0F ; emoji style; # (6.0 ⏭️ ) BLACK RIGHT-POINTING DOUBLE TRIANGLE WITH VERTICAL BAR
-23EE FE0E ; text style; # (6.0 ⏮︎ ) BLACK LEFT-POINTING DOUBLE TRIANGLE WITH VERTICAL BAR
-23EE FE0F ; emoji style; # (6.0 ⏮️ ) BLACK LEFT-POINTING DOUBLE TRIANGLE WITH VERTICAL BAR
-23EF FE0E ; text style; # (6.0 ⏯︎ ) BLACK RIGHT-POINTING TRIANGLE WITH DOUBLE VERTICAL BAR
-23EF FE0F ; emoji style; # (6.0 ⏯️ ) BLACK RIGHT-POINTING TRIANGLE WITH DOUBLE VERTICAL BAR
-23F1 FE0E ; text style; # (6.0 ⏱︎ ) STOPWATCH
-23F1 FE0F ; emoji style; # (6.0 ⏱️ ) STOPWATCH
-23F2 FE0E ; text style; # (6.0 ⏲︎ ) TIMER CLOCK
-23F2 FE0F ; emoji style; # (6.0 ⏲️ ) TIMER CLOCK
-23F3 FE0E ; text style; # (6.0 ⏳︎ ) HOURGLASS WITH FLOWING SAND
-23F3 FE0F ; emoji style; # (6.0 ⏳️ ) HOURGLASS WITH FLOWING SAND
-23F8 FE0E ; text style; # (7.0 ⏸︎ ) DOUBLE VERTICAL BAR
-23F8 FE0F ; emoji style; # (7.0 ⏸️ ) DOUBLE VERTICAL BAR
-23F9 FE0E ; text style; # (7.0 ⏹︎ ) BLACK SQUARE FOR STOP
-23F9 FE0F ; emoji style; # (7.0 ⏹️ ) BLACK SQUARE FOR STOP
-23FA FE0E ; text style; # (7.0 ⏺︎ ) BLACK CIRCLE FOR RECORD
-23FA FE0F ; emoji style; # (7.0 ⏺️ ) BLACK CIRCLE FOR RECORD
-24C2 FE0E ; text style; # (1.1 Ⓜ︎ ) CIRCLED LATIN CAPITAL LETTER M
-24C2 FE0F ; emoji style; # (1.1 Ⓜ️ ) CIRCLED LATIN CAPITAL LETTER M
-25AA FE0E ; text style; # (1.1 ▪︎ ) BLACK SMALL SQUARE
-25AA FE0F ; emoji style; # (1.1 ▪️ ) BLACK SMALL SQUARE
-25AB FE0E ; text style; # (1.1 ▫︎ ) WHITE SMALL SQUARE
-25AB FE0F ; emoji style; # (1.1 ▫️ ) WHITE SMALL SQUARE
-25B6 FE0E ; text style; # (1.1 ▶︎ ) BLACK RIGHT-POINTING TRIANGLE
-25B6 FE0F ; emoji style; # (1.1 ▶️ ) BLACK RIGHT-POINTING TRIANGLE
-25C0 FE0E ; text style; # (1.1 ◀︎ ) BLACK LEFT-POINTING TRIANGLE
-25C0 FE0F ; emoji style; # (1.1 ◀️ ) BLACK LEFT-POINTING TRIANGLE
-25FB FE0E ; text style; # (3.2 ◻︎ ) WHITE MEDIUM SQUARE
-25FB FE0F ; emoji style; # (3.2 ◻️ ) WHITE MEDIUM SQUARE
-25FC FE0E ; text style; # (3.2 ◼︎ ) BLACK MEDIUM SQUARE
-25FC FE0F ; emoji style; # (3.2 ◼️ ) BLACK MEDIUM SQUARE
-25FD FE0E ; text style; # (3.2 ◽︎ ) WHITE MEDIUM SMALL SQUARE
-25FD FE0F ; emoji style; # (3.2 ◽️ ) WHITE MEDIUM SMALL SQUARE
-25FE FE0E ; text style; # (3.2 ◾︎ ) BLACK MEDIUM SMALL SQUARE
-25FE FE0F ; emoji style; # (3.2 ◾️ ) BLACK MEDIUM SMALL SQUARE
-2600 FE0E ; text style; # (1.1 ☀︎ ) BLACK SUN WITH RAYS
-2600 FE0F ; emoji style; # (1.1 ☀️ ) BLACK SUN WITH RAYS
-2601 FE0E ; text style; # (1.1 ☁︎ ) CLOUD
-2601 FE0F ; emoji style; # (1.1 ☁️ ) CLOUD
-2602 FE0E ; text style; # (1.1 ☂︎ ) UMBRELLA
-2602 FE0F ; emoji style; # (1.1 ☂️ ) UMBRELLA
-2603 FE0E ; text style; # (1.1 ☃︎ ) SNOWMAN
-2603 FE0F ; emoji style; # (1.1 ☃️ ) SNOWMAN
-2604 FE0E ; text style; # (1.1 ☄︎ ) COMET
-2604 FE0F ; emoji style; # (1.1 ☄️ ) COMET
-260E FE0E ; text style; # (1.1 ☎︎ ) BLACK TELEPHONE
-260E FE0F ; emoji style; # (1.1 ☎️ ) BLACK TELEPHONE
-2611 FE0E ; text style; # (1.1 ☑︎ ) BALLOT BOX WITH CHECK
-2611 FE0F ; emoji style; # (1.1 ☑️ ) BALLOT BOX WITH CHECK
-2614 FE0E ; text style; # (4.0 ☔︎ ) UMBRELLA WITH RAIN DROPS
-2614 FE0F ; emoji style; # (4.0 ☔️ ) UMBRELLA WITH RAIN DROPS
-2615 FE0E ; text style; # (4.0 ☕︎ ) HOT BEVERAGE
-2615 FE0F ; emoji style; # (4.0 ☕️ ) HOT BEVERAGE
-2618 FE0E ; text style; # (4.1 ☘︎ ) SHAMROCK
-2618 FE0F ; emoji style; # (4.1 ☘️ ) SHAMROCK
-261D FE0E ; text style; # (1.1 ☝︎ ) WHITE UP POINTING INDEX
-261D FE0F ; emoji style; # (1.1 ☝️ ) WHITE UP POINTING INDEX
-2620 FE0E ; text style; # (1.1 ☠︎ ) SKULL AND CROSSBONES
-2620 FE0F ; emoji style; # (1.1 ☠️ ) SKULL AND CROSSBONES
-2622 FE0E ; text style; # (1.1 ☢︎ ) RADIOACTIVE SIGN
-2622 FE0F ; emoji style; # (1.1 ☢️ ) RADIOACTIVE SIGN
-2623 FE0E ; text style; # (1.1 ☣︎ ) BIOHAZARD SIGN
-2623 FE0F ; emoji style; # (1.1 ☣️ ) BIOHAZARD SIGN
-2626 FE0E ; text style; # (1.1 ☦︎ ) ORTHODOX CROSS
-2626 FE0F ; emoji style; # (1.1 ☦️ ) ORTHODOX CROSS
-262A FE0E ; text style; # (1.1 ☪︎ ) STAR AND CRESCENT
-262A FE0F ; emoji style; # (1.1 ☪️ ) STAR AND CRESCENT
-262E FE0E ; text style; # (1.1 ☮︎ ) PEACE SYMBOL
-262E FE0F ; emoji style; # (1.1 ☮️ ) PEACE SYMBOL
-262F FE0E ; text style; # (1.1 ☯︎ ) YIN YANG
-262F FE0F ; emoji style; # (1.1 ☯️ ) YIN YANG
-2638 FE0E ; text style; # (1.1 ☸︎ ) WHEEL OF DHARMA
-2638 FE0F ; emoji style; # (1.1 ☸️ ) WHEEL OF DHARMA
-2639 FE0E ; text style; # (1.1 ☹︎ ) WHITE FROWNING FACE
-2639 FE0F ; emoji style; # (1.1 ☹️ ) WHITE FROWNING FACE
-263A FE0E ; text style; # (1.1 ☺︎ ) WHITE SMILING FACE
-263A FE0F ; emoji style; # (1.1 ☺️ ) WHITE SMILING FACE
-2640 FE0E ; text style; # (1.1 ♀︎ ) FEMALE SIGN
-2640 FE0F ; emoji style; # (1.1 ♀️ ) FEMALE SIGN
-2642 FE0E ; text style; # (1.1 ♂︎ ) MALE SIGN
-2642 FE0F ; emoji style; # (1.1 ♂️ ) MALE SIGN
-2648 FE0E ; text style; # (1.1 ♈︎ ) ARIES
-2648 FE0F ; emoji style; # (1.1 ♈️ ) ARIES
-2649 FE0E ; text style; # (1.1 ♉︎ ) TAURUS
-2649 FE0F ; emoji style; # (1.1 ♉️ ) TAURUS
-264A FE0E ; text style; # (1.1 ♊︎ ) GEMINI
-264A FE0F ; emoji style; # (1.1 ♊️ ) GEMINI
-264B FE0E ; text style; # (1.1 ♋︎ ) CANCER
-264B FE0F ; emoji style; # (1.1 ♋️ ) CANCER
-264C FE0E ; text style; # (1.1 ♌︎ ) LEO
-264C FE0F ; emoji style; # (1.1 ♌️ ) LEO
-264D FE0E ; text style; # (1.1 ♍︎ ) VIRGO
-264D FE0F ; emoji style; # (1.1 ♍️ ) VIRGO
-264E FE0E ; text style; # (1.1 ♎︎ ) LIBRA
-264E FE0F ; emoji style; # (1.1 ♎️ ) LIBRA
-264F FE0E ; text style; # (1.1 ♏︎ ) SCORPIUS
-264F FE0F ; emoji style; # (1.1 ♏️ ) SCORPIUS
-2650 FE0E ; text style; # (1.1 ♐︎ ) SAGITTARIUS
-2650 FE0F ; emoji style; # (1.1 ♐️ ) SAGITTARIUS
-2651 FE0E ; text style; # (1.1 ♑︎ ) CAPRICORN
-2651 FE0F ; emoji style; # (1.1 ♑️ ) CAPRICORN
-2652 FE0E ; text style; # (1.1 ♒︎ ) AQUARIUS
-2652 FE0F ; emoji style; # (1.1 ♒️ ) AQUARIUS
-2653 FE0E ; text style; # (1.1 ♓︎ ) PISCES
-2653 FE0F ; emoji style; # (1.1 ♓️ ) PISCES
-265F FE0E ; text style; # (1.1 ♟︎ ) BLACK CHESS PAWN
-265F FE0F ; emoji style; # (1.1 ♟️ ) BLACK CHESS PAWN
-2660 FE0E ; text style; # (1.1 ♠︎ ) BLACK SPADE SUIT
-2660 FE0F ; emoji style; # (1.1 ♠️ ) BLACK SPADE SUIT
-2663 FE0E ; text style; # (1.1 ♣︎ ) BLACK CLUB SUIT
-2663 FE0F ; emoji style; # (1.1 ♣️ ) BLACK CLUB SUIT
-2665 FE0E ; text style; # (1.1 ♥︎ ) BLACK HEART SUIT
-2665 FE0F ; emoji style; # (1.1 ♥️ ) BLACK HEART SUIT
-2666 FE0E ; text style; # (1.1 ♦︎ ) BLACK DIAMOND SUIT
-2666 FE0F ; emoji style; # (1.1 ♦️ ) BLACK DIAMOND SUIT
-2668 FE0E ; text style; # (1.1 ♨︎ ) HOT SPRINGS
-2668 FE0F ; emoji style; # (1.1 ♨️ ) HOT SPRINGS
-267B FE0E ; text style; # (3.2 ♻︎ ) BLACK UNIVERSAL RECYCLING SYMBOL
-267B FE0F ; emoji style; # (3.2 ♻️ ) BLACK UNIVERSAL RECYCLING SYMBOL
-267E FE0E ; text style; # (4.1 ♾︎ ) PERMANENT PAPER SIGN
-267E FE0F ; emoji style; # (4.1 ♾️ ) PERMANENT PAPER SIGN
-267F FE0E ; text style; # (4.1 ♿︎ ) WHEELCHAIR SYMBOL
-267F FE0F ; emoji style; # (4.1 ♿️ ) WHEELCHAIR SYMBOL
-2692 FE0E ; text style; # (4.1 ⚒︎ ) HAMMER AND PICK
-2692 FE0F ; emoji style; # (4.1 ⚒️ ) HAMMER AND PICK
-2693 FE0E ; text style; # (4.1 ⚓︎ ) ANCHOR
-2693 FE0F ; emoji style; # (4.1 ⚓️ ) ANCHOR
-2694 FE0E ; text style; # (4.1 ⚔︎ ) CROSSED SWORDS
-2694 FE0F ; emoji style; # (4.1 ⚔️ ) CROSSED SWORDS
-2695 FE0E ; text style; # (4.1 ⚕︎ ) STAFF OF AESCULAPIUS
-2695 FE0F ; emoji style; # (4.1 ⚕️ ) STAFF OF AESCULAPIUS
-2696 FE0E ; text style; # (4.1 ⚖︎ ) SCALES
-2696 FE0F ; emoji style; # (4.1 ⚖️ ) SCALES
-2697 FE0E ; text style; # (4.1 ⚗︎ ) ALEMBIC
-2697 FE0F ; emoji style; # (4.1 ⚗️ ) ALEMBIC
-2699 FE0E ; text style; # (4.1 ⚙︎ ) GEAR
-2699 FE0F ; emoji style; # (4.1 ⚙️ ) GEAR
-269B FE0E ; text style; # (4.1 ⚛︎ ) ATOM SYMBOL
-269B FE0F ; emoji style; # (4.1 ⚛️ ) ATOM SYMBOL
-269C FE0E ; text style; # (4.1 ⚜︎ ) FLEUR-DE-LIS
-269C FE0F ; emoji style; # (4.1 ⚜️ ) FLEUR-DE-LIS
-26A0 FE0E ; text style; # (4.0 ⚠︎ ) WARNING SIGN
-26A0 FE0F ; emoji style; # (4.0 ⚠️ ) WARNING SIGN
-26A1 FE0E ; text style; # (4.0 ⚡︎ ) HIGH VOLTAGE SIGN
-26A1 FE0F ; emoji style; # (4.0 ⚡️ ) HIGH VOLTAGE SIGN
-26A7 FE0E ; text style; # (4.1 ⚧︎ ) MALE WITH STROKE AND MALE AND FEMALE SIGN
-26A7 FE0F ; emoji style; # (4.1 ⚧️ ) MALE WITH STROKE AND MALE AND FEMALE SIGN
-26AA FE0E ; text style; # (4.1 ⚪︎ ) MEDIUM WHITE CIRCLE
-26AA FE0F ; emoji style; # (4.1 ⚪️ ) MEDIUM WHITE CIRCLE
-26AB FE0E ; text style; # (4.1 ⚫︎ ) MEDIUM BLACK CIRCLE
-26AB FE0F ; emoji style; # (4.1 ⚫️ ) MEDIUM BLACK CIRCLE
-26B0 FE0E ; text style; # (4.1 ⚰︎ ) COFFIN
-26B0 FE0F ; emoji style; # (4.1 ⚰️ ) COFFIN
-26B1 FE0E ; text style; # (4.1 ⚱︎ ) FUNERAL URN
-26B1 FE0F ; emoji style; # (4.1 ⚱️ ) FUNERAL URN
-26BD FE0E ; text style; # (5.2 ⚽︎ ) SOCCER BALL
-26BD FE0F ; emoji style; # (5.2 ⚽️ ) SOCCER BALL
-26BE FE0E ; text style; # (5.2 ⚾︎ ) BASEBALL
-26BE FE0F ; emoji style; # (5.2 ⚾️ ) BASEBALL
-26C4 FE0E ; text style; # (5.2 ⛄︎ ) SNOWMAN WITHOUT SNOW
-26C4 FE0F ; emoji style; # (5.2 ⛄️ ) SNOWMAN WITHOUT SNOW
-26C5 FE0E ; text style; # (5.2 ⛅︎ ) SUN BEHIND CLOUD
-26C5 FE0F ; emoji style; # (5.2 ⛅️ ) SUN BEHIND CLOUD
-26C8 FE0E ; text style; # (5.2 ⛈︎ ) THUNDER CLOUD AND RAIN
-26C8 FE0F ; emoji style; # (5.2 ⛈️ ) THUNDER CLOUD AND RAIN
-26CF FE0E ; text style; # (5.2 ⛏︎ ) PICK
-26CF FE0F ; emoji style; # (5.2 ⛏️ ) PICK
-26D1 FE0E ; text style; # (5.2 ⛑︎ ) HELMET WITH WHITE CROSS
-26D1 FE0F ; emoji style; # (5.2 ⛑️ ) HELMET WITH WHITE CROSS
-26D3 FE0E ; text style; # (5.2 ⛓︎ ) CHAINS
-26D3 FE0F ; emoji style; # (5.2 ⛓️ ) CHAINS
-26D4 FE0E ; text style; # (5.2 ⛔︎ ) NO ENTRY
-26D4 FE0F ; emoji style; # (5.2 ⛔️ ) NO ENTRY
-26E9 FE0E ; text style; # (5.2 ⛩︎ ) SHINTO SHRINE
-26E9 FE0F ; emoji style; # (5.2 ⛩️ ) SHINTO SHRINE
-26EA FE0E ; text style; # (5.2 ⛪︎ ) CHURCH
-26EA FE0F ; emoji style; # (5.2 ⛪️ ) CHURCH
-26F0 FE0E ; text style; # (5.2 ⛰︎ ) MOUNTAIN
-26F0 FE0F ; emoji style; # (5.2 ⛰️ ) MOUNTAIN
-26F1 FE0E ; text style; # (5.2 ⛱︎ ) UMBRELLA ON GROUND
-26F1 FE0F ; emoji style; # (5.2 ⛱️ ) UMBRELLA ON GROUND
-26F2 FE0E ; text style; # (5.2 ⛲︎ ) FOUNTAIN
-26F2 FE0F ; emoji style; # (5.2 ⛲️ ) FOUNTAIN
-26F3 FE0E ; text style; # (5.2 ⛳︎ ) FLAG IN HOLE
-26F3 FE0F ; emoji style; # (5.2 ⛳️ ) FLAG IN HOLE
-26F4 FE0E ; text style; # (5.2 ⛴︎ ) FERRY
-26F4 FE0F ; emoji style; # (5.2 ⛴️ ) FERRY
-26F5 FE0E ; text style; # (5.2 ⛵︎ ) SAILBOAT
-26F5 FE0F ; emoji style; # (5.2 ⛵️ ) SAILBOAT
-26F7 FE0E ; text style; # (5.2 ⛷︎ ) SKIER
-26F7 FE0F ; emoji style; # (5.2 ⛷️ ) SKIER
-26F8 FE0E ; text style; # (5.2 ⛸︎ ) ICE SKATE
-26F8 FE0F ; emoji style; # (5.2 ⛸️ ) ICE SKATE
-26F9 FE0E ; text style; # (5.2 ⛹︎ ) PERSON WITH BALL
-26F9 FE0F ; emoji style; # (5.2 ⛹️ ) PERSON WITH BALL
-26FA FE0E ; text style; # (5.2 ⛺︎ ) TENT
-26FA FE0F ; emoji style; # (5.2 ⛺️ ) TENT
-26FD FE0E ; text style; # (5.2 ⛽︎ ) FUEL PUMP
-26FD FE0F ; emoji style; # (5.2 ⛽️ ) FUEL PUMP
-2702 FE0E ; text style; # (1.1 ✂︎ ) BLACK SCISSORS
-2702 FE0F ; emoji style; # (1.1 ✂️ ) BLACK SCISSORS
-2708 FE0E ; text style; # (1.1 ✈︎ ) AIRPLANE
-2708 FE0F ; emoji style; # (1.1 ✈️ ) AIRPLANE
-2709 FE0E ; text style; # (1.1 ✉︎ ) ENVELOPE
-2709 FE0F ; emoji style; # (1.1 ✉️ ) ENVELOPE
-270C FE0E ; text style; # (1.1 ✌︎ ) VICTORY HAND
-270C FE0F ; emoji style; # (1.1 ✌️ ) VICTORY HAND
-270D FE0E ; text style; # (1.1 ✍︎ ) WRITING HAND
-270D FE0F ; emoji style; # (1.1 ✍️ ) WRITING HAND
-270F FE0E ; text style; # (1.1 ✏︎ ) PENCIL
-270F FE0F ; emoji style; # (1.1 ✏️ ) PENCIL
-2712 FE0E ; text style; # (1.1 ✒︎ ) BLACK NIB
-2712 FE0F ; emoji style; # (1.1 ✒️ ) BLACK NIB
-2714 FE0E ; text style; # (1.1 ✔︎ ) HEAVY CHECK MARK
-2714 FE0F ; emoji style; # (1.1 ✔️ ) HEAVY CHECK MARK
-2716 FE0E ; text style; # (1.1 ✖︎ ) HEAVY MULTIPLICATION X
-2716 FE0F ; emoji style; # (1.1 ✖️ ) HEAVY MULTIPLICATION X
-271D FE0E ; text style; # (1.1 ✝︎ ) LATIN CROSS
-271D FE0F ; emoji style; # (1.1 ✝️ ) LATIN CROSS
-2721 FE0E ; text style; # (1.1 ✡︎ ) STAR OF DAVID
-2721 FE0F ; emoji style; # (1.1 ✡️ ) STAR OF DAVID
-2733 FE0E ; text style; # (1.1 ✳︎ ) EIGHT SPOKED ASTERISK
-2733 FE0F ; emoji style; # (1.1 ✳️ ) EIGHT SPOKED ASTERISK
-2734 FE0E ; text style; # (1.1 ✴︎ ) EIGHT POINTED BLACK STAR
-2734 FE0F ; emoji style; # (1.1 ✴️ ) EIGHT POINTED BLACK STAR
-2744 FE0E ; text style; # (1.1 ❄︎ ) SNOWFLAKE
-2744 FE0F ; emoji style; # (1.1 ❄️ ) SNOWFLAKE
-2747 FE0E ; text style; # (1.1 ❇︎ ) SPARKLE
-2747 FE0F ; emoji style; # (1.1 ❇️ ) SPARKLE
-2753 FE0E ; text style; # (6.0 ❓︎ ) BLACK QUESTION MARK ORNAMENT
-2753 FE0F ; emoji style; # (6.0 ❓️ ) BLACK QUESTION MARK ORNAMENT
-2757 FE0E ; text style; # (5.2 ❗︎ ) HEAVY EXCLAMATION MARK SYMBOL
-2757 FE0F ; emoji style; # (5.2 ❗️ ) HEAVY EXCLAMATION MARK SYMBOL
-2763 FE0E ; text style; # (1.1 ❣︎ ) HEAVY HEART EXCLAMATION MARK ORNAMENT
-2763 FE0F ; emoji style; # (1.1 ❣️ ) HEAVY HEART EXCLAMATION MARK ORNAMENT
-2764 FE0E ; text style; # (1.1 ❤︎ ) HEAVY BLACK HEART
-2764 FE0F ; emoji style; # (1.1 ❤️ ) HEAVY BLACK HEART
-27A1 FE0E ; text style; # (1.1 ➡︎ ) BLACK RIGHTWARDS ARROW
-27A1 FE0F ; emoji style; # (1.1 ➡️ ) BLACK RIGHTWARDS ARROW
-2934 FE0E ; text style; # (3.2 ⤴︎ ) ARROW POINTING RIGHTWARDS THEN CURVING UPWARDS
-2934 FE0F ; emoji style; # (3.2 ⤴️ ) ARROW POINTING RIGHTWARDS THEN CURVING UPWARDS
-2935 FE0E ; text style; # (3.2 ⤵︎ ) ARROW POINTING RIGHTWARDS THEN CURVING DOWNWARDS
-2935 FE0F ; emoji style; # (3.2 ⤵️ ) ARROW POINTING RIGHTWARDS THEN CURVING DOWNWARDS
-2B05 FE0E ; text style; # (4.0 ⬅︎ ) LEFTWARDS BLACK ARROW
-2B05 FE0F ; emoji style; # (4.0 ⬅️ ) LEFTWARDS BLACK ARROW
-2B06 FE0E ; text style; # (4.0 ⬆︎ ) UPWARDS BLACK ARROW
-2B06 FE0F ; emoji style; # (4.0 ⬆️ ) UPWARDS BLACK ARROW
-2B07 FE0E ; text style; # (4.0 ⬇︎ ) DOWNWARDS BLACK ARROW
-2B07 FE0F ; emoji style; # (4.0 ⬇️ ) DOWNWARDS BLACK ARROW
-2B1B FE0E ; text style; # (5.1 ⬛︎ ) BLACK LARGE SQUARE
-2B1B FE0F ; emoji style; # (5.1 ⬛️ ) BLACK LARGE SQUARE
-2B1C FE0E ; text style; # (5.1 ⬜︎ ) WHITE LARGE SQUARE
-2B1C FE0F ; emoji style; # (5.1 ⬜️ ) WHITE LARGE SQUARE
-2B50 FE0E ; text style; # (5.1 ⭐︎ ) WHITE MEDIUM STAR
-2B50 FE0F ; emoji style; # (5.1 ⭐️ ) WHITE MEDIUM STAR
-2B55 FE0E ; text style; # (5.2 ⭕︎ ) HEAVY LARGE CIRCLE
-2B55 FE0F ; emoji style; # (5.2 ⭕️ ) HEAVY LARGE CIRCLE
-3030 FE0E ; text style; # (1.1 〰︎ ) WAVY DASH
-3030 FE0F ; emoji style; # (1.1 〰️ ) WAVY DASH
-303D FE0E ; text style; # (3.2 〽︎ ) PART ALTERNATION MARK
-303D FE0F ; emoji style; # (3.2 〽️ ) PART ALTERNATION MARK
-3297 FE0E ; text style; # (1.1 ㊗︎ ) CIRCLED IDEOGRAPH CONGRATULATION
-3297 FE0F ; emoji style; # (1.1 ㊗️ ) CIRCLED IDEOGRAPH CONGRATULATION
-3299 FE0E ; text style; # (1.1 ㊙︎ ) CIRCLED IDEOGRAPH SECRET
-3299 FE0F ; emoji style; # (1.1 ㊙️ ) CIRCLED IDEOGRAPH SECRET
-1F004 FE0E ; text style; # (5.1 🀄︎ ) MAHJONG TILE RED DRAGON
-1F004 FE0F ; emoji style; # (5.1 🀄️ ) MAHJONG TILE RED DRAGON
-1F170 FE0E ; text style; # (6.0 🅰︎ ) NEGATIVE SQUARED LATIN CAPITAL LETTER A
-1F170 FE0F ; emoji style; # (6.0 🅰️ ) NEGATIVE SQUARED LATIN CAPITAL LETTER A
-1F171 FE0E ; text style; # (6.0 🅱︎ ) NEGATIVE SQUARED LATIN CAPITAL LETTER B
-1F171 FE0F ; emoji style; # (6.0 🅱️ ) NEGATIVE SQUARED LATIN CAPITAL LETTER B
-1F17E FE0E ; text style; # (6.0 🅾︎ ) NEGATIVE SQUARED LATIN CAPITAL LETTER O
-1F17E FE0F ; emoji style; # (6.0 🅾️ ) NEGATIVE SQUARED LATIN CAPITAL LETTER O
-1F17F FE0E ; text style; # (5.2 🅿︎ ) NEGATIVE SQUARED LATIN CAPITAL LETTER P
-1F17F FE0F ; emoji style; # (5.2 🅿️ ) NEGATIVE SQUARED LATIN CAPITAL LETTER P
-1F202 FE0E ; text style; # (6.0 🈂︎ ) SQUARED KATAKANA SA
-1F202 FE0F ; emoji style; # (6.0 🈂️ ) SQUARED KATAKANA SA
-1F21A FE0E ; text style; # (5.2 🈚︎ ) SQUARED CJK UNIFIED IDEOGRAPH-7121
-1F21A FE0F ; emoji style; # (5.2 🈚️ ) SQUARED CJK UNIFIED IDEOGRAPH-7121
-1F22F FE0E ; text style; # (5.2 🈯︎ ) SQUARED CJK UNIFIED IDEOGRAPH-6307
-1F22F FE0F ; emoji style; # (5.2 🈯️ ) SQUARED CJK UNIFIED IDEOGRAPH-6307
-1F237 FE0E ; text style; # (6.0 🈷︎ ) SQUARED CJK UNIFIED IDEOGRAPH-6708
-1F237 FE0F ; emoji style; # (6.0 🈷️ ) SQUARED CJK UNIFIED IDEOGRAPH-6708
-1F30D FE0E ; text style; # (6.0 🌍︎ ) EARTH GLOBE EUROPE-AFRICA
-1F30D FE0F ; emoji style; # (6.0 🌍️ ) EARTH GLOBE EUROPE-AFRICA
-1F30E FE0E ; text style; # (6.0 🌎︎ ) EARTH GLOBE AMERICAS
-1F30E FE0F ; emoji style; # (6.0 🌎️ ) EARTH GLOBE AMERICAS
-1F30F FE0E ; text style; # (6.0 🌏︎ ) EARTH GLOBE ASIA-AUSTRALIA
-1F30F FE0F ; emoji style; # (6.0 🌏️ ) EARTH GLOBE ASIA-AUSTRALIA
-1F315 FE0E ; text style; # (6.0 🌕︎ ) FULL MOON SYMBOL
-1F315 FE0F ; emoji style; # (6.0 🌕️ ) FULL MOON SYMBOL
-1F31C FE0E ; text style; # (6.0 🌜︎ ) LAST QUARTER MOON WITH FACE
-1F31C FE0F ; emoji style; # (6.0 🌜️ ) LAST QUARTER MOON WITH FACE
-1F321 FE0E ; text style; # (7.0 🌡︎ ) THERMOMETER
-1F321 FE0F ; emoji style; # (7.0 🌡️ ) THERMOMETER
-1F324 FE0E ; text style; # (7.0 🌤︎ ) WHITE SUN WITH SMALL CLOUD
-1F324 FE0F ; emoji style; # (7.0 🌤️ ) WHITE SUN WITH SMALL CLOUD
-1F325 FE0E ; text style; # (7.0 🌥︎ ) WHITE SUN BEHIND CLOUD
-1F325 FE0F ; emoji style; # (7.0 🌥️ ) WHITE SUN BEHIND CLOUD
-1F326 FE0E ; text style; # (7.0 🌦︎ ) WHITE SUN BEHIND CLOUD WITH RAIN
-1F326 FE0F ; emoji style; # (7.0 🌦️ ) WHITE SUN BEHIND CLOUD WITH RAIN
-1F327 FE0E ; text style; # (7.0 🌧︎ ) CLOUD WITH RAIN
-1F327 FE0F ; emoji style; # (7.0 🌧️ ) CLOUD WITH RAIN
-1F328 FE0E ; text style; # (7.0 🌨︎ ) CLOUD WITH SNOW
-1F328 FE0F ; emoji style; # (7.0 🌨️ ) CLOUD WITH SNOW
-1F329 FE0E ; text style; # (7.0 🌩︎ ) CLOUD WITH LIGHTNING
-1F329 FE0F ; emoji style; # (7.0 🌩️ ) CLOUD WITH LIGHTNING
-1F32A FE0E ; text style; # (7.0 🌪︎ ) CLOUD WITH TORNADO
-1F32A FE0F ; emoji style; # (7.0 🌪️ ) CLOUD WITH TORNADO
-1F32B FE0E ; text style; # (7.0 🌫︎ ) FOG
-1F32B FE0F ; emoji style; # (7.0 🌫️ ) FOG
-1F32C FE0E ; text style; # (7.0 🌬︎ ) WIND BLOWING FACE
-1F32C FE0F ; emoji style; # (7.0 🌬️ ) WIND BLOWING FACE
-1F336 FE0E ; text style; # (7.0 🌶︎ ) HOT PEPPER
-1F336 FE0F ; emoji style; # (7.0 🌶️ ) HOT PEPPER
-1F378 FE0E ; text style; # (6.0 🍸︎ ) COCKTAIL GLASS
-1F378 FE0F ; emoji style; # (6.0 🍸️ ) COCKTAIL GLASS
-1F37D FE0E ; text style; # (7.0 🍽︎ ) FORK AND KNIFE WITH PLATE
-1F37D FE0F ; emoji style; # (7.0 🍽️ ) FORK AND KNIFE WITH PLATE
-1F393 FE0E ; text style; # (6.0 🎓︎ ) GRADUATION CAP
-1F393 FE0F ; emoji style; # (6.0 🎓️ ) GRADUATION CAP
-1F396 FE0E ; text style; # (7.0 🎖︎ ) MILITARY MEDAL
-1F396 FE0F ; emoji style; # (7.0 🎖️ ) MILITARY MEDAL
-1F397 FE0E ; text style; # (7.0 🎗︎ ) REMINDER RIBBON
-1F397 FE0F ; emoji style; # (7.0 🎗️ ) REMINDER RIBBON
-1F399 FE0E ; text style; # (7.0 🎙︎ ) STUDIO MICROPHONE
-1F399 FE0F ; emoji style; # (7.0 🎙️ ) STUDIO MICROPHONE
-1F39A FE0E ; text style; # (7.0 🎚︎ ) LEVEL SLIDER
-1F39A FE0F ; emoji style; # (7.0 🎚️ ) LEVEL SLIDER
-1F39B FE0E ; text style; # (7.0 🎛︎ ) CONTROL KNOBS
-1F39B FE0F ; emoji style; # (7.0 🎛️ ) CONTROL KNOBS
-1F39E FE0E ; text style; # (7.0 🎞︎ ) FILM FRAMES
-1F39E FE0F ; emoji style; # (7.0 🎞️ ) FILM FRAMES
-1F39F FE0E ; text style; # (7.0 🎟︎ ) ADMISSION TICKETS
-1F39F FE0F ; emoji style; # (7.0 🎟️ ) ADMISSION TICKETS
-1F3A7 FE0E ; text style; # (6.0 🎧︎ ) HEADPHONE
-1F3A7 FE0F ; emoji style; # (6.0 🎧️ ) HEADPHONE
-1F3AC FE0E ; text style; # (6.0 🎬︎ ) CLAPPER BOARD
-1F3AC FE0F ; emoji style; # (6.0 🎬️ ) CLAPPER BOARD
-1F3AD FE0E ; text style; # (6.0 🎭︎ ) PERFORMING ARTS
-1F3AD FE0F ; emoji style; # (6.0 🎭️ ) PERFORMING ARTS
-1F3AE FE0E ; text style; # (6.0 🎮︎ ) VIDEO GAME
-1F3AE FE0F ; emoji style; # (6.0 🎮️ ) VIDEO GAME
-1F3C2 FE0E ; text style; # (6.0 🏂︎ ) SNOWBOARDER
-1F3C2 FE0F ; emoji style; # (6.0 🏂️ ) SNOWBOARDER
-1F3C4 FE0E ; text style; # (6.0 🏄︎ ) SURFER
-1F3C4 FE0F ; emoji style; # (6.0 🏄️ ) SURFER
-1F3C6 FE0E ; text style; # (6.0 🏆︎ ) TROPHY
-1F3C6 FE0F ; emoji style; # (6.0 🏆️ ) TROPHY
-1F3CA FE0E ; text style; # (6.0 🏊︎ ) SWIMMER
-1F3CA FE0F ; emoji style; # (6.0 🏊️ ) SWIMMER
-1F3CB FE0E ; text style; # (7.0 🏋︎ ) WEIGHT LIFTER
-1F3CB FE0F ; emoji style; # (7.0 🏋️ ) WEIGHT LIFTER
-1F3CC FE0E ; text style; # (7.0 🏌︎ ) GOLFER
-1F3CC FE0F ; emoji style; # (7.0 🏌️ ) GOLFER
-1F3CD FE0E ; text style; # (7.0 🏍︎ ) RACING MOTORCYCLE
-1F3CD FE0F ; emoji style; # (7.0 🏍️ ) RACING MOTORCYCLE
-1F3CE FE0E ; text style; # (7.0 🏎︎ ) RACING CAR
-1F3CE FE0F ; emoji style; # (7.0 🏎️ ) RACING CAR
-1F3D4 FE0E ; text style; # (7.0 🏔︎ ) SNOW CAPPED MOUNTAIN
-1F3D4 FE0F ; emoji style; # (7.0 🏔️ ) SNOW CAPPED MOUNTAIN
-1F3D5 FE0E ; text style; # (7.0 🏕︎ ) CAMPING
-1F3D5 FE0F ; emoji style; # (7.0 🏕️ ) CAMPING
-1F3D6 FE0E ; text style; # (7.0 🏖︎ ) BEACH WITH UMBRELLA
-1F3D6 FE0F ; emoji style; # (7.0 🏖️ ) BEACH WITH UMBRELLA
-1F3D7 FE0E ; text style; # (7.0 🏗︎ ) BUILDING CONSTRUCTION
-1F3D7 FE0F ; emoji style; # (7.0 🏗️ ) BUILDING CONSTRUCTION
-1F3D8 FE0E ; text style; # (7.0 🏘︎ ) HOUSE BUILDINGS
-1F3D8 FE0F ; emoji style; # (7.0 🏘️ ) HOUSE BUILDINGS
-1F3D9 FE0E ; text style; # (7.0 🏙︎ ) CITYSCAPE
-1F3D9 FE0F ; emoji style; # (7.0 🏙️ ) CITYSCAPE
-1F3DA FE0E ; text style; # (7.0 🏚︎ ) DERELICT HOUSE BUILDING
-1F3DA FE0F ; emoji style; # (7.0 🏚️ ) DERELICT HOUSE BUILDING
-1F3DB FE0E ; text style; # (7.0 🏛︎ ) CLASSICAL BUILDING
-1F3DB FE0F ; emoji style; # (7.0 🏛️ ) CLASSICAL BUILDING
-1F3DC FE0E ; text style; # (7.0 🏜︎ ) DESERT
-1F3DC FE0F ; emoji style; # (7.0 🏜️ ) DESERT
-1F3DD FE0E ; text style; # (7.0 🏝︎ ) DESERT ISLAND
-1F3DD FE0F ; emoji style; # (7.0 🏝️ ) DESERT ISLAND
-1F3DE FE0E ; text style; # (7.0 🏞︎ ) NATIONAL PARK
-1F3DE FE0F ; emoji style; # (7.0 🏞️ ) NATIONAL PARK
-1F3DF FE0E ; text style; # (7.0 🏟︎ ) STADIUM
-1F3DF FE0F ; emoji style; # (7.0 🏟️ ) STADIUM
-1F3E0 FE0E ; text style; # (6.0 🏠︎ ) HOUSE BUILDING
-1F3E0 FE0F ; emoji style; # (6.0 🏠️ ) HOUSE BUILDING
-1F3ED FE0E ; text style; # (6.0 🏭︎ ) FACTORY
-1F3ED FE0F ; emoji style; # (6.0 🏭️ ) FACTORY
-1F3F3 FE0E ; text style; # (7.0 🏳︎ ) WAVING WHITE FLAG
-1F3F3 FE0F ; emoji style; # (7.0 🏳️ ) WAVING WHITE FLAG
-1F3F5 FE0E ; text style; # (7.0 🏵︎ ) ROSETTE
-1F3F5 FE0F ; emoji style; # (7.0 🏵️ ) ROSETTE
-1F3F7 FE0E ; text style; # (7.0 🏷︎ ) LABEL
-1F3F7 FE0F ; emoji style; # (7.0 🏷️ ) LABEL
-1F408 FE0E ; text style; # (6.0 🐈︎ ) CAT
-1F408 FE0F ; emoji style; # (6.0 🐈️ ) CAT
-1F415 FE0E ; text style; # (6.0 🐕︎ ) DOG
-1F415 FE0F ; emoji style; # (6.0 🐕️ ) DOG
-1F41F FE0E ; text style; # (6.0 🐟︎ ) FISH
-1F41F FE0F ; emoji style; # (6.0 🐟️ ) FISH
-1F426 FE0E ; text style; # (6.0 🐦︎ ) BIRD
-1F426 FE0F ; emoji style; # (6.0 🐦️ ) BIRD
-1F43F FE0E ; text style; # (7.0 🐿︎ ) CHIPMUNK
-1F43F FE0F ; emoji style; # (7.0 🐿️ ) CHIPMUNK
-1F441 FE0E ; text style; # (7.0 👁︎ ) EYE
-1F441 FE0F ; emoji style; # (7.0 👁️ ) EYE
-1F442 FE0E ; text style; # (6.0 👂︎ ) EAR
-1F442 FE0F ; emoji style; # (6.0 👂️ ) EAR
-1F446 FE0E ; text style; # (6.0 👆︎ ) WHITE UP POINTING BACKHAND INDEX
-1F446 FE0F ; emoji style; # (6.0 👆️ ) WHITE UP POINTING BACKHAND INDEX
-1F447 FE0E ; text style; # (6.0 👇︎ ) WHITE DOWN POINTING BACKHAND INDEX
-1F447 FE0F ; emoji style; # (6.0 👇️ ) WHITE DOWN POINTING BACKHAND INDEX
-1F448 FE0E ; text style; # (6.0 👈︎ ) WHITE LEFT POINTING BACKHAND INDEX
-1F448 FE0F ; emoji style; # (6.0 👈️ ) WHITE LEFT POINTING BACKHAND INDEX
-1F449 FE0E ; text style; # (6.0 👉︎ ) WHITE RIGHT POINTING BACKHAND INDEX
-1F449 FE0F ; emoji style; # (6.0 👉️ ) WHITE RIGHT POINTING BACKHAND INDEX
-1F44D FE0E ; text style; # (6.0 👍︎ ) THUMBS UP SIGN
-1F44D FE0F ; emoji style; # (6.0 👍️ ) THUMBS UP SIGN
-1F44E FE0E ; text style; # (6.0 👎︎ ) THUMBS DOWN SIGN
-1F44E FE0F ; emoji style; # (6.0 👎️ ) THUMBS DOWN SIGN
-1F453 FE0E ; text style; # (6.0 👓︎ ) EYEGLASSES
-1F453 FE0F ; emoji style; # (6.0 👓️ ) EYEGLASSES
-1F46A FE0E ; text style; # (6.0 👪︎ ) FAMILY
-1F46A FE0F ; emoji style; # (6.0 👪️ ) FAMILY
-1F47D FE0E ; text style; # (6.0 👽︎ ) EXTRATERRESTRIAL ALIEN
-1F47D FE0F ; emoji style; # (6.0 👽️ ) EXTRATERRESTRIAL ALIEN
-1F4A3 FE0E ; text style; # (6.0 💣︎ ) BOMB
-1F4A3 FE0F ; emoji style; # (6.0 💣️ ) BOMB
-1F4B0 FE0E ; text style; # (6.0 💰︎ ) MONEY BAG
-1F4B0 FE0F ; emoji style; # (6.0 💰️ ) MONEY BAG
-1F4B3 FE0E ; text style; # (6.0 💳︎ ) CREDIT CARD
-1F4B3 FE0F ; emoji style; # (6.0 💳️ ) CREDIT CARD
-1F4BB FE0E ; text style; # (6.0 💻︎ ) PERSONAL COMPUTER
-1F4BB FE0F ; emoji style; # (6.0 💻️ ) PERSONAL COMPUTER
-1F4BF FE0E ; text style; # (6.0 💿︎ ) OPTICAL DISC
-1F4BF FE0F ; emoji style; # (6.0 💿️ ) OPTICAL DISC
-1F4CB FE0E ; text style; # (6.0 📋︎ ) CLIPBOARD
-1F4CB FE0F ; emoji style; # (6.0 📋️ ) CLIPBOARD
-1F4DA FE0E ; text style; # (6.0 📚︎ ) BOOKS
-1F4DA FE0F ; emoji style; # (6.0 📚️ ) BOOKS
-1F4DF FE0E ; text style; # (6.0 📟︎ ) PAGER
-1F4DF FE0F ; emoji style; # (6.0 📟️ ) PAGER
-1F4E4 FE0E ; text style; # (6.0 📤︎ ) OUTBOX TRAY
-1F4E4 FE0F ; emoji style; # (6.0 📤️ ) OUTBOX TRAY
-1F4E5 FE0E ; text style; # (6.0 📥︎ ) INBOX TRAY
-1F4E5 FE0F ; emoji style; # (6.0 📥️ ) INBOX TRAY
-1F4E6 FE0E ; text style; # (6.0 📦︎ ) PACKAGE
-1F4E6 FE0F ; emoji style; # (6.0 📦️ ) PACKAGE
-1F4EA FE0E ; text style; # (6.0 📪︎ ) CLOSED MAILBOX WITH LOWERED FLAG
-1F4EA FE0F ; emoji style; # (6.0 📪️ ) CLOSED MAILBOX WITH LOWERED FLAG
-1F4EB FE0E ; text style; # (6.0 📫︎ ) CLOSED MAILBOX WITH RAISED FLAG
-1F4EB FE0F ; emoji style; # (6.0 📫️ ) CLOSED MAILBOX WITH RAISED FLAG
-1F4EC FE0E ; text style; # (6.0 📬︎ ) OPEN MAILBOX WITH RAISED FLAG
-1F4EC FE0F ; emoji style; # (6.0 📬️ ) OPEN MAILBOX WITH RAISED FLAG
-1F4ED FE0E ; text style; # (6.0 📭︎ ) OPEN MAILBOX WITH LOWERED FLAG
-1F4ED FE0F ; emoji style; # (6.0 📭️ ) OPEN MAILBOX WITH LOWERED FLAG
-1F4F7 FE0E ; text style; # (6.0 📷︎ ) CAMERA
-1F4F7 FE0F ; emoji style; # (6.0 📷️ ) CAMERA
-1F4F9 FE0E ; text style; # (6.0 📹︎ ) VIDEO CAMERA
-1F4F9 FE0F ; emoji style; # (6.0 📹️ ) VIDEO CAMERA
-1F4FA FE0E ; text style; # (6.0 📺︎ ) TELEVISION
-1F4FA FE0F ; emoji style; # (6.0 📺️ ) TELEVISION
-1F4FB FE0E ; text style; # (6.0 📻︎ ) RADIO
-1F4FB FE0F ; emoji style; # (6.0 📻️ ) RADIO
-1F4FD FE0E ; text style; # (7.0 📽︎ ) FILM PROJECTOR
-1F4FD FE0F ; emoji style; # (7.0 📽️ ) FILM PROJECTOR
-1F508 FE0E ; text style; # (6.0 🔈︎ ) SPEAKER
-1F508 FE0F ; emoji style; # (6.0 🔈️ ) SPEAKER
-1F50D FE0E ; text style; # (6.0 🔍︎ ) LEFT-POINTING MAGNIFYING GLASS
-1F50D FE0F ; emoji style; # (6.0 🔍️ ) LEFT-POINTING MAGNIFYING GLASS
-1F512 FE0E ; text style; # (6.0 🔒︎ ) LOCK
-1F512 FE0F ; emoji style; # (6.0 🔒️ ) LOCK
-1F513 FE0E ; text style; # (6.0 🔓︎ ) OPEN LOCK
-1F513 FE0F ; emoji style; # (6.0 🔓️ ) OPEN LOCK
-1F549 FE0E ; text style; # (7.0 🕉︎ ) OM SYMBOL
-1F549 FE0F ; emoji style; # (7.0 🕉️ ) OM SYMBOL
-1F54A FE0E ; text style; # (7.0 🕊︎ ) DOVE OF PEACE
-1F54A FE0F ; emoji style; # (7.0 🕊️ ) DOVE OF PEACE
-1F550 FE0E ; text style; # (6.0 🕐︎ ) CLOCK FACE ONE OCLOCK
-1F550 FE0F ; emoji style; # (6.0 🕐️ ) CLOCK FACE ONE OCLOCK
-1F551 FE0E ; text style; # (6.0 🕑︎ ) CLOCK FACE TWO OCLOCK
-1F551 FE0F ; emoji style; # (6.0 🕑️ ) CLOCK FACE TWO OCLOCK
-1F552 FE0E ; text style; # (6.0 🕒︎ ) CLOCK FACE THREE OCLOCK
-1F552 FE0F ; emoji style; # (6.0 🕒️ ) CLOCK FACE THREE OCLOCK
-1F553 FE0E ; text style; # (6.0 🕓︎ ) CLOCK FACE FOUR OCLOCK
-1F553 FE0F ; emoji style; # (6.0 🕓️ ) CLOCK FACE FOUR OCLOCK
-1F554 FE0E ; text style; # (6.0 🕔︎ ) CLOCK FACE FIVE OCLOCK
-1F554 FE0F ; emoji style; # (6.0 🕔️ ) CLOCK FACE FIVE OCLOCK
-1F555 FE0E ; text style; # (6.0 🕕︎ ) CLOCK FACE SIX OCLOCK
-1F555 FE0F ; emoji style; # (6.0 🕕️ ) CLOCK FACE SIX OCLOCK
-1F556 FE0E ; text style; # (6.0 🕖︎ ) CLOCK FACE SEVEN OCLOCK
-1F556 FE0F ; emoji style; # (6.0 🕖️ ) CLOCK FACE SEVEN OCLOCK
-1F557 FE0E ; text style; # (6.0 🕗︎ ) CLOCK FACE EIGHT OCLOCK
-1F557 FE0F ; emoji style; # (6.0 🕗️ ) CLOCK FACE EIGHT OCLOCK
-1F558 FE0E ; text style; # (6.0 🕘︎ ) CLOCK FACE NINE OCLOCK
-1F558 FE0F ; emoji style; # (6.0 🕘️ ) CLOCK FACE NINE OCLOCK
-1F559 FE0E ; text style; # (6.0 🕙︎ ) CLOCK FACE TEN OCLOCK
-1F559 FE0F ; emoji style; # (6.0 🕙️ ) CLOCK FACE TEN OCLOCK
-1F55A FE0E ; text style; # (6.0 🕚︎ ) CLOCK FACE ELEVEN OCLOCK
-1F55A FE0F ; emoji style; # (6.0 🕚️ ) CLOCK FACE ELEVEN OCLOCK
-1F55B FE0E ; text style; # (6.0 🕛︎ ) CLOCK FACE TWELVE OCLOCK
-1F55B FE0F ; emoji style; # (6.0 🕛️ ) CLOCK FACE TWELVE OCLOCK
-1F55C FE0E ; text style; # (6.0 🕜︎ ) CLOCK FACE ONE-THIRTY
-1F55C FE0F ; emoji style; # (6.0 🕜️ ) CLOCK FACE ONE-THIRTY
-1F55D FE0E ; text style; # (6.0 🕝︎ ) CLOCK FACE TWO-THIRTY
-1F55D FE0F ; emoji style; # (6.0 🕝️ ) CLOCK FACE TWO-THIRTY
-1F55E FE0E ; text style; # (6.0 🕞︎ ) CLOCK FACE THREE-THIRTY
-1F55E FE0F ; emoji style; # (6.0 🕞️ ) CLOCK FACE THREE-THIRTY
-1F55F FE0E ; text style; # (6.0 🕟︎ ) CLOCK FACE FOUR-THIRTY
-1F55F FE0F ; emoji style; # (6.0 🕟️ ) CLOCK FACE FOUR-THIRTY
-1F560 FE0E ; text style; # (6.0 🕠︎ ) CLOCK FACE FIVE-THIRTY
-1F560 FE0F ; emoji style; # (6.0 🕠️ ) CLOCK FACE FIVE-THIRTY
-1F561 FE0E ; text style; # (6.0 🕡︎ ) CLOCK FACE SIX-THIRTY
-1F561 FE0F ; emoji style; # (6.0 🕡️ ) CLOCK FACE SIX-THIRTY
-1F562 FE0E ; text style; # (6.0 🕢︎ ) CLOCK FACE SEVEN-THIRTY
-1F562 FE0F ; emoji style; # (6.0 🕢️ ) CLOCK FACE SEVEN-THIRTY
-1F563 FE0E ; text style; # (6.0 🕣︎ ) CLOCK FACE EIGHT-THIRTY
-1F563 FE0F ; emoji style; # (6.0 🕣️ ) CLOCK FACE EIGHT-THIRTY
-1F564 FE0E ; text style; # (6.0 🕤︎ ) CLOCK FACE NINE-THIRTY
-1F564 FE0F ; emoji style; # (6.0 🕤️ ) CLOCK FACE NINE-THIRTY
-1F565 FE0E ; text style; # (6.0 🕥︎ ) CLOCK FACE TEN-THIRTY
-1F565 FE0F ; emoji style; # (6.0 🕥️ ) CLOCK FACE TEN-THIRTY
-1F566 FE0E ; text style; # (6.0 🕦︎ ) CLOCK FACE ELEVEN-THIRTY
-1F566 FE0F ; emoji style; # (6.0 🕦️ ) CLOCK FACE ELEVEN-THIRTY
-1F567 FE0E ; text style; # (6.0 🕧︎ ) CLOCK FACE TWELVE-THIRTY
-1F567 FE0F ; emoji style; # (6.0 🕧️ ) CLOCK FACE TWELVE-THIRTY
-1F56F FE0E ; text style; # (7.0 🕯︎ ) CANDLE
-1F56F FE0F ; emoji style; # (7.0 🕯️ ) CANDLE
-1F570 FE0E ; text style; # (7.0 🕰︎ ) MANTELPIECE CLOCK
-1F570 FE0F ; emoji style; # (7.0 🕰️ ) MANTELPIECE CLOCK
-1F573 FE0E ; text style; # (7.0 🕳︎ ) HOLE
-1F573 FE0F ; emoji style; # (7.0 🕳️ ) HOLE
-1F574 FE0E ; text style; # (7.0 🕴︎ ) MAN IN BUSINESS SUIT LEVITATING
-1F574 FE0F ; emoji style; # (7.0 🕴️ ) MAN IN BUSINESS SUIT LEVITATING
-1F575 FE0E ; text style; # (7.0 🕵︎ ) SLEUTH OR SPY
-1F575 FE0F ; emoji style; # (7.0 🕵️ ) SLEUTH OR SPY
-1F576 FE0E ; text style; # (7.0 🕶︎ ) DARK SUNGLASSES
-1F576 FE0F ; emoji style; # (7.0 🕶️ ) DARK SUNGLASSES
-1F577 FE0E ; text style; # (7.0 🕷︎ ) SPIDER
-1F577 FE0F ; emoji style; # (7.0 🕷️ ) SPIDER
-1F578 FE0E ; text style; # (7.0 🕸︎ ) SPIDER WEB
-1F578 FE0F ; emoji style; # (7.0 🕸️ ) SPIDER WEB
-1F579 FE0E ; text style; # (7.0 🕹︎ ) JOYSTICK
-1F579 FE0F ; emoji style; # (7.0 🕹️ ) JOYSTICK
-1F587 FE0E ; text style; # (7.0 🖇︎ ) LINKED PAPERCLIPS
-1F587 FE0F ; emoji style; # (7.0 🖇️ ) LINKED PAPERCLIPS
-1F58A FE0E ; text style; # (7.0 🖊︎ ) LOWER LEFT BALLPOINT PEN
-1F58A FE0F ; emoji style; # (7.0 🖊️ ) LOWER LEFT BALLPOINT PEN
-1F58B FE0E ; text style; # (7.0 🖋︎ ) LOWER LEFT FOUNTAIN PEN
-1F58B FE0F ; emoji style; # (7.0 🖋️ ) LOWER LEFT FOUNTAIN PEN
-1F58C FE0E ; text style; # (7.0 🖌︎ ) LOWER LEFT PAINTBRUSH
-1F58C FE0F ; emoji style; # (7.0 🖌️ ) LOWER LEFT PAINTBRUSH
-1F58D FE0E ; text style; # (7.0 🖍︎ ) LOWER LEFT CRAYON
-1F58D FE0F ; emoji style; # (7.0 🖍️ ) LOWER LEFT CRAYON
-1F590 FE0E ; text style; # (7.0 🖐︎ ) RAISED HAND WITH FINGERS SPLAYED
-1F590 FE0F ; emoji style; # (7.0 🖐️ ) RAISED HAND WITH FINGERS SPLAYED
-1F5A5 FE0E ; text style; # (7.0 🖥︎ ) DESKTOP COMPUTER
-1F5A5 FE0F ; emoji style; # (7.0 🖥️ ) DESKTOP COMPUTER
-1F5A8 FE0E ; text style; # (7.0 🖨︎ ) PRINTER
-1F5A8 FE0F ; emoji style; # (7.0 🖨️ ) PRINTER
-1F5B1 FE0E ; text style; # (7.0 🖱︎ ) THREE BUTTON MOUSE
-1F5B1 FE0F ; emoji style; # (7.0 🖱️ ) THREE BUTTON MOUSE
-1F5B2 FE0E ; text style; # (7.0 🖲︎ ) TRACKBALL
-1F5B2 FE0F ; emoji style; # (7.0 🖲️ ) TRACKBALL
-1F5BC FE0E ; text style; # (7.0 🖼︎ ) FRAME WITH PICTURE
-1F5BC FE0F ; emoji style; # (7.0 🖼️ ) FRAME WITH PICTURE
-1F5C2 FE0E ; text style; # (7.0 🗂︎ ) CARD INDEX DIVIDERS
-1F5C2 FE0F ; emoji style; # (7.0 🗂️ ) CARD INDEX DIVIDERS
-1F5C3 FE0E ; text style; # (7.0 🗃︎ ) CARD FILE BOX
-1F5C3 FE0F ; emoji style; # (7.0 🗃️ ) CARD FILE BOX
-1F5C4 FE0E ; text style; # (7.0 🗄︎ ) FILE CABINET
-1F5C4 FE0F ; emoji style; # (7.0 🗄️ ) FILE CABINET
-1F5D1 FE0E ; text style; # (7.0 🗑︎ ) WASTEBASKET
-1F5D1 FE0F ; emoji style; # (7.0 🗑️ ) WASTEBASKET
-1F5D2 FE0E ; text style; # (7.0 🗒︎ ) SPIRAL NOTE PAD
-1F5D2 FE0F ; emoji style; # (7.0 🗒️ ) SPIRAL NOTE PAD
-1F5D3 FE0E ; text style; # (7.0 🗓︎ ) SPIRAL CALENDAR PAD
-1F5D3 FE0F ; emoji style; # (7.0 🗓️ ) SPIRAL CALENDAR PAD
-1F5DC FE0E ; text style; # (7.0 🗜︎ ) COMPRESSION
-1F5DC FE0F ; emoji style; # (7.0 🗜️ ) COMPRESSION
-1F5DD FE0E ; text style; # (7.0 🗝︎ ) OLD KEY
-1F5DD FE0F ; emoji style; # (7.0 🗝️ ) OLD KEY
-1F5DE FE0E ; text style; # (7.0 🗞︎ ) ROLLED-UP NEWSPAPER
-1F5DE FE0F ; emoji style; # (7.0 🗞️ ) ROLLED-UP NEWSPAPER
-1F5E1 FE0E ; text style; # (7.0 🗡︎ ) DAGGER KNIFE
-1F5E1 FE0F ; emoji style; # (7.0 🗡️ ) DAGGER KNIFE
-1F5E3 FE0E ; text style; # (7.0 🗣︎ ) SPEAKING HEAD IN SILHOUETTE
-1F5E3 FE0F ; emoji style; # (7.0 🗣️ ) SPEAKING HEAD IN SILHOUETTE
-1F5E8 FE0E ; text style; # (7.0 🗨︎ ) LEFT SPEECH BUBBLE
-1F5E8 FE0F ; emoji style; # (7.0 🗨️ ) LEFT SPEECH BUBBLE
-1F5EF FE0E ; text style; # (7.0 🗯︎ ) RIGHT ANGER BUBBLE
-1F5EF FE0F ; emoji style; # (7.0 🗯️ ) RIGHT ANGER BUBBLE
-1F5F3 FE0E ; text style; # (7.0 🗳︎ ) BALLOT BOX WITH BALLOT
-1F5F3 FE0F ; emoji style; # (7.0 🗳️ ) BALLOT BOX WITH BALLOT
-1F5FA FE0E ; text style; # (7.0 🗺︎ ) WORLD MAP
-1F5FA FE0F ; emoji style; # (7.0 🗺️ ) WORLD MAP
-1F610 FE0E ; text style; # (6.0 😐︎ ) NEUTRAL FACE
-1F610 FE0F ; emoji style; # (6.0 😐️ ) NEUTRAL FACE
-1F687 FE0E ; text style; # (6.0 🚇︎ ) METRO
-1F687 FE0F ; emoji style; # (6.0 🚇️ ) METRO
-1F68D FE0E ; text style; # (6.0 🚍︎ ) ONCOMING BUS
-1F68D FE0F ; emoji style; # (6.0 🚍️ ) ONCOMING BUS
-1F691 FE0E ; text style; # (6.0 🚑︎ ) AMBULANCE
-1F691 FE0F ; emoji style; # (6.0 🚑️ ) AMBULANCE
-1F694 FE0E ; text style; # (6.0 🚔︎ ) ONCOMING POLICE CAR
-1F694 FE0F ; emoji style; # (6.0 🚔️ ) ONCOMING POLICE CAR
-1F698 FE0E ; text style; # (6.0 🚘︎ ) ONCOMING AUTOMOBILE
-1F698 FE0F ; emoji style; # (6.0 🚘️ ) ONCOMING AUTOMOBILE
-1F6AD FE0E ; text style; # (6.0 🚭︎ ) NO SMOKING SYMBOL
-1F6AD FE0F ; emoji style; # (6.0 🚭️ ) NO SMOKING SYMBOL
-1F6B2 FE0E ; text style; # (6.0 🚲︎ ) BICYCLE
-1F6B2 FE0F ; emoji style; # (6.0 🚲️ ) BICYCLE
-1F6B9 FE0E ; text style; # (6.0 🚹︎ ) MENS SYMBOL
-1F6B9 FE0F ; emoji style; # (6.0 🚹️ ) MENS SYMBOL
-1F6BA FE0E ; text style; # (6.0 🚺︎ ) WOMENS SYMBOL
-1F6BA FE0F ; emoji style; # (6.0 🚺️ ) WOMENS SYMBOL
-1F6BC FE0E ; text style; # (6.0 🚼︎ ) BABY SYMBOL
-1F6BC FE0F ; emoji style; # (6.0 🚼️ ) BABY SYMBOL
-1F6CB FE0E ; text style; # (7.0 🛋︎ ) COUCH AND LAMP
-1F6CB FE0F ; emoji style; # (7.0 🛋️ ) COUCH AND LAMP
-1F6CD FE0E ; text style; # (7.0 🛍︎ ) SHOPPING BAGS
-1F6CD FE0F ; emoji style; # (7.0 🛍️ ) SHOPPING BAGS
-1F6CE FE0E ; text style; # (7.0 🛎︎ ) BELLHOP BELL
-1F6CE FE0F ; emoji style; # (7.0 🛎️ ) BELLHOP BELL
-1F6CF FE0E ; text style; # (7.0 🛏︎ ) BED
-1F6CF FE0F ; emoji style; # (7.0 🛏️ ) BED
-1F6E0 FE0E ; text style; # (7.0 🛠︎ ) HAMMER AND WRENCH
-1F6E0 FE0F ; emoji style; # (7.0 🛠️ ) HAMMER AND WRENCH
-1F6E1 FE0E ; text style; # (7.0 🛡︎ ) SHIELD
-1F6E1 FE0F ; emoji style; # (7.0 🛡️ ) SHIELD
-1F6E2 FE0E ; text style; # (7.0 🛢︎ ) OIL DRUM
-1F6E2 FE0F ; emoji style; # (7.0 🛢️ ) OIL DRUM
-1F6E3 FE0E ; text style; # (7.0 🛣︎ ) MOTORWAY
-1F6E3 FE0F ; emoji style; # (7.0 🛣️ ) MOTORWAY
-1F6E4 FE0E ; text style; # (7.0 🛤︎ ) RAILWAY TRACK
-1F6E4 FE0F ; emoji style; # (7.0 🛤️ ) RAILWAY TRACK
-1F6E5 FE0E ; text style; # (7.0 🛥︎ ) MOTOR BOAT
-1F6E5 FE0F ; emoji style; # (7.0 🛥️ ) MOTOR BOAT
-1F6E9 FE0E ; text style; # (7.0 🛩︎ ) SMALL AIRPLANE
-1F6E9 FE0F ; emoji style; # (7.0 🛩️ ) SMALL AIRPLANE
-1F6F0 FE0E ; text style; # (7.0 🛰︎ ) SATELLITE
-1F6F0 FE0F ; emoji style; # (7.0 🛰️ ) SATELLITE
-1F6F3 FE0E ; text style; # (7.0 🛳︎ ) PASSENGER SHIP
-1F6F3 FE0F ; emoji style; # (7.0 🛳️ ) PASSENGER SHIP
+0023 FE0E ; text style; # (1.1) NUMBER SIGN
+0023 FE0F ; emoji style; # (1.1) NUMBER SIGN
+002A FE0E ; text style; # (1.1) ASTERISK
+002A FE0F ; emoji style; # (1.1) ASTERISK
+0030 FE0E ; text style; # (1.1) DIGIT ZERO
+0030 FE0F ; emoji style; # (1.1) DIGIT ZERO
+0031 FE0E ; text style; # (1.1) DIGIT ONE
+0031 FE0F ; emoji style; # (1.1) DIGIT ONE
+0032 FE0E ; text style; # (1.1) DIGIT TWO
+0032 FE0F ; emoji style; # (1.1) DIGIT TWO
+0033 FE0E ; text style; # (1.1) DIGIT THREE
+0033 FE0F ; emoji style; # (1.1) DIGIT THREE
+0034 FE0E ; text style; # (1.1) DIGIT FOUR
+0034 FE0F ; emoji style; # (1.1) DIGIT FOUR
+0035 FE0E ; text style; # (1.1) DIGIT FIVE
+0035 FE0F ; emoji style; # (1.1) DIGIT FIVE
+0036 FE0E ; text style; # (1.1) DIGIT SIX
+0036 FE0F ; emoji style; # (1.1) DIGIT SIX
+0037 FE0E ; text style; # (1.1) DIGIT SEVEN
+0037 FE0F ; emoji style; # (1.1) DIGIT SEVEN
+0038 FE0E ; text style; # (1.1) DIGIT EIGHT
+0038 FE0F ; emoji style; # (1.1) DIGIT EIGHT
+0039 FE0E ; text style; # (1.1) DIGIT NINE
+0039 FE0F ; emoji style; # (1.1) DIGIT NINE
+00A9 FE0E ; text style; # (1.1) COPYRIGHT SIGN
+00A9 FE0F ; emoji style; # (1.1) COPYRIGHT SIGN
+00AE FE0E ; text style; # (1.1) REGISTERED SIGN
+00AE FE0F ; emoji style; # (1.1) REGISTERED SIGN
+203C FE0E ; text style; # (1.1) DOUBLE EXCLAMATION MARK
+203C FE0F ; emoji style; # (1.1) DOUBLE EXCLAMATION MARK
+2049 FE0E ; text style; # (3.0) EXCLAMATION QUESTION MARK
+2049 FE0F ; emoji style; # (3.0) EXCLAMATION QUESTION MARK
+2122 FE0E ; text style; # (1.1) TRADE MARK SIGN
+2122 FE0F ; emoji style; # (1.1) TRADE MARK SIGN
+2139 FE0E ; text style; # (3.0) INFORMATION SOURCE
+2139 FE0F ; emoji style; # (3.0) INFORMATION SOURCE
+2194 FE0E ; text style; # (1.1) LEFT RIGHT ARROW
+2194 FE0F ; emoji style; # (1.1) LEFT RIGHT ARROW
+2195 FE0E ; text style; # (1.1) UP DOWN ARROW
+2195 FE0F ; emoji style; # (1.1) UP DOWN ARROW
+2196 FE0E ; text style; # (1.1) NORTH WEST ARROW
+2196 FE0F ; emoji style; # (1.1) NORTH WEST ARROW
+2197 FE0E ; text style; # (1.1) NORTH EAST ARROW
+2197 FE0F ; emoji style; # (1.1) NORTH EAST ARROW
+2198 FE0E ; text style; # (1.1) SOUTH EAST ARROW
+2198 FE0F ; emoji style; # (1.1) SOUTH EAST ARROW
+2199 FE0E ; text style; # (1.1) SOUTH WEST ARROW
+2199 FE0F ; emoji style; # (1.1) SOUTH WEST ARROW
+21A9 FE0E ; text style; # (1.1) LEFTWARDS ARROW WITH HOOK
+21A9 FE0F ; emoji style; # (1.1) LEFTWARDS ARROW WITH HOOK
+21AA FE0E ; text style; # (1.1) RIGHTWARDS ARROW WITH HOOK
+21AA FE0F ; emoji style; # (1.1) RIGHTWARDS ARROW WITH HOOK
+231A FE0E ; text style; # (1.1) WATCH
+231A FE0F ; emoji style; # (1.1) WATCH
+231B FE0E ; text style; # (1.1) HOURGLASS
+231B FE0F ; emoji style; # (1.1) HOURGLASS
+2328 FE0E ; text style; # (1.1) KEYBOARD
+2328 FE0F ; emoji style; # (1.1) KEYBOARD
+23CF FE0E ; text style; # (4.0) EJECT SYMBOL
+23CF FE0F ; emoji style; # (4.0) EJECT SYMBOL
+23E9 FE0E ; text style; # (6.0) BLACK RIGHT-POINTING DOUBLE TRIANGLE
+23E9 FE0F ; emoji style; # (6.0) BLACK RIGHT-POINTING DOUBLE TRIANGLE
+23EA FE0E ; text style; # (6.0) BLACK LEFT-POINTING DOUBLE TRIANGLE
+23EA FE0F ; emoji style; # (6.0) BLACK LEFT-POINTING DOUBLE TRIANGLE
+23EB FE0E ; text style; # (6.0) BLACK UP-POINTING DOUBLE TRIANGLE
+23EB FE0F ; emoji style; # (6.0) BLACK UP-POINTING DOUBLE TRIANGLE
+23EC FE0E ; text style; # (6.0) BLACK DOWN-POINTING DOUBLE TRIANGLE
+23EC FE0F ; emoji style; # (6.0) BLACK DOWN-POINTING DOUBLE TRIANGLE
+23ED FE0E ; text style; # (6.0) BLACK RIGHT-POINTING DOUBLE TRIANGLE WITH VERTICAL BAR
+23ED FE0F ; emoji style; # (6.0) BLACK RIGHT-POINTING DOUBLE TRIANGLE WITH VERTICAL BAR
+23EE FE0E ; text style; # (6.0) BLACK LEFT-POINTING DOUBLE TRIANGLE WITH VERTICAL BAR
+23EE FE0F ; emoji style; # (6.0) BLACK LEFT-POINTING DOUBLE TRIANGLE WITH VERTICAL BAR
+23EF FE0E ; text style; # (6.0) BLACK RIGHT-POINTING TRIANGLE WITH DOUBLE VERTICAL BAR
+23EF FE0F ; emoji style; # (6.0) BLACK RIGHT-POINTING TRIANGLE WITH DOUBLE VERTICAL BAR
+23F0 FE0E ; text style; # (6.0) ALARM CLOCK
+23F0 FE0F ; emoji style; # (6.0) ALARM CLOCK
+23F1 FE0E ; text style; # (6.0) STOPWATCH
+23F1 FE0F ; emoji style; # (6.0) STOPWATCH
+23F2 FE0E ; text style; # (6.0) TIMER CLOCK
+23F2 FE0F ; emoji style; # (6.0) TIMER CLOCK
+23F3 FE0E ; text style; # (6.0) HOURGLASS WITH FLOWING SAND
+23F3 FE0F ; emoji style; # (6.0) HOURGLASS WITH FLOWING SAND
+23F8 FE0E ; text style; # (7.0) DOUBLE VERTICAL BAR
+23F8 FE0F ; emoji style; # (7.0) DOUBLE VERTICAL BAR
+23F9 FE0E ; text style; # (7.0) BLACK SQUARE FOR STOP
+23F9 FE0F ; emoji style; # (7.0) BLACK SQUARE FOR STOP
+23FA FE0E ; text style; # (7.0) BLACK CIRCLE FOR RECORD
+23FA FE0F ; emoji style; # (7.0) BLACK CIRCLE FOR RECORD
+24C2 FE0E ; text style; # (1.1) CIRCLED LATIN CAPITAL LETTER M
+24C2 FE0F ; emoji style; # (1.1) CIRCLED LATIN CAPITAL LETTER M
+25AA FE0E ; text style; # (1.1) BLACK SMALL SQUARE
+25AA FE0F ; emoji style; # (1.1) BLACK SMALL SQUARE
+25AB FE0E ; text style; # (1.1) WHITE SMALL SQUARE
+25AB FE0F ; emoji style; # (1.1) WHITE SMALL SQUARE
+25B6 FE0E ; text style; # (1.1) BLACK RIGHT-POINTING TRIANGLE
+25B6 FE0F ; emoji style; # (1.1) BLACK RIGHT-POINTING TRIANGLE
+25C0 FE0E ; text style; # (1.1) BLACK LEFT-POINTING TRIANGLE
+25C0 FE0F ; emoji style; # (1.1) BLACK LEFT-POINTING TRIANGLE
+25FB FE0E ; text style; # (3.2) WHITE MEDIUM SQUARE
+25FB FE0F ; emoji style; # (3.2) WHITE MEDIUM SQUARE
+25FC FE0E ; text style; # (3.2) BLACK MEDIUM SQUARE
+25FC FE0F ; emoji style; # (3.2) BLACK MEDIUM SQUARE
+25FD FE0E ; text style; # (3.2) WHITE MEDIUM SMALL SQUARE
+25FD FE0F ; emoji style; # (3.2) WHITE MEDIUM SMALL SQUARE
+25FE FE0E ; text style; # (3.2) BLACK MEDIUM SMALL SQUARE
+25FE FE0F ; emoji style; # (3.2) BLACK MEDIUM SMALL SQUARE
+2600 FE0E ; text style; # (1.1) BLACK SUN WITH RAYS
+2600 FE0F ; emoji style; # (1.1) BLACK SUN WITH RAYS
+2601 FE0E ; text style; # (1.1) CLOUD
+2601 FE0F ; emoji style; # (1.1) CLOUD
+2602 FE0E ; text style; # (1.1) UMBRELLA
+2602 FE0F ; emoji style; # (1.1) UMBRELLA
+2603 FE0E ; text style; # (1.1) SNOWMAN
+2603 FE0F ; emoji style; # (1.1) SNOWMAN
+2604 FE0E ; text style; # (1.1) COMET
+2604 FE0F ; emoji style; # (1.1) COMET
+260E FE0E ; text style; # (1.1) BLACK TELEPHONE
+260E FE0F ; emoji style; # (1.1) BLACK TELEPHONE
+2611 FE0E ; text style; # (1.1) BALLOT BOX WITH CHECK
+2611 FE0F ; emoji style; # (1.1) BALLOT BOX WITH CHECK
+2614 FE0E ; text style; # (4.0) UMBRELLA WITH RAIN DROPS
+2614 FE0F ; emoji style; # (4.0) UMBRELLA WITH RAIN DROPS
+2615 FE0E ; text style; # (4.0) HOT BEVERAGE
+2615 FE0F ; emoji style; # (4.0) HOT BEVERAGE
+2618 FE0E ; text style; # (4.1) SHAMROCK
+2618 FE0F ; emoji style; # (4.1) SHAMROCK
+261D FE0E ; text style; # (1.1) WHITE UP POINTING INDEX
+261D FE0F ; emoji style; # (1.1) WHITE UP POINTING INDEX
+2620 FE0E ; text style; # (1.1) SKULL AND CROSSBONES
+2620 FE0F ; emoji style; # (1.1) SKULL AND CROSSBONES
+2622 FE0E ; text style; # (1.1) RADIOACTIVE SIGN
+2622 FE0F ; emoji style; # (1.1) RADIOACTIVE SIGN
+2623 FE0E ; text style; # (1.1) BIOHAZARD SIGN
+2623 FE0F ; emoji style; # (1.1) BIOHAZARD SIGN
+2626 FE0E ; text style; # (1.1) ORTHODOX CROSS
+2626 FE0F ; emoji style; # (1.1) ORTHODOX CROSS
+262A FE0E ; text style; # (1.1) STAR AND CRESCENT
+262A FE0F ; emoji style; # (1.1) STAR AND CRESCENT
+262E FE0E ; text style; # (1.1) PEACE SYMBOL
+262E FE0F ; emoji style; # (1.1) PEACE SYMBOL
+262F FE0E ; text style; # (1.1) YIN YANG
+262F FE0F ; emoji style; # (1.1) YIN YANG
+2638 FE0E ; text style; # (1.1) WHEEL OF DHARMA
+2638 FE0F ; emoji style; # (1.1) WHEEL OF DHARMA
+2639 FE0E ; text style; # (1.1) WHITE FROWNING FACE
+2639 FE0F ; emoji style; # (1.1) WHITE FROWNING FACE
+263A FE0E ; text style; # (1.1) WHITE SMILING FACE
+263A FE0F ; emoji style; # (1.1) WHITE SMILING FACE
+2640 FE0E ; text style; # (1.1) FEMALE SIGN
+2640 FE0F ; emoji style; # (1.1) FEMALE SIGN
+2642 FE0E ; text style; # (1.1) MALE SIGN
+2642 FE0F ; emoji style; # (1.1) MALE SIGN
+2648 FE0E ; text style; # (1.1) ARIES
+2648 FE0F ; emoji style; # (1.1) ARIES
+2649 FE0E ; text style; # (1.1) TAURUS
+2649 FE0F ; emoji style; # (1.1) TAURUS
+264A FE0E ; text style; # (1.1) GEMINI
+264A FE0F ; emoji style; # (1.1) GEMINI
+264B FE0E ; text style; # (1.1) CANCER
+264B FE0F ; emoji style; # (1.1) CANCER
+264C FE0E ; text style; # (1.1) LEO
+264C FE0F ; emoji style; # (1.1) LEO
+264D FE0E ; text style; # (1.1) VIRGO
+264D FE0F ; emoji style; # (1.1) VIRGO
+264E FE0E ; text style; # (1.1) LIBRA
+264E FE0F ; emoji style; # (1.1) LIBRA
+264F FE0E ; text style; # (1.1) SCORPIUS
+264F FE0F ; emoji style; # (1.1) SCORPIUS
+2650 FE0E ; text style; # (1.1) SAGITTARIUS
+2650 FE0F ; emoji style; # (1.1) SAGITTARIUS
+2651 FE0E ; text style; # (1.1) CAPRICORN
+2651 FE0F ; emoji style; # (1.1) CAPRICORN
+2652 FE0E ; text style; # (1.1) AQUARIUS
+2652 FE0F ; emoji style; # (1.1) AQUARIUS
+2653 FE0E ; text style; # (1.1) PISCES
+2653 FE0F ; emoji style; # (1.1) PISCES
+265F FE0E ; text style; # (1.1) BLACK CHESS PAWN
+265F FE0F ; emoji style; # (1.1) BLACK CHESS PAWN
+2660 FE0E ; text style; # (1.1) BLACK SPADE SUIT
+2660 FE0F ; emoji style; # (1.1) BLACK SPADE SUIT
+2663 FE0E ; text style; # (1.1) BLACK CLUB SUIT
+2663 FE0F ; emoji style; # (1.1) BLACK CLUB SUIT
+2665 FE0E ; text style; # (1.1) BLACK HEART SUIT
+2665 FE0F ; emoji style; # (1.1) BLACK HEART SUIT
+2666 FE0E ; text style; # (1.1) BLACK DIAMOND SUIT
+2666 FE0F ; emoji style; # (1.1) BLACK DIAMOND SUIT
+2668 FE0E ; text style; # (1.1) HOT SPRINGS
+2668 FE0F ; emoji style; # (1.1) HOT SPRINGS
+267B FE0E ; text style; # (3.2) BLACK UNIVERSAL RECYCLING SYMBOL
+267B FE0F ; emoji style; # (3.2) BLACK UNIVERSAL RECYCLING SYMBOL
+267E FE0E ; text style; # (4.1) PERMANENT PAPER SIGN
+267E FE0F ; emoji style; # (4.1) PERMANENT PAPER SIGN
+267F FE0E ; text style; # (4.1) WHEELCHAIR SYMBOL
+267F FE0F ; emoji style; # (4.1) WHEELCHAIR SYMBOL
+2692 FE0E ; text style; # (4.1) HAMMER AND PICK
+2692 FE0F ; emoji style; # (4.1) HAMMER AND PICK
+2693 FE0E ; text style; # (4.1) ANCHOR
+2693 FE0F ; emoji style; # (4.1) ANCHOR
+2694 FE0E ; text style; # (4.1) CROSSED SWORDS
+2694 FE0F ; emoji style; # (4.1) CROSSED SWORDS
+2695 FE0E ; text style; # (4.1) STAFF OF AESCULAPIUS
+2695 FE0F ; emoji style; # (4.1) STAFF OF AESCULAPIUS
+2696 FE0E ; text style; # (4.1) SCALES
+2696 FE0F ; emoji style; # (4.1) SCALES
+2697 FE0E ; text style; # (4.1) ALEMBIC
+2697 FE0F ; emoji style; # (4.1) ALEMBIC
+2699 FE0E ; text style; # (4.1) GEAR
+2699 FE0F ; emoji style; # (4.1) GEAR
+269B FE0E ; text style; # (4.1) ATOM SYMBOL
+269B FE0F ; emoji style; # (4.1) ATOM SYMBOL
+269C FE0E ; text style; # (4.1) FLEUR-DE-LIS
+269C FE0F ; emoji style; # (4.1) FLEUR-DE-LIS
+26A0 FE0E ; text style; # (4.0) WARNING SIGN
+26A0 FE0F ; emoji style; # (4.0) WARNING SIGN
+26A1 FE0E ; text style; # (4.0) HIGH VOLTAGE SIGN
+26A1 FE0F ; emoji style; # (4.0) HIGH VOLTAGE SIGN
+26A7 FE0E ; text style; # (4.1) MALE WITH STROKE AND MALE AND FEMALE SIGN
+26A7 FE0F ; emoji style; # (4.1) MALE WITH STROKE AND MALE AND FEMALE SIGN
+26AA FE0E ; text style; # (4.1) MEDIUM WHITE CIRCLE
+26AA FE0F ; emoji style; # (4.1) MEDIUM WHITE CIRCLE
+26AB FE0E ; text style; # (4.1) MEDIUM BLACK CIRCLE
+26AB FE0F ; emoji style; # (4.1) MEDIUM BLACK CIRCLE
+26B0 FE0E ; text style; # (4.1) COFFIN
+26B0 FE0F ; emoji style; # (4.1) COFFIN
+26B1 FE0E ; text style; # (4.1) FUNERAL URN
+26B1 FE0F ; emoji style; # (4.1) FUNERAL URN
+26BD FE0E ; text style; # (5.2) SOCCER BALL
+26BD FE0F ; emoji style; # (5.2) SOCCER BALL
+26BE FE0E ; text style; # (5.2) BASEBALL
+26BE FE0F ; emoji style; # (5.2) BASEBALL
+26C4 FE0E ; text style; # (5.2) SNOWMAN WITHOUT SNOW
+26C4 FE0F ; emoji style; # (5.2) SNOWMAN WITHOUT SNOW
+26C5 FE0E ; text style; # (5.2) SUN BEHIND CLOUD
+26C5 FE0F ; emoji style; # (5.2) SUN BEHIND CLOUD
+26C8 FE0E ; text style; # (5.2) THUNDER CLOUD AND RAIN
+26C8 FE0F ; emoji style; # (5.2) THUNDER CLOUD AND RAIN
+26CE FE0E ; text style; # (6.0) OPHIUCHUS
+26CE FE0F ; emoji style; # (6.0) OPHIUCHUS
+26CF FE0E ; text style; # (5.2) PICK
+26CF FE0F ; emoji style; # (5.2) PICK
+26D1 FE0E ; text style; # (5.2) HELMET WITH WHITE CROSS
+26D1 FE0F ; emoji style; # (5.2) HELMET WITH WHITE CROSS
+26D3 FE0E ; text style; # (5.2) CHAINS
+26D3 FE0F ; emoji style; # (5.2) CHAINS
+26D4 FE0E ; text style; # (5.2) NO ENTRY
+26D4 FE0F ; emoji style; # (5.2) NO ENTRY
+26E9 FE0E ; text style; # (5.2) SHINTO SHRINE
+26E9 FE0F ; emoji style; # (5.2) SHINTO SHRINE
+26EA FE0E ; text style; # (5.2) CHURCH
+26EA FE0F ; emoji style; # (5.2) CHURCH
+26F0 FE0E ; text style; # (5.2) MOUNTAIN
+26F0 FE0F ; emoji style; # (5.2) MOUNTAIN
+26F1 FE0E ; text style; # (5.2) UMBRELLA ON GROUND
+26F1 FE0F ; emoji style; # (5.2) UMBRELLA ON GROUND
+26F2 FE0E ; text style; # (5.2) FOUNTAIN
+26F2 FE0F ; emoji style; # (5.2) FOUNTAIN
+26F3 FE0E ; text style; # (5.2) FLAG IN HOLE
+26F3 FE0F ; emoji style; # (5.2) FLAG IN HOLE
+26F4 FE0E ; text style; # (5.2) FERRY
+26F4 FE0F ; emoji style; # (5.2) FERRY
+26F5 FE0E ; text style; # (5.2) SAILBOAT
+26F5 FE0F ; emoji style; # (5.2) SAILBOAT
+26F7 FE0E ; text style; # (5.2) SKIER
+26F7 FE0F ; emoji style; # (5.2) SKIER
+26F8 FE0E ; text style; # (5.2) ICE SKATE
+26F8 FE0F ; emoji style; # (5.2) ICE SKATE
+26F9 FE0E ; text style; # (5.2) PERSON WITH BALL
+26F9 FE0F ; emoji style; # (5.2) PERSON WITH BALL
+26FA FE0E ; text style; # (5.2) TENT
+26FA FE0F ; emoji style; # (5.2) TENT
+26FD FE0E ; text style; # (5.2) FUEL PUMP
+26FD FE0F ; emoji style; # (5.2) FUEL PUMP
+2702 FE0E ; text style; # (1.1) BLACK SCISSORS
+2702 FE0F ; emoji style; # (1.1) BLACK SCISSORS
+2705 FE0E ; text style; # (6.0) WHITE HEAVY CHECK MARK
+2705 FE0F ; emoji style; # (6.0) WHITE HEAVY CHECK MARK
+2708 FE0E ; text style; # (1.1) AIRPLANE
+2708 FE0F ; emoji style; # (1.1) AIRPLANE
+2709 FE0E ; text style; # (1.1) ENVELOPE
+2709 FE0F ; emoji style; # (1.1) ENVELOPE
+270A FE0E ; text style; # (6.0) RAISED FIST
+270A FE0F ; emoji style; # (6.0) RAISED FIST
+270B FE0E ; text style; # (6.0) RAISED HAND
+270B FE0F ; emoji style; # (6.0) RAISED HAND
+270C FE0E ; text style; # (1.1) VICTORY HAND
+270C FE0F ; emoji style; # (1.1) VICTORY HAND
+270D FE0E ; text style; # (1.1) WRITING HAND
+270D FE0F ; emoji style; # (1.1) WRITING HAND
+270F FE0E ; text style; # (1.1) PENCIL
+270F FE0F ; emoji style; # (1.1) PENCIL
+2712 FE0E ; text style; # (1.1) BLACK NIB
+2712 FE0F ; emoji style; # (1.1) BLACK NIB
+2714 FE0E ; text style; # (1.1) HEAVY CHECK MARK
+2714 FE0F ; emoji style; # (1.1) HEAVY CHECK MARK
+2716 FE0E ; text style; # (1.1) HEAVY MULTIPLICATION X
+2716 FE0F ; emoji style; # (1.1) HEAVY MULTIPLICATION X
+271D FE0E ; text style; # (1.1) LATIN CROSS
+271D FE0F ; emoji style; # (1.1) LATIN CROSS
+2721 FE0E ; text style; # (1.1) STAR OF DAVID
+2721 FE0F ; emoji style; # (1.1) STAR OF DAVID
+2728 FE0E ; text style; # (6.0) SPARKLES
+2728 FE0F ; emoji style; # (6.0) SPARKLES
+2733 FE0E ; text style; # (1.1) EIGHT SPOKED ASTERISK
+2733 FE0F ; emoji style; # (1.1) EIGHT SPOKED ASTERISK
+2734 FE0E ; text style; # (1.1) EIGHT POINTED BLACK STAR
+2734 FE0F ; emoji style; # (1.1) EIGHT POINTED BLACK STAR
+2744 FE0E ; text style; # (1.1) SNOWFLAKE
+2744 FE0F ; emoji style; # (1.1) SNOWFLAKE
+2747 FE0E ; text style; # (1.1) SPARKLE
+2747 FE0F ; emoji style; # (1.1) SPARKLE
+274C FE0E ; text style; # (6.0) CROSS MARK
+274C FE0F ; emoji style; # (6.0) CROSS MARK
+274E FE0E ; text style; # (6.0) NEGATIVE SQUARED CROSS MARK
+274E FE0F ; emoji style; # (6.0) NEGATIVE SQUARED CROSS MARK
+2753 FE0E ; text style; # (6.0) BLACK QUESTION MARK ORNAMENT
+2753 FE0F ; emoji style; # (6.0) BLACK QUESTION MARK ORNAMENT
+2754 FE0E ; text style; # (6.0) WHITE QUESTION MARK ORNAMENT
+2754 FE0F ; emoji style; # (6.0) WHITE QUESTION MARK ORNAMENT
+2755 FE0E ; text style; # (6.0) WHITE EXCLAMATION MARK ORNAMENT
+2755 FE0F ; emoji style; # (6.0) WHITE EXCLAMATION MARK ORNAMENT
+2757 FE0E ; text style; # (5.2) HEAVY EXCLAMATION MARK SYMBOL
+2757 FE0F ; emoji style; # (5.2) HEAVY EXCLAMATION MARK SYMBOL
+2763 FE0E ; text style; # (1.1) HEAVY HEART EXCLAMATION MARK ORNAMENT
+2763 FE0F ; emoji style; # (1.1) HEAVY HEART EXCLAMATION MARK ORNAMENT
+2764 FE0E ; text style; # (1.1) HEAVY BLACK HEART
+2764 FE0F ; emoji style; # (1.1) HEAVY BLACK HEART
+2795 FE0E ; text style; # (6.0) HEAVY PLUS SIGN
+2795 FE0F ; emoji style; # (6.0) HEAVY PLUS SIGN
+2796 FE0E ; text style; # (6.0) HEAVY MINUS SIGN
+2796 FE0F ; emoji style; # (6.0) HEAVY MINUS SIGN
+2797 FE0E ; text style; # (6.0) HEAVY DIVISION SIGN
+2797 FE0F ; emoji style; # (6.0) HEAVY DIVISION SIGN
+27A1 FE0E ; text style; # (1.1) BLACK RIGHTWARDS ARROW
+27A1 FE0F ; emoji style; # (1.1) BLACK RIGHTWARDS ARROW
+27B0 FE0E ; text style; # (6.0) CURLY LOOP
+27B0 FE0F ; emoji style; # (6.0) CURLY LOOP
+27BF FE0E ; text style; # (6.0) DOUBLE CURLY LOOP
+27BF FE0F ; emoji style; # (6.0) DOUBLE CURLY LOOP
+2934 FE0E ; text style; # (3.2) ARROW POINTING RIGHTWARDS THEN CURVING UPWARDS
+2934 FE0F ; emoji style; # (3.2) ARROW POINTING RIGHTWARDS THEN CURVING UPWARDS
+2935 FE0E ; text style; # (3.2) ARROW POINTING RIGHTWARDS THEN CURVING DOWNWARDS
+2935 FE0F ; emoji style; # (3.2) ARROW POINTING RIGHTWARDS THEN CURVING DOWNWARDS
+2B05 FE0E ; text style; # (4.0) LEFTWARDS BLACK ARROW
+2B05 FE0F ; emoji style; # (4.0) LEFTWARDS BLACK ARROW
+2B06 FE0E ; text style; # (4.0) UPWARDS BLACK ARROW
+2B06 FE0F ; emoji style; # (4.0) UPWARDS BLACK ARROW
+2B07 FE0E ; text style; # (4.0) DOWNWARDS BLACK ARROW
+2B07 FE0F ; emoji style; # (4.0) DOWNWARDS BLACK ARROW
+2B1B FE0E ; text style; # (5.1) BLACK LARGE SQUARE
+2B1B FE0F ; emoji style; # (5.1) BLACK LARGE SQUARE
+2B1C FE0E ; text style; # (5.1) WHITE LARGE SQUARE
+2B1C FE0F ; emoji style; # (5.1) WHITE LARGE SQUARE
+2B50 FE0E ; text style; # (5.1) WHITE MEDIUM STAR
+2B50 FE0F ; emoji style; # (5.1) WHITE MEDIUM STAR
+2B55 FE0E ; text style; # (5.2) HEAVY LARGE CIRCLE
+2B55 FE0F ; emoji style; # (5.2) HEAVY LARGE CIRCLE
+3030 FE0E ; text style; # (1.1) WAVY DASH
+3030 FE0F ; emoji style; # (1.1) WAVY DASH
+303D FE0E ; text style; # (3.2) PART ALTERNATION MARK
+303D FE0F ; emoji style; # (3.2) PART ALTERNATION MARK
+3297 FE0E ; text style; # (1.1) CIRCLED IDEOGRAPH CONGRATULATION
+3297 FE0F ; emoji style; # (1.1) CIRCLED IDEOGRAPH CONGRATULATION
+3299 FE0E ; text style; # (1.1) CIRCLED IDEOGRAPH SECRET
+3299 FE0F ; emoji style; # (1.1) CIRCLED IDEOGRAPH SECRET
+1F004 FE0E ; text style; # (5.1) MAHJONG TILE RED DRAGON
+1F004 FE0F ; emoji style; # (5.1) MAHJONG TILE RED DRAGON
+1F170 FE0E ; text style; # (6.0) NEGATIVE SQUARED LATIN CAPITAL LETTER A
+1F170 FE0F ; emoji style; # (6.0) NEGATIVE SQUARED LATIN CAPITAL LETTER A
+1F171 FE0E ; text style; # (6.0) NEGATIVE SQUARED LATIN CAPITAL LETTER B
+1F171 FE0F ; emoji style; # (6.0) NEGATIVE SQUARED LATIN CAPITAL LETTER B
+1F17E FE0E ; text style; # (6.0) NEGATIVE SQUARED LATIN CAPITAL LETTER O
+1F17E FE0F ; emoji style; # (6.0) NEGATIVE SQUARED LATIN CAPITAL LETTER O
+1F17F FE0E ; text style; # (5.2) NEGATIVE SQUARED LATIN CAPITAL LETTER P
+1F17F FE0F ; emoji style; # (5.2) NEGATIVE SQUARED LATIN CAPITAL LETTER P
+1F202 FE0E ; text style; # (6.0) SQUARED KATAKANA SA
+1F202 FE0F ; emoji style; # (6.0) SQUARED KATAKANA SA
+1F21A FE0E ; text style; # (5.2) SQUARED CJK UNIFIED IDEOGRAPH-7121
+1F21A FE0F ; emoji style; # (5.2) SQUARED CJK UNIFIED IDEOGRAPH-7121
+1F22F FE0E ; text style; # (5.2) SQUARED CJK UNIFIED IDEOGRAPH-6307
+1F22F FE0F ; emoji style; # (5.2) SQUARED CJK UNIFIED IDEOGRAPH-6307
+1F237 FE0E ; text style; # (6.0) SQUARED CJK UNIFIED IDEOGRAPH-6708
+1F237 FE0F ; emoji style; # (6.0) SQUARED CJK UNIFIED IDEOGRAPH-6708
+1F30D FE0E ; text style; # (6.0) EARTH GLOBE EUROPE-AFRICA
+1F30D FE0F ; emoji style; # (6.0) EARTH GLOBE EUROPE-AFRICA
+1F30E FE0E ; text style; # (6.0) EARTH GLOBE AMERICAS
+1F30E FE0F ; emoji style; # (6.0) EARTH GLOBE AMERICAS
+1F30F FE0E ; text style; # (6.0) EARTH GLOBE ASIA-AUSTRALIA
+1F30F FE0F ; emoji style; # (6.0) EARTH GLOBE ASIA-AUSTRALIA
+1F315 FE0E ; text style; # (6.0) FULL MOON SYMBOL
+1F315 FE0F ; emoji style; # (6.0) FULL MOON SYMBOL
+1F31C FE0E ; text style; # (6.0) LAST QUARTER MOON WITH FACE
+1F31C FE0F ; emoji style; # (6.0) LAST QUARTER MOON WITH FACE
+1F321 FE0E ; text style; # (7.0) THERMOMETER
+1F321 FE0F ; emoji style; # (7.0) THERMOMETER
+1F324 FE0E ; text style; # (7.0) WHITE SUN WITH SMALL CLOUD
+1F324 FE0F ; emoji style; # (7.0) WHITE SUN WITH SMALL CLOUD
+1F325 FE0E ; text style; # (7.0) WHITE SUN BEHIND CLOUD
+1F325 FE0F ; emoji style; # (7.0) WHITE SUN BEHIND CLOUD
+1F326 FE0E ; text style; # (7.0) WHITE SUN BEHIND CLOUD WITH RAIN
+1F326 FE0F ; emoji style; # (7.0) WHITE SUN BEHIND CLOUD WITH RAIN
+1F327 FE0E ; text style; # (7.0) CLOUD WITH RAIN
+1F327 FE0F ; emoji style; # (7.0) CLOUD WITH RAIN
+1F328 FE0E ; text style; # (7.0) CLOUD WITH SNOW
+1F328 FE0F ; emoji style; # (7.0) CLOUD WITH SNOW
+1F329 FE0E ; text style; # (7.0) CLOUD WITH LIGHTNING
+1F329 FE0F ; emoji style; # (7.0) CLOUD WITH LIGHTNING
+1F32A FE0E ; text style; # (7.0) CLOUD WITH TORNADO
+1F32A FE0F ; emoji style; # (7.0) CLOUD WITH TORNADO
+1F32B FE0E ; text style; # (7.0) FOG
+1F32B FE0F ; emoji style; # (7.0) FOG
+1F32C FE0E ; text style; # (7.0) WIND BLOWING FACE
+1F32C FE0F ; emoji style; # (7.0) WIND BLOWING FACE
+1F336 FE0E ; text style; # (7.0) HOT PEPPER
+1F336 FE0F ; emoji style; # (7.0) HOT PEPPER
+1F378 FE0E ; text style; # (6.0) COCKTAIL GLASS
+1F378 FE0F ; emoji style; # (6.0) COCKTAIL GLASS
+1F37D FE0E ; text style; # (7.0) FORK AND KNIFE WITH PLATE
+1F37D FE0F ; emoji style; # (7.0) FORK AND KNIFE WITH PLATE
+1F393 FE0E ; text style; # (6.0) GRADUATION CAP
+1F393 FE0F ; emoji style; # (6.0) GRADUATION CAP
+1F396 FE0E ; text style; # (7.0) MILITARY MEDAL
+1F396 FE0F ; emoji style; # (7.0) MILITARY MEDAL
+1F397 FE0E ; text style; # (7.0) REMINDER RIBBON
+1F397 FE0F ; emoji style; # (7.0) REMINDER RIBBON
+1F399 FE0E ; text style; # (7.0) STUDIO MICROPHONE
+1F399 FE0F ; emoji style; # (7.0) STUDIO MICROPHONE
+1F39A FE0E ; text style; # (7.0) LEVEL SLIDER
+1F39A FE0F ; emoji style; # (7.0) LEVEL SLIDER
+1F39B FE0E ; text style; # (7.0) CONTROL KNOBS
+1F39B FE0F ; emoji style; # (7.0) CONTROL KNOBS
+1F39E FE0E ; text style; # (7.0) FILM FRAMES
+1F39E FE0F ; emoji style; # (7.0) FILM FRAMES
+1F39F FE0E ; text style; # (7.0) ADMISSION TICKETS
+1F39F FE0F ; emoji style; # (7.0) ADMISSION TICKETS
+1F3A7 FE0E ; text style; # (6.0) HEADPHONE
+1F3A7 FE0F ; emoji style; # (6.0) HEADPHONE
+1F3AC FE0E ; text style; # (6.0) CLAPPER BOARD
+1F3AC FE0F ; emoji style; # (6.0) CLAPPER BOARD
+1F3AD FE0E ; text style; # (6.0) PERFORMING ARTS
+1F3AD FE0F ; emoji style; # (6.0) PERFORMING ARTS
+1F3AE FE0E ; text style; # (6.0) VIDEO GAME
+1F3AE FE0F ; emoji style; # (6.0) VIDEO GAME
+1F3C2 FE0E ; text style; # (6.0) SNOWBOARDER
+1F3C2 FE0F ; emoji style; # (6.0) SNOWBOARDER
+1F3C4 FE0E ; text style; # (6.0) SURFER
+1F3C4 FE0F ; emoji style; # (6.0) SURFER
+1F3C6 FE0E ; text style; # (6.0) TROPHY
+1F3C6 FE0F ; emoji style; # (6.0) TROPHY
+1F3CA FE0E ; text style; # (6.0) SWIMMER
+1F3CA FE0F ; emoji style; # (6.0) SWIMMER
+1F3CB FE0E ; text style; # (7.0) WEIGHT LIFTER
+1F3CB FE0F ; emoji style; # (7.0) WEIGHT LIFTER
+1F3CC FE0E ; text style; # (7.0) GOLFER
+1F3CC FE0F ; emoji style; # (7.0) GOLFER
+1F3CD FE0E ; text style; # (7.0) RACING MOTORCYCLE
+1F3CD FE0F ; emoji style; # (7.0) RACING MOTORCYCLE
+1F3CE FE0E ; text style; # (7.0) RACING CAR
+1F3CE FE0F ; emoji style; # (7.0) RACING CAR
+1F3D4 FE0E ; text style; # (7.0) SNOW CAPPED MOUNTAIN
+1F3D4 FE0F ; emoji style; # (7.0) SNOW CAPPED MOUNTAIN
+1F3D5 FE0E ; text style; # (7.0) CAMPING
+1F3D5 FE0F ; emoji style; # (7.0) CAMPING
+1F3D6 FE0E ; text style; # (7.0) BEACH WITH UMBRELLA
+1F3D6 FE0F ; emoji style; # (7.0) BEACH WITH UMBRELLA
+1F3D7 FE0E ; text style; # (7.0) BUILDING CONSTRUCTION
+1F3D7 FE0F ; emoji style; # (7.0) BUILDING CONSTRUCTION
+1F3D8 FE0E ; text style; # (7.0) HOUSE BUILDINGS
+1F3D8 FE0F ; emoji style; # (7.0) HOUSE BUILDINGS
+1F3D9 FE0E ; text style; # (7.0) CITYSCAPE
+1F3D9 FE0F ; emoji style; # (7.0) CITYSCAPE
+1F3DA FE0E ; text style; # (7.0) DERELICT HOUSE BUILDING
+1F3DA FE0F ; emoji style; # (7.0) DERELICT HOUSE BUILDING
+1F3DB FE0E ; text style; # (7.0) CLASSICAL BUILDING
+1F3DB FE0F ; emoji style; # (7.0) CLASSICAL BUILDING
+1F3DC FE0E ; text style; # (7.0) DESERT
+1F3DC FE0F ; emoji style; # (7.0) DESERT
+1F3DD FE0E ; text style; # (7.0) DESERT ISLAND
+1F3DD FE0F ; emoji style; # (7.0) DESERT ISLAND
+1F3DE FE0E ; text style; # (7.0) NATIONAL PARK
+1F3DE FE0F ; emoji style; # (7.0) NATIONAL PARK
+1F3DF FE0E ; text style; # (7.0) STADIUM
+1F3DF FE0F ; emoji style; # (7.0) STADIUM
+1F3E0 FE0E ; text style; # (6.0) HOUSE BUILDING
+1F3E0 FE0F ; emoji style; # (6.0) HOUSE BUILDING
+1F3ED FE0E ; text style; # (6.0) FACTORY
+1F3ED FE0F ; emoji style; # (6.0) FACTORY
+1F3F3 FE0E ; text style; # (7.0) WAVING WHITE FLAG
+1F3F3 FE0F ; emoji style; # (7.0) WAVING WHITE FLAG
+1F3F5 FE0E ; text style; # (7.0) ROSETTE
+1F3F5 FE0F ; emoji style; # (7.0) ROSETTE
+1F3F7 FE0E ; text style; # (7.0) LABEL
+1F3F7 FE0F ; emoji style; # (7.0) LABEL
+1F408 FE0E ; text style; # (6.0) CAT
+1F408 FE0F ; emoji style; # (6.0) CAT
+1F415 FE0E ; text style; # (6.0) DOG
+1F415 FE0F ; emoji style; # (6.0) DOG
+1F41F FE0E ; text style; # (6.0) FISH
+1F41F FE0F ; emoji style; # (6.0) FISH
+1F426 FE0E ; text style; # (6.0) BIRD
+1F426 FE0F ; emoji style; # (6.0) BIRD
+1F43F FE0E ; text style; # (7.0) CHIPMUNK
+1F43F FE0F ; emoji style; # (7.0) CHIPMUNK
+1F441 FE0E ; text style; # (7.0) EYE
+1F441 FE0F ; emoji style; # (7.0) EYE
+1F442 FE0E ; text style; # (6.0) EAR
+1F442 FE0F ; emoji style; # (6.0) EAR
+1F446 FE0E ; text style; # (6.0) WHITE UP POINTING BACKHAND INDEX
+1F446 FE0F ; emoji style; # (6.0) WHITE UP POINTING BACKHAND INDEX
+1F447 FE0E ; text style; # (6.0) WHITE DOWN POINTING BACKHAND INDEX
+1F447 FE0F ; emoji style; # (6.0) WHITE DOWN POINTING BACKHAND INDEX
+1F448 FE0E ; text style; # (6.0) WHITE LEFT POINTING BACKHAND INDEX
+1F448 FE0F ; emoji style; # (6.0) WHITE LEFT POINTING BACKHAND INDEX
+1F449 FE0E ; text style; # (6.0) WHITE RIGHT POINTING BACKHAND INDEX
+1F449 FE0F ; emoji style; # (6.0) WHITE RIGHT POINTING BACKHAND INDEX
+1F44D FE0E ; text style; # (6.0) THUMBS UP SIGN
+1F44D FE0F ; emoji style; # (6.0) THUMBS UP SIGN
+1F44E FE0E ; text style; # (6.0) THUMBS DOWN SIGN
+1F44E FE0F ; emoji style; # (6.0) THUMBS DOWN SIGN
+1F453 FE0E ; text style; # (6.0) EYEGLASSES
+1F453 FE0F ; emoji style; # (6.0) EYEGLASSES
+1F46A FE0E ; text style; # (6.0) FAMILY
+1F46A FE0F ; emoji style; # (6.0) FAMILY
+1F47D FE0E ; text style; # (6.0) EXTRATERRESTRIAL ALIEN
+1F47D FE0F ; emoji style; # (6.0) EXTRATERRESTRIAL ALIEN
+1F4A3 FE0E ; text style; # (6.0) BOMB
+1F4A3 FE0F ; emoji style; # (6.0) BOMB
+1F4B0 FE0E ; text style; # (6.0) MONEY BAG
+1F4B0 FE0F ; emoji style; # (6.0) MONEY BAG
+1F4B3 FE0E ; text style; # (6.0) CREDIT CARD
+1F4B3 FE0F ; emoji style; # (6.0) CREDIT CARD
+1F4BB FE0E ; text style; # (6.0) PERSONAL COMPUTER
+1F4BB FE0F ; emoji style; # (6.0) PERSONAL COMPUTER
+1F4BF FE0E ; text style; # (6.0) OPTICAL DISC
+1F4BF FE0F ; emoji style; # (6.0) OPTICAL DISC
+1F4CB FE0E ; text style; # (6.0) CLIPBOARD
+1F4CB FE0F ; emoji style; # (6.0) CLIPBOARD
+1F4DA FE0E ; text style; # (6.0) BOOKS
+1F4DA FE0F ; emoji style; # (6.0) BOOKS
+1F4DF FE0E ; text style; # (6.0) PAGER
+1F4DF FE0F ; emoji style; # (6.0) PAGER
+1F4E4 FE0E ; text style; # (6.0) OUTBOX TRAY
+1F4E4 FE0F ; emoji style; # (6.0) OUTBOX TRAY
+1F4E5 FE0E ; text style; # (6.0) INBOX TRAY
+1F4E5 FE0F ; emoji style; # (6.0) INBOX TRAY
+1F4E6 FE0E ; text style; # (6.0) PACKAGE
+1F4E6 FE0F ; emoji style; # (6.0) PACKAGE
+1F4EA FE0E ; text style; # (6.0) CLOSED MAILBOX WITH LOWERED FLAG
+1F4EA FE0F ; emoji style; # (6.0) CLOSED MAILBOX WITH LOWERED FLAG
+1F4EB FE0E ; text style; # (6.0) CLOSED MAILBOX WITH RAISED FLAG
+1F4EB FE0F ; emoji style; # (6.0) CLOSED MAILBOX WITH RAISED FLAG
+1F4EC FE0E ; text style; # (6.0) OPEN MAILBOX WITH RAISED FLAG
+1F4EC FE0F ; emoji style; # (6.0) OPEN MAILBOX WITH RAISED FLAG
+1F4ED FE0E ; text style; # (6.0) OPEN MAILBOX WITH LOWERED FLAG
+1F4ED FE0F ; emoji style; # (6.0) OPEN MAILBOX WITH LOWERED FLAG
+1F4F7 FE0E ; text style; # (6.0) CAMERA
+1F4F7 FE0F ; emoji style; # (6.0) CAMERA
+1F4F9 FE0E ; text style; # (6.0) VIDEO CAMERA
+1F4F9 FE0F ; emoji style; # (6.0) VIDEO CAMERA
+1F4FA FE0E ; text style; # (6.0) TELEVISION
+1F4FA FE0F ; emoji style; # (6.0) TELEVISION
+1F4FB FE0E ; text style; # (6.0) RADIO
+1F4FB FE0F ; emoji style; # (6.0) RADIO
+1F4FD FE0E ; text style; # (7.0) FILM PROJECTOR
+1F4FD FE0F ; emoji style; # (7.0) FILM PROJECTOR
+1F508 FE0E ; text style; # (6.0) SPEAKER
+1F508 FE0F ; emoji style; # (6.0) SPEAKER
+1F50D FE0E ; text style; # (6.0) LEFT-POINTING MAGNIFYING GLASS
+1F50D FE0F ; emoji style; # (6.0) LEFT-POINTING MAGNIFYING GLASS
+1F512 FE0E ; text style; # (6.0) LOCK
+1F512 FE0F ; emoji style; # (6.0) LOCK
+1F513 FE0E ; text style; # (6.0) OPEN LOCK
+1F513 FE0F ; emoji style; # (6.0) OPEN LOCK
+1F549 FE0E ; text style; # (7.0) OM SYMBOL
+1F549 FE0F ; emoji style; # (7.0) OM SYMBOL
+1F54A FE0E ; text style; # (7.0) DOVE OF PEACE
+1F54A FE0F ; emoji style; # (7.0) DOVE OF PEACE
+1F550 FE0E ; text style; # (6.0) CLOCK FACE ONE OCLOCK
+1F550 FE0F ; emoji style; # (6.0) CLOCK FACE ONE OCLOCK
+1F551 FE0E ; text style; # (6.0) CLOCK FACE TWO OCLOCK
+1F551 FE0F ; emoji style; # (6.0) CLOCK FACE TWO OCLOCK
+1F552 FE0E ; text style; # (6.0) CLOCK FACE THREE OCLOCK
+1F552 FE0F ; emoji style; # (6.0) CLOCK FACE THREE OCLOCK
+1F553 FE0E ; text style; # (6.0) CLOCK FACE FOUR OCLOCK
+1F553 FE0F ; emoji style; # (6.0) CLOCK FACE FOUR OCLOCK
+1F554 FE0E ; text style; # (6.0) CLOCK FACE FIVE OCLOCK
+1F554 FE0F ; emoji style; # (6.0) CLOCK FACE FIVE OCLOCK
+1F555 FE0E ; text style; # (6.0) CLOCK FACE SIX OCLOCK
+1F555 FE0F ; emoji style; # (6.0) CLOCK FACE SIX OCLOCK
+1F556 FE0E ; text style; # (6.0) CLOCK FACE SEVEN OCLOCK
+1F556 FE0F ; emoji style; # (6.0) CLOCK FACE SEVEN OCLOCK
+1F557 FE0E ; text style; # (6.0) CLOCK FACE EIGHT OCLOCK
+1F557 FE0F ; emoji style; # (6.0) CLOCK FACE EIGHT OCLOCK
+1F558 FE0E ; text style; # (6.0) CLOCK FACE NINE OCLOCK
+1F558 FE0F ; emoji style; # (6.0) CLOCK FACE NINE OCLOCK
+1F559 FE0E ; text style; # (6.0) CLOCK FACE TEN OCLOCK
+1F559 FE0F ; emoji style; # (6.0) CLOCK FACE TEN OCLOCK
+1F55A FE0E ; text style; # (6.0) CLOCK FACE ELEVEN OCLOCK
+1F55A FE0F ; emoji style; # (6.0) CLOCK FACE ELEVEN OCLOCK
+1F55B FE0E ; text style; # (6.0) CLOCK FACE TWELVE OCLOCK
+1F55B FE0F ; emoji style; # (6.0) CLOCK FACE TWELVE OCLOCK
+1F55C FE0E ; text style; # (6.0) CLOCK FACE ONE-THIRTY
+1F55C FE0F ; emoji style; # (6.0) CLOCK FACE ONE-THIRTY
+1F55D FE0E ; text style; # (6.0) CLOCK FACE TWO-THIRTY
+1F55D FE0F ; emoji style; # (6.0) CLOCK FACE TWO-THIRTY
+1F55E FE0E ; text style; # (6.0) CLOCK FACE THREE-THIRTY
+1F55E FE0F ; emoji style; # (6.0) CLOCK FACE THREE-THIRTY
+1F55F FE0E ; text style; # (6.0) CLOCK FACE FOUR-THIRTY
+1F55F FE0F ; emoji style; # (6.0) CLOCK FACE FOUR-THIRTY
+1F560 FE0E ; text style; # (6.0) CLOCK FACE FIVE-THIRTY
+1F560 FE0F ; emoji style; # (6.0) CLOCK FACE FIVE-THIRTY
+1F561 FE0E ; text style; # (6.0) CLOCK FACE SIX-THIRTY
+1F561 FE0F ; emoji style; # (6.0) CLOCK FACE SIX-THIRTY
+1F562 FE0E ; text style; # (6.0) CLOCK FACE SEVEN-THIRTY
+1F562 FE0F ; emoji style; # (6.0) CLOCK FACE SEVEN-THIRTY
+1F563 FE0E ; text style; # (6.0) CLOCK FACE EIGHT-THIRTY
+1F563 FE0F ; emoji style; # (6.0) CLOCK FACE EIGHT-THIRTY
+1F564 FE0E ; text style; # (6.0) CLOCK FACE NINE-THIRTY
+1F564 FE0F ; emoji style; # (6.0) CLOCK FACE NINE-THIRTY
+1F565 FE0E ; text style; # (6.0) CLOCK FACE TEN-THIRTY
+1F565 FE0F ; emoji style; # (6.0) CLOCK FACE TEN-THIRTY
+1F566 FE0E ; text style; # (6.0) CLOCK FACE ELEVEN-THIRTY
+1F566 FE0F ; emoji style; # (6.0) CLOCK FACE ELEVEN-THIRTY
+1F567 FE0E ; text style; # (6.0) CLOCK FACE TWELVE-THIRTY
+1F567 FE0F ; emoji style; # (6.0) CLOCK FACE TWELVE-THIRTY
+1F56F FE0E ; text style; # (7.0) CANDLE
+1F56F FE0F ; emoji style; # (7.0) CANDLE
+1F570 FE0E ; text style; # (7.0) MANTELPIECE CLOCK
+1F570 FE0F ; emoji style; # (7.0) MANTELPIECE CLOCK
+1F573 FE0E ; text style; # (7.0) HOLE
+1F573 FE0F ; emoji style; # (7.0) HOLE
+1F574 FE0E ; text style; # (7.0) MAN IN BUSINESS SUIT LEVITATING
+1F574 FE0F ; emoji style; # (7.0) MAN IN BUSINESS SUIT LEVITATING
+1F575 FE0E ; text style; # (7.0) SLEUTH OR SPY
+1F575 FE0F ; emoji style; # (7.0) SLEUTH OR SPY
+1F576 FE0E ; text style; # (7.0) DARK SUNGLASSES
+1F576 FE0F ; emoji style; # (7.0) DARK SUNGLASSES
+1F577 FE0E ; text style; # (7.0) SPIDER
+1F577 FE0F ; emoji style; # (7.0) SPIDER
+1F578 FE0E ; text style; # (7.0) SPIDER WEB
+1F578 FE0F ; emoji style; # (7.0) SPIDER WEB
+1F579 FE0E ; text style; # (7.0) JOYSTICK
+1F579 FE0F ; emoji style; # (7.0) JOYSTICK
+1F587 FE0E ; text style; # (7.0) LINKED PAPERCLIPS
+1F587 FE0F ; emoji style; # (7.0) LINKED PAPERCLIPS
+1F58A FE0E ; text style; # (7.0) LOWER LEFT BALLPOINT PEN
+1F58A FE0F ; emoji style; # (7.0) LOWER LEFT BALLPOINT PEN
+1F58B FE0E ; text style; # (7.0) LOWER LEFT FOUNTAIN PEN
+1F58B FE0F ; emoji style; # (7.0) LOWER LEFT FOUNTAIN PEN
+1F58C FE0E ; text style; # (7.0) LOWER LEFT PAINTBRUSH
+1F58C FE0F ; emoji style; # (7.0) LOWER LEFT PAINTBRUSH
+1F58D FE0E ; text style; # (7.0) LOWER LEFT CRAYON
+1F58D FE0F ; emoji style; # (7.0) LOWER LEFT CRAYON
+1F590 FE0E ; text style; # (7.0) RAISED HAND WITH FINGERS SPLAYED
+1F590 FE0F ; emoji style; # (7.0) RAISED HAND WITH FINGERS SPLAYED
+1F5A5 FE0E ; text style; # (7.0) DESKTOP COMPUTER
+1F5A5 FE0F ; emoji style; # (7.0) DESKTOP COMPUTER
+1F5A8 FE0E ; text style; # (7.0) PRINTER
+1F5A8 FE0F ; emoji style; # (7.0) PRINTER
+1F5B1 FE0E ; text style; # (7.0) THREE BUTTON MOUSE
+1F5B1 FE0F ; emoji style; # (7.0) THREE BUTTON MOUSE
+1F5B2 FE0E ; text style; # (7.0) TRACKBALL
+1F5B2 FE0F ; emoji style; # (7.0) TRACKBALL
+1F5BC FE0E ; text style; # (7.0) FRAME WITH PICTURE
+1F5BC FE0F ; emoji style; # (7.0) FRAME WITH PICTURE
+1F5C2 FE0E ; text style; # (7.0) CARD INDEX DIVIDERS
+1F5C2 FE0F ; emoji style; # (7.0) CARD INDEX DIVIDERS
+1F5C3 FE0E ; text style; # (7.0) CARD FILE BOX
+1F5C3 FE0F ; emoji style; # (7.0) CARD FILE BOX
+1F5C4 FE0E ; text style; # (7.0) FILE CABINET
+1F5C4 FE0F ; emoji style; # (7.0) FILE CABINET
+1F5D1 FE0E ; text style; # (7.0) WASTEBASKET
+1F5D1 FE0F ; emoji style; # (7.0) WASTEBASKET
+1F5D2 FE0E ; text style; # (7.0) SPIRAL NOTE PAD
+1F5D2 FE0F ; emoji style; # (7.0) SPIRAL NOTE PAD
+1F5D3 FE0E ; text style; # (7.0) SPIRAL CALENDAR PAD
+1F5D3 FE0F ; emoji style; # (7.0) SPIRAL CALENDAR PAD
+1F5DC FE0E ; text style; # (7.0) COMPRESSION
+1F5DC FE0F ; emoji style; # (7.0) COMPRESSION
+1F5DD FE0E ; text style; # (7.0) OLD KEY
+1F5DD FE0F ; emoji style; # (7.0) OLD KEY
+1F5DE FE0E ; text style; # (7.0) ROLLED-UP NEWSPAPER
+1F5DE FE0F ; emoji style; # (7.0) ROLLED-UP NEWSPAPER
+1F5E1 FE0E ; text style; # (7.0) DAGGER KNIFE
+1F5E1 FE0F ; emoji style; # (7.0) DAGGER KNIFE
+1F5E3 FE0E ; text style; # (7.0) SPEAKING HEAD IN SILHOUETTE
+1F5E3 FE0F ; emoji style; # (7.0) SPEAKING HEAD IN SILHOUETTE
+1F5E8 FE0E ; text style; # (7.0) LEFT SPEECH BUBBLE
+1F5E8 FE0F ; emoji style; # (7.0) LEFT SPEECH BUBBLE
+1F5EF FE0E ; text style; # (7.0) RIGHT ANGER BUBBLE
+1F5EF FE0F ; emoji style; # (7.0) RIGHT ANGER BUBBLE
+1F5F3 FE0E ; text style; # (7.0) BALLOT BOX WITH BALLOT
+1F5F3 FE0F ; emoji style; # (7.0) BALLOT BOX WITH BALLOT
+1F5FA FE0E ; text style; # (7.0) WORLD MAP
+1F5FA FE0F ; emoji style; # (7.0) WORLD MAP
+1F610 FE0E ; text style; # (6.0) NEUTRAL FACE
+1F610 FE0F ; emoji style; # (6.0) NEUTRAL FACE
+1F687 FE0E ; text style; # (6.0) METRO
+1F687 FE0F ; emoji style; # (6.0) METRO
+1F68D FE0E ; text style; # (6.0) ONCOMING BUS
+1F68D FE0F ; emoji style; # (6.0) ONCOMING BUS
+1F691 FE0E ; text style; # (6.0) AMBULANCE
+1F691 FE0F ; emoji style; # (6.0) AMBULANCE
+1F694 FE0E ; text style; # (6.0) ONCOMING POLICE CAR
+1F694 FE0F ; emoji style; # (6.0) ONCOMING POLICE CAR
+1F698 FE0E ; text style; # (6.0) ONCOMING AUTOMOBILE
+1F698 FE0F ; emoji style; # (6.0) ONCOMING AUTOMOBILE
+1F6AD FE0E ; text style; # (6.0) NO SMOKING SYMBOL
+1F6AD FE0F ; emoji style; # (6.0) NO SMOKING SYMBOL
+1F6B2 FE0E ; text style; # (6.0) BICYCLE
+1F6B2 FE0F ; emoji style; # (6.0) BICYCLE
+1F6B9 FE0E ; text style; # (6.0) MENS SYMBOL
+1F6B9 FE0F ; emoji style; # (6.0) MENS SYMBOL
+1F6BA FE0E ; text style; # (6.0) WOMENS SYMBOL
+1F6BA FE0F ; emoji style; # (6.0) WOMENS SYMBOL
+1F6BC FE0E ; text style; # (6.0) BABY SYMBOL
+1F6BC FE0F ; emoji style; # (6.0) BABY SYMBOL
+1F6CB FE0E ; text style; # (7.0) COUCH AND LAMP
+1F6CB FE0F ; emoji style; # (7.0) COUCH AND LAMP
+1F6CD FE0E ; text style; # (7.0) SHOPPING BAGS
+1F6CD FE0F ; emoji style; # (7.0) SHOPPING BAGS
+1F6CE FE0E ; text style; # (7.0) BELLHOP BELL
+1F6CE FE0F ; emoji style; # (7.0) BELLHOP BELL
+1F6CF FE0E ; text style; # (7.0) BED
+1F6CF FE0F ; emoji style; # (7.0) BED
+1F6E0 FE0E ; text style; # (7.0) HAMMER AND WRENCH
+1F6E0 FE0F ; emoji style; # (7.0) HAMMER AND WRENCH
+1F6E1 FE0E ; text style; # (7.0) SHIELD
+1F6E1 FE0F ; emoji style; # (7.0) SHIELD
+1F6E2 FE0E ; text style; # (7.0) OIL DRUM
+1F6E2 FE0F ; emoji style; # (7.0) OIL DRUM
+1F6E3 FE0E ; text style; # (7.0) MOTORWAY
+1F6E3 FE0F ; emoji style; # (7.0) MOTORWAY
+1F6E4 FE0E ; text style; # (7.0) RAILWAY TRACK
+1F6E4 FE0F ; emoji style; # (7.0) RAILWAY TRACK
+1F6E5 FE0E ; text style; # (7.0) MOTOR BOAT
+1F6E5 FE0F ; emoji style; # (7.0) MOTOR BOAT
+1F6E9 FE0E ; text style; # (7.0) SMALL AIRPLANE
+1F6E9 FE0F ; emoji style; # (7.0) SMALL AIRPLANE
+1F6F0 FE0E ; text style; # (7.0) SATELLITE
+1F6F0 FE0F ; emoji style; # (7.0) SATELLITE
+1F6F3 FE0E ; text style; # (7.0) PASSENGER SHIP
+1F6F3 FE0F ; emoji style; # (7.0) PASSENGER SHIP
-#Total sequences: 354
+#Total sequences: 371
#EOF
diff --git a/admin/unidata/emoji-zwj-sequences.txt b/admin/unidata/emoji-zwj-sequences.txt
index 4125bec62e2..25f8b6154b5 100644
--- a/admin/unidata/emoji-zwj-sequences.txt
+++ b/admin/unidata/emoji-zwj-sequences.txt
@@ -1,11 +1,11 @@
# emoji-zwj-sequences.txt
-# Date: 2022-05-06, 16:14:52 GMT
-# © 2022 Unicode®, Inc.
+# Date: 2023-06-05, 20:04:50 GMT
+# © 2023 Unicode®, Inc.
# Unicode and the Unicode Logo are registered trademarks of Unicode, Inc. in the U.S. and other countries.
# For terms of use, see https://www.unicode.org/terms_of_use.html
#
# Emoji ZWJ Sequences for UTS #51
-# Version: 15.0
+# Version: 15.1
#
# For documentation and usage, see https://www.unicode.org/reports/tr51
#
@@ -269,6 +269,10 @@
1F469 1F3FF 200D 1F91D 200D 1F469 1F3FD ; RGI_Emoji_ZWJ_Sequence ; women holding hands: dark skin tone, medium skin tone # E12.0 [1] (👩🏿‍🤝‍👩🏽)
1F469 1F3FF 200D 1F91D 200D 1F469 1F3FE ; RGI_Emoji_ZWJ_Sequence ; women holding hands: dark skin tone, medium-dark skin tone # E12.0 [1] (👩🏿‍🤝‍👩🏾)
1F9D1 200D 1F91D 200D 1F9D1 ; RGI_Emoji_ZWJ_Sequence ; people holding hands # E12.0 [1] (🧑‍🤝‍🧑)
+1F9D1 200D 1F9D1 200D 1F9D2 ; RGI_Emoji_ZWJ_Sequence ; family: adult, adult, child # E15.1 [1] (🧑‍🧑‍🧒)
+1F9D1 200D 1F9D1 200D 1F9D2 200D 1F9D2 ; RGI_Emoji_ZWJ_Sequence ; family: adult, adult, child, child # E15.1 [1] (🧑‍🧑‍🧒‍🧒)
+1F9D1 200D 1F9D2 ; RGI_Emoji_ZWJ_Sequence ; family: adult, child # E15.1 [1] (🧑‍🧒)
+1F9D1 200D 1F9D2 200D 1F9D2 ; RGI_Emoji_ZWJ_Sequence ; family: adult, child, child # E15.1 [1] (🧑‍🧒‍🧒)
1F9D1 1F3FB 200D 2764 FE0F 200D 1F48B 200D 1F9D1 1F3FC; RGI_Emoji_ZWJ_Sequence; kiss: person, person, light skin tone, medium-light skin tone #E13.1[1] (🧑🏻‍❤️‍💋‍🧑🏼)
1F9D1 1F3FB 200D 2764 FE0F 200D 1F48B 200D 1F9D1 1F3FD; RGI_Emoji_ZWJ_Sequence; kiss: person, person, light skin tone, medium skin tone #E13.1 [1] (🧑🏻‍❤️‍💋‍🧑🏽)
1F9D1 1F3FB 200D 2764 FE0F 200D 1F48B 200D 1F9D1 1F3FE; RGI_Emoji_ZWJ_Sequence; kiss: person, person, light skin tone, medium-dark skin tone #E13.1[1] (🧑🏻‍❤️‍💋‍🧑🏾)
@@ -277,7 +281,6 @@
1F9D1 1F3FB 200D 2764 FE0F 200D 1F9D1 1F3FD ; RGI_Emoji_ZWJ_Sequence ; couple with heart: person, person, light skin tone, medium skin tone #E13.1[1] (🧑🏻‍❤️‍🧑🏽)
1F9D1 1F3FB 200D 2764 FE0F 200D 1F9D1 1F3FE ; RGI_Emoji_ZWJ_Sequence ; couple with heart: person, person, light skin tone, medium-dark skin tone #E13.1[1] (🧑🏻‍❤️‍🧑🏾)
1F9D1 1F3FB 200D 2764 FE0F 200D 1F9D1 1F3FF ; RGI_Emoji_ZWJ_Sequence ; couple with heart: person, person, light skin tone, dark skin tone #E13.1[1] (🧑🏻‍❤️‍🧑🏿)
-1F9D1 1F3FB 200D 1F384 ; RGI_Emoji_ZWJ_Sequence ; mx claus: light skin tone # E13.0 [1] (🧑🏻‍🎄)
1F9D1 1F3FB 200D 1F91D 200D 1F9D1 1F3FB ; RGI_Emoji_ZWJ_Sequence ; people holding hands: light skin tone # E12.0 [1] (🧑🏻‍🤝‍🧑🏻)
1F9D1 1F3FB 200D 1F91D 200D 1F9D1 1F3FC ; RGI_Emoji_ZWJ_Sequence ; people holding hands: light skin tone, medium-light skin tone # E12.1 [1] (🧑🏻‍🤝‍🧑🏼)
1F9D1 1F3FB 200D 1F91D 200D 1F9D1 1F3FD ; RGI_Emoji_ZWJ_Sequence ; people holding hands: light skin tone, medium skin tone # E12.1 [1] (🧑🏻‍🤝‍🧑🏽)
@@ -291,7 +294,6 @@
1F9D1 1F3FC 200D 2764 FE0F 200D 1F9D1 1F3FD ; RGI_Emoji_ZWJ_Sequence ; couple with heart: person, person, medium-light skin tone, medium skin tone #E13.1[1] (🧑🏼‍❤️‍🧑🏽)
1F9D1 1F3FC 200D 2764 FE0F 200D 1F9D1 1F3FE ; RGI_Emoji_ZWJ_Sequence ; couple with heart: person, person, medium-light skin tone, medium-dark skin tone #E13.1[1] (🧑🏼‍❤️‍🧑🏾)
1F9D1 1F3FC 200D 2764 FE0F 200D 1F9D1 1F3FF ; RGI_Emoji_ZWJ_Sequence ; couple with heart: person, person, medium-light skin tone, dark skin tone #E13.1[1] (🧑🏼‍❤️‍🧑🏿)
-1F9D1 1F3FC 200D 1F384 ; RGI_Emoji_ZWJ_Sequence ; mx claus: medium-light skin tone # E13.0 [1] (🧑🏼‍🎄)
1F9D1 1F3FC 200D 1F91D 200D 1F9D1 1F3FB ; RGI_Emoji_ZWJ_Sequence ; people holding hands: medium-light skin tone, light skin tone # E12.0 [1] (🧑🏼‍🤝‍🧑🏻)
1F9D1 1F3FC 200D 1F91D 200D 1F9D1 1F3FC ; RGI_Emoji_ZWJ_Sequence ; people holding hands: medium-light skin tone # E12.0 [1] (🧑🏼‍🤝‍🧑🏼)
1F9D1 1F3FC 200D 1F91D 200D 1F9D1 1F3FD ; RGI_Emoji_ZWJ_Sequence ; people holding hands: medium-light skin tone, medium skin tone # E12.1 [1] (🧑🏼‍🤝‍🧑🏽)
@@ -305,7 +307,6 @@
1F9D1 1F3FD 200D 2764 FE0F 200D 1F9D1 1F3FC ; RGI_Emoji_ZWJ_Sequence ; couple with heart: person, person, medium skin tone, medium-light skin tone #E13.1[1] (🧑🏽‍❤️‍🧑🏼)
1F9D1 1F3FD 200D 2764 FE0F 200D 1F9D1 1F3FE ; RGI_Emoji_ZWJ_Sequence ; couple with heart: person, person, medium skin tone, medium-dark skin tone #E13.1[1] (🧑🏽‍❤️‍🧑🏾)
1F9D1 1F3FD 200D 2764 FE0F 200D 1F9D1 1F3FF ; RGI_Emoji_ZWJ_Sequence ; couple with heart: person, person, medium skin tone, dark skin tone #E13.1[1] (🧑🏽‍❤️‍🧑🏿)
-1F9D1 1F3FD 200D 1F384 ; RGI_Emoji_ZWJ_Sequence ; mx claus: medium skin tone # E13.0 [1] (🧑🏽‍🎄)
1F9D1 1F3FD 200D 1F91D 200D 1F9D1 1F3FB ; RGI_Emoji_ZWJ_Sequence ; people holding hands: medium skin tone, light skin tone # E12.0 [1] (🧑🏽‍🤝‍🧑🏻)
1F9D1 1F3FD 200D 1F91D 200D 1F9D1 1F3FC ; RGI_Emoji_ZWJ_Sequence ; people holding hands: medium skin tone, medium-light skin tone # E12.0 [1] (🧑🏽‍🤝‍🧑🏼)
1F9D1 1F3FD 200D 1F91D 200D 1F9D1 1F3FD ; RGI_Emoji_ZWJ_Sequence ; people holding hands: medium skin tone # E12.0 [1] (🧑🏽‍🤝‍🧑🏽)
@@ -319,7 +320,6 @@
1F9D1 1F3FE 200D 2764 FE0F 200D 1F9D1 1F3FC ; RGI_Emoji_ZWJ_Sequence ; couple with heart: person, person, medium-dark skin tone, medium-light skin tone #E13.1[1] (🧑🏾‍❤️‍🧑🏼)
1F9D1 1F3FE 200D 2764 FE0F 200D 1F9D1 1F3FD ; RGI_Emoji_ZWJ_Sequence ; couple with heart: person, person, medium-dark skin tone, medium skin tone #E13.1[1] (🧑🏾‍❤️‍🧑🏽)
1F9D1 1F3FE 200D 2764 FE0F 200D 1F9D1 1F3FF ; RGI_Emoji_ZWJ_Sequence ; couple with heart: person, person, medium-dark skin tone, dark skin tone #E13.1[1] (🧑🏾‍❤️‍🧑🏿)
-1F9D1 1F3FE 200D 1F384 ; RGI_Emoji_ZWJ_Sequence ; mx claus: medium-dark skin tone # E13.0 [1] (🧑🏾‍🎄)
1F9D1 1F3FE 200D 1F91D 200D 1F9D1 1F3FB ; RGI_Emoji_ZWJ_Sequence ; people holding hands: medium-dark skin tone, light skin tone # E12.0 [1] (🧑🏾‍🤝‍🧑🏻)
1F9D1 1F3FE 200D 1F91D 200D 1F9D1 1F3FC ; RGI_Emoji_ZWJ_Sequence ; people holding hands: medium-dark skin tone, medium-light skin tone #E12.0[1] (🧑🏾‍🤝‍🧑🏼)
1F9D1 1F3FE 200D 1F91D 200D 1F9D1 1F3FD ; RGI_Emoji_ZWJ_Sequence ; people holding hands: medium-dark skin tone, medium skin tone # E12.0 [1] (🧑🏾‍🤝‍🧑🏽)
@@ -333,7 +333,6 @@
1F9D1 1F3FF 200D 2764 FE0F 200D 1F9D1 1F3FC ; RGI_Emoji_ZWJ_Sequence ; couple with heart: person, person, dark skin tone, medium-light skin tone #E13.1[1] (🧑🏿‍❤️‍🧑🏼)
1F9D1 1F3FF 200D 2764 FE0F 200D 1F9D1 1F3FD ; RGI_Emoji_ZWJ_Sequence ; couple with heart: person, person, dark skin tone, medium skin tone #E13.1[1] (🧑🏿‍❤️‍🧑🏽)
1F9D1 1F3FF 200D 2764 FE0F 200D 1F9D1 1F3FE ; RGI_Emoji_ZWJ_Sequence ; couple with heart: person, person, dark skin tone, medium-dark skin tone #E13.1[1] (🧑🏿‍❤️‍🧑🏾)
-1F9D1 1F3FF 200D 1F384 ; RGI_Emoji_ZWJ_Sequence ; mx claus: dark skin tone # E13.0 [1] (🧑🏿‍🎄)
1F9D1 1F3FF 200D 1F91D 200D 1F9D1 1F3FB ; RGI_Emoji_ZWJ_Sequence ; people holding hands: dark skin tone, light skin tone # E12.0 [1] (🧑🏿‍🤝‍🧑🏻)
1F9D1 1F3FF 200D 1F91D 200D 1F9D1 1F3FC ; RGI_Emoji_ZWJ_Sequence ; people holding hands: dark skin tone, medium-light skin tone # E12.0 [1] (🧑🏿‍🤝‍🧑🏼)
1F9D1 1F3FF 200D 1F91D 200D 1F9D1 1F3FD ; RGI_Emoji_ZWJ_Sequence ; people holding hands: dark skin tone, medium skin tone # E12.0 [1] (🧑🏿‍🤝‍🧑🏽)
@@ -360,12 +359,18 @@
1FAF1 1F3FF 200D 1FAF2 1F3FD ; RGI_Emoji_ZWJ_Sequence ; handshake: dark skin tone, medium skin tone # E14.0 [1] (🫱🏿‍🫲🏽)
1FAF1 1F3FF 200D 1FAF2 1F3FE ; RGI_Emoji_ZWJ_Sequence ; handshake: dark skin tone, medium-dark skin tone # E14.0 [1] (🫱🏿‍🫲🏾)
-# Total elements: 332
+# Total elements: 331
# ================================================
# RGI_Emoji_ZWJ_Sequence: Role
+1F3C3 200D 27A1 FE0F ; RGI_Emoji_ZWJ_Sequence ; person running facing right # E15.1 [1] (🏃‍➡️)
+1F3C3 1F3FB 200D 27A1 FE0F ; RGI_Emoji_ZWJ_Sequence ; person running facing right: light skin tone # E15.1 [1] (🏃🏻‍➡️)
+1F3C3 1F3FC 200D 27A1 FE0F ; RGI_Emoji_ZWJ_Sequence ; person running facing right: medium-light skin tone # E15.1 [1] (🏃🏼‍➡️)
+1F3C3 1F3FD 200D 27A1 FE0F ; RGI_Emoji_ZWJ_Sequence ; person running facing right: medium skin tone # E15.1 [1] (🏃🏽‍➡️)
+1F3C3 1F3FE 200D 27A1 FE0F ; RGI_Emoji_ZWJ_Sequence ; person running facing right: medium-dark skin tone # E15.1 [1] (🏃🏾‍➡️)
+1F3C3 1F3FF 200D 27A1 FE0F ; RGI_Emoji_ZWJ_Sequence ; person running facing right: dark skin tone # E15.1 [1] (🏃🏿‍➡️)
1F468 200D 2695 FE0F ; RGI_Emoji_ZWJ_Sequence ; man health worker # E4.0 [1] (👨‍⚕️)
1F468 200D 2696 FE0F ; RGI_Emoji_ZWJ_Sequence ; man judge # E4.0 [1] (👨‍⚖️)
1F468 200D 2708 FE0F ; RGI_Emoji_ZWJ_Sequence ; man pilot # E4.0 [1] (👨‍✈️)
@@ -384,8 +389,11 @@
1F468 200D 1F680 ; RGI_Emoji_ZWJ_Sequence ; man astronaut # E4.0 [1] (👨‍🚀)
1F468 200D 1F692 ; RGI_Emoji_ZWJ_Sequence ; man firefighter # E4.0 [1] (👨‍🚒)
1F468 200D 1F9AF ; RGI_Emoji_ZWJ_Sequence ; man with white cane # E12.0 [1] (👨‍🦯)
+1F468 200D 1F9AF 200D 27A1 FE0F ; RGI_Emoji_ZWJ_Sequence ; man with white cane facing right # E15.1 [1] (👨‍🦯‍➡️)
1F468 200D 1F9BC ; RGI_Emoji_ZWJ_Sequence ; man in motorized wheelchair # E12.0 [1] (👨‍🦼)
+1F468 200D 1F9BC 200D 27A1 FE0F ; RGI_Emoji_ZWJ_Sequence ; man in motorized wheelchair facing right # E15.1 [1] (👨‍🦼‍➡️)
1F468 200D 1F9BD ; RGI_Emoji_ZWJ_Sequence ; man in manual wheelchair # E12.0 [1] (👨‍🦽)
+1F468 200D 1F9BD 200D 27A1 FE0F ; RGI_Emoji_ZWJ_Sequence ; man in manual wheelchair facing right # E15.1 [1] (👨‍🦽‍➡️)
1F468 1F3FB 200D 2695 FE0F ; RGI_Emoji_ZWJ_Sequence ; man health worker: light skin tone # E4.0 [1] (👨🏻‍⚕️)
1F468 1F3FB 200D 2696 FE0F ; RGI_Emoji_ZWJ_Sequence ; man judge: light skin tone # E4.0 [1] (👨🏻‍⚖️)
1F468 1F3FB 200D 2708 FE0F ; RGI_Emoji_ZWJ_Sequence ; man pilot: light skin tone # E4.0 [1] (👨🏻‍✈️)
@@ -404,8 +412,11 @@
1F468 1F3FB 200D 1F680 ; RGI_Emoji_ZWJ_Sequence ; man astronaut: light skin tone # E4.0 [1] (👨🏻‍🚀)
1F468 1F3FB 200D 1F692 ; RGI_Emoji_ZWJ_Sequence ; man firefighter: light skin tone # E4.0 [1] (👨🏻‍🚒)
1F468 1F3FB 200D 1F9AF ; RGI_Emoji_ZWJ_Sequence ; man with white cane: light skin tone # E12.0 [1] (👨🏻‍🦯)
+1F468 1F3FB 200D 1F9AF 200D 27A1 FE0F ; RGI_Emoji_ZWJ_Sequence ; man with white cane facing right: light skin tone # E15.1 [1] (👨🏻‍🦯‍➡️)
1F468 1F3FB 200D 1F9BC ; RGI_Emoji_ZWJ_Sequence ; man in motorized wheelchair: light skin tone # E12.0 [1] (👨🏻‍🦼)
+1F468 1F3FB 200D 1F9BC 200D 27A1 FE0F ; RGI_Emoji_ZWJ_Sequence ; man in motorized wheelchair facing right: light skin tone # E15.1 [1] (👨🏻‍🦼‍➡️)
1F468 1F3FB 200D 1F9BD ; RGI_Emoji_ZWJ_Sequence ; man in manual wheelchair: light skin tone # E12.0 [1] (👨🏻‍🦽)
+1F468 1F3FB 200D 1F9BD 200D 27A1 FE0F ; RGI_Emoji_ZWJ_Sequence ; man in manual wheelchair facing right: light skin tone # E15.1 [1] (👨🏻‍🦽‍➡️)
1F468 1F3FC 200D 2695 FE0F ; RGI_Emoji_ZWJ_Sequence ; man health worker: medium-light skin tone # E4.0 [1] (👨🏼‍⚕️)
1F468 1F3FC 200D 2696 FE0F ; RGI_Emoji_ZWJ_Sequence ; man judge: medium-light skin tone # E4.0 [1] (👨🏼‍⚖️)
1F468 1F3FC 200D 2708 FE0F ; RGI_Emoji_ZWJ_Sequence ; man pilot: medium-light skin tone # E4.0 [1] (👨🏼‍✈️)
@@ -424,8 +435,11 @@
1F468 1F3FC 200D 1F680 ; RGI_Emoji_ZWJ_Sequence ; man astronaut: medium-light skin tone # E4.0 [1] (👨🏼‍🚀)
1F468 1F3FC 200D 1F692 ; RGI_Emoji_ZWJ_Sequence ; man firefighter: medium-light skin tone # E4.0 [1] (👨🏼‍🚒)
1F468 1F3FC 200D 1F9AF ; RGI_Emoji_ZWJ_Sequence ; man with white cane: medium-light skin tone # E12.0 [1] (👨🏼‍🦯)
+1F468 1F3FC 200D 1F9AF 200D 27A1 FE0F ; RGI_Emoji_ZWJ_Sequence ; man with white cane facing right: medium-light skin tone # E15.1 [1] (👨🏼‍🦯‍➡️)
1F468 1F3FC 200D 1F9BC ; RGI_Emoji_ZWJ_Sequence ; man in motorized wheelchair: medium-light skin tone # E12.0 [1] (👨🏼‍🦼)
+1F468 1F3FC 200D 1F9BC 200D 27A1 FE0F ; RGI_Emoji_ZWJ_Sequence ; man in motorized wheelchair facing right: medium-light skin tone #E15.1 [1] (👨🏼‍🦼‍➡️)
1F468 1F3FC 200D 1F9BD ; RGI_Emoji_ZWJ_Sequence ; man in manual wheelchair: medium-light skin tone # E12.0 [1] (👨🏼‍🦽)
+1F468 1F3FC 200D 1F9BD 200D 27A1 FE0F ; RGI_Emoji_ZWJ_Sequence ; man in manual wheelchair facing right: medium-light skin tone # E15.1 [1] (👨🏼‍🦽‍➡️)
1F468 1F3FD 200D 2695 FE0F ; RGI_Emoji_ZWJ_Sequence ; man health worker: medium skin tone # E4.0 [1] (👨🏽‍⚕️)
1F468 1F3FD 200D 2696 FE0F ; RGI_Emoji_ZWJ_Sequence ; man judge: medium skin tone # E4.0 [1] (👨🏽‍⚖️)
1F468 1F3FD 200D 2708 FE0F ; RGI_Emoji_ZWJ_Sequence ; man pilot: medium skin tone # E4.0 [1] (👨🏽‍✈️)
@@ -444,8 +458,11 @@
1F468 1F3FD 200D 1F680 ; RGI_Emoji_ZWJ_Sequence ; man astronaut: medium skin tone # E4.0 [1] (👨🏽‍🚀)
1F468 1F3FD 200D 1F692 ; RGI_Emoji_ZWJ_Sequence ; man firefighter: medium skin tone # E4.0 [1] (👨🏽‍🚒)
1F468 1F3FD 200D 1F9AF ; RGI_Emoji_ZWJ_Sequence ; man with white cane: medium skin tone # E12.0 [1] (👨🏽‍🦯)
+1F468 1F3FD 200D 1F9AF 200D 27A1 FE0F ; RGI_Emoji_ZWJ_Sequence ; man with white cane facing right: medium skin tone # E15.1 [1] (👨🏽‍🦯‍➡️)
1F468 1F3FD 200D 1F9BC ; RGI_Emoji_ZWJ_Sequence ; man in motorized wheelchair: medium skin tone # E12.0 [1] (👨🏽‍🦼)
+1F468 1F3FD 200D 1F9BC 200D 27A1 FE0F ; RGI_Emoji_ZWJ_Sequence ; man in motorized wheelchair facing right: medium skin tone # E15.1 [1] (👨🏽‍🦼‍➡️)
1F468 1F3FD 200D 1F9BD ; RGI_Emoji_ZWJ_Sequence ; man in manual wheelchair: medium skin tone # E12.0 [1] (👨🏽‍🦽)
+1F468 1F3FD 200D 1F9BD 200D 27A1 FE0F ; RGI_Emoji_ZWJ_Sequence ; man in manual wheelchair facing right: medium skin tone # E15.1 [1] (👨🏽‍🦽‍➡️)
1F468 1F3FE 200D 2695 FE0F ; RGI_Emoji_ZWJ_Sequence ; man health worker: medium-dark skin tone # E4.0 [1] (👨🏾‍⚕️)
1F468 1F3FE 200D 2696 FE0F ; RGI_Emoji_ZWJ_Sequence ; man judge: medium-dark skin tone # E4.0 [1] (👨🏾‍⚖️)
1F468 1F3FE 200D 2708 FE0F ; RGI_Emoji_ZWJ_Sequence ; man pilot: medium-dark skin tone # E4.0 [1] (👨🏾‍✈️)
@@ -464,8 +481,11 @@
1F468 1F3FE 200D 1F680 ; RGI_Emoji_ZWJ_Sequence ; man astronaut: medium-dark skin tone # E4.0 [1] (👨🏾‍🚀)
1F468 1F3FE 200D 1F692 ; RGI_Emoji_ZWJ_Sequence ; man firefighter: medium-dark skin tone # E4.0 [1] (👨🏾‍🚒)
1F468 1F3FE 200D 1F9AF ; RGI_Emoji_ZWJ_Sequence ; man with white cane: medium-dark skin tone # E12.0 [1] (👨🏾‍🦯)
+1F468 1F3FE 200D 1F9AF 200D 27A1 FE0F ; RGI_Emoji_ZWJ_Sequence ; man with white cane facing right: medium-dark skin tone # E15.1 [1] (👨🏾‍🦯‍➡️)
1F468 1F3FE 200D 1F9BC ; RGI_Emoji_ZWJ_Sequence ; man in motorized wheelchair: medium-dark skin tone # E12.0 [1] (👨🏾‍🦼)
+1F468 1F3FE 200D 1F9BC 200D 27A1 FE0F ; RGI_Emoji_ZWJ_Sequence ; man in motorized wheelchair facing right: medium-dark skin tone #E15.1 [1] (👨🏾‍🦼‍➡️)
1F468 1F3FE 200D 1F9BD ; RGI_Emoji_ZWJ_Sequence ; man in manual wheelchair: medium-dark skin tone # E12.0 [1] (👨🏾‍🦽)
+1F468 1F3FE 200D 1F9BD 200D 27A1 FE0F ; RGI_Emoji_ZWJ_Sequence ; man in manual wheelchair facing right: medium-dark skin tone # E15.1 [1] (👨🏾‍🦽‍➡️)
1F468 1F3FF 200D 2695 FE0F ; RGI_Emoji_ZWJ_Sequence ; man health worker: dark skin tone # E4.0 [1] (👨🏿‍⚕️)
1F468 1F3FF 200D 2696 FE0F ; RGI_Emoji_ZWJ_Sequence ; man judge: dark skin tone # E4.0 [1] (👨🏿‍⚖️)
1F468 1F3FF 200D 2708 FE0F ; RGI_Emoji_ZWJ_Sequence ; man pilot: dark skin tone # E4.0 [1] (👨🏿‍✈️)
@@ -484,8 +504,11 @@
1F468 1F3FF 200D 1F680 ; RGI_Emoji_ZWJ_Sequence ; man astronaut: dark skin tone # E4.0 [1] (👨🏿‍🚀)
1F468 1F3FF 200D 1F692 ; RGI_Emoji_ZWJ_Sequence ; man firefighter: dark skin tone # E4.0 [1] (👨🏿‍🚒)
1F468 1F3FF 200D 1F9AF ; RGI_Emoji_ZWJ_Sequence ; man with white cane: dark skin tone # E12.0 [1] (👨🏿‍🦯)
+1F468 1F3FF 200D 1F9AF 200D 27A1 FE0F ; RGI_Emoji_ZWJ_Sequence ; man with white cane facing right: dark skin tone # E15.1 [1] (👨🏿‍🦯‍➡️)
1F468 1F3FF 200D 1F9BC ; RGI_Emoji_ZWJ_Sequence ; man in motorized wheelchair: dark skin tone # E12.0 [1] (👨🏿‍🦼)
+1F468 1F3FF 200D 1F9BC 200D 27A1 FE0F ; RGI_Emoji_ZWJ_Sequence ; man in motorized wheelchair facing right: dark skin tone # E15.1 [1] (👨🏿‍🦼‍➡️)
1F468 1F3FF 200D 1F9BD ; RGI_Emoji_ZWJ_Sequence ; man in manual wheelchair: dark skin tone # E12.0 [1] (👨🏿‍🦽)
+1F468 1F3FF 200D 1F9BD 200D 27A1 FE0F ; RGI_Emoji_ZWJ_Sequence ; man in manual wheelchair facing right: dark skin tone # E15.1 [1] (👨🏿‍🦽‍➡️)
1F469 200D 2695 FE0F ; RGI_Emoji_ZWJ_Sequence ; woman health worker # E4.0 [1] (👩‍⚕️)
1F469 200D 2696 FE0F ; RGI_Emoji_ZWJ_Sequence ; woman judge # E4.0 [1] (👩‍⚖️)
1F469 200D 2708 FE0F ; RGI_Emoji_ZWJ_Sequence ; woman pilot # E4.0 [1] (👩‍✈️)
@@ -504,8 +527,11 @@
1F469 200D 1F680 ; RGI_Emoji_ZWJ_Sequence ; woman astronaut # E4.0 [1] (👩‍🚀)
1F469 200D 1F692 ; RGI_Emoji_ZWJ_Sequence ; woman firefighter # E4.0 [1] (👩‍🚒)
1F469 200D 1F9AF ; RGI_Emoji_ZWJ_Sequence ; woman with white cane # E12.0 [1] (👩‍🦯)
+1F469 200D 1F9AF 200D 27A1 FE0F ; RGI_Emoji_ZWJ_Sequence ; woman with white cane facing right # E15.1 [1] (👩‍🦯‍➡️)
1F469 200D 1F9BC ; RGI_Emoji_ZWJ_Sequence ; woman in motorized wheelchair # E12.0 [1] (👩‍🦼)
+1F469 200D 1F9BC 200D 27A1 FE0F ; RGI_Emoji_ZWJ_Sequence ; woman in motorized wheelchair facing right # E15.1 [1] (👩‍🦼‍➡️)
1F469 200D 1F9BD ; RGI_Emoji_ZWJ_Sequence ; woman in manual wheelchair # E12.0 [1] (👩‍🦽)
+1F469 200D 1F9BD 200D 27A1 FE0F ; RGI_Emoji_ZWJ_Sequence ; woman in manual wheelchair facing right # E15.1 [1] (👩‍🦽‍➡️)
1F469 1F3FB 200D 2695 FE0F ; RGI_Emoji_ZWJ_Sequence ; woman health worker: light skin tone # E4.0 [1] (👩🏻‍⚕️)
1F469 1F3FB 200D 2696 FE0F ; RGI_Emoji_ZWJ_Sequence ; woman judge: light skin tone # E4.0 [1] (👩🏻‍⚖️)
1F469 1F3FB 200D 2708 FE0F ; RGI_Emoji_ZWJ_Sequence ; woman pilot: light skin tone # E4.0 [1] (👩🏻‍✈️)
@@ -524,8 +550,11 @@
1F469 1F3FB 200D 1F680 ; RGI_Emoji_ZWJ_Sequence ; woman astronaut: light skin tone # E4.0 [1] (👩🏻‍🚀)
1F469 1F3FB 200D 1F692 ; RGI_Emoji_ZWJ_Sequence ; woman firefighter: light skin tone # E4.0 [1] (👩🏻‍🚒)
1F469 1F3FB 200D 1F9AF ; RGI_Emoji_ZWJ_Sequence ; woman with white cane: light skin tone # E12.0 [1] (👩🏻‍🦯)
+1F469 1F3FB 200D 1F9AF 200D 27A1 FE0F ; RGI_Emoji_ZWJ_Sequence ; woman with white cane facing right: light skin tone # E15.1 [1] (👩🏻‍🦯‍➡️)
1F469 1F3FB 200D 1F9BC ; RGI_Emoji_ZWJ_Sequence ; woman in motorized wheelchair: light skin tone # E12.0 [1] (👩🏻‍🦼)
+1F469 1F3FB 200D 1F9BC 200D 27A1 FE0F ; RGI_Emoji_ZWJ_Sequence ; woman in motorized wheelchair facing right: light skin tone # E15.1 [1] (👩🏻‍🦼‍➡️)
1F469 1F3FB 200D 1F9BD ; RGI_Emoji_ZWJ_Sequence ; woman in manual wheelchair: light skin tone # E12.0 [1] (👩🏻‍🦽)
+1F469 1F3FB 200D 1F9BD 200D 27A1 FE0F ; RGI_Emoji_ZWJ_Sequence ; woman in manual wheelchair facing right: light skin tone # E15.1 [1] (👩🏻‍🦽‍➡️)
1F469 1F3FC 200D 2695 FE0F ; RGI_Emoji_ZWJ_Sequence ; woman health worker: medium-light skin tone # E4.0 [1] (👩🏼‍⚕️)
1F469 1F3FC 200D 2696 FE0F ; RGI_Emoji_ZWJ_Sequence ; woman judge: medium-light skin tone # E4.0 [1] (👩🏼‍⚖️)
1F469 1F3FC 200D 2708 FE0F ; RGI_Emoji_ZWJ_Sequence ; woman pilot: medium-light skin tone # E4.0 [1] (👩🏼‍✈️)
@@ -544,8 +573,11 @@
1F469 1F3FC 200D 1F680 ; RGI_Emoji_ZWJ_Sequence ; woman astronaut: medium-light skin tone # E4.0 [1] (👩🏼‍🚀)
1F469 1F3FC 200D 1F692 ; RGI_Emoji_ZWJ_Sequence ; woman firefighter: medium-light skin tone # E4.0 [1] (👩🏼‍🚒)
1F469 1F3FC 200D 1F9AF ; RGI_Emoji_ZWJ_Sequence ; woman with white cane: medium-light skin tone # E12.0 [1] (👩🏼‍🦯)
+1F469 1F3FC 200D 1F9AF 200D 27A1 FE0F ; RGI_Emoji_ZWJ_Sequence ; woman with white cane facing right: medium-light skin tone # E15.1 [1] (👩🏼‍🦯‍➡️)
1F469 1F3FC 200D 1F9BC ; RGI_Emoji_ZWJ_Sequence ; woman in motorized wheelchair: medium-light skin tone # E12.0 [1] (👩🏼‍🦼)
+1F469 1F3FC 200D 1F9BC 200D 27A1 FE0F ; RGI_Emoji_ZWJ_Sequence ; woman in motorized wheelchair facing right: medium-light skin tone #E15.1[1] (👩🏼‍🦼‍➡️)
1F469 1F3FC 200D 1F9BD ; RGI_Emoji_ZWJ_Sequence ; woman in manual wheelchair: medium-light skin tone # E12.0 [1] (👩🏼‍🦽)
+1F469 1F3FC 200D 1F9BD 200D 27A1 FE0F ; RGI_Emoji_ZWJ_Sequence ; woman in manual wheelchair facing right: medium-light skin tone #E15.1 [1] (👩🏼‍🦽‍➡️)
1F469 1F3FD 200D 2695 FE0F ; RGI_Emoji_ZWJ_Sequence ; woman health worker: medium skin tone # E4.0 [1] (👩🏽‍⚕️)
1F469 1F3FD 200D 2696 FE0F ; RGI_Emoji_ZWJ_Sequence ; woman judge: medium skin tone # E4.0 [1] (👩🏽‍⚖️)
1F469 1F3FD 200D 2708 FE0F ; RGI_Emoji_ZWJ_Sequence ; woman pilot: medium skin tone # E4.0 [1] (👩🏽‍✈️)
@@ -564,8 +596,11 @@
1F469 1F3FD 200D 1F680 ; RGI_Emoji_ZWJ_Sequence ; woman astronaut: medium skin tone # E4.0 [1] (👩🏽‍🚀)
1F469 1F3FD 200D 1F692 ; RGI_Emoji_ZWJ_Sequence ; woman firefighter: medium skin tone # E4.0 [1] (👩🏽‍🚒)
1F469 1F3FD 200D 1F9AF ; RGI_Emoji_ZWJ_Sequence ; woman with white cane: medium skin tone # E12.0 [1] (👩🏽‍🦯)
+1F469 1F3FD 200D 1F9AF 200D 27A1 FE0F ; RGI_Emoji_ZWJ_Sequence ; woman with white cane facing right: medium skin tone # E15.1 [1] (👩🏽‍🦯‍➡️)
1F469 1F3FD 200D 1F9BC ; RGI_Emoji_ZWJ_Sequence ; woman in motorized wheelchair: medium skin tone # E12.0 [1] (👩🏽‍🦼)
+1F469 1F3FD 200D 1F9BC 200D 27A1 FE0F ; RGI_Emoji_ZWJ_Sequence ; woman in motorized wheelchair facing right: medium skin tone # E15.1 [1] (👩🏽‍🦼‍➡️)
1F469 1F3FD 200D 1F9BD ; RGI_Emoji_ZWJ_Sequence ; woman in manual wheelchair: medium skin tone # E12.0 [1] (👩🏽‍🦽)
+1F469 1F3FD 200D 1F9BD 200D 27A1 FE0F ; RGI_Emoji_ZWJ_Sequence ; woman in manual wheelchair facing right: medium skin tone # E15.1 [1] (👩🏽‍🦽‍➡️)
1F469 1F3FE 200D 2695 FE0F ; RGI_Emoji_ZWJ_Sequence ; woman health worker: medium-dark skin tone # E4.0 [1] (👩🏾‍⚕️)
1F469 1F3FE 200D 2696 FE0F ; RGI_Emoji_ZWJ_Sequence ; woman judge: medium-dark skin tone # E4.0 [1] (👩🏾‍⚖️)
1F469 1F3FE 200D 2708 FE0F ; RGI_Emoji_ZWJ_Sequence ; woman pilot: medium-dark skin tone # E4.0 [1] (👩🏾‍✈️)
@@ -584,8 +619,11 @@
1F469 1F3FE 200D 1F680 ; RGI_Emoji_ZWJ_Sequence ; woman astronaut: medium-dark skin tone # E4.0 [1] (👩🏾‍🚀)
1F469 1F3FE 200D 1F692 ; RGI_Emoji_ZWJ_Sequence ; woman firefighter: medium-dark skin tone # E4.0 [1] (👩🏾‍🚒)
1F469 1F3FE 200D 1F9AF ; RGI_Emoji_ZWJ_Sequence ; woman with white cane: medium-dark skin tone # E12.0 [1] (👩🏾‍🦯)
+1F469 1F3FE 200D 1F9AF 200D 27A1 FE0F ; RGI_Emoji_ZWJ_Sequence ; woman with white cane facing right: medium-dark skin tone # E15.1 [1] (👩🏾‍🦯‍➡️)
1F469 1F3FE 200D 1F9BC ; RGI_Emoji_ZWJ_Sequence ; woman in motorized wheelchair: medium-dark skin tone # E12.0 [1] (👩🏾‍🦼)
+1F469 1F3FE 200D 1F9BC 200D 27A1 FE0F ; RGI_Emoji_ZWJ_Sequence ; woman in motorized wheelchair facing right: medium-dark skin tone #E15.1[1] (👩🏾‍🦼‍➡️)
1F469 1F3FE 200D 1F9BD ; RGI_Emoji_ZWJ_Sequence ; woman in manual wheelchair: medium-dark skin tone # E12.0 [1] (👩🏾‍🦽)
+1F469 1F3FE 200D 1F9BD 200D 27A1 FE0F ; RGI_Emoji_ZWJ_Sequence ; woman in manual wheelchair facing right: medium-dark skin tone # E15.1 [1] (👩🏾‍🦽‍➡️)
1F469 1F3FF 200D 2695 FE0F ; RGI_Emoji_ZWJ_Sequence ; woman health worker: dark skin tone # E4.0 [1] (👩🏿‍⚕️)
1F469 1F3FF 200D 2696 FE0F ; RGI_Emoji_ZWJ_Sequence ; woman judge: dark skin tone # E4.0 [1] (👩🏿‍⚖️)
1F469 1F3FF 200D 2708 FE0F ; RGI_Emoji_ZWJ_Sequence ; woman pilot: dark skin tone # E4.0 [1] (👩🏿‍✈️)
@@ -604,14 +642,30 @@
1F469 1F3FF 200D 1F680 ; RGI_Emoji_ZWJ_Sequence ; woman astronaut: dark skin tone # E4.0 [1] (👩🏿‍🚀)
1F469 1F3FF 200D 1F692 ; RGI_Emoji_ZWJ_Sequence ; woman firefighter: dark skin tone # E4.0 [1] (👩🏿‍🚒)
1F469 1F3FF 200D 1F9AF ; RGI_Emoji_ZWJ_Sequence ; woman with white cane: dark skin tone # E12.0 [1] (👩🏿‍🦯)
+1F469 1F3FF 200D 1F9AF 200D 27A1 FE0F ; RGI_Emoji_ZWJ_Sequence ; woman with white cane facing right: dark skin tone # E15.1 [1] (👩🏿‍🦯‍➡️)
1F469 1F3FF 200D 1F9BC ; RGI_Emoji_ZWJ_Sequence ; woman in motorized wheelchair: dark skin tone # E12.0 [1] (👩🏿‍🦼)
+1F469 1F3FF 200D 1F9BC 200D 27A1 FE0F ; RGI_Emoji_ZWJ_Sequence ; woman in motorized wheelchair facing right: dark skin tone # E15.1 [1] (👩🏿‍🦼‍➡️)
1F469 1F3FF 200D 1F9BD ; RGI_Emoji_ZWJ_Sequence ; woman in manual wheelchair: dark skin tone # E12.0 [1] (👩🏿‍🦽)
+1F469 1F3FF 200D 1F9BD 200D 27A1 FE0F ; RGI_Emoji_ZWJ_Sequence ; woman in manual wheelchair facing right: dark skin tone # E15.1 [1] (👩🏿‍🦽‍➡️)
+1F6B6 200D 27A1 FE0F ; RGI_Emoji_ZWJ_Sequence ; person walking facing right # E15.1 [1] (🚶‍➡️)
+1F6B6 1F3FB 200D 27A1 FE0F ; RGI_Emoji_ZWJ_Sequence ; person walking facing right: light skin tone # E15.1 [1] (🚶🏻‍➡️)
+1F6B6 1F3FC 200D 27A1 FE0F ; RGI_Emoji_ZWJ_Sequence ; person walking facing right: medium-light skin tone # E15.1 [1] (🚶🏼‍➡️)
+1F6B6 1F3FD 200D 27A1 FE0F ; RGI_Emoji_ZWJ_Sequence ; person walking facing right: medium skin tone # E15.1 [1] (🚶🏽‍➡️)
+1F6B6 1F3FE 200D 27A1 FE0F ; RGI_Emoji_ZWJ_Sequence ; person walking facing right: medium-dark skin tone # E15.1 [1] (🚶🏾‍➡️)
+1F6B6 1F3FF 200D 27A1 FE0F ; RGI_Emoji_ZWJ_Sequence ; person walking facing right: dark skin tone # E15.1 [1] (🚶🏿‍➡️)
+1F9CE 200D 27A1 FE0F ; RGI_Emoji_ZWJ_Sequence ; person kneeling facing right # E15.1 [1] (🧎‍➡️)
+1F9CE 1F3FB 200D 27A1 FE0F ; RGI_Emoji_ZWJ_Sequence ; person kneeling facing right: light skin tone # E15.1 [1] (🧎🏻‍➡️)
+1F9CE 1F3FC 200D 27A1 FE0F ; RGI_Emoji_ZWJ_Sequence ; person kneeling facing right: medium-light skin tone # E15.1 [1] (🧎🏼‍➡️)
+1F9CE 1F3FD 200D 27A1 FE0F ; RGI_Emoji_ZWJ_Sequence ; person kneeling facing right: medium skin tone # E15.1 [1] (🧎🏽‍➡️)
+1F9CE 1F3FE 200D 27A1 FE0F ; RGI_Emoji_ZWJ_Sequence ; person kneeling facing right: medium-dark skin tone # E15.1 [1] (🧎🏾‍➡️)
+1F9CE 1F3FF 200D 27A1 FE0F ; RGI_Emoji_ZWJ_Sequence ; person kneeling facing right: dark skin tone # E15.1 [1] (🧎🏿‍➡️)
1F9D1 200D 2695 FE0F ; RGI_Emoji_ZWJ_Sequence ; health worker # E12.1 [1] (🧑‍⚕️)
1F9D1 200D 2696 FE0F ; RGI_Emoji_ZWJ_Sequence ; judge # E12.1 [1] (🧑‍⚖️)
1F9D1 200D 2708 FE0F ; RGI_Emoji_ZWJ_Sequence ; pilot # E12.1 [1] (🧑‍✈️)
1F9D1 200D 1F33E ; RGI_Emoji_ZWJ_Sequence ; farmer # E12.1 [1] (🧑‍🌾)
1F9D1 200D 1F373 ; RGI_Emoji_ZWJ_Sequence ; cook # E12.1 [1] (🧑‍🍳)
1F9D1 200D 1F37C ; RGI_Emoji_ZWJ_Sequence ; person feeding baby # E13.0 [1] (🧑‍🍼)
+1F9D1 200D 1F384 ; RGI_Emoji_ZWJ_Sequence ; mx claus # E13.0 [1] (🧑‍🎄)
1F9D1 200D 1F393 ; RGI_Emoji_ZWJ_Sequence ; student # E12.1 [1] (🧑‍🎓)
1F9D1 200D 1F3A4 ; RGI_Emoji_ZWJ_Sequence ; singer # E12.1 [1] (🧑‍🎤)
1F9D1 200D 1F3A8 ; RGI_Emoji_ZWJ_Sequence ; artist # E12.1 [1] (🧑‍🎨)
@@ -624,14 +678,18 @@
1F9D1 200D 1F680 ; RGI_Emoji_ZWJ_Sequence ; astronaut # E12.1 [1] (🧑‍🚀)
1F9D1 200D 1F692 ; RGI_Emoji_ZWJ_Sequence ; firefighter # E12.1 [1] (🧑‍🚒)
1F9D1 200D 1F9AF ; RGI_Emoji_ZWJ_Sequence ; person with white cane # E12.1 [1] (🧑‍🦯)
+1F9D1 200D 1F9AF 200D 27A1 FE0F ; RGI_Emoji_ZWJ_Sequence ; person with white cane facing right # E15.1 [1] (🧑‍🦯‍➡️)
1F9D1 200D 1F9BC ; RGI_Emoji_ZWJ_Sequence ; person in motorized wheelchair # E12.1 [1] (🧑‍🦼)
+1F9D1 200D 1F9BC 200D 27A1 FE0F ; RGI_Emoji_ZWJ_Sequence ; person in motorized wheelchair facing right # E15.1 [1] (🧑‍🦼‍➡️)
1F9D1 200D 1F9BD ; RGI_Emoji_ZWJ_Sequence ; person in manual wheelchair # E12.1 [1] (🧑‍🦽)
+1F9D1 200D 1F9BD 200D 27A1 FE0F ; RGI_Emoji_ZWJ_Sequence ; person in manual wheelchair facing right # E15.1 [1] (🧑‍🦽‍➡️)
1F9D1 1F3FB 200D 2695 FE0F ; RGI_Emoji_ZWJ_Sequence ; health worker: light skin tone # E12.1 [1] (🧑🏻‍⚕️)
1F9D1 1F3FB 200D 2696 FE0F ; RGI_Emoji_ZWJ_Sequence ; judge: light skin tone # E12.1 [1] (🧑🏻‍⚖️)
1F9D1 1F3FB 200D 2708 FE0F ; RGI_Emoji_ZWJ_Sequence ; pilot: light skin tone # E12.1 [1] (🧑🏻‍✈️)
1F9D1 1F3FB 200D 1F33E ; RGI_Emoji_ZWJ_Sequence ; farmer: light skin tone # E12.1 [1] (🧑🏻‍🌾)
1F9D1 1F3FB 200D 1F373 ; RGI_Emoji_ZWJ_Sequence ; cook: light skin tone # E12.1 [1] (🧑🏻‍🍳)
1F9D1 1F3FB 200D 1F37C ; RGI_Emoji_ZWJ_Sequence ; person feeding baby: light skin tone # E13.0 [1] (🧑🏻‍🍼)
+1F9D1 1F3FB 200D 1F384 ; RGI_Emoji_ZWJ_Sequence ; mx claus: light skin tone # E13.0 [1] (🧑🏻‍🎄)
1F9D1 1F3FB 200D 1F393 ; RGI_Emoji_ZWJ_Sequence ; student: light skin tone # E12.1 [1] (🧑🏻‍🎓)
1F9D1 1F3FB 200D 1F3A4 ; RGI_Emoji_ZWJ_Sequence ; singer: light skin tone # E12.1 [1] (🧑🏻‍🎤)
1F9D1 1F3FB 200D 1F3A8 ; RGI_Emoji_ZWJ_Sequence ; artist: light skin tone # E12.1 [1] (🧑🏻‍🎨)
@@ -644,14 +702,18 @@
1F9D1 1F3FB 200D 1F680 ; RGI_Emoji_ZWJ_Sequence ; astronaut: light skin tone # E12.1 [1] (🧑🏻‍🚀)
1F9D1 1F3FB 200D 1F692 ; RGI_Emoji_ZWJ_Sequence ; firefighter: light skin tone # E12.1 [1] (🧑🏻‍🚒)
1F9D1 1F3FB 200D 1F9AF ; RGI_Emoji_ZWJ_Sequence ; person with white cane: light skin tone # E12.1 [1] (🧑🏻‍🦯)
+1F9D1 1F3FB 200D 1F9AF 200D 27A1 FE0F ; RGI_Emoji_ZWJ_Sequence ; person with white cane facing right: light skin tone # E15.1 [1] (🧑🏻‍🦯‍➡️)
1F9D1 1F3FB 200D 1F9BC ; RGI_Emoji_ZWJ_Sequence ; person in motorized wheelchair: light skin tone # E12.1 [1] (🧑🏻‍🦼)
+1F9D1 1F3FB 200D 1F9BC 200D 27A1 FE0F ; RGI_Emoji_ZWJ_Sequence ; person in motorized wheelchair facing right: light skin tone # E15.1 [1] (🧑🏻‍🦼‍➡️)
1F9D1 1F3FB 200D 1F9BD ; RGI_Emoji_ZWJ_Sequence ; person in manual wheelchair: light skin tone # E12.1 [1] (🧑🏻‍🦽)
+1F9D1 1F3FB 200D 1F9BD 200D 27A1 FE0F ; RGI_Emoji_ZWJ_Sequence ; person in manual wheelchair facing right: light skin tone # E15.1 [1] (🧑🏻‍🦽‍➡️)
1F9D1 1F3FC 200D 2695 FE0F ; RGI_Emoji_ZWJ_Sequence ; health worker: medium-light skin tone # E12.1 [1] (🧑🏼‍⚕️)
1F9D1 1F3FC 200D 2696 FE0F ; RGI_Emoji_ZWJ_Sequence ; judge: medium-light skin tone # E12.1 [1] (🧑🏼‍⚖️)
1F9D1 1F3FC 200D 2708 FE0F ; RGI_Emoji_ZWJ_Sequence ; pilot: medium-light skin tone # E12.1 [1] (🧑🏼‍✈️)
1F9D1 1F3FC 200D 1F33E ; RGI_Emoji_ZWJ_Sequence ; farmer: medium-light skin tone # E12.1 [1] (🧑🏼‍🌾)
1F9D1 1F3FC 200D 1F373 ; RGI_Emoji_ZWJ_Sequence ; cook: medium-light skin tone # E12.1 [1] (🧑🏼‍🍳)
1F9D1 1F3FC 200D 1F37C ; RGI_Emoji_ZWJ_Sequence ; person feeding baby: medium-light skin tone # E13.0 [1] (🧑🏼‍🍼)
+1F9D1 1F3FC 200D 1F384 ; RGI_Emoji_ZWJ_Sequence ; mx claus: medium-light skin tone # E13.0 [1] (🧑🏼‍🎄)
1F9D1 1F3FC 200D 1F393 ; RGI_Emoji_ZWJ_Sequence ; student: medium-light skin tone # E12.1 [1] (🧑🏼‍🎓)
1F9D1 1F3FC 200D 1F3A4 ; RGI_Emoji_ZWJ_Sequence ; singer: medium-light skin tone # E12.1 [1] (🧑🏼‍🎤)
1F9D1 1F3FC 200D 1F3A8 ; RGI_Emoji_ZWJ_Sequence ; artist: medium-light skin tone # E12.1 [1] (🧑🏼‍🎨)
@@ -664,14 +726,18 @@
1F9D1 1F3FC 200D 1F680 ; RGI_Emoji_ZWJ_Sequence ; astronaut: medium-light skin tone # E12.1 [1] (🧑🏼‍🚀)
1F9D1 1F3FC 200D 1F692 ; RGI_Emoji_ZWJ_Sequence ; firefighter: medium-light skin tone # E12.1 [1] (🧑🏼‍🚒)
1F9D1 1F3FC 200D 1F9AF ; RGI_Emoji_ZWJ_Sequence ; person with white cane: medium-light skin tone # E12.1 [1] (🧑🏼‍🦯)
+1F9D1 1F3FC 200D 1F9AF 200D 27A1 FE0F ; RGI_Emoji_ZWJ_Sequence ; person with white cane facing right: medium-light skin tone # E15.1 [1] (🧑🏼‍🦯‍➡️)
1F9D1 1F3FC 200D 1F9BC ; RGI_Emoji_ZWJ_Sequence ; person in motorized wheelchair: medium-light skin tone # E12.1 [1] (🧑🏼‍🦼)
+1F9D1 1F3FC 200D 1F9BC 200D 27A1 FE0F ; RGI_Emoji_ZWJ_Sequence ; person in motorized wheelchair facing right: medium-light skin tone #E15.1[1] (🧑🏼‍🦼‍➡️)
1F9D1 1F3FC 200D 1F9BD ; RGI_Emoji_ZWJ_Sequence ; person in manual wheelchair: medium-light skin tone # E12.1 [1] (🧑🏼‍🦽)
+1F9D1 1F3FC 200D 1F9BD 200D 27A1 FE0F ; RGI_Emoji_ZWJ_Sequence ; person in manual wheelchair facing right: medium-light skin tone #E15.1 [1] (🧑🏼‍🦽‍➡️)
1F9D1 1F3FD 200D 2695 FE0F ; RGI_Emoji_ZWJ_Sequence ; health worker: medium skin tone # E12.1 [1] (🧑🏽‍⚕️)
1F9D1 1F3FD 200D 2696 FE0F ; RGI_Emoji_ZWJ_Sequence ; judge: medium skin tone # E12.1 [1] (🧑🏽‍⚖️)
1F9D1 1F3FD 200D 2708 FE0F ; RGI_Emoji_ZWJ_Sequence ; pilot: medium skin tone # E12.1 [1] (🧑🏽‍✈️)
1F9D1 1F3FD 200D 1F33E ; RGI_Emoji_ZWJ_Sequence ; farmer: medium skin tone # E12.1 [1] (🧑🏽‍🌾)
1F9D1 1F3FD 200D 1F373 ; RGI_Emoji_ZWJ_Sequence ; cook: medium skin tone # E12.1 [1] (🧑🏽‍🍳)
1F9D1 1F3FD 200D 1F37C ; RGI_Emoji_ZWJ_Sequence ; person feeding baby: medium skin tone # E13.0 [1] (🧑🏽‍🍼)
+1F9D1 1F3FD 200D 1F384 ; RGI_Emoji_ZWJ_Sequence ; mx claus: medium skin tone # E13.0 [1] (🧑🏽‍🎄)
1F9D1 1F3FD 200D 1F393 ; RGI_Emoji_ZWJ_Sequence ; student: medium skin tone # E12.1 [1] (🧑🏽‍🎓)
1F9D1 1F3FD 200D 1F3A4 ; RGI_Emoji_ZWJ_Sequence ; singer: medium skin tone # E12.1 [1] (🧑🏽‍🎤)
1F9D1 1F3FD 200D 1F3A8 ; RGI_Emoji_ZWJ_Sequence ; artist: medium skin tone # E12.1 [1] (🧑🏽‍🎨)
@@ -684,14 +750,18 @@
1F9D1 1F3FD 200D 1F680 ; RGI_Emoji_ZWJ_Sequence ; astronaut: medium skin tone # E12.1 [1] (🧑🏽‍🚀)
1F9D1 1F3FD 200D 1F692 ; RGI_Emoji_ZWJ_Sequence ; firefighter: medium skin tone # E12.1 [1] (🧑🏽‍🚒)
1F9D1 1F3FD 200D 1F9AF ; RGI_Emoji_ZWJ_Sequence ; person with white cane: medium skin tone # E12.1 [1] (🧑🏽‍🦯)
+1F9D1 1F3FD 200D 1F9AF 200D 27A1 FE0F ; RGI_Emoji_ZWJ_Sequence ; person with white cane facing right: medium skin tone # E15.1 [1] (🧑🏽‍🦯‍➡️)
1F9D1 1F3FD 200D 1F9BC ; RGI_Emoji_ZWJ_Sequence ; person in motorized wheelchair: medium skin tone # E12.1 [1] (🧑🏽‍🦼)
+1F9D1 1F3FD 200D 1F9BC 200D 27A1 FE0F ; RGI_Emoji_ZWJ_Sequence ; person in motorized wheelchair facing right: medium skin tone # E15.1 [1] (🧑🏽‍🦼‍➡️)
1F9D1 1F3FD 200D 1F9BD ; RGI_Emoji_ZWJ_Sequence ; person in manual wheelchair: medium skin tone # E12.1 [1] (🧑🏽‍🦽)
+1F9D1 1F3FD 200D 1F9BD 200D 27A1 FE0F ; RGI_Emoji_ZWJ_Sequence ; person in manual wheelchair facing right: medium skin tone # E15.1 [1] (🧑🏽‍🦽‍➡️)
1F9D1 1F3FE 200D 2695 FE0F ; RGI_Emoji_ZWJ_Sequence ; health worker: medium-dark skin tone # E12.1 [1] (🧑🏾‍⚕️)
1F9D1 1F3FE 200D 2696 FE0F ; RGI_Emoji_ZWJ_Sequence ; judge: medium-dark skin tone # E12.1 [1] (🧑🏾‍⚖️)
1F9D1 1F3FE 200D 2708 FE0F ; RGI_Emoji_ZWJ_Sequence ; pilot: medium-dark skin tone # E12.1 [1] (🧑🏾‍✈️)
1F9D1 1F3FE 200D 1F33E ; RGI_Emoji_ZWJ_Sequence ; farmer: medium-dark skin tone # E12.1 [1] (🧑🏾‍🌾)
1F9D1 1F3FE 200D 1F373 ; RGI_Emoji_ZWJ_Sequence ; cook: medium-dark skin tone # E12.1 [1] (🧑🏾‍🍳)
1F9D1 1F3FE 200D 1F37C ; RGI_Emoji_ZWJ_Sequence ; person feeding baby: medium-dark skin tone # E13.0 [1] (🧑🏾‍🍼)
+1F9D1 1F3FE 200D 1F384 ; RGI_Emoji_ZWJ_Sequence ; mx claus: medium-dark skin tone # E13.0 [1] (🧑🏾‍🎄)
1F9D1 1F3FE 200D 1F393 ; RGI_Emoji_ZWJ_Sequence ; student: medium-dark skin tone # E12.1 [1] (🧑🏾‍🎓)
1F9D1 1F3FE 200D 1F3A4 ; RGI_Emoji_ZWJ_Sequence ; singer: medium-dark skin tone # E12.1 [1] (🧑🏾‍🎤)
1F9D1 1F3FE 200D 1F3A8 ; RGI_Emoji_ZWJ_Sequence ; artist: medium-dark skin tone # E12.1 [1] (🧑🏾‍🎨)
@@ -704,14 +774,18 @@
1F9D1 1F3FE 200D 1F680 ; RGI_Emoji_ZWJ_Sequence ; astronaut: medium-dark skin tone # E12.1 [1] (🧑🏾‍🚀)
1F9D1 1F3FE 200D 1F692 ; RGI_Emoji_ZWJ_Sequence ; firefighter: medium-dark skin tone # E12.1 [1] (🧑🏾‍🚒)
1F9D1 1F3FE 200D 1F9AF ; RGI_Emoji_ZWJ_Sequence ; person with white cane: medium-dark skin tone # E12.1 [1] (🧑🏾‍🦯)
+1F9D1 1F3FE 200D 1F9AF 200D 27A1 FE0F ; RGI_Emoji_ZWJ_Sequence ; person with white cane facing right: medium-dark skin tone # E15.1 [1] (🧑🏾‍🦯‍➡️)
1F9D1 1F3FE 200D 1F9BC ; RGI_Emoji_ZWJ_Sequence ; person in motorized wheelchair: medium-dark skin tone # E12.1 [1] (🧑🏾‍🦼)
+1F9D1 1F3FE 200D 1F9BC 200D 27A1 FE0F ; RGI_Emoji_ZWJ_Sequence ; person in motorized wheelchair facing right: medium-dark skin tone #E15.1[1] (🧑🏾‍🦼‍➡️)
1F9D1 1F3FE 200D 1F9BD ; RGI_Emoji_ZWJ_Sequence ; person in manual wheelchair: medium-dark skin tone # E12.1 [1] (🧑🏾‍🦽)
+1F9D1 1F3FE 200D 1F9BD 200D 27A1 FE0F ; RGI_Emoji_ZWJ_Sequence ; person in manual wheelchair facing right: medium-dark skin tone #E15.1 [1] (🧑🏾‍🦽‍➡️)
1F9D1 1F3FF 200D 2695 FE0F ; RGI_Emoji_ZWJ_Sequence ; health worker: dark skin tone # E12.1 [1] (🧑🏿‍⚕️)
1F9D1 1F3FF 200D 2696 FE0F ; RGI_Emoji_ZWJ_Sequence ; judge: dark skin tone # E12.1 [1] (🧑🏿‍⚖️)
1F9D1 1F3FF 200D 2708 FE0F ; RGI_Emoji_ZWJ_Sequence ; pilot: dark skin tone # E12.1 [1] (🧑🏿‍✈️)
1F9D1 1F3FF 200D 1F33E ; RGI_Emoji_ZWJ_Sequence ; farmer: dark skin tone # E12.1 [1] (🧑🏿‍🌾)
1F9D1 1F3FF 200D 1F373 ; RGI_Emoji_ZWJ_Sequence ; cook: dark skin tone # E12.1 [1] (🧑🏿‍🍳)
1F9D1 1F3FF 200D 1F37C ; RGI_Emoji_ZWJ_Sequence ; person feeding baby: dark skin tone # E13.0 [1] (🧑🏿‍🍼)
+1F9D1 1F3FF 200D 1F384 ; RGI_Emoji_ZWJ_Sequence ; mx claus: dark skin tone # E13.0 [1] (🧑🏿‍🎄)
1F9D1 1F3FF 200D 1F393 ; RGI_Emoji_ZWJ_Sequence ; student: dark skin tone # E12.1 [1] (🧑🏿‍🎓)
1F9D1 1F3FF 200D 1F3A4 ; RGI_Emoji_ZWJ_Sequence ; singer: dark skin tone # E12.1 [1] (🧑🏿‍🎤)
1F9D1 1F3FF 200D 1F3A8 ; RGI_Emoji_ZWJ_Sequence ; artist: dark skin tone # E12.1 [1] (🧑🏿‍🎨)
@@ -724,10 +798,13 @@
1F9D1 1F3FF 200D 1F680 ; RGI_Emoji_ZWJ_Sequence ; astronaut: dark skin tone # E12.1 [1] (🧑🏿‍🚀)
1F9D1 1F3FF 200D 1F692 ; RGI_Emoji_ZWJ_Sequence ; firefighter: dark skin tone # E12.1 [1] (🧑🏿‍🚒)
1F9D1 1F3FF 200D 1F9AF ; RGI_Emoji_ZWJ_Sequence ; person with white cane: dark skin tone # E12.1 [1] (🧑🏿‍🦯)
+1F9D1 1F3FF 200D 1F9AF 200D 27A1 FE0F ; RGI_Emoji_ZWJ_Sequence ; person with white cane facing right: dark skin tone # E15.1 [1] (🧑🏿‍🦯‍➡️)
1F9D1 1F3FF 200D 1F9BC ; RGI_Emoji_ZWJ_Sequence ; person in motorized wheelchair: dark skin tone # E12.1 [1] (🧑🏿‍🦼)
+1F9D1 1F3FF 200D 1F9BC 200D 27A1 FE0F ; RGI_Emoji_ZWJ_Sequence ; person in motorized wheelchair facing right: dark skin tone # E15.1 [1] (🧑🏿‍🦼‍➡️)
1F9D1 1F3FF 200D 1F9BD ; RGI_Emoji_ZWJ_Sequence ; person in manual wheelchair: dark skin tone # E12.1 [1] (🧑🏿‍🦽)
+1F9D1 1F3FF 200D 1F9BD 200D 27A1 FE0F ; RGI_Emoji_ZWJ_Sequence ; person in manual wheelchair facing right: dark skin tone # E15.1 [1] (🧑🏿‍🦽‍➡️)
-# Total elements: 360
+# Total elements: 438
# ================================================
@@ -746,17 +823,29 @@
26F9 FE0F 200D 2640 FE0F ; RGI_Emoji_ZWJ_Sequence ; woman bouncing ball # E4.0 [1] (⛹️‍♀️)
26F9 FE0F 200D 2642 FE0F ; RGI_Emoji_ZWJ_Sequence ; man bouncing ball # E4.0 [1] (⛹️‍♂️)
1F3C3 200D 2640 FE0F ; RGI_Emoji_ZWJ_Sequence ; woman running # E4.0 [1] (🏃‍♀️)
+1F3C3 200D 2640 FE0F 200D 27A1 FE0F ; RGI_Emoji_ZWJ_Sequence ; woman running facing right # E15.1 [1] (🏃‍♀️‍➡️)
1F3C3 200D 2642 FE0F ; RGI_Emoji_ZWJ_Sequence ; man running # E4.0 [1] (🏃‍♂️)
+1F3C3 200D 2642 FE0F 200D 27A1 FE0F ; RGI_Emoji_ZWJ_Sequence ; man running facing right # E15.1 [1] (🏃‍♂️‍➡️)
1F3C3 1F3FB 200D 2640 FE0F ; RGI_Emoji_ZWJ_Sequence ; woman running: light skin tone # E4.0 [1] (🏃🏻‍♀️)
+1F3C3 1F3FB 200D 2640 FE0F 200D 27A1 FE0F ; RGI_Emoji_ZWJ_Sequence ; woman running facing right: light skin tone # E15.1 [1] (🏃🏻‍♀️‍➡️)
1F3C3 1F3FB 200D 2642 FE0F ; RGI_Emoji_ZWJ_Sequence ; man running: light skin tone # E4.0 [1] (🏃🏻‍♂️)
+1F3C3 1F3FB 200D 2642 FE0F 200D 27A1 FE0F ; RGI_Emoji_ZWJ_Sequence ; man running facing right: light skin tone # E15.1 [1] (🏃🏻‍♂️‍➡️)
1F3C3 1F3FC 200D 2640 FE0F ; RGI_Emoji_ZWJ_Sequence ; woman running: medium-light skin tone # E4.0 [1] (🏃🏼‍♀️)
+1F3C3 1F3FC 200D 2640 FE0F 200D 27A1 FE0F ; RGI_Emoji_ZWJ_Sequence ; woman running facing right: medium-light skin tone # E15.1 [1] (🏃🏼‍♀️‍➡️)
1F3C3 1F3FC 200D 2642 FE0F ; RGI_Emoji_ZWJ_Sequence ; man running: medium-light skin tone # E4.0 [1] (🏃🏼‍♂️)
+1F3C3 1F3FC 200D 2642 FE0F 200D 27A1 FE0F ; RGI_Emoji_ZWJ_Sequence ; man running facing right: medium-light skin tone # E15.1 [1] (🏃🏼‍♂️‍➡️)
1F3C3 1F3FD 200D 2640 FE0F ; RGI_Emoji_ZWJ_Sequence ; woman running: medium skin tone # E4.0 [1] (🏃🏽‍♀️)
+1F3C3 1F3FD 200D 2640 FE0F 200D 27A1 FE0F ; RGI_Emoji_ZWJ_Sequence ; woman running facing right: medium skin tone # E15.1 [1] (🏃🏽‍♀️‍➡️)
1F3C3 1F3FD 200D 2642 FE0F ; RGI_Emoji_ZWJ_Sequence ; man running: medium skin tone # E4.0 [1] (🏃🏽‍♂️)
+1F3C3 1F3FD 200D 2642 FE0F 200D 27A1 FE0F ; RGI_Emoji_ZWJ_Sequence ; man running facing right: medium skin tone # E15.1 [1] (🏃🏽‍♂️‍➡️)
1F3C3 1F3FE 200D 2640 FE0F ; RGI_Emoji_ZWJ_Sequence ; woman running: medium-dark skin tone # E4.0 [1] (🏃🏾‍♀️)
+1F3C3 1F3FE 200D 2640 FE0F 200D 27A1 FE0F ; RGI_Emoji_ZWJ_Sequence ; woman running facing right: medium-dark skin tone # E15.1 [1] (🏃🏾‍♀️‍➡️)
1F3C3 1F3FE 200D 2642 FE0F ; RGI_Emoji_ZWJ_Sequence ; man running: medium-dark skin tone # E4.0 [1] (🏃🏾‍♂️)
+1F3C3 1F3FE 200D 2642 FE0F 200D 27A1 FE0F ; RGI_Emoji_ZWJ_Sequence ; man running facing right: medium-dark skin tone # E15.1 [1] (🏃🏾‍♂️‍➡️)
1F3C3 1F3FF 200D 2640 FE0F ; RGI_Emoji_ZWJ_Sequence ; woman running: dark skin tone # E4.0 [1] (🏃🏿‍♀️)
+1F3C3 1F3FF 200D 2640 FE0F 200D 27A1 FE0F ; RGI_Emoji_ZWJ_Sequence ; woman running facing right: dark skin tone # E15.1 [1] (🏃🏿‍♀️‍➡️)
1F3C3 1F3FF 200D 2642 FE0F ; RGI_Emoji_ZWJ_Sequence ; man running: dark skin tone # E4.0 [1] (🏃🏿‍♂️)
+1F3C3 1F3FF 200D 2642 FE0F 200D 27A1 FE0F ; RGI_Emoji_ZWJ_Sequence ; man running facing right: dark skin tone # E15.1 [1] (🏃🏿‍♂️‍➡️)
1F3C4 200D 2640 FE0F ; RGI_Emoji_ZWJ_Sequence ; woman surfing # E4.0 [1] (🏄‍♀️)
1F3C4 200D 2642 FE0F ; RGI_Emoji_ZWJ_Sequence ; man surfing # E4.0 [1] (🏄‍♂️)
1F3C4 1F3FB 200D 2640 FE0F ; RGI_Emoji_ZWJ_Sequence ; woman surfing: light skin tone # E4.0 [1] (🏄🏻‍♀️)
@@ -1036,17 +1125,29 @@
1F6B5 1F3FF 200D 2640 FE0F ; RGI_Emoji_ZWJ_Sequence ; woman mountain biking: dark skin tone # E4.0 [1] (🚵🏿‍♀️)
1F6B5 1F3FF 200D 2642 FE0F ; RGI_Emoji_ZWJ_Sequence ; man mountain biking: dark skin tone # E4.0 [1] (🚵🏿‍♂️)
1F6B6 200D 2640 FE0F ; RGI_Emoji_ZWJ_Sequence ; woman walking # E4.0 [1] (🚶‍♀️)
+1F6B6 200D 2640 FE0F 200D 27A1 FE0F ; RGI_Emoji_ZWJ_Sequence ; woman walking facing right # E15.1 [1] (🚶‍♀️‍➡️)
1F6B6 200D 2642 FE0F ; RGI_Emoji_ZWJ_Sequence ; man walking # E4.0 [1] (🚶‍♂️)
+1F6B6 200D 2642 FE0F 200D 27A1 FE0F ; RGI_Emoji_ZWJ_Sequence ; man walking facing right # E15.1 [1] (🚶‍♂️‍➡️)
1F6B6 1F3FB 200D 2640 FE0F ; RGI_Emoji_ZWJ_Sequence ; woman walking: light skin tone # E4.0 [1] (🚶🏻‍♀️)
+1F6B6 1F3FB 200D 2640 FE0F 200D 27A1 FE0F ; RGI_Emoji_ZWJ_Sequence ; woman walking facing right: light skin tone # E15.1 [1] (🚶🏻‍♀️‍➡️)
1F6B6 1F3FB 200D 2642 FE0F ; RGI_Emoji_ZWJ_Sequence ; man walking: light skin tone # E4.0 [1] (🚶🏻‍♂️)
+1F6B6 1F3FB 200D 2642 FE0F 200D 27A1 FE0F ; RGI_Emoji_ZWJ_Sequence ; man walking facing right: light skin tone # E15.1 [1] (🚶🏻‍♂️‍➡️)
1F6B6 1F3FC 200D 2640 FE0F ; RGI_Emoji_ZWJ_Sequence ; woman walking: medium-light skin tone # E4.0 [1] (🚶🏼‍♀️)
+1F6B6 1F3FC 200D 2640 FE0F 200D 27A1 FE0F ; RGI_Emoji_ZWJ_Sequence ; woman walking facing right: medium-light skin tone # E15.1 [1] (🚶🏼‍♀️‍➡️)
1F6B6 1F3FC 200D 2642 FE0F ; RGI_Emoji_ZWJ_Sequence ; man walking: medium-light skin tone # E4.0 [1] (🚶🏼‍♂️)
+1F6B6 1F3FC 200D 2642 FE0F 200D 27A1 FE0F ; RGI_Emoji_ZWJ_Sequence ; man walking facing right: medium-light skin tone # E15.1 [1] (🚶🏼‍♂️‍➡️)
1F6B6 1F3FD 200D 2640 FE0F ; RGI_Emoji_ZWJ_Sequence ; woman walking: medium skin tone # E4.0 [1] (🚶🏽‍♀️)
+1F6B6 1F3FD 200D 2640 FE0F 200D 27A1 FE0F ; RGI_Emoji_ZWJ_Sequence ; woman walking facing right: medium skin tone # E15.1 [1] (🚶🏽‍♀️‍➡️)
1F6B6 1F3FD 200D 2642 FE0F ; RGI_Emoji_ZWJ_Sequence ; man walking: medium skin tone # E4.0 [1] (🚶🏽‍♂️)
+1F6B6 1F3FD 200D 2642 FE0F 200D 27A1 FE0F ; RGI_Emoji_ZWJ_Sequence ; man walking facing right: medium skin tone # E15.1 [1] (🚶🏽‍♂️‍➡️)
1F6B6 1F3FE 200D 2640 FE0F ; RGI_Emoji_ZWJ_Sequence ; woman walking: medium-dark skin tone # E4.0 [1] (🚶🏾‍♀️)
+1F6B6 1F3FE 200D 2640 FE0F 200D 27A1 FE0F ; RGI_Emoji_ZWJ_Sequence ; woman walking facing right: medium-dark skin tone # E15.1 [1] (🚶🏾‍♀️‍➡️)
1F6B6 1F3FE 200D 2642 FE0F ; RGI_Emoji_ZWJ_Sequence ; man walking: medium-dark skin tone # E4.0 [1] (🚶🏾‍♂️)
+1F6B6 1F3FE 200D 2642 FE0F 200D 27A1 FE0F ; RGI_Emoji_ZWJ_Sequence ; man walking facing right: medium-dark skin tone # E15.1 [1] (🚶🏾‍♂️‍➡️)
1F6B6 1F3FF 200D 2640 FE0F ; RGI_Emoji_ZWJ_Sequence ; woman walking: dark skin tone # E4.0 [1] (🚶🏿‍♀️)
+1F6B6 1F3FF 200D 2640 FE0F 200D 27A1 FE0F ; RGI_Emoji_ZWJ_Sequence ; woman walking facing right: dark skin tone # E15.1 [1] (🚶🏿‍♀️‍➡️)
1F6B6 1F3FF 200D 2642 FE0F ; RGI_Emoji_ZWJ_Sequence ; man walking: dark skin tone # E4.0 [1] (🚶🏿‍♂️)
+1F6B6 1F3FF 200D 2642 FE0F 200D 27A1 FE0F ; RGI_Emoji_ZWJ_Sequence ; man walking facing right: dark skin tone # E15.1 [1] (🚶🏿‍♂️‍➡️)
1F926 200D 2640 FE0F ; RGI_Emoji_ZWJ_Sequence ; woman facepalming # E4.0 [1] (🤦‍♀️)
1F926 200D 2642 FE0F ; RGI_Emoji_ZWJ_Sequence ; man facepalming # E4.0 [1] (🤦‍♂️)
1F926 1F3FB 200D 2640 FE0F ; RGI_Emoji_ZWJ_Sequence ; woman facepalming: light skin tone # E4.0 [1] (🤦🏻‍♀️)
@@ -1170,17 +1271,29 @@
1F9CD 1F3FF 200D 2640 FE0F ; RGI_Emoji_ZWJ_Sequence ; woman standing: dark skin tone # E12.0 [1] (🧍🏿‍♀️)
1F9CD 1F3FF 200D 2642 FE0F ; RGI_Emoji_ZWJ_Sequence ; man standing: dark skin tone # E12.0 [1] (🧍🏿‍♂️)
1F9CE 200D 2640 FE0F ; RGI_Emoji_ZWJ_Sequence ; woman kneeling # E12.0 [1] (🧎‍♀️)
+1F9CE 200D 2640 FE0F 200D 27A1 FE0F ; RGI_Emoji_ZWJ_Sequence ; woman kneeling facing right # E15.1 [1] (🧎‍♀️‍➡️)
1F9CE 200D 2642 FE0F ; RGI_Emoji_ZWJ_Sequence ; man kneeling # E12.0 [1] (🧎‍♂️)
+1F9CE 200D 2642 FE0F 200D 27A1 FE0F ; RGI_Emoji_ZWJ_Sequence ; man kneeling facing right # E15.1 [1] (🧎‍♂️‍➡️)
1F9CE 1F3FB 200D 2640 FE0F ; RGI_Emoji_ZWJ_Sequence ; woman kneeling: light skin tone # E12.0 [1] (🧎🏻‍♀️)
+1F9CE 1F3FB 200D 2640 FE0F 200D 27A1 FE0F ; RGI_Emoji_ZWJ_Sequence ; woman kneeling facing right: light skin tone # E15.1 [1] (🧎🏻‍♀️‍➡️)
1F9CE 1F3FB 200D 2642 FE0F ; RGI_Emoji_ZWJ_Sequence ; man kneeling: light skin tone # E12.0 [1] (🧎🏻‍♂️)
+1F9CE 1F3FB 200D 2642 FE0F 200D 27A1 FE0F ; RGI_Emoji_ZWJ_Sequence ; man kneeling facing right: light skin tone # E15.1 [1] (🧎🏻‍♂️‍➡️)
1F9CE 1F3FC 200D 2640 FE0F ; RGI_Emoji_ZWJ_Sequence ; woman kneeling: medium-light skin tone # E12.0 [1] (🧎🏼‍♀️)
+1F9CE 1F3FC 200D 2640 FE0F 200D 27A1 FE0F ; RGI_Emoji_ZWJ_Sequence ; woman kneeling facing right: medium-light skin tone # E15.1 [1] (🧎🏼‍♀️‍➡️)
1F9CE 1F3FC 200D 2642 FE0F ; RGI_Emoji_ZWJ_Sequence ; man kneeling: medium-light skin tone # E12.0 [1] (🧎🏼‍♂️)
+1F9CE 1F3FC 200D 2642 FE0F 200D 27A1 FE0F ; RGI_Emoji_ZWJ_Sequence ; man kneeling facing right: medium-light skin tone # E15.1 [1] (🧎🏼‍♂️‍➡️)
1F9CE 1F3FD 200D 2640 FE0F ; RGI_Emoji_ZWJ_Sequence ; woman kneeling: medium skin tone # E12.0 [1] (🧎🏽‍♀️)
+1F9CE 1F3FD 200D 2640 FE0F 200D 27A1 FE0F ; RGI_Emoji_ZWJ_Sequence ; woman kneeling facing right: medium skin tone # E15.1 [1] (🧎🏽‍♀️‍➡️)
1F9CE 1F3FD 200D 2642 FE0F ; RGI_Emoji_ZWJ_Sequence ; man kneeling: medium skin tone # E12.0 [1] (🧎🏽‍♂️)
+1F9CE 1F3FD 200D 2642 FE0F 200D 27A1 FE0F ; RGI_Emoji_ZWJ_Sequence ; man kneeling facing right: medium skin tone # E15.1 [1] (🧎🏽‍♂️‍➡️)
1F9CE 1F3FE 200D 2640 FE0F ; RGI_Emoji_ZWJ_Sequence ; woman kneeling: medium-dark skin tone # E12.0 [1] (🧎🏾‍♀️)
+1F9CE 1F3FE 200D 2640 FE0F 200D 27A1 FE0F ; RGI_Emoji_ZWJ_Sequence ; woman kneeling facing right: medium-dark skin tone # E15.1 [1] (🧎🏾‍♀️‍➡️)
1F9CE 1F3FE 200D 2642 FE0F ; RGI_Emoji_ZWJ_Sequence ; man kneeling: medium-dark skin tone # E12.0 [1] (🧎🏾‍♂️)
+1F9CE 1F3FE 200D 2642 FE0F 200D 27A1 FE0F ; RGI_Emoji_ZWJ_Sequence ; man kneeling facing right: medium-dark skin tone # E15.1 [1] (🧎🏾‍♂️‍➡️)
1F9CE 1F3FF 200D 2640 FE0F ; RGI_Emoji_ZWJ_Sequence ; woman kneeling: dark skin tone # E12.0 [1] (🧎🏿‍♀️)
+1F9CE 1F3FF 200D 2640 FE0F 200D 27A1 FE0F ; RGI_Emoji_ZWJ_Sequence ; woman kneeling facing right: dark skin tone # E15.1 [1] (🧎🏿‍♀️‍➡️)
1F9CE 1F3FF 200D 2642 FE0F ; RGI_Emoji_ZWJ_Sequence ; man kneeling: dark skin tone # E12.0 [1] (🧎🏿‍♂️)
+1F9CE 1F3FF 200D 2642 FE0F 200D 27A1 FE0F ; RGI_Emoji_ZWJ_Sequence ; man kneeling facing right: dark skin tone # E15.1 [1] (🧎🏿‍♂️‍➡️)
1F9CF 200D 2640 FE0F ; RGI_Emoji_ZWJ_Sequence ; deaf woman # E12.0 [1] (🧏‍♀️)
1F9CF 200D 2642 FE0F ; RGI_Emoji_ZWJ_Sequence ; deaf man # E12.0 [1] (🧏‍♂️)
1F9CF 1F3FB 200D 2640 FE0F ; RGI_Emoji_ZWJ_Sequence ; deaf woman: light skin tone # E12.0 [1] (🧏🏻‍♀️)
@@ -1306,7 +1419,7 @@
1F9DF 200D 2640 FE0F ; RGI_Emoji_ZWJ_Sequence ; woman zombie # E5.0 [1] (🧟‍♀️)
1F9DF 200D 2642 FE0F ; RGI_Emoji_ZWJ_Sequence ; man zombie # E5.0 [1] (🧟‍♂️)
-# Total elements: 572
+# Total elements: 608
# ================================================
@@ -1391,21 +1504,26 @@
# RGI_Emoji_ZWJ_Sequence: Other
+26D3 FE0F 200D 1F4A5 ; RGI_Emoji_ZWJ_Sequence ; broken chain # E15.1 [1] (⛓️‍💥)
2764 FE0F 200D 1F525 ; RGI_Emoji_ZWJ_Sequence ; heart on fire # E13.1 [1] (❤️‍🔥)
2764 FE0F 200D 1FA79 ; RGI_Emoji_ZWJ_Sequence ; mending heart # E13.1 [1] (❤️‍🩹)
+1F344 200D 1F7EB ; RGI_Emoji_ZWJ_Sequence ; brown mushroom # E15.1 [1] (🍄‍🟫)
+1F34B 200D 1F7E9 ; RGI_Emoji_ZWJ_Sequence ; lime # E15.1 [1] (🍋‍🟩)
1F3F3 FE0F 200D 26A7 FE0F ; RGI_Emoji_ZWJ_Sequence ; transgender flag # E13.0 [1] (🏳️‍⚧️)
1F3F3 FE0F 200D 1F308 ; RGI_Emoji_ZWJ_Sequence ; rainbow flag # E4.0 [1] (🏳️‍🌈)
1F3F4 200D 2620 FE0F ; RGI_Emoji_ZWJ_Sequence ; pirate flag # E11.0 [1] (🏴‍☠️)
1F408 200D 2B1B ; RGI_Emoji_ZWJ_Sequence ; black cat # E13.0 [1] (🐈‍⬛)
1F415 200D 1F9BA ; RGI_Emoji_ZWJ_Sequence ; service dog # E12.0 [1] (🐕‍🦺)
1F426 200D 2B1B ; RGI_Emoji_ZWJ_Sequence ; black bird # E15.0 [1] (🐦‍⬛)
+1F426 200D 1F525 ; RGI_Emoji_ZWJ_Sequence ; phoenix # E15.1 [1] (🐦‍🔥)
1F43B 200D 2744 FE0F ; RGI_Emoji_ZWJ_Sequence ; polar bear # E13.0 [1] (🐻‍❄️)
1F441 FE0F 200D 1F5E8 FE0F ; RGI_Emoji_ZWJ_Sequence ; eye in speech bubble # E2.0 [1] (👁️‍🗨️)
1F62E 200D 1F4A8 ; RGI_Emoji_ZWJ_Sequence ; face exhaling # E13.1 [1] (😮‍💨)
1F635 200D 1F4AB ; RGI_Emoji_ZWJ_Sequence ; face with spiral eyes # E13.1 [1] (😵‍💫)
1F636 200D 1F32B FE0F ; RGI_Emoji_ZWJ_Sequence ; face in clouds # E13.1 [1] (😶‍🌫️)
-1F9D1 200D 1F384 ; RGI_Emoji_ZWJ_Sequence ; mx claus # E13.0 [1] (🧑‍🎄)
+1F642 200D 2194 FE0F ; RGI_Emoji_ZWJ_Sequence ; head shaking horizontally # E15.1 [1] (🙂‍↔️)
+1F642 200D 2195 FE0F ; RGI_Emoji_ZWJ_Sequence ; head shaking vertically # E15.1 [1] (🙂‍↕️)
-# Total elements: 14
+# Total elements: 19
#EOF
diff --git a/admin/unidata/emoji-zwj.awk b/admin/unidata/emoji-zwj.awk
index 53170214d8a..c69bc6822d0 100644
--- a/admin/unidata/emoji-zwj.awk
+++ b/admin/unidata/emoji-zwj.awk
@@ -1,6 +1,6 @@
#!/usr/bin/awk -f
-## Copyright (C) 2020, 2022-2023 Free Software Foundation, Inc.
+## Copyright (C) 2020, 2022-2024 Free Software Foundation, Inc.
## Author: Robert Pluim <rpluim@gmail.com>
@@ -100,14 +100,14 @@ END {
vec[codepoint] = vec[codepoint] "\n\"\\N{U+" trigger_codepoints[trig] "}\\N{U+FE0F}\""
}
- print "(dolist (elt `("
+ print "(dolist (elt (eval-when-compile `("
for (elt in ch)
{
- print "(#x" elt " .\n,(eval-when-compile (regexp-opt\n'(\n" vec[elt]
- print "\"\\N{U+" elt "}\\N{U+FE0E}\"\n\"\\N{U+" elt "}\\N{U+FE0F}\"\n))))"
+ print "(#x" elt " .\n,(regexp-opt\n'(\n" vec[elt]
+ print "\"\\N{U+" elt "}\\N{U+FE0E}\"\n\"\\N{U+" elt "}\\N{U+FE0F}\"\n)))"
}
- print "))"
+ print ")))"
print " (set-char-table-range composition-function-table"
print " (car elt)"
print " (nconc (char-table-range composition-function-table (car elt))"
diff --git a/admin/unidata/unidata-gen.el b/admin/unidata/unidata-gen.el
index 1ad347c9425..7be03fe63af 100644
--- a/admin/unidata/unidata-gen.el
+++ b/admin/unidata/unidata-gen.el
@@ -1,6 +1,6 @@
;;; unidata-gen.el --- Create files containing character property data -*- lexical-binding:t -*-
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
;; Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011
;; National Institute of Advanced Industrial Science and Technology (AIST)
diff --git a/admin/unidata/uvs.el b/admin/unidata/uvs.el
index 70f6d323f12..736d5d67bd1 100644
--- a/admin/unidata/uvs.el
+++ b/admin/unidata/uvs.el
@@ -1,6 +1,6 @@
;;; uvs.el --- utility for UVS (format 14) cmap subtables in OpenType fonts -*- lexical-binding:t -*-
-;; Copyright (C) 2014-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2014-2024 Free Software Foundation, Inc.
;; Author: YAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp>
diff --git a/admin/update-copyright b/admin/update-copyright
index df6f6c7d487..b9007100b35 100755
--- a/admin/update-copyright
+++ b/admin/update-copyright
@@ -7,7 +7,7 @@
# By default, this script uses the local-time calendar year.
# Set the UPDATE_COPYRIGHT_YEAR environment variable to override the default.
-# Copyright 2013-2023 Free Software Foundation, Inc.
+# Copyright 2013-2024 Free Software Foundation, Inc.
# This file is part of GNU Emacs.
diff --git a/admin/update_autogen b/admin/update_autogen
index 5088bc674ca..224d6c66eed 100755
--- a/admin/update_autogen
+++ b/admin/update_autogen
@@ -1,7 +1,7 @@
#!/usr/bin/env bash
### update_autogen - update some auto-generated files in the Emacs tree
-## Copyright (C) 2011-2023 Free Software Foundation, Inc.
+## Copyright (C) 2011-2024 Free Software Foundation, Inc.
## Author: Glenn Morris <rgm@gnu.org>
## Maintainer: Stefan Kangas <stefankangas@gmail.com>
diff --git a/admin/upload-manuals b/admin/upload-manuals
index a206177a5c1..2e6d03e6bc6 100755
--- a/admin/upload-manuals
+++ b/admin/upload-manuals
@@ -2,7 +2,7 @@
### upload-manuals - upload the Emacs manuals to the gnu.org website
-## Copyright 2018-2023 Free Software Foundation, Inc.
+## Copyright 2018-2024 Free Software Foundation, Inc.
## Author: Glenn Morris <rgm@gnu.org>
## Maintainer: emacs-devel@gnu.org
diff --git a/autogen.sh b/autogen.sh
index 0d89b7cfc9a..be41771cae7 100755
--- a/autogen.sh
+++ b/autogen.sh
@@ -1,7 +1,7 @@
#!/bin/sh
### autogen.sh - tool to help build Emacs from a repository checkout
-## Copyright (C) 2011-2023 Free Software Foundation, Inc.
+## Copyright (C) 2011-2024 Free Software Foundation, Inc.
## Author: Glenn Morris <rgm@gnu.org>
## Maintainer: emacs-devel@gnu.org
diff --git a/build-aux/config.guess b/build-aux/config.guess
index b187213930f..405d53d9785 100755
--- a/build-aux/config.guess
+++ b/build-aux/config.guess
@@ -1,6 +1,6 @@
#! /bin/sh
# Attempt to guess a canonical system name.
-# Copyright 1992-2023 Free Software Foundation, Inc.
+# Copyright 1992-2024 Free Software Foundation, Inc.
# shellcheck disable=SC2006,SC2268 # see below for rationale
diff --git a/build-aux/config.sub b/build-aux/config.sub
index 6ae25027537..183b3cc627b 100755
--- a/build-aux/config.sub
+++ b/build-aux/config.sub
@@ -1,6 +1,6 @@
#! /bin/sh
# Configuration validation subroutine script.
-# Copyright 1992-2023 Free Software Foundation, Inc.
+# Copyright 1992-2024 Free Software Foundation, Inc.
# shellcheck disable=SC2006,SC2268 # see below for rationale
diff --git a/build-aux/git-hooks/commit-msg b/build-aux/git-hooks/commit-msg
index d0578bcfb46..1eb2560bba2 100755
--- a/build-aux/git-hooks/commit-msg
+++ b/build-aux/git-hooks/commit-msg
@@ -1,7 +1,7 @@
#!/bin/sh
# Check the format of GNU Emacs change log entries.
-# Copyright 2014-2023 Free Software Foundation, Inc.
+# Copyright 2014-2024 Free Software Foundation, Inc.
# This file is part of GNU Emacs.
diff --git a/build-aux/git-hooks/commit-msg-files.awk b/build-aux/git-hooks/commit-msg-files.awk
index 5c9b70a5de5..2fbbd059500 100644
--- a/build-aux/git-hooks/commit-msg-files.awk
+++ b/build-aux/git-hooks/commit-msg-files.awk
@@ -1,6 +1,6 @@
# Check the file list of GNU Emacs change log entries for each commit SHA.
-# Copyright 2023 Free Software Foundation, Inc.
+# Copyright 2023-2024 Free Software Foundation, Inc.
# This file is part of GNU Emacs.
diff --git a/build-aux/git-hooks/post-commit b/build-aux/git-hooks/post-commit
index e02fee48db4..e6b5effc93a 100755
--- a/build-aux/git-hooks/post-commit
+++ b/build-aux/git-hooks/post-commit
@@ -1,7 +1,7 @@
#!/bin/sh
# Check the file list of GNU Emacs change log entries after committing.
-# Copyright 2023 Free Software Foundation, Inc.
+# Copyright 2023-2024 Free Software Foundation, Inc.
# This file is part of GNU Emacs.
diff --git a/build-aux/git-hooks/pre-commit b/build-aux/git-hooks/pre-commit
index 2e0dd7dfd7c..a86bbf642a5 100755
--- a/build-aux/git-hooks/pre-commit
+++ b/build-aux/git-hooks/pre-commit
@@ -1,7 +1,7 @@
#!/bin/sh
# Check file names in git commits for GNU Emacs.
-# Copyright 2014-2023 Free Software Foundation, Inc.
+# Copyright 2014-2024 Free Software Foundation, Inc.
# This file is part of GNU Emacs.
diff --git a/build-aux/git-hooks/pre-push b/build-aux/git-hooks/pre-push
index a342814c1e3..86c81e02d9a 100755
--- a/build-aux/git-hooks/pre-push
+++ b/build-aux/git-hooks/pre-push
@@ -1,7 +1,7 @@
#!/bin/sh
# Check the file list of GNU Emacs change log entries before pushing.
-# Copyright 2023 Free Software Foundation, Inc.
+# Copyright 2023-2024 Free Software Foundation, Inc.
# This file is part of GNU Emacs.
diff --git a/build-aux/git-hooks/prepare-commit-msg b/build-aux/git-hooks/prepare-commit-msg
index 1520ef3f5f8..0367858ea7e 100755
--- a/build-aux/git-hooks/prepare-commit-msg
+++ b/build-aux/git-hooks/prepare-commit-msg
@@ -1,7 +1,7 @@
#!/bin/sh
# Check the format of GNU Emacs change log entries.
-# Copyright 2019-2023 Free Software Foundation, Inc.
+# Copyright 2019-2024 Free Software Foundation, Inc.
# This file is part of GNU Emacs.
diff --git a/build-aux/gitlog-to-changelog b/build-aux/gitlog-to-changelog
index 43e4a37adf4..16a9405a7cb 100755
--- a/build-aux/gitlog-to-changelog
+++ b/build-aux/gitlog-to-changelog
@@ -3,7 +3,7 @@
# Convert git log output to ChangeLog format.
-# Copyright (C) 2008-2023 Free Software Foundation, Inc.
+# Copyright (C) 2008-2024 Free Software Foundation, Inc.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -20,7 +20,7 @@
#
# Written by Jim Meyering
-# This is a prologue that allows to run a perl script as an executable
+# This is a prologue that allows running a perl script as an executable
# on systems that are compliant to a POSIX version before POSIX:2017.
# On such systems, the usual invocation of an executable through execlp()
# or execvp() fails with ENOEXEC if it is a script that does not start
diff --git a/build-aux/gitlog-to-emacslog b/build-aux/gitlog-to-emacslog
index 73bf973dbb1..e9e9420fe40 100755
--- a/build-aux/gitlog-to-emacslog
+++ b/build-aux/gitlog-to-emacslog
@@ -2,7 +2,7 @@
# Convert git log output to ChangeLog format for GNU Emacs.
-# Copyright (C) 2014-2023 Free Software Foundation, Inc.
+# Copyright (C) 2014-2024 Free Software Foundation, Inc.
# Author: Paul Eggert
diff --git a/build-aux/make-info-dir b/build-aux/make-info-dir
index 64cf2d43f16..703abc7bd0a 100755
--- a/build-aux/make-info-dir
+++ b/build-aux/make-info-dir
@@ -2,7 +2,7 @@
### make-info-dir - create info/dir, for systems without install-info
-## Copyright (C) 2013-2023 Free Software Foundation, Inc.
+## Copyright (C) 2013-2024 Free Software Foundation, Inc.
## Author: Glenn Morris <rgm@gnu.org>
## Maintainer: emacs-devel@gnu.org
diff --git a/build-aux/makecounter.sh b/build-aux/makecounter.sh
index 3bebd288031..a63fcbb7c61 100755
--- a/build-aux/makecounter.sh
+++ b/build-aux/makecounter.sh
@@ -2,7 +2,7 @@
# Generate or update a C file containing an increasing counter
# variable.
#
-# Copyright (C) 2023 Free Software Foundation, Inc.
+# 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
diff --git a/build-aux/move-if-change b/build-aux/move-if-change
index 93839108fd9..18a720735cd 100755
--- a/build-aux/move-if-change
+++ b/build-aux/move-if-change
@@ -8,7 +8,7 @@ VERSION='2018-03-07 03:47'; # UTC
# If you change this file with Emacs, please let the write hook
# do its job. Otherwise, update this string manually.
-# Copyright (C) 2002-2023 Free Software Foundation, Inc.
+# Copyright (C) 2002-2024 Free Software Foundation, Inc.
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
diff --git a/build-aux/msys-to-w32 b/build-aux/msys-to-w32
index 53bc60da55e..5d8eac4cf20 100755
--- a/build-aux/msys-to-w32
+++ b/build-aux/msys-to-w32
@@ -2,7 +2,7 @@
# Convert a MSYS path list to Windows-native format.
# Status is zero if successful, nonzero otherwise.
-# Copyright (C) 2013-2023 Free Software Foundation, Inc.
+# Copyright (C) 2013-2024 Free Software Foundation, Inc.
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
diff --git a/build-aux/ndk-build-helper-1.mk b/build-aux/ndk-build-helper-1.mk
index 2cde5146301..5681728154c 100644
--- a/build-aux/ndk-build-helper-1.mk
+++ b/build-aux/ndk-build-helper-1.mk
@@ -1,5 +1,5 @@
# ndk-build-helper-1.mk -- Helper for ndk-build.m4.
-# Copyright (C) 2023 Free Software Foundation, Inc.
+# 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
diff --git a/build-aux/ndk-build-helper-2.mk b/build-aux/ndk-build-helper-2.mk
index 186f3aec333..1c2409cfd57 100644
--- a/build-aux/ndk-build-helper-2.mk
+++ b/build-aux/ndk-build-helper-2.mk
@@ -1,5 +1,5 @@
# ndk-build-helper-2.mk -- Helper for ndk-build.m4.
-# Copyright (C) 2023 Free Software Foundation, Inc.
+# 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
diff --git a/build-aux/ndk-build-helper-3.mk b/build-aux/ndk-build-helper-3.mk
index 4d0358d4f77..e360a347bb4 100644
--- a/build-aux/ndk-build-helper-3.mk
+++ b/build-aux/ndk-build-helper-3.mk
@@ -1,5 +1,5 @@
# ndk-build-helper-3.mk -- Helper for ndk-build.m4.
-# Copyright (C) 2023 Free Software Foundation, Inc.
+# 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
diff --git a/build-aux/ndk-build-helper-4.mk b/build-aux/ndk-build-helper-4.mk
index a41679c53af..54f781bdbaa 100644
--- a/build-aux/ndk-build-helper-4.mk
+++ b/build-aux/ndk-build-helper-4.mk
@@ -1,4 +1,4 @@
-# Copyright (C) 2023 Free Software Foundation, Inc.
+# 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
diff --git a/build-aux/ndk-build-helper.mk b/build-aux/ndk-build-helper.mk
index 05f0af76411..521e1b24ce3 100644
--- a/build-aux/ndk-build-helper.mk
+++ b/build-aux/ndk-build-helper.mk
@@ -1,5 +1,5 @@
# ndk-build-helper.mk -- Helper for ndk-build.m4.
-# Copyright (C) 2023 Free Software Foundation, Inc.
+# 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
diff --git a/build-aux/update-copyright b/build-aux/update-copyright
index 0343eaa72c1..6d56e48fdb1 100755
--- a/build-aux/update-copyright
+++ b/build-aux/update-copyright
@@ -3,7 +3,7 @@
# Update an FSF copyright year list to include the current year.
-# Copyright (C) 2009-2023 Free Software Foundation, Inc.
+# Copyright (C) 2009-2024 Free Software Foundation, Inc.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -123,7 +123,7 @@
# 5. Set UPDATE_COPYRIGHT_HOLDER if the copyright holder is other
# than "Free Software Foundation, Inc.".
-# This is a prologue that allows to run a perl script as an executable
+# This is a prologue that allows running a perl script as an executable
# on systems that are compliant to a POSIX version before POSIX:2017.
# On such systems, the usual invocation of an executable through execlp()
# or execvp() fails with ENOEXEC if it is a script that does not start
diff --git a/build-aux/update-subdirs b/build-aux/update-subdirs
index 275b2d37cac..6279e8c12ff 100755
--- a/build-aux/update-subdirs
+++ b/build-aux/update-subdirs
@@ -1,7 +1,7 @@
#!/bin/sh
# Write into $1/subdirs.el a list of subdirs of directory $1.
-# Copyright (C) 1994-1995, 1997, 1999, 2001-2023 Free Software
+# Copyright (C) 1994-1995, 1997, 1999, 2001-2024 Free Software
# Foundation, Inc.
# This file is part of GNU Emacs.
diff --git a/config.bat b/config.bat
index edea9610803..f63da88303c 100644
--- a/config.bat
+++ b/config.bat
@@ -1,7 +1,7 @@
@echo off
rem ----------------------------------------------------------------------
rem Configuration script for MSDOS
-rem Copyright (C) 1994-1999, 2001-2023 Free Software Foundation, Inc.
+rem Copyright (C) 1994-1999, 2001-2024 Free Software Foundation, Inc.
rem This file is part of GNU Emacs.
diff --git a/configure.ac b/configure.ac
index f92339225b5..90b3cde0d18 100644
--- a/configure.ac
+++ b/configure.ac
@@ -4,7 +4,7 @@ dnl autoconf
dnl in the directory containing this script.
dnl If you changed any AC_DEFINES, also run autoheader.
dnl
-dnl Copyright (C) 1994-1996, 1999-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 1994-1996, 1999-2024 Free Software Foundation, Inc.
dnl
dnl This file is part of GNU Emacs.
dnl
@@ -306,7 +306,7 @@ AC_DEFUN([OPTION_DEFAULT_OFF], [dnl
dnl OPTION_DEFAULT_IFAVAILABLE(NAME, HELP-STRING)
dnl Create a new --with option that defaults to 'ifavailable',
-dnl unless it is overriden by $with_features being equal to 'no'.
+dnl unless it is overridden by $with_features being equal to 'no'.
dnl NAME is the base name of the option. The shell variable with_NAME
dnl will be set to either the user's value (if the option is
dnl specified; 'yes' for a plain --with-NAME) or to 'ifavailable' (if the
@@ -941,7 +941,7 @@ a valid path to android.jar. See config.log for more details.])
fi
AC_CACHE_CHECK([whether android.jar is new enough],
- [emacs_cv_android_s_or_later],
+ [emacs_cv_android_u_or_later],
AS_IF([rm -f conftest.class
cat << EOF > conftest.java
@@ -949,18 +949,18 @@ import android.os.Build;
class conftest
{
- private static int test = Build.VERSION_CODES.TIRAMISU;
+ private static int test = Build.VERSION_CODES.UPSIDE_DOWN_CAKE;
}
EOF
("$JAVAC" -classpath "$with_android" -target 1.7 -source 1.7 conftest.java \
-d . >&AS_MESSAGE_LOG_FD 2>&1) && test -s conftest.class && rm -f conftest.class],
- [emacs_cv_android_s_or_later=yes],
- [emacs_cv_android_s_or_later=no]))
+ [emacs_cv_android_u_or_later=yes],
+ [emacs_cv_android_u_or_later=no]))
- if test "$emacs_cv_android_s_or_later" = "no"; then
+ if test "$emacs_cv_android_u_or_later" = "no"; then
AC_MSG_ERROR([Emacs must be built with an android.jar file produced for \
-Android 13 (Tiramisu) or later.])
+Android 14 (Upside Down Cake) or later.])
fi
dnl See if the Java compiler supports the `--release' option which
@@ -1152,6 +1152,8 @@ main (void)
foo = "emacs_api_32";
#elif __ANDROID_API__ < 34
foo = "emacs_api_33";
+#elif __ANDROID_API__ < 35
+ foo = "emacs_api_34";
#else
foo = "emacs_api_future";
#endif
@@ -1318,6 +1320,7 @@ if test "$ANDROID" = "yes"; then
with_mailutils=no
with_pop=no
with_harfbuzz=no
+ with_native_compilation=no
fi
with_rsvg=no
@@ -1664,13 +1667,13 @@ AC_ARG_ENABLE([gcc-warnings],
# however, if there is also a .tarball-version file it is probably
# just a release imported into Git for patch management.
gl_gcc_warnings=no
- if test -d "$srcdir"/.git && test ! -f "$srcdir"/.tarball-version; then
- # Clang typically identifies itself as GCC 4.2 or something similar
- # even if it is recent enough to accept the warnings we enable.
- AS_IF([test "$emacs_cv_clang" = yes],
- [gl_gcc_warnings=warn-only],
- [gl_GCC_VERSION_IFELSE([5], [3], [gl_gcc_warnings=warn-only])])
- fi])
+ AS_IF([test -d "$srcdir"/.git || test -f "$srcdir"/.git],
+ [AS_IF([test -f "$srcdir"/.tarball-version], [],
+ # Clang typically identifies itself as GCC 4.2 or something similar
+ # even if it is recent enough to accept the warnings we enable.
+ [AS_IF([test "$emacs_cv_clang" = yes],
+ [gl_gcc_warnings=warn-only],
+ [gl_GCC_VERSION_IFELSE([5], [3], [gl_gcc_warnings=warn-only])])])])])
NATIVE_COMPILATION_AOT=no
AC_ARG_WITH([native-compilation],
@@ -1691,7 +1694,7 @@ AC_ARG_WITH([native-compilation],
*) AC_MSG_ERROR([bad value $withval for native-compilation option]) ;;
esac
with_native_compilation=$withval],
- [with_native_compilation=no]
+ [with_native_compilation=default]
)
AC_SUBST([NATIVE_COMPILATION_AOT])
@@ -1713,7 +1716,6 @@ AS_IF([test $gl_gcc_warnings = no],
AS_IF([test "$emacs_cv_clang" = yes],
[
# Turn off some warnings if supported.
- gl_WARN_ADD([-Wno-switch])
gl_WARN_ADD([-Wno-pointer-sign])
gl_WARN_ADD([-Wno-string-plus-int])
gl_WARN_ADD([-Wno-unknown-attributes])
@@ -5076,20 +5078,20 @@ AC_DEFUN([libgccjit_smoke_test], [
return 0;
}]])])
-AC_DEFUN([libgccjit_not_found], [
+AC_DEFUN([libgccjit_not_found_err], [
AC_MSG_ERROR([ELisp native compiler was requested, but libgccjit was not found.
Please try installing libgccjit or a similar package.
If you are sure you want Emacs be compiled without ELisp native compiler,
pass the --without-native-compilation option to configure.])])
-AC_DEFUN([libgccjit_dev_not_found], [
+AC_DEFUN([libgccjit_dev_not_found_err], [
AC_MSG_ERROR([ELisp native compiler was requested, but libgccjit header files were
not found.
Please try installing libgccjit-dev or a similar package.
If you are sure you want Emacs be compiled without ELisp native compiler,
pass the --without-native-compilation option to configure.])])
-AC_DEFUN([libgccjit_broken], [
+AC_DEFUN([libgccjit_broken_err], [
AC_MSG_ERROR([The installed libgccjit failed to compile and run a test program using
the libgccjit library; see config.log for the details of the failure.
The test program can be found here:
@@ -5114,6 +5116,58 @@ If you really want to try it anyway, use the configure option
fi
fi
+AC_DEFUN([libgccjit_not_found], [
+ AC_MSG_WARN([Elisp native compiler can't be enabled as libgccjit was not
+found.
+Please try installing libgccjit or a similar package if you want to have it
+enabled.])
+
+ with_native_compilation=no
+])
+
+AC_DEFUN([libgccjit_dev_not_found], [
+ AC_MSG_WARN([Elisp native compiler can't be enabled as libgccjit header files
+were not found.
+Please try installing libgccjit-dev or a similar package if you want to have it
+enabled.])
+
+ with_native_compilation=no
+])
+
+AC_DEFUN([libgccjit_broken], [
+ AC_MSG_WARN([Elisp native compiler can't be enabled as the installed libgccjit
+failed to compile and run a test program using the libgccjit library; see
+config.log for the details of the failure.
+The test program can be found here:
+<https://gcc.gnu.org/onlinedocs/jit/intro/tutorial01.html>.
+You can try compiling it yourself to investigate the issues.
+Please report the issue to your distribution if libgccjit was installed
+through that.
+You can find the instructions on how to compile and install libgccjit from
+source on this site:
+<https://gcc.gnu.org/wiki/JIT>.])
+
+ with_native_compilation=no])
+
+if test "$with_features" = "no" \
+ && test "${with_native_compilation}" = "default"; then
+ with_native_compilation=no
+fi
+
+if test "${with_native_compilation}" = "default"; then
+ # Check if libgccjit is available.
+ AC_CHECK_LIB([gccjit], [gcc_jit_context_acquire],
+ [], [libgccjit_not_found])
+ AC_CHECK_HEADERS([libgccjit.h], [], [libgccjit_dev_not_found])
+ if test "${with_native_compilation}" != "no"; then
+ # Check if libgccjit really works.
+ AC_RUN_IFELSE([libgccjit_smoke_test], [], [libgccjit_broken])
+ fi
+ if test "$with_unexec" = yes; then
+ with_native_compilation=no
+ fi
+fi
+
if test "${with_native_compilation}" != "no"; then
if test "$with_unexec" = yes; then
AC_MSG_ERROR(['--with-native-compilation' is not compatible with unexec])
@@ -5161,18 +5215,22 @@ if test "${with_native_compilation}" != "no"; then
fi
fi
- # Check if libgccjit is available.
- AC_CHECK_LIB([gccjit], [gcc_jit_context_acquire],
- [], [libgccjit_not_found])
- AC_CHECK_HEADERS([libgccjit.h], [], [libgccjit_dev_not_found])
- # Check if libgccjit really works.
- AC_RUN_IFELSE([libgccjit_smoke_test], [], [libgccjit_broken])
+ # In the default case we already checked
+ if test "${with_native_compilation}" != "default"; then
+ # Check if libgccjit is available.
+ AC_CHECK_LIB([gccjit], [gcc_jit_context_acquire],
+ [], [libgccjit_not_found_err])
+ AC_CHECK_HEADERS([libgccjit.h], [], [libgccjit_dev_not_found_err])
+ # Check if libgccjit really works.
+ AC_RUN_IFELSE([libgccjit_smoke_test], [], [libgccjit_broken_err])
+ fi
HAVE_NATIVE_COMP=yes
case "${opsys}" in
# mingw32 loads the library dynamically.
mingw32) ;;
- # OpenBSD doesn't have libdl, all the functions are in libc
- netbsd|openbsd)
+ # Neither NetBSD, OpenBSD nor Haiku have libdl, with all dynamic
+ # linker functions placed within libc.
+ netbsd|openbsd|haiku)
LIBGCCJIT_LIBS="-lgccjit" ;;
darwin)
LIBGCCJIT_CFLAGS="${MAC_CFLAGS}"
@@ -6263,7 +6321,7 @@ AC_FUNC_FORK
dnl AC_CHECK_FUNCS_ONCE wouldn’t be right for snprintf, which needs
dnl the current CFLAGS etc.
-AC_CHECK_FUNCS([snprintf])
+AC_CHECK_FUNCS([snprintf open_memstream])
dnl posix_spawn. The chdir and setsid functionality is relatively
dnl recent, so we check for it specifically.
@@ -6513,7 +6571,7 @@ case $opsys in
esac
case $opsys in
- gnu-* | solaris | cygwin )
+ gnu-* | android | solaris | cygwin )
dnl FIXME Can't we test if this exists (eg /proc/$$)?
AC_DEFINE([HAVE_PROCFS], [1], [Define if you have the /proc filesystem.])
;;
@@ -7034,7 +7092,7 @@ fi
version=$PACKAGE_VERSION
-copyright="Copyright (C) 2023 Free Software Foundation, Inc."
+copyright="Copyright (C) 2024 Free Software Foundation, Inc."
AC_DEFINE_UNQUOTED([COPYRIGHT], ["$copyright"],
[Short copyright string for this version of Emacs.])
AC_SUBST([copyright])
diff --git a/cross/Makefile.in b/cross/Makefile.in
index b66025283aa..6f2250fe02f 100644
--- a/cross/Makefile.in
+++ b/cross/Makefile.in
@@ -1,6 +1,6 @@
### @configure_input@
-# Copyright (C) 2023 Free Software Foundation, Inc.
+# Copyright (C) 2023-2024 Free Software Foundation, Inc.
# This file is part of GNU Emacs.
diff --git a/cross/langinfo.h b/cross/langinfo.h
index b296ba8db80..0edb0082bda 100644
--- a/cross/langinfo.h
+++ b/cross/langinfo.h
@@ -1,6 +1,6 @@
/* Replacement langinfo.h file for building GNU Emacs on Android.
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/cross/ndk-build/Makefile.in b/cross/ndk-build/Makefile.in
index cdf18471ff3..8ba2d356f27 100644
--- a/cross/ndk-build/Makefile.in
+++ b/cross/ndk-build/Makefile.in
@@ -1,6 +1,6 @@
### @configure_input@
-# Copyright 2023 Free Software Foundation, Inc.
+# Copyright 2023-2024 Free Software Foundation, Inc.
# This file is part of GNU Emacs.
diff --git a/cross/ndk-build/README b/cross/ndk-build/README
index aca2e7230bf..84a131443c4 100644
--- a/cross/ndk-build/README
+++ b/cross/ndk-build/README
@@ -1,6 +1,6 @@
NDK BUILD SYSTEM IMPLEMENTATION
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
See the end of the file for license conditions.
Emacs implements ndk-build itself, because the version that comes with
@@ -86,7 +86,7 @@ $(ANDROID_MAKEFILE), the ``Android.mk'' file, for the first time. The
purpose of this evaluation is to establish a list of packages (or
modules) provided by the ``Android.mk'' file, and the corresponding
Makefile targets and compiler and linker flags required to build and
-link to those tagets.
+link to those targets.
Before doing so, build-aux/ndk-build-helper.mk will define several
variables and functions required by all ``Android.mk'' files. The
@@ -164,7 +164,7 @@ module_cxx_deps=""
module_imports=""
which is then evaluated by `configure'. Once the variable
-`module_name' is set, configure apends the remaining
+`module_name' is set, configure appends the remaining
$(module_includes), $(module_cflags) and $(module_ldflags) to the
module's CFLAGS and LIBS variables, and appends the list of Makefile
targets specified to the variable NDK_BUILD_MODULES.
diff --git a/cross/ndk-build/ndk-build-executable.mk b/cross/ndk-build/ndk-build-executable.mk
index 9591c862b18..4f520074c7f 100644
--- a/cross/ndk-build/ndk-build-executable.mk
+++ b/cross/ndk-build/ndk-build-executable.mk
@@ -1,4 +1,4 @@
-# Copyright 2023 Free Software Foundation, Inc.
+# Copyright 2023-2024 Free Software Foundation, Inc.
# This file is part of GNU Emacs.
diff --git a/cross/ndk-build/ndk-build-shared-library.mk b/cross/ndk-build/ndk-build-shared-library.mk
index d60802da1d0..74c6756a0c1 100644
--- a/cross/ndk-build/ndk-build-shared-library.mk
+++ b/cross/ndk-build/ndk-build-shared-library.mk
@@ -1,4 +1,4 @@
-# Copyright 2023 Free Software Foundation, Inc.
+# Copyright 2023-2024 Free Software Foundation, Inc.
# This file is part of GNU Emacs.
diff --git a/cross/ndk-build/ndk-build-static-library.mk b/cross/ndk-build/ndk-build-static-library.mk
index 98afd864ed6..aba4539f6bb 100644
--- a/cross/ndk-build/ndk-build-static-library.mk
+++ b/cross/ndk-build/ndk-build-static-library.mk
@@ -1,4 +1,4 @@
-# Copyright 2023 Free Software Foundation, Inc.
+# Copyright 2023-2024 Free Software Foundation, Inc.
# This file is part of GNU Emacs.
diff --git a/cross/ndk-build/ndk-build.mk.in b/cross/ndk-build/ndk-build.mk.in
index 57006901721..6c85ff5044e 100644
--- a/cross/ndk-build/ndk-build.mk.in
+++ b/cross/ndk-build/ndk-build.mk.in
@@ -1,6 +1,6 @@
### @configure_input@
-# Copyright (C) 2023 Free Software Foundation, Inc.
+# Copyright (C) 2023-2024 Free Software Foundation, Inc.
# This file is part of GNU Emacs.
diff --git a/cross/ndk-build/ndk-clear-vars.mk b/cross/ndk-build/ndk-clear-vars.mk
index 7309b7bb513..0803522f3d4 100644
--- a/cross/ndk-build/ndk-clear-vars.mk
+++ b/cross/ndk-build/ndk-clear-vars.mk
@@ -1,4 +1,4 @@
-# Copyright 2023 Free Software Foundation, Inc.
+# Copyright 2023-2024 Free Software Foundation, Inc.
# This file is part of GNU Emacs.
diff --git a/cross/ndk-build/ndk-prebuilt-shared-library.mk b/cross/ndk-build/ndk-prebuilt-shared-library.mk
index 2a8260f9851..d63ca4a0c76 100644
--- a/cross/ndk-build/ndk-prebuilt-shared-library.mk
+++ b/cross/ndk-build/ndk-prebuilt-shared-library.mk
@@ -1,6 +1,6 @@
### @configure_input@
-# Copyright 2023 Free Software Foundation, Inc.
+# Copyright 2023-2024 Free Software Foundation, Inc.
# This file is part of GNU Emacs.
diff --git a/cross/ndk-build/ndk-prebuilt-static-library.mk b/cross/ndk-build/ndk-prebuilt-static-library.mk
index 9230f690bb1..94c98435d5f 100644
--- a/cross/ndk-build/ndk-prebuilt-static-library.mk
+++ b/cross/ndk-build/ndk-prebuilt-static-library.mk
@@ -1,6 +1,6 @@
### @configure_input@
-# Copyright 2023 Free Software Foundation, Inc.
+# Copyright 2023-2024 Free Software Foundation, Inc.
# This file is part of GNU Emacs.
diff --git a/cross/ndk-build/ndk-resolve.mk b/cross/ndk-build/ndk-resolve.mk
index b29a2c6dc39..d3b398bca62 100644
--- a/cross/ndk-build/ndk-resolve.mk
+++ b/cross/ndk-build/ndk-resolve.mk
@@ -1,4 +1,4 @@
-# Copyright 2023 Free Software Foundation, Inc.
+# Copyright 2023-2024 Free Software Foundation, Inc.
# This file is part of GNU Emacs.
diff --git a/cross/verbose.mk.android b/cross/verbose.mk.android
index d41d6b6aac0..958cf237c58 100644
--- a/cross/verbose.mk.android
+++ b/cross/verbose.mk.android
@@ -1,7 +1,7 @@
### verbose.mk --- Makefile fragment for GNU Emacs during
### cross-compilation.
-## Copyright (C) 2023 Free Software Foundation, Inc.
+## Copyright (C) 2023-2024 Free Software Foundation, Inc.
## This file is part of GNU Emacs.
diff --git a/doc/emacs/ChangeLog.1 b/doc/emacs/ChangeLog.1
index 1cf26aeff06..e1de11c5540 100644
--- a/doc/emacs/ChangeLog.1
+++ b/doc/emacs/ChangeLog.1
@@ -1294,7 +1294,7 @@
* display.texi (Visual Line Mode): Fix index entry.
- * buffers.texi (Several Buffers): List Buffer Menu command anmes,
+ * buffers.texi (Several Buffers): List Buffer Menu command names,
and index the keybindings. Document tabulated-list-sort.
(Kill Buffer): Capitalize Buffer Menu.
@@ -5771,7 +5771,7 @@
Add view-external-packages on C-h C-e.
Add view-order-manuals on C-h C-m.
-2008-02-17 Ulrich Mueller <ulm@kph.uni-mainz.de>
+2008-02-17 Ulrich Müller <ulm@kph.uni-mainz.de>
* msdog-xtra.texi (MS-DOS): Docstring fix.
@@ -6443,7 +6443,7 @@
2007-01-01 Richard Stallman <rms@gnu.org>
- * commands.texi (User Input): Document keys stolen by window mangers.
+ * commands.texi (User Input): Document keys stolen by window managers.
2006-12-31 Richard Stallman <rms@gnu.org>
@@ -10919,7 +10919,7 @@
;; coding: utf-8
;; End:
- Copyright (C) 1993-1999, 2001-2023 Free Software Foundation, Inc.
+ Copyright (C) 1993-1999, 2001-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/doc/emacs/Makefile.in b/doc/emacs/Makefile.in
index c7415312753..4c51e2277ae 100644
--- a/doc/emacs/Makefile.in
+++ b/doc/emacs/Makefile.in
@@ -1,6 +1,6 @@
### @configure_input@
-# Copyright (C) 1994, 1996-2023 Free Software Foundation, Inc.
+# Copyright (C) 1994, 1996-2024 Free Software Foundation, Inc.
# This file is part of GNU Emacs.
diff --git a/doc/emacs/abbrevs.texi b/doc/emacs/abbrevs.texi
index 3678377e9b5..a00837fe7d0 100644
--- a/doc/emacs/abbrevs.texi
+++ b/doc/emacs/abbrevs.texi
@@ -1,5 +1,5 @@
@c This is part of the Emacs manual.
-@c Copyright (C) 1985--1987, 1993--1995, 1997, 2001--2023 Free Software
+@c Copyright (C) 1985--1987, 1993--1995, 1997, 2001--2024 Free Software
@c Foundation, Inc.
@c See file emacs.texi for copying conditions.
@node Abbrevs
@@ -275,6 +275,8 @@ Edit a list of abbrevs; you can add, alter or remove definitions.
@example
@var{various other tables@dots{}}
+(python-mode-skeleton-abbrev-table)
+"class" (sys) 0 "" python-skeleton-class
(lisp-mode-abbrev-table)
"ks" 0 "keymap-set"
(global-abbrev-table)
@@ -297,11 +299,14 @@ keeps track of this to help you see which abbrevs you actually use, so
that you can eliminate those that you don't use often. The string at
the end of the line is the expansion.
- Some abbrevs are marked with @samp{(sys)}. These @dfn{system abbrevs}
-(@pxref{Abbrevs,,, elisp, The Emacs Lisp Reference Manual}) are
-pre-defined by various modes, and are not saved to your abbrev file.
-To disable a system abbrev, define an abbrev of the same name that
-expands to itself, and save it to your abbrev file.
+ Some abbrevs are marked with @samp{(sys)}. These @dfn{system
+abbrevs} (@pxref{Abbrevs,,, elisp, The Emacs Lisp Reference Manual})
+are pre-defined by various modes, and are not saved to your abbrev
+file. To disable a system abbrev, define an abbrev of the same name
+that expands to itself, and save it to your abbrev file. The system
+abbrevs have an associated hook function, which is called to perform
+the abbrev expansion; the name of that function follows the abbrev
+expansion in the buffer shown by @code{list-abbrevs}.
@findex edit-abbrevs
@kindex C-c C-c @r{(Edit Abbrevs)}
diff --git a/doc/emacs/ack.texi b/doc/emacs/ack.texi
index 4a8a2a24377..62f6382113e 100644
--- a/doc/emacs/ack.texi
+++ b/doc/emacs/ack.texi
@@ -1,6 +1,6 @@
@c -*- coding: utf-8 -*-
@c This is part of the Emacs manual.
-@c Copyright (C) 1994--1997, 1999--2023 Free Software Foundation, Inc.
+@c Copyright (C) 1994--1997, 1999--2024 Free Software Foundation, Inc.
@c See file emacs.texi for copying conditions.
@c
@node Acknowledgments
@@ -525,7 +525,7 @@ browser to display a URL.
@item
Lars Magne Ingebrigtsen was the Emacs (co-)maintainer from Emacs 27.2
-onwards. He did a major redesign of the Gnus news-reader and wrote
+to 29.1. He did a major redesign of the Gnus news-reader and wrote
many of its parts. Several of these are now general components of
Emacs, including: @file{dns.el} for Domain Name Service lookups;
@file{format-spec.el} for formatting arbitrary format strings;
@@ -591,6 +591,9 @@ Tomoji Kagatani implemented @file{smtpmail.el}, used for sending out
mail with SMTP.
@item
+Stefan Kangas was the Emacs (co-)maintainer from 29.2 onwards.
+
+@item
Ivan Kanis wrote @file{vc-hg.el}, support for the Mercurial version
control system.
@@ -903,6 +906,11 @@ Thomas Neumann and Eric S. Raymond wrote @file{make-mode.el},
a mode for editing makefiles.
@item
+Thien-Thi Nguyen wrote the @samp{xpm}, @samp{gnugo}, and
+@samp{ascii-art-to-unicode} packages. He also made substantial
+contributions to many others, such as @file{vc.el}.
+
+@item
Thien-Thi Nguyen and Dan Nicolaescu wrote @file{hideshow.el}, a minor
mode for selectively displaying blocks of text.
@@ -1379,9 +1387,9 @@ Rodney Whitby and Reto Zimmermann wrote @file{vhdl-mode.el}, a major
mode for editing VHDL source code.
@item
-John Wiegley was the Emacs maintainer from Emacs 25 onwards. He wrote
-@file{align.el}, a set of commands for aligning text according to
-regular-expression based rules; @file{isearchb.el} for fast buffer
+John Wiegley was the Emacs (co-)maintainer from Emacs 25 to 29.1. He
+wrote @file{align.el}, a set of commands for aligning text according
+to regular-expression based rules; @file{isearchb.el} for fast buffer
switching; @file{timeclock.el}, a package for keeping track of time
spent on projects; the Bahá'í calendar support; @file{pcomplete.el}, a
programmable completion facility; @file{remember.el}, a mode for
diff --git a/doc/emacs/android.texi b/doc/emacs/android.texi
index cee5406b840..0ea96d91492 100644
--- a/doc/emacs/android.texi
+++ b/doc/emacs/android.texi
@@ -1,5 +1,5 @@
@c This is part of the Emacs manual.
-@c Copyright (C) 2023 Free Software Foundation, Inc.
+@c Copyright (C) 2023--2024 Free Software Foundation, Inc.
@c See file emacs.texi for copying conditions.
@node Android
@appendix Emacs and Android
@@ -9,9 +9,9 @@
Alliance. This section describes the peculiarities of using Emacs on
an Android device running Android 2.2 or later.
- Android devices commonly rely on user input through a touch screen
-or digitizer device and on-screen keyboard. For more information
-about using such devices with Emacs, @pxref{Other Input Devices}.
+ Android devices commonly rely a touch screen or digitizer device and
+virtual keyboard for user input. For more information about using
+such devices with Emacs, @pxref{Other Input}.
@menu
* What is Android?:: Preamble.
@@ -129,8 +129,7 @@ buffer.
Since there is no other way to start the @command{emacsclient}
program (@pxref{Emacs Server}) from another Android program, Emacs
provides a wrapper around the @command{emacsclient} program, which is
-registered with the system as an application that can open all text
-files.
+registered with the system as an application that can open any file.
When that wrapper is selected as the program with which to open a
file, it invokes @command{emacsclient} with the options
@@ -154,6 +153,18 @@ directory, or try to open files in it yourself.
case such files are copied to a temporary directory before being
opened.
+@cindex ``org-protocol'' links, android
+ In addition to opening ordinary text files, Emacs also registers its
+@command{emacsclient} wrapper as a program capable of opening
+``org-protocol'' links (@pxref{Protocols,,,org, The Org Manual}).
+
+@cindex ``mailto'' links, android
+ Furthermore, the wrapper is also registered as a program capable of
+sending mail to @code{mailto} URIs; when it is invoked to open such a
+URL, it calls the function @code{message-mailto} with that URI as its
+first argument. This feature does not function when the Emacs server
+is not already running.
+
@node Android File System
@section What Files Emacs Can Access on Android
@cindex /assets directory, android
@@ -223,7 +234,7 @@ Document Providers}.)
the (normally read-only) root directory named @file{content} or
@file{assets}, you may want to access real files by these names if the
Android installation in use has been customized. These files will
-conflict with the aformentioned special directories, but can
+conflict with the aforementioned special directories, but can
nevertheless be accessed by writing their names relative to the
``parent'' directory of the root directory, as so illustrated:
@file{/../content}, @file{/../assets}.
@@ -247,7 +258,7 @@ at startup to symlink the application library directory to its
traditional location within the parent of the app data directory.
If Emacs is reinstalled and the location of the app library
-directory consequentially changes, that symlink will also be updated
+directory consequently changes, that symlink will also be updated
to point to its new location the next time Emacs is started by the
system.
@@ -293,7 +304,7 @@ provide, placing their files within the directory
@file{/content/storage}.
@findex android-request-directory-access
- Before Emacs is granted access to any of these directories, it must
+ Before Emacs is granted access to one of these directories, it must
first request the right to access it. This is done by running the
command (@pxref{M-x}) @code{android-request-directory-access}, which
displays a file selection dialog.
@@ -322,39 +333,39 @@ time.
From the perspective of users, Android is mostly a single user
operating system; however, from the perspective of applications and
-Emacs, the system has an overwhelming number of users.
+Emacs, the system is host to an overwhelming number of users.
Each application runs in its own user, with its home directory set
to its app data directory (@pxref{Android File
System}.)@footnote{Except in cases where a ``shared user ID'' is
specified and other applications signed using the same ``package
signing key'' are installed, in which case Emacs runs as the same user
-and has access to the same files as each of the aformentioned
+and has access to the same files as each of the aforementioned
applications.}
Each application is also prohibited from accessing many system
directories and the app data directories of other applications.
- Emacs comes with several binaries. While being executable files,
-they are packaged as libraries in the library directory, because
-otherwise the system will not unpack them while Emacs is being
-installed. This means, instead of specifying @code{ctags} or
-@code{emacsclient} in a subprocess, Lisp code must specify
-@code{libctags.so} or @code{libemacsclient.so} on the command line
-instead when starting either of those programs in a subprocess; to
-determine which names to use, consult the values of the variables
-@code{ctags-program-name}, @code{etags-program-name},
-@code{hexl-program-name}, @code{emacsclient-program-name},
-@code{movemail-program-name}, and @code{ebrowse-program-name}.
+ The Emacs distribution also incorporates several binaries. While
+being executable files, they are packaged as libraries in the library
+directory, because otherwise the system will not unpack them while
+Emacs is being installed. This means that instead of @code{ctags} or
+@code{emacsclient}, Lisp code must specify @code{libctags.so} or
+@code{libemacsclient.so} on the command line when starting either of
+those programs in a subprocess; to determine which names to use,
+consult the values of the variables @code{ctags-program-name},
+@code{etags-program-name}, @code{hexl-program-name},
+@code{emacsclient-program-name}, @code{movemail-program-name},
+@code{ebrowse-program-name}, and @code{rcs2log-program-name}.
@xref{Subprocess Creation,,, elisp, the Emacs Lisp Reference Manual}.
The @file{/assets} directory containing Emacs start-up files is
-supposed to be inaccessible to processes not directly created by
+meant to be inaccessible to processes not directly created by
@code{zygote}, the system service responsible for starting
applications. Since required Lisp is found in the @file{/assets}
directory, it would thus follow that it is not possible for Emacs to
start itself as a subprocess. A special binary named
-@command{libandroid-emacs.so} is provided with Emacs, and does its
+@command{libandroid-emacs.so} is provided with Emacs, which tries its
best to start Emacs for the purpose of running Lisp in batch mode.
However, the approach it takes was devised by reading Android source
code, and is not sanctioned by the Android compatibility definition
@@ -363,33 +374,32 @@ documents, so your mileage may vary.
@cindex call-process, Android
@vindex android-use-exec-loader
Android 10 and later also prohibit Emacs itself from running
-executables inside the app data directory, obstensibly for security
-reasons. On these systems, Emacs normally applies a workaround;
+executables inside the app data directory, ostensibly out of security
+concerns. On these systems, Emacs normally applies a workaround;
however, this workaround requires running all sub-processes through
another subprocess which implements an executable loader and applies
-process tracing to all its children, which may prove to be problematic
-for various different reasons. In that case, the workaround can be
-disabled by changing the variable @code{android-use-exec-loader} to
-@code{nil}.
+process tracing to all its children, which may prove problematic for a
+variety of reasons. In that case, the workaround can be disabled by
+changing the variable @code{android-use-exec-loader} to @code{nil}.
When this workaround is in effect, process IDs retrieved through the
@code{process-id} function will be that of the executable loader
process; its child will belong to the same process group as the
-loader. As a result, @code{interrupt-process}, and other related
+loader. Consequently, @code{interrupt-process}, and other related
functions will work correctly, but using the process ID returned by
@code{process-id} for other purposes will not.
- One side effect of the mechanism by which process tracing is carried
-out is that job control facilities inside inferior shells
+ One ramification of the mechanism by which process tracing is
+carried out is that job control facilities inside inferior shells
(@pxref{Interactive Shell}) will not be able to stop processes, and
-sending the @code{SIGSTOP} signal to a subprocess created by Emacs
-will appear to have no effect.
+@code{SIGSTOP} signals to subprocesses created by Emacs will not take
+effect.
In addition, Android 12 also terminates subprocesses which are
consuming CPU while Emacs itself is in the background. The system
-determines which processes are consuming too much CPU in intervals of
-five minutes, and terminates the process that has consumed the most
-CPU time.
+judges which processes are consuming too much CPU at intervals of five
+minutes, and terminates the process that has consumed the most CPU
+time.
Android 12.1 and Android 13 provide an option to disable this
behavior; to use it, enable ``USB debugging'' (@pxref{Android
@@ -399,6 +409,24 @@ Startup}) connect the Android system to another computer, and run:
$ adb shell "settings put global settings_enable_monitor_phantom_procs false"
@end example
+@cindex system language settings, Android
+ The ``Languages & Input'' preferences which apply to the operating
+system do not influence the C locale set for programs, but are taken
+into account by Emacs during startup: a locale name is generated from
+the selected language and regional variant and a language environment
+(@pxref{Language Environments}) is selected on that basis, which does
+not overwrite @code{LANG} or other locale-related environment
+variables. The coding system for language environments set in this
+fashion is @code{utf-8-unix} without exception.
+
+@cindex C locale settings, Android
+ Instead, the @code{LANG} environment variable (@pxref{General
+Variables}) is set to @code{en_US.utf8} when Emacs starts on Android
+5.0 or newer, which induces subprocesses linked against the Android C
+library to print output sensibly. Earlier versions of Android do not
+implement locales at all, and on that account, the variable is set to
+@code{C}.
+
@cindex running emacs in the background, android
@cindex emacs killed, android
@cindex emacs in the background, android
@@ -408,25 +436,31 @@ system. When all Emacs frames move to the background, Emacs might be
terminated by the system at any time, for the purpose of saving system
resources.
- On Android 7.1 and earlier, Emacs tells the system to treat it as a
-``background service''. The system will try to avoid killing Emacs
-unless the system is stressed for memory.
+ On Android 7.1 and earlier, Emacs designates itself a ``background
+service'', which impels the system to avoid killing Emacs unless it is
+stressed for memory.
Android 8.0 removed the ability for background services to receive
such special treatment. However, Emacs applies a workaround: the
system considers applications that create a permanent notification to
be performing active work, and will avoid killing such applications.
Thus, on those systems, Emacs displays a permanent notification for as
-long as it is running. Once the notification is displayed, it can be
-safely hidden through the system settings without resulting in Emacs
-being killed.
-
- However, it is not guaranteed that the system will not kill Emacs
-even if a notification is being displayed. While the Open Handset
-Alliance's sample implementation of Android behaves correctly, many
-manufacturers place additional restrictions on program execution in
-the background in their proprietary versions of Android. There is a
-list of such troublesome manufacturers and sometimes workarounds at
+long as it is running.
+
+ Before Android 13, Emacs does not require rights to display
+notifications. Under Android 13 or later, the notification is hidden
+until the user accords Emacs such rights. In spite of that, merely
+attempting to display the notification suffices to avert sudden death;
+whether the notification is displayed has no bearing on Emacs's
+capacity to execute in the background, and it may be disabled without
+any adverse consequences.
+
+ However, it is not guaranteed that the system will not kill Emacs.
+Although the Open Handset Alliance's sample implementation of Android
+behaves correctly, many manufacturers institute additional
+restrictions on program execution in the background in their
+proprietary versions of Android. There is a list of such troublesome
+manufacturers and sometimes workarounds at
@url{https://dontkillmyapp.com/}.
@cindex permissions under android
@@ -434,11 +468,41 @@ list of such troublesome manufacturers and sometimes workarounds at
Android also defines a permissions system that determines what
system services Emacs is allowed to access. Programs must specify
-what permissions they want; what then happens depends on the version
-of Android being used:
+what permissions they want; what then happens is then subject to the
+version of Android being used:
@itemize @bullet
@item
+Under more or less recent releases of Android, such as Android 6.0 and
+later, Emacs only receives the following permissions upon
+installation:
+
+@itemize @minus
+@item
+@code{android.permission.VIBRATE}
+@item
+@code{android.permission.ACCESS_NETWORK_STATE}
+@item
+@code{android.permission.INTERNET}
+@item
+@code{android.permission.SET_WALLPAPER}
+@item
+@code{android.permission.NFC}
+@item
+@code{android.permission.TRANSMIT_IR}
+@item
+@code{android.permission.WAKE_LOCK}
+@item
+@code{android.permission.FOREGROUND_SERVICE}
+@item
+@code{android.permission.FOREGROUND_SERVICE_SPECIAL_USE}
+@end itemize
+
+Other permissions must be granted by the user through the system
+settings application. Consult the manufacturer of your device for
+more details, as how to do this varies by device.
+
+@item
On Android 5.1 and earlier, Emacs automatically receives the following
permissions it has requested upon being installed:
@@ -458,6 +522,10 @@ permissions it has requested upon being installed:
@item
@code{android.permission.SET_WALLPAPER}
@item
+@code{android.permission.READ_CALENDAR}
+@item
+@code{android.permission.WRITE_CALENDAR}
+@item
@code{android.permission.READ_EXTERNAL_STORAGE}
@item
@code{android.permission.WRITE_EXTERNAL_STORAGE}
@@ -498,48 +566,23 @@ permissions it has requested upon being installed:
While most of these permissions are left unused by Emacs itself, they
are declared by Emacs as they could be useful for other programs; for
example, the permission to access contacts may be useful for EUDC.
-
-@item
-On Android 6.0 and later, Emacs only receives the following
-permissions upon installation:
-
-@itemize @minus
-@item
-@code{android.permission.VIBRATE}
-@item
-@code{android.permission.ACCESS_NETWORK_STATE}
-@item
-@code{android.permission.INTERNET}
-@item
-@code{android.permission.SET_WALLPAPER}
-@item
-@code{android.permission.NFC}
-@item
-@code{android.permission.TRANSMIT_IR}
-@item
-@code{android.permission.WAKE_LOCK}
-@end itemize
-
-Other permissions must be granted by the user through the system
-settings application. Consult the manufacturer of your device for
-more details, as how to do this varies by device.
@end itemize
@node Android Windowing
@section The Android Window System
- Android has an unusual window system; there, all windows are
+ Android's window system is unusual, in that all windows are
maximized or full-screen, and only one window can be displayed at a
-time. On larger devices, the system allows up to four windows to be
-tiled on the screen at any time.
+time. On larger devices, the system permits simultaneously tiling up
+to four windows on the screen.
- Windows on Android do not continue to exist indefinitely after they
-are created. Instead, the system may choose to close windows that are
-not on screen in order to save memory, with the assumption that the
-program will save its contents to disk and restore them later, when
-the user asks for it to be opened again. As this is obviously not
-possible with Emacs, Emacs separates the resources associated with a
-frame from its system window.
+ Windows on Android do not exist indefinitely after they are created.
+Instead, the system may choose to close windows that are not on screen
+in order to conserve memory, with the assumption that the program will
+save its contents to disk and restore them later, when the user asks
+for it to be opened again. As this is obviously not possible with
+Emacs, Emacs separates the resources associated with a frame from its
+system window.
Each system window created (including the initial window created
during Emacs startup) is appended to a list of windows that do not
@@ -640,22 +683,20 @@ volume buttons in that case.
@cindex dialog boxes, android
Emacs is unable to display dialog boxes (@pxref{Dialog Boxes}) while
it does not have the input focus on Android 6.0 or later. If this is
-important to you, this ability can be restored by granting Emacs
-permission to display over other programs. Normally, this can be done
-from the:
+important to you, this capability can be restored by granting Emacs
+permission to display over other programs. On most systems, this can
+be done from the following Settings menu:
@example
System -> Apps -> Emacs -> More -> Display over other apps
@end example
-menu in the system settings, but this procedure may vary by device.
-
@cindex keyboard modifiers, android
There is a direct relation between physical modifier keys and Emacs
modifiers (@pxref{Modifier Keys}) reported within key events, subject
to a single exception: if @key{Alt} on your keyboard is depressed,
then the @key{Meta} modifier will be reported by Emacs in its place,
-and vice versa. This irregularity is since most keyboards posses no
+and vice versa. This irregularity is since most keyboards possess no
special @key{Meta} key, and the @key{Alt} modifier is seldom employed
in Emacs.
@@ -663,12 +704,34 @@ in Emacs.
modifier: it is referred to as @key{SYM} on Android keyboards and
within the Settings keymap menu.
+@vindex android-intercept-control-space
+@cindex @kbd{C-SPC} interception, android
+ Android input methods have a penchant for irritating users by
+silently discarding key sequences containing @kbd{C-SPC} during the
+event filtering process, that they normally have no real application
+for such key sequences notwithstanding. By default, Emacs intercepts
+these key sequences before they can be filtered by the input method.
+
+ If this proves unwanted (for instance, if the input method treats
+@kbd{C-SPC} as a shortcut key for switching languages), it can be
+disabled by setting the variable
+@code{android-intercept-control-space} to @code{nil}.
+
+@vindex android-keyboard-bell-duration
+@cindex keyboard bell, android
+ The keyboard bell installed within Android systems takes the form of
+a vibrating element that is activated for a number of milliseconds
+whenever the bell is rung. The duration of this vibration can be
+customized through altering the variable
+@code{android-keyboard-bell-duration} to any value between @code{10}
+and @code{1000}.
+
@node Android Fonts
@section Font Backends and Selection under Android
@cindex fonts, android
- Emacs supports two font backends under Android: they are respectively
-named @code{sfnt-android} and @code{android}.
+ Emacs supports two font backends under Android: they are
+respectively named @code{sfnt-android} and @code{android}.
Upon startup, Emacs enumerates all the TrueType format fonts in the
directories @file{/system/fonts} and @file{/product/fonts}, and the
@@ -677,17 +740,17 @@ home directory. Emacs assumes there will always be a font named
``Droid Sans Mono'', and then defaults to using this font. These
fonts are then displayed by the @code{sfnt-android} font driver.
- When running on Android, Emacs currently lacks support for OpenType
-fonts. This means that only a subset of the fonts installed on the
-system are currently available to Emacs. If you are interested in
-lifting this limitation, please contact @email{emacs-devel@@gnu.org}.
+ This font driver is presently without support for OpenType fonts;
+hence, only a subset of the fonts installed on any given system are
+available to Emacs. If you are interested in lifting this limitation,
+please contact @email{emacs-devel@@gnu.org}.
If the @code{sfnt-android} font driver fails to find any fonts at
all, Emacs falls back to the @code{android} font driver. This is a
-very lousy font driver, because of limitations and inaccuracies in the
-font metrics provided by the Android platform. In that case, Emacs
-uses the ``Monospace'' typeface configured on your system; this should
-always be Droid Sans Mono.
+very poor font driver, consequent upon limitations and inaccuracies in
+the font metrics provided by the Android platform. In that case,
+Emacs uses the ``Monospace'' typeface configured on your system; this
+should always be Droid Sans Mono.
@cindex TrueType GX fonts, android
@cindex distortable fonts, android
@@ -695,7 +758,7 @@ always be Droid Sans Mono.
As on X systems, Emacs supports distortable fonts under Android.
These fonts (also termed ``TrueType GX fonts'', ``variable fonts'',
and ``multiple master fonts'') provide multiple different styles
-(``Bold'', ``Italic'', etc) using a single font file.
+(``Bold'', ``Italic'', and the like) using a single font file.
When a user-installed distortable font is found, each style that a
previously discovered font provided will no longer be used. In
@@ -707,6 +770,22 @@ conventional font with the same style and family will be removed;
distortable fonts with the same family will no longer be used to
provide that style.
+@cindex default font families, Android
+@vindex sfnt-default-family-alist
+
+ Emacs generally assumes the presence of font families named
+@samp{Monospace}, @samp{Monospace Serif}, @samp{Sans Serif}, and
+@samp{DejaVu Serif}. Since Android does not provide any fonts by
+these names, Emacs modifies requests for them to request one of a
+corresponding set of font families distributed with Android.
+
+ To change either the set of font families subject to replacement, or
+that by which they are replaced, modify the variable
+@code{sfnt-default-family-alist}; then, restart Emacs. Bear in mind
+that this is usually unwarranted, with customizations to the default
+or @code{variable-pitch} faces better made through modifying their
+definitions (@pxref{Face Customization}).
+
@node Android Troubleshooting
@section Troubleshooting Startup Problems on Android
@cindex troubleshooting, android
@@ -716,8 +795,8 @@ provide that style.
Since Android has no command line, there is normally no way to
specify command-line arguments when starting Emacs. This is very
nasty when you make a mistake in your Emacs initialization files that
-prevents Emacs from starting up at all, as the system normally
-prevents other programs from accessing Emacs's home directory.
+prevents Emacs from starting up at all, as the system generally
+prohibits other programs from accessing Emacs's home directory.
@xref{Initial Options}.
However, Emacs can be started with the equivalent of either the
@@ -760,11 +839,12 @@ your initialization or dump files from there instead.
@cindex installing extra software on Android
@cindex installing Unix software on Android
- Android includes an extremely limited set of Unix-like command line
-tools in a default installation. Several projects exist to argument
-this selection, providing options that range from improved
-reproductions of Unix command-line utilities to package repositories
-containing extensive collections of free GNU and Unix software.
+ An exceptionally limited set of Unix-like command line tools is
+distributed alongside default installations of Android. Several
+projects exist to augment this selection, providing options that range
+from improved reproductions of Unix command-line utilities to package
+repositories providing extensive collections of free GNU and Unix
+software.
@uref{http://busybox.net, Busybox} provides Unix utilities and
limited replicas of certain popular GNU programs such as
@@ -776,17 +856,17 @@ on the Debian project's @command{dpkg} system and a set of package
repositories containing substantial amounts of free software for Unix
systems, including compilers, debuggers, and runtimes for languages
such as C, C++, Java, Python and Common Lisp. These packages are
-normally installed from within a purpose-built terminal emulator
-application, but Emacs can access them if it is built with the same
-application signing key as the Termux terminal emulator, and with its
-``shared user ID'' set to the package name of the terminal emulator
-program. The @file{java/INSTALL} within the Emacs distribution
-explains how to build Emacs in this fashion.
+customarily installed from within a purpose-built terminal emulator
+application, but access is also granted to Emacs when it is built with
+the same application signing key, and its ``shared user ID'' is set to
+the same package name, as that of the terminal emulator program. The
+file @file{java/INSTALL} within the Emacs distribution illustrates how
+to build Emacs in this fashion.
@uref{https://github.com/termux/termux-packages, termux-packages}
-provides the package definitions that are used by Termux to generate
-their package repositories, which may also be independently compiled
-for installation within Emacs's home directory.
+provides the package definitions used by Termux to generate their
+package repositories, which may also be independently compiled for
+installation within Emacs's home directory.
In addition to the projects mentioned above, statically linked
binaries for most Linux kernel-based systems can also be run on
diff --git a/doc/emacs/anti.texi b/doc/emacs/anti.texi
index b25d8a8e3cc..7abb504632b 100644
--- a/doc/emacs/anti.texi
+++ b/doc/emacs/anti.texi
@@ -1,6 +1,6 @@
@c -*- coding: utf-8 -*-
@c This is part of the Emacs manual.
-@c Copyright (C) 2005--2023 Free Software Foundation, Inc.
+@c Copyright (C) 2005--2024 Free Software Foundation, Inc.
@c See file emacs.texi for copying conditions.
@node Antinews
diff --git a/doc/emacs/arevert-xtra.texi b/doc/emacs/arevert-xtra.texi
index 9dc1d3b5fb7..621804ced85 100644
--- a/doc/emacs/arevert-xtra.texi
+++ b/doc/emacs/arevert-xtra.texi
@@ -1,5 +1,5 @@
@c This is part of the Emacs manual.
-@c Copyright (C) 2004--2023 Free Software Foundation, Inc.
+@c Copyright (C) 2004--2024 Free Software Foundation, Inc.
@c See file emacs.texi for copying conditions.
@c
@c This file is included either in emacs-xtra.texi (when producing the
diff --git a/doc/emacs/back.texi b/doc/emacs/back.texi
index 49b116df72d..b8094c6cf36 100644
--- a/doc/emacs/back.texi
+++ b/doc/emacs/back.texi
@@ -1,6 +1,6 @@
\input texinfo @c -*-texinfo-*-
@c This is part of the Emacs manual.
-@c Copyright (C) 1985--1987, 1993--1995, 1997, 2001--2023 Free Software
+@c Copyright (C) 1985--1987, 1993--1995, 1997, 2001--2024 Free Software
@c Foundation, Inc.
@c See file emacs.texi for copying conditions.
@c
diff --git a/doc/emacs/basic.texi b/doc/emacs/basic.texi
index a271cb65bdc..f64b3995d25 100644
--- a/doc/emacs/basic.texi
+++ b/doc/emacs/basic.texi
@@ -1,6 +1,6 @@
@c -*- coding: utf-8 -*-
@c This is part of the Emacs manual.
-@c Copyright (C) 1985--1987, 1993--1995, 1997, 2000--2023 Free Software
+@c Copyright (C) 1985--1987, 1993--1995, 1997, 2000--2024 Free Software
@c Foundation, Inc.
@c See file emacs.texi for copying conditions.
@node Basic
@@ -360,15 +360,15 @@ preserve the horizontal position, as usual.
@vindex line-move-visual
When a line of text in the buffer is longer than the width of the
-window, Emacs usually displays it on two or more @dfn{screen lines}.
-For convenience, @kbd{C-n} and @kbd{C-p} move point by screen lines,
-as do the equivalent keys @kbd{@key{down}} and @kbd{@key{up}}. You
-can force these commands to move according to @dfn{logical lines}
-(i.e., according to the text lines in the buffer) by setting the
-variable @code{line-move-visual} to @code{nil}; if a logical line
-occupies multiple screen lines, the cursor then skips over the
-additional screen lines. For details, see @ref{Continuation Lines}.
-@xref{Variables}, for how to set variables such as
+window, Emacs usually displays it on two or more @dfn{screen lines},
+a.k.a.@: @dfn{visual lines}. For convenience, @kbd{C-n} and @kbd{C-p}
+move point by screen lines, as do the equivalent keys @kbd{@key{down}}
+and @kbd{@key{up}}. You can force these commands to move according to
+@dfn{logical lines} (i.e., according to the text lines in the buffer)
+by setting the variable @code{line-move-visual} to @code{nil}; if a
+logical line occupies multiple screen lines, the cursor then skips
+over the additional screen lines. For details, see @ref{Continuation
+Lines}. @xref{Variables}, for how to set variables such as
@code{line-move-visual}.
Unlike @kbd{C-n} and @kbd{C-p}, most of the Emacs commands that work
@@ -596,10 +596,13 @@ lines, if any exists.
@cindex wrapping
@cindex line wrapping
@cindex fringes, and continuation lines
+@cindex logical line
+@cindex screen line
+@cindex visual line
Sometimes, a line of text in the buffer---a @dfn{logical line}---is
too long to fit in the window, and Emacs displays it as two or more
-@dfn{screen lines}. This is called @dfn{line wrapping} or
-@dfn{continuation}, and the long logical line is called a
+@dfn{screen lines}, or @dfn{visual lines}. This is called @dfn{line
+wrapping} or @dfn{continuation}, and the long logical line is called a
@dfn{continued line}. On a graphical display, Emacs indicates line
wrapping with small bent arrows in the left and right window fringes.
On a text terminal, Emacs indicates line wrapping by displaying a
diff --git a/doc/emacs/buffers.texi b/doc/emacs/buffers.texi
index b6aafe24b96..8b093078edd 100644
--- a/doc/emacs/buffers.texi
+++ b/doc/emacs/buffers.texi
@@ -1,5 +1,5 @@
@c This is part of the Emacs manual.
-@c Copyright (C) 1985--1987, 1993--1995, 1997, 2000--2023 Free Software
+@c Copyright (C) 1985--1987, 1993--1995, 1997, 2000--2024 Free Software
@c Foundation, Inc.
@c See file emacs.texi for copying conditions.
@node Buffers
@@ -728,7 +728,7 @@ rule or another is easier for you to remember and apply quickly.
@findex icomplete-mode
@cindex Icomplete mode
- Icomplete global minor mode provides a convenient way to quickly select an
+ Icomplete mode provides a convenient way to quickly select an
element among the possible completions in a minibuffer. When enabled, typing
in the minibuffer continuously displays a list of possible completions that
match the string you have typed.
@@ -746,9 +746,28 @@ further. This is typically used when entering a file name, where
@kbd{M-@key{TAB}} can be used a few times to descend in the hierarchy
of directories.
- To enable Icomplete mode, type @kbd{M-x icomplete-mode}, or customize
-the variable @code{icomplete-mode} to @code{t} (@pxref{Easy
-Customization}).
+ To enable Icomplete mode for the minibuffer, type @kbd{M-x
+icomplete-mode}, or customize the variable @code{icomplete-mode} to
+@code{t} (@pxref{Easy Customization}).
+
+ You can also additionally enable Icomplete mode for @kbd{C-M-i} (the
+command @code{completion-at-point}) by customizing the variable
+@code{icomplete-in-buffer} to @code{t}. For in-buffer completion, the
+@code{completion-auto-help} variable controls when Icomplete mode's
+display of possible completions appears. The default value of
+@code{t} means that the display of possible completions appears when
+you first type @kbd{C-M-i}.
+
+ By default, when you press @kbd{C-M-i}, both Icomplete mode's
+in-buffer display of possible completions and the @file{*Completions*}
+buffer appear. If you are using @code{icomplete-in-buffer}, then you
+may wish to suppress this apperance of the @file{*Completions*}
+buffer. To do that, add the following to your initialization file
+(@pxref{Init File}):
+
+@example
+(advice-add 'completion-at-point :after #'minibuffer-hide-completions)
+@end example
@findex fido-mode
@cindex fido mode
diff --git a/doc/emacs/building.texi b/doc/emacs/building.texi
index f82b605598e..38cc0bb67af 100644
--- a/doc/emacs/building.texi
+++ b/doc/emacs/building.texi
@@ -1,5 +1,5 @@
@c This is part of the Emacs manual.
-@c Copyright (C) 1985--1987, 1993--1995, 1997, 2000--2023 Free Software
+@c Copyright (C) 1985--1987, 1993--1995, 1997, 2000--2024 Free Software
@c Foundation, Inc.
@c See file emacs.texi for copying conditions.
@node Building
@@ -567,7 +567,7 @@ see the Flymake Info manual, which is distributed with Emacs.
The GUD (Grand Unified Debugger) library provides an Emacs interface
to a wide variety of symbolic debuggers. It can run the GNU Debugger
-(GDB), as well as DBX, SDB, XDB, Guile REPL debug commands, Perl's
+(GDB), as well as LLDB, DBX, SDB, XDB, Guile REPL debug commands, Perl's
debugging mode, the Python debugger PDB, and the Java Debugger JDB.
Emacs provides a special interface to GDB, which uses extra Emacs
@@ -609,6 +609,10 @@ exists, switch to it; otherwise, create the buffer and switch to it.
The other commands in this list do the same, for other debugger
programs.
+@item M-x lldb
+@findex lldb
+Run the LLDB debugger.
+
@item M-x perldb
@findex perldb
Run the Perl interpreter in debug mode.
@@ -698,10 +702,23 @@ which edited source line corresponds to the line reported by the
debugger subprocess. To update this information, you typically have
to recompile and restart the program.
+@cindex GUD and hl-line-mode
+@cindex highlighting execution lines in GUD
+@vindex gud-highlight-current-line
+ Moreover, GUD is capable of visually demarcating the current
+execution line within the window text itself in one of two fashions:
+the first takes effect when the user option
+@code{gud-highlight-current-line} is enabled, and displays that line
+in an overlay whose appearance is provided by the face
+@code{gud-highlight-current-line-face}. The other takes effect when
+HL Line Mode (@pxref{Cursor Display}) is enabled, and moves the
+overlay introduced by HL Line Mode briefly to the execution line,
+until a subsequent editing command repositions it back beneath the
+cursor.
+
@cindex GUD Tooltip mode
@cindex mode, GUD Tooltip
@findex gud-tooltip-mode
-@vindex gud-tooltip-echo-area
GUD Tooltip mode is a global minor mode that adds tooltip support to
GUD@. To toggle this mode, type @kbd{M-x gud-tooltip-mode}. It is
disabled by default. If enabled, you can move the mouse pointer over a
@@ -713,10 +730,8 @@ you can tell Emacs more explicitly what expression to evaluate by
dragging the mouse over the expression, then leaving the mouse inside
the marked area. The GUD Tooltip mode takes effect in the GUD
interaction buffer, and in all source buffers with major modes listed
-in the variable @code{gud-tooltip-modes}. If the variable
-@code{gud-tooltip-echo-area} is non-@code{nil}, or if you turned off
-the tooltip mode, values are shown in the echo area instead of a
-tooltip.
+in the variable @code{gud-tooltip-modes}. If you turned off the
+tooltip mode, values are shown in the echo area instead of a tooltip.
When using GUD Tooltip mode with @kbd{M-x gud-gdb}, displaying an
expression's value in GDB can sometimes expand a macro, potentially
diff --git a/doc/emacs/cal-xtra.texi b/doc/emacs/cal-xtra.texi
index f0341a2817d..49fa2e9547e 100644
--- a/doc/emacs/cal-xtra.texi
+++ b/doc/emacs/cal-xtra.texi
@@ -1,5 +1,5 @@
@c This is part of the Emacs manual. -*- coding: utf-8 -*-
-@c Copyright (C) 2004--2023 Free Software Foundation, Inc.
+@c Copyright (C) 2004--2024 Free Software Foundation, Inc.
@c See file emacs.texi for copying conditions.
@c
@c This file is included either in emacs-xtra.texi (when producing the
diff --git a/doc/emacs/calendar.texi b/doc/emacs/calendar.texi
index 7b5b1b78fc9..7312cfb34c9 100644
--- a/doc/emacs/calendar.texi
+++ b/doc/emacs/calendar.texi
@@ -1,5 +1,5 @@
@c This is part of the Emacs manual. -*- coding: utf-8 -*-
-@c Copyright (C) 1985--1987, 1993--1995, 1997, 2000--2023 Free Software
+@c Copyright (C) 1985--1987, 1993--1995, 1997, 2000--2024 Free Software
@c Foundation, Inc.
@c See file emacs.texi for copying conditions.
@node Calendar/Diary
diff --git a/doc/emacs/cmdargs.texi b/doc/emacs/cmdargs.texi
index 9514e3414e1..49810ee7693 100644
--- a/doc/emacs/cmdargs.texi
+++ b/doc/emacs/cmdargs.texi
@@ -1,5 +1,5 @@
@c This is part of the Emacs manual.
-@c Copyright (C) 1985--1987, 1993--1995, 1997, 2001--2023 Free Software
+@c Copyright (C) 1985--1987, 1993--1995, 1997, 2001--2024 Free Software
@c Foundation, Inc.
@c See file emacs.texi for copying conditions.
@node Emacs Invocation
@@ -309,6 +309,9 @@ This is like @samp{--script}, but suppresses loading the init files
reaches the end of the script, it exits Emacs and uses the value of
the final form as the exit value from the script (if the final value
is numerical). Otherwise, it will always exit with a zero value.
+Note that when Emacs reads the Lisp code in this case, it ignores any
+file-local variables (@pxref{Specifying File Variables}), both in the
+first line and in a local-variables section near the end of the file.
@item --no-build-details
@opindex --no-build-details
@@ -637,6 +640,11 @@ set this in the ``Regional Settings'' Control Panel on some versions
of MS-Windows, and in the ``Language and Region'' System Preference on
macOS.
+When running a GUI session on Android, @env{LANG} is set to a fixed
+value, but the language and locale environment is derived from the
+system's ``Languages & Input'' preferences. @xref{Android
+Environment}.
+
The value of the @env{LC_CTYPE} category is
matched against entries in @code{locale-language-names},
@code{locale-charset-language-names}, and
diff --git a/doc/emacs/commands.texi b/doc/emacs/commands.texi
index 98f0610ee44..a8f89feed62 100644
--- a/doc/emacs/commands.texi
+++ b/doc/emacs/commands.texi
@@ -1,5 +1,5 @@
@c This is part of the Emacs manual.
-@c Copyright (C) 1985--1987, 1993--1995, 1997, 2001--2023 Free Software
+@c Copyright (C) 1985--1987, 1993--1995, 1997, 2001--2024 Free Software
@c Foundation, Inc.
@c See file emacs.texi for copying conditions.
@iftex
@@ -227,6 +227,8 @@ until you are interested in customizing them. Then read the basic
information on variables (@pxref{Variables}) and the information about
specific variables will make sense.
+@include input.texi
+
@ifnottex
@lowersections
@end ifnottex
diff --git a/doc/emacs/custom.texi b/doc/emacs/custom.texi
index 456e2087217..9c8558c93a1 100644
--- a/doc/emacs/custom.texi
+++ b/doc/emacs/custom.texi
@@ -1,6 +1,6 @@
@c -*- coding: utf-8 -*-
@c This is part of the Emacs manual.
-@c Copyright (C) 1985--1987, 1993--1995, 1997, 2000--2023 Free Software
+@c Copyright (C) 1985--1987, 1993--1995, 1997, 2000--2024 Free Software
@c Foundation, Inc.
@c See file emacs.texi for copying conditions.
@node Customization
@@ -626,7 +626,7 @@ button.
the theme file and asks if you really want to load it. Because
loading a Custom theme can execute arbitrary Lisp code, you should
only say yes if you know that the theme is safe; in that case, Emacs
-offers to remember in the future that the theme is safe(this is done
+offers to remember in the future that the theme is safe (this is done
by saving the theme file's SHA-256 hash to the variable
@code{custom-safe-themes}; if you want to treat all themes as safe,
change its value to @code{t}). Themes that come with Emacs (in the
@@ -1507,7 +1507,18 @@ mode or subdirectory, and for variable and value, and adds the
entry defining the directory-local variable. @kbd{M-x
delete-dir-local-variable} deletes an entry. @kbd{M-x
copy-file-locals-to-dir-locals} copies the file-local variables in the
-current file into @file{.dir-locals.el}.
+current file into @file{.dir-locals.el}, or @file{.dir-locals-2.el} if
+that file is also present.
+
+With a prefix argument, all three commands prompt for the file you
+want to modify. Although it doesn't have to exist, you must enter a
+valid filename, either @file{.dir-locals.el} or
+@file{.dir-locals-2.el}.
+
+@findex customize-dirlocals
+There's also a command to pop up an Easy Customization buffer
+(@pxref{Easy Customization}) to edit directory local variables,
+@code{customize-dirlocals}.
@findex dir-locals-set-class-variables
@findex dir-locals-set-directory-class
@@ -1591,6 +1602,10 @@ discriminate for the properties @code{:protocol} (this is the Tramp
method) or @code{:user} (a remote user name). The @code{nil} criteria
matches all buffers with a remote default directory.
+ Be careful when declaring different profiles with the same variable,
+and setting these profiles to criteria which could match in parallel.
+It is unspecified which variable value is used then.
+
@node Key Bindings
@section Customizing Key Bindings
@cindex key bindings
@@ -1992,8 +2007,8 @@ the one for @kbd{C-c C-x x} in Texinfo mode:
(keymap-set texinfo-mode-map "C-c p"
'backward-paragraph)
(keymap-set texinfo-mode-map "C-c n"
- 'forward-paragraph)))
- (keymap-set texinfo-mode-map "C-c C-x x" nil)
+ 'forward-paragraph)
+ (keymap-set texinfo-mode-map "C-c C-x x" nil)))
@end example
@node Modifier Keys
@@ -2050,7 +2065,7 @@ C-a} is a way to enter @kbd{Hyper-Control-a}. (Unfortunately, there
is no way to add two modifiers by using @kbd{C-x @@} twice for the
same character, because the first one goes to work on the @kbd{C-x}.)
You can similarly enter the Shift, Control, and Meta modifiers by
-using @kbd{C-x @ S}, @kbd{C-x @ c}, and @kbd{C-x @ m}, respectively,
+using @kbd{C-x @@ S}, @kbd{C-x @@ c}, and @kbd{C-x @@ m}, respectively,
although this is rarely needed.
@node Function Keys
@@ -2924,6 +2939,7 @@ Type @kbd{C-q}, followed by the key you want to bind, to insert @var{char}.
@node Early Init File
@subsection The Early Init File
@cindex early init file
+@cindex @file{early-init.el} file
Most customizations for Emacs should be put in the normal init file.
@xref{Init File}. However, it is sometimes necessary
diff --git a/doc/emacs/dired-xtra.texi b/doc/emacs/dired-xtra.texi
index 04b5ed44ed1..12cba1345b9 100644
--- a/doc/emacs/dired-xtra.texi
+++ b/doc/emacs/dired-xtra.texi
@@ -1,5 +1,5 @@
@c This is part of the Emacs manual.
-@c Copyright (C) 2004--2023 Free Software Foundation, Inc.
+@c Copyright (C) 2004--2024 Free Software Foundation, Inc.
@c See file emacs.texi for copying conditions.
@c
@c This file is included either in emacs-xtra.texi (when producing the
diff --git a/doc/emacs/dired.texi b/doc/emacs/dired.texi
index 87124e962ca..a3a740f9727 100644
--- a/doc/emacs/dired.texi
+++ b/doc/emacs/dired.texi
@@ -1,5 +1,5 @@
@c This is part of the Emacs manual.
-@c Copyright (C) 1985--1987, 1993--1995, 1997, 2000--2023 Free Software
+@c Copyright (C) 1985--1987, 1993--1995, 1997, 2000--2024 Free Software
@c Foundation, Inc.
@c See file emacs.texi for copying conditions.
@node Dired
@@ -142,6 +142,10 @@ characters well. If you have many such files, you may consider adding
special characters and allow Dired to handle them better. (You can
also use the @kbd{C-u C-x d} command to add @samp{-b} temporarily.)
+@code{dired-listing-switches} can be declared as connection-local
+variable to adjust it to match what a remote system expects
+(@pxref{Connection Variables}).
+
@vindex dired-switches-in-mode-line
Dired displays in the mode line an indication of what were the
switches used to invoke @command{ls}. By default, Dired will try to
diff --git a/doc/emacs/display.texi b/doc/emacs/display.texi
index fa8ca4cbf17..e6a43bf74a8 100644
--- a/doc/emacs/display.texi
+++ b/doc/emacs/display.texi
@@ -1,6 +1,6 @@
@c -*- coding: utf-8 -*-
@c This is part of the Emacs manual.
-@c Copyright (C) 1985--1987, 1993--1995, 1997, 2000--2023 Free Software
+@c Copyright (C) 1985--1987, 1993--1995, 1997, 2000--2024 Free Software
@c Foundation, Inc.
@c See file emacs.texi for copying conditions.
@@ -740,7 +740,7 @@ frame:
This is the base face used for the mode lines, as well as header lines
and for menu bars when toolkit menus are not used. By default, it's
drawn with shadows for a raised effect on graphical displays, and
-drawn as the inverse of the default face on non-windowed terminals.
+drawn as the inverse of the default face on text terminals.
The @code{mode-line-active} and @code{mode-line-inactive} faces (which
are the ones used on the mode lines) inherit from this face.
@@ -2010,9 +2010,10 @@ line truncation. @xref{Split Window}, for the variable
@section Visual Line Mode
@cindex word wrap
- Another alternative to ordinary line continuation is to use
-@dfn{word wrap}. Here, each long logical line is divided into two or
-more screen lines, like in ordinary line continuation. However, Emacs
+ Another alternative to ordinary line continuation
+(@pxref{Continuation Lines}) is to use @dfn{word wrap}. Here, each
+long logical line is divided into two or more screen lines, or
+``visual lines'', like in ordinary line continuation. However, Emacs
attempts to wrap the line at word boundaries near the right window
edge. (If the line's direction is right-to-left, it is wrapped at the
left window edge instead.) This makes the text easier to read, as
diff --git a/doc/emacs/emacs-xtra.texi b/doc/emacs/emacs-xtra.texi
index 066070262a7..442fe952075 100644
--- a/doc/emacs/emacs-xtra.texi
+++ b/doc/emacs/emacs-xtra.texi
@@ -16,7 +16,7 @@
@copying
This manual describes specialized features of Emacs.
-Copyright @copyright{} 2004--2023 Free Software Foundation, Inc.
+Copyright @copyright{} 2004--2024 Free Software Foundation, Inc.
@quotation
Permission is granted to copy, distribute and/or modify this document
diff --git a/doc/emacs/emacs.texi b/doc/emacs/emacs.texi
index 7a21eb49e24..7d77f13ab21 100644
--- a/doc/emacs/emacs.texi
+++ b/doc/emacs/emacs.texi
@@ -20,8 +20,7 @@ This is the @cite{GNU Emacs Manual},
@end ifclear
updated for Emacs version @value{EMACSVER}.
-Copyright @copyright{} 1985--1987, 1993--2023 Free Software Foundation,
-Inc.
+Copyright @copyright{} 1985--2024 Free Software Foundation, Inc.
@quotation
Permission is granted to copy, distribute and/or modify this document
@@ -150,6 +149,7 @@ Important General Concepts
editing action.
* Mouse Input:: Using the mouse and keypads.
* Commands:: Named functions run by key sequences to do editing.
+* Other Input:: Input besides the mouse, keyboard and keypads.
* Entering Emacs:: Starting Emacs from the shell.
* Exiting:: Stopping or killing Emacs.
@@ -225,7 +225,6 @@ Appendices
* Haiku:: Using Emacs on Haiku.
* Android:: Using Emacs on Android.
* Microsoft Windows:: Using Emacs on Microsoft Windows and MS-DOS.
-* Other Input Devices:: Using Emacs with other input devices.
* Manifesto:: What's GNU? Gnu's Not Unix!
* Glossary:: Terms used in this manual.
@@ -259,6 +258,10 @@ The Organization of the Screen
* Mode Line:: Interpreting the mode line.
* Menu Bar:: How to use the menu bar.
+Touchscreen Input and Virtual Keyboards
+* Touchscreens:: Interacting with Emacs from touchscreens.
+* On-Screen Keyboards:: Text input with virtual keyboards.
+
Basic Editing Commands
* Inserting Text:: Inserting text by simply typing it.
@@ -553,7 +556,7 @@ Frames and Graphical Displays
* Dialog Boxes:: Controlling use of dialog boxes.
* Tooltips:: Displaying information at the current mouse position.
* Mouse Avoidance:: Preventing the mouse pointer from obscuring text.
-* Non-Window Terminals:: Multiple frames on terminals that show only one.
+* Text Terminals:: Multiple frames on terminals that show only one.
* Text-Only Mouse:: Using the mouse in text terminals.
International Character Set Support
@@ -595,6 +598,7 @@ Indentation
* Tab Stops:: Stop points for indentation in Text modes.
* Just Spaces:: Using only space characters for indentation.
* Indent Convenience:: Optional indentation features.
+* Code Alignment:: Making common parts of lines start at the same column.
Commands for Human Languages
@@ -1274,11 +1278,6 @@ Emacs and Android
* Android Troubleshooting:: Dealing with problems.
* Android Software:: Getting extra software.
-Emacs and Unconventional Input Devices
-
-* Touchscreens:: Using Emacs on touchscreens.
-* On-Screen Keyboards:: Using Emacs with virtual keyboards.
-
Emacs and Microsoft Windows/MS-DOS
* Windows Startup:: How to start Emacs on Windows.
@@ -1652,7 +1651,6 @@ Lisp programming.
@include android.texi
@c Includes msdos-xtra.
@include msdos.texi
-@include input.texi
@include gnu.texi
@include glossary.texi
@ifnottex
diff --git a/doc/emacs/emerge-xtra.texi b/doc/emacs/emerge-xtra.texi
index 32392dde460..8d6df87b648 100644
--- a/doc/emacs/emerge-xtra.texi
+++ b/doc/emacs/emerge-xtra.texi
@@ -1,5 +1,5 @@
@c This is part of the Emacs manual.
-@c Copyright (C) 2004--2023 Free Software Foundation, Inc.
+@c Copyright (C) 2004--2024 Free Software Foundation, Inc.
@c See file emacs.texi for copying conditions.
@c
@c This file is included either in emacs-xtra.texi (when producing the
diff --git a/doc/emacs/entering.texi b/doc/emacs/entering.texi
index c23015ee10e..2dfc11a7b32 100644
--- a/doc/emacs/entering.texi
+++ b/doc/emacs/entering.texi
@@ -1,5 +1,5 @@
@c This is part of the Emacs manual.
-@c Copyright (C) 1985--1987, 1993--1995, 2001--2023 Free Software
+@c Copyright (C) 1985--1987, 1993--1995, 2001--2024 Free Software
@c Foundation, Inc.
@c See file emacs.texi for copying conditions.
@iftex
diff --git a/doc/emacs/files.texi b/doc/emacs/files.texi
index 7efb4516d15..9c5305acf60 100644
--- a/doc/emacs/files.texi
+++ b/doc/emacs/files.texi
@@ -1,5 +1,5 @@
@c This is part of the Emacs manual.
-@c Copyright (C) 1985--1987, 1993--1995, 1997, 1999--2023 Free Software
+@c Copyright (C) 1985--1987, 1993--1995, 1997, 1999--2024 Free Software
@c Foundation, Inc.
@c See file emacs.texi for copying conditions.
@node Files
@@ -547,6 +547,10 @@ buffer name with the buffer's default directory (@pxref{File Names}).
to that major mode, in most cases. The command
@code{set-visited-file-name} also does this. @xref{Choosing Modes}.
+ If you wish to save the current buffer to a different file without
+visiting that file, use @code{mark-whole-buffer} (@kbd{C-x h}), then
+@w{@kbd{M-x write-region}} (@pxref{Misc File Ops}).
+
If Emacs is about to save a file and sees that the date of the latest
version on disk does not match what Emacs last read or wrote, Emacs
notifies you of this fact, because it probably indicates a problem caused
@@ -1325,6 +1329,10 @@ directory listing describing the specified file and the auto-save file,
so you can compare their sizes and dates. If the auto-save file
is older, @kbd{M-x recover-file} does not offer to read it.
+When @kbd{M-x recover-file} asks for confirmation, if you answer with
+@kbd{diff} or @kbd{=}, it shows the diffs between @var{file} and its
+auto-save file @file{#@var{file}#} and reprompts you for confirmation.
+
@findex recover-session
If Emacs or the computer crashes, you can recover all the files you
were editing from their auto save files with the command @kbd{M-x
diff --git a/doc/emacs/fixit.texi b/doc/emacs/fixit.texi
index 78503d31a38..638cc46608c 100644
--- a/doc/emacs/fixit.texi
+++ b/doc/emacs/fixit.texi
@@ -1,5 +1,5 @@
@c This is part of the Emacs manual.
-@c Copyright (C) 1985--1987, 1993--1995, 1997, 2001--2023 Free Software
+@c Copyright (C) 1985--1987, 1993--1995, 1997, 2001--2024 Free Software
@c Foundation, Inc.
@c See file emacs.texi for copying conditions.
@node Fixit
@@ -295,8 +295,8 @@ Kill the spell-checker subprocess.
@item M-@key{TAB}
@itemx @key{ESC} @key{TAB}
@itemx C-M-i
-Complete the word before point based on the spelling dictionary
-(@code{ispell-complete-word}).
+Complete the word before point based on the spelling dictionary and
+other completion sources (@code{completion-at-point}).
@item M-x flyspell-mode
Enable Flyspell mode, which highlights all misspelled words.
@item M-x flyspell-prog-mode
@@ -398,14 +398,11 @@ Quit interactive spell-checking and kill the spell-checker subprocess.
Show the list of options.
@end table
-@findex ispell-complete-word
- In Text mode and related modes, @kbd{M-@key{TAB}}
-(@code{ispell-complete-word}) performs in-buffer completion based on
-spelling correction. Insert the beginning of a word, and then type
-@kbd{M-@key{TAB}}; this shows a list of completions. (If your
+ Use the command @kbd{M-@key{TAB}} (@code{completion-at-point}) to
+complete the word at point. Insert the beginning of a word, and then
+type @kbd{M-@key{TAB}} to select from a list of completions. (If your
window manager intercepts @kbd{M-@key{TAB}}, type @w{@kbd{@key{ESC}
-@key{TAB}}} or @kbd{C-M-i}.) Each completion is listed with a digit or
-character; type that digit or character to choose it.
+@key{TAB}}} or @kbd{C-M-i}.)
@cindex @code{ispell} program
@findex ispell-kill-ispell
diff --git a/doc/emacs/fortran-xtra.texi b/doc/emacs/fortran-xtra.texi
index 8e904cfbd28..5225dfccbd0 100644
--- a/doc/emacs/fortran-xtra.texi
+++ b/doc/emacs/fortran-xtra.texi
@@ -1,5 +1,5 @@
@c This is part of the Emacs manual.
-@c Copyright (C) 2004--2023 Free Software Foundation, Inc.
+@c Copyright (C) 2004--2024 Free Software Foundation, Inc.
@c See file emacs.texi for copying conditions.
@c
@c This file is included either in emacs-xtra.texi (when producing the
diff --git a/doc/emacs/frames.texi b/doc/emacs/frames.texi
index a968c2a97c5..8e6cbeed70b 100644
--- a/doc/emacs/frames.texi
+++ b/doc/emacs/frames.texi
@@ -1,6 +1,5 @@
@c This is part of the Emacs manual.
-@c Copyright (C) 1985--1987, 1993--1995, 1997, 1999--2023 Free Software
-@c Foundation, Inc.
+@c Copyright (C) 1985--2024 Free Software Foundation, Inc.
@c See file emacs.texi for copying conditions.
@node Frames
@chapter Frames and Graphical Displays
@@ -30,9 +29,9 @@ displays (@pxref{Exiting}). To close just the selected frame, type
frames. On text terminals, many of these features are unavailable.
However, it is still possible to create multiple frames on text
terminals; such frames are displayed one at a time, filling the entire
-terminal screen (@pxref{Non-Window Terminals}). It is also possible
-to use the mouse on some text terminals (@pxref{Text-Only Mouse}, for
-doing so on GNU and Unix systems; and
+terminal screen (@pxref{Text Terminals}). It is also possible to use
+the mouse on some text terminals (@pxref{Text-Only Mouse}, for doing
+so on GNU and Unix systems; and
@iftex
@pxref{MS-DOS Mouse,,,emacs-xtra,Specialized Emacs Features},
@end iftex
@@ -62,7 +61,7 @@ for doing so on MS-DOS). Menus are supported on all text terminals.
* Dialog Boxes:: Controlling use of dialog boxes.
* Tooltips:: Displaying information at the current mouse position.
* Mouse Avoidance:: Preventing the mouse pointer from obscuring text.
-* Non-Window Terminals:: Multiple frames on terminals that show only one.
+* Text Terminals:: Multiple frames on terminals that show only one.
* Text-Only Mouse:: Using the mouse in text terminals.
@end menu
@@ -593,7 +592,7 @@ the ordinary, interactive frames are deleted. In this case, @kbd{C-x
The @kbd{C-x 5 1} (@code{delete-other-frames}) command deletes all
other frames on the current terminal (this terminal refers to either a
-graphical display, or a text terminal; @pxref{Non-Window Terminals}).
+graphical display, or a text terminal; @pxref{Text Terminals}).
If the Emacs session has frames open on other graphical displays or
text terminals, those are not deleted.
@@ -1408,9 +1407,10 @@ the number of tabs created on each frame.
@findex toggle-frame-tab-bar
To toggle the use of the Tab Bar only on the selected frame, type
-@kbd{M-x toggle-frame-tab-bar}. This command allows to enable the
-display of the Tab Bar on some frames and disable it on others,
-regardless of the values of @code{tab-bar-mode} and @code{tab-bar-show}.
+@kbd{M-x toggle-frame-tab-bar}. This command facilitates selectively
+enabling the Tab Bar on some frames while keeping it disabled on
+others, irrespective of the values of @code{tab-bar-mode} and
+@code{tab-bar-show}.
@kindex C-x t
The prefix key @kbd{C-x t} is analogous to @kbd{C-x 5}.
@@ -1586,14 +1586,13 @@ the items that operate on the clicked tab. Dragging the tab with
wheel scrolling switches to the next or previous tab. Holding down
the @key{SHIFT} key during scrolling moves the tab to the left or right.
- Touch screen input (@pxref{Other Input Devices}) can also be used to
-operate on tabs. Long-pressing (@pxref{Touchscreens}) a tab will
-display a context menu with items that operate on the tab that was
-pressed, and long-pressing the tab bar itself will display a context
-menu which lets you create and remove tabs; tapping a tab itself will
-result in that tab's window configuration being selected, and tapping
-a button on the tab bar will behave as if it was clicked with
-@kbd{mouse-1}.
+ Touch screen input (@pxref{Other Input}) can also be used to operate
+on tabs. Long-pressing (@pxref{Touchscreens}) a tab will display a
+context menu with items that operate on the tab that was pressed, and
+long-pressing the tab bar itself will display a context menu which
+lets you create and remove tabs; tapping a tab itself will result in
+that tab's window configuration being selected, and tapping a button
+on the tab bar will behave as if it was clicked with @kbd{mouse-1}.
@findex tab-bar-history-mode
You can enable @code{tab-bar-history-mode} to remember window
@@ -1764,8 +1763,8 @@ You can also use the command @kbd{M-x mouse-avoidance-mode} to enable
the mode. Whenever Mouse Avoidance mode moves the mouse, it also
raises the frame.
-@node Non-Window Terminals
-@section Non-Window Terminals
+@node Text Terminals
+@section Text Terminals
@cindex text terminal
On a text terminal, Emacs can display only one Emacs frame at a
diff --git a/doc/emacs/glossary.texi b/doc/emacs/glossary.texi
index e845ea8827a..344e4831f36 100644
--- a/doc/emacs/glossary.texi
+++ b/doc/emacs/glossary.texi
@@ -1,5 +1,5 @@
@c This is part of the Emacs manual.
-@c Copyright (C) 1985--1987, 1993--1995, 1997, 2001--2023 Free Software
+@c Copyright (C) 1985--1987, 1993--1995, 1997, 2001--2024 Free Software
@c Foundation, Inc.
@c See file emacs.texi for copying conditions.
@node Glossary
diff --git a/doc/emacs/gnu.texi b/doc/emacs/gnu.texi
index f484e5499a5..f7c77e23f7f 100644
--- a/doc/emacs/gnu.texi
+++ b/doc/emacs/gnu.texi
@@ -1,4 +1,4 @@
-@c Copyright (C) 1985--1987, 1993, 1995, 2001--2023 Free Software
+@c Copyright (C) 1985--1987, 1993, 1995, 2001--2024 Free Software
@c Foundation, Inc.
@c
@c Permission is granted to anyone to make or distribute verbatim copies
diff --git a/doc/emacs/haiku.texi b/doc/emacs/haiku.texi
index 1506bc8f912..8b2a12b8223 100644
--- a/doc/emacs/haiku.texi
+++ b/doc/emacs/haiku.texi
@@ -1,5 +1,5 @@
@c This is part of the Emacs manual.
-@c Copyright (C) 2021--2023 Free Software Foundation, Inc.
+@c Copyright (C) 2021--2024 Free Software Foundation, Inc.
@c See file emacs.texi for copying conditions.
@node Haiku
@appendix Emacs and Haiku
@@ -8,52 +8,55 @@
Haiku is a Unix-like operating system that originated as a
re-implementation of the operating system BeOS.
- This section describes the peculiarities of using Emacs built with
-the Application Kit, the windowing system native to Haiku. The
-oddities described here do not apply to using Emacs on Haiku built
-without windowing support, or built with X11.
+ This appendix describes the peculiarities of using Emacs built with
+the Application Kit, the windowing system indigenous to Haiku. The
+idiosyncrasies illustrated here do not apply to Emacs on Haiku built
+without windowing support, or configured with X11.
@menu
* Haiku Basics:: Basic Emacs usage and installation under Haiku.
-* Haiku Fonts:: The various options for displaying fonts on Haiku.
+* Haiku Fonts:: Various options for displaying fonts on Haiku.
@end menu
@node Haiku Basics
-@section Installation and usage peculiarities under Haiku
+@section Haiku Installation and Startup
@cindex haiku application
@cindex haiku installation
- Emacs installs two separate executables under Haiku; it is up to the
-user to decide which one suits him best: A regular executable, with
-the lowercase name @code{emacs}, and a binary containing
-Haiku-specific application metadata, with the name @code{Emacs}.
-
-@cindex launching Emacs from the tracker
-@cindex tty Emacs in haiku
- If you are launching Emacs from the Tracker, or want to make the
-Tracker open files using Emacs, you should use the binary named
-@code{Emacs}; if you are going to use Emacs in the terminal, or wish
-to launch separate instances of Emacs, or do not care for the
-aforementioned system integration features, use the binary named
-@code{emacs} instead.
+ When Emacs is installed under Haiku, two executables are copied to
+the binaries directory, which are identical save for some identifying
+file-system metadata. The first is a normal Emacs executable,
+@file{emacs}, whereas the second, @file{Emacs}, incorporates an icon
+and an application ``signature'' that abets the system in attributing
+both file types and open frames to it, thereby enabling it to receive
+file type assignments, and thus to open files directly from the
+Tracker.
+
+ Several file attributes are set within @file{Emacs} that prompt the
+system to permit only a single copy to run at any given time. This
+invariant is verified upon the establishment of a display connection,
+and is enforced by terminating any Emacs process that attempts to
+create a display connection when one is already present.
+
+ For this and other reasons, @file{Emacs} is appropriate for starting
+a GUI session of Emacs, while @file{emacs} should be used for other
+types of Emacs sessions.
@cindex modifier keys and system keymap (Haiku)
-@cindex haiku keymap
- On Haiku, unusual modifier keys such as the Hyper key are
-unsupported. By default, the super key corresponds with the option
-key defined by the operating system, the meta key with the command
-key, the control key with the system control key, and the shift key
-with the system shift key. On a standard PC keyboard, Haiku should
-map these keys to positions familiar to those using a GNU system, but
-this may require some adjustment to your system's configuration to
-work.
-
- It is impossible to type accented characters using the system super
-key map.
-
- You can customize the correspondence between modifier keys known to
-the system, and those known to Emacs. The variables that allow for
-that are described below.
+ Emacs is incapable of receiving unusual modifier keys such as
+@kbd{Hyper} under Haiku, or to receive accented characters produced
+from the system Super key map.
+
+ By default, the @key{Super} modifier is reported when the Option key
+defined by the operating system is depressed. Analogously, the
+@key{Meta} modifier is assigned to the Command key, and of course
+@key{Control} to the system Control key and @key{Shift} to the system
+Shift key. On a standard PC keyboard, Haiku should map these keys to
+positions familiar to those using a GNU system, but this may require
+some adjustment to your system's configuration to work.
+
+ You can customize the relation between modifier keys known to the
+system and those known to Emacs by means of the variables below.
@cindex modifier key customization (Haiku)
@table @code
@@ -86,25 +89,22 @@ instead.
@cindex tooltips (haiku)
@cindex haiku tooltips
On Haiku, Emacs defaults to using the system tooltip mechanism.
-This usually leads to more responsive tooltips, but the tooltips will
-not be able to display text properties or faces. If you need those
-features, customize the variable @code{use-system-tooltips} to the
-@code{nil} value, and Emacs will use its own implementation of
-tooltips.
+Tooltips thus generated are sometimes more responsive, but will not be
+able to display text properties or faces. If you need those features,
+customize the variable @code{use-system-tooltips} to @code{nil} value,
+whereupon Emacs will use its own implementation of tooltips instead.
@cindex X resources on Haiku
- Unlike the X window system, Haiku does not have a system-wide
-resource database. Since many important options are specified via
-X resources (@pxref{X Resources}), an emulation is provided: upon
+ Unlike the X window system, Haiku does not provide a system-wide
+resource database. Since many important options are specified via X
+resources (@pxref{X Resources}), an emulation is provided: upon
startup, Emacs will load a file named @file{GNU Emacs} inside the user
configuration directory (normally @file{/boot/home/config/settings}),
which should be a flattened system message where keys and values are
both strings, and correspond to attributes and their values
-respectively.
-
-You can create such a file with the @command{xmlbmessage} tool.
+respectively. Such a file may be created with the
+@command{xmlbmessage} tool.
-@subsection What to do when Emacs crashes
@cindex crashes, Haiku
@cindex haiku debugger
@vindex haiku-debug-on-fatal-error
@@ -115,18 +115,18 @@ attach the report generated by the system debugger when reporting a
bug.
@node Haiku Fonts
-@section Font and font backend selection on Haiku
+@section Font Backends and Selection under Haiku
@cindex font backend selection (Haiku)
- Emacs, when built with Haiku windowing support, can be built with
-several different font backends. You can specify font backends by
-specifying @kbd{-xrm Emacs.fontBackend:BACKEND} on the command line
-used to invoke Emacs, where @kbd{BACKEND} is one of the backends
-specified below, or on a per-frame basis by changing the
-@code{font-backend} frame parameter.
+ Emacs supports several different font backends when built with Haiku
+windowing support, though the subset supported is subject to the list
+of dependencies present and enabled when Emacs was configured. You
+can specify which font backends to utilize by providing @w{@code{-xrm
+Emacs.fontBackend:@var{backend}}} on the command line used to invoke
+Emacs, where @var{backend} is one of the backends listed below, or on
+a per-frame basis by changing the @code{font-backend} frame parameter.
Two of these backends, @code{ftcr} and @code{ftcrhb} are identical
to their counterparts on the X Window System. There is also a
Haiku-specific backend named @code{haiku}, that uses the App Server to
-draw fonts, but does not at present support display of color font and
-emoji.
+draw fonts, but presently cannot display color fonts or Emoji.
diff --git a/doc/emacs/help.texi b/doc/emacs/help.texi
index 945e12a05d2..e2f9f8a8c86 100644
--- a/doc/emacs/help.texi
+++ b/doc/emacs/help.texi
@@ -1,5 +1,5 @@
@c This is part of the Emacs manual.
-@c Copyright (C) 1985--1987, 1993--1995, 1997, 2000--2023 Free Software
+@c Copyright (C) 1985--1987, 1993--1995, 1997, 2000--2024 Free Software
@c Foundation, Inc.
@c See file emacs.texi for copying conditions.
@node Help
diff --git a/doc/emacs/indent.texi b/doc/emacs/indent.texi
index 17b663d22e1..de5f35f6139 100644
--- a/doc/emacs/indent.texi
+++ b/doc/emacs/indent.texi
@@ -1,5 +1,5 @@
@c This is part of the Emacs manual.
-@c Copyright (C) 1985--1987, 1993--1995, 1997, 2001--2023 Free Software
+@c Copyright (C) 1985--1987, 1993--1995, 1997, 2001--2024 Free Software
@c Foundation, Inc.
@c See file emacs.texi for copying conditions.
@node Indentation
@@ -55,6 +55,7 @@ repositioned to the first non-whitespace character on the line.
* Tab Stops:: Stop points for indentation in Text modes.
* Just Spaces:: Using only space characters for indentation.
* Indent Convenience:: Optional indentation features.
+* Code Alignment:: Making common parts of lines start at the same column.
@end menu
@node Indentation Commands
@@ -265,3 +266,236 @@ indents the line after every @key{RET} you type. This mode is enabled
by default. To toggle this minor mode, type @kbd{M-x
electric-indent-mode}. To toggle the mode in a single buffer,
use @kbd{M-x electric-indent-local-mode}.
+
+@node Code Alignment
+@section Code Alignment
+@cindex code alignment
+@cindex aligning code
+
+ @dfn{Alignment} is the process of adjusting whitespace in a sequence
+of lines in the region such that in all lines certain parts begin at
+the same column. This is usually something you do to enhance
+readability of a piece of text or code. The classic example is
+aligning a series of assignments in C-like programming languages:
+
+@example
+int a = 1;
+short foo = 2;
+double blah = 4;
+@end example
+
+@noindent
+is commonly aligned to:
+
+@example
+int a = 1;
+short foo = 2;
+double blah = 4;
+@end example
+
+@cindex alignment rules
+@findex align
+ You can use the command @kbd{M-x align} to align lines in the
+current region. This command knows about common alignment patterns
+across many markup and programming languages. It encodes these
+patterns as a set of @dfn{alignment rules}, that say how to align
+different kinds of text in different contexts.
+
+@vindex align-rules-list
+@vindex align-mode-rules-list
+The user option @code{align-rules-list} says which alignment rules
+@kbd{M-x align} should consult. The value of this option is a list
+with elements describing alignment rules. Each element is a cons cell
+@code{(@var{title} . @var{attributes})}, where @var{title} is the name
+of the alignment rule as a symbol, and @var{attributes} is a list of
+rule attributes that define when the rule should apply and how it
+partitions and aligns lines. Each rule attribute is a cons cell
+@code{(@var{attribute} . @var{value})}, where @var{attribute} is the
+name of attribute and @var{value} is its value. The only required
+attribute is @code{regexp}, whose value is a regular expression with
+sub-expressions matching the parts of each line where @kbd{M-x align}
+should expand or contract whitespace (@pxref{Regexp Backslash}). See
+the documentation string of @code{align-rules-list} (@kbd{C-h v
+align-rules-list @key{RET}}) for a full description of possible
+alignment rule attributes. By default, this option is set to a long
+list of alignment rules for many languages that Emacs supports. The
+default rules use the @code{modes} rule attribute to specify major
+modes in which @kbd{M-x align} should apply them. Major modes can
+also override @code{align-rules-list} by setting the buffer-local
+variable @code{align-mode-rules-list} to a non-@code{nil} list of
+alignment rules. When @code{align-mode-rules-list} is non-@code{nil},
+@kbd{M-x align} consults it instead of @code{align-rules-list}.
+
+@cindex align exclusion rules
+@vindex align-exclude-rules-list
+@vindex align-mode-exclude-rules-list
+Besides alignment rules, @kbd{M-x align} uses another kind of rules
+called @dfn{exclusion rules}. The exclusion rules say which parts in
+the region @kbd{M-x align} should not align and instead leave them
+intact. The user option @code{align-exclude-rules-list} specifies
+these exclusion rules. Similarly to @code{align-rules-list}, the
+value of @code{align-exclude-rules-list} is also a list of cons cells
+that describe the exclusion rules. By default,
+@code{align-exclude-rules-list} includes rules that exclude alignment
+in quoted strings and comments in Lisp, C and other languages. Beyond
+the default exclusion rules in @code{align-exclude-rules-list}, major
+modes can define bespoke exclusion rules by setting
+@code{align-mode-exclude-rules-list} to a non-@code{nil} list of
+rules, this overrides @code{align-exclude-rules-list} just like
+@code{align-mode-rules-list} overrides @code{align-rules-list}.
+
+@cindex alignment sections
+@vindex align-region-separate
+@kbd{M-x align} splits the region into a series of @dfn{sections},
+usually sequences of non-blank lines, and aligns each section
+according to all matching alignment rule by expanding or contracting
+stretches of whitespace. @kbd{M-x align} consistently aligns all
+lines inside a single section, but it may align different sections in
+the region differently. The user option @code{align-region-separate}
+specifies how @kbd{M-x align} separates the region to sections. This
+option can be one of the symbols @code{entire}, @code{group}, or a
+regular expression. If @code{align-region-separate} is @code{entire},
+Emacs aligns the entire region as a single section. If this option is
+@code{group}, Emacs aligns each group of consecutive non-blank lines
+in the region as a separate section. If @code{align-region-separate}
+is a regular expression, @kbd{M-x align} scans the region for matches
+to that regular expression and treats them as section separators. By
+default @code{align-region-separate} is set to a regular expression
+that matches blank lines and lines that contains only whitespace and a
+single curly brace (@samp{@{} or @samp{@}}). For special cases where
+regular expressions are not accurate enough, you can also set
+@code{align-region-separate} to a function that says how to separate
+the region to alignment sections. See the documentation string of
+@code{align-region-separate} for more details. Specific alignment
+rules can override the value of @code{align-region-separate} and
+define their own section separator by specifying the @code{separate}
+rule attribute.
+
+If you call @kbd{M-x align} with a prefix argument (@kbd{C-u}), it
+enables more alignment rules that are often useful but may sometimes
+be too intrusive. For example, in a Lisp buffer with the following
+form:
+
+@lisp
+(set-face-attribute 'mode-line-inactive nil
+ :box nil
+ :background nil
+ :underline "black")
+@end lisp
+
+@noindent
+Typing (@kbd{C-u M-x align}) yields:
+
+@lisp
+(set-face-attribute 'mode-line-inactive nil
+ :box nil
+ :background nil
+ :underline "black")
+@end lisp
+
+In most cases, you should try @kbd{M-x align} without a prefix
+argument first, and if that doesn't produce the right result you can
+undo with @kbd{C-/} and try again with @kbd{C-u M-x align}.
+
+@findex align-highlight-rule
+@findex align-unhighlight-rule
+You can use the command @kbd{M-x align-highlight-rule} to visualize
+the effect of a specific alignment or exclusion rule in the current
+region. This command prompts you for the title of a rule and
+highlights the parts on the region that this rule affects. For
+alignment rules, this command highlights the whitespace that @kbd{M-x
+align} would expand or contract, and for exclusion this command
+highlights the parts that @kbd{M-x align} would exclude from
+alignment. To remove the highlighting that this command creates, type
+@kbd{M-x align-unhighlight-rule}.
+
+@findex align-current
+@findex align-entire
+ The command @kbd{M-x align-current} is similar to @kbd{M-x align},
+except that it operates only on the alignment section that contains
+point regardless of the current region. This command determines the
+boundaries of the current section according to the section separators
+that @code{align-region-separate} define. @kbd{M-x align-entire} is
+another variant of @kbd{M-x align}, that disregards
+@code{align-region-separate} and aligns the entire region as a single
+alignment section with consistent alignment. If you set
+@code{align-region-separate} to @code{entire}, @kbd{M-x align} behaves
+like @kbd{M-x align-entire} by default. To illustrate the effect of
+aligning the entire region as a single alignment section, consider the
+following code:
+
+@example
+one = 1;
+foobarbaz = 2;
+
+spam = 3;
+emacs = 4;
+@end example
+
+@noindent
+when the region covers all of these lines, typing @kbd{M-x align}
+yields:
+
+@example
+one = 1;
+foobarbaz = 2;
+
+spam = 3;
+emacs = 4;
+@end example
+
+@noindent
+On the other hand, @kbd{M-x align-entire} aligns all of the lines as a
+single section, so the @samp{=} appears at the same column in all
+lines:
+
+@example
+one = 1;
+foobarbaz = 2;
+
+spam = 3;
+emacs = 4;
+@end example
+
+@findex align-regexp
+ The command @kbd{M-x align-regexp} lets you align the current region
+with an alignment rule that you define ad-hoc, instead of using the
+predefined rules in @code{align-rules-list}. @kbd{M-x align-regexp}
+prompts you for a regular expression and uses that expression as the
+@code{regexp} attribute for an ad-hoc alignment rule that this command
+uses to align the current region. By default, this command adjusts
+the whitespace that matches the first sub-expression of the regular
+expression you specify. If you call @kbd{M-x align-regexp} with a
+prefix argument, it also prompts you for the sub-expression to use and
+lets you specify the amount of whitespace to use as padding, as well
+as whether to apply the rule repeatedly to all matches of the regular
+expression in each line. @xref{Regexp Backslash}, for more
+information about regular expressions and their sub-expressions.
+
+@vindex align-indent-before-aligning
+ If the user option @code{align-indent-before-aligning} is
+non-@code{nil}, Emacs indents the region before aligning it with
+@kbd{M-x align}. @xref{Indentation}. By default
+@code{align-indent-before-aligning} is set to @code{nil}.
+
+@vindex align-to-tab-stop
+ The user option @code{align-to-tab-stop} says whether aligned parts
+should start at a tab stop (@pxref{Tab Stops}). If this option is
+@code{nil}, @kbd{M-x align} uses just enough whitespace for alignment,
+disregarding tab stops. If this is a non-@code{nil} symbol, @kbd{M-x
+align} checks the value of that symbol, and if this value is
+non-@code{nil}, @kbd{M-x align} aligns to tab stops. By default, this
+option is set to @code{indent-tabs-mode}, so alignment respects tab
+stops in buffers that use tabs for indentation. @xref{Just Spaces}.
+
+@vindex align-default-spacing
+ The user option @code{align-default-spacing} specifies the default
+amount of whitespace that @kbd{M-x align} and its related commands use
+for padding between the different parts of each line when aligning it.
+When @code{align-to-tab-stop} is @code{nil}, the value of
+@code{align-default-spacing} is the number of spaces to use for
+padding; when @code{align-to-tab-stop} is non-@code{nil}, the value of
+@code{align-default-spacing} is instead the number of tab stops to
+use. Each alignment rule can override the default that
+@code{align-default-spacing} specifies with the @code{spacing}
+attribute rule.
diff --git a/doc/emacs/input.texi b/doc/emacs/input.texi
index 4f49ca3cece..67679b00e89 100644
--- a/doc/emacs/input.texi
+++ b/doc/emacs/input.texi
@@ -1,78 +1,82 @@
@c This is part of the Emacs manual.
-@c Copyright (C) 2023 Free Software Foundation, Inc.
+@c Copyright (C) 2023--2024 Free Software Foundation, Inc.
@c See file emacs.texi for copying conditions.
-@node Other Input Devices
-@appendix Emacs and Unconventional Input Devices
+@node Other Input
+@section Touchscreen Input and Virtual Keyboards
@cindex other input devices
- Emacs was originally developed with the assumption that its users
-have access to a desktop computer or computer terminal, with a
-keyboard and perhaps a suitable pointing device such as a mouse.
+ Emacs was first written assuming that its users were to use it from
+a desktop computer or computer terminal, equipped with a keyboard and
+perhaps a suitable pointing device such as a mouse (@pxref{Mouse
+Input}).
- However, recent developments in the X Window System and operating
-systems such as Android mean that this assumption no longer holds
-true. Emacs supports input from various other kinds of input devices,
-which is detailed here.
+ Emacs is also capable of receiving input from alternative sources of
+input, enabling users to interact with it even if it is installed on a
+computer that substitutes such input sources for the customary
+combination of keyboard and mouse.
@menu
-* Touchscreens:: Using Emacs on touchscreens.
-* On-Screen Keyboards:: Using Emacs with virtual keyboards.
+* Touchscreens:: Interacting with Emacs from touchscreens.
+* On-Screen Keyboards:: Text input with virtual keyboards.
@end menu
@node Touchscreens
-@section Using Emacs on Touchscreens
+@subsection Using Emacs on Touchscreens
@cindex touchscreen input
- Touchscreen input works by pressing and moving tools (which include
-fingers and some pointing devices--styluses, for example) onto a frame
-in order to manipulate its contents.
+ Touchscreen input is the manipulation of a frame's contents by the
+placement and motion of tools (instanced by fingers and such pointing
+devices as styluses) on a monitor or computer terminal where it is
+displayed.
- When running under the X Window System or Android, Emacs
-automatically detects and maps the following sequences of movements
-(``gestures'') to common actions:
+ Two factors, the order and position on which such tools are placed,
+are compared against predefined patterns dubbed @dfn{gestures}, after
+which any gesture those factors align with designates a series of
+actions to be taken on the text beneath the tools; the gestures
+presently recognized are:
@itemize @bullet
@item
@cindex tapping, touchscreens
- ``Tapping'', briefly placing and lifting a tool from the display,
-will result in Emacs selecting the window that was tapped, and
-executing any command bound to @code{mouse-1} at that location in the
-window. If the tap happened on top of a link (@pxref{Mouse
-References}), then Emacs will follow the link instead.
-
- If a command bound to @code{down-mouse-1} is bound to the location
-where the tap took place, Emacs will execute that command as well.
+ @dfn{Tapping}, briefly placing and lifting a tool from the display,
+will select the window that was tapped, and execute any command bound
+to @code{mouse-1} at that location in the window. If a link
+(@pxref{Mouse References}) exists there, then Emacs will follow that
+link instead (insofar as such action differs from that taken upon the
+simulation of a @code{mouse-1} event).
@item
@cindex scrolling, touchscreens
- ``Scrolling'', meaning to place a tool on the display and move it up
-or down, will result in Emacs scrolling the window contents in the
-direction where the tool moves.
-
- If the tool is moved left or right, Emacs additionally scrolls the
-window horizontally to follow (@pxref{Horizontal Scrolling}.)
+@vindex touch-screen-enable-hscroll
+ @dfn{Scrolling}, which is continuous vertical or horizontal motion
+on the screen, will scroll the contents of the window beneath the
+tool's initial location in the direction of movement. The user option
+@code{touch-screen-enable-hscroll} governs whether horizontal
+scrolling (@pxref{Horizontal Scrolling}) is performed in reaction to
+this gesture.
@item
@cindex dragging, touchscreens
@cindex long-press, touchscreens
- ``Dragging'', which is performing a @dfn{long-press} by placing a
-tool on the display and leaving it there for a while prior to moving
-the tool around will make Emacs set the point to where the tool was
-and begin selecting text under the tool as it moves around, as if
-@code{mouse-1} were to be held down. @xref{Mouse Commands}.
+ @dfn{Dragging}, which is performing a @dfn{long-press} by placing a
+tool on the display and leaving it there awhile before moving it to
+another position, will move point to the tool's initial position, and
+commence selecting text under the tool as it continues its motion, as
+if @code{mouse-1} were to be held down and a mouse moved analogously.
+@xref{Mouse Commands}.
@vindex touch-screen-word-select
@cindex word selection mode, touchscreens
- Some people find it difficult to position a tool accurately on a
-touch screen display, to the detriment of text selection. The user
-option @code{touch-screen-word-select} enables ``word selection
-mode'', causing dragging to select the complete word, not only the
-character containing the position of the tool.
+ To the detriment of text selection, it can prove challenging to
+position a tool accurately on a touch screen display. The user option
+@code{touch-screen-word-select}, which when enabled, prompts dragging
+to select the complete word under the tool. (Normally, the selection
+is only extended to encompass the character beneath the tool.)
@vindex touch-screen-extend-selection
@cindex extending the selection, touchscreens
- Similarly, it may be difficult to select all of the text intended
-within a single gesture. If the user option
+ In the same vein, it may be difficult to select all of the text
+intended within a single gesture. If the user option
@code{touch-screen-extend-selection} is enabled, taps on the locations
of the point or the mark within a window will begin a new ``drag''
gesture, where the region will be extended in the direction of any
@@ -80,100 +84,109 @@ subsequent movement.
@vindex touch-screen-preview-select
@cindex previewing the region during selection, touchscreens
- Difficulties in making accurate adjustments to the region can also
-be alleviated by indicating the position of the point relative to its
-containing line within the echo area, since the window cursor may be
-physically obscured by the tool. If
+ Difficulties in making accurate adjustments to the region from the
+cursor being physically obscured by the tool can be mitigated by
+indicating the position of the point within the echo area. If
@code{touch-screen-preview-select} is non-@code{nil}, the line
-containing point is displayed in the echo area (@pxref{Echo Area})
-during the motion of the tool, followed by another line indicating the
-position of point within the first line.
+surrounding point is displayed in the echo area (@pxref{Echo Area})
+during the motion of the tool, below which is another line indicating
+the position of point relative to the first.
+
+@item
+@cindex pinching, touchscreens
+ @dfn{Pinching}, the placement of two tools apart on the screen
+followed by adjustments to their position such as to increase or
+decrease the distance between them will modify the text scale
+(@pxref{Text Scale}) in proportion to the change in that distance.
@end itemize
@vindex touch-screen-delay
- By default, Emacs considers a tool as having been left on the
-display long enough to trigger a ``long-press'' after 0.7 seconds, but
-this can be changed by customizing the variable
-@code{touch-screen-delay}.
+ Emacs registers a long-press after the time a tool has been placed
+upon the screen exceeds 0.7 seconds. This delay can be adjusted
+through customizing the variable @code{touch-screen-delay}.
@node On-Screen Keyboards
-@section Using Emacs with Virtual Keyboards
+@subsection Using Emacs with Virtual Keyboards
@cindex virtual keyboards
@cindex on-screen keyboards
- When there is no physical keyboard attached to a system, the
-windowing system typically provides an on-screen keyboard, more often
-known as a ``virtual keyboard'', containing rows of clickable buttons
-that send keyboard input to the application, much like a real keyboard
-would. This virtual keyboard is hidden by default, as it uses up
-valuable on-screen real estate, and must be opened once the program
-being used is ready to accept keyboard input.
+ When there is no physical keyboard attached to a system, its
+windowing system might provide an on-screen keyboard, widely known as
+a ``virtual keyboard'', containing rows of clickable buttons that send
+keyboard input to the application, much as a real keyboard would.
- Under the X Window System, the client that provides the on-screen
-keyboard typically detects when the application is ready to accept
-keyboard input through a set of complex heuristics, and automatically
-displays the keyboard when necessary.
-
- On other systems such as Android, Emacs must tell the system when it
-is ready to accept keyboard input. Typically, this is done in
-response to a touchscreen ``tap'' gesture (@pxref{Touchscreens}), or
-once to the minibuffer becomes in use (@pxref{Minibuffer}.)
+ This virtual keyboard is hidden when the focused program is not
+requesting text input as it occupies scarce space on display, and
+programs are therefore enjoined to display it once they are ready to
+accept keyboard input. Systems running X detect when the presence of
+the virtual keyboard is warranted, but on others such as Android Emacs
+is responsible for displaying it when need be, generally in reaction
+to a touch screen ``tap'' gesture (@pxref{Touchscreens}) or the
+minibuffer being brought into use (@pxref{Minibuffer}).
@vindex touch-screen-set-point-commands
When a ``tap'' gesture results in a command being executed, Emacs
-checks to see whether or not the command is supposed to set the point
-by looking for it in the list @code{touch-screen-set-point-commands}.
-If it is, then Emacs looks up whether or not the text under the point
-is read-only; if not, it activates the on-screen keyboard, assuming
-that the user is about to enter text in to the current buffer.
+checks whether the command is meant to set the point by searching for
+it in the list @code{touch-screen-set-point-commands}. If it is and
+the text beneath the new point is not read-only, it activates the
+virtual keyboard, in anticipation that the user is about to enter text
+there.
-@vindex touch-screen-display-keyboard
- The user option @code{touch-screen-display-keyboard} forces Emacs to
-always display the on screen keyboard; it may also be set buffer
-locally, which means that Emacs should always display the keyboard
-when the buffer is selected.
+ The default value of @code{touch-screen-set-point-commands} holds
+only the command @code{mouse-set-point} (@pxref{Mouse Commands}),
+which is the default binding of @code{mouse-1}, and thus of
+touchscreen tap gestures as well.
- Emacs also provides a set of functions to show or hide the on-screen
-keyboard. For more details, @pxref{On-Screen Keyboards,,, elisp, The
+@vindex touch-screen-display-keyboard
+ The user option @code{touch-screen-display-keyboard} compels Emacs
+to display the virtual keyboard on such taps even if the text is read
+only; it may also be set buffer locally, in which case Emacs will
+always display the keyboard in response to a tap on a window
+displaying the buffer it is set in.
+
+ There are moreover several functions to show or hide the on-screen
+keyboard. For more details, @xref{On-Screen Keyboards,,, elisp, The
Emacs Lisp Reference Manual}.
@cindex quitting, without a keyboard
- Since it may not be possible for Emacs to display the on screen
+ Since it may not be possible for Emacs to display the virtual
keyboard while it is executing a command, Emacs implements a feature
-on devices with only an on-screen keyboard, by which two rapid clicks
-of a hardware button that is always present on the device results in
-Emacs quitting. @xref{Quitting}.
+on window systems frequently equipped with no physical keyboard, by
+which two rapid clicks of a hardware button that is always present on
+the device induces a quit. @xref{Quitting}.
@vindex x-quit-keysym
- Which button is used to do this depends on the window system in use:
-on X, it is defined in the variable @code{x-quit-keysym}, and on
-Android, it is always the volume down button.
+ No such button is enabled on X, but one can be configured through
+the variable @code{x-quit-keysym}. On Android this button is always
+the volume down button.
@cindex text conversion, keyboards
- Most input methods designed to work with on-screen keyboards perform
-buffer edits differently from desktop input methods.
+ Most input methods designed to work with virtual keyboards edit text
+differently from desktop input methods.
On a conventional desktop windowing system, an input method will
-simply display the contents of any on going character compositions on
-screen, and send the appropriate key events to Emacs after completion.
+simply display the contents of any ongoing character composition on
+screen, and send key events reflecting its contents to Emacs after it
+is confirmed by the user.
- However, on screen keyboard input methods directly perform edits to
-the selected window of each frame; this is known as ``text
+ By contrast, virtual keyboard input methods directly perform edits
+to the selected window of each frame; this is known as ``text
conversion'', or ``string conversion'' under the X Window System.
-Emacs enables these input methods whenever the buffer local value of
-@code{text-conversion-style} is non-@code{nil}, normally inside
-derivatives of @code{text-mode} and @code{prog-mode}.
+
+ Emacs enables these input methods whenever the buffer local value of
+@code{text-conversion-style} is non-@code{nil}, that is to say,
+generally inside derivatives of @code{text-mode} and @code{prog-mode}.
Text conversion is performed asynchronously whenever Emacs receives
a request to perform the conversion from the input method, and Emacs
is not currently reading a key sequence for which one prefix key has
-already been read (@pxref{Keys}.) After the conversion completes, a
+already been read (@pxref{Keys}). After the conversion completes, a
@code{text-conversion} event is sent. @xref{Misc Events,,, elisp, the
Emacs Reference Manual}.
@vindex text-conversion-face
If the input method needs to work on a region of the buffer, then
-the region becomes known as the ``composing region'' (or
-``preconversion region''.) The variable @code{text-conversion-face}
-describes whether or not to display the composing region in a specific
-face.
+the region is designated the ``composing region'' (or ``preconversion
+region''). The variable @code{text-conversion-face} controls whether
+to display the composing region in a distinctive face, and if so,
+which face to employ.
diff --git a/doc/emacs/killing.texi b/doc/emacs/killing.texi
index 47e0b5e37ae..9717c02f782 100644
--- a/doc/emacs/killing.texi
+++ b/doc/emacs/killing.texi
@@ -1,5 +1,5 @@
@c This is part of the Emacs manual.
-@c Copyright (C) 1985--1987, 1993--1995, 1997, 2000--2023 Free Software
+@c Copyright (C) 1985--1987, 1993--1995, 1997, 2000--2024 Free Software
@c Foundation, Inc.
@c See file emacs.texi for copying conditions.
@@ -308,7 +308,7 @@ way to move or copy text is to kill it and then yank it elsewhere.
Yank the last kill into the buffer, at point (@code{yank}).
@item M-y
Either replace the text just yanked with an earlier batch of killed
-text (@code{yank-pop}), or allow to select from the list of
+text (@code{yank-pop}), or allow selecting from the list of
previously-killed batches of text. @xref{Earlier Kills}.
@item C-M-w
Cause the following command, if it is a kill command, to append to the
diff --git a/doc/emacs/kmacro.texi b/doc/emacs/kmacro.texi
index fc1402b489d..e30def34475 100644
--- a/doc/emacs/kmacro.texi
+++ b/doc/emacs/kmacro.texi
@@ -1,5 +1,5 @@
@c This is part of the Emacs manual.
-@c Copyright (C) 1985--1987, 1993--1995, 1997, 2000--2023 Free Software
+@c Copyright (C) 1985--1987, 1993--1995, 1997, 2000--2024 Free Software
@c Foundation, Inc.
@c See file emacs.texi for copying conditions.
@node Keyboard Macros
@@ -515,6 +515,19 @@ editing it. Type @kbd{C-h m} once in that buffer to display details
of how to edit the macro. When you are finished editing, type
@kbd{C-c C-c}.
+@findex edmacro-insert-key
+@findex edmacro-set-macro-to-region-lines
+ @code{edmacro-mode}, the major mode used by
+@code{kmacro-edit-macro}, provides commands for more easily editing
+the formatted macro. Use @kbd{C-c C-q} (@code{edmacro-insert-key}) to
+insert the next key sequence that you type into the buffer using the
+correct format, similar to @kbd{C-q} (@code{quoted-insert}). Use
+@kbd{C-c C-r} (@code{edmacro-set-macro-to-region-lines}) to replace
+the macro's text with the text in the region. If the region does not
+begin at the start of a line or if it does not end at the end of a
+line, the region is extended to include complete lines. If the region
+ends at the beginning of a line, that final line is excluded.
+
@findex edit-kbd-macro
@kindex C-x C-k e
You can edit a named keyboard macro or a macro bound to a key by typing
@@ -523,9 +536,13 @@ keyboard input that you would use to invoke the macro---@kbd{C-x e} or
@kbd{M-x @var{name}} or some other key sequence.
@findex kmacro-edit-lossage
+@vindex edmacro-reverse-macro-lines
@kindex C-x C-k l
You can edit the last 300 keystrokes as a macro by typing
-@kbd{C-x C-k l} (@code{kmacro-edit-lossage}).
+@kbd{C-x C-k l} (@code{kmacro-edit-lossage}). By default,
+your most recent keystrokes are listed at the bottom of the buffer.
+To list a macro's key sequences in reverse order, set
+@code{edmacro-reverse-macro-lines} to @code{t}.
@node Keyboard Macro Step-Edit
@section Stepwise Editing a Keyboard Macro
diff --git a/doc/emacs/m-x.texi b/doc/emacs/m-x.texi
index 7b366562019..6a88b2019a0 100644
--- a/doc/emacs/m-x.texi
+++ b/doc/emacs/m-x.texi
@@ -1,5 +1,5 @@
@c This is part of the Emacs manual.
-@c Copyright (C) 1985--1987, 1993--1995, 1997, 2001--2023 Free Software
+@c Copyright (C) 1985--1987, 1993--1995, 1997, 2001--2024 Free Software
@c Foundation, Inc.
@c See file emacs.texi for copying conditions.
@node M-x
diff --git a/doc/emacs/macos.texi b/doc/emacs/macos.texi
index 18811291a9e..b5f263996cb 100644
--- a/doc/emacs/macos.texi
+++ b/doc/emacs/macos.texi
@@ -1,5 +1,5 @@
@c This is part of the Emacs manual.
-@c Copyright (C) 2000--2023 Free Software Foundation, Inc.
+@c Copyright (C) 2000--2024 Free Software Foundation, Inc.
@c See file emacs.texi for copying conditions.
@node Mac OS / GNUstep
@appendix Emacs and macOS / GNUstep
@@ -149,7 +149,10 @@ the corresponding left-hand key.
@vindex ns-use-proxy-icon
@item ns-use-proxy-icon
This variable specifies whether to display the proxy icon in the
-titlebar.
+titlebar. The proxy icon can be used to drag the file associated with
+the current buffer to other applications, a printer, the desktop,
+etc., in the same way you can from Finder. You might have to disable
+@code{tool-bar-mode} to see the proxy icon.
@vindex ns-confirm-quit
@item ns-confirm-quit
diff --git a/doc/emacs/maintaining.texi b/doc/emacs/maintaining.texi
index 2dad70d3d13..8de9cf2c2f3 100644
--- a/doc/emacs/maintaining.texi
+++ b/doc/emacs/maintaining.texi
@@ -1,5 +1,5 @@
@c This is part of the Emacs manual., Abbrevs, This is part of the Emacs manual., Top
-@c Copyright (C) 1985--1987, 1993--1995, 1997, 1999--2023 Free Software
+@c Copyright (C) 1985--1987, 1993--1995, 1997, 1999--2024 Free Software
@c Foundation, Inc.
@c See file emacs.texi for copying conditions.
@node Maintaining
@@ -447,9 +447,10 @@ merge-based version control system, a @samp{-} character indicates
that the work file is unmodified, and @samp{:} indicates that it has
been modified. @samp{!} indicates that the file contains conflicts as
result of a recent merge operation (@pxref{Merging}), or that the file
-was removed from the version control. Finally, @samp{?} means that
-the file is under version control, but is missing from the working
-tree.
+was removed from the version control, or that it is versioned but also
+@dfn{ignored}, something that usually should not happen (@pxref{VC
+Ignore}). Finally, @samp{?} means that the file is under version
+control, but is missing from the working tree.
In a lock-based system, @samp{-} indicates an unlocked file, and
@samp{:} a locked file; if the file is locked by another user (for
@@ -481,22 +482,23 @@ system, but is usually not excessive.
@cindex filesets, VC
@cindex VC filesets
Most VC commands operate on @dfn{VC filesets}. A VC fileset is a
-collection of one or more files that a VC operation acts on. When you
-type VC commands in a buffer visiting a version-controlled file, the
-VC fileset is simply that one file. When you type them in a VC
+collection of one or more files that a VC operation acts upon. When
+you type VC commands in a buffer visiting a version-controlled file,
+the VC fileset is simply that one file. When you type them in a VC
Directory buffer, and some files in it are marked, the VC fileset
consists of the marked files (@pxref{VC Directory Mode}). Likewise,
when you invoke a VC command from a Dired buffer, the VC fileset
consists of the marked files (@pxref{Marks vs Flags}), defaulting to
the file shown on the current line if no files are marked.
- On modern changeset-based version control systems (@pxref{VCS
-Changesets}), VC commands handle multi-file VC filesets as a group.
-For example, committing a multi-file VC fileset generates a single
-revision, containing the changes to all those files. On older
-file-based version control systems like CVS, each file in a multi-file
-VC fileset is handled individually; for example, a commit generates
-one revision for each changed file.
+ With modern changeset-based version control systems (@pxref{VCS
+Changesets}), such as Git, Mercurial, and Bazaar, VC commands handle
+multi-file VC filesets as a group. For example, committing a
+multi-file VC fileset generates a single revision, containing the
+changes to all those files. On older file-based version control
+systems like CVS, each file in a multi-file VC fileset is handled
+individually; thus, committing a fileset generates one revision for
+each changed file in the fileset.
@table @kbd
@item C-x v v
@@ -507,14 +509,16 @@ VC fileset.
@findex vc-next-action
@kindex C-x v v
The principal VC command is a multi-purpose command, @kbd{C-x v v}
-(@code{vc-next-action}), which performs the most appropriate
-action on the current VC fileset: either registering it with a version
-control system, or committing it, or unlocking it, or merging changes
-into it. The precise actions are described in detail in the following
-subsections. You can use @kbd{C-x v v} either in a file-visiting
-buffer, in a Dired buffer, or in a VC Directory buffer; in the latter
-two cases the command operates on the fileset consisting of the marked
-files.
+(@code{vc-next-action}), which performs the most appropriate action on
+the current VC fileset: either registering it with a version control
+system, or committing it, or unlocking it, or merging changes into it.
+The precise actions for each situation are described in detail in the
+following subsections. You can use @kbd{C-x v v} either in a
+file-visiting buffer, in a Dired buffer, or in a VC Directory buffer;
+in the latter two cases the command operates on the fileset consisting
+of the marked files. You can also use @kbd{C-x v v}, in a buffer with
+patches under Diff Mode (@pxref{Diff Mode}), in which case the command
+operates on the files whose diffs are shown in the buffer.
Note that VC filesets are distinct from the named filesets used
for viewing and visiting files in functional groups
@@ -522,7 +526,7 @@ for viewing and visiting files in functional groups
and don't persist across sessions.
@menu
-* VC With A Merging VCS:: Without locking: default mode for CVS.
+* VC With A Merging VCS:: Without locking: default mode for Git, Hg, SVN, CVS.
* VC With A Locking VCS:: RCS in its default mode, SCCS, and optionally CVS.
* Advanced C-x v v:: Advanced features available with a prefix argument.
@end menu
@@ -530,44 +534,56 @@ and don't persist across sessions.
@node VC With A Merging VCS
@subsubsection Basic Version Control with Merging
- On a merging-based version control system (i.e., most modern ones;
-@pxref{VCS Merging}), @kbd{C-x v v} does the following:
+ With a modern merging-based version control system (such as Git and Hg;
+@pxref{VCS Merging}), @kbd{C-x v v} does the following when invoked
+from a buffer that visits a version-controlled file or a VC Directory
+or Dired buffer:
@itemize @bullet
@item
If there is more than one file in the VC fileset and the files have
inconsistent version control statuses, signal an error. (Note,
-however, that a fileset is allowed to include both newly-added
-files and modified files; @pxref{Registering}.)
+however, that a fileset is allowed to include both newly-added files
+and modified files; @pxref{Registering}.) Also signal an error if the
+files in the fileset are missing (removed from the filesystem, but
+still tracked by version control), or are ignored by version control.
@item
-If none of the files in the VC fileset are registered with a version
-control system, register the VC fileset, i.e., place it under version
-control. @xref{Registering}. If Emacs cannot find a system to
-register under, it prompts for a repository type, creates a new
-repository, and registers the VC fileset with it.
-
-@item
-If every work file in the VC fileset is unchanged, do nothing.
-
-@item
-If every work file in the VC fileset has been modified, commit the
-changes. To do this, Emacs pops up a @file{*vc-log*} buffer; type the
-desired log entry for the new revision, followed by @kbd{C-c C-c} to
-commit. @xref{Log Buffer}.
-
-If committing to a shared repository, the commit may fail if the
-repository has been changed since your last update. In that
-case, you must perform an update before trying again. On a
-decentralized version control system, use @kbd{C-x v +}
-(@pxref{Pulling / Pushing}) or @kbd{C-x v m} (@pxref{Merging}).
-On a centralized version control system, type @kbd{C-x v v} again to
-merge in the repository changes.
+If every file in the VC fileset is registered and unchanged with
+respect to the last revision, do nothing.
@item
-Finally, if you are using a centralized version control system, check
-if each work file in the VC fileset is up-to-date. If any file has
-been changed in the repository, offer to update it.
+If none of the files in the VC fileset are registered with a version
+control system, register the newly-added files in the VC fileset,
+i.e., place them under version control. @xref{Registering}. If Emacs
+cannot find a system to register under, it prompts for a repository
+type, creates a new repository, and registers the VC fileset with it.
+You can also specify the system explicitly, see @ref{Advanced C-x v
+v}. Note that registering the files doesn't commit them; you must
+invoke @w{@kbd{C-x v v}} again to commit, see below.
+
+@item
+If every file in the VC fileset has been either newly-added or
+modified, commit the changed files. To do this, Emacs pops up a
+@file{*vc-log*} buffer; type the desired log entry for the changes,
+followed by @kbd{C-c C-c} to commit. @xref{Log Buffer}.
+
+With modern decentralized version control systems (Git, Mercurial,
+etc.), the changes are committed locally and not automatically
+propagated to the upstream repository (which is usually on a remote
+host). In these cases, if the repository has been changed since your
+last update, the commit may fail. In that case, you must update from
+upstream and then try again. Use @kbd{C-x v +} (@pxref{Pulling /
+Pushing}) or @kbd{C-x v m} (@pxref{Merging}) for that.
+
+With a centralized version control system, if the commit fails due to
+upstream changes, type @kbd{C-x v v} again to merge in the upstream
+repository changes.
+
+@item
+Finally, if you are using a centralized version control system, if any
+file in the VC fileset is outdated with respect to the upstream
+repository, offer to update the fileset from the repository.
@end itemize
These rules also apply when you use RCS in its non-locking mode,
@@ -581,43 +597,60 @@ changes. In addition, locking is possible with RCS even in this mode:
@kbd{C-x v v} with an unmodified file locks the file, just as it does
with RCS in its normal locking mode (@pxref{VC With A Locking VCS}).
+ If @kbd{C-x v v} is invoked from a buffer under Diff Mode, the
+command assumes the buffer holds a set of patches for one or more
+files. It then applies the changes to the respective files and
+commits the changes after popping up the @file{*vc-log*} buffer to
+allow you to type a suitable commit log message.
+
@node VC With A Locking VCS
@subsubsection Basic Version Control with Locking
- On a locking-based version control system (such as SCCS, and RCS in
+ With a locking-based version control system (such as SCCS, and RCS in
its default mode), @kbd{C-x v v} does the following:
@itemize @bullet
@item
If there is more than one file in the VC fileset and the files have
-inconsistent version control statuses, signal an error.
+inconsistent version control statuses, signal an error. Also signal
+an error if the files in the fileset are missing (removed from the
+filesystem, but still tracked by version control).
@item
If each file in the VC fileset is not registered with a version
-control system, register the VC fileset. @xref{Registering}. If
-Emacs cannot find a system to register under, it prompts for a
-repository type, creates a new repository, and registers the VC
-fileset with it.
+control system, register the newly-added files in the fileset.
+@xref{Registering}. If Emacs cannot find a system to register under,
+it prompts for a repository type, creates a new repository, and
+registers the VC fileset with it. You can also specify the system
+explicitly, see @ref{Advanced C-x v v}.
@item
-If each file is registered and unlocked, lock it and make it writable,
-so that you can begin to edit it.
+If each file is registered and unlocked, check the files out: lock
+each one and make it writable, so that you can begin to edit it.
@item
-If each file is locked by you and contains changes, commit the
-changes. To do this, Emacs pops up a @file{*vc-log*} buffer; type the
-desired log entry for the new revision, followed by @kbd{C-c C-c} to
-commit (@pxref{Log Buffer}).
+If each file is locked by you and contains changes, commit (a.k.a.@:
+``check-in'') the changes. To do this, Emacs pops up a
+@file{*vc-log*} buffer; type the desired log entry for the new
+revision, followed by @kbd{C-c C-c} to commit (@pxref{Log Buffer}).
@item
If each file is locked by you, but you have not changed it, release
-the lock and make the file read-only again.
+the lock and make the file read-only again. This undoes previous
+check-out operation for files that were not changed since the
+checkout.
@item
If each file is locked by another user, ask whether you want to
steal the lock. If you say yes, the file becomes locked by you,
and a warning message is sent to the user who had formerly locked the
file.
+
+@item
+If files in the fileset are unlocked, but have changes with respect to
+their last revision, offer to claim the lock for each such file or to
+revert the file to the last checked-in revision. (This situation is
+exceptional and should not normally happen.)
@end itemize
These rules also apply when you use CVS in locking mode, except
@@ -642,19 +675,21 @@ and Emacs fails to detect the correct one.
@item
Otherwise, if using CVS, RCS or SRC, you can specify a revision ID.
-If the fileset is modified (or locked), this makes Emacs commit with
-that revision ID@. You can create a new branch by supplying an
-appropriate revision ID (@pxref{Branches}).
-
-If the fileset is unmodified (and unlocked), this checks the specified
-revision into the working tree. You can also specify a revision on
-another branch by giving its revision or branch ID (@pxref{Switching
-Branches}). An empty argument (i.e., @kbd{C-u C-x v v @key{RET}})
-checks out the latest (head) revision on the current branch.
-
-This is silently ignored on a decentralized version control system.
-Those systems do not let you specify your own revision IDs, nor do
-they use the concept of checking out individual files.
+If the fileset is modified (or locked), this makes Emacs commit the
+files with that revision ID@. You can create a new branch by
+supplying an appropriate revision ID (@pxref{Branches}).
+
+If the fileset is unmodified (and unlocked), this checks out the
+specified revision into the working tree. You can also specify a
+revision on another branch by giving its revision or branch ID
+(@pxref{Switching Branches}). An empty argument (i.e., @kbd{C-u C-x v
+v @key{RET}}) checks out the latest (a.k.a.@: ``head'') revision on
+the current branch.
+
+Specifying revision ID in this manner is silently ignored by a
+decentralized version control system. Those systems do not let you
+specify your own revision IDs, nor do they use the concept of checking
+out individual files.
@end itemize
@node Log Buffer
@@ -788,17 +823,21 @@ If Emacs cannot find a version control system to register the file
under, it prompts for a repository type, creates a new repository, and
registers the file into that repository.
- On most version control systems, registering a file with @kbd{C-x v
-i} or @kbd{C-x v v} adds it to the working tree but not to the
-repository. Such files are labeled as @samp{added} in the VC
-Directory buffer, and show a revision ID of @samp{@@@@} in the mode
-line. To make the registration take effect in the repository, you
-must perform a commit (@pxref{Basic VC Editing}). Note that a single
-commit can include both file additions and edits to existing files.
-
- On a locking-based version control system (@pxref{VCS Merging}),
+@cindex added files, VC
+@cindex files added to VCS
+ With most version control systems, registering a file with
+@w{@kbd{C-x v i}} or @w{@kbd{C-x v v}} adds it to the working tree,
+but does not commit it, i.e., doesn't add it to the repository. Such
+files are labeled as @dfn{added} in the VC Directory buffer, and the
+mode line of the buffers visiting such files shows a revision ID of
+@samp{@@@@}. To make the registration take effect in the repository,
+you must commit the newly-added files (@pxref{Basic VC Editing}).
+Note that a single commit can include both file additions and edits to
+files already known to the VCS.
+
+ With a locking-based version control system (@pxref{VCS Merging}),
registering a file leaves it unlocked and read-only. Type @kbd{C-x v
-v} to start editing it.
+v} to check-out the file and start editing it.
@node Old Revisions
@subsection Examining And Comparing Old Revisions
@@ -1563,32 +1602,39 @@ commit will be committed to that specific branch.
@subsubsection Pulling/Pushing Changes into/from a Branch
@table @kbd
+@cindex push changes to upstream (VC)
@item C-x v P
-On a decentralized version control system, update another location
-with changes from the current branch (a.k.a. ``push'' changes). This
-concept does not exist for centralized version control systems
+With a decentralized version control system, update another repository
+with locally-committed changes from the current branch (a.k.a.@:
+@dfn{push} changes). This concept does not exist for centralized
+version control systems
+@cindex pull changes from upstream (VC)
@item C-x v +
-On a decentralized version control system, update the current branch
-by ``pulling in'' changes from another location.
+With a decentralized version control system, update the current branch
+of the local repository by @dfn{pulling in} changes from another
+repository.
-On a centralized version control system, update the current VC
-fileset.
+With a centralized version control system, update the current VC
+fileset from the repository.
@end table
@kindex C-x v P
@findex vc-push
+@cindex upstream repository
On a decentralized version control system, the command @kbd{C-x v P}
-(@code{vc-push}) updates another location with changes from the
+(@code{vc-push}) updates another location, commonly known as the
+@dfn{upstream repository}, with locally-committed changes from the
current branch. With a prefix argument, it prompts for the exact
version control command to run, which lets you specify where to push
-changes; the default is @kbd{bzr push} with Bazaar, @kbd{git
-push} with Git, and @kbd{hg push} with Mercurial. The default
-commands always push to a default location determined by the version
-control system from your branch configuration.
+changes; the default is @kbd{bzr push} with Bazaar, @kbd{git push}
+with Git, and @kbd{hg push} with Mercurial. The default commands
+always push to the repository in the default location determined by
+the version control system from your branch configuration.
Prior to pushing, you can use @kbd{C-x v O} (@code{vc-log-outgoing})
-to view a log buffer of the changes to be sent. @xref{VC Change Log}.
+to view a log buffer of the changes to be sent upstream. @xref{VC
+Change Log}.
@cindex bound branch (Bazaar VCS)
This command is currently supported only by Bazaar, Git, and Mercurial.
@@ -1602,13 +1648,15 @@ bound.
@kindex C-x v +
@findex vc-pull
- On a decentralized version control system, the command @kbd{C-x v +}
-(@code{vc-pull}) updates the current branch and working tree. It is
-typically used to update a copy of a remote branch. If you supply a
-prefix argument, the command prompts for the exact version control
-command to use, which lets you specify where to pull changes from.
-Otherwise, it pulls from a default location determined by the version
-control system.
+ With a decentralized version control system, the command @kbd{C-x v
++} (@code{vc-pull}) updates the current branch of the local repository
+and it working tree with changes made in the upstream repository. It
+is typically used to update a copy (a.k.a.@: @dfn{clone}) of a remote
+branch. If you supply a prefix argument, the command prompts for the
+exact version control command to use, which lets you specify where to
+pull changes from. Otherwise, it pulls from the repository in the
+default location determined by the version control system from your
+branch configuration.
Amongst decentralized version control systems, @kbd{C-x v +} is
currently supported only by Bazaar, Git, and Mercurial. With Bazaar,
@@ -1624,7 +1672,7 @@ the working directory.
to view a log buffer of the changes to be applied. @xref{VC Change
Log}.
- On a centralized version control system like CVS, @kbd{C-x v +}
+ With a centralized version control system like CVS, @kbd{C-x v +}
updates the current VC fileset from the repository.
@node Merging
@@ -1633,36 +1681,36 @@ updates the current VC fileset from the repository.
@table @kbd
@item C-x v m
-On a decentralized version control system, merge changes from another
+With a decentralized version control system, merge changes from another
branch into the current one.
-On a centralized version control system, merge changes from another
+With a centralized version control system, merge changes from another
branch into the current VC fileset.
@end table
While developing a branch, you may sometimes need to @dfn{merge} in
changes that have already been made in another branch. This is not a
-trivial operation, as overlapping changes may have been made to the
-two branches.
-
- On a decentralized version control system, merging is done with the
-command @kbd{C-x v m} (@code{vc-merge}). On Bazaar, this prompts for
-the exact arguments to pass to @kbd{bzr merge}, offering a
-sensible default if possible. On Git, this prompts for the name of a
-branch to merge from, with completion (based on the branch names known
-to the current repository). With Mercurial, this prompts for argument
-to pass to @kbd{hg merge}. The output from running the merge
-command is shown in a separate buffer.
-
- On a centralized version control system like CVS, @kbd{C-x v m}
+trivial operation, as overlapping and conflicting changes may have
+been made to the two branches.
+
+ With a decentralized version control system, you merge changes with
+the command @kbd{C-x v m} (@code{vc-merge}). With Bazaar, this
+prompts for the exact arguments to pass to the @command{bzr merge}
+command, offering a sensible default if possible. With Git, this
+prompts for the name of a branch to merge from, with completion (based
+on the branch names known to the current repository). With Mercurial,
+this prompts for argument to pass to @command{hg merge}. The output
+from running the merge command is shown in a separate buffer.
+
+ With a centralized version control system like CVS, @kbd{C-x v m}
prompts for a branch ID, or a pair of revision IDs (@pxref{Switching
Branches}); then it finds the changes from that branch, or the changes
between the two revisions you specified, and merges those changes into
-the current VC fileset. If you just type @kbd{@key{RET}}, Emacs simply
-merges any changes that were made on the same branch since you checked
-the file out.
+the current VC fileset. If you just type @kbd{@key{RET}} at the
+prompt, Emacs simply merges any changes that were made on the same
+branch since you checked the file out.
-@cindex conflicts
+@cindex conflicts, VC
@cindex resolving conflicts
Immediately after performing a merge, only the working tree is
modified, and you can review the changes produced by the merge with
@@ -1671,9 +1719,12 @@ two branches contained overlapping changes, merging produces a
@dfn{conflict}; a warning appears in the output of the merge command,
and @dfn{conflict markers} are inserted into each affected work file,
surrounding the two sets of conflicting changes. You must then
-resolve the conflict by editing the conflicted files. Once you are
-done, the modified files must be committed in the usual way for the
-merge to take effect (@pxref{Basic VC Editing}).
+resolve the conflict by editing the conflicted files; by default,
+Emacs will place buffers with VC conflicts in the special Smerge mode,
+which provides special commands for resolving the merge conflicts.
+Once you are done with resolving the conflicts and have saved the
+files with resolved conflicts, those files must be committed in the
+usual way for the merge to take effect (@pxref{Basic VC Editing}).
@node Creating Branches
@subsubsection Creating New Branches
@@ -1742,6 +1793,14 @@ project. Also, the VC-aware Project back-end considers ``untracked''
files by default. That behavior is controllable with the variable
@code{project-vc-include-untracked}.
+@cindex current project name on mode line
+@defopt project-mode-line
+If this user option is non-@code{nil}, Emacs displays the name of the
+current project (if any) on the mode line; clicking @kbd{mouse-1} on
+the project name pops up the menu with the project-related commands.
+The default value is @code{nil}.
+@end defopt
+
@menu
* Project File Commands:: Commands for handling project files.
* Project Buffer Commands:: Commands for handling project buffers.
@@ -1803,7 +1862,7 @@ prompt you for the project directory.
@vindex vc-directory-exclusion-list
The command @kbd{C-x p f} (@code{project-find-file}) is a convenient
way of visiting files (@pxref{Visiting}) that belong to the current
-project. Unlike @kbd{C-x C-f}, this command doesn't require to type
+project. Unlike @kbd{C-x C-f}, this command doesn't require typing
the full file name of the file to visit, you can type only the file's
base name (i.e., omit the leading directories). In addition, the
completion candidates considered by the command include only the files
@@ -2657,8 +2716,8 @@ definitions have tag names like @samp{operator+}. If you specify the
@samp{--class-qualify} option, tags for variables and functions in
classes are named @samp{@var{class}::@var{variable}} and
@samp{@var{class}::@var{function}}. By default, class methods and
-members are not class-qualified, which allows to identify their names in
-the sources more accurately.
+members are not class-qualified, which facilitates identifying their
+names in the sources more accurately.
@item
In Java code, tags include all the constructs recognized in C++, plus
diff --git a/doc/emacs/mark.texi b/doc/emacs/mark.texi
index 3f1c76c1591..0d705769f55 100644
--- a/doc/emacs/mark.texi
+++ b/doc/emacs/mark.texi
@@ -1,5 +1,5 @@
@c This is part of the Emacs manual.
-@c Copyright (C) 1985--1987, 1993--1995, 1997, 2001--2023 Free Software
+@c Copyright (C) 1985--1987, 1993--1995, 1997, 2001--2024 Free Software
@c Foundation, Inc.
@c See file emacs.texi for copying conditions.
@node Mark
diff --git a/doc/emacs/mini.texi b/doc/emacs/mini.texi
index a104cd2bfa1..30a61a02f06 100644
--- a/doc/emacs/mini.texi
+++ b/doc/emacs/mini.texi
@@ -1,6 +1,6 @@
@c -*- coding: utf-8 -*-
@c This is part of the Emacs manual.
-@c Copyright (C) 1985--1987, 1993--1995, 1997, 2000--2023 Free Software
+@c Copyright (C) 1985--1987, 1993--1995, 1997, 2000--2024 Free Software
@c Foundation, Inc.
@c See file emacs.texi for copying conditions.
@node Minibuffer
diff --git a/doc/emacs/misc.texi b/doc/emacs/misc.texi
index 7a88b7ef5e0..7eb28f56826 100644
--- a/doc/emacs/misc.texi
+++ b/doc/emacs/misc.texi
@@ -1,5 +1,5 @@
@c This is part of the Emacs manual.
-@c Copyright (C) 1985--2023 Free Software Foundation, Inc.
+@c Copyright (C) 1985--2024 Free Software Foundation, Inc.
@c See file emacs.texi for copying conditions.
@iftex
@chapter Miscellaneous Commands
@@ -399,18 +399,18 @@ vulnerable to a variety of attacks, and you may want to avoid using
these if what you're doing requires higher security. (This is the
@code{ssl} check in @code{network-security-protocol-checks}).
+@item Triple DES (or @acronym{3DES}) cipher
+The @acronym{3DES} stream cipher provides at most 112 bits of
+effective security, and a major security vulnerability in it was
+disclosed in 2016 (CVE-2016-2183). It has been deprecated by NIST in
+all applications from late 2023 onwards. (This is the
+@code{3des-cipher} check in @code{network-security-protocol-checks}).
@end table
If @code{network-security-level} is @code{high}, the following checks
will be made, in addition to the above:
@table @asis
-@item @acronym{3DES} cipher
-The @acronym{3DES} stream cipher provides at most 112 bits of
-effective security, which is considered to be towards the low end.
-(This is the @code{3des} check in
-@code{network-security-protocol-checks}).
-
@item a validated certificate changes the public key
Servers change their keys occasionally, and that is normally nothing
to be concerned about. However, if you are worried that your network
@@ -2078,6 +2078,18 @@ files. When this option is given, the arguments to
@command{emacsclient} are interpreted as a list of expressions to
evaluate, @emph{not} as a list of files to visit.
+@vindex server-eval-args-left
+Passing complex Lisp expression via the @option{--eval} command-line
+option sometimes requires elaborate escaping of characters special to
+the shell. To avoid this, you can pass arguments to Lisp functions in
+your expression as additional separate arguments to
+@command{emacsclient}, and use @var{server-eval-args-left} in the
+expression to access those arguments. Be careful to have your
+expression remove the processed arguments from
+@var{server-eval-args-left} regardless of whether your code succeeds,
+for example by using @code{pop}, otherwise Emacs will attempt to
+evaluate those arguments as separate Lisp expressions.
+
@item -f @var{server-file}
@itemx --server-file=@var{server-file}
Specify a server file (@pxref{TCP Emacs server}) for connecting to an
@@ -2146,7 +2158,7 @@ overrides the environment variable.)
Create a new client frame on the current text terminal, instead of
using an existing Emacs frame. This behaves just like the @samp{-c}
option, described above, except that it creates a text terminal frame
-(@pxref{Non-Window Terminals}).
+(@pxref{Text Terminals}).
On MS-Windows, @samp{-t} behaves just like @samp{-c} if the Emacs
server is using the graphical display, but if the Emacs server is
@@ -2839,8 +2851,11 @@ want it to preserve certain buffers, customize the variable
@code{desktop-clear-preserve-buffers-regexp}, whose value is a regular
expression matching the names of buffers not to kill.
+@vindex desktop-globals-to-save
If you want to save minibuffer history from one session to
-another, use the @code{savehist} library.
+another, use the @code{savehist} library. You can also save selected
+minibuffer-history variables as part of @code{desktop-save-mode} if
+you add those variables to the value of @code{desktop-globals-to-save}.
@node Recursive Edit
@section Recursive Editing Levels
diff --git a/doc/emacs/modes.texi b/doc/emacs/modes.texi
index d2f96af0b55..2776dc72a27 100644
--- a/doc/emacs/modes.texi
+++ b/doc/emacs/modes.texi
@@ -1,6 +1,6 @@
@c -*- coding: utf-8 -*-
@c This is part of the Emacs manual.
-@c Copyright (C) 1985--1987, 1993--1995, 1997, 2000--2023 Free Software
+@c Copyright (C) 1985--1987, 1993--1995, 1997, 2000--2024 Free Software
@c Foundation, Inc.
@c See file emacs.texi for copying conditions.
@node Modes
diff --git a/doc/emacs/msdos-xtra.texi b/doc/emacs/msdos-xtra.texi
index 11e63be51a0..74bb68d0547 100644
--- a/doc/emacs/msdos-xtra.texi
+++ b/doc/emacs/msdos-xtra.texi
@@ -1,5 +1,5 @@
@c This is part of the Emacs manual.
-@c Copyright (C) 2004--2023 Free Software Foundation, Inc.
+@c Copyright (C) 2004--2024 Free Software Foundation, Inc.
@c See file emacs.texi for copying conditions.
@c
@c This file is included either in emacs-xtra.texi (when producing the
diff --git a/doc/emacs/msdos.texi b/doc/emacs/msdos.texi
index 52561ec9a33..b00f116ee4e 100644
--- a/doc/emacs/msdos.texi
+++ b/doc/emacs/msdos.texi
@@ -1,5 +1,5 @@
@c This is part of the Emacs manual.
-@c Copyright (C) 1985--1987, 1993--1995, 1997, 2000--2023 Free Software
+@c Copyright (C) 1985--1987, 1993--1995, 1997, 2000--2024 Free Software
@c Foundation, Inc.
@c See file emacs.texi for copying conditions.
@node Microsoft Windows
@@ -412,10 +412,10 @@ this option can be one of the following symbols:
@itemx nil
Emulate @sc{gnu} systems; this is the default. This sets
@code{ls-lisp-ignore-case} and @code{ls-lisp-dirs-first} to
-@code{nil}, and @code{ls-lisp-verbosity} to @code{(links uid gid)}.
+@code{nil}, and @code{ls-lisp-verbosity} to @code{(links uid gid modes)}.
@item UNIX
Emulate Unix systems. Like @code{GNU}, but sets
-@code{ls-lisp-verbosity} to @code{(links uid)}.
+@code{ls-lisp-verbosity} to @code{(links uid modes)}.
@item MacOS
Emulate macOS@. Sets @code{ls-lisp-ignore-case} to @code{t}, and
@code{ls-lisp-dirs-first} and @code{ls-lisp-verbosity} to @code{nil}.
diff --git a/doc/emacs/mule.texi b/doc/emacs/mule.texi
index 3a4ff5baccf..a16a9ea8f71 100644
--- a/doc/emacs/mule.texi
+++ b/doc/emacs/mule.texi
@@ -1,6 +1,6 @@
@c -*- coding: utf-8 -*-
@c This is part of the Emacs manual.
-@c Copyright (C) 1997, 1999--2023 Free Software Foundation, Inc.
+@c Copyright (C) 1997, 1999--2024 Free Software Foundation, Inc.
@c See file emacs.texi for copying conditions.
@node International
@chapter International Character Set Support
diff --git a/doc/emacs/package.texi b/doc/emacs/package.texi
index b294e3d58bd..c8f790bab47 100644
--- a/doc/emacs/package.texi
+++ b/doc/emacs/package.texi
@@ -1,5 +1,5 @@
@c This is part of the Emacs manual.
-@c Copyright (C) 1985--1987, 1993--1995, 1997, 2000--2023 Free Software
+@c Copyright (C) 1985--1987, 1993--1995, 1997, 2000--2024 Free Software
@c Foundation, Inc.
@c See file emacs.texi for copying conditions.
@node Packages
@@ -690,13 +690,13 @@ an Org file.
@item :make
A string or list of strings providing the target or targets defined in
the repository Makefile which should run before building the Info
-file. Only takes effect when @code{package-vc-allow-side-effects} is
-non-nil.
+file. Only takes effect when @code{package-vc-allow-build-commands}
+is non-nil.
@item :shell-command
A string providing the shell command to run before building the Info
-file. Only takes effect when @code{package-vc-allow-side-effects} is
-non-@code{nil}.
+file. Only takes effect when @code{package-vc-allow-build-commands}
+is non-@code{nil}.
@item :vc-backend
A symbol naming the VC backend to use for downloading a copy of the
diff --git a/doc/emacs/picture-xtra.texi b/doc/emacs/picture-xtra.texi
index d155a34951d..1eabd54af11 100644
--- a/doc/emacs/picture-xtra.texi
+++ b/doc/emacs/picture-xtra.texi
@@ -1,5 +1,5 @@
@c This is part of the Emacs manual.
-@c Copyright (C) 2004--2023 Free Software Foundation, Inc.
+@c Copyright (C) 2004--2024 Free Software Foundation, Inc.
@c See file emacs.texi for copying conditions.
@c
@c This file is included either in emacs-xtra.texi (when producing the
diff --git a/doc/emacs/programs.texi b/doc/emacs/programs.texi
index 40746e03ecc..1627e7e6cb7 100644
--- a/doc/emacs/programs.texi
+++ b/doc/emacs/programs.texi
@@ -1,6 +1,6 @@
@c -*- coding: utf-8 -*-
@c This is part of the Emacs manual.
-@c Copyright (C) 1985--1987, 1993--1995, 1997, 1999--2023 Free Software
+@c Copyright (C) 1985--1987, 1993--1995, 1997, 1999--2024 Free Software
@c Foundation, Inc.
@c See file emacs.texi for copying conditions.
@node Programs
@@ -1402,6 +1402,13 @@ asynchronously. You can force the invocation to be synchronous by
customizing @code{Man-prefer-synchronous-calls} to a non-@code{nil}
value.
+@vindex Man-support-remote-systems
+ If the user option @code{Man-support-remote-systems} is
+non-@code{nil}, and @code{default-directory} indicates a remote system
+(@pxref{Remote Files}), the man page is taken from the remote system.
+Calling the @code{man} command with a prefix like @kbd{C-u M-x man}
+reverts the value of @code{Man-support-remote-systems} for that call.
+
@findex woman
@cindex manual pages, on MS-DOS/MS-Windows
An alternative way of reading manual pages is the @kbd{M-x woman}
@@ -1694,6 +1701,17 @@ completion to the buffer. @xref{Completion}.
In Text mode and related modes, @kbd{M-@key{TAB}} completes words
based on the spell-checker's dictionary. @xref{Spelling}.
+@cindex completion preview
+@cindex preview completion
+@cindex suggestion preview
+@cindex Completion Preview mode
+@findex completion-preview-mode
+ Completion Preview mode is a minor mode that shows completion
+suggestions as you type. When you enable this mode (with @kbd{M-x
+completion-preview-mode}), Emacs automatically displays the
+suggested completion for text around point as an in-line preview
+right after point; type @key{TAB} to accept the suggestion.
+
@node MixedCase Words
@section MixedCase Words
@cindex camel case
diff --git a/doc/emacs/regs.texi b/doc/emacs/regs.texi
index e52f68dd18e..fdcddbbc739 100644
--- a/doc/emacs/regs.texi
+++ b/doc/emacs/regs.texi
@@ -1,5 +1,5 @@
@c This is part of the Emacs manual.
-@c Copyright (C) 1985--1987, 1993--1995, 1997, 2001--2023 Free Software
+@c Copyright (C) 1985--1987, 1993--1995, 1997, 2001--2024 Free Software
@c Foundation, Inc.
@c See file emacs.texi for copying conditions.
@node Registers
@@ -16,9 +16,8 @@ jump back to that position once or many times.
we will denote by @var{r}; @var{r} can be a letter (such as @samp{a})
or a number (such as @samp{1}); case matters, so register @samp{a} is
not the same as register @samp{A}. You can also set a register in
-non-alphanumeric characters, for instance @samp{*} or @samp{C-d}.
-Note, it's not possible to set a register in @samp{C-g} or @samp{ESC},
-because these keys are reserved for quitting (@pxref{Quitting}).
+non-alphanumeric characters, for instance @samp{C-d} by using for
+example @key{C-q} @samp{C-d}.
@findex view-register
A register can store a position, a piece of text, a rectangle, a
@@ -33,14 +32,53 @@ view-register}:
Display a description of what register @var{r} contains.
@end table
-@vindex register-preview-delay
+
@cindex preview of registers
- All of the commands that prompt for a register will display a
-preview window that lists the existing registers (if there are
-any) after a short delay. To change the length of the delay,
-customize @code{register-preview-delay}. To prevent this display, set
-that option to @code{nil}. You can explicitly request a preview
-window by pressing @kbd{C-h} or @key{F1}.
+@vindex register-use-preview
+ All of the commands that prompt for a register will by default
+display a preview window that lists the existing registers (if there
+are any) and their current values, after a short delay. This and
+other aspects of prompting for a register can be customized by setting
+the value of @code{register-use-preview}, which can have the following
+values:
+
+@table @code
+@vindex register-preview-delay
+@item traditional
+With this value, which is the default, Emacs behaves like it did in
+all the versions before Emacs 29: it shows a preview of existing registers
+after a delay, and lets you overwrite the values of existing registers
+by typing a single character, the name of the register. The preview
+appears after the delay determined by the customizable variable
+@code{register-preview-delay}, which specifies the delay in seconds;
+setting it to @code{nil} disables the preview (but you can still
+explicitly request a preview window by pressing @kbd{C-h} or
+@key{F1} when Emacs prompts for a register).
+
+@item t
+This value requests a more flexible preview of existing registers.
+The preview appears immediately when Emacs prompts for a register
+(thus @code{register-preview-delay} has no effect), and the preview
+window provides navigation: by using @kbd{C-n} and @kbd{C-p} (or the
+@kbd{@key{UP}} and @kbd{@key{DOWN}} arrow keys), you can move between
+the registers in the preview window. To overwrite the value of an
+existing registers in this mode, you need to type @key{RET} after
+selecting the register by navigation or typing its name.
+
+In addition, the registers shown by the preview are filtered according
+to the command that popped the preview: for example, the preview shown
+by @code{insert-register} will only show registers whose values can be
+inserted into the buffer, omitting registers which hold window
+configurations, positions, and other un-insertable values.
+
+@item nil
+This value requests behavior similar to @code{traditional}, but the
+preview is shown without delay, and is filtered according to the
+command.
+
+@item never
+This value is like @code{nil}, but it disables the preview.
+@end table
@dfn{Bookmarks} record files and positions in them, so you can
return to those positions when you look at the file again. Bookmarks
diff --git a/doc/emacs/rmail.texi b/doc/emacs/rmail.texi
index 382254cc11b..51bd6086ce0 100644
--- a/doc/emacs/rmail.texi
+++ b/doc/emacs/rmail.texi
@@ -1,5 +1,5 @@
@c This is part of the Emacs manual.
-@c Copyright (C) 1985--1987, 1993--1995, 1997, 2001--2023 Free Software
+@c Copyright (C) 1985--1987, 1993--1995, 1997, 2001--2024 Free Software
@c Foundation, Inc.
@c See file emacs.texi for copying conditions.
@node Rmail
diff --git a/doc/emacs/screen.texi b/doc/emacs/screen.texi
index 5e9e89e6b11..6b09dcb8e0a 100644
--- a/doc/emacs/screen.texi
+++ b/doc/emacs/screen.texi
@@ -1,5 +1,5 @@
@c This is part of the Emacs manual.
-@c Copyright (C) 1985--1987, 1993--1995, 1997, 2001--2023 Free Software
+@c Copyright (C) 1985--1987, 1993--1995, 1997, 2001--2024 Free Software
@c Foundation, Inc.
@c See file emacs.texi for copying conditions.
@node Screen
@@ -173,7 +173,7 @@ unselected windows, in order to make it stand out.
The text displayed in the mode line has the following format:
@example
- @var{cs}:@var{ch}-@var{fr} @var{buf} @var{pos} @var{line} (@var{major} @var{minor})
+ @var{cs}:@var{ch}-@var{d}@var{fr} @var{buf} @var{pos} @var{line} (@var{major} @var{minor})
@end example
@noindent
@@ -231,6 +231,12 @@ shows @samp{%*} if the buffer is modified, and @samp{%%} otherwise.
However, if @code{default-directory} (@pxref{File Names}) for the
current buffer is on a remote machine, @samp{@@} is displayed instead.
+ @var{d} appears if the window is dedicated to its current buffer.
+It appears as @samp{D} for strong dedication and @samp{d} for other
+forms of dedication. If the window is not dedicated, @var{d} does not
+appear. @xref{Dedicated Windows,, elisp, The Emacs Lisp Reference
+Manual}.
+
@var{fr} gives the selected frame name (@pxref{Frames}). It appears
only on text terminals. The initial frame's name is @samp{F1}.
diff --git a/doc/emacs/search.texi b/doc/emacs/search.texi
index 6d8b3a2727a..9ba425f2d21 100644
--- a/doc/emacs/search.texi
+++ b/doc/emacs/search.texi
@@ -1,6 +1,6 @@
@c -*- coding: utf-8 -*-
@c This is part of the Emacs manual.
-@c Copyright (C) 1985--1987, 1993--1995, 1997, 2000--2023 Free Software
+@c Copyright (C) 1985--1987, 1993--1995, 1997, 2000--2024 Free Software
@c Foundation, Inc.
@c See file emacs.texi for copying conditions.
@node Search
@@ -407,8 +407,11 @@ characters, that disables character folding during that search.
@cindex invisible text, searching for
@kindex M-s i @r{(Incremental search)}
@findex isearch-toggle-invisible
- To toggle whether or not invisible text is searched, type
-@kbd{M-s i} (@code{isearch-toggle-invisible}). @xref{Outline Search}.
+ To toggle whether or not the search will find text made invisible by
+overlays, type @kbd{M-s i} (@code{isearch-toggle-invisible}).
+@xref{Outline Search}. To make all incremental searches find matches
+inside invisible text, whether due to text properties or overlay
+properties, customize @code{search-invisible} to the value @code{t}.
@kindex M-r @r{(Incremental Search)}
@kindex M-s r @r{(Incremental Search)}
@@ -1159,6 +1162,8 @@ surrounding @samp{\( @dots{} \)} grouping can limit the grouping power of
Full backtracking capability exists to handle multiple uses of @samp{\|}.
+@cindex sub-expressions, in regular expressions
+@cindex grouping, in regular expressions
@item \( @dots{} \)
is a grouping construct that serves three purposes:
diff --git a/doc/emacs/sending.texi b/doc/emacs/sending.texi
index 6b94cd0b737..7d9f4917929 100644
--- a/doc/emacs/sending.texi
+++ b/doc/emacs/sending.texi
@@ -1,5 +1,5 @@
@c This is part of the Emacs manual.
-@c Copyright (C) 1985--1987, 1993--1995, 1997, 2000--2023 Free Software
+@c Copyright (C) 1985--1987, 1993--1995, 1997, 2000--2024 Free Software
@c Foundation, Inc.
@c See file emacs.texi for copying conditions.
@node Sending Mail
@@ -257,6 +257,24 @@ of the address, such as the person's full name. Emacs puts them in if
they are needed. For instance, it inserts the above address as
@samp{"John Q. Smith" <none@@example.com>}.
+@findex rebuild-mail-abbrevs
+@findex merge-mail-abbrevs
+ After editing the @file{~/.mailrc} file, or if the file was modified
+outside of Emacs, you can update the mail aliases used by a running
+Emacs session with @w{@kbd{M-x rebuild-mail-abbrevs @key{RET}}}. This
+prompts for the name of the file to use, the default being the value
+of @code{mail-personal-alias-file}. A similar command
+@code{merge-mail-abbrevs} prompts for a file with mail aliases, then
+merges the aliases in that file with the existing ones.
+
+@findex define-mail-abbrev
+ Alternatively, you can use Emacs commands to define mail aliases.
+The command @code{define-mail-abbrev} prompts for the alias and the
+full address, and defines the alias to expand to the full address.
+Emacs will save the added aliases whenever it offers to save all
+files (for @kbd{C-x s} or @kbd{C-x C-c}), like it does with other
+abbrevs (@pxref{Saving Abbrevs}).
+
Emacs also recognizes include commands in @file{~/.mailrc}. They
look like this:
@@ -282,6 +300,10 @@ fields, such as @samp{Subject}.
@kbd{M-x mail-abbrev-insert-alias}. This reads an alias name, with
completion, and inserts its definition at point.
+@findex mail-abbrev-complete-alias
+ The command @code{mail-abbrev-complete-alias} completes on the mail
+alias preceding point.
+
@node Mail Commands
@section Mail Commands
@cindex Message mode
diff --git a/doc/emacs/text.texi b/doc/emacs/text.texi
index 3d3f2562617..338bf014208 100644
--- a/doc/emacs/text.texi
+++ b/doc/emacs/text.texi
@@ -1,6 +1,6 @@
@c -*- coding: utf-8 -*-
@c This is part of the Emacs manual.
-@c Copyright (C) 1985--1987, 1993--1995, 1997, 2000--2023 Free Software
+@c Copyright (C) 1985--1987, 1993--1995, 1997, 2000--2024 Free Software
@c Foundation, Inc.
@c See file emacs.texi for copying conditions.
@node Text
@@ -943,12 +943,12 @@ situations where you shouldn't change the major mode---in mail
composition, for instance.
@kindex M-TAB @r{(Text mode)}
- Text mode binds @kbd{M-@key{TAB}} to @code{ispell-complete-word}.
-This command performs completion of the partial word in the buffer
-before point, using the spelling dictionary as the space of possible
-words. @xref{Spelling}. If your window manager defines
-@kbd{M-@key{TAB}} to switch windows, you can type @kbd{@key{ESC}
-@key{TAB}} or @kbd{C-M-i} instead.
+ The command @kbd{M-@key{TAB}} (@code{completion-at-point}) performs
+completion of the partial word in the buffer before point, using the
+spelling dictionary as the space of possible words by default.
+@xref{Spelling}. If your window manager defines @kbd{M-@key{TAB}} to
+switch windows, you can type @kbd{@key{ESC} @key{TAB}} or @kbd{C-M-i}
+instead.
@vindex text-mode-hook
Entering Text mode runs the mode hook @code{text-mode-hook}
@@ -1024,10 +1024,11 @@ addition to ellipsis, to show that a section is hidden. Clicking the
mouse on the button toggles display of the section. If the value of
this variable is @code{insert}, the buttons are inserted directly into
the buffer text, so @key{RET} on the button will also toggle display
-of the section, like a mouse click does. If the value is
-@code{in-margins}, Outline minor mode will use the window margins to
-indicate that a section is hidden. The buttons are customizable as icons
-(@pxref{Icons}).
+of the section, like a mouse click does. Using the value @code{insert}
+is not recommended in editable buffers because it modifies them.
+If the value is @code{in-margins}, Outline minor mode will use the
+window margins to indicate that a section is hidden. The buttons are
+customizable as icons (@pxref{Icons}).
@vindex outline-minor-mode-cycle
If the @code{outline-minor-mode-cycle} user option is
diff --git a/doc/emacs/trouble.texi b/doc/emacs/trouble.texi
index d2e8ac3452a..22042b4c92c 100644
--- a/doc/emacs/trouble.texi
+++ b/doc/emacs/trouble.texi
@@ -1,5 +1,5 @@
@c This is part of the Emacs manual.
-@c Copyright (C) 1985--1987, 1993--1995, 1997, 2001--2023 Free Software
+@c Copyright (C) 1985--1987, 1993--1995, 1997, 2001--2024 Free Software
@c Foundation, Inc.
@c See file emacs.texi for copying conditions.
@iftex
@@ -1514,7 +1514,7 @@ Appendix, elisp, Emacs Lisp Reference}.
@end ifclear
@item
-Avoid using @code{defadvice} or @code{with-eval-after-load} for Lisp code
+Avoid using @code{advice-add} or @code{with-eval-after-load} for Lisp code
to be included in Emacs.
@item
diff --git a/doc/emacs/vc-xtra.texi b/doc/emacs/vc-xtra.texi
index 3b0471872a2..5008cf2773b 100644
--- a/doc/emacs/vc-xtra.texi
+++ b/doc/emacs/vc-xtra.texi
@@ -1,5 +1,5 @@
@c This is part of the Emacs manual.
-@c Copyright (C) 2004--2023 Free Software Foundation, Inc.
+@c Copyright (C) 2004--2024 Free Software Foundation, Inc.
@c See file emacs.texi for copying conditions.
@c
@c This file is included in emacs-xtra.texi when producing the printed
diff --git a/doc/emacs/vc1-xtra.texi b/doc/emacs/vc1-xtra.texi
index 3785e565676..303efa05d82 100644
--- a/doc/emacs/vc1-xtra.texi
+++ b/doc/emacs/vc1-xtra.texi
@@ -1,5 +1,5 @@
@c This is part of the Emacs manual.
-@c Copyright (C) 2004--2023 Free Software Foundation, Inc.
+@c Copyright (C) 2004--2024 Free Software Foundation, Inc.
@c See file emacs.texi for copying conditions.
@c
@c This file is included either in vc-xtra.texi (when producing the
diff --git a/doc/emacs/windows.texi b/doc/emacs/windows.texi
index 665fd80e53b..f1f7a5b4b86 100644
--- a/doc/emacs/windows.texi
+++ b/doc/emacs/windows.texi
@@ -1,5 +1,5 @@
@c This is part of the Emacs manual.
-@c Copyright (C) 1985--1987, 1993--1995, 1997, 2000--2023 Free Software
+@c Copyright (C) 1985--1987, 1993--1995, 1997, 2000--2024 Free Software
@c Foundation, Inc.
@c See file emacs.texi for copying conditions.
@node Windows
@@ -411,6 +411,28 @@ selected window and (ii) prefer to either create a new frame or use a
window on some other frame to display the desired buffer. Several of
these commands are bound in the @kbd{C-x 5} prefix key.
+@cindex dedicated window
+ Sometimes, a window is ``dedicated'' to its current buffer.
+@xref{Dedicated Windows,, elisp, The Emacs Lisp Reference Manual}.
+@code{display-buffer} will avoid reusing dedicated windows most of the
+time. This is indicated by a @samp{d} in the mode line (@pxref{Mode
+Line}). A window can also be strongly dedicated, which prevents any
+changes to the buffer displayed in the window. This is indicated by a
+@samp{D} in the mode line.
+
+Usually, dedicated windows are used to display specialized buffers,
+but dedication can sometimes be useful interactively. For example,
+when viewing errors with @kbd{M-g M-n} @code{next-error}, newly
+displayed source code may replace a buffer you want to refer to. If
+you dedicate a window to that buffer, the command (through
+@code{display-buffer}) will prefer to use a different window instead.
+
+@kindex C-x w d
+@findex toggle-window-dedicated
+ Toggle whether the selected window is dedicated to the current
+buffer. With a prefix argument, make the window strongly dedicated
+instead.
+
@menu
* Window Choice:: How @code{display-buffer} works.
* Temporary Displays:: Displaying non-editable buffers.
@@ -642,7 +664,7 @@ to the window-local tab line of buffers, and clicking on the @kbd{x}
icon of a tab deletes it. The mouse wheel on the tab line scrolls
the tabs horizontally.
- Touch screen input (@pxref{Other Input Devices}) can also be used to
+ Touch screen input (@pxref{Other Input}) can also be used to
interact with the ``tab line''. Long-pressing (@pxref{Touchscreens})
a tab will display a context menu with items that operate on the tab
that was pressed; tapping a tab itself will result in switching to
diff --git a/doc/emacs/xresources.texi b/doc/emacs/xresources.texi
index ee054430766..bbdb7ee8876 100644
--- a/doc/emacs/xresources.texi
+++ b/doc/emacs/xresources.texi
@@ -1,5 +1,5 @@
@c This is part of the Emacs manual.
-@c Copyright (C) 1987, 1993--1995, 1997, 2001--2023 Free Software
+@c Copyright (C) 1987, 1993--1995, 1997, 2001--2024 Free Software
@c Foundation, Inc.
@c See file emacs.texi for copying conditions.
@node X Resources
diff --git a/doc/lang/fr/misc/ses-fr.texi b/doc/lang/fr/misc/ses-fr.texi
new file mode 100644
index 00000000000..e1b9cac5fc3
--- /dev/null
+++ b/doc/lang/fr/misc/ses-fr.texi
@@ -0,0 +1,1631 @@
+\input texinfo @c -*- mode: texinfo; coding: utf-8; -*-
+@c %**start of header
+@setfilename ../../../../info/ses-fr.info
+@documentlanguage fr
+@documentencoding UTF-8
+@settitle @acronym{SES}: Le tableur simple d’Emacs
+@include docstyle.texi
+@setchapternewpage off
+@syncodeindex fn cp
+@syncodeindex vr cp
+@syncodeindex ky cp
+@c %**end of header
+
+@copying
+Ce fichier documente @acronym{SES} : le tableur simple d’Emacs (Simple
+Emacs Spreadsheet).
+
+Copyright @copyright{} 2002--2024 Free Software Foundation, Inc.
+
+@quotation
+Permission is granted to copy, distribute and/or modify this document
+under the terms of the GNU Free Documentation License, Version 1.3 or
+any later version published by the Free Software Foundation; with no
+Invariant Sections, with the Front-Cover Texts being ``A GNU Manual,''
+and with the Back-Cover Texts as in (a) below. A copy of the license
+is included in the section entitled ``GNU Free Documentation License.''
+
+(a) The FSF's Back-Cover Text is: ``You have the freedom to copy and
+modify this GNU manual.''
+@end quotation
+@end copying
+
+@dircategory Emacs misc features
+@direntry
+* @acronym{SES}-fr: (ses-fr). Le tableur simple d’Emacs.
+@end direntry
+
+@finalout
+
+@titlepage
+@title @acronym{SES}
+@subtitle Le tableur simple d’Emacs
+@author Jonathan A. Yavner
+@author @email{jyavner@@member.fsf.org}
+
+@page
+@vskip 0pt plus 1filll
+@insertcopying
+@end titlepage
+
+@contents
+
+@c ===================================================================
+
+@ifnottex
+@node Top
+@comment node-name, next, previous, up
+@top @acronym{SES}: Simple Emacs Spreadsheet
+
+@display
+@acronym{SES} est mode majeur de GNU Emacs pour éditer des fichiers
+tableur, c.-à-d.@: des fichiers contenant une grille rectangulaire de
+cellules. Les valeurs des cellules sont spécifiées par des formules
+pouvant se référer aux valeurs d’autres cellules.
+@end display
+@end ifnottex
+
+Pour les rapports d’anomalie, utiliser @kbd{M-x report-emacs-bug}.
+
+@insertcopying
+
+@menu
+* Boniment: Sales Pitch. Pourquoi utiliser @acronym{SES}?
+* Tuto: Quick Tutorial. Une introduction sommaire
+* Les bases: The Basics. Les commandes de base du tableur
+* Fonctions avancées: Advanced Features. Vous voulez en savoir plus ?
+* Pour les gourous: For Gurus. Vous voulez en savoir @emph{encore plus} ?
+* Index: Index. Index des concepts, fonctions et variables
+* Remerciements: Acknowledgments. Remerciements
+* Licence GNU pour la documentation libre: GNU Free Documentation License. La licence de cette documentation.
+@end menu
+
+@c ===================================================================
+
+@node Sales Pitch
+@comment node-name, next, previous, up
+@chapter Boniment
+@cindex features
+
+@itemize --
+@item Créer et éditer des feuilles de calcul avec un minimum de tracas.
+@item Prise en charge complète du Défaire/Refaire/Sauvegarde auto.
+@item Protection contre les virus enfouis dans les feuilles de calcul.
+@item Les formules de cellule sont directement du code Emacs Lisp.
+@item Fonctions d’impression pour contrôler l’apparence des cellules.
+@item Raccourcis clavier intuitifs : C-o = insérer une ligne, M-o = insérer une colonne, etc.
+@item « Débordement » des valeurs de cellule longues dans les cellules vides suivantes.
+@item La ligne d’en-tête montre les lettres désignant les colonnes.
+@item Autocomplétion pour la saisie des symboles de cellules nommées lors de la saisie des formules.
+@item Couper, copier et coller peut transferer les formules et les fonctions d’impression.
+@item Import and export de valeurs séparées par des tabulations, ou de formules séparées par des tabulations.
+@item Format de fichier en texte, facile à bidouiller.
+@end itemize
+
+@c ===================================================================
+
+@node Quick Tutorial
+@chapter Tuto
+@cindex introduction
+@cindex tuto
+
+Si vous désirez être rapidement lancé et pensez que vous savez ce que
+vous attendez d’un tableur simple, alors ce chapitre peut être tout ce
+dont vous avez besoin.
+
+Premièrement, visitez un nouveau fichier avec pour extension de nom de
+fichier @file{.ses}. Emacs vous présente alors une feuille de calcul
+vide contenant une seule cellule.
+
+Commencez par saisir une ligne d’en-tête : @kbd{"Revenu@key{RET}}. Le
+guillemet double @code{"} indique que vous saisissez une cellule
+textuelle, il ne fait pas partie de la valeur de la cellule, et aucun
+guillemet de fermeture n’est nécessaire.
+
+Pour insérer votre première valeur de revenu, vous devez d’abord
+redimensionner la feuille. Appuyer sur la touche @key{TAB} pour
+ajouter une nouvelle cellule et revenez à elle en remontant.
+Saisissez un nombre, tel que @samp{2.23}. Puis continuer pour ajouter
+quelques valeurs supplémentaires de revenu, par ex. :
+
+@example
+@group
+A
+ Revenu
+ 2.23
+ 0.02
+ 15.76
+ -4.00
+@end group
+@end example
+
+Pour additionner les valeurs entre elles, saisissez une expression
+Lisp :
+
+@example
+(+ A2 A3 A4 A5)
+@end example
+
+Peut-être désirez vous ajouter une cellule à la droite de la cellule
+@samp{A4} pour expliquer pourquoi vous avez une valeur négative. En
+appuyant sur @kbd{TAB} dans cette cellule vous ajouter entièrement une
+nouvelle colonne @samp{B} où vous pourrez ajouter une telle note.
+
+La colonne est assez étroite par défaut, mais en appuyant sur @kbd{w}
+vous pouvez la redimensionner selon vos besoins. Faites la de 22
+caractères de large. Vous pouvez maintenant ajoutez des notes
+descriptives pour chacune des cases, par ex.@: :
+
+@example
+@group
+A B
+ Revenu
+ 2.23 Frais de consultation
+ 0.02 Opinion informée
+ 15.76 Stand limonade
+ -4 Prêt à Joseph
+ 14.01 Total
+@end group
+@end example
+
+Par défaut, l’impression des valeurs de cellule se fait alignée à
+droite, c’est la raison d’un tel alignement pour les notes dans la
+colonne @samp{B}. Pour changer cela, vous pouvez saisir une fonction
+d’impression pour la colonne entière, en utilisant par ex. @kbd{M-p
+("%s")}. Le fait que @code{"%s"} soit contenu dans une liste indique à
+@acronym{SES} que l’alignement est à faire à gauche. Vous pouvez
+l’emporter sur la fonction d’impression de colonne pour l’une
+quelconque de ses cellules en donnant une fonction d’impression par
+cellule avec @kbd{p}.
+
+Vous pouvez nommer une fonction d’impression, et utiliser le nom de la
+fonction à la place de sa définition, de sorte à faciliter la
+modification de l’impression de toutes les cellules utilisant cette
+fonction. Par exemple tapez @kbd{M-x
+ses-define-local-printer@key{ret}}, puis @kbd{note@key{ret}}, puis
+@kbd{("%s")} pour définir une fonction d’impression nommée @code{note}
+dont la définition est @code{("%s")}, puis sur la colonne @samp{B} tapez
+@kbd{M-p note@key{ret}}
+
+@example
+@group
+A B
+ Revenu
+ 2.23 Frais de consultation
+ 0.02 Opinion informée
+ 15.76 Stand limonade
+ -4 Prêt à Joseph
+ 14.01 Total
+@end group
+@end example
+
+Si maintenant vous redéfinissez @code{note} avec pour nouvelle
+définition @kbd{("*%s")} qui ajoute un astérisque @code{*} devant le
+texte, la zone d’impression est modifiée ainsi :
+@example
+@group
+A B
+ Revenu
+ 2.23 *Frais de consultation
+ 0.02 *Opinion informée
+ 15.76 *Stand limonade
+ -4 *Prêt à Joseph
+ 14.01 *Total
+@end group
+@end example
+
+Notez que la cellule @samp{B1} reste affichée vide et n’est pas
+affichée comme @samp{*}. C’est parce que la valeur de la cellule est
+@code{nil}, et que les fonctions d’impression définies à partir d’une
+chaîne de formatage comme @code{"%s"} dans @code{("%s")} impriment
+systématiquement @code{nil} comme une chaîne vide, et tentent
+d’imprimer toute valeur non-@code{nil} en utilisant la fonction
+standarde @code{format} avec la chaîne de formatage, et si cela
+échoue, utilisent la fonction de repli @code{ses-prin1} la place.
+
+Si maintenant Joseph rembourse son prêt, vous pourriez effacer cette
+case ; par ex.@: en positionnant le curseur sur la cellule A5 et en
+appuyant sur @kbd{C-d}. Si vous faites celle le total imprimé dans la
+cellule A6 affichera @samp{######}. La raison de cela est la valeur
+dans une cellule vide est typiquement @code{nil} et que l’opérateur
+@code{+} ordinaire échoue à gérer une telle valeur. Au lieu de vider
+la cellule, vous pourriez littéralement saisir @samp{0}, ou supprimer
+entièrement la ligne en utilisant @kbd{C-k}. Une alternative est
+d’utiliser la fonction spéciale @code{ses+} au lieu du @code{+}
+ordinaire :
+
+@example
+(ses+ A2 A3 A4 A5)
+@end example
+
+Pour rendre une formule robuste au changement de géométrie de la
+feuille, vous pouvez utiliser la macro @code{ses-range} pour faire
+référence à une plage de cellules par ses extrémités, par ex. :
+
+@example
+(apply 'ses+ (ses-range A2 A5))
+@end example
+
+(Le @code{apply} est nécessaire parce que @code{ses-range} produite
+une @emph{liste} de valeurs, ce qui ouvre des possibilités plus
+complexes).
+
+Alternativement vous pouvez utiliser le modificateur @code{!} de
+@code{ses-range} pour retirer les cellules vides de la liste renvoyée,
+ce qui permet d’utiliser @code{+} au lieu de @code{ses+}:
+
+@lisp
+(apply '+ (ses-range A2 A5 !))
+@end lisp
+
+@c ===================================================================
+
+@node The Basics
+@comment node-name, next, previous, up
+@chapter Les bases
+@cindex commandes de base
+@cindex base, commandes de
+@findex ses-jump
+@findex ses-mark-row
+@findex ses-mark-column
+@findex ses-mark-whole-buffer
+@findex set-mark-command
+@findex keyboard-quit
+
+Pour créer une nouveau tableur, visitez un fichier inexistant dont le
+nom se termine en @file{.ses}. Par exemple, @kbd{C-x C-f essai.ses
+@key{ret}}.
+
+
+Un @dfn{identificateur de cellule} est un symbole avec une lettre de
+colonne et un numéro de ligne. La cellule B7 est la 2e column de la
+7e ligne. Pour les feuilles très larges, il ya deux lettres de
+colonne : la cellule AB7 les la 28e colonne de la 7e ligne. Les
+feuilles encore plus larges ont AAA1, etc. On se déplace avec les
+commandes ordinaires de déplacement d’Emacs.
+
+@table @kbd
+@item j
+Déplace le point vers la cellule spécifiée par identificateur
+(@code{ses-jump}). À moins que la cellule ne soit une cellule
+renommée, l’identificateur est insensible à la casse. Un argument
+préfixe @math{n} déplace vers la cellule de coordonnées @math{(n\div
+R, n \% C)} pour une feuille de @math{R} ligne et @math{C} colonnes,
+et @samp{A1} étant aux coordonnées @math{(0,0)}. La façon dont
+l’identificateur ou l’argument préfixe de commande sont interprétés
+peut être personnalisée via les variables
+@code{ses-jump-cell-name-function} et @code{ses-jump-prefix-function}.
+@end table
+
+Le Point est toujours sur le bord de gauche d’une cellule, ou à la fin
+de ligne vide. Quand la marque est inactive, la cellule courante est
+soulignée. Quand la marque est active, la plage est le rectangle de
+cellules mis en vedette (@acronym{SES} utilise toujours le mode de
+marque transitoire). Faire glisser la souris de @samp{A1} à @samp{A3}
+crée la plage @samp{A1-A2}. Beaucoup de commandes @acronym{SES}
+opèrent seulement sur une seule cellule, et non sur une plage.
+
+@table @kbd
+@item C-@key{SPC}
+@itemx C-@@
+Règle la marque au point (@code{set-mark-command}).
+
+@item C-g
+Désactive la marque (@code{keyboard-quit}).
+
+@item M-h
+Met en vedette la ligne courante (@code{ses-mark-row}).
+
+@item S-M-h
+Met en vedette la colonne courante (@code{ses-mark-column}).
+
+@item C-x h
+Mettre en vedette toutes les cellules (@code{mark-whole-buffer}).
+@end table
+
+@menu
+* Formules: Formulas.
+* Redimensionner: Resizing.
+* Fonctions d’impression: Printer functions.
+* Effacer des cellules: Clearing cells.
+* Copier/couper/coller: Copy/cut/paste.
+* Personnaliser @acronym{SES}: Customizing @acronym{SES}.
+@end menu
+
+@node Formulas
+@section Formules de cellule
+@cindex formules
+@cindex formules, saisire
+@cindex valeurs
+@cindex valeurs de cellule
+@cindex éditer des cellules
+@findex ses-read-cell
+@findex ses-read-symbole
+@findex ses-edit-cell
+@findex ses-recalculate-cell
+@findex ses-recalculate-all
+
+Pour insérer une valeur dans une cellule, tapez juste une expression
+numérique, un @samp{"texte entre guillemets anglais"}, ou une
+expression Lisp.
+
+@table @kbd
+@item 0..9
+Auto-insérer un nombre (@code{ses-read-cell}).
+
+@item -
+Auto-insérer un nombre négatif (@code{ses-read-cell}).
+
+@item .
+Auto-insérer un nombre décimal (@code{ses-read-cell}).
+
+@item "
+Auto-insérer une chaîne de caractères. Le guillemet anglais de
+terminaison est inséré automatiquement (@code{ses-read-cell}).
+
+@item (
+Auto-insérer une expression. La parenthèse de droite est insérée
+automatiquement (@code{ses-read-cell}). Pour accéder à la valeur
+d’une autre cellule, il suffit d’utiliser son identificateur dans
+votre expression. Dès que l’autre cellule change, la formule de cette
+cellule-ci est réévaluée. En tapant l’expression, vous pouvez
+utiliser les raccourcis clavier suivants :
+@table @kbd
+@item M-@key{TAB}
+pour compléter les noms de symboles, et
+@item C-h C-n
+pour lister les symboles de cellules renommées dans un tampon d’aide.
+@end table
+
+@item ' @r{(apostrophe)}
+Entrer un symbole (@code{ses-read-symbol}). @acronym{SES} se souvient
+de tous les symboles qui ont été utilisés comme formules, de sorte que
+vous pouvez taper juste le début d’un symbole et utiliser
+@kbd{@key{SPC}}, @kbd{@key{TAB}}, et @kbd{?} pour le compléter.
+@end table
+
+Pour saisire quelque-chose d’autre (par ex., un vecteur), commencer
+avec un chiffre, puis effacer le chiffre et tapez ce que vous désirez.
+
+@table @kbd
+@item @key{RET}
+Édite la formule existante dans la cellule courante (@code{ses-edit-cell}).
+
+@item C-c C-c
+Force le recalcul de la cellule ou plage courante (@code{ses-recalculate-cell}).
+
+@item C-c C-l
+Recalcule la feuille entière (@code{ses-recalculate-all}).
+@end table
+
+@node Resizing
+@section Redimensionner la feuille
+@cindex redimensionner des feuilles
+@cindex dimensions
+@cindex ligne, ajout ou suppression
+@cindex colonne, ajout ou suppression
+@cindex ajouter des lignes ou colonnes
+@cindex insérer des lignes ou colonnes
+@cindex enlever des lignes ou colonnes
+@cindex supprimer des lignes ou colonnes
+@findex ses-insert-row
+@findex ses-insert-column
+@findex ses-delete-row
+@findex ses-delete-column
+@findex ses-set-column-width
+@findex ses-forward-or-insert
+@findex ses-append-row-jump-first-column
+
+
+Commande de base :
+
+@table @kbd
+@item C-o
+(@code{ses-insert-row})
+
+@item M-o
+(@code{ses-insert-column})
+
+@item C-k
+(@code{ses-delete-row})
+
+@item M-k
+(@code{ses-delete-column})
+
+@item w
+(@code{ses-set-column-width})
+
+@item @key{TAB}
+Déplace le point sur la prochaine cellule vers la droite, ou insère
+une nouvelle colonne si on est déjà sur la dernière cellule de la
+ligne, ou insère une nouvelle ligne si on est sur la ligne de
+terminaison (@code{ses-forward-or-insert}).
+
+@item C-j
+Insère une nouvelle ligne sous la ligne courante et va à la colonne A
+de cette ligne (@code{ses-append-row-jump-first-column}).
+@end table
+
+En redimensionnant la feuille (à moins que vous ne fassiez que changer
+la largeur d’une colonne) les références de cellule au sein des
+formules sont toutes relocalisées de sorte à continuer à faire
+référence aux mêmes cellules. Si une formule mentionne B1 et que vous
+insérez une nouvelle première ligne, alors la formule mentionnera B2.
+
+Si vous supprimez une cellule à laquelle une formule fait référence,
+le symbole de cellule est supprimé de la formule, de sorte que
+@code{(+ A1 B1 C1)} après suppression de la troisième colonne devient
+@code{(+ A1 B1)}. Au cas où cela ne serait pas ce que vous désiriez :
+
+@table @kbd
+@item C-_
+@itemx C-x u
+Défait l’action action précédente (@code{(undo)}).
+@end table
+
+
+@node Printer functions
+@section Fonctions d’impression
+@cindex fonctions d’impression
+@cindex formatage de cellule
+@cindex cellules, formater
+
+Les fonctions d’impression convertissent des valeurs binaires de
+cellule en formes d’impression qu’Emacs affiche à l’écran.
+
+@menu
+* Différents types de fonctions d’impression: Various kinds of printer functions.
+* Configurer quelle fonction d’impression s’applique: Configuring what printer function applies.
+* Les fonctions d’impression standardes: Standard printer functions.
+* Les fonctions d’impression locales: Local printer functions.
+* Écrire une fonctions d’impression lambda: Writing a lambda printer function.
+@end menu
+
+@node Various kinds of printer functions
+@subsection Différents types de fonctions d’impression
+
+Lorsque on configure quelle fonction d’impression s’applique
+(@pxref{Configuring what printer function applies}), on peut saisir
+une fonction d’impression comme l’une des possibilités suivantes :
+
+@itemize
+@item
+Une chaîne de formatage, telle que @samp{"$%.2f"}. la chaîne formatée
+résultante est alignée à droite au sein de la cellule
+d’impression. Pour obtenir un alignement à gauche, utilisez des
+parenthèses : @samp{("$%.2f")}.
+@item
+Une fonction d’impression peut aussi être une fonction à un argument
+dont la valeur renvoyée est une chaîne (pour obtenir un alignement à
+droite) ou une liste d’une chaîne (pour obtenir un alignement à
+gauche). Une telle fonction peut à son tour être configurée comme :
+@itemize
+@item
+Une expression lambda, par exemple :
+
+@lisp
+(lambda (x)
+ (cond
+ ((null x) "")
+ ((numberp x) (format "%.2f" x))
+ (t (ses-center-span x ?# 'ses-prin1))))
+@end lisp
+
+Pendant la saisie d’une lambda, vous pouvez utiliser @kbd{M-@key{TAB}}
+pour completer les noms de symboles.
+@item
+Un symbole faisant référence à une fonction d’impression standarde
+(@pxref{Standard printer functions}).
+@item
+Un symbole faisant référence à une fonction d’impression locale
+(@pxref{Local printer functions}).
+@end itemize
+
+
+@end itemize
+
+
+@node Configuring what printer function applies
+@subsection Configurer quelle fonction d’impression s’applique
+
+Chaque cellule a une fonction d’impression. Si c’est @code{nil},
+alors la fonction d’impression de la colonne de cette cellule est
+utilisée. Et si cela est aussi @code{nil}, alors la fonction
+d’impression par défaut de la feuille est utilisée.
+
+@table @kbd
+@item p
+@findex ses-read-cell-printer
+Saisit une fonction d’impression pour la cellule ou plage courante
+(@code{ses-read-cell-printer}).
+
+@item M-p
+@findex ses-read-column-printer
+Saisit une fonction d’impression pour la colonne courante (@code{ses-read-column-printer}).
+
+@item C-c C-p
+@findex ses-read-default-printer
+Saisit la fonction d’impression par défaut de la feuille
+(@code{ses-read-default-printer}).
+@end table
+
+Les commandes @code{ses-read-@var{xxx}-printer} permettent les commandes
+suivantes pendant l’édition:
+
+@table @kbd
+@item @key{arrow-up}
+@itemx @key{arrow-down}
+Pour parcourir l’historique : les commandes
+@code{ses-read-@var{xxx}-printer} ont leur propre historique de
+mini-tampon, il est préchargé avec l’ensemble de toutes les fonctions
+d’impression utilisées dans cette feuille, plus les fonctions
+d’impression standardes (@pxref{Standard printer functions}) et les
+fonctions d’impression locales (@pxref{Local printer functions}).
+@item @key{TAB}
+Pour compléter les symboles de fonctions d’impression locales, et
+@item C-h C-p
+Pour lister les fonctions d’impression locales dans un tampon d’aide.
+@end table
+
+
+@node Standard printer functions
+@subsection Les fonctions d’impression standardes
+
+
+Mise à part @code{ses-prin1}, les autres fonctions d’impression
+standardes ne conviennent que pour les cellules, et non pour les
+colonnes ou comme fonction d’impression par défaut de la feuille,
+parce qu’elles formatent la valeur en utilisant la fonction
+d’impression de colonne (ou par défaut si @code{nil}) et ensuite
+post-traite le résultat, par ex.@: le centre :
+
+@ftable @code
+@item ses-center
+Centre juste.
+
+@item ses-center-span
+Centrer en débordant sur les cellules vides suivantes.
+
+@item ses-dashfill
+Centrer en utilisant des tirets (@samp{-}) au lieu d’espaces.
+
+@item ses-dashfill-span
+Centrer avec tirets et débordement.
+
+@item ses-tildefill-span
+Centrer avec tildes (@samp{~}) et débordement.
+
+@item ses-prin1
+C’est la fonction d’impression de repli, utilisée quand l’appel à la
+fonction d’impression configurée envoie une erreur.
+@end ftable
+
+@node Local printer functions
+@subsection Les fonctions d’impression locales
+
+@findex ses-define-local-printer
+Vous pouvez définir une fonction d’impression locale à la feuille avec
+la commande @code{ses-define-local-printer}. Par exemple, définissez
+une fonction d’impression @samp{toto} à @code{"%.2f"}, et ensuite
+utilisez le symbole @samp{toto} comme fonction d’impression. Ensuite,
+si vous rappelez @code{ses-define-local-printer} sur @samp{toto} pour
+le redéfinir comme @code{"%.3f"}, alors toutes les cellules utilisant
+la fonction d’impression @samp{toto} seront re-imprimées conformément.
+
+Il peut arriver que vous désiriez définir ou redéfinir certaines
+fonctions d’impression à chaque fois que vous ouvrez une feuille. Par
+exemple, imaginez que vous désiriez définir/re-définir automatiquement
+une fonction d’impression locale @code{euro} pour afficher un nombre
+comme une somme en euros, par exemple le nombre @code{3.1} serait
+affiché comme @code{3.10@dmn{}@euro{}}. Pour faire cela dans tout
+tampon SES qui n’est pas en lecture seule, vous pouvez ajouter ce
+genre de code à votre fichier d’init @file{.emacs} :
+
+@lisp
+(defun my-ses-mode-hook ()
+ (unless buffer-read-only
+ (ses-define-local-printer
+ 'euro
+ (lambda (x)
+ (cond
+ ((null x) "")
+ ((numberp x) (format "%.2f€" x))
+ (t (ses-center-span x ?# 'ses-prin1)))))))
+(add-hook 'ses-mode-hook 'my-ses-mode-hook)
+@end lisp
+
+Si vous remplacez la commande @code{ses-define-local-printer} par la
+fonction @code{ses-define-if-new-local-printer}
+@findex ses-define-if-new-local-printer
+la définition ne se produira que si aucune fonction d’impression de
+même nom n’est déjà définie.
+
+
+@node Writing a lambda printer function
+@subsection Écrire une fonctions d’impression lambda
+
+Vous pouvez écrire une fonction d’impression avec une expression
+lambda prenant un seul argument en deux cas :
+
+@itemize
+@item
+quand vous configurez la fonction d’impression s’appliquant à
+une cellule ou colonne, ou
+@item
+quand vous définissez une fonction d’impression avec la commande
+@code{ses-define-local-printer}.
+@end itemize
+
+En faisant cela, prenez garde à ce que la valeur renvoyée soit une
+chaîne, ou une liste contenant une chaîne, même quand l’argument
+d’entrée a une valeur inattendue. Voici un exemple :
+
+@example
+(lambda (val)
+ (cond
+ ((null val) "")
+ ((and (numberp val) (>= val 0)) (format "%.1f" val))
+ (t (ses-center-span val ?# 'ses-prin1))))
+@end example
+
+Cet exemple fait ceci :
+
+@itemize
+@item
+Quand la cellule est vide (c.-à-d.@: quand @code{val} est @code{nil}),
+imprime une chaîne vide @code{""}
+@item
+Quand la valeur de cellule est un nombre positif ou nul, formate la
+valeur en notation à virgule fixe avec une decimale après la virgule
+@item
+Sinon, gère la valeur comme erronnée en l’imprimant comme une
+s-expression (avec @code{ses-prin1}), centrée et entourée de
+croisillons @code{#} de bourrage.
+@end itemize
+
+Une autre précaution à prendre est d’éviter un débordement de pile à
+cause d’une fonction d’impression se rappelant elle-même sans
+fin. Cette erreur peut se produire quand vous utilisez une fonction
+d’impression locale comme fonction d’impression de colonne, et que
+cette fonction d’impression locale appelle implicitement la fonction
+d’impression de colonne courante, ainsi elle se rappelle elle-même
+récursivement. Imaginez par exemple que vous désirez créer une
+fonction d’impression locale @code{=bourre} qui centre le contenu
+imprimé d’une cellule et l’entoure de signes égal @code{=}, et que
+vous le faites (erronnément) comme cela :
+
+@lisp
+;; CODE ERRONÉ
+(lambda (x)
+ (cond
+ ((null x) "")
+ (t (ses-center x 0 ?=))))
+@end lisp
+
+Comme @code{=bourre} utilise la fonction d’impression standarde
+@code{ses-center} mais sans lui passer exemplicitement une fonction
+d’impression, @code{ses-center} appelle la fonction d’impression de
+colonne courante s’il y en a une, ou la fonction d’impression par
+défaut de la feuille sinon. Aussi, utiliser @code{=bourre} comme
+fonction d’impression de colonne aura pour résultat de causer un
+débordement de pile dans cette colonne sur toute cellule non vide,
+puisque @code{ses-center} rappelle récursivement la fonction qui l'a
+appelé. @acronym{SES} ne vérifie pas cela ; il vous faut donc faire
+attention. Par exemple, reécrivez @code{=bourre} ainsi :
+
+@lisp
+(lambda (x)
+ (cond
+ ((null x) "")
+ ((stringp x) (ses-center x 0 ?= " %s "))
+ (t (ses-center-span x ?# 'ses-prin1))))
+@end lisp
+
+Le code ci-dessus est réparé au sens où @code{ses-center} et
+@code{ses-center-span} sont toutes deux appelées avec un dernier
+argument @var{printer} explicite spécifiant la fonction d'impression,
+respectivement @code{" %s "} et @code{'ses-prin1}.
+
+
+Le code ci-dessus applique le bourrage de @code{=} seulement aux
+chaînes ; et aussi il entoure la chaîne par un espace de chaque côté
+avant de bourrer avec des signes @code{=}. Ainsi la chaîne @samp{Ula}
+s’affichera comme @samp{@w{=== Ula ===}} dans une colonne large de 11
+caractères. Toute valeur qui n’est ni @code{nil} (c.-à-d.@: une
+cellule vide) ni une chaîne est affichée comme une erreur par l’usage
+de bourrage par des croisillons @code{#}.
+
+@node Clearing cells
+@section Effacer des cellules
+@cindex effacer, commandes
+@findex ses-clear-cell-backward
+@findex ses-clear-cell-forward
+
+Ces commandes règlent à la fois la formule et la fonction d’impression
+à @code{nil} :
+
+@table @kbd
+@item @key{DEL}
+Se deplace à gauche et efface la cellule (@code{ses-clear-cell-backward}).
+
+@item C-d
+Efface la cellule et se déplace à droite (@code{ses-clear-cell-forward}).
+@end table
+
+
+@node Copy/cut/paste
+@section Copier, couper, et coller
+@cindex copier
+@cindex couper
+@cindex coller
+@findex kill-ring-save
+@findex mouse-set-region
+@findex mouse-set-secondary
+@findex ses-kill-override
+@findex yank
+@findex clipboard-yank
+@findex mouse-yank-at-click
+@findex mouse-yank-at-secondary
+@findex ses-yank-pop
+
+Les fonctions de copie opèrent sur des regions rectangulaires de
+cellules. Vous pouvez coller les copies dans des tampons
+non-@acronym{SES} pour exporter le texte d’impression.
+
+@table @kbd
+@item M-w
+@itemx [copy]
+@itemx [C-insert]
+Copie les cellules en vedette vers l’anneau presse-papier et le
+presse-papier primaire (@code{kill-ring-save}).
+
+@item [drag-mouse-1]
+Marque une region et la copie vers l’anneau presse-papier et le
+presse-papier primaire (@code{mouse-set-region}).
+
+@item [M-drag-mouse-1]
+Marque une region et la copie vers l’anneau presse-papier et le
+presse-papier secondaire (@code{mouse-set-secondary}).
+
+@item C-w
+@itemx [cut]
+@itemx [S-delete]
+Les fonctions couper ne suppriment pas en fait de lignes ou de
+colonnes --- elles les copient et puis les effacent
+(@code{ses-kill-override}).
+
+@item C-y
+@itemx [S-insert]
+Colle à partir de l’anneau presse-papier (@code{yank}). Les fonctions
+coller se comportent différemment selon le format du texte qu’elles
+insèrent :
+@itemize @bullet
+@item
+Quand on colle des cellules qui ont été coupées ou copiées à partir
+d’un tampon @acronym{SES}, le texte d’impression est ignoré et
+seulement la formule et fonction d’impression jointes sont insérées ;
+les références de cellule de la formule sont relocalisées à moins que
+vous n’utilisiez @kbd{C-u}.
+@item
+Le texte collé écrase un rectangle de cellules dont le coin haut
+gauche est la cellule courante. Si une partie du rectangle est
+au-délà des bords de la feuille, vous devez confirmer l’augmentation
+de la taille de la feuille.
+@item
+Du texte Non-@acronym{SES} est d’ordinaire inséré comme formule de
+remplacement pour la cellule courante. Si la formule serait un
+symbole, elle est traitée comme une chaîne à moins que vous
+n’utilisiez @kbd{C-u}. Les formules collées comprenant des erreurs de
+syntaxe sont toujours traitées comme des chaînes.
+@end itemize
+
+@item [paste]
+Colle à partir du presse-papier primaire ou de l’anneau presse-papier
+(@code{clipboard-yank}).
+
+@item [mouse-2]
+Règle le point et colle à partir du presse-papier primaire
+(@code{mouse-yank-at-click}).
+
+@item [M-mouse-2]
+Règle le point et colle à partir du presse-papier secondaire
+(@code{mouse-yank-secondary}).
+
+@item M-y
+Immédiatement après un coller, vous pouvez remplacer le texte avec un
+élément précédent à partir de l’anneau presse-papier
+(@code{ses-yank-pop}). Contrairement au yank-pop standard d’Emacs, la
+version de @acronym{SES} utilise @code{undo} pour supprimer l’ancien
+collage. Est-ce que cela ne fait aucune différence ?
+@end table
+
+@node Customizing @acronym{SES}
+@section Personnaliser @acronym{SES}
+@cindex personnaliser
+@vindex enable-local-eval
+
+Par défaut, une feuille venant d’être créée a 1 ligne et 1 colonne.
+La largeur de colonne est 7 et la fonction d’impression par défaut est
+@samp{"%.7g"}. Chacune de ces choses peut être personnalisée. Allez
+voir dans le groupe « ses ».
+
+Après avoir saisi une valeur de cellule, normalement
+@code{forward-char} est appelé, ce qui déplace le point vers la
+cellule suivante à droite, ou à la première cellule à gauche de la
+ligne suivante si la cellule courante est la plus à droite de la
+feuille. Vous pouvez personnaliser @code{ses-after-entry-functions}
+pour que le déplacement soit vers la gauche ou le haut ou le bas.
+Pour un mouvement diagonal, selectionnez deux fonctions de la liste.
+
+@vindex ses-jump-cell-name-function
+@code{ses-jump-cell-name-function} est une variable personnalisable
+réglée par défaut à la fonction @code{upcase}. Cette fonction est
+appelée quand vous passez un nom de cellule à la commande
+@command{ses-jump} (@kbd{j}), et que ce nom n’est pas le nom d’une
+cellule renommée. Elle change le nom de cellule saisi en celui de la
+cellule vers laquelle sauter. Le réglage par défaut @code{upcase} vous
+permet de saisir le nom de cellule en bas de casse. Un autre usage de
+@code{ses-jump-cell-name-function} pourrait être une
+internationalisation pour convertir des caractères non latins en
+équivalents latins pour nommer la cellule. Au lieu d’un nom de
+cellule, la fonction peut renvoyer des coordonnées de cellule sous la
+forme d’un cons, par exemple @code{(0 . 0)} pour la cellule @code{A1},
+@code{(1 . 0)} pour la cellule @code{A2}, etc.
+
+@vindex ses-jump-prefix-function
+@code{ses-jump-prefix-function} est une variable personnalisable
+réglée par défaut à la fonction @code{ses-jump-prefix}. Cette fonction
+est appelée quand vous donnez un argument préfixe à la commande
+@command{ses-jump} (@kbd{j}). Elle renvoie un nom de cellule ou des
+coordonnées de cellule correspondant à l’argument préfixe. Les
+coordonnées de cellule sont sous la forme d’un cons, par exemple
+@code{(1 . 0)} pour la cellule @code{A2}. Le réglage par défaut
+@code{ses-jump-prefix} numérote les cellules de gauche à droite et
+puis de haut en bas, de sorte que si on suppose une feuille 4×3,
+l’argument préfixe @samp{0} saute à la cellule @samp{A1}, l’argument
+préfixe @samp{2} saute à @samp{C1}, l’argument préfixe @samp{3} saute
+à @samp{A2}, etc.
+
+@vindex ses-mode-hook
+@code{ses-mode-hook} est un crochet de mode normal (une liste de
+fonctions qui s’exécutent quand le mode @acronym{SES} démarre sur un
+tampon).
+
+@vindex safe-functions
+La variable @code{safe-functions} est une liste de fonctions
+potentiellement risquées à traiter comme si elles étaient sûres lors
+de l’analyse des formules et fonctions d’impression. @xref{Virus
+protection}. Avant de personnaliser @code{safe-functions},
+réfléchissez à quel point vous faites confiance à la personne qui vous
+suggère cette modification. La valeur @code{t} désactive toute
+protection anti-virus. Une valeur donnant une liste-de-fonctions peut
+rendre une feuille « trop bien », mais elle crée aussi des portes
+dérobées dans votre armure anti-virus. Pour que votre protection
+contre les virus fonctionne, vous devez toujours appuyer sur @kbd{n}
+quand un avertissement contre un virus vous est présenté, à moins que
+vous compreniez ce que le code en question essaie de faire. N’écoutez
+pas ceux qui vous racontent de personnaliser @code{enable-local-eval}
+--- cette variable est pour les gens qui ne portent pas de ceinture de
+sécurité !
+
+
+@c ===================================================================
+
+@node Advanced Features
+@chapter Fonctions avancées
+@cindex avancées, fonctions
+@findex ses-read-header-row
+
+
+@table @kbd
+@item C-c M-C-h
+(@code{ses-set-header-row}).
+@findex ses-set-header-row
+@kindex C-c M-C-h
+La ligne d’en-tête au sommet de la fenêtre @acronym{SES} affiche
+normalement la ligne de colonne pour chaque colonne. Vous pouvez la
+régler pour afficher une copie de l’une des lignes, tell que qu’une
+ligne de titres de colonnes, ainsi cette ligne sera toujours visible.
+Par défaut la commande règle la ligne courante comme en-tête ;
+utiliser C-u pour une invite à désigner la ligne d’en-têre. Régler la
+ligne d’en-tête à la ligne 0 pour afficher les lettres de colonne de
+nouveau.
+@item [header-line mouse-3]
+Affiche un menu pour régler la ligne courante comme en-tête, ou
+revenir à des lettres de colonne.
+@item M-x ses-rename-cell
+@findex ses-rename-cell
+Renomme une cellule pour passer d'un nom standard du genre de A1 à
+toute chaîne pouvant être un nom valide pour une variable locale (Voir
+aussi @ref{Nonrelocatable references}).
+@item M-x ses-repair-cell-reference-all
+@findex ses-repair-cell-reference-all
+Quand vous interrompez la mise à jour d’une formule de cellule en
+tapant @kbd{C-g}, alors cela peut casser le lien de référence de
+cellule, ce qui compromet la mise à jour automatique de cellule quand
+toute autre cellule dont elle dépend est modifiée. Pour réparer cela,
+utilisez la fonction @code{ses-repair-cell-reference-all}
+@end table
+
+@menu
+* La zone d’impression: The print area.
+* Plages dans les formules: Ranges in formulas.
+* Trier par colonne: Sorting by column.
+* Fonctions de formule standardes: Standard formula functions.
+* Plus sur l’impression de cellule: More on cell printing.
+* Import et export: Import and export.
+* Protection contre les virus: Virus protection.
+* Feuilles avec détails et synthèse: Spreadsheets with details and summary.
+@end menu
+
+@node The print area
+@section La zone d’impression
+@cindex zone d’impression
+@cindex impression, zone d’
+@findex widen
+@findex ses-renarrow-buffer
+@findex ses-reprint-all
+
+Un fichier @acronym{SES} consiste en une zone d’impression et une zone
+de données. Normalement le tampon est réduit de sorte à n’afficher
+que la zone d’impression. La zone d’impression est en lecture seule,
+hormis pour les commandes spéciales de @acronym{SES} ; elle contient
+les valeurs de cellule formatées par les fonctions d’impression. La
+zone de données enregistre les formules, fonctions d’impression, etc.
+
+@table @kbd
+@item C-x n w
+Affiche à la fois les zones d’impression et de données (@code{widen}).
+
+@item C-c C-n
+Affiche seulement la zone d’impression (@code{ses-renarrow-buffer}).
+
+@item S-C-l
+@itemx M-C-l
+Recrée la zone d’impression en réévaluant pour toutes les cellules sa
+fonction d’impression (@code{ses-reprint-all}).
+@end table
+
+@node Ranges in formulas
+@section Plages dans les formules
+@cindex plages
+@findex ses-insert-plage-click
+@findex ses-insert-plage
+@findex ses-insert-ses-plage-click
+@findex ses-insert-ses-plage
+@vindex de
+@vindex à
+
+Une formule du genre de :
+@lisp
+(+ A1 A2 A3)
+@end lisp
+est la somme de trois cellules spécifiques. Si vous insérez une
+nouvelle deuxième ligne, la formule devient
+@lisp
+(+ A1 A3 A4)
+@end lisp
+et la nouvelle ligne n’est pas incluse dans la somme.
+
+La macro @code{(ses-range @var{de} @var{à})} s’évalue en une liste des
+valeurs dans un rectangle de cellules. Si votre formule est
+@lisp
+(apply '+ (ses-range A1 A3))
+@end lisp
+et que vous insérez une nouvelle deuxième ligne, elle devient
+@lisp
+(apply '+ (ses-range A1 A4))
+@end lisp
+et la nouvelle ligne est incluse dans la somme.
+
+Alors que vous saisissez ou éditez une formule dans le minitampon,
+vous pouvez sélectionner une plage dans la feuille (en utilisant la
+souris ou le clavier), et injecter une représentation de cette plage
+dans votre formule. Supposez que vous sélectionnez @samp{A1-C1} :
+
+@table @kbd
+@item [S-mouse-3]
+Insère @samp{A1 B1 C1} (@code{ses-insert-range-click})
+
+@item C-c C-r
+Version clavier (@code{ses-insert-range}).
+
+@item [C-S-mouse-3]
+Insère @samp{(ses-range A1 C1)} (@code{ses-insert-ses-range-click}).
+
+@item C-c C-s
+Version clavier (@code{ses-insert-ses-range}).
+@end table
+
+Si vous supprimez la cellule @var{de} ou @var{à} d’une plage, la
+cellule la plus proche toujours existante est utilisée à la place. Si
+vous supprimez l’entière plage, le relocalisateur de formule supprime
+le @samp{ses-range} de la formule.
+
+Si vous insérez une nouvelle ligne juste au delà de la fin d’une plage
+à une colonne, ou une nouvelle colonne juste au delà d’une plage à une
+ligne, la nouvelle cellule est incluse dans la plage. Les nouvelles
+cellules insérées juste avant une plage ne sont pas incluses.
+
+Des fanions peuvent être ajoutés à @code{ses-range} immédiatement
+après la cellule @var{à} .
+@table @code
+@item !
+Les cellules vides de la plage peuvent être enlevées en ajoutant le
+fanion @code{!}. Une cellule vide est une cellule dont la valeur est
+l’un des symboles @code{nil} ou @code{*skip*}. Par exemple
+@code{(ses-range A1 A4 !)} fait la même chose que @code{(list A1 A3)}
+quand les cellules @code{A2} et @code{A4} sont vides.
+@item _
+Les valeurs de cellules vides sont remplacées par l’argument suivant
+le fanion @code{_}, ou @code{0} quand le fanion @code{_} est le
+dernier dans la liste d’arguments. Par exemple @code{(ses-range A1 A4
+_ "vide")} fera la même chose que @code{(list A1 "vide" A3 "vide")}
+quand les cellules @code{A2} et @code{A4} sont vides. Similairement,
+@code{(ses-range A1 A4 _ )} fera la même chose que @code{(list A1 0 A3
+0)}.
+@item >v
+Quand l’ordre a de l’importance, liste les cellules en lisant les
+cellules ligne par ligne de la cellule en haut à gauche vers la
+cellule en bas à droite. Ce fanion est fourni pour être complet car
+c’est déjà l’ordre par défaut.
+@item <v
+Liste les cellules en lisant les cellules ligne par ligne de la
+cellule en haut à droite vers la cellule en bas à gauche.
+@item v>
+Liste les cellules en lisant les cellules colonne par colonne de la
+cellule en haut à gauche vers la cellule en bas à droite.
+@item v<
+Liste les cellules en lisant les cellules colonne par colonne de la
+cellule en haut à droite vers la cellule en bas à gauche.
+@item v
+Un raccourci pour @code{v>}.
+@item ^
+Un raccourci pour @code{^>}.
+@item >
+Un raccourci pour @code{>v}.
+@item <
+Un raccourci pour @code{>^}.
+@item *
+Au lieu de lister les cellules, en fait un vecteur ou une matrice Calc
+(@pxref{Top,,,calc,GNU Emacs Calc Manual}). Si la plage contient
+seulement une ligne ou une colonne un vecteur est fait, sinon une
+matrice est faite.
+@item *2
+Idem que @code{*} à ceci près qu’une matrice est toujours faite même
+quand il y a une seule ligne ou colonne dans la plage.
+@item *1
+Idem que @code{*} à ceci près qu’un vecteur est toujours fait même
+quand il n’y a qu’une ligne ou colonne dans la plage, c.-à-d.@: que la
+matrice correspondante est aplatie.
+@end table
+
+@node Sorting by column
+@section Trier par colonne
+@cindex trier
+@findex ses-sort-column
+@findex ses-sort-column-click
+
+@table @kbd
+@item C-c M-C-s
+Trie les cellules d’une plage en utilisant l’une des colonnes
+(@code{ses-sort-column}). Les lignes (ou lignes partielles si la
+plage n’inclut pas toutes les colonnes) sont réarrangées de sorte que
+la colonne choisie soit ordonnée.
+
+@item [header-line mouse-2]
+La façon la plus facile de trier est de cliquer sur mouse-2 sur la
+ligne d’en-tête de colonne (@code{ses-sort-column-click}).
+@end table
+
+La comparaison du tri utilise @code{string<}, ce qui fonctionne bien
+pour des nombres alignés à droite ou des chaînes alignées à gauche.
+
+Avec un argument préfixe, trie dans l’ordre descendant.
+
+Les lignes sont déplacées une à la fois, avec relocalisation des
+formules. Ceci fonctionne bien si les formules font référence à
+d’autres cellules dans leur ligne, mais non pas si bien pour des
+formules qui font référence à d’autres lignes dans la plage ou à des
+cellules hors de la plage.
+
+
+@node Standard formula functions
+@section Fonctions de formule standardes
+@cindex fonctions standardes de formule
+@cindex *skip*
+@cindex *error*
+@findex ses-delete-blanks
+@findex ses-average
+@findex ses+
+
+Souvent on désire qu’un calcul exclue les cellules vides. Voici
+quelques fonctions utiles à appeler dans vos formules :
+
+@table @code
+@item (ses-delete-blanks &rest @var{args})
+Renvoie une liste dont toutes les cellules vides (dont la valeur est
+soit @code{nil} ou @code{'*skip*}) ont été supprimées. L’ordre des
+arguments est inversé. Prière de noter que @code{ses-range} a un
+modificateur @code{!} qui permet de supprimer les cellules vides,
+ainsi il est possible d’écrire :
+@lisp
+(ses-range A1 A5 !)
+@end lisp
+au lieu de
+@lisp
+(apply 'ses-delete-blanks (ses-range A1 A5 <))
+@end lisp
+
+@item (ses+ &rest @var{args})
+Somme des arguments non vides pris en ordre inverse.
+
+@item (ses-average @var{liste})
+Moyenne des éléments non vides de @var{liste}. Ici la liste est
+passée comme un seul argument, vu que typiquement on la forme avec
+@code{ses-range}.
+@end table
+
+@node More on cell printing
+@section Plus sur l’impression de cellule
+@cindex cellule, plus sur l'impression
+@cindex impression de cellule
+@findex ses-truncate-cell
+@findex ses-recalculate-cell
+
+Valeurs spéciales de cellule :
+@itemize
+@item nil
+s’imprime typiquement de la même façon que "", mais permet que la
+cellule précédente déborde dessus.
+@item '*skip*
+remplace nil quand la cellule précédente déborde effectivement ; rien
+n’est donc imprimée pour cette cellule.
+@item '*error*
+indique que la formule a signalé une erreur au lieu de produire une
+valeur : la cellule imprimée est remplie de croisillons (#).
+@end itemize
+
+Lorsque la fonction d’impression est définie par une chaîne de
+formatage, par ex. @samp{"%.3f"}, @acronym{SES} imprime
+automatiquement @code{nil} comme une chaîne vide, mais si la fonction
+d’impression est définie par une expression lambda, vous devez définir
+explicitement comment @code{nil} est traité, par ex. :
+@example
+(lambda (x)
+ (cond
+ ((null x) "")
+ ((stringp x) (list x))
+ ((numberp x) (format "%.3f" x))
+ (t (ses-prin1 x)))
+@end example
+imprime @code{nil} comme une chaîne vide, aligne à gauche la valeur si
+c’est une chaîne, et si c’est un nombre l’aligne à droite en
+l’imprimant avec trois décimales.
+
+Il n’est pas nécessaire par contre que vous vous souciez de
+@code{'*skip*} dans la définition d’une fonction d’impression, en
+effet aucune fonction d’impression n’est appelée sur @code{'*skip*}.
+
+Si le résultat de la fonction d’impression est trop large pour la
+cellule et que la cellule suivante est @code{nil}, le résultat
+débordera sur la cellule suivante. Les résultats très larges peuvent
+déborder sur plusieurs cellules. Si le résultat est trop large pour
+l’espace disponible (jusqu'à la fin de la ligne ou la prochaine
+cellule non-@code{nil}), le résultat est tronqué si la valeur de
+cellule est une chaîne, ou remplacé par des croisillons (@samp{#})
+sinon.
+
+@acronym{SES} pourrait être perturbé par des résultats de fonction
+d'impression contenant des sauts de ligne ou des tabulations, aussi
+ces caractères sont remplacés par des points d'interrogation.
+
+@table @kbd
+@item t
+Confine une cellule à sa propre colonne (@code{ses-truncate-cell}).
+Ceci vous permet de déplacer le point sur la cellule de droite qui
+sinon serait couverte par un débordement. Si vous ne modifiez pas la
+cellule de droite, la cellule confinée débordera de nouveau la
+prochaine fois qu’elle sera imprimée.
+
+@item c
+Appliquée à une seule cellule, cette commande affiche dans la zone
+d’écho toute erreur de formule ou erreur d’impression survenue pendant
+le recalcul/la réimpression (@code{ses-recalculate-cell}). Vous
+pouvez utiliser cela pour défaire l’effet de @kbd{t}.
+@end table
+
+Quand une fonction d’impression signale une erreur, la fonction
+d’impression de repli
+@findex ses-prin1
+@code{ses-prin1} lui est substituée. Ceci est utile quand votre
+fonction d’impression de colonne est seulement numérique et que vous
+utilisez une chaîne comme valeur de cellule. Notez que la fonction
+d’impression par défaut standarde est @samp{"%.7g"} qui est numérique
+seulement, ainsi les cellules auxquelles la fonction d’impression par
+défaut standarde s’applique et qui ne sont pas vides et ne contiennent
+pas un nombre utilisent la fonction d’impression de repli
+@code{ses-prin1}, par ex.@: les cellules qui contiennent une chaîne
+font cela. @kbd{c} sur de telles cellules affiche « Format specifier
+doesn't match argument type ».
+
+
+@node Import and export
+@section Import et export
+@cindex import et export
+@cindex export, et import
+@findex ses-export-tsv
+@findex ses-export-tsf
+
+@table @kbd
+@item x t
+Exporte une plage de cellules comme des valeurs séparées par des
+tabulations (@code{ses-export-tsv}).
+@item x T
+Exporte une plage de cellules comme des formules séparées par des
+tabulations (@code{ses-export-tsf}).
+@end table
+
+Le texte exporté va dans l’anneau presse-papier ; vous pouvez le
+coller dans un autre tampon. Les colonnes sont séparées par des
+tabulations, les lignes par des sauts de lignes.
+
+Pour importer du texte, utilisez n’importe laquelle des commandes
+coller où le texte à coller contient des tabulations et/ou des sauts de
+lignes. Les formules importées ne sont pas relocalisées.
+
+@node Virus protection
+@section Protection contre les virus
+@cindex virus protection
+
+À chaque fois une formule ou fonction d’impression est lue d’un
+fichier ou est collée dans la feuille, elle est marquée comme
+« nécessitant une vérification de sécurité ». Plus tard, quand la
+formule ou la fonction d’impression est évaluée pour la première fois,
+elle est vérifiée comme sûre en utilisant le prédicat @code{unsafep} ;
+si elle s’avère « potentiellement risquée », la formule ou fonction
+d’impression en question est affichée et vous devez appuyer @kbd{Y}
+pour l’approuver ou @kbd{N} pour utiliser un substitut. Le substitut
+signale toujours une erreur.
+
+Les formules ou fonctions d’impression que vous tapez sont
+immédiatement vérifiées quant à leur sûreté. Si elles s’avèrent
+potentiellement risquées et que vous appuyez @kbd{N} pour refuser,
+l’action est annulée et l’ancienne formule ou fonction d’impression
+demeure.
+
+En plus des virus (qui tentent de se recopier dans d’autres
+fichiers), @code{unsafep} peut aussi détecter toutes sortes de chevaux
+de Troie, tels que des feuilles de calcul qui effacent les fichiers,
+envoient des courriels, inondent des sites Web, corrompent vos
+réglages d’Emacs, etc.
+
+Généralement, les formules et fonctions d’impression de feuilles sont
+des choses simples qui n’ont pas besoin de faire des traitements
+exotiques, aussi toute partie potentiellement dangereuse de
+l’environnement Emacs Lisp peut être exclus sans entraver votre style
+comme écrivain de formule. Lisez la documentation dans
+@file{unsafep.el} pour plus d’information sur la façon dont les formes
+Lisp sont classifiées comme sûres ou risquées.
+
+@node Spreadsheets with details and summary
+@section Feuilles avec détails et synthèse
+@cindex détails et synthèse
+@cindex synthèses, et détails
+
+Une organisation usuelle pour une feuille de calcul est d’avoir un tas
+de lignes de « détail », chacune décrivant possiblement une
+transaction, et ensuite un ensemble de lignes de « synthèse » qui
+affichent chacune des données condensées pour un certain sous-ensemble
+des détails. @acronym{SES} prend en charge ce type d’organisation via
+la fonction @code{ses-select}.
+
+@table @code
+@item (ses-select @var{de-plage} @var{test} @var{à-plage})
+Renvoie un sous-ensemble de @var{à-plage}. Pour chaque membre dans
+@var{de-plage} qui est égal à @var{test}, le membre correspondant de
+@var{à-plage} est inclus dans le résultat.
+@end table
+
+Exemple d’utilisation :
+@lisp
+(ses-average (ses-select (ses-range A1 A5) 'Bidochon (ses-range B1 B5)))
+@end lisp
+Ceci calcule la moyenne des valeurs de la colonne @samp{B} pour les
+lignes dont la valeur dans la colonne @samp{A} est le symbole
+@samp{'Bidochon}.
+
+Vous vous demandez peut-être pourquoi les arguments de
+@code{ses-select} ne consistent pas au lieu de @var{à-plage} de
+décalages @var{décalage-à-la-ligne} et @var{décalage-à-la-colonne}
+relativement à @var{de-plage} : spécifier @var{à-plage} explicitement
+assure que la formule est recalculée si l’une quelconque des cellules
+de cette plage est modifiée.
+
+Le fichier @file{etc/ses-example.el} dans la distribution Emacs est un
+exemple d’une feuille organisée en détails-et-synthèse.
+
+
+@c ===================================================================
+
+@node For Gurus
+@chapter Pour les gourous
+@cindex avancées, fonctions
+@cindex fonctions avancées
+
+@menu
+* Mises à jour différées: Deferred updates.
+* Références non-relocalisables: Nonrelocatable references.
+* La zone données: The data area.
+* Variables locales-tampon dans les feuilles: Buffer-local variables in spreadsheets.
+* Utilisation de advice-add dans @acronym{SES}: Uses of advice-add in @acronym{SES}.
+@end menu
+
+@node Deferred updates
+@section Mises à jour différées
+@cindex différées, mises à jour
+@cindex mises à jour différées
+@vindex run-with-idle-timer
+
+Pour épargner du temps de calcul redondant, les cellules dont le
+recalcul est rendu nécessaire par des changements dans d’autres
+cellules sont ajoutées à un ensemble. À la fin de la commande, chaque
+cellule de cet ensemble est recalculée une fois. Ceci peut créer un
+nouvel ensemble de cellules nécessitant un recalcul. Ce processus est
+répété jusqu'à ce que l’ensemble soit vide ou que des références
+circulaires soient détectées. Dans les cas extrêmes, et notamment si
+une référence circulaire est en cours de détection, vous pourriez voir
+des messages de progression de la forme « Recalculating... (@var{nnn}
+cells left) ». Si vous interrompez le calcul avec @kbd{C-g}, la
+feuille demeurera dans un état incohérent, utilisez alors @kbd{C-_} ou
+@kbd{C-c C-l} pour réparer cela.
+
+Pour épargner encore plus de temps en évitant les écritures
+redondantes, les cellules qui sont modifiées sont ajoutées à un
+ensemble au lieu d’être immédiatement écrites dans la zone de
+données. Chaque cellule de cet ensemble est écrite une fois à la fin
+de la commande. Si vous modifiez un grand nombre de cellules, vous
+pourriez voir un message de progression de la forme
+« Writing... (@var{nnn} cells left) ». Ces écritures différées de
+cellules ne peuvent pas être interrompues par @kbd{C-g}, alors il vous
+faudra juste attendre.
+
+@acronym{SES} utilise @code{run-with-idle-timer} pour déplacer le
+souligné de cellule quand Emacs fait défiler le tampon à la fin d’une
+commande, et aussi pour @c xxx narrow and underline
+réduire et souligner après visiter un fichier. Ceci peut être visible
+par une perturbation transitoire après visiter un fichier et certaines
+commandes de défilement. Vous pouvez continuer à taper sans vous
+inquiéter de cette perturbation.
+
+
+@node Nonrelocatable references
+@section Références non relocalisables
+@cindex non-relocalisables, références
+@cindex références non-relocalisables
+
+@kbd{C-y} relocalise toutes les références de cellule dans une formule
+collée, alors que @kbd{C-u C-y} n’en relocalise aucune. Et pour les
+cas mélangés ?
+
+La meilleure approche est de renommer les cellules que vous @emph{ne}
+voulez @emph{pas} être relocalisables en utilisant
+@code{ses-rename-cell}.
+@findex ses-rename-cell
+Les cellules qui n’ont pas un style de nom du genre de A1 ne sont pas
+relocalisées au collage. En utilisant cette méthode, les cellules
+concernées ne seront pas relocalisées quelle que soit la formule où
+elles apparaissent. Prière toutefois de noter que dans une formule
+contenant quelque plage @code{(ses-range @var{cell1} @var{cell2})}
+alors dans la formule collée chacune des bornes @var{cell1} et
+@var{cell2} de la plage est relocalisée, ou non, indépendemment, selon
+qu’elle est nommée du genre de @samp{A1} ou renommée.
+
+Une méthode alternative est d’utiliser
+@lisp
+(symbol-value 'B3)
+@end lisp
+pour faire une @dfn{référence absolue}. Le relocalisateur de formule
+saute par dessus tout ce qui est sous un @code{quote}, aussi cela ne
+sera pas relocalisé quand on le colle ou quand des lignes/colonnes
+sont insérées/supprimées. Toutefois, @samp{B3} ne sera pas
+enregistrée comme une dépendance de cette cellule, et donc cette
+cellule ne sera pas mise à jour automatiquement quand @samp{B3} est
+modifiée, c’est pourquoi l’usage de @code{ses-rename-cell} est la
+plupart du temps préférable.
+
+Les variables @code{row} et @code{col} sont liées dynamiquement
+pendant l’évaluation d’une formule de cellule. Vous pouvez utiliser
+@lisp
+(ses-cell-value row 0)
+@end lisp
+pour obtenir la valeur de la colonne la plus à gauche de la ligne
+courante. Ce type de dépendance n’est pas non plus enregistré.
+
+
+@node The data area
+@section La zone de données
+@cindex données, zone de
+@cindex zone de données
+@findex ses-reconstruct-all
+
+Commence avec un caractère saut de page (de code ASCII 014 en octal),
+suivi par un ensemble de macros de définition de cellule pour chaque
+ligne, suivi par l’ensemble des définitions de fonctions d’impression
+locales, suivi par les largeurs de colonnes, fonctions d’impression de
+colonne, fonction d’impression par défaut, et ligne d’en-tête. Ensuite
+il y a les paramètres globaux (ID de format fichier, nombre de lignes,
+nombre de colonnes, nombre de fonctions d’impression locales) et les
+variables locales (spécification du mode @acronym{SES} pour le tampon,
+etc.).
+
+Quand un fichier @acronym{SES} est chargé, tout d’abord les paramètres
+globaux sont chargés, puis l’ensemble de la zone de données est
+@code{eval}ué, et finalement les variables locales sont traitées.
+
+Vous pouvez éditer la zone de données, mais n’insérez pas ni ne
+supprimez de sauts de ligne, hormis dans la partie des variables
+locales, en effet @acronym{SES} localise les choses en comptant les
+sauts de ligne. Utilisez @kbd{C-x C-e} à la fin d’une ligne pour
+installer ce que vous avez édité dans les structures de données de la
+feuille (ceci ne met pas à jour la zone d’impression, utilisez, par
+ex., @kbd{C-c C-l} pour cela).
+
+La zone de données est maintenue comme une image des structures de
+données de la feuille stockée dans des variables locales tampon au
+moment du chargement initial de la zone. Si le contenu de la zone de
+données se trouve corrompu par la suite, vous pouvez essayer de
+reconstruire la zone de données à partir des structures de données
+avec :
+
+@table @kbd
+@item C-c M-C-l
+(@code{ses-reconstruct-all}).
+@end table
+
+
+@node Buffer-local variables in spreadsheets
+@section Les variables locales-tampon dans les feuilles de calcul
+@cindex locales-tampon, variables
+@cindex variables locales-tampon
+
+Vous pouvez ajouter des variables locales supplémentaires à la liste
+au bas de la zone de données, telles que des constantes cachées
+auxquelles vous désirez faire référence dans vos formules.
+
+Vous pouvez initialiser la variable @code{ses--symbolic-formulas} pour
+être une liste de symboles (comme une suite de chaînes entre
+parenthèses) à proposer comme complétions pour la commande @kbd{'}.
+Cette liste initiale de complétions sera utilisée à la place de
+l’ensemble effectif des symboles-comme-formules de la feuille.
+
+Pour un exemple de ceci, voir le fichier @file{etc/ses-example.ses}.
+
+Si (pour une raison quelconque) vous désirez que vos formules ou
+fonctions d’impression sauvegardent des données dans des variables,
+vous devez déclarer ces variables comme locales tampon pour éviter un
+avertissement de virus.
+
+Vous pouvez définir des fonctions en en faisant des valeurs pour la
+fausse variable locale @code{eval}. De telles fonctions peuvent
+ensuite être utilisées dans les formules et comme fonctions
+d’impression, mais d’ordinaire chaque @code{eval} est présenté à
+l’utilisateur pendant le chargement du fichier comme un virus
+potentiel. Et cela peut devenir gênant.
+
+Vous pouvez définir des fonctions dans votre fichier @file{.emacs}.
+Toute personne pourra encore lire la zone d’impression de votre
+feuille, mais ne pourra pas recalculer ou réimprimer quoi que ce soit
+qui dépende de vos fonctions. Pour éviter des avertissements contre
+les virus, chaque fonction utilisée dans une formule nécessite
+@lisp
+(put 'le-nom-de-votre-fonction 'safe-function t)
+@end lisp
+
+@node Uses of advice-add in @acronym{SES}
+@section Utilisation de advice-add dans @acronym{SES}
+@findex advice-add
+@findex copy-region-as-kill
+@findex yank
+
+@table @code
+@item copy-region-as-kill
+Quand on copie de la zone d’impression d’une feuille, traite la région
+comme un rectangle et joint pour chaque cellule sa formule et sa
+fonction d’impression comme des propriétés @code{'ses}.
+
+@item yank
+Quand on colle dans la zone d’impression d’une feuille de calcul,
+essaie de coller comme des cellules (si le texte à coller a des
+propriétés @code{'ses}), ensuite comme des formules séparées par des
+tabulations, ensuite (si tout le reste a échoué) comme une seule
+formule pour la cellule courante.
+@end table
+
+@c ===================================================================
+@node Index
+@unnumbered Index
+
+@printindex cp
+
+@c ===================================================================
+
+@node Acknowledgments
+@unnumbered Remerciements
+
+Codé par :
+@quotation
+@c jyavner@@member.fsf.org
+Jonathan Yavner,
+@c monnier@@gnu.org
+Stefan Monnier,
+@c shigeru.fukaya@@gmail.com
+Shigeru Fukaya,
+@c vincent.belaiche@@sourceforge.net
+Vincent Belaïche
+@end quotation
+
+@noindent
+Manuel Texinfo de :
+@quotation
+@c jyavner@@member.fsf.org
+Jonathan Yavner,
+@c brad@@chenla.org
+Brad Collins,
+@c vincent.belaiche@@sourceforge.net
+Vincent Belaïche
+@end quotation
+
+@noindent
+Idées de :
+@quotation
+@c christoph.conrad@@gmx.de
+Christoph Conrad,
+@c cyberbob@@redneck.gacracker.org
+CyberBob,
+@c syver-en@@online.no
+Syver Enstad,
+@c fischman@@zion.bpnetworks.com
+Ami Fischman,
+@c Thomas.Gehrlein@@t-online.de
+Thomas Gehrlein,
+@c c.f.a.johnson@@rogers.com
+Chris F.A. Johnson,
+@c lyusong@@hotmail.com
+Yusong Li,
+@c juri@@jurta.org
+Juri Linkov,
+@c maierh@@myself.com
+Harald Maier,
+@c anash@@san.rr.com
+Alan Nash,
+@c pinard@@iro.umontreal.ca
+François Pinard,
+@c ppinto@@cs.cmu.edu
+Pedro Pinto,
+@c xsteve@@riic.at
+Stefan Reichör,
+@c epameinondas@@gmx.de
+Oliver Scholz,
+@c rms@@gnu.org
+Richard M. Stallman,
+@c teirllm@@dms.auburn.edu
+Luc Teirlinck,
+@c jotto@@pobox.com
+J. Otto Tennant,
+@c jphil@@acs.pagesjaunes.fr
+Jean-Philippe Theberge,
+@c rrandresf@@hotmail.com
+Andrés Ramírez
+@end quotation
+
+@c ===================================================================
+
+@node GNU Free Documentation License
+@appendix GNU Free Documentation License
+@include doclicense.texi
+
+@bye
+@c Local Variables:
+@c ispell-dictionary: "fr"
+@c End:
diff --git a/doc/lispintro/ChangeLog.1 b/doc/lispintro/ChangeLog.1
index 76603b0a5f3..0f9c33f7c88 100644
--- a/doc/lispintro/ChangeLog.1
+++ b/doc/lispintro/ChangeLog.1
@@ -782,7 +782,7 @@
;; coding: utf-8
;; End:
- Copyright (C) 2001-2023 Free Software Foundation, Inc.
+ Copyright (C) 2001-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/doc/lispintro/Makefile.in b/doc/lispintro/Makefile.in
index 77087e97fac..53fc3b33e64 100644
--- a/doc/lispintro/Makefile.in
+++ b/doc/lispintro/Makefile.in
@@ -1,6 +1,6 @@
### @configure_input@
-# Copyright (C) 1994-1999, 2001-2023 Free Software Foundation, Inc.
+# Copyright (C) 1994-1999, 2001-2024 Free Software Foundation, Inc.
# This file is part of GNU Emacs.
diff --git a/doc/lispintro/README b/doc/lispintro/README
index b1b30bcbf49..70a840142b2 100644
--- a/doc/lispintro/README
+++ b/doc/lispintro/README
@@ -1,4 +1,4 @@
-Copyright (C) 2001-2023 Free Software Foundation, Inc.
+Copyright (C) 2001-2024 Free Software Foundation, Inc.
See the end of the file for license conditions.
diff --git a/doc/lispintro/cons-1.eps b/doc/lispintro/cons-1.eps
index e8b5ec78b3f..db8e6e0b774 100644
--- a/doc/lispintro/cons-1.eps
+++ b/doc/lispintro/cons-1.eps
@@ -4,7 +4,7 @@
%%CreationDate: Wed Mar 8 14:26:58 1995
%%Creator: Tgif-2.16-p4 by William Chia-Wei Cheng (william@cs.UCLA.edu)
-% Copyright (C) 1995, 1997, 2001-2023 Free Software Foundation, Inc.
+% Copyright (C) 1995, 1997, 2001-2024 Free Software Foundation, Inc.
%
% This file is part of GNU Emacs.
%
diff --git a/doc/lispintro/cons-2.eps b/doc/lispintro/cons-2.eps
index 0bb93c83e3b..6be064c519b 100644
--- a/doc/lispintro/cons-2.eps
+++ b/doc/lispintro/cons-2.eps
@@ -4,7 +4,7 @@
%%CreationDate: Wed Mar 8 14:26:39 1995
%%Creator: Tgif-2.16-p4 by William Chia-Wei Cheng (william@cs.UCLA.edu)
-% Copyright (C) 1995, 1997, 2001-2023 Free Software Foundation, Inc.
+% Copyright (C) 1995, 1997, 2001-2024 Free Software Foundation, Inc.
%
% This file is part of GNU Emacs.
%
diff --git a/doc/lispintro/cons-2a.eps b/doc/lispintro/cons-2a.eps
index 5ca33ac8807..a6fa6d89e5f 100644
--- a/doc/lispintro/cons-2a.eps
+++ b/doc/lispintro/cons-2a.eps
@@ -4,7 +4,7 @@
%%CreationDate: Tue Mar 14 15:09:30 1995
%%Creator: Tgif-2.16-p4 by William Chia-Wei Cheng (william@cs.UCLA.edu)
-% Copyright (C) 1995, 1997, 2001-2023 Free Software Foundation, Inc.
+% Copyright (C) 1995, 1997, 2001-2024 Free Software Foundation, Inc.
%
% This file is part of GNU Emacs.
%
diff --git a/doc/lispintro/cons-3.eps b/doc/lispintro/cons-3.eps
index bf2a14e7da8..f83d99ab1e3 100644
--- a/doc/lispintro/cons-3.eps
+++ b/doc/lispintro/cons-3.eps
@@ -4,7 +4,7 @@
%%CreationDate: Wed Mar 8 14:25:41 1995
%%Creator: Tgif-2.16-p4 by William Chia-Wei Cheng (william@cs.UCLA.edu)
-% Copyright (C) 1995, 1997, 2001-2023 Free Software Foundation, Inc.
+% Copyright (C) 1995, 1997, 2001-2024 Free Software Foundation, Inc.
%
% This file is part of GNU Emacs.
%
diff --git a/doc/lispintro/cons-4.eps b/doc/lispintro/cons-4.eps
index bf995906a12..84da01f1f2b 100644
--- a/doc/lispintro/cons-4.eps
+++ b/doc/lispintro/cons-4.eps
@@ -4,7 +4,7 @@
%%CreationDate: Wed Mar 8 14:25:06 1995
%%Creator: Tgif-2.16-p4 by William Chia-Wei Cheng (william@cs.UCLA.edu)
-% Copyright (C) 1995, 1997, 2001-2023 Free Software Foundation, Inc.
+% Copyright (C) 1995, 1997, 2001-2024 Free Software Foundation, Inc.
%
% This file is part of GNU Emacs.
%
diff --git a/doc/lispintro/cons-5.eps b/doc/lispintro/cons-5.eps
index cd27259ae98..5325f7aa5a3 100644
--- a/doc/lispintro/cons-5.eps
+++ b/doc/lispintro/cons-5.eps
@@ -4,7 +4,7 @@
%%CreationDate: Wed Mar 8 14:27:28 1995
%%Creator: Tgif-2.16-p4 by William Chia-Wei Cheng (william@cs.UCLA.edu)
-% Copyright (C) 1995, 1997, 2001-2023 Free Software Foundation, Inc.
+% Copyright (C) 1995, 1997, 2001-2024 Free Software Foundation, Inc.
%
% This file is part of GNU Emacs.
%
diff --git a/doc/lispintro/drawers.eps b/doc/lispintro/drawers.eps
index 446bd8c71a7..9162dc96b89 100644
--- a/doc/lispintro/drawers.eps
+++ b/doc/lispintro/drawers.eps
@@ -9,7 +9,7 @@
%%EndComments
%%BeginProlog
-% Copyright (C) 2001-2023 Free Software Foundation, Inc.
+% Copyright (C) 2001-2024 Free Software Foundation, Inc.
%
% This file is part of GNU Emacs.
%
diff --git a/doc/lispintro/emacs-lisp-intro.texi b/doc/lispintro/emacs-lisp-intro.texi
index fce7583fe91..1e10f62104a 100644
--- a/doc/lispintro/emacs-lisp-intro.texi
+++ b/doc/lispintro/emacs-lisp-intro.texi
@@ -115,7 +115,7 @@ Edition @value{edition-number}, @value{update-date}
@sp 1
Distributed with Emacs version @value{EMACSVER}.
@sp 1
-Copyright @copyright{} 1990--1995, 1997, 2001--2023 Free Software
+Copyright @copyright{} 1990--1995, 1997, 2001--2024 Free Software
Foundation, Inc.
@sp 1
@@ -317,7 +317,7 @@ List Processing
* Evaluation:: Running a program.
* Variables:: Returning a value from a variable.
* Arguments:: Passing information to a function.
-* set & setq:: Setting the value of a variable.
+* setq:: Setting the value of a variable.
* Summary:: The major points.
* Error Message Exercises::
@@ -358,7 +358,6 @@ Arguments
Setting the Value of a Variable
-* Using set:: Setting values.
* Using setq:: Setting a quoted value.
* Counting:: Using @code{setq} to count.
@@ -1060,7 +1059,7 @@ of Lisp.
* Evaluation:: Running a program.
* Variables:: Returning a value from a variable.
* Arguments:: Passing information to a function.
-* set & setq:: Setting the value of a variable.
+* setq:: Setting the value of a variable.
* Summary:: The major points.
* Error Message Exercises::
@end menu
@@ -1782,7 +1781,7 @@ A symbol can have any value attached to it or, to use the jargon, we can
string, @code{"such as this"}; to a list, such as @code{(spruce pine
oak)}; we can even bind a variable to a function definition.
-A symbol can be bound to a value in several ways. @xref{set & setq, ,
+A symbol can be bound to a value in several ways. @xref{setq, ,
Setting the Value of a Variable}, for information about one way to do
this.
@@ -2273,52 +2272,52 @@ When your fill column is 70 and you evaluate the expression, the
message @code{"He saw 38 red foxes leaping."} appears in your echo
area.
-@node set & setq
+@node setq
@section Setting the Value of a Variable
@cindex Variable, setting value
@cindex Setting value of variable
@cindex @samp{bind} defined
-There are several ways by which a variable can be given a value. One of
-the ways is to use either the function @code{set} or the special form
-@code{setq}. Another way is to use @code{let} (@pxref{let}). (The
-jargon for this process is to @dfn{bind} a variable to a value.)
+There are several ways by which a variable can be given a value.
+One of the ways is to use the special form @code{setq}. Another way
+is to use @code{let} (@pxref{let}). (The jargon for this process is
+to @dfn{bind} a variable to a value.)
-The following sections not only describe how @code{set} and @code{setq}
-work but also illustrate how arguments are passed.
+The following sections not only describe how @code{setq} works but
+also illustrate how arguments are passed.
@menu
-* Using set:: Setting values.
-* Using setq:: Setting a quoted value.
+* Using setq:: Setting variables.
* Counting:: Using @code{setq} to count.
@end menu
-@node Using set
-@subsection Using @code{set}
+@node Using setq
+@subsection Using @code{setq}
@findex set
-To set the value of the symbol @code{flowers} to the list @code{'(rose
+To set the value of the symbol @code{flowers} to the list @code{(rose
violet daisy buttercup)}, evaluate the following expression by
positioning the cursor after the expression and typing @kbd{C-x C-e}.
@smallexample
-(set 'flowers '(rose violet daisy buttercup))
+(setq flowers '(rose violet daisy buttercup))
@end smallexample
@noindent
The list @code{(rose violet daisy buttercup)} will appear in the echo
-area. This is what is @emph{returned} by the @code{set} function. As a
-side effect, the symbol @code{flowers} is bound to the list; that is,
-the symbol @code{flowers}, which can be viewed as a variable, is given
-the list as its value. (This process, by the way, illustrates how a
-side effect to the Lisp interpreter, setting the value, can be the
-primary effect that we humans are interested in. This is because every
-Lisp function must return a value if it does not get an error, but it
-will only have a side effect if it is designed to have one.)
+area. This is what is @emph{returned} by the @code{setq} special
+form. As a side effect, the symbol @code{flowers} is bound to the
+list; that is, the symbol @code{flowers}, which can be viewed as
+a variable, is given the list as its value. (This process, by the
+way, illustrates how a side effect to the Lisp interpreter, setting
+the value, can be the primary effect that we humans are interested in.
+This is because every Lisp function must return a value if it does not
+get an error, but it will only have a side effect if it is designed to
+have one.)
-After evaluating the @code{set} expression, you can evaluate the symbol
-@code{flowers} and it will return the value you just set. Here is the
-symbol. Place your cursor after it and type @kbd{C-x C-e}.
+After evaluating the @code{setq} expression, you can evaluate the
+symbol @code{flowers} and it will return the value you just set.
+Here is the symbol. Place your cursor after it and type @kbd{C-x C-e}.
@smallexample
flowers
@@ -2336,30 +2335,8 @@ in front of it, what you will see in the echo area is the symbol itself,
'flowers
@end smallexample
-Note also, that when you use @code{set}, you need to quote both
-arguments to @code{set}, unless you want them evaluated. Since we do
-not want either argument evaluated, neither the variable
-@code{flowers} nor the list @code{(rose violet daisy buttercup)}, both
-are quoted. (When you use @code{set} without quoting its first
-argument, the first argument is evaluated before anything else is
-done. If you did this and @code{flowers} did not have a value
-already, you would get an error message that the @samp{Symbol's value
-as variable is void}; on the other hand, if @code{flowers} did return
-a value after it was evaluated, the @code{set} would attempt to set
-the value that was returned. There are situations where this is the
-right thing for the function to do; but such situations are rare.)
-
-@node Using setq
-@subsection Using @code{setq}
-@findex setq
-
-As a practical matter, you almost always quote the first argument to
-@code{set}. The combination of @code{set} and a quoted first argument
-is so common that it has its own name: the special form @code{setq}.
-This special form is just like @code{set} except that the first argument
-is quoted automatically, so you don't need to type the quote mark
-yourself. Also, as an added convenience, @code{setq} permits you to set
-several different variables to different values, all in one expression.
+Also, as an added convenience, @code{setq} permits you to set several
+different variables to different values, all in one expression.
To set the value of the variable @code{carnivores} to the list
@code{'(lion tiger leopard)} using @code{setq}, the following expression
@@ -2369,18 +2346,6 @@ is used:
(setq carnivores '(lion tiger leopard))
@end smallexample
-@noindent
-This is exactly the same as using @code{set} except the first argument
-is automatically quoted by @code{setq}. (The @samp{q} in @code{setq}
-means @code{quote}.)
-
-@need 1250
-With @code{set}, the expression would look like this:
-
-@smallexample
-(set 'carnivores '(lion tiger leopard))
-@end smallexample
-
Also, @code{setq} can be used to assign different values to
different variables. The first argument is bound to the value
of the second argument, the third argument is bound to the value of the
@@ -2400,14 +2365,14 @@ to the symbol @code{herbivores}:
not have fit on a page; and humans find it easier to read nicely
formatted lists.)
-Although I have been using the term ``assign'', there is another way of
-thinking about the workings of @code{set} and @code{setq}; and that is to
-say that @code{set} and @code{setq} make the symbol @emph{point} to the
-list. This latter way of thinking is very common and in forthcoming
-chapters we shall come upon at least one symbol that has ``pointer'' as
-part of its name. The name is chosen because the symbol has a value,
-specifically a list, attached to it; or, expressed another way,
-the symbol is set to point to the list.
+Although I have been using the term ``assign'', there is another way
+of thinking about the workings of @code{setq}; and that is to say that
+@code{setq} makes the symbol @emph{point} to the list. This latter
+way of thinking is very common and in forthcoming chapters we shall
+come upon at least one symbol that has ``pointer'' as part of its
+name. The name is chosen because the symbol has a value, specifically
+a list, attached to it; or, expressed another way, the symbol is set
+to point to the list.
@node Counting
@subsection Counting
@@ -3598,6 +3563,8 @@ and the two are not intended to refer to the same value. The
@unnumberedsubsec @code{let} Prevents Confusion
@end ifnottex
+@c FIXME!! lexbind!!
+
@cindex @samp{local variable} defined
@cindex @samp{variable, local}, defined
The @code{let} special form prevents confusion. @code{let} creates a
@@ -4471,9 +4438,7 @@ number; it will be printed as the character with that @sc{ascii} code.
The @code{setq} special form sets the value of its first argument to the
value of the second argument. The first argument is automatically
quoted by @code{setq}. It does the same for succeeding pairs of
-arguments. Another function, @code{set}, takes only two arguments and
-evaluates both of them before setting the value returned by its first
-argument to the value returned by its second argument.
+arguments.
@item buffer-name
Without an argument, return the name of the buffer, as a string.
@@ -5445,7 +5410,11 @@ That expression starts with @code{get-buffer-create buffer}. The
function tells the computer to use the buffer with the name specified
as the one to which you are copying, or if such a buffer does not
exist, to create it. Then, the @code{with-current-buffer} function
-evaluates its body with that buffer temporarily current.
+evaluates its body with that buffer temporarily current, after which
+it will switch back to the buffer we are at now@footnote{It is like
+calling @w{@code{(save-excursion (set-buffer @dots{}) @dots{})}} in
+one go, though it is defined slightly differently which interested
+reader can find out using @code{describe-function}.}.
(This demonstrates another way to shift the computer's attention but
not the user's. The @code{append-to-buffer} function showed how to do
@@ -5982,12 +5951,12 @@ In outline, the whole function looks like this:
(and @var{are-both-transient-mark-mode-and-mark-active-true})
(push-mark))
(let (@var{determine-size-and-set-it})
- (goto-char
- (@var{if-there-is-an-argument}
- @var{figure-out-where-to-go}
- @var{else-go-to}
- (point-min))))
- @var{do-nicety}
+ (goto-char
+ (@var{if-there-is-an-argument}
+ @var{figure-out-where-to-go}
+ @var{else-go-to}
+ (point-min))))
+ @var{do-nicety}
@end group
@end smallexample
@@ -6040,12 +6009,13 @@ like this:
@group
(if (> (buffer-size) 10000)
;; @r{Avoid overflow for large buffer sizes!}
- (* (prefix-numeric-value arg)
- (/ size 10))
+ (* (prefix-numeric-value arg)
+ (/ size 10))
(/
(+ 10
- (*
- size (prefix-numeric-value arg))) 10)))
+ (* size
+ (prefix-numeric-value arg)))
+ 10))
@end group
@end smallexample
@@ -6182,7 +6152,7 @@ The code looks like this:
@c Keep this on one line.
@smallexample
-(/ (+ 10 (* size (prefix-numeric-value arg))) 10))
+(/ (+ 10 (* size (prefix-numeric-value arg))) 10)
@end smallexample
@need 1200
@@ -6199,7 +6169,7 @@ enclosing expression:
(*
size
(prefix-numeric-value arg)))
- 10))
+ 10)
@end group
@end smallexample
@@ -8165,9 +8135,9 @@ the expectation that all goes well has a @code{when}. The code uses
text that exists.
A @code{when} expression is simply a programmers' convenience. It is
-an @code{if} without the possibility of an else clause. In your mind,
-you can replace @code{when} with @code{if} and understand what goes
-on. That is what the Lisp interpreter does.
+like an @code{if} without the possibility of an else clause. In your
+mind, you can replace @code{when} with @code{if} and understand what
+goes on. That is what the Lisp interpreter does.
Technically speaking, @code{when} is a Lisp macro. A Lisp macro
enables you to define new control constructs and other language
@@ -8176,8 +8146,9 @@ expression which will in turn compute the value. In this case, the
other expression is an @code{if} expression.
The @code{kill-region} function definition also has an @code{unless}
-macro; it is the converse of @code{when}. The @code{unless} macro is
-an @code{if} without a then clause
+macro; it is the opposite of @code{when}. The @code{unless} macro is
+like an @code{if} except that it has no then-clause, and it supplies
+an implicit @code{nil} for that.
For more about Lisp macros, see @ref{Macros, , Macros, elisp, The GNU
Emacs Lisp Reference Manual}. The C programming language also
@@ -12876,7 +12847,40 @@ The next line of the @code{forward-paragraph} function begins a
introduced}), in which Emacs binds a total of seven variables:
@code{opoint}, @code{fill-prefix-regexp}, @code{parstart},
@code{parsep}, @code{sp-parstart}, @code{start}, and
-@code{found-start}.
+@code{found-start}. The first part of the @code{let*} expression
+looks like below:
+
+@smallexample
+@group
+(let* ((opoint (point))
+ (fill-prefix-regexp
+ (and fill-prefix (not (equal fill-prefix ""))
+ (not paragraph-ignore-fill-prefix)
+ (regexp-quote fill-prefix)))
+ ;; Remove ^ from paragraph-start and paragraph-sep if they are there.
+ ;; These regexps shouldn't be anchored, because we look for them
+ ;; starting at the left-margin. This allows paragraph commands to
+ ;; work normally with indented text.
+ ;; This hack will not find problem cases like "whatever\\|^something".
+ (parstart (if (and (not (equal "" paragraph-start))
+ (equal ?^ (aref paragraph-start 0)))
+ (substring paragraph-start 1)
+ paragraph-start))
+ (parsep (if (and (not (equal "" paragraph-separate))
+ (equal ?^ (aref paragraph-separate 0)))
+ (substring paragraph-separate 1)
+ paragraph-separate))
+ (parsep
+ (if fill-prefix-regexp
+ (concat parsep "\\|"
+ fill-prefix-regexp "[ \t]*$")
+ parsep))
+ ;; This is used for searching.
+ (sp-parstart (concat "^[ \t]*\\(?:" parstart "\\|" parsep "\\)"))
+ start found-start)
+ ...)
+@end group
+@end smallexample
The variable @code{parsep} appears twice, first, to remove instances
of @samp{^}, and second, to handle fill prefixes.
@@ -13244,6 +13248,10 @@ The last expression when there is no fill prefix is
@end smallexample
@noindent
+(Note that this code snippet is copied verbatim from the original code,
+so the two extra ending parentheses are matching the previous @code{if}
+and @code{while}.)
+
This says that if there is no fill prefix and if we are not at the
end, point should move to the beginning of whatever was found by the
regular expression search for @code{sp-parstart}.
@@ -14624,7 +14632,7 @@ almost the same code as for the recursive version of
@need 800
@noindent
-Let's re-use @kbd{C-c =} as a convenient key binding:
+Let's reuse @kbd{C-c =} as a convenient key binding:
@smallexample
(global-set-key "\C-c=" 'count-words-defun)
@@ -15793,6 +15801,7 @@ of the @code{and} expression.
@c colon in printed section title causes problem in Info cross reference
This way, we avoid an error.
+
@iftex
@noindent
(For information about @code{and}, see
@@ -16883,8 +16892,14 @@ remember to look here to remind myself.
@node Text and Auto-fill
@section Text and Auto Fill Mode
-Now we come to the part that turns on Text mode and
-Auto Fill mode.
+Now we come to the part that turns on Text mode and Auto Fill
+mode@footnote{
+This section suggests settings that are more suitable for writers.
+For programmers, the default mode will be set to the corresponding
+prog-mode automatically based on the type of the file. And it's
+perfectly fine if you want to keep the fundamental mode as the default
+mode.
+}.
@smallexample
@group
@@ -16936,21 +16951,26 @@ Here is the line again; how does it work?
@cindex Text Mode turned on
@smallexample
-(setq major-mode 'text-mode)
+(setq-default major-mode 'text-mode)
@end smallexample
@noindent
This line is a short, but complete Emacs Lisp expression.
-We are already familiar with @code{setq}. It sets the following variable,
-@code{major-mode}, to the subsequent value, which is @code{text-mode}.
-The single-quote before @code{text-mode} tells Emacs to deal directly
-with the @code{text-mode} symbol, not with whatever it might stand for.
-@xref{set & setq, , Setting the Value of a Variable},
-for a reminder of how @code{setq} works.
-The main point is that there is no difference between the procedure you
-use to set a value in your @file{.emacs} file and the procedure you use
-anywhere else in Emacs.
+We are already familiar with @code{setq}. We use a similar macro
+@code{setq-default} to set the following variable,
+@code{major-mode}@footnote{
+We use @code{setq-default} here because @code{text-mode} is
+buffer-local. If we use @code{setq}, it will only apply to the
+current buffer, whereas using @code{setq-default} will also apply to
+newly created buffers. This is not recommended for programmers.
+}, to the subsequent value, which is @code{text-mode}. The
+single-quote before @code{text-mode} tells Emacs to deal directly with
+the @code{text-mode} symbol, not with whatever it might stand for.
+@xref{setq, , Setting the Value of a Variable}, for a reminder of how
+@code{setq} works. The main point is that there is no difference
+between the procedure you use to set a value in your @file{.emacs}
+file and the procedure you use anywhere else in Emacs.
@need 800
Here is the next line:
diff --git a/doc/lispintro/lambda-1.eps b/doc/lispintro/lambda-1.eps
index 91a7ce9431f..ecfa25dca49 100644
--- a/doc/lispintro/lambda-1.eps
+++ b/doc/lispintro/lambda-1.eps
@@ -4,7 +4,7 @@
%%CreationDate: Wed Mar 8 14:31:53 1995
%%Creator: Tgif-2.16-p4 by William Chia-Wei Cheng (william@cs.UCLA.edu)
-% Copyright (C) 1995, 1997, 2001-2023 Free Software Foundation, Inc.
+% Copyright (C) 1995, 1997, 2001-2024 Free Software Foundation, Inc.
%
% This file is part of GNU Emacs.
%
diff --git a/doc/lispintro/lambda-2.eps b/doc/lispintro/lambda-2.eps
index 9dc7f138eda..8f2b2220918 100644
--- a/doc/lispintro/lambda-2.eps
+++ b/doc/lispintro/lambda-2.eps
@@ -4,7 +4,7 @@
%%CreationDate: Wed Mar 8 14:33:09 1995
%%Creator: Tgif-2.16-p4 by William Chia-Wei Cheng (william@cs.UCLA.edu)
-% Copyright (C) 1995, 1997, 2001-2023 Free Software Foundation, Inc.
+% Copyright (C) 1995, 1997, 2001-2024 Free Software Foundation, Inc.
%
% This file is part of GNU Emacs.
%
diff --git a/doc/lispintro/lambda-3.eps b/doc/lispintro/lambda-3.eps
index b403271c1f3..8929fd294f4 100644
--- a/doc/lispintro/lambda-3.eps
+++ b/doc/lispintro/lambda-3.eps
@@ -4,7 +4,7 @@
%%CreationDate: Wed Mar 8 14:33:49 1995
%%Creator: Tgif-2.16-p4 by William Chia-Wei Cheng (william@cs.UCLA.edu)
-% Copyright (C) 1995, 1997, 2001-2023 Free Software Foundation, Inc.
+% Copyright (C) 1995, 1997, 2001-2024 Free Software Foundation, Inc.
%
% This file is part of GNU Emacs.
%
diff --git a/doc/lispref/ChangeLog.1 b/doc/lispref/ChangeLog.1
index c96ba40dbe5..ee8f418414c 100644
--- a/doc/lispref/ChangeLog.1
+++ b/doc/lispref/ChangeLog.1
@@ -5792,7 +5792,7 @@
* display.texi (Face Functions): Mention define-obsolete-face-alias.
-2009-08-26 Ulrich Mueller <ulm@gentoo.org>
+2009-08-26 Ulrich Müller <ulm@gentoo.org>
* nonascii.texi (Character Codes): Fix typos.
@@ -13989,7 +13989,7 @@
;; coding: utf-8
;; End:
- Copyright (C) 1998-2023 Free Software Foundation, Inc.
+ Copyright (C) 1998-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/doc/lispref/Makefile.in b/doc/lispref/Makefile.in
index 325f23a3c0f..476b8cf8fe6 100644
--- a/doc/lispref/Makefile.in
+++ b/doc/lispref/Makefile.in
@@ -1,6 +1,6 @@
### @configure_input@
-# Copyright (C) 1990-1996, 1998-2023 Free Software Foundation, Inc.
+# Copyright (C) 1990-1996, 1998-2024 Free Software Foundation, Inc.
# This file is part of GNU Emacs.
diff --git a/doc/lispref/README b/doc/lispref/README
index 48bbccd61f9..2fe37630bae 100644
--- a/doc/lispref/README
+++ b/doc/lispref/README
@@ -1,4 +1,4 @@
-Copyright (C) 2001-2023 Free Software Foundation, Inc. -*- outline -*-
+Copyright (C) 2001-2024 Free Software Foundation, Inc. -*- outline -*-
See the end of the file for license conditions.
diff --git a/doc/lispref/abbrevs.texi b/doc/lispref/abbrevs.texi
index a9a5f84434d..9b719145584 100644
--- a/doc/lispref/abbrevs.texi
+++ b/doc/lispref/abbrevs.texi
@@ -1,6 +1,6 @@
@c -*-texinfo-*-
@c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990--1994, 1999, 2001--2023 Free Software Foundation,
+@c Copyright (C) 1990--1994, 1999, 2001--2024 Free Software Foundation,
@c Inc.
@c See the file elisp.texi for copying conditions.
@node Abbrevs
diff --git a/doc/lispref/anti.texi b/doc/lispref/anti.texi
index cddf675d336..0cb956eea98 100644
--- a/doc/lispref/anti.texi
+++ b/doc/lispref/anti.texi
@@ -1,6 +1,6 @@
@c -*-texinfo-*-
@c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1999, 2002--2023 Free Software Foundation, Inc.
+@c Copyright (C) 1999, 2002--2024 Free Software Foundation, Inc.
@c See the file elisp.texi for copying conditions.
@c This node must have no pointers.
diff --git a/doc/lispref/back.texi b/doc/lispref/back.texi
index adc3c575f27..19f78d4c567 100644
--- a/doc/lispref/back.texi
+++ b/doc/lispref/back.texi
@@ -1,6 +1,6 @@
\input texinfo @c -*-texinfo-*-
@c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 2001--2023 Free Software Foundation, Inc.
+@c Copyright (C) 2001--2024 Free Software Foundation, Inc.
@c See the file elisp.texi for copying conditions.
@c
@c %**start of header
diff --git a/doc/lispref/backups.texi b/doc/lispref/backups.texi
index cba212c634d..8d0f3806646 100644
--- a/doc/lispref/backups.texi
+++ b/doc/lispref/backups.texi
@@ -1,6 +1,6 @@
@c -*-texinfo-*-
@c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990--1995, 1999, 2001--2023 Free Software Foundation,
+@c Copyright (C) 1990--1995, 1999, 2001--2024 Free Software Foundation,
@c Inc.
@c See the file elisp.texi for copying conditions.
@node Backups and Auto-Saving
diff --git a/doc/lispref/buffers.texi b/doc/lispref/buffers.texi
index 86c47ae7310..6a5367c17ba 100644
--- a/doc/lispref/buffers.texi
+++ b/doc/lispref/buffers.texi
@@ -1,6 +1,6 @@
@c -*-texinfo-*-
@c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990--1995, 1998--1999, 2001--2023 Free Software
+@c Copyright (C) 1990--1995, 1998--1999, 2001--2024 Free Software
@c Foundation, Inc.
@c See the file elisp.texi for copying conditions.
@node Buffers
@@ -957,10 +957,10 @@ with a @code{nil} @var{norecord} argument since this may lead to
infinite recursion.
@end defvar
-@defun buffer-match-p condition buffer-or-name &optional arg
+@defun buffer-match-p condition buffer-or-name &rest args
This function checks if a buffer designated by @code{buffer-or-name}
-satisfies the specified @code{condition}. Optional third argument
-@var{arg} is passed to the predicate function in @var{condition}. A
+satisfies the specified @code{condition}. Optional arguments
+@var{args} are passed to the predicate function in @var{condition}. A
valid @var{condition} can be one of the following:
@itemize @bullet{}
@item
@@ -969,23 +969,21 @@ satisfies the condition if the regular expression matches the buffer
name.
@item
A predicate function, which should return non-@code{nil} if the buffer
-matches. If the function expects one argument, it is called with
-@var{buffer-or-name} as the argument; if it expects 2 arguments, the
-first argument is @var{buffer-or-name} and the second is @var{arg}
-(or @code{nil} if @var{arg} is omitted).
+matches. It is called with
+@var{buffer-or-name} as the first argument followed by @var{args}.
@item
A cons-cell @code{(@var{oper} . @var{expr})} where @var{oper} is one
of
@table @code
@item (not @var{cond})
Satisfied if @var{cond} doesn't satisfy @code{buffer-match-p} with
-the same buffer and @code{arg}.
+the same buffer and @code{args}.
@item (or @var{conds}@dots{})
Satisfied if @emph{any} condition in @var{conds} satisfies
-@code{buffer-match-p}, with the same buffer and @code{arg}.
+@code{buffer-match-p}, with the same buffer and @code{args}.
@item (and @var{conds}@dots{})
Satisfied if @emph{all} the conditions in @var{conds} satisfy
-@code{buffer-match-p}, with the same buffer and @code{arg}.
+@code{buffer-match-p}, with the same buffer and @code{args}.
@item derived-mode
Satisfied if the buffer's major mode derives from @var{expr}.
@item major-mode
@@ -998,14 +996,14 @@ string) or @code{(and)} (empty conjunction).
@end itemize
@end defun
-@defun match-buffers condition &optional buffer-list arg
+@defun match-buffers condition &optional buffer-list &rest args
This function returns a list of all buffers that satisfy the
@code{condition}. If no buffers match, the function returns
@code{nil}. The argument @var{condition} is as defined in
@code{buffer-match-p} above. By default, all the buffers are
considered, but this can be restricted via the optional argument
@code{buffer-list}, which should be a list of buffers to consider.
-Optional third argument @var{arg} will be passed to @var{condition} in
+Remaining arguments @var{args} will be passed to @var{condition} in
the same way as @code{buffer-match-p} does.
@end defun
diff --git a/doc/lispref/commands.texi b/doc/lispref/commands.texi
index 78fc43d0daf..10f47d736d2 100644
--- a/doc/lispref/commands.texi
+++ b/doc/lispref/commands.texi
@@ -1,6 +1,6 @@
@c -*-texinfo-*-
@c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990--1995, 1998--1999, 2001--2023 Free Software
+@c Copyright (C) 1990--1995, 1998--1999, 2001--2024 Free Software
@c Foundation, Inc.
@c See the file elisp.texi for copying conditions.
@node Command Loop
@@ -1854,20 +1854,19 @@ represented in Lisp as lists. The lists record both the starting mouse
position and the final position, like this:
@example
-(@var{event-type}
- (@var{window1} START-POSITION)
- (@var{window2} END-POSITION))
+(@var{event-type} @var{start-position} @var{end-position})
@end example
For a drag event, the name of the symbol @var{event-type} contains the
prefix @samp{drag-}. For example, dragging the mouse with button 2
held down generates a @code{drag-mouse-2} event. The second and third
-elements of the event give the starting and ending position of the
-drag, as mouse position lists (@pxref{Click Events}). You can access
-the second element of any mouse event in the same way. However, the
-drag event may end outside the boundaries of the frame that was
-initially selected. In that case, the third element's position list
-contains that frame in place of a window.
+elements of the event, @var{start-position} and @var{end-position} in
+the foregoing illustration, are set to the start and end positions of
+the drag as mouse position lists (@pxref{Click Events}). You can
+access the second element of any mouse event in the same way.
+However, the drag event may end outside the boundaries of the frame
+that was initially selected. In that case, the third element's
+position list contains that frame in place of a window.
The @samp{drag-} prefix follows the modifier key prefixes such as
@samp{C-} and @samp{M-}.
@@ -2107,8 +2106,9 @@ When no command is bound to @code{touchscreen-begin},
translate key sequences containing touch screen events into ordinary
mouse events (@pxref{Mouse Events}.) Since Emacs doesn't support
distinguishing events originating from separate mouse devices, it
-assumes that only one touchpoint is active while translation takes
-place; breaking this assumption may lead to unexpected behavior.
+assumes that a maximum of two touchpoints are active while translation
+takes place, and does not place any guarantees on the results of event
+translation when that restriction is overstepped.
Emacs applies two different strategies for translating touch events
into mouse events, contingent on factors such as the commands bound to
@@ -2151,7 +2151,7 @@ is dismissed (@pxref{Mouse Menus}), Emacs also avoids 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, consequentially displaying
+starting position of the touch sequence, consequently displaying
the mouse menu.
@cindex @code{mouse-1-menu-command}, a symbol property
@@ -2160,6 +2160,15 @@ purpose of displaying pop-up menus, Emacs additionally behaves as
illustrated in the last paragraph if @code{down-mouse-1} is bound to a
command whose name has the property @code{mouse-1-menu-command}.
+@cindex pinch-to-zoom touchscreen gesture translation
+When a second touch point is registered as a touch point is already
+being translated, gesture translation is terminated, and the distance
+from the second touch point (the @dfn{ancillary tool}) to the first is
+measured. Subsequent motion from either of those touch points will
+yield @code{touchscreen-pinch} events incorporating the ratio formed
+by the distance between their new positions and the distance measured
+at the outset, as illustrated in the following table.
+
@cindex touchscreen gesture events
If touch gestures are detected during translation, one of the
following input events may be generated:
@@ -2196,8 +2205,36 @@ position of the touchpoint.
@item (touchscreen-restart-drag @var{posn})
This event is sent upon the start of a touch sequence resulting in the
continuation of a ``drag-to-select'' gesture (subject to the
-aformentioned user option) with @var{posn} set to the position list of
+aforementioned user option) with @var{posn} set to the position list of
the initial @code{touchscreen-begin} event within that touch sequence.
+
+@cindex @code{touchscreen-pinch} event
+@item (touchscreen-pinch @var{posn} @var{ratio} @var{pan-x} @var{pan-y} @var{ratio-diff})
+This event is delivered upon significant changes to the positions of
+either active touch point when an ancillary tool is active.
+
+@var{posn} is a mouse position list for the midpoint of a line drawn
+from the ancillary tool to the other touch point being observed.
+
+@var{ratio} is the distance between both touch points being observed
+divided by that distance when the ancillary point was first
+registered; which is to say, the scale of the ``pinch'' gesture.
+
+@var{pan-x} and @var{pan-y} are the difference between the pixel
+position of @var{posn} and this position within the last event
+delivered appertaining to this series of touch events, or in the case
+that no such event exists, the centerpoint between both touch points
+when the ancillary tool was first registered.
+
+@var{ratio-diff} is the difference between this event's ratio and
+@var{ratio} in the last event delivered; it is @var{ratio} if no such
+event exists.
+
+Such events are sent when the magnitude of the changes they represent
+will yield a @var{ratio} which differs by more than @code{0.2} from
+that in the previous event, or the sum of @var{pan-x} and @var{pan-y}
+will surpass half the frame's character width in pixels (@pxref{Frame
+Font}).
@end table
@cindex handling touch screen events
@@ -2208,7 +2245,7 @@ below is from commands bound directly to @code{touchscreen-begin}
events; they allow responding to commonly used touch screen gestures
separately from mouse event translation.
-@defun touch-screen-track-tap event &optional update data
+@defun touch-screen-track-tap event &optional update data threshold
This function is used to track a single ``tap'' gesture originating
from the @code{touchscreen-begin} event @var{event}, often used to
set the point or to activate a button. It waits for a
@@ -2221,6 +2258,14 @@ contains at least one touchpoint with the same identifier as in
the list of touchpoints in that @code{touchscreen-update} event, and
@var{data}.
+If @var{threshold} is non-@code{nil} and such an event indicates that
+the touchpoint represented by @var{event} has moved beyond a threshold
+of either @var{threshold} or 10 pixels if it is not a number from the
+position of @var{event}, @code{nil} is returned and mouse event
+translation is resumed for that touchpoint, so as not to impede the
+recognition of any subsequent touchscreen gesture arising from its
+sequence.
+
If any other event arrives in the mean time, @code{nil} is returned.
The caller should not perform any action in that case.
@end defun
@@ -2762,16 +2807,6 @@ the @code{track-mouse} macro, that produces an event like this:
(mouse-movement (#<frame *ielm* 0x102849a30> nil (563 . 205) 532301936))
@end smallexample
-To handle a SIGUSR1 signal, define an interactive function, and
-bind it to the @code{signal usr1} event sequence:
-
-@smallexample
-(defun usr1-handler ()
- (interactive)
- (message "Got USR1 signal"))
-(keymap-global-set "<signal> <usr1>" 'usr1-handler)
-@end smallexample
-
@node Classifying Events
@subsection Classifying Events
@cindex event type
@@ -3978,26 +4013,19 @@ the timeout elapses).
In batch mode (@pxref{Batch Mode}), @code{sit-for} cannot be
interrupted, even by input from the standard input descriptor. It is
thus equivalent to @code{sleep-for}, which is described below.
-
-It is also possible to call @code{sit-for} with three arguments,
-as @code{(sit-for @var{seconds} @var{millisec} @var{nodisp})},
-but that is considered obsolete.
@end defun
-@defun sleep-for seconds &optional millisec
+@defun sleep-for seconds
This function simply pauses for @var{seconds} seconds without updating
the display. It pays no attention to available input. It returns
@code{nil}.
The argument @var{seconds} need not be an integer. If it is floating
point, @code{sleep-for} waits for a fractional number of seconds.
-Some systems support only a whole number of seconds; on these systems,
-@var{seconds} is rounded down.
-The optional argument @var{millisec} specifies an additional waiting
-period measured in milliseconds. This adds to the period specified by
-@var{seconds}. If the system doesn't support waiting fractions of a
-second, you get an error if you specify nonzero @var{millisec}.
+It is also possible to call @code{sleep-for} with two arguments,
+as @code{(sleep-for @var{seconds} @var{millisec})},
+but that is considered obsolete and will be removed in the future.
Use @code{sleep-for} when you wish to guarantee a delay.
@end defun
diff --git a/doc/lispref/compile.texi b/doc/lispref/compile.texi
index a51691bddcf..98a01fb67f9 100644
--- a/doc/lispref/compile.texi
+++ b/doc/lispref/compile.texi
@@ -1,6 +1,6 @@
@c -*-texinfo-*-
@c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990--1994, 2001--2023 Free Software Foundation, Inc.
+@c Copyright (C) 1990--1994, 2001--2024 Free Software Foundation, Inc.
@c See the file elisp.texi for copying conditions.
@node Byte Compilation
@chapter Byte Compilation
@@ -422,7 +422,7 @@ execution of the compiled file. For example,
@lisp
(eval-when-compile
(unless (fboundp 'some-new-thing)
- (defmacro 'some-new-thing ()
+ (defmacro some-new-thing ()
(compatibility code))))
@end lisp
@@ -801,9 +801,9 @@ Compilation, the previous chapter}, Emacs can also optionally compile
Lisp function definitions into a true compiled code, known as
@dfn{native code}. This feature uses the @file{libgccjit} library,
which is part of the GCC distribution, and requires that Emacs be
-built with support for using that library. It also requires to have
-GCC and Binutils (the assembler and linker) available on your system
-for you to be able to native-compile Lisp code.
+built with support for using that library. It also requires GCC and
+Binutils (the assembler and linker) to be available on your system for
+you to be able to native-compile Lisp code.
@vindex native-compile@r{, a Lisp feature}
To determine whether the current Emacs process can produce and load
@@ -831,9 +831,9 @@ produced by earlier or later Emacs versions; native compilation of the
same Lisp code by a different Emacs version will usually produce a
natively-compiled library under a unique file name that only that
version of Emacs will be able to load. However, the use of unique
-file names allows to have in the same directory several versions of
-the same Lisp library natively-compiled by several different versions
-of Emacs.
+file names enables several versions of the same Lisp library
+natively-compiled by several different versions of Emacs to be placed
+within the same directory.
@vindex no-native-compile
A non-@code{nil} file-local variable binding of
@@ -878,8 +878,7 @@ well.
You can natively-compile either a single function or macro
definition, or a whole file of Lisp code, with the
@code{native-compile} function. Natively-compiling a file will
-produce both the corresponding @file{.elc} file with byte code and the
-@file{.eln} file with native code.
+produce the @file{.eln} file with native code.
@findex native-comp-limple-mode
@vindex native-comp-verbose
@@ -971,6 +970,18 @@ compilation subprocesses in parallel, under the control of
Variables}).
@end defun
+@deffn Command emacs-lisp-native-compile
+This command compiles the file visited by the current buffer into
+native code, if the file was changed since the last time it was
+natively-compiled.
+@end deffn
+
+@deffn Command emacs-lisp-native-compile-and-load
+This command compiles the file visited by the current buffer into
+native code, like @code{emacs-lisp-native-compile}, but it also loads
+the native code when the compilation finishes.
+@end deffn
+
The following function allows Lisp programs to test whether
native-compilation is available at runtime.
@@ -1116,7 +1127,7 @@ functions provided by the @file{.elc} file.
@end defvar
@cindex trampolines, in native compilation
- Setting the value of @code{native-comp-jit-compilation} to@code{nil}
+ Setting the value of @code{native-comp-jit-compilation} to @code{nil}
disables JIT native compilation. However, even when JIT native
compilation is disabled, Emacs might still need to start asynchronous
native compilation subprocesses to produce @dfn{trampolines}. To
diff --git a/doc/lispref/control.texi b/doc/lispref/control.texi
index 3aee9dd80e4..acf9be5c3ff 100644
--- a/doc/lispref/control.texi
+++ b/doc/lispref/control.texi
@@ -1,6 +1,6 @@
@c -*- mode: texinfo; coding: utf-8 -*-
@c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990--1995, 1998--1999, 2001--2023 Free Software
+@c Copyright (C) 1990--1995, 1998--1999, 2001--2024 Free Software
@c Foundation, Inc.
@c See the file elisp.texi for copying conditions.
@node Control Structures
@@ -36,13 +36,14 @@ evaluated sequentially. You can use macros to define your own control
structure constructs (@pxref{Macros}).
@menu
-* Sequencing:: Evaluation in textual order.
-* Conditionals:: @code{if}, @code{cond}, @code{when}, @code{unless}.
-* Combining Conditions:: @code{and}, @code{or}, @code{not}, and friends.
+* Sequencing:: Evaluation in textual order.
+* Conditionals:: @code{if}, @code{cond}, @code{when}, @code{unless}.
+* Combining Conditions:: @code{and}, @code{or}, @code{not}, and friends.
* Pattern-Matching Conditional:: How to use @code{pcase} and friends.
-* Iteration:: @code{while} loops.
-* Generators:: Generic sequences and coroutines.
-* Nonlocal Exits:: Jumping out of a sequence.
+* Iteration:: @code{while} loops.
+* Generators:: Generic sequences and coroutines.
+* Nonlocal Exits:: Jumping out of a sequence.
+* Conditional Compilation:: A facility like C's #if.
@end menu
@node Sequencing
@@ -597,6 +598,10 @@ Two symbols to avoid are @code{t}, which behaves like @code{_}
Likewise, it makes no sense to bind keyword symbols
(@pxref{Constant Variables}).
+@item `@var{qpat}
+A backquote-style pattern. @xref{Backquote Patterns}, for the
+details.
+
@item (cl-type @var{type})
Matches if @var{expval} is of type @var{type}, which is a type
descriptor as accepted by @code{cl-typep} (@pxref{Type Predicates,,,cl,Common
@@ -724,7 +729,7 @@ has over @code{cl-case}
;; symbol
('success (message "Done!"))
('would-block (message "Sorry, can't do it now"))
- ('read-only (message "The shmliblick is read-only"))
+ ('read-only (message "The schmilblick is read-only"))
('access-denied (message "You do not have the needed rights"))
@end group
@group
@@ -1235,7 +1240,8 @@ The first three clauses use backquote-style patterns.
@code{`(add ,x ,y)} is a pattern that checks that @code{form}
is a three-element list starting with the literal symbol @code{add},
then extracts the second and third elements and binds them
-to symbols @code{x} and @code{y}, respectively.
+to symbols @code{x} and @code{y}, respectively. This is known as
+@dfn{destructuring}, see @ref{Destructuring with pcase Patterns}.
The clause body evaluates @code{x} and @code{y} and adds the results.
Similarly, the @code{call} clause implements a function call,
and the @code{fn} clause implements an anonymous function definition.
@@ -1280,11 +1286,11 @@ fail, @code{pcase} will immediately return @code{nil} without calling
@code{message}.
Extraction of multiple values stored in an object is known as
-@dfn{destructuring}. Using @code{pcase} patterns allows to perform
-@dfn{destructuring binding}, which is similar to a local binding
-(@pxref{Local Variables}), but gives values to multiple elements of
-a variable by extracting those values from an object of compatible
-structure.
+@dfn{destructuring}. Using @code{pcase} patterns allows you to
+perform @dfn{destructuring binding}, which is similar to a local
+binding (@pxref{Local Variables}), but gives values to multiple
+elements of a variable by extracting those values from an object of
+compatible structure.
The macros described in this section use @code{pcase} patterns to
perform destructuring binding. The condition of the object to be of
@@ -1882,6 +1888,9 @@ verbatim, don't just write @code{(error @var{string})}. If @var{string}
@var{string} contains @samp{%}, @samp{`}, or @samp{'} it may be
reformatted, with undesirable results. Instead, use @code{(error "%s"
@var{string})}.
+
+When @code{noninteractive} is non-@code{nil} (@pxref{Batch Mode}),
+this function kills Emacs if the signaled error has no handler.
@end defun
@defun signal error-symbol data
@@ -1915,6 +1924,9 @@ variable to a list of the form @code{(@var{error-symbol} .@:
The function @code{signal} never returns.
@c (though in older Emacs versions it sometimes could).
+If the error @var{error-symbol} has no handler, and
+@code{noninteractive} is non-@code{nil} (@pxref{Batch Mode}),
+this function eventually kills Emacs.
@example
@group
@@ -1979,11 +1991,14 @@ function which called the primitive that signaled the error.
@end defvar
@cindex @code{debug-on-error} use
-An error that has no explicit handler may call the Lisp debugger. The
-debugger is enabled if the variable @code{debug-on-error} (@pxref{Error
-Debugging}) is non-@code{nil}. Unlike error handlers, the debugger runs
-in the environment of the error, so that you can examine values of
-variables precisely as they were at the time of the error.
+An error that has no explicit handler may call the Lisp debugger
+(@pxref{Invoking the Debugger}). The debugger is enabled if the
+variable @code{debug-on-error} (@pxref{Error Debugging}) is
+non-@code{nil}. Unlike error handlers, the debugger runs in the
+environment of the error, so that you can examine values of variables
+precisely as they were at the time of the error. In batch mode
+(@pxref{Batch Mode}), the Emacs process then normally exits with a
+non-zero exit status.
@node Handling Errors
@subsubsection Writing Code to Handle Errors
@@ -2467,3 +2482,47 @@ quit, and the quit happens immediately after the function
@code{ftp-setup-buffer} returns but before the variable @code{process} is
set, the process will not be killed. There is no easy way to fix this bug,
but at least it is very unlikely.
+
+@node Conditional Compilation
+@section Conditional Compilation
+
+ There will be times when you want certain code to be compiled only
+when a certain condition holds. This is particularly the case when
+maintaining Emacs packages; to keep the package compatible with older
+versions of Emacs you may need to use a function or variable which has
+become obsolete in the current version of Emacs.
+
+ You could just use a conditional form to select the old or new form
+at run time, but this tends to output annoying warning messages about
+the obsolete function/variable. For such situations, the macro
+@code{static-if} comes in handy. It is patterned after the special
+form @code{if} (@pxref{Conditionals}).
+
+ To use this facility for an older version of Emacs, copy the source
+for @code{static-if} from the Emacs source file @file{lisp/subr.el}
+into your package.
+
+@defmac static-if condition then-form else-forms...
+Test @var{condition} at macro-expansion time. If its value is
+non-@code{nil}, expand the macro to @var{then-form}, otherwise expand
+it to @var{else-forms} enclosed in a @code{progn}. @var{else-forms}
+may be empty.
+
+Here is an example of its use from CC Mode, which prevents a
+@code{defadvice} form being compiled in newer versions of Emacs:
+@example
+@group
+(static-if (boundp 'comment-line-break-function)
+ (progn)
+ (defvar c-inside-line-break-advice nil)
+ (defadvice indent-new-comment-line (around c-line-break-advice
+ activate preactivate)
+ "Call `c-indent-new-comment-line' if in CC Mode."
+ (if (or c-inside-line-break-advice
+ (not c-buffer-is-cc-mode))
+ ad-do-it
+ (let ((c-inside-line-break-advice t))
+ (c-indent-new-comment-line (ad-get-arg 0))))))
+@end group
+@end example
+@end defmac
diff --git a/doc/lispref/customize.texi b/doc/lispref/customize.texi
index 6d5d9e0a2bc..33708d7faaa 100644
--- a/doc/lispref/customize.texi
+++ b/doc/lispref/customize.texi
@@ -1,6 +1,6 @@
@c -*-texinfo-*-
@c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1997--2023 Free Software Foundation, Inc.
+@c Copyright (C) 1997--2024 Free Software Foundation, Inc.
@c See the file elisp.texi for copying conditions.
@node Customization
@chapter Customization Settings
diff --git a/doc/lispref/debugging.texi b/doc/lispref/debugging.texi
index 169e3ac37d3..774fcaf68bf 100644
--- a/doc/lispref/debugging.texi
+++ b/doc/lispref/debugging.texi
@@ -1,6 +1,6 @@
@c -*-texinfo-*-
@c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990--1994, 1998--1999, 2001--2023 Free Software
+@c Copyright (C) 1990--1994, 1998--1999, 2001--2024 Free Software
@c Foundation, Inc.
@c See the file elisp.texi for copying conditions.
@node Debugging
@@ -13,11 +13,12 @@ Lisp program.
@itemize @bullet
@item
If a problem occurs when you run the program, you can use the built-in
-Emacs Lisp debugger to suspend the Lisp evaluator, and examine and/or
-alter its internal state.
+Emacs Lisp debugger (@pxref{Debugger}) to suspend the Lisp evaluator,
+and examine and/or alter its internal state.
@item
You can use Edebug, a source-level debugger for Emacs Lisp.
+@xref{Edebug}.
@item
@cindex tracing Lisp programs
@@ -47,6 +48,7 @@ You can use the ERT package to write regression tests for the program.
@item
You can profile the program to get hints about how to make it more efficient.
+@xref{Profiling}.
@end itemize
Other useful tools for debugging input and output problems are the
@@ -629,11 +631,18 @@ This is a list of functions that are set to break on entry by means of
to invoke the debugger.
@deffn Command debug &rest debugger-args
-This function enters the debugger. It switches buffers to a buffer
-named @file{*Backtrace*} (or @file{*Backtrace*<2>} if it is the second
-recursive entry to the debugger, etc.), and fills it with information
-about the stack of Lisp function calls. It then enters a recursive
-edit, showing the backtrace buffer in Debugger mode.
+This function enters the debugger. In interactive sessions, it
+switches to a buffer named @file{*Backtrace*} (or
+@file{*Backtrace*<2>} if it is the second recursive entry to the
+debugger, etc.), and fills it with information about the stack of Lisp
+function calls. It then enters a recursive edit, showing the
+backtrace buffer in Debugger mode. In batch mode (more generally,
+when @code{noninteractive} is non-@code{nil}, @pxref{Batch Mode}),
+this function shows the Lisp backtrace on the standard error stream,
+and then kills Emacs, causing it to exit with a non-zero exit code
+(@pxref{Killing Emacs}). Binding
+@code{backtrace-on-error-noninteractive} to @code{nil} suppresses the
+backtrace in batch mode, see below.
The Debugger mode @kbd{c}, @kbd{d}, @kbd{j}, and @kbd{r} commands exit
the recursive edit; then @code{debug} switches back to the previous
@@ -717,6 +726,13 @@ under which @code{debug} is called.
@end table
@end deffn
+@defvar backtrace-on-error-noninteractive
+If this variable is non-@code{nil}, the default, entering the debugger
+in batch mode shows the backtrace of Lisp functions calls. Binding
+the variable to the @code{nil} value suppresses the backtrace and
+shows only the error message.
+@end defvar
+
@node Internals of Debugger
@subsection Internals of the Debugger
diff --git a/doc/lispref/display.texi b/doc/lispref/display.texi
index 0331c48fa6b..10cf5ce89e2 100644
--- a/doc/lispref/display.texi
+++ b/doc/lispref/display.texi
@@ -1,6 +1,6 @@
@c -*- mode: texinfo; coding: utf-8 -*-
@c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990--1995, 1998--2023 Free Software Foundation, Inc.
+@c Copyright (C) 1990--1995, 1998--2024 Free Software Foundation, Inc.
@c See the file elisp.texi for copying conditions.
@node Display
@chapter Emacs Display
@@ -1821,8 +1821,8 @@ where the @var{primary} value is used as described above, and
@var{secondary} is the fallback value used when @var{primary} and the
nesting considerations fail to resolve the precedence between
overlays. In particular, priority value @w{@code{(nil . @var{n})}},
-with @var{n} a positive integer, allows to have the overlays ordered
-by priority when necessary without completely overriding other
+with @var{n} a positive integer, enables you to have the overlays
+ordered by priority when necessary without completely overriding other
overlays.
Currently, all overlays take priority over text properties.
@@ -2726,7 +2726,7 @@ Draw a box with lines of width 1, in color @var{color}.
You can explicitly specify all aspects of the box with a plist on this
form. Any element in this plist can be omitted.
-The values @var{vwidth} and @var{hwidth} specifies respectively the
+The values of @var{vwidth} and @var{hwidth} specify respectively the
width of the vertical and horizontal lines to draw; they default to (1
. 1). A negative horizontal or vertical width @minus{}@var{n} means
to draw a line of width @var{n} that occupies the space of the
@@ -2735,16 +2735,16 @@ width. For simplification the width could be specified with only a
single number @var{n} instead of a list, such case is equivalent to
@code{((abs @var{n}) . @var{n})}.
-The value @var{style} specifies whether to draw a 3D box. If it is
+The value of @var{color} specifies the color to draw with. The default
+is the background color of the face for 3D boxes and
+@code{flat-button}, and the foreground color of the face for other
+boxes.
+
+The value of @var{style} specifies whether to draw a 3D box. If it is
@code{released-button}, the box looks like a 3D button that is not
being pressed. If it is @code{pressed-button}, the box looks like a
3D button that is being pressed. If it is @code{nil},
@code{flat-button} or omitted, a plain 2D box is used.
-
-The value @var{color} specifies the color to draw with. The default
-is the background color of the face for 3D boxes and
-@code{flat-button}, and the foreground color of the face for other
-boxes.
@end table
@item :inverse-video
@@ -4254,14 +4254,20 @@ key-attribute pairs may be omitted from the list if they are not
specified by @var{font}.
@end defun
-@defun font-xlfd-name font &optional fold-wildcards
+@defun font-xlfd-name font &optional fold-wildcards long-xlfds
This function returns the XLFD (X Logical Font Descriptor), a string,
matching @var{font}. @xref{Fonts,,, emacs, The GNU Emacs Manual}, for
-information about XLFDs. If the name is too long for an XLFD (which
-can contain at most 255 characters), the function returns @code{nil}.
+information about XLFDs.
If the optional argument @var{fold-wildcards} is non-@code{nil},
consecutive wildcards in the XLFD are folded into one.
+
+If the optional argument @var{long-xlfds} is omitted or @code{nil},
+then the function returns @code{nil} if the XLFD would exceed 255
+characters in length; this is for compatibility with the X protocol,
+which mandates that XLFDs are restricted to that length. If
+@var{long-xlfds} is non-@code{nil}, this restriction is lifted, and
+the function can return XLFDs of any length.
@end defun
The following two functions return important information about a font.
@@ -8725,8 +8731,8 @@ hexadecimal notation.
Display a box containing that string. The string should contain at
most 6 @acronym{ASCII} characters. As an exception, if the string
includes just one character, on text-mode terminals that character
-will be displayed without a box; this allows to handle such
-``acronyms'' as a replacement character for characters that cannot be
+will be displayed without a box; this enables treating such
+``acronyms'' as replacement characters for characters that cannot be
displayed by the terminal.
@item a cons cell @code{(@var{graphical} . @var{text})}
@@ -9022,7 +9028,7 @@ Bidirectionality'' class implementation of the @acronym{UBA},
consistent with the requirements of the Unicode Standard v9.0. Note,
however, that the way Emacs displays continuation lines when text
direction is opposite to the base paragraph direction deviates from
-the UBA, which requires to perform line wrapping before reordering
+the UBA, which requires performing line wrapping before reordering
text for display.
@defvar bidi-display-reordering
diff --git a/doc/lispref/edebug.texi b/doc/lispref/edebug.texi
index c5be3a40d2c..03fae67e528 100644
--- a/doc/lispref/edebug.texi
+++ b/doc/lispref/edebug.texi
@@ -1,6 +1,6 @@
@comment -*-texinfo-*-
@c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1992--1994, 1998--1999, 2001--2023 Free Software
+@c Copyright (C) 1992--1994, 1998--1999, 2001--2024 Free Software
@c Foundation, Inc.
@c See the file elisp.texi for copying conditions.
@@ -1289,6 +1289,8 @@ examples):
@item sexp
A single unevaluated Lisp object, which is not instrumented.
@c an "expression" is not necessarily intended for evaluation.
+If the macro evaluates an argument at macro-expansion time, you should
+use @code{sexp} for it rather than @code{form}.
@item form
A single evaluated expression, which is instrumented. If your macro
diff --git a/doc/lispref/elisp.texi b/doc/lispref/elisp.texi
index 72441c8d442..a3ef8313f8e 100644
--- a/doc/lispref/elisp.texi
+++ b/doc/lispref/elisp.texi
@@ -99,7 +99,7 @@ This is the @cite{GNU Emacs Lisp Reference Manual}
@end ifclear
corresponding to Emacs version @value{EMACSVER}.
-Copyright @copyright{} 1990--1996, 1998--2023 Free Software Foundation,
+Copyright @copyright{} 1990--1996, 1998--2024 Free Software Foundation,
Inc.
@quotation
@@ -534,10 +534,10 @@ Variables
Scoping Rules for Variable Bindings
-* Dynamic Binding:: The default for binding local variables in Emacs.
+* Lexical Binding:: The standard type of local variable binding.
+* Dynamic Binding:: A different type of local variable binding.
* Dynamic Binding Tips:: Avoiding problems with dynamic binding.
-* Lexical Binding:: A different type of local variable binding.
-* Using Lexical Binding:: How to enable lexical binding.
+* Selecting Lisp Dialect:: How to select the Emacs Lisp dialect to use.
* Converting to Lexical Binding:: Convert existing code to lexical binding.
Buffer-Local Variables
diff --git a/doc/lispref/errors.texi b/doc/lispref/errors.texi
index db46a6aaf59..b51a8844dbf 100644
--- a/doc/lispref/errors.texi
+++ b/doc/lispref/errors.texi
@@ -1,6 +1,6 @@
@c -*-texinfo-*-
@c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990--1993, 1999, 2001--2023 Free Software Foundation,
+@c Copyright (C) 1990--1993, 1999, 2001--2024 Free Software Foundation,
@c Inc.
@c See the file elisp.texi for copying conditions.
@node Standard Errors
@@ -246,7 +246,8 @@ signaled when @code{inhibit-interaction} is non-@code{nil} and a user
interaction function (like @code{read-from-minibuffer}) is called.
@end table
-@ignore The following seem to be unused now.
+@c The following seem to be unused now.
+@ignore
The following kinds of error, which are classified as special cases of
@code{arith-error}, can occur on certain systems for invalid use of
mathematical functions. @xref{Math Functions}.
diff --git a/doc/lispref/eval.texi b/doc/lispref/eval.texi
index a45517287b7..f4c99640143 100644
--- a/doc/lispref/eval.texi
+++ b/doc/lispref/eval.texi
@@ -1,6 +1,6 @@
@c -*-texinfo-*-
@c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990--1994, 1998, 2001--2023 Free Software Foundation,
+@c Copyright (C) 1990--1994, 1998, 2001--2024 Free Software Foundation,
@c Inc.
@c See the file elisp.texi for copying conditions.
@node Evaluation
@@ -740,13 +740,17 @@ type of the @var{form} object determines how it is evaluated.
@xref{Forms}.
The argument @var{lexical} specifies the scoping rule for local
-variables (@pxref{Variable Scoping}). If it is omitted or @code{nil},
-that means to evaluate @var{form} using the default dynamic scoping
-rule. If it is @code{t}, that means to use the lexical scoping rule.
-The value of @var{lexical} can also be a non-empty alist specifying a
+variables (@pxref{Variable Scoping}). If it is @code{t}, that means
+to evaluate @var{form} using lexical scoping; this is the recommended
+value. If it is omitted or @code{nil}, that means to use the old
+dynamic-only variable scoping rule.
+
+The value of @var{lexical} can also be a non-empty list specifying a
particular @dfn{lexical environment} for lexical bindings; however,
this feature is only useful for specialized purposes, such as in Emacs
-Lisp debuggers. @xref{Lexical Binding}.
+Lisp debuggers. Each member of the list is either a cons cell which
+represents a lexical symbol-value pair, or a symbol representing a
+(special) variable that would use dynamic scoping if bound.
Since @code{eval} is a function, the argument expression that appears
in a call to @code{eval} is evaluated twice: once as preparation before
diff --git a/doc/lispref/files.texi b/doc/lispref/files.texi
index afedf776c86..9e7aeeecec8 100644
--- a/doc/lispref/files.texi
+++ b/doc/lispref/files.texi
@@ -1,6 +1,6 @@
@c -*-texinfo-*-
@c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990--1995, 1998--1999, 2001--2023 Free Software
+@c Copyright (C) 1990--1995, 1998--1999, 2001--2024 Free Software
@c Foundation, Inc.
@c See the file elisp.texi for copying conditions.
@node Files
@@ -1803,7 +1803,7 @@ If @var{newname} exists, then it must be an empty directory if
@var{oldname} is a directory and a non-directory otherwise.
@end deffn
-@deffn Command copy-file oldname newname &optional ok-if-already-exists time preserve-uid-gid preserve-extended-attributes
+@deffn Command copy-file oldname newname &optional ok-if-already-exists time preserve-uid-gid preserve-permissions
This command copies the file @var{oldname} to @var{newname}. An
error is signaled if @var{oldname} is not a regular file. If @var{newname}
names a directory, it copies @var{oldname} into that directory,
@@ -1871,9 +1871,10 @@ multiple names, it continues to exist under the other names. If
@var{filename} is a symbolic link, @code{delete-file} deletes only the
symbolic link and not its target.
-A suitable kind of @code{file-error} error is signaled if the file
-does not exist, or is not deletable. (On GNU and other POSIX-like
-systems, a file is deletable if its directory is writable.)
+The command signals a suitable kind of @code{file-error} error if
+@var{filename} cannot be deleted. (On GNU and other POSIX-like
+systems, a file can be deleted if its directory is writable.) If the
+file does not exist, this command will not signal any error.
If the optional argument @var{trash} is non-@code{nil} and the
variable @code{delete-by-moving-to-trash} is non-@code{nil}, this
diff --git a/doc/lispref/frames.texi b/doc/lispref/frames.texi
index 853ca5ae69e..16c0432da3a 100644
--- a/doc/lispref/frames.texi
+++ b/doc/lispref/frames.texi
@@ -1,6 +1,6 @@
@c -*-texinfo-*-
@c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990--1995, 1998--1999, 2001--2023 Free Software
+@c Copyright (C) 1990--1995, 1998--1999, 2001--2024 Free Software
@c Foundation, Inc.
@c See the file elisp.texi for copying conditions.
@node Frames
@@ -60,8 +60,12 @@ The frame is displayed on a GNUstep or Macintosh Cocoa graphical
terminal.
@item pc
The frame is displayed on an MS-DOS terminal.
+@item haiku
+The frame is displayed using the Haiku Application Kit.
@item pgtk
The frame is displayed using pure GTK facilities.
+@item android
+The frame is displayed on an Android device.
@end table
@end defun
@@ -224,8 +228,8 @@ The terminal and keyboard coding systems used on the terminal.
@item
The kind of display associated with the terminal. This is the symbol
returned by the function @code{terminal-live-p} (i.e., @code{x},
-@code{t}, @code{w32}, @code{ns}, @code{pc}, @code{haiku}, or @code{pgtk}).
-@xref{Frames}.
+@code{t}, @code{w32}, @code{ns}, @code{pc}, @code{haiku}, @code{pgtk},
+or @code{android}). @xref{Frames}.
@item
A list of terminal parameters. @xref{Terminal Parameters}.
@@ -606,7 +610,7 @@ frames (@pxref{Child Frames}) and @code{undecorated} or
Outer borders are never shown on text terminal frames and on frames
generated by GTK+ routines. On MS-Windows, the outer border is emulated
with the help of a one pixel wide external border. Non-toolkit builds
-on X allow to change the color of the outer border by setting the
+on X allow changing the color of the outer border by setting the
@code{border-color} frame parameter (@pxref{Layout Parameters}).
@item Title Bar
@@ -1000,12 +1004,12 @@ Negative parameter values position the right edge of the outer frame by
frame's native rectangle) and the bottom edge by @var{-y} pixels up from
the bottom edge of the screen (or the parent frame's native rectangle).
-Note that negative values do not permit to align the right or bottom
+Note that negative values do not permit aligning the right or bottom
edge of @var{frame} exactly at the right or bottom edge of its display
-or parent frame. Neither do they allow to specify a position that does
+or parent frame. Neither do they allow specifying a position that does
not lie within the edges of the display or parent frame. The frame
parameters @code{left} and @code{top} (@pxref{Position Parameters})
-allow to do that, but may still fail to provide good results for the
+allow doing that, but may still fail to provide good results for the
initial or a new frame.
This function has no effect on text terminal frames.
@@ -1742,7 +1746,7 @@ Geometry}) of the frame, in characters. Normally, the functions that
establish a frame's initial width or resize a frame horizontally make
sure that all the frame's windows, vertical scroll bars, fringes,
margins and vertical dividers can be displayed. This parameter, if
-non-@code{nil} allows to make a frame narrower than that with the
+non-@code{nil} enables making a frame narrower than that with the
consequence that any components that do not fit will be clipped by the
window manager.
@@ -1753,7 +1757,7 @@ Geometry}) of the frame, in characters. Normally, the functions that
establish a frame's initial size or resize a frame make sure that all
the frame's windows, horizontal scroll bars and dividers, mode and
header lines, the echo area and the internal menu and tool bar can be
-displayed. This parameter, if non-@code{nil} allows to make a frame
+displayed. This parameter, if non-@code{nil} enables making a frame
smaller than that with the consequence that any components that do not
fit will be clipped by the window manager.
@@ -1814,14 +1818,14 @@ the first time.
@vindex fit-frame-to-buffer-margins@r{, a frame parameter}
@item fit-frame-to-buffer-margins
-This parameter allows to override the value of the option
-@code{fit-frame-to-buffer-margins} when fitting this frame to the buffer
-of its root window with @code{fit-frame-to-buffer} (@pxref{Resizing
-Windows}).
+This parameter enables overriding the value of the option
+@code{fit-frame-to-buffer-margins} when fitting this frame to the
+buffer of its root window with @code{fit-frame-to-buffer}
+(@pxref{Resizing Windows}).
@vindex fit-frame-to-buffer-sizes@r{, a frame parameter}
@item fit-frame-to-buffer-sizes
-This parameter allows to override the value of the option
+This parameter enables overriding the value of the option
@code{fit-frame-to-buffer-sizes} when fitting this frame to the buffer
of its root window with @code{fit-frame-to-buffer} (@pxref{Resizing
Windows}).
@@ -1902,13 +1906,13 @@ to not draw bottom dividers.
@vindex menu-bar-lines@r{, a frame parameter}
@item menu-bar-lines
The number of lines to allocate at the top of the frame for a menu bar
-(@pxref{Menu Bar}). The default is one if Menu Bar mode is enabled and
-zero otherwise. @xref{Menu Bars,,,emacs, The GNU Emacs Manual}. For an
-external menu bar (@pxref{Frame Layout}), this value remains unchanged
-even when the menu bar wraps to two or more lines. In that case, the
-@code{menu-bar-size} value returned by @code{frame-geometry}
-(@pxref{Frame Geometry}) allows to derive whether the menu bar actually
-occupies one or more lines.
+(@pxref{Menu Bar}). The default is one if Menu Bar mode is enabled
+and zero otherwise. @xref{Menu Bars,,,emacs, The GNU Emacs Manual}.
+For an external menu bar (@pxref{Frame Layout}), this value remains
+unchanged even when the menu bar wraps to two or more lines. In that
+case, the @code{menu-bar-size} value returned by @code{frame-geometry}
+(@pxref{Frame Geometry}) enables you to establish whether the menu bar
+actually occupies one or more lines.
@vindex tool-bar-lines@r{, a frame parameter}
@item tool-bar-lines
@@ -2219,8 +2223,10 @@ resource must also be set to the string @code{"extended"}.
@item inhibit-double-buffering
If non-@code{nil}, the frame is drawn to the screen without double
buffering. Emacs normally attempts to use double buffering, where
-available, to reduce flicker. Set this property if you experience
-display bugs or pine for that retro, flicker-y feeling.
+available, to reduce flicker; nevertheless, this parameter is provided
+for circumstances where double-buffering induces display corruption,
+and for those eccentrics wistful for the immemorial flicker that once
+beset Emacs.
@vindex skip-taskbar@r{, a frame parameter}
@item skip-taskbar
@@ -3433,15 +3439,15 @@ parameter indicates the number of pixels where the frame @dfn{snaps} at
the respective edge or corner of its parent frame.
There are two ways to drag an entire child frame with the mouse: The
-@code{drag-with-mode-line} parameter, if non-@code{nil}, allows to drag
-a frame without minibuffer window (@pxref{Minibuffer Windows}) via the
-mode line area of its bottommost window. The
-@code{drag-with-header-line} parameter, if non-@code{nil}, allows to
-drag the frame via the header line area of its topmost window.
+@code{drag-with-mode-line} parameter, if non-@code{nil}, enables
+dragging a frame without minibuffer window (@pxref{Minibuffer
+Windows}) via the mode line area of its bottommost window. The
+@code{drag-with-header-line} parameter, if non-@code{nil}, enables
+dragging the frame via the header line area of its topmost window.
In order to give a child frame a draggable header or mode line, the
window parameters @code{mode-line-format} and @code{header-line-format}
-are handy (@pxref{Window Parameters}). These allow to remove an
+are handy (@pxref{Window Parameters}). These allow removing an
unwanted mode line (when @code{drag-with-header-line} is chosen) and to
remove mouse-sensitive areas which might interfere with frame dragging.
@@ -4001,22 +4007,24 @@ defined in the file @file{lisp/term/x-win.el}. Use @kbd{M-x apropos
@cindex secondary selection
In window systems, such as X, data can be transferred between
-different applications by means of @dfn{selections}. X defines an
-arbitrary number of @dfn{selection types}, each of which can store its
-own data; however, only three are commonly used: the @dfn{clipboard},
-@dfn{primary selection}, and @dfn{secondary selection}. Other window
-systems support only the clipboard. @xref{Cut and Paste,, Cut and
-Paste, emacs, The GNU Emacs Manual}, for Emacs commands that make use
-of these selections. This section documents the low-level functions
-for reading and setting window-system selections.
+different applications by means of @dfn{selections}. Each window
+system defines an arbitrary number of @dfn{selection types}, all
+storing their own data; however, only three are commonly used: the
+@dfn{clipboard}, @dfn{primary selection}, and @dfn{secondary
+selection}. @xref{Cut and Paste,, Cut and Paste, emacs, The GNU Emacs
+Manual}, for Emacs commands that make use of these selections. This
+section documents the low-level functions for reading and setting
+window-system selections; @xref{Accessing Selections}, for
+documentation concerning selection types and data formats under
+particular window systems.
@deffn Command gui-set-selection type data
This function sets a window-system selection. It takes two arguments:
a selection type @var{type}, and the value to assign to it, @var{data}.
@var{type} should be a symbol; it is usually one of @code{PRIMARY},
-@code{SECONDARY} or @code{CLIPBOARD}. These are symbols with
-upper-case names, in accord with X Window System conventions. If
+@code{SECONDARY} or @code{CLIPBOARD}. These are generally symbols
+with upper-case names, in accord with X Window System conventions. If
@var{type} is @code{nil}, that stands for @code{PRIMARY}.
If @var{data} is @code{nil}, it means to clear out the selection.
@@ -4044,31 +4052,37 @@ programs. It takes two optional arguments, @var{type} and
The @var{data-type} argument specifies the form of data conversion to
use, to convert the raw data obtained from another program into Lisp
-data. Meaningful values include @code{TEXT}, @code{STRING},
-@code{UTF8_STRING}, @code{TARGETS}, @code{LENGTH}, @code{DELETE},
-@code{FILE_NAME}, @code{CHARACTER_POSITION}, @code{NAME},
-@code{LINE_NUMBER}, @code{COLUMN_NUMBER}, @code{OWNER_OS},
-@code{HOST_NAME}, @code{USER}, @code{CLASS}, @code{ATOM}, and
-@code{INTEGER}. (These are symbols with upper-case names in accord
-with X conventions.) The default for @var{data-type} is
-@code{STRING}. Window systems other than X usually support only a
-small subset of these types, in addition to @code{STRING}.
+data. @xref{X Selections}, for an enumeration of data types valid
+under X, and @xref{Other Selections} for those elsewhere.
@end defun
@defopt selection-coding-system
-This variable specifies the coding system to use when reading and
-writing selections or the clipboard. @xref{Coding
-Systems}. The default is @code{compound-text-with-extensions}, which
-converts to the text representation that X11 normally uses.
+This variable provides a coding system (@pxref{Coding Systems}) which
+is used to encode selection data, and takes effect on MS-Windows and
+X@. It is also used in the MS-DOS port when it runs on MS-Windows and
+can access the Windows clipboard text.
+
+On X, the value of this variable provides the coding system which
+@code{gui-get-selection} will use to decode selection data for a
+subset of text data types, and also forces replies to selection
+requests for the polymorphic @code{TEXT} data type to be encoded by
+the @code{compound-text-with-extensions} coding system rather than
+Unicode.
+
+On MS-Windows, this variable is generally ignored, as the MS-Windows
+clipboard provides the information about decoding as part of the
+clipboard data, and uses either UTF-16 or locale-specific encoding
+automatically as appropriate. We recommend to set the value of this
+variable only on the older Windows 9X, as it is otherwise used only in
+the very rare cases when the information provided by the clipboard
+data is unusable for some reason.
+
+The default value of this variable is the system code page under
+MS-Windows 95, 98 or Me, @code{utf-16le-dos} on Windows
+NT/W2K/XP/Vista/7/8/10/11, @code{iso-latin-1-dos} on MS-DOS, and
+@code{nil} elsewhere.
@end defopt
-@cindex clipboard support (for MS-Windows)
-When Emacs runs on MS-Windows, it does not implement X selections in
-general, but it does support the clipboard. @code{gui-get-selection}
-and @code{gui-set-selection} on MS-Windows support the text data type
-only; if the clipboard holds other types of data, Emacs treats the
-clipboard as empty. The supported data type is @code{STRING}.
-
For backward compatibility, there are obsolete aliases
@code{x-get-selection} and @code{x-set-selection}, which were the
names of @code{gui-get-selection} and @code{gui-set-selection} before
@@ -4077,44 +4091,42 @@ Emacs 25.1.
@node Accessing Selections
@section Accessing Selections
- @code{gui-get-selection} is able to retrieve multiple different
-kinds of selection data from any number of selections. However, the
-data types and selections that Emacs understands is not precisely
-specified and differs depending on the window system on which Emacs is
-running.
-
- At the same time, @code{gui-set-selection} hides a great deal of
-complexity behind its back, at least on some systems: its @var{data}
-argument need not be a string, but is actually given verbatim to
-system specific code.
-
- Emacs's implementation of selections is most complete on the X
-Window System. This is both an artifact of history (X was the first
-window system supported by Emacs) and one of technical reasons:
-instead of using selections only to transfer text and multimedia
-content between clients, X uses selections as a general inter-client
-communication system, leading to a great proliferation of selection
-data types.
-
- Even more confusingly, X also supports another inter-client
-communication mechanism: the Inter-Client Exchange. However, ICE is
+ The data types and selections that @code{gui-get-selection} and
+@code{gui-set-selection} understand are not precisely specified and
+differ subject to the window system on which Emacs is running.
+
+ At the same time, @code{gui-set-selection} abstracts over plenty of
+complexity: its @var{data} argument is given verbatim to
+system-specific code to be rendered suitable for transfer to the
+window system or requesting clients.
+
+ The most comprehensive implementation of selections exists under the
+X Window System. This is both an artifact of history (X was the first
+window system supported by Emacs) and one occasioned by technical
+considerations: X selections are not merely an expedient for the
+transfer of text and multimedia content between clients, but a general
+inter-client communication system, a design that has yielded a
+proliferation of selection and data types.
+
+ Compounding this confusion, there is another inter-client
+communication mechanism under X: the Inter-Client Exchange. ICE is
only used by Emacs to communicate with session managers, and is a
separate topic.
@menu
-* X Selections:: Selection data types (and more) on X.
+* X Selections:: Selection data types (and more) on X@.
* Other Selections:: How they work on other window systems.
@end menu
@node X Selections
@subsection X Selections
- X refrains from defining fixed data types for selection data, or a
-fixed number of selections. Selections are instead identified by X
-``atoms'', which are unique 29-bit identifiers issued by the X server
-for a corresponding name. In Emacs, you can simply write a symbol
-with the name of the atom, and Emacs will transparently request these
-identifiers where necessary.
+ X refrains from defining fixed data types for selection data or a
+fixed number of selections. Selections are identified by X ``atoms'',
+which are unique 29-bit identifiers issued by the X server for string
+names. This complexity is hidden by Emacs: when Lisp provides a
+symbol whose name is that of the atom, Emacs will request these
+identifiers without further intervention.
When a program ``sets'' a selection under X, it actually makes
itself the ``owner'' of the selection---the X server will then deliver
@@ -4123,30 +4135,32 @@ requesting client with the selection data.
Similarly, a program does not ``get'' selection data from the X
server. Instead, its selection requests are sent to the client with
-the window which last took ownership over the selection, which then
-replies with the requested data.
+the window which last asserted ownership over the selection, which is
+expected to respond with the requested data.
- Each selection request contains three parameters:
+ Each selection request incorporates three parameters:
@itemize @bullet
@item
-The window which requested the selection; this is used to identify the
+The window which requested the selection, which identifies the
@c Not a typo: X spells ``requestor'' with an o.
requesting program, otherwise known as the @dfn{requestor}.
@item
-An atom identifying the ``target'' to which the owner should convert
+An atom identifying the @dfn{target} to which the owner should convert
the selection. It is easiest to think of the conversion target as the
kind of data that the requestor wants: in selection requests made by
-Emacs, the target is determined by the @dfn{type} argument to
+Emacs, the target is determined by the @var{type} argument to
@code{gui-get-selection}.
@item
-A 32-bit timestamp containing the X server time at which the requestor
-last obtained input.
+A 32-bit timestamp representing the X server time at which the
+requestor last received input; this parameter is not relevant to Lisp
+code, for it's only meant to abet synchronization between the X
+server, owner and requestor.
@end itemize
- The selection owner responds by tranferring to the requestor a
+ The selection owner responds by transferring to the requestor a
series of bytes, 16 bit words, or 32 bit words, along with another
atom identifying the type of those words. After requesting a
selection, Emacs then applies its own interpretation of the data
@@ -4154,31 +4168,30 @@ format and data type to convert the data transferred by the selection
owner to a Lisp representation, which @code{gui-get-selection}
returns.
- By default, Emacs converts selection data consisting of any series
-of bytes to a unibyte string containing those bytes, selection data
-consisting of a single 16-bit or 32-bit word as an unsigned number,
-and selection data consisting of multiple such words as a vector of
-unsigned numbers. However, Emacs applies special treatment for
-several selection data types:
+ Emacs converts selection data consisting of any series of bytes to a
+unibyte string holding those bytes, that consisting of a single 16-bit
+or 32-bit word as an unsigned number, and that consisting of multiple
+such words as a vector of unsigned numbers. The exceptions to this
+general pattern are that Emacs applies special treatment for data from
+the following conversion targets:
@table @code
@item INTEGER
-16-bit or 32-bit words of this type are treated as signed integers,
-instead of unsigned ones. If there are multiple words in the
-selection data, a vector is returned; otherwise, the integer is
-returned by itself.
+16-bit or 32-bit words of this type are treated as signed rather than
+unsigned integers. If there are multiple words in the selection data,
+a vector is returned; otherwise, the integer is returned by itself.
@item ATOM
32-bit words of this type are treated as X atoms, and returned (either
-alone or as vectors) as Lisp symbols containing the names they
-identify. Invalid atoms are returned as @code{nil}.
+alone or as vectors) as Lisp symbols by the names they identify.
+Invalid atoms are replaced by @code{nil}.
@item COMPOUND_TEXT
@item UTF8_STRING
@item STRING
-Unibyte strings returned for these data types will have a single
-@code{foreign-selection} text property set to a symbol with the type
-of the selection data.
+A single @code{foreign-selection} text property set to the type of the
+selection data will be placed in unibyte strings derived from a
+request for these data types.
@end table
Each selection owner must return at least two selection targets:
@@ -4189,21 +4202,21 @@ number of other targets, some of which may be standardized by the X
Consortium's
@url{http://x.org/releases/X11R7.6/doc/xorg-docs/specs/ICCCM/icccm.html,
Inter-Client Communication Conventions Manual}, while others, such as
-@code{UTF8_STRING}, were supposed to be standardized by the XFree86
-Project, which unfortunately did not happen.
+@code{UTF8_STRING}, were meant to be standardized by the XFree86
+Project, but their standardization was never completed.
Requests for a given selection target may, by convention, return
data in a specific type, or it may return data in one of several
types, whichever is most convenient for the selection owner; the
latter type of selection target is dubbed a @dfn{polymorphic target}.
-A selection target may also return no data at all: by convention, the
-selection owner performs some action a side effect upon responding to
-a selection request with that target, and as such these targets are
-referred to as @dfn{side-effect targets}.
+In response to a request, a selection target may also return no data
+at all, whereafter the selection owner executes some action as a side
+effect. Targets that are thus replied to are termed @dfn{side-effect
+targets}.
- Here are some selection targets which behave in a reasonably
-standard manner when used with the @code{CLIPBOARD}, @code{PRIMARY},
-or @code{SECONDARY} selections.
+ Here are some selection targets whose behavior is generally
+consistent with a standard when requested from the @code{CLIPBOARD},
+@code{PRIMARY}, or @code{SECONDARY} selections.
@table @code
@item ADOBE_PORTABLE_DOCUMENT_FORMAT
@@ -4269,7 +4282,7 @@ positions of the selection data in the text field containing it.
@item MODULE
This target returns the name of any function containing the selection
-data. It is mainly used by text editors.
+data. It is principally requested by text editors.
@item STRING
This target returns the selection data as a string of type
@@ -4301,17 +4314,18 @@ selection owner.
When a request for the targets @code{STRING}, @code{COMPOUND_TEXT},
or @code{UTF8_STRING} is made using the function
@code{gui-get-selection}, and neither @code{selection-coding-system}
-nor @code{next-selection-coding-system} are set, the returned strings
-are additionally decoded using the appropriate coding system for those
-data types: @code{iso-8859-1}, @code{compound-text-with-extensions}
-and @code{utf-8} respectively.
+nor @code{next-selection-coding-system} is set, the resultant strings
+are decoded by the proper coding systems for those targets:
+@code{iso-8859-1}, @code{compound-text-with-extensions} and
+@code{utf-8} respectively.
In addition to the targets specified above (and the many targets
used by various programs for their own purposes), several popular
-programs and toolkits have decided to define selection data types of
-their own, without consulting the appropriate X standards bodies.
-These targets are usually named after MIME types, such as
-@code{text/html} or @code{image/jpeg}, and have been known to contain:
+programs and toolkits have defined selection data types of their own,
+without consulting the appropriate X standards bodies. These targets
+are generally named after such MIME types as @code{text/html} or
+@code{image/jpeg}; they have been witnessed returning the following
+forms of data:
@itemize @bullet
@item
@@ -4322,54 +4336,56 @@ names of an image or text file.
Image or text data in the appropriate format.
@item
-@code{file://} URIs (or possibly newline or NUL terminated lists of
-URIs) leading to files in the appropriate format.
+@code{file://} URIs (or conceivably newline or NUL terminated lists of
+URIs) identifying files in the appropriate format.
@end itemize
These selection targets were first used by Netscape, but are now
-found in all kinds of programs, especially those based on recent
+proffered by all kinds of programs, especially those based on recent
versions of the GTK+ or Qt toolkits.
- Emacs is also capable of acting as a selection owner. When
-@code{gui-set-selection} is called, the selection data specified is
-not transferred to the X server; instead, Emacs records it internally
-and obtains ownership of the selection.
+ Emacs is also capable of serving as a selection owner. When
+@code{gui-set-selection} is called, the selection data provided is
+recorded internally and Emacs obtains ownership of the selection being
+set.
@defvar selection-converter-alist
- Alist of selection targets to ``selection converter'' functions.
-When a selection request is received, Emacs looks up the selection
-converter associated with the requested selection target.
+Alist of selection targets to ``selection converter'' functions. When
+a selection request is received, Emacs looks up the selection
+converter pertaining to the requested selection target.
- The selection converter is called with three arguments: the symbol
+Selection converters are called with three arguments: the symbol
corresponding to the atom identifying the selection being requested,
the selection target that is being requested, and the value set with
-@code{gui-set-selection}. The value which it returns is either a cons
-of a symbol specifying the data type and a number, symbol, or a vector
-of numbers or symbols, or its cdr by itself.
+@code{gui-set-selection}. The values which they must return are
+either conses of symbols designating the data type and numbers,
+symbols, vectors of numbers or symbols, or the cdrs of such conses by
+themselves.
- If the value is the special symbol @code{NULL}, the data type is set
-to @code{NULL}, and no data is returned to the requestor.
+If a selection converter's value is the special symbol @code{NULL},
+the data type returned to its requestor is set to @code{NULL}, and no
+data is sent in response.
- If the value is a string, it must be a unibyte string; should no
-data type be explicitly specified, the data is transferred to the
+If such a value is a string, it must be a unibyte string; should no
+data type be explicitly specified, the data is transferred to its
requestor with the type @code{STRING}.
- If the value is a symbol, its ``atom'' is retrieved, and it is
-transferred to the requestor as a 32-bit value---if no data type was
-specified, its type is @code{ATOM}.
+If it is a symbol, its ``atom'' is retrieved, and it is transferred to
+its requestor as a 32-bit value---if no data type is specified, its
+type is @code{ATOM}.
- If the value is a number between @code{-32769} and @code{32768}, it
-is transferred to the requestor as a 16 bit value---if no data type
-was specified, its type is @code{INTEGER}.
+If it is a number between @code{-32769} and @code{32768}, it is
+transferred to its requestor as a 16 bit value---if no data type is
+specified, its type is @code{INTEGER}.
- If the value is any other number, it is returned as a 32 bit value.
-Even if the number returned is unsigned, the requestor will treat
-words of type @code{INTEGER} as signed. To return an unsigned value,
-specify the type @code{CARDINAL} instead.
+If it is any other number, it is accounted a 32 bit value. Even if
+the number returned is unsigned, its requestor will treat words of
+type @code{INTEGER} as signed. To return an unsigned value, specify
+the type @code{CARDINAL} in its place.
- If the value is a vector of symbols or numbers, it is returned as a
-list of multiple atoms or numbers. The data type returned by default
-is determined by that of its first element.
+If it is a vector of symbols or numbers, the response to its requestor
+will be a list of multiple atoms or numbers. The data type returned
+when not expressly set is that of the list's first element.
@end defvar
By default, Emacs is configured with selection converters for the
@@ -4382,8 +4398,8 @@ This selection converter returns selection data as:
@itemize @bullet
@item
A string of type @code{C_STRING}, if the selection contents contain no
-multibyte characters, or contains 8-bit characters with all 8 bits
-set.
+multibyte characters, or contain ``raw 8-bit bytes'' (@pxref{Text
+Representations}).
@item
A string of type @code{STRING}, if the selection contents can be
@@ -4479,7 +4495,7 @@ These selection converters are used for internal purposes.
@end table
With the exception of @code{INTEGER}, all selection converters
-expect the value given to @code{gui-set-selection} to be one of the
+expect the data provided to @code{gui-set-selection} to be one of the
following:
@itemize @bullet
@@ -4495,28 +4511,69 @@ bounds of the selection data in the buffer @var{buf}.
@node Other Selections
@subsection Other Selections
- Window systems such as MS-Windows, Nextstep, Haiku and Android do
-not provide selections corresponding to the X semantics. Each window
-system provides its own ad-hoc emulation of selections, none of which
-make use of the ``selection converter'' mechanism described above. In
-addition, only the @code{PRIMARY}, @code{CLIPBOARD}, and
-@code{SECONDARY} selections are typically supported, alongside the
-@code{XdndSelection} used for drag-and-drop operations.
-
- GTK itself exposes emulations of X selections to applications, but
-those emulations are of varying completeness. While Emacs built with
-PGTK will use the same selection interface as Emacs built with X, many
+ Selections under such window systems as MS-Windows, Nextstep, Haiku
+and Android are not aligned with those under X@. Each of these window
+system improvises its own selection mechanism without employing the
+``selection converter'' mechanism illustrated in the preceding node.
+Only the @code{PRIMARY}, @code{CLIPBOARD}, and @code{SECONDARY}
+selections are generally supported, with the @code{XdndSelection}
+selection that records drag-and-drop data also available under
+Nextstep and Haiku.
+
+@cindex PGTK selections
+ GTK seeks to emulate the X selection system, but its emulations are
+not altogether dependable, with the overall quality of each subject to
+the GDK backend being used. Therefore, Emacs built with PGTK will
+supply the same selection interface as Emacs built with X, but many
selection targets will not be useful.
- On MS-Windows, @code{gui-get-selection} accepts a single target,
-@code{STRING}. The value returned is the selection data decoded
-using @code{selection-coding-system}.
-
- @code{gui-set-selection} also only accepts strings, encodes them
-in the selection coding system, and saves them to the clipboard.
-
- On Nextstep, Emacs only supports saving strings to selections.
-However, requests for the following targets are accepted:
+@cindex MS-Windows selection emulation
+@cindex MS-Windows primary and secondary selection
+ Although a clipboard exists, there is no concept of primary or
+secondary selections within the MS-Windows operating system. On this
+system, Emacs simulates the presence of a primary and secondary
+selection, while saving to and retrieving from the clipboard when so
+requested.
+
+ The simulation of the primary and secondary selections is conducted
+by saving values supplied to @code{gui-set-selection} within the
+@code{x-selections} property of the symbol designating the pertinent
+selection, namely the @var{type} argument to @code{gui-get-selection}.
+Each subsequent call to @code{gui-get-selection} in turn returns its
+value, which is not subject to further examination (such as type
+checks and the like). Under such circumstances, @var{data-type}
+argument is generally disregarded. (But see below for the
+qualification regarding @code{TARGETS}.)
+
+@cindex MS-Windows clipboard
+ Where the clipboard selection is concerned (whenever @var{type} is
+@code{CLIPBOARD}), @code{gui-set-selection} verifies that the value
+provided is a string and saves it within the system clipboard once it
+is encoded by the coding system configured in
+@code{selection-coding-system}. Callers of @code{gui-get-selection}
+are required to set @var{data-type} to either @code{STRING} or
+@code{TARGETS}.
+
+ When @var{data-type} is set to @code{TARGETS} in a call to
+@code{gui-get-selection}, a vector of symbols is returned when
+selection data exists, much as it is under X@. It is impossible to
+request clipboard data in any format besides @code{STRING}, for the
+prerequisite data conversion routines are absent. Just as strings
+saved into the clipboard are encoded by the
+@code{selection-coding-system}, so those read from the clipboard are
+decoded by that same coding system; this variable and its cousin
+@code{next-selection-coding-system} merit particular scrutiny when
+difficulties are encountered with saving selection text into the
+clipboard.
+
+@cindex Nextstep selections
+ All three selections standard in X exist in Nextstep as well, but
+Emacs is only capable of saving strings to such selections.
+Restrictions imposed upon calls to @code{gui-set-selection} there are
+much the same as those on MS-Windows, though text is uniformly encoded
+as @code{utf-8-unix} without regard to the value of
+@code{selection-coding-system}. @code{gui-get-selection} is more
+charitable, and accepts requests for the following selection targets:
@c FIXME: how is the text coding system determined, and do image/* or
@c application/* return image data or file names?
@@ -4532,29 +4589,34 @@ However, requests for the following targets are accepted:
@item image/tiff
@end itemize
- On Haiku, Emacs supports the same selection values as on X. In
-addition, Emacs fully implements the primary and secondary selections.
-However, instead of taking ownership over the selection data, Emacs
-transfers the selection data to the window server when
-@code{gui-set-selection} is called. The Haiku window server expects
-selection data to be provided in the form of a ``message'', containing
-associations between data types and selection data.
+ The @code{XdndSelection} selection is also present under Nextstep,
+in the form of a repository that records values supplied to
+@code{gui-set-selection}. Its sole purpose is to save such values for
+the fundamental drag-and-drop function @code{x-begin-drag}
+(@pxref{Drag and Drop}); no guarantees exist concerning its value when
+read by anything else.
-@defvar haiku-normal-selection-encoders
-List of functions which act as selection encoders. When
-@code{gui-set-selection} is called, each function in this list is
-successively called with its @var{selection} and @var{value}
-arguments. If the function returns non-@code{nil}, it should return a
-list of the form @w{@code{(@var{key} @var{type} @var{value})}}, where
-@var{key} is the name of the data type being transferred, @var{type}
-is either a number identifying a data type (in which case @var{value}
-should be a unibyte string that is directly transferred to the window
-server), or a symbol identifying both a data type and how @var{value}
-should be interpreted.
-@end defvar
+@cindex Haiku selections
+ Selections on Haiku systems comprise all three selections customary
+under X and the @code{XdndSelection} that records drag-and-drop data.
- Here are the meaningful values of @var{type}, and what they will
-cause Emacs to interpret @var{value} as:
+ When @code{gui-set-selection} is called for the former three
+selections, the data supplied is converted into a window server
+``message'' by a list of @dfn{selection encoder} functions, which is
+sent to the window server.
+
+@defvar haiku-normal-selection-encoders
+List of selection encoder functions. When @code{gui-set-selection} is
+called, each function in this list is successively called with its
+@var{selection} and @var{value} arguments. If such a function returns
+non-@code{nil}, its return value must be a list of the form
+@w{@code{(@var{key} @var{type} @var{value})}}. In this list,
+@var{key} must be the name of the data being transferred, generally
+that of a MIME type, for example @samp{"text/plain"}, and @var{type}
+is a symbol or a number designating the type of the data; thus also
+governing the interpretation of @var{value}; following is a list of
+valid data types and how each of them will cause @var{value} to be
+interpreted.
@table @code
@item string
@@ -4562,8 +4624,8 @@ A unibyte string. The string is NULL-terminated after being placed in
the message.
@item ref
-A file name. The file is looked up and file system information
-identifying the file is placed in the message.
+A file name. The file is located and the inode identifying the file
+is placed in the message.
@item short
A 16-bit integer value.
@@ -4596,141 +4658,217 @@ format.
@item (haiku-numeric-enum MIME)
A unibyte string containing data in a certain MIME type.
@end table
+@end defvar
- Under Haiku, @code{gui-get-selection} accepts either the targets
-@code{TARGETS} and @code{TIMESTAMP}, where the former returns a vector
-containing supported data types (much like on X), and the latter
-returns the number of times the selection has been set, the targets
-@code{STRING} and @code{UTF8_STRING}, which return text in ISO-Latin-1
-and UTF-8 format, or a MIME type, in which the data is returned
-undecoded as a unibyte string.
+ A call to @code{gui-get-selection} generally returns the the data
+named @var{data-type} within the selection message, albeit with
+@var{data-type} replaced by an alternative name should it be one of
+the following X selection targets:
- Under Android, @code{gui-get-selection} is restricted to returning
-UTF-8 string data of the type @code{STRING}, or image and application
-data associated with a MIME type. @code{gui-set-selection} will only
-set string data, as on MS-Windows.
+@table @code
+@item STRING
+This represents Latin-1 text under X: ``text/plain;charset=iso-8859-1''
+
+@item UTF8_STRING
+This represents UTF-8 text: ``text/plain''
+@end table
+
+ If @var{data-type} is a text type such as @code{STRING} or a MIME
+type matching the pattern @samp{`text/*}, the string data is decoded
+with the coding system apposite for it before being returned.
+
+ Furthermore, the two data types @var{TIMESTAMP} and @code{TARGETS}
+are afforded special treatment; the value returned for the first is
+the number of times the selection has been modified since system
+startup (@emph{not} a timestamp), and that for the other is a vector
+of available selection data types, as elsewhere.
+
+@cindex Android selections
+ Much like MS-Windows, Android provides a clipboard but no primary or
+secondary selection; @code{gui-set-selection} simulates the primary
+and secondary selections by saving the value supplied into a variable
+subsequent calls to @code{gui-get-selection} return.
+
+ From the clipboard, @code{gui-get-selection} is capable of returning
+UTF-8 string data of the type @code{STRING}, the @code{TAREGTS} data
+type, or image and application data of any MIME type.
+@code{gui-set-selection} sets only string data, much as under
+MS-Windows, although this data is not affected by the value of
+@code{selection-coding-system}. By contrast, only string data can be
+saved to and from the primary and secondary selections; but since this
+data is not communicated to programs besides Emacs, it is not subject
+to encoding or decoding by any coding system.
@node Yanking Media
@section Yanking Media
- If you choose, for instance, ``Copy Image'' in a web browser, that
-image is put onto the clipboard, and Emacs can access it via
-@code{gui-get-selection}. But in general, inserting image data into
-an arbitrary buffer isn't very useful---you can't really do much with
-it by default.
-
- So Emacs has a system to let modes register handlers for these
-``complicated'' selections.
+ Data saved within window system selections is not restricted to
+plain text. It is possible for selection data to encompass images or
+other binary data of the like, as well as rich text content instanced
+by HTML, and also PostScript. Since the selection data types incident
+to this data are at variance with those for plain text, the insertion
+of such data is facilitated by a set of functions dubbed
+@dfn{yank-media handlers}, which are registered by each major mode
+undertaking its insertion and called where warranted upon the
+execution of the @code{yank-media} command.
@defun yank-media-handler types handler
-@var{types} can be a @acronym{MIME} media type symbol, a regexp to
-match these, or a list of these symbols and regexps. For instance:
+Register a yank-media handler which applies to the current buffer.
+
+@var{types} can be a symbol designating a selection data type
+(@pxref{Accessing Selections}), a regexp against which such types are
+matched, or a list of these symbols and regexps. For instance:
@example
(yank-media-handler 'text/html #'my-html-handler)
(yank-media-handler "image/.*" #'my-image-handler)
@end example
-A mode can register as many handlers as required.
-
- The @var{handler} function is called with two parameters: The
-@acronym{MIME} media type symbol and the data (as a string). The
-handler should then insert the object into the buffer, or save it, or
-do whatever is appropriate for the mode.
+When a selection offers a data type matching @var{types}, the function
+@var{handler} is called to insert its data, with the symbol
+designating the matching selection data type, and the data returned by
+@code{gui-get-selection}.
@end defun
- The @code{yank-media} command will consult the registered handlers in
-the current buffer, compare that with the available media types on the
-clipboard, and then pass on the matching selection to the handler (if
-any). If there's more than one matching selection, the user is
-queried first.
-
- The @code{yank-media-types} command can be used to explore the
-clipboard/primary selection. It lists all the media types that are
-currently available, and can be handy when creating handlers---to see
-what data is actually available. Some applications put a surprising
-amount of different data types on the clipboard.
+The @code{yank-media-types} command presents a list of selection data
+types that are currently available, which is useful when implementing
+yank-media handlers; for programs generally offer an eclectic and
+seldom consistent medley of data types.
@node Drag and Drop
@section Drag and Drop
@cindex drag and drop
- When the user drops something from another application over Emacs,
-Emacs will try to insert any text and open any URL that was dropped.
-If text was dropped, then it will always be inserted at the location
-of the mouse pointer where the drop happened, or saved in the kill
-ring if insertion failed, which could happen if the buffer was
-read-only. If a URL was dropped instead, then Emacs will first try to
-call an appropriate handler function by matching the URL against
-regexps defined in the variable @code{dnd-protocol-alist}, and then
-against those defined in the variables @code{browse-url-handlers} and
-@code{browse-url-default-handlers}. Should no suitable handler be
-located, Emacs will fall back to inserting the URL as plain text.
+ Data transferred by drag and drop is generally either plain text or
+a list of URLs designating files or other resources. When text is
+dropped, it is inserted at the location of the drop, with recourse to
+saving it into the kill ring if that is not possible.
+
+ URLs dropped are supplied to pertinent @dfn{DND handler functions}
+in the variable @code{dnd-protocol-alist}, or alternatively ``URL
+handlers'' as set forth by the variables @code{browse-url-handlers}
+and @code{browse-url-default-handlers}; absent matching handlers of
+either type, they are treated as plain text and inserted in the
+buffer.
@defvar dnd-protocol-alist
- This variable is a list of cons cells of the form
-@w{@code{(@var{pattern} . @var{action})}}. @var{pattern} is a regexp
-that URLs are matched against after being dropped. @var{action} is a
-function that is called with two arguments, should a URL being dropped
-match @var{pattern}: the URL being dropped, and the action being
-performed for the drop, which is one of the symbols @code{copy},
-@code{move}, @code{link}, @code{private} or @code{ask}.
-
-If @var{action} is @var{private}, then it means the program that
-initiated the drop wants Emacs to perform an unspecified action with
-the URL; a reasonable action to perform in that case is to open the URL
-or copy its contents into the current buffer. Otherwise, @var{action}
-has the same meaning as the @var{action} argument to
+This variable is an alist between regexps against which URLs are
+matched and DND handler functions called on the dropping of matching
+URLs.
+
+@cindex dnd-multiple-handler, a symbol property
+If a handler function is a symbol whose @code{dnd-multiple-handler}
+property (@pxref{Symbol Properties}) is set, then upon a drop it is
+given a list of every URL that matches its regexp; absent this
+property, it is called once for each of those URLs. Following this
+first argument is one of the symbols @code{copy}, @code{move},
+@code{link}, @code{private} or @code{ask} identifying the action to be
+taken.
+
+If @var{action} is @code{private}, the program that initiated the drop
+does not insist on any particular behavior on the part of its
+recipient; a reasonable action to take in that case is to open the URL
+or copy its contents into the current buffer. The other values of
+@var{action} imply much the same as in the @var{action} argument to
@code{dnd-begin-file-drag}.
+
+Once its work completes, a handler function must return a symbol
+designating the action it took: either the action it was provided, or
+the symbol @code{private}, which communicates to the source of the
+drop that the action it prescribed has not been executed.
+
+When multiple handlers match an overlapping subset of items within a
+drop, the handler matched against by the greatest number of items is
+called to open that subset. The items it is supplied are subsequently
+withheld from other handlers, even those they also match.
@end defvar
@cindex drag and drop, X
@cindex drag and drop, other formats
- Emacs implements receiving text and URLs individually for each
-window system, and does not by default support receiving other kinds
-of data as drops. To support receiving other kinds of data, use the
-X-specific interface described below.
-
-@vindex x-dnd-test-function
-@vindex x-dnd-known-types
- When a user drags something from another application over Emacs
-under the X Window System, that other application expects Emacs to
-tell it if Emacs understands the data being dragged. The function in
-the variable @code{x-dnd-test-function} is called by Emacs to
-determine what to reply to any such inquiry. The default value is
-@code{x-dnd-default-test-function}, which accepts drops if the type of
-the data to be dropped is present in @code{x-dnd-known-types}.
-Changing the variables @code{x-dnd-test-function} and
-@code{x-dnd-known-types} can make Emacs accept or reject drops based
-on some other criteria.
-
-@vindex x-dnd-types-alist
- If you want to change the way Emacs receives drops of different data
-types, or you want to enable it to understand a new type, change the variable
-@code{x-dnd-types-alist}. Doing so correctly requires detailed
-knowledge of what data types other applications use for drag and drop.
-
- These data types are typically implemented as special data types
-that can be obtained from an X selection provided by the other
-application. In most cases, they are either the same data types that
-are typically accepted by @code{gui-set-selection}, or MIME types,
-depending on the specific drag-and-drop protocol being used. For
-example, the data type used for plain text may be either
-@code{"STRING"} or @code{"text/plain"}.
+ Emacs does not take measures to accept data besides text and URLs,
+for the window system interfaces which enable this are too far removed
+from each other to abstract over consistently. Nor are DND handlers
+accorded influence over the actions they are meant to take, as
+particular drag-and-drop protocols deny recipients such control. The
+X11 drag-and-drop implementation rests on several underlying protocols
+that make use of selection transfer and share much in common, to which
+low level access is provided through the following functions and
+variables:
+
+@defvar x-dnd-test-function
+This function is called to ascertain whether Emacs should accept a
+drop. It is called with three arguments:
+
+@itemize @bullet
+@item
+The window under the item being dragged, which is to say the window
+whose buffer is to receive the drop. If the item is situated over a
+non-window component of a frame (such as scroll bars, tool bars and
+things to that effect), the frame itself is provided in its place.
+
+@item
+One of the symbols @code{move}, @code{copy}, @code{link} or
+@code{ask}, representing an action to take on the item data suggested
+by the drop source. These symbols carry the same implications as in
+@code{x-begin-drag}.
+
+@item
+A vector of selection data types (@pxref{X Selections}) the item
+provides.
+@end itemize
+
+This function must return @code{nil} to reject the drop or a cons of
+the action that will be taken (such as through transfer to a DND
+handler function) and the selection data type to be requested. The
+action returned in that cons may also be the symbol @code{private},
+which intimates that the action taken is as yet indeterminate.
+@end defvar
+
+@defvar x-dnd-known-types
+Modifying @code{x-dnd-test-function} is generally unwarranted, for its
+default set of criteria for accepting a drop can be adjusted by
+changing this list of selection data types. Each element is a string,
+which if found as the symbol name of an element within the list of
+data types by the default ``test function'', will induce that function
+to accept the drop.
+
+Introducing a new entry into this list is not useful unless a
+counterpart handler function is appended to @code{x-dnd-types-alist}.
+@end defvar
+
+@defvar x-dnd-types-alist
+This variable is an alist between strings designating selection data
+types and functions which are called when things of such types are
+dropped.
+
+Each such function is supplied three arguments; the first is the
+window or frame below the location of the drop, as in
+@code{x-dnd-test-function}; the second is the action to be taken,
+which may be any of the actions returned by test functions, and third
+is the selection data itself (@pxref{Accessing Selections}).
+@end defvar
+
+ Selection data types as provided by X11 drag-and-drop protocols are
+sometimes distinct from those provided by the ICCCM and conforming
+clipboard or primary selection owners. Frequently, the name of a MIME
+type, such as @code{"text/plain;charset=utf-8"} (with discrepant
+capitalization of the ``utf-8''), is substituted for a standard X
+selection name such as @code{UTF8_STRING}.
@cindex XDS
@cindex direct save protocol
@vindex x-dnd-direct-save-function
- When Emacs runs on X window system, it supports the X Direct Save
-(@acronym{XDS}) protocol, which allows users to save a file by
-dragging and dropping it onto an Emacs window, such as a Dired window.
-To comply with the unique requirements of @acronym{XDS}, these
-drag-and-drop requests are processed specially: instead of being
-handled according to @code{x-dnd-types-alist}, they are handled by the
-@dfn{direct-save function} that is the value of the variable
-@code{x-dnd-direct-save-function}. The value should be a function of
-two arguments, @var{need-name} and @var{filename}. The @acronym{XDS}
-protocol uses a two-step procedure for dragging files:
+ The X Direct Save (@acronym{XDS}) protocol enables programs to
+devolve responsibility for naming a dropped file upon the recipient.
+When such a drop transpires, DND handlers and the foregoing X-specific
+interface are largely circumvented, tasking a different function with
+responding to the drop.
+
+@defvar x-dnd-direct-save-function
+This variable should be set to a function that registers and names
+files dropped using the @acronym{XDS} protocol in a two-step
+procedure. It is provided two arguments, @var{need-name} and
+@var{filename}.
@enumerate 1
@item
@@ -4758,8 +4896,9 @@ Dired should update the directory on display by showing the new file
there.
@end enumerate
-The default value of @code{x-dnd-direct-save-function} is
+Its default @code{x-dnd-direct-save-function} is
@code{x-dnd-save-direct}.
+@end defvar
@defun x-dnd-save-direct need-name filename
When called with the @var{need-name} argument non-@code{nil}, this
@@ -4785,48 +4924,47 @@ default directory.)
@end defun
@cindex initiating drag-and-drop
- On capable window systems, Emacs also supports dragging contents
-from its frames to windows of other applications.
+ It is also possible to drag content from Emacs to other programs
+when this is supported by the current window-system. The functions
+which provide for this are as follows:
@cindex drop target, in drag-and-drop operations
@defun dnd-begin-text-drag text &optional frame action allow-same-frame
-This function begins dragging text from @var{frame} to another program
-(known as the @dfn{drop target}), and returns the result of
-drag-and-drop operation when the text is dropped or the drag-and-drop
-operation is canceled. @var{text} is the text that will be inserted
-by the drop target.
+This function starts a drag-and-drop operation from @var{frame} to
+another program (dubbed the @dfn{drop target}), and returns when
+@var{text} is dropped or the operation is canceled.
@var{action} must be one of the symbols @code{copy} or @code{move},
where @code{copy} means that @var{text} should be inserted by the drop
-target, and @code{move} means the same as @code{copy}, but in addition
-the caller may have to delete @var{text} from its source as explained
+target, and @code{move} means the same as @code{copy}, but the caller
+must also delete @var{text} from its source as explained in the list
below.
@var{frame} is the frame where the mouse is currently held down, or
-@code{nil}, which means to use the selected frame. This function may
-return immediately if no mouse buttons are held down, so it should be
-only called immediately after a @code{down-mouse-1} or similar event
-(@pxref{Mouse Events}), with @var{frame} set to the frame where that
-event was generated (@pxref{Click Events}).
+@code{nil}, which means to use the selected frame. Since this
+function might return promptly if no mouse buttons are held down, it
+should be only called in response to a @code{down-mouse-1} or
+analogous event (@pxref{Mouse Events}), with @var{frame} set to the
+frame where that event was generated (@pxref{Click Events}).
-@var{allow-same-frame} specifies whether or not drops on top of
-@var{frame} itself are to be ignored.
+If @var{allow-same-frame} is @code{nil}, drops on top of @var{frame}
+will be ignored.
-The return value specifies the action that the drop target actually
-performed, and optionally what the caller should do. It can be one of
-the following symbols:
+The return value reflects the action that the drop target actually
+performed, and thus also what action, if any, the caller should in
+turn take. It is one of the following symbols:
@table @code
@item copy
The drop target inserted the dropped text.
@item move
-The drop target inserted the dropped text, but in addition the caller
-should delete @var{text} from wherever it originated, such as its
-buffer.
+The drop target inserted the dropped text, and the caller should
+delete @var{text} from the buffer where it was extracted from, if
+applicable.
@item private
-The drop target performed some other unspecified action.
+The drop target took some other unspecified action.
@item nil
The drag-and-drop operation was canceled.
@@ -4835,11 +4973,12 @@ The drag-and-drop operation was canceled.
@end defun
@defun dnd-begin-file-drag file &optional frame action allow-same-frame
-This function begins dragging @var{file} from @var{frame} to another
-program, and returns the result of the drag-and-drop operation when
-the file is dropped or the drag-and-drop operation is canceled.
+This function starts a drag-and-drop operation from @var{frame} to
+another program (dubbed the @dfn{drop target}), and returns when
+@var{file} is dropped or the operation is canceled.
-If @var{file} is a remote file, then a temporary copy will be made.
+If @var{file} is a remote file, then a temporary local copy will be
+made.
@var{action} must be one of the symbols @code{copy}, @code{move} or
@code{link}, where @code{copy} means that @var{file} should be opened
@@ -4848,11 +4987,11 @@ move the file to another location, and @code{link} means the drop
target should create a symbolic link to @var{file}. It is an error to
specify @code{link} as the action if @var{file} is a remote file.
-@var{frame} and @var{allow-same-frame} have the same meaning as in
-@code{dnd-begin-text-drag}.
+@var{frame} and @var{allow-same-frame} mean the same as they do in
+calls to @code{dnd-begin-text-drag}.
The return value is the action that the drop target actually
-performed, which can be one of the following symbols:
+performed, which is one of the following symbols:
@table @code
@item copy
@@ -4881,19 +5020,18 @@ dropping multiple files, then the first file will be used instead.
@end defun
@defun dnd-direct-save file name &optional frame allow-same-frame
-This function is similar to @code{dnd-begin-file-drag} (with the
-default action of copy), but instead of specifying the action you
-specify the name of the copy created by the target program in
-@code{name}.
+The behavior of this function is akin to that of
+@code{dnd-begin-file-drag} (when the default action @code{copy} is
+used), except that it accepts a name under which the copy is meant to
+be filed.
@end defun
@cindex initiating drag-and-drop, low-level
The high-level interfaces described above are implemented on top of
-a lower-level primitive. If you need to drag content other than files
-or text, use the low-level interface @code{x-begin-drag}
-instead. However, using it will require detailed knowledge of the
-data types and actions used by the programs to transfer content via
-drag-and-drop on each platform you want to support.
+a lower-level primitive. The low-level interface @code{x-begin-drag}
+is also available for dragging content besides text and files. It
+demands detailed knowledge of the data types and actions understood by
+programs on each platform its callers wish to support.
@defun x-begin-drag targets &optional action frame return-frame allow-current-frame follow-tooltip
This function begins a drag from @var{frame}, and returns when the
@@ -4905,60 +5043,59 @@ non-@code{nil}. If no mouse buttons are held down when the
drag-and-drop operation begins, this function may immediately return
@code{nil}.
-@var{targets} is a list of strings describing selection targets, much
-like the @var{data-type} argument to @code{gui-get-selection}, that
-the drop target can request from Emacs (@pxref{Window System
+@var{targets} is a list of strings representing selection targets,
+much like the @var{data-type} argument to @code{gui-get-selection},
+that the drop target can request from Emacs (@pxref{Window System
Selections}).
-@var{action} is a symbol describing the action recommended to the
-target. It can either be @code{XdndActionCopy}, which
-means to copy the contents of the selection @code{XdndSelection} to
-the drop target; or @code{XdndActionMove}, which means copy as with
-@code{XdndActionCopy}, and in addition the caller should delete
-whatever was stored in that selection after copying it.
+@var{action} is a symbol designating the action recommended to the
+target. It can either be @code{XdndActionCopy} or
+@code{XdndActionMove}; both imply copying the contents of the
+selection @code{XdndSelection} to the drop target, but the latter
+moreover conveys a promise to delete the contents of the selection
+after the copying.
@var{action} may also be an alist which associates between symbols
-describing the available actions, and strings that the drop target is
-expected to present to the user to choose between the available
-actions.
+representing available actions, and strings that the drop target
+presents to the user for him to select between those actions.
If @var{return-frame} is non-@code{nil} and the mouse moves over an
Emacs frame after first moving out of @var{frame}, then the frame to
which the mouse moves will be returned immediately. If
-@var{return-frame} is the symbol @code{now}, then any frame underneath
+@var{return-frame} is the symbol @code{now}, then any frame beneath
the mouse pointer will be returned without waiting for the mouse to
first move out of @var{frame}. @var{return-frame} is useful when you
want to treat dragging content from one frame to another specially,
-while also being able to drag content to other programs, but it is not
-guaranteed to work on all systems and with all window managers.
+while also dragging content to other programs, but it is not
+guaranteed to function on all systems and with all window managers.
If @var{follow-tooltip} is non-@code{nil}, the position of any tooltip
-(such as one shown by @code{tooltip-show}) will follow the location of
-the mouse pointer whenever it moves during the drag-and-drop
+(such as one displayed by @code{tooltip-show}) will follow the
+location of the mouse pointer as it moves during the drag-and-drop
operation. The tooltip will be hidden once all mouse buttons are
released.
If the drop was rejected or no drop target was found, this function
-returns @code{nil}. Otherwise, it returns a symbol describing the
-action the target chose to perform, which can differ from @var{action}
-if that isn't supported by the drop target. @code{XdndActionPrivate}
-is also a valid return value in addition to @code{XdndActionCopy} and
-@code{XdndActionMove}; it means that the drop target chose to perform
-an unspecified action, and no further processing is required by the
-caller.
-
-The caller must cooperate with the target to fully perform the action
-chosen by the target. For example, callers should delete the buffer
-text that was dragged if this function returns @code{XdndActionMove}.
+returns @code{nil}. Otherwise, it returns a symbol representing the
+action the target opted to take, which can differ from @var{action} if
+that isn't supported by the drop target. @code{XdndActionPrivate} is
+also a valid return value in addition to @code{XdndActionCopy} and
+@code{XdndActionMove}; it suggests that the drop target opted for an
+indeterminate action, and no further action is required of the caller.
+
+The caller must cooperate with the target to complete the action
+selected by the target. For example, callers should delete any buffer
+text that was dragged if this function returns @code{XdndActionMove},
+and likewise for other drag data where comparable criteria apply.
@end defun
@cindex drag and drop protocols, X
- On X Windows, several different drag-and-drop protocols are
-supported by @code{x-begin-drag}. When dragging content that is known
-to not be supported by a specific drag-and-drop protocol, it might be
-desirable to turn that protocol off, by changing the values of the
-following variables:
+ The function @code{x-begin-drag} leverages several drag-and-drop
+protocols ``behind the scenes''. When dragging content that is known
+to not be supported by a specific drag-and-drop protocol, that
+protocol can be disabled by changing the values of the following
+variables:
@defvar x-dnd-disable-motif-protocol
When this is non-@code{nil}, the Motif drag and drop protocols are
@@ -4982,8 +5119,8 @@ events and the primary selection to insert the text if the drop target
doesn't support any drag-and-drop protocol at all.
A side effect is that Emacs will become the owner of the primary
-selection upon such a drop. If that is not desired, then the drop
-emulation can be disabled by setting this variable to @code{nil}.
+selection upon such a drop. Such emulation can be disabled by setting
+this variable to @code{nil}.
@end defvar
@node Color Names
diff --git a/doc/lispref/functions.texi b/doc/lispref/functions.texi
index af116f62973..2b2c9287d91 100644
--- a/doc/lispref/functions.texi
+++ b/doc/lispref/functions.texi
@@ -1,6 +1,6 @@
@c -*- mode: texinfo; coding: utf-8 -*-
@c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990--1995, 1998--1999, 2001--2023 Free Software
+@c Copyright (C) 1990--1995, 1998--1999, 2001--2024 Free Software
@c Foundation, Inc.
@c See the file elisp.texi for copying conditions.
@node Functions
@@ -533,6 +533,40 @@ Instead, use the @code{advertised-calling-convention} declaration
compiler emit a warning message when it compiles Lisp programs which
use the deprecated calling convention.
+@ifnottex
+The @code{(fn)} feature is typically used in the following situations:
+
+@itemize @minus
+@item To spell out arguments and their purposes in a macro or a function. Example:
+
+@example
+(defmacro lambda (&rest cdr)
+ "@dots{}
+\(fn ARGS [DOCSTRING] [INTERACTIVE] BODY)"@dots{})
+@end example
+
+@item To provide a more detailed description and names of arguments. Example:
+
+@example
+(defmacro macroexp--accumulate (var+list &rest body)
+ "@dots{}
+\(fn (VAR LIST) BODY@dots{})"
+ (declare (indent 1))
+ (let ((var (car var+list))
+ (list (cadr var+list))
+@dots{})))
+@end example
+
+@item To better explain the purpose of a @code{defalias}. Example:
+
+@example
+(defalias 'abbrev-get 'get
+ "@dots{}
+\(fn ABBREV PROP)")
+@end example
+@end itemize
+@end ifnottex
+
@cindex computed documentation string
@kindex :documentation
Documentation strings are usually static, but occasionally it can be
@@ -1994,9 +2028,16 @@ advice. Advice can also cause confusion in debugging, if the person doing the
debugging does not notice or remember that the function has been modified
by advice.
- For these reasons, advice should be reserved for the cases where you
-cannot modify a function's behavior in any other way. If it is
-possible to do the same thing via a hook, that is preferable
+ Note that the problems are not due to advice per se, but to the act
+of modifying a named function. It is even more problematic to modify
+a named function via lower-level primitives like @code{fset},
+@code{defalias}, or @code{cl-letf}. From that point of view, advice
+is the better way to modify a named function because it keeps track of
+the modifications, so they can be listed and undone.
+
+ Modifying a named function should be reserved for
+the cases where you cannot modify Emacs' behavior in any other way.
+If it is possible to do the same thing via a hook, that is preferable
(@pxref{Hooks}). If you simply want to change what a particular key
does, it may be better to write a new command, and remap the old
command's key bindings to the new one (@pxref{Remapping Commands}).
@@ -2177,7 +2218,7 @@ More specifically, the composition of the two functions behaves like:
@findex defadvice
@findex ad-activate
-A lot of code uses the old @code{defadvice} mechanism, which is largely made
+A lot of code uses the old @code{defadvice} mechanism, which has been made
obsolete by the new @code{advice-add}, whose implementation and semantics is
significantly simpler.
@@ -2357,8 +2398,8 @@ accepted three arguments, like this
(sit-for seconds milliseconds nodisp)
@end example
-However, calling @code{sit-for} this way is considered obsolete
-(@pxref{Waiting}). The old calling convention is deprecated like
+During a transition period, the function accepted those three
+arguments, but declared this old calling convention as deprecated like
this:
@example
diff --git a/doc/lispref/hash.texi b/doc/lispref/hash.texi
index 4edc761cfab..ff9d1799a60 100644
--- a/doc/lispref/hash.texi
+++ b/doc/lispref/hash.texi
@@ -1,6 +1,6 @@
@c -*-texinfo-*-
@c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1999, 2001--2023 Free Software Foundation, Inc.
+@c Copyright (C) 1999, 2001--2024 Free Software Foundation, Inc.
@c See the file elisp.texi for copying conditions.
@node Hash Tables
@chapter Hash Tables
diff --git a/doc/lispref/help.texi b/doc/lispref/help.texi
index d5e4e1c31d3..a76bac011b7 100644
--- a/doc/lispref/help.texi
+++ b/doc/lispref/help.texi
@@ -1,6 +1,6 @@
@c -*- mode: texinfo; coding: utf-8 -*-
@c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990--1995, 1998--1999, 2001--2023 Free Software
+@c Copyright (C) 1990--1995, 1998--1999, 2001--2024 Free Software
@c Foundation, Inc.
@c See the file elisp.texi for copying conditions.
@node Documentation
diff --git a/doc/lispref/hooks.texi b/doc/lispref/hooks.texi
index 513146a3c08..9231d7573f9 100644
--- a/doc/lispref/hooks.texi
+++ b/doc/lispref/hooks.texi
@@ -1,6 +1,6 @@
@c -*-texinfo-*-
@c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990--1993, 1998, 2001--2023 Free Software Foundation,
+@c Copyright (C) 1990--1993, 1998, 2001--2024 Free Software Foundation,
@c Inc.
@c See the file elisp.texi for copying conditions.
@node Standard Hooks
diff --git a/doc/lispref/internals.texi b/doc/lispref/internals.texi
index 0951e60433a..ee3463a1fd6 100644
--- a/doc/lispref/internals.texi
+++ b/doc/lispref/internals.texi
@@ -1,6 +1,6 @@
@c -*-texinfo-*-
@c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990--1993, 1998--1999, 2001--2023 Free Software
+@c Copyright (C) 1990--1993, 1998--1999, 2001--2024 Free Software
@c Foundation, Inc.
@c See the file elisp.texi for copying conditions.
@node GNU Emacs Internals
@@ -1567,7 +1567,7 @@ return values from module functions. For this purpose, the module
Emacs Lisp objects communicated via the @acronym{API}; it is the
functional equivalent of the @code{Lisp_Object} type used in Emacs C
primitives (@pxref{Writing Emacs Primitives}). This section describes
-the parts of the module @acronym{API} that allow to create
+the parts of the module @acronym{API} that allow creating
@code{emacs_value} objects corresponding to basic Lisp data types, and
how to access from C data in @code{emacs_value} objects that
correspond to Lisp objects.
@@ -2519,7 +2519,6 @@ when the buffer is not current.
@item mode_line_format
@itemx header_line_format
-@itemx case_fold_search
@itemx tab_width
@itemx fill_column
@itemx left_margin
diff --git a/doc/lispref/intro.texi b/doc/lispref/intro.texi
index cfe5679b643..2062ae64866 100644
--- a/doc/lispref/intro.texi
+++ b/doc/lispref/intro.texi
@@ -1,6 +1,6 @@
@c -*-coding: utf-8-*-
@c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990--1994, 2001--2023 Free Software Foundation, Inc.
+@c Copyright (C) 1990--1994, 2001--2024 Free Software Foundation, Inc.
@c See the file elisp.texi for copying conditions.
@node Introduction
diff --git a/doc/lispref/keymaps.texi b/doc/lispref/keymaps.texi
index 99bc10677cd..1521b3815f4 100644
--- a/doc/lispref/keymaps.texi
+++ b/doc/lispref/keymaps.texi
@@ -1,6 +1,6 @@
@c -*- mode: texinfo; coding: utf-8 -*-
@c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990--1994, 1998--2023 Free Software Foundation, Inc.
+@c Copyright (C) 1990--1994, 1998--2024 Free Software Foundation, Inc.
@c See the file elisp.texi for copying conditions.
@node Keymaps
@chapter Keymaps
@@ -90,7 +90,7 @@ Manual}.
(kbd "C-x C-f") @result{} "\C-x\C-f"
(kbd "C-x 4 C-f") @result{} "\C-x4\C-f"
(kbd "X") @result{} "X"
-(kbd "RET") @result{} "\^M"
+(kbd "RET") @result{} "^M"
(kbd "C-c SPC") @result{} "\C-c@ "
(kbd "<f1> SPC") @result{} [f1 32]
(kbd "C-M-<down>") @result{} [C-M-down]
@@ -491,7 +491,7 @@ useful if there is a command which doesn't exist in the map being
defined, but which should have the @code{repeat-map} property.
If the @code{:exit} list is empty then no commands in the map exit
-@code{repeat-mode}. Specifying one ore more commands in this list is
+@code{repeat-mode}. Specifying one or more commands in this list is
useful if the keymap being defined contains a command that should not
have the @code{repeat-map} property.
@end table
diff --git a/doc/lispref/lay-flat.texi b/doc/lispref/lay-flat.texi
index c4262907772..0ff8529eddb 100644
--- a/doc/lispref/lay-flat.texi
+++ b/doc/lispref/lay-flat.texi
@@ -1,6 +1,6 @@
\input texinfo @c -*-texinfo-*-
@c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 2001--2023 Free Software Foundation, Inc.
+@c Copyright (C) 2001--2024 Free Software Foundation, Inc.
@c See the file elisp.texi for copying conditions.
@c
@comment %**start of header
diff --git a/doc/lispref/lists.texi b/doc/lispref/lists.texi
index 6a00f2887e7..1409e51c0d4 100644
--- a/doc/lispref/lists.texi
+++ b/doc/lispref/lists.texi
@@ -1,6 +1,6 @@
@c -*-texinfo-*-
@c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990--1995, 1998--1999, 2001--2023 Free Software
+@c Copyright (C) 1990--1995, 1998--1999, 2001--2024 Free Software
@c Foundation, Inc.
@c See the file elisp.texi for copying conditions.
@node Lists
diff --git a/doc/lispref/loading.texi b/doc/lispref/loading.texi
index 125011c780f..75b9d11028a 100644
--- a/doc/lispref/loading.texi
+++ b/doc/lispref/loading.texi
@@ -1,6 +1,6 @@
@c -*-texinfo-*-
@c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990--1995, 1998--1999, 2001--2023 Free Software
+@c Copyright (C) 1990--1995, 1998--1999, 2001--2024 Free Software
@c Foundation, Inc.
@c See the file elisp.texi for copying conditions.
@node Loading
@@ -1011,6 +1011,19 @@ If loading the file succeeds but does not provide @var{feature},
@code{require} signals an error about the missing feature.
@end defun
+@defun require-with-check feature &optional filename noerror
+This function works like @code{require}, except if @var{feature} is
+already loaded (i.e.@: is already a member of the list in
+@code{features}, see below). If @var{feature} is already loaded, this
+function checks if @var{feature} was provided by a file different from
+@var{filename}, and if so, it by default signals an error. If the
+value of the optional argument @var{noerror} is @code{reload}, the
+function doesn't signal an error, but instead forcibly reloads
+@var{filename}; if @var{noerror} is some other non-@code{nil} value,
+the function emits a warning about @var{feature} being already
+provided by another file.
+@end defun
+
@defun featurep feature &optional subfeature
This function returns @code{t} if @var{feature} has been provided in
the current Emacs session (i.e., if @var{feature} is a member of
diff --git a/doc/lispref/macros.texi b/doc/lispref/macros.texi
index e3961e4bace..659dba17524 100644
--- a/doc/lispref/macros.texi
+++ b/doc/lispref/macros.texi
@@ -1,6 +1,6 @@
@c -*-texinfo-*-
@c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990--1995, 1998, 2001--2023 Free Software Foundation,
+@c Copyright (C) 1990--1995, 1998, 2001--2024 Free Software Foundation,
@c Inc.
@c See the file elisp.texi for copying conditions.
@node Macros
diff --git a/doc/lispref/maps.texi b/doc/lispref/maps.texi
index 7da704c79b6..6ae98da49c7 100644
--- a/doc/lispref/maps.texi
+++ b/doc/lispref/maps.texi
@@ -1,6 +1,6 @@
@c -*-texinfo-*-
@c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990--1993, 1999, 2001--2023 Free Software Foundation,
+@c Copyright (C) 1990--1993, 1999, 2001--2024 Free Software Foundation,
@c Inc.
@c See the file elisp.texi for copying conditions.
@node Standard Keymaps
diff --git a/doc/lispref/markers.texi b/doc/lispref/markers.texi
index 0b98eee137a..3037790692c 100644
--- a/doc/lispref/markers.texi
+++ b/doc/lispref/markers.texi
@@ -1,6 +1,6 @@
@c -*-texinfo-*-
@c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990--1995, 1998--1999, 2001--2023 Free Software
+@c Copyright (C) 1990--1995, 1998--1999, 2001--2024 Free Software
@c Foundation, Inc.
@c See the file elisp.texi for copying conditions.
@node Markers
diff --git a/doc/lispref/minibuf.texi b/doc/lispref/minibuf.texi
index 8ff5c14055e..5c5edf62a8d 100644
--- a/doc/lispref/minibuf.texi
+++ b/doc/lispref/minibuf.texi
@@ -1,6 +1,6 @@
@c -*-texinfo-*-
@c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990--1995, 1998--1999, 2001--2023 Free Software
+@c Copyright (C) 1990--1995, 1998--1999, 2001--2024 Free Software
@c Foundation, Inc.
@c See the file elisp.texi for copying conditions.
@node Minibuffers
@@ -374,6 +374,7 @@ key, so the text properties are only preserved on the last three
characters.
@end defvar
+@vindex minibuffer-mode-map
@defvar minibuffer-local-map
This
@anchor{Definition of minibuffer-local-map}
@@ -414,6 +415,9 @@ default, it makes the following bindings:
@code{file-cache-minibuffer-complete}
@end ignore
@end table
+
+@noindent
+The variable @code{minibuffer-mode-map} is an alias for this variable.
@end defvar
@defun read-no-blanks-input prompt &optional initial inherit-input-method
@@ -1560,7 +1564,7 @@ Interactively, or when @var{display} is non-@code{nil}, the return
value is also displayed in the echo area.
The optional arguments @var{foreground} and @var{face} control the
-appearence of the completion candidates in the @file{*Completions*}
+appearance of the completion candidates in the @file{*Completions*}
buffer. The candidates are displayed in the specified @var{face} but
with different colors: if @var{foreground} is non-@code{nil}, the
foreground color is changed to be the color of the candidate,
@@ -1981,6 +1985,7 @@ the piece of the prefix and suffix covered by the completion
boundaries. @xref{Basic Completion}, for the precise expected semantics
of completion boundaries.
+@cindex completion metadata
@item metadata
This specifies a request for information about the state of the
current completion. The return value should have the form
@@ -1997,6 +2002,8 @@ The following is a list of metadata entries that a completion function
may return in response to a @code{metadata} flag argument:
@table @code
+@cindex @code{category}, in completion
+@cindex completion category
@item category
The value should be a symbol describing what kind of text the
completion function is trying to complete. If the symbol matches one
@@ -2669,7 +2676,7 @@ variable instead (@pxref{Echo Area Customization}).
The option @code{resize-mini-windows} does not affect the behavior of
minibuffer-only frames (@pxref{Frame Layout}). The following option
-allows to automatically resize such frames as well.
+enables automatically resizing such frames as well.
@defopt resize-mini-frames
If this is @code{nil}, minibuffer-only frames are never resized
@@ -2877,3 +2884,22 @@ This is the major mode used in inactive minibuffers. It uses
keymap @code{minibuffer-inactive-mode-map}. This can be useful
if the minibuffer is in a separate frame. @xref{Minibuffers and Frames}.
@end deffn
+
+@deffn Command minibuffer-regexp-mode
+This minor mode makes editing regular expressions in the minibuffer
+more convenient. It highlight parens via @code{show-paren-mode} and
+@code{blink-matching-paren} in a user-friendly way, avoids reporting
+false paren mismatches, and makes sexp navigation more intuitive.
+@end deffn
+
+By default, only certain minibuffer prompts automatically activate the
+convenience features of @code{minibuffer-regexp-mode} when the
+minibuffer becomes active. This list of prompts can be customized via
+@code{minibuffer-regexp-prompts}.
+
+@defopt minibuffer-regexp-prompts
+This variable holds the list of regular expressions for activating the
+features of @code{minibuffer-regexp-mode} in the minibuffer. The
+mode's features will be activated only if the minibuffer prompt
+matches one of the regular expressions in the list.
+@end defopt
diff --git a/doc/lispref/modes.texi b/doc/lispref/modes.texi
index 00148420893..8c5fd63918a 100644
--- a/doc/lispref/modes.texi
+++ b/doc/lispref/modes.texi
@@ -1,6 +1,6 @@
@c -*-texinfo-*-
@c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990--1995, 1998--1999, 2001--2023 Free Software
+@c Copyright (C) 1990--1995, 1998--1999, 2001--2024 Free Software
@c Foundation, Inc.
@c See the file elisp.texi for copying conditions.
@node Modes
@@ -932,11 +932,41 @@ Do not write an @code{interactive} spec in the definition;
@code{define-derived-mode} does that automatically.
@end defmac
-@defun derived-mode-p &rest modes
+@defun derived-mode-p modes
This function returns non-@code{nil} if the current major mode is
-derived from any of the major modes given by the symbols @var{modes}.
+derived from any of the major modes given by the list of symbols
+in @var{modes}.
+Instead of a list, @var{modes} can also be a single mode symbol.
+
+Furthermore, we still support a deprecated calling convention where the
+@var{modes} were passed as separate arguments.
+@end defun
+
+The graph of major modes is accessed with the following lower-level
+functions:
+
+@defun derived-mode-set-parent mode parent
+This function declares that @var{mode} inherits from @code{parent}.
+This is the function that @code{define-derived-mode} calls after
+defining @var{mode} to register the fact that @var{mode} was defined
+by reusing @code{parent}.
+@end defun
+
+@defun derived-mode-add-parents mode extra-parents
+This function makes it possible to register additional parents beside
+the one that was used when defining @var{mode}. This can be used when
+the similarity between @var{mode} and the modes in @var{extra-parents}
+is such that it makes sense to treat it as a child of those
+modes for purposes like applying directory-local variables.
@end defun
+@defun derived-mode-all-parents mode
+This function returns the list of all the modes in the ancestry of
+@var{mode}, ordered from the most specific to the least specific, and
+starting with @var{mode} itself.
+@end defun
+
+
@node Basic Major Modes
@subsection Basic Major Modes
@@ -956,9 +986,9 @@ allows users to customize a single mode hook
@deffn Command text-mode
Text mode is a major mode for editing human languages. It defines the
@samp{"} and @samp{\} characters as having punctuation syntax
-(@pxref{Syntax Class Table}), and binds @kbd{M-@key{TAB}} to
-@code{ispell-complete-word} (@pxref{Spelling,,, emacs, The GNU Emacs
-Manual}).
+(@pxref{Syntax Class Table}), and arranges for
+@code{completion-at-point} to complete words based on the spelling
+dictionary (@pxref{Completion in Buffers}).
An example of a major mode derived from Text mode is HTML mode.
@xref{HTML Mode,,SGML and HTML Modes, emacs, The GNU Emacs Manual}.
@@ -1352,15 +1382,6 @@ the conventions listed above:
st)
"Syntax table used while in `text-mode'.")
@end group
-
-;; @r{Create the keymap for this mode.}
-@group
-(defvar-keymap text-mode-map
- :doc "Keymap for `text-mode'.
-Many other modes, such as `mail-mode' and `outline-mode', inherit all
-the commands defined in this map."
- "C-M-i" #'ispell-complete-word)
-@end group
@end smallexample
Here is how the actual mode command is defined now:
@@ -2667,7 +2688,7 @@ display in pixels, by multiplying the value of this variable by the
value returned by @code{frame-char-width} (@pxref{Frame Font}), and
then use the result to align header-line text using the
@code{:align-to} display property spec (@pxref{Specified Space}) in
-pixels on the relevant parts of @code{header-line-frormat}.
+pixels on the relevant parts of @code{header-line-format}.
@end defvar
@defun window-header-line-height &optional window
@@ -3614,7 +3635,9 @@ errors are suppressed, is instead run by a timer. Thus, this mode
allows using debugging aids such as @code{debug-on-error}
(@pxref{Error Debugging}) and Edebug (@pxref{Edebug}) for finding and
fixing problems in font-lock code and any other code run by JIT
-font-lock.
+font-lock. Another command that could be useful when developing and
+debugging font-lock is @code{font-lock-debug-fontify}, see @ref{Font
+Lock Basics}.
@end deffn
@node Levels of Font Lock
@@ -4149,7 +4172,7 @@ it add meta information to it. The @code{:language} keyword declares
name of @var{query}. Users can control which features are enabled
with @code{treesit-font-lock-level} and
@code{treesit-font-lock-feature-list} (described below). These two
-keywords are mandatory.
+keywords are mandatory (with exceptions).
Other keywords are optional:
@@ -4161,6 +4184,9 @@ Other keywords are optional:
@item @tab @code{append} @tab Append the new face to existing ones
@item @tab @code{prepend} @tab Prepend the new face to existing ones
@item @tab @code{keep} @tab Fill-in regions without an existing face
+@item @code{:default-language} @tab @var{language}
+@tab Every @var{query} after this keyword will use @var{language}
+by default.
@end multitable
Lisp programs mark patterns in @var{query} with capture names (names
@@ -5094,7 +5120,7 @@ this matcher doesn't check that argument. For example, to match the
first child where parent is @code{argument_list}, use
@example
-(match nil "argument_list" nil nil 0 0)
+(match nil "argument_list" nil 0 0)
@end example
In addition, @var{node-type} can be a special value @code{null},
diff --git a/doc/lispref/nonascii.texi b/doc/lispref/nonascii.texi
index 7e5590ed8ec..b33082e2b24 100644
--- a/doc/lispref/nonascii.texi
+++ b/doc/lispref/nonascii.texi
@@ -1,6 +1,6 @@
@c -*- mode: texinfo; coding: utf-8 -*-
@c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1998--1999, 2001--2023 Free Software Foundation, Inc.
+@c Copyright (C) 1998--1999, 2001--2024 Free Software Foundation, Inc.
@c See the file elisp.texi for copying conditions.
@node Non-ASCII Characters
@chapter Non-@acronym{ASCII} Characters
@@ -133,7 +133,7 @@ This function is similar to @code{position-bytes}, but instead of byte
position in the current buffer it returns the offset from the
beginning of the current buffer's file of the byte that corresponds to
the given character @var{position} in the buffer. The conversion
-requires to know how the text is encoded in the buffer's file; this is
+requires knowing how the text is encoded in the buffer's file; this is
what the @var{coding-system} argument is for, defaulting to the value
of @code{buffer-file-coding-system}. The optional argument
@var{quality} specifies how accurate the result should be; it should
@@ -1181,7 +1181,7 @@ the text to be written cannot be safely encoded using the coding system
specified by this variable, these operations select an alternative
encoding by calling the function @code{select-safe-coding-system}
(@pxref{User-Chosen Coding Systems}). If selecting a different encoding
-requires to ask the user to specify a coding system,
+requires asking the user to specify a coding system,
@code{buffer-file-coding-system} is updated to the newly selected coding
system.
diff --git a/doc/lispref/numbers.texi b/doc/lispref/numbers.texi
index 071ec0f518d..99b456043b9 100644
--- a/doc/lispref/numbers.texi
+++ b/doc/lispref/numbers.texi
@@ -1,6 +1,6 @@
@c -*-texinfo-*-
@c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990--1995, 1998--1999, 2001--2023 Free Software
+@c Copyright (C) 1990--1995, 1998--1999, 2001--2024 Free Software
@c Foundation, Inc.
@c See the file elisp.texi for copying conditions.
@node Numbers
diff --git a/doc/lispref/objects.texi b/doc/lispref/objects.texi
index ad079e0d63a..111beb5e5b0 100644
--- a/doc/lispref/objects.texi
+++ b/doc/lispref/objects.texi
@@ -1,6 +1,6 @@
@c -*- mode: texinfo; coding: utf-8 -*-
@c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990--1995, 1998--1999, 2001--2023 Free Software
+@c Copyright (C) 1990--1995, 1998--1999, 2001--2024 Free Software
@c Foundation, Inc.
@c See the file elisp.texi for copying conditions.
@node Lisp Data Types
@@ -82,7 +82,9 @@ it does not make sense to enter objects of these types as constants in
a Lisp program. These objects are printed in @dfn{hash notation},
which consists of the characters @samp{#<}, a descriptive string
(typically the type name followed by the name of the object), and a
-closing @samp{>}. For example:
+closing @samp{>}. (This is called ``hash notation'' because it begins
+with the @samp{#} character, known as ``hash'' or ``number sign'').
+For example:
@example
(current-buffer)
@@ -94,6 +96,12 @@ Hash notation cannot be read at all, so the Lisp reader signals the
error @code{invalid-read-syntax} whenever it encounters @samp{#<}.
@kindex invalid-read-syntax
+ We describe the read syntax and the printed representation of each
+Lisp data type where we describe that data type, in the following
+sections of this chapter. For example, see @ref{String Type}, and its
+subsections for the read syntax and printed representation of strings;
+see @ref{Vector Type} for the same information about vectors; etc.
+
In other languages, an expression is text; it has no other form. In
Lisp, an expression is primarily a Lisp object and only secondarily the
text that is the object's read syntax. Often there is no need to
@@ -319,6 +327,8 @@ number whose value is 1500. They are all equivalent.
A @dfn{character} in Emacs Lisp is nothing more than an integer. In
other words, characters are represented by their character codes. For
example, the character @kbd{A} is represented as the @w{integer 65}.
+That is also their usual printed representation; see @ref{Basic Char
+Syntax}.
Individual characters are used occasionally in programs, but it is
more common to work with @emph{strings}, which are sequences composed
@@ -1104,6 +1114,22 @@ character. Likewise, you can include a backslash by preceding it with
another backslash, like this: @code{"this \\ is a single embedded
backslash"}.
+ Since a string is an array of characters, you can specify the string
+characters using the read syntax of characters, but without the
+leading question mark. This is useful for including in string
+constants characters that don't stand for themselves. Thus, control
+characters can be specified as escape sequences that start with a
+backslash; for example, @code{"foo\r"} yields @samp{foo} followed by
+the carriage return character. @xref{Basic Char Syntax}, for escape
+sequences of other control characters. Similarly, you can use the
+special read syntax for control characters (@pxref{Ctl-Char Syntax}),
+as in @code{"foo\^Ibar"}, which produces a tab character embedded
+within a string. You can also use the escape sequences for non-ASCII
+characters described in @ref{General Escape Syntax}, as in
+@w{@code{"\N@{LATIN SMALL LETTER A WITH GRAVE@}"}} and @code{"\u00e0"}
+(however, see a caveat with non-ASCII characters in @ref{Non-ASCII in
+Strings}).
+
@cindex newline in strings
The newline character is not special in the read syntax for strings;
if you write a new line between the double-quotes, it becomes a
@@ -1180,8 +1206,9 @@ but it does terminate any preceding hex escape.
as in character literals (but do not use the question mark that begins a
character constant). For example, you can write a string containing the
nonprinting characters tab and @kbd{C-a}, with commas and spaces between
-them, like this: @code{"\t, \C-a"}. @xref{Character Type}, for a
-description of the read syntax for characters.
+them, like this: @code{"\t, \C-a"}. @xref{Character Type}, and its
+subsections for a description of the various kinds of read syntax for
+characters.
However, not all of the characters you can write with backslash
escape-sequences are valid in strings. The only control characters that
@@ -2206,6 +2233,10 @@ and the same non-fixnum numeric type, then they might or might not be
the same object, and @code{eq} returns @code{t} or @code{nil}
depending on whether the Lisp interpreter created one object or two.
+If @var{object1} or @var{object2} is a symbol with position, @code{eq}
+regards it as its bare symbol when @code{symbols-with-pos-enabled} is
+non-@code{nil} (@pxref{Symbols with Position}).
+
@example
@group
(eq 'foo 'foo)
@@ -2363,6 +2394,13 @@ same sequence of character codes and all these codes are in the range
The @code{equal} function recursively compares the contents of objects
if they are integers, strings, markers, vectors, bool-vectors,
byte-code function objects, char-tables, records, or font objects.
+
+If @var{object1} or @var{object2} is a symbol with position,
+@code{equal} regards it as its bare symbol when
+@code{symbols-with-pos-enabled} is non-@code{nil}. Otherwise
+@code{equal} compares two symbols with position by recursively
+comparing their components. @xref{Symbols with Position}.
+
Other objects are considered @code{equal} only if they are @code{eq}.
For example, two distinct buffers are never considered @code{equal},
even if their textual contents are the same.
diff --git a/doc/lispref/os.texi b/doc/lispref/os.texi
index 3c704970cda..feba7192d3c 100644
--- a/doc/lispref/os.texi
+++ b/doc/lispref/os.texi
@@ -1,6 +1,6 @@
@c -*-texinfo-*-
@c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990--1995, 1998--1999, 2001--2023 Free Software
+@c Copyright (C) 1990--1995, 1998--1999, 2001--2024 Free Software
@c Foundation, Inc.
@c See the file elisp.texi for copying conditions.
@node System Interface
@@ -2127,6 +2127,14 @@ This function returns the number of days between the beginning of year
The operating system limits the range of time and zone values.
@end defun
+@defun days-to-time days
+This is not quite the inverse of the @code{time-to-days} function, as
+it uses the Emacs epoch (instead of the year 1) for historical
+reasons. To get the inverse, subtract @code{(time-to-days 0)} from
+@var{days}, in which case @code{days-to-time} may return @code{nil} if
+@var{days} is negative.
+@end defun
+
@defun time-to-day-in-year time-value
This returns the day number within the year corresponding to @var{time-value},
assuming the default time zone.
@@ -2751,6 +2759,35 @@ way to specify the programs to run is with @samp{-l @var{file}}, which
loads the library named @var{file}, or @samp{-f @var{function}}, which
calls @var{function} with no arguments, or @samp{--eval=@var{form}}.
+@defvar noninteractive
+This variable is non-@code{nil} when Emacs is running in batch mode.
+@end defvar
+
+ If the specified Lisp program signals an unhandled error in batch
+mode, Emacs exits with a non-zero exit status after invoking the Lisp
+debugger which shows the Lisp backtrace (@pxref{Invoking the
+Debugger}) on the standard error stream:
+
+@example
+$ emacs -Q --batch --eval '(error "foo")'; echo $?
+
+@group
+Error: error ("foo")
+mapbacktrace(#f(compiled-function (evald func args flags) #<bytecode -0x4f85c5
+7c45e2f81>))
+debug-early-backtrace()
+debug-early(error (error "foo"))
+signal(error ("foo"))
+error("foo")
+eval((error "foo") t)
+command-line-1(("--eval" "(error \"foo\")"))
+command-line()
+normal-top-level()
+@end group
+foo
+255
+@end example
+
Any Lisp program output that would normally go to the echo area,
either using @code{message}, or using @code{prin1}, etc., with
@code{t} as the stream (@pxref{Output Streams}), goes instead to
@@ -2768,6 +2805,7 @@ if it is non-@code{nil}; this can be overridden by binding
@code{coding-system-for-write} to a coding system of you choice
(@pxref{Explicit Encoding}).
+@vindex gc-cons-percentage@r{, in batch mode}
In batch mode, Emacs will enlarge the value of the
@code{gc-cons-percentage} variable from the default of @samp{0.1} up to
@samp{1.0}. Batch jobs that are supposed to run for a long time
@@ -2775,19 +2813,6 @@ should adjust the limit back down again, because this means that less
garbage collection will be performed by default (and more memory
consumed).
-@defvar noninteractive
-This variable is non-@code{nil} when Emacs is running in batch mode.
-@end defvar
-
-If Emacs exits due to signaling an error in batch mode, the exit
-status of the Emacs command is non-zero:
-
-@example
-$ emacs -Q --batch --eval '(error "foo")'; echo $?
-foo
-255
-@end example
-
@node Session Management
@section Session Management
@cindex session manager
@@ -3220,15 +3245,25 @@ These have the same meaning as they do when used in calls to
@code{notifications-notify}.
@item :urgency @var{urgency}
+The set of values for @var{urgency} is the same as with
+@code{notifications-notify}, but the urgency applies to all
+notifications displayed with the defined @var{group}, except under
+Android 7.1 and earlier.
+
@item :group @var{group}
-These two parameters are ignored under Android 7.1 and earlier
-versions of the system. The set of values for @var{urgency} is the
-same as with @code{notifications-notify}, but the urgency applies to
-all notifications displayed with the defined @var{group}.
+@var{group} is a string that designates a category to which the
+notification sent will belong. This category is reproduced within the
+system's notification settings menus, but is ignored under Android 7.1
+and earlier.
If @var{group} is nil or not present within @var{params}, it is
replaced by the string @samp{"Desktop Notifications"}.
+Callers should provide one stable combination of @var{urgency} and
+@var{group} for each kind of notification they send, given that the
+system may elect to disregard @var{urgency} if it does not match that
+of any notification previously delivered to @var{group}.
+
@item :icon @var{icon}
This parameter controls the symbolic icon the notification will be
displayed with. Its value is a string designating an icon within the
@@ -3345,7 +3380,8 @@ reliably report file attribute changes when watching a directory.
The @code{stopped} event means that watching the file has been
discontinued. This could be because @code{file-notify-rm-watch} was
called (see below), or because the file being watched was deleted, or
-due to another error reported from the underlying library which makes
+because the filesystem of the file being watched was unmounted, or due
+to another error reported from the underlying library which makes
further watching impossible.
@var{file} and @var{file1} are the name of the file(s) whose event is
diff --git a/doc/lispref/package.texi b/doc/lispref/package.texi
index 2952e7dfcfc..6f52a33d194 100644
--- a/doc/lispref/package.texi
+++ b/doc/lispref/package.texi
@@ -1,6 +1,6 @@
@c -*-texinfo-*-
@c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 2010--2023 Free Software Foundation, Inc.
+@c Copyright (C) 2010--2024 Free Software Foundation, Inc.
@c See the file elisp.texi for copying conditions.
@node Packaging
@chapter Preparing Lisp code for distribution
diff --git a/doc/lispref/parsing.texi b/doc/lispref/parsing.texi
index 36b3c19df01..5d79c4b27f4 100644
--- a/doc/lispref/parsing.texi
+++ b/doc/lispref/parsing.texi
@@ -1,6 +1,6 @@
@c -*- mode: texinfo; coding: utf-8 -*-
@c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 2021--2023 Free Software Foundation, Inc.
+@c Copyright (C) 2021--2024 Free Software Foundation, Inc.
@c See the file elisp.texi for copying conditions.
@node Parsing Program Source
@chapter Parsing Program Source
@@ -400,14 +400,17 @@ when deciding whether to enable tree-sitter features.
@cindex creating tree-sitter parsers
@cindex tree-sitter parser, creating
-@defun treesit-parser-create language &optional buffer no-reuse
+@defun treesit-parser-create language &optional buffer no-reuse tag
Create a parser for the specified @var{buffer} and @var{language}
-(@pxref{Language Grammar}). If @var{buffer} is omitted or
-@code{nil}, it stands for the current buffer.
+(@pxref{Language Grammar}), with @var{tag}. If @var{buffer} is
+omitted or @code{nil}, it stands for the current buffer.
By default, this function reuses a parser if one already exists for
-@var{language} in @var{buffer}, but if @var{no-reuse} is
-non-@code{nil}, this function always creates a new parser.
+@var{language} with @var{tag} in @var{buffer}, but if @var{no-reuse}
+is non-@code{nil}, this function always creates a new parser.
+
+@var{tag} can be any symbol except @code{t}, and defaults to
+@code{nil}. Different parsers can have the same tag.
If that buffer is an indirect buffer, its base buffer is used instead.
That is, indirect buffers use their base buffer's parsers. If the
@@ -450,11 +453,17 @@ internal parser list. Every time a change is made to the buffer,
Emacs updates parsers in this list so they can update their syntax
tree incrementally.
-@defun treesit-parser-list &optional buffer
-This function returns the parser list of @var{buffer}. If
-@var{buffer} is @code{nil} or omitted, it defaults to the current
-buffer. If that buffer is an indirect buffer, its base buffer is used
-instead. That is, indirect buffers use their base buffer's parsers.
+@defun treesit-parser-list &optional buffer language tag
+This function returns the parser list of @var{buffer}, filtered by
+@var{language} and @var{tag}. If @var{buffer} is @code{nil} or
+omitted, it defaults to the current buffer. If that buffer is an
+indirect buffer, its base buffer is used instead. That is, indirect
+buffers use their base buffer's parsers.
+
+If @var{language} is non-@var{nil}, only include parsers for that
+language, and only include parsers with @var{tag}. @var{tag} defaults
+to @code{nil}. If @var{tag} is @code{t}, include parsers in the
+returned list regardless of their tag.
@end defun
@defun treesit-parser-delete parser
@@ -696,7 +705,7 @@ This function finds the previous sibling of @var{node}. If
To make the syntax tree easier to analyze, many language grammars
assign @dfn{field names} to child nodes (@pxref{tree-sitter node field
name, field name}). For example, a @code{function_definition} node
-could have a @code{declarator} node and a @code{body} node.
+could have a @code{declarator} child and a @code{body} child.
@defun treesit-node-child-by-field-name node field-name
This function finds the child of @var{node} whose field name is
@@ -1072,6 +1081,22 @@ This function returns the number of children of @var{node}. If
(@pxref{tree-sitter named node, named node}).
@end defun
+@heading Convenience functions
+
+@defun treesit-node-enclosed-p smaller larger &optional strict
+This function returns non-@code{nil} if @var{smaller} is enclosed in
+@var{larger}. @var{smaller} and @var{larger} can be either a cons
+@code{(@var{beg} . @var{end})} or a node.
+
+Return non-@code{nil} if @var{larger}'s start <= @var{smaller}'s start
+and @var{larger}'s end <= @var{smaller}'s end.
+
+If @var{strict} is @code{t}, compare with < rather than <=.
+
+If @var{strict} is @code{partial}, consider @var{larger} encloses
+@var{smaller} when at least one side is strictly enclosing.
+@end defun
+
@node Pattern Matching
@section Pattern Matching Tree-sitter Nodes
@cindex pattern matching with tree-sitter nodes
@@ -1706,6 +1731,20 @@ If @var{query} is a tree-sitter query, it should be preceded by two
specifies the embedded language, and the @code{:host} keyword
specifies the host language.
+@cindex local parser
+If the query is given the @code{:local} keyword whose value is
+@code{t}, the range set by this query has a dedicated local parser;
+otherwise the range shares a parser with other ranges for the same
+language.
+
+By default, a parser sees its ranges as a continuum, rather than
+treating them as separate independent segments. Therefore, if the
+embedded ranges are semantically independent segments, they should be
+processed by local parsers, described below.
+
+Local parser set to a range can be retrieved by
+@code{treesit-local-parsers-at} and @code{treesit-local-parsers-on}.
+
@code{treesit-update-ranges} uses @var{query} to figure out how to set
the ranges for parsers for the embedded language. It queries
@var{query} in a host language parser, computes the ranges which the
@@ -1741,6 +1780,25 @@ language of the buffer text at @var{pos}. This variable is used by
@code{treesit-language-at}.
@end defvar
+@defun treesit-local-parsers-at &optional pos language
+This function returns all the local parsers at @var{pos} in the
+current buffer. @var{pos} defaults to point.
+
+Local parsers are those which only parse a limited region marked by an
+overlay with a non-@code{nil} @code{treesit-parser} property. If
+@var{language} is non-@code{nil}, only return parsers for that
+language.
+@end defun
+
+@defun treesit-local-parsers-on &optional beg end language
+This function is the same as @code{treesit-local-parsers-at}, but it
+returns the local parsers in the range between @var{beg} and @var{end}
+instead of at point.
+
+@var{beg} and @var{end} default to the entire accessible portion of
+the buffer.
+@end defun
+
@node Tree-sitter Major Modes
@section Developing major modes with tree-sitter
@cindex major mode, developing with tree-sitter
@@ -1835,6 +1893,8 @@ add-log functions used by @code{add-log-current-defun}.
If @code{treesit-simple-imenu-settings} (@pxref{Imenu}) is
non-@code{nil}, it sets up Imenu.
@end itemize
+
+@c TODO: Add treesit-thing-settings stuff once we finalize it.
@end defun
For more information on these built-in tree-sitter features,
diff --git a/doc/lispref/positions.texi b/doc/lispref/positions.texi
index 98cf81be107..5e0143c7131 100644
--- a/doc/lispref/positions.texi
+++ b/doc/lispref/positions.texi
@@ -1,6 +1,6 @@
@c -*- mode: texinfo; coding: utf-8 -*-
@c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990--1995, 1998--2023 Free Software Foundation, Inc.
+@c Copyright (C) 1990--1995, 1998--2024 Free Software Foundation, Inc.
@c See the file elisp.texi for copying conditions.
@node Positions
@chapter Positions
@@ -872,36 +872,25 @@ defuns. If the value is @code{nested}, navigation functions recognize
nested defuns.
@end defvar
-@defvar treesit-sentence-type-regexp
-The value of this variable is a regexp matching the node type of sentence
-nodes. (For ``node'' and ``node type'', @pxref{Parsing Program Source}.)
-@end defvar
-
@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-sentence-type-regexp} to determine that.
+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}).
-@defvar treesit-sexp-type-regexp
-The value of this variable is a regexp matching the node type of sexp
-nodes. (For ``node'' and ``node type'', @pxref{Parsing Program
-Source}.)
-@end defvar
-
@findex treesit-forward-sexp
@findex forward-sexp@r{, and tree-sitter}
@findex backward-sexp@r{, and tree-sitter}
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 sexp varies between languages, a major mode
-should set @code{treesit-sexp-type-regexp} to determine that. Then
+should set @code{treesit-thing-settings} to determine that. Then
the mode can get navigation-by-sexp functionality for free, by using
@code{forward-sexp} and @code{backward-sexp}(@pxref{Moving by
Sentences,,, emacs, The extensible self-documenting text editor}).
diff --git a/doc/lispref/processes.texi b/doc/lispref/processes.texi
index 799a9e19722..ea3fe738f69 100644
--- a/doc/lispref/processes.texi
+++ b/doc/lispref/processes.texi
@@ -1,6 +1,6 @@
@c -*-texinfo-*-
@c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990--1995, 1998--1999, 2001--2023 Free Software
+@c Copyright (C) 1990--1995, 1998--1999, 2001--2024 Free Software
@c Foundation, Inc.
@c See the file elisp.texi for copying conditions.
@node Processes
@@ -134,7 +134,7 @@ but all the 3 primitives allow optionally to direct the standard error
stream to a different destination.
@cindex program arguments
- All three of the subprocess-creating functions allow to specify
+ All three of the subprocess-creating functions allow specifying
command-line arguments for the process to run. For @code{call-process}
and @code{call-process-region}, these come in the form of a
@code{&rest} argument, @var{args}. For @code{make-process}, both the
@@ -191,17 +191,18 @@ the function returns just the value of the variable @code{exec-path}.
@vindex hexl-program-name
@vindex emacsclient-program-name
@vindex movemail-program-name
-@vindex ebrowse-program-manem
- When starting a program that is part of the Emacs distribution,
-you must take into account that the program may have been renamed in
-order to comply with executable naming restrictions present on the
-system.
+@vindex ebrowse-program-name
+@vindex rcs2log-program-name
+ When starting a program that is part of the Emacs distribution, you
+must take into account that the program may have been renamed in order
+to comply with executable naming restrictions present on the system.
Instead of starting @command{ctags}, for example, you should specify
the value of @code{ctags-program-name} instead. Likewise, instead of
starting @command{movemail}, you must start
@code{movemail-program-name}, and the same goes for @command{etags},
-@command{hexl}, @command{emacsclient}, and @command{ebrowse}.
+@command{hexl}, @command{emacsclient}, @code{rcs2log}, and
+@command{ebrowse}.
@node Shell Arguments
@section Shell Arguments
@@ -519,7 +520,7 @@ This user option indicates whether a call of @code{process-file}
returns a string describing the signal interrupting a remote process.
When a process returns an exit code greater than 128, it is
-interpreted as a signal. @code{process-file} requires to return a
+interpreted as a signal. @code{process-file} requires returning a
string describing this signal.
Since there are processes violating this rule, returning exit codes
@@ -680,7 +681,7 @@ This function is the basic low-level primitive for starting
asynchronous subprocesses. It returns a process object representing
the subprocess. Compared to the more high-level @code{start-process},
described below, it takes keyword arguments, is more flexible, and
-allows to specify process filters and sentinels in a single call.
+enables you to specify process filters and sentinels in a single call.
The arguments @var{args} are a list of keyword/argument pairs.
Omitting a keyword is always equivalent to specifying it with value
@@ -1515,6 +1516,9 @@ If @var{process} is a process object which contains the property
@code{remote-pid}, or @var{process} is a number and @var{remote} is a
remote file name, @var{process} is interpreted as process on the
respective remote host, which will be the process to signal.
+
+If @var{process} is a string, it is interpreted as process object with
+the respective process name, or as a number.
@end deffn
Sometimes, it is necessary to send a signal to a non-local
@@ -1659,8 +1663,10 @@ from previous output.
@defun set-process-buffer process buffer
This function sets the buffer associated with @var{process} to
@var{buffer}. If @var{buffer} is @code{nil}, the process becomes
-associated with no buffer; if non-@code{nil}, the process mark will be
-set to point to the end of @var{buffer}.
+associated with no buffer; if non-@code{nil} and different from the
+buffer associated with the process, the process mark will be set to
+point to the end of @var{buffer} (unless the process mark is already
+associated with @var{buffer}).
@end defun
@defun get-buffer-process buffer-or-name
@@ -2181,7 +2187,7 @@ programs was running when the sentinel was started. However, if
This makes it possible to use the Lisp debugger to debug the
sentinel. @xref{Debugger}. If an error is caught, Emacs pauses for
@code{process-error-pause-time} seconds so that the user sees the
-error. @xref{Asynchronous Processes}
+error. @xref{Asynchronous Processes}.
While a sentinel is running, the process sentinel is temporarily
set to @code{nil} so that the sentinel won't run recursively.
@@ -2633,7 +2639,7 @@ and @samp{:capability-command} are supplied, try to upgrade to an encrypted
connection via @acronym{STARTTLS}. If that fails, retain the
unencrypted connection.
@item starttls
-As for @code{nil}, but if @acronym{STARTTLS} fails drop the connection.
+As for @code{nil}, but if @acronym{STARTTLS} fails, drop the connection.
@item shell
A shell connection.
@end table
@@ -2644,9 +2650,9 @@ doing a @samp{plain} connection.
@item :capability-command @var{capability-command}
Command to query the host capabilities. This can either be a string
-(which will then be sent verbatim to the server), or a function
-(called with a single parameter; the "greeting" from the server when
-connecting), and should return a string.
+(which will then be sent verbatim to the server) or a function
+(called with a single parameter: the ``greeting'' from the server when
+connecting) that should return a string.
@item :end-of-command @var{regexp}
@itemx :end-of-capability @var{regexp}
@@ -2655,8 +2661,8 @@ command @var{capability-command}. The latter defaults to the former.
@item :starttls-function @var{function}
Function of one argument (the response to @var{capability-command}),
-which returns either @code{nil}, or the command to activate @acronym{STARTTLS}
-if supported.
+which returns either @code{nil} or the command to activate
+@acronym{STARTTLS}, if supported.
@item :success @var{regexp}
Regular expression matching a successful @acronym{STARTTLS} negotiation.
@@ -2684,8 +2690,9 @@ enable automatic queries of @code{auth-source} when
@item :return-list @var{cons-or-nil}
The return value of this function. If omitted or @code{nil}, return a
-process object. Otherwise, a cons of the form @code{(@var{process-object}
-. @var{plist})}, where @var{plist} has keywords:
+process object. Otherwise, a cons of the form
+@w{@code{(@var{process-object} . @var{plist})}}, where @var{plist} can
+include the following keywords:
@table @code
@item :greeting @var{string-or-nil}
@@ -2698,11 +2705,12 @@ The connection type: @samp{plain} or @samp{tls}.
@item :shell-command @var{string-or-nil}
If the connection @code{type} is @code{shell}, this parameter will be
-interpreted as a format-spec string that will be executed to make the
-connection. The specs available are @samp{%s} for the host name and
-@samp{%p} for the port number. For instance, if you want to first ssh
-to @samp{gateway} before making a plain connection, then this
-parameter could be something like @samp{ssh gateway nc %s %p}.
+interpreted as a format-spec string (@pxref{Custom Format Strings})
+that will be executed to make the connection. The specs available are
+@samp{%s} for the host name and @samp{%p} for the port number. For
+instance, if you want to first ssh to @samp{gateway} before making a
+plain connection, then this parameter's value could be something like
+@samp{ssh gateway nc %s %p}.
@end table
diff --git a/doc/lispref/records.texi b/doc/lispref/records.texi
index 287ad869297..34a632a23f3 100644
--- a/doc/lispref/records.texi
+++ b/doc/lispref/records.texi
@@ -1,6 +1,6 @@
@c -*-texinfo-*-
@c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 2017--2023 Free Software Foundation, Inc.
+@c Copyright (C) 2017--2024 Free Software Foundation, Inc.
@c See the file elisp.texi for copying conditions.
@node Records
@chapter Records
diff --git a/doc/lispref/searching.texi b/doc/lispref/searching.texi
index 66b33316faa..2fa7ebc903d 100644
--- a/doc/lispref/searching.texi
+++ b/doc/lispref/searching.texi
@@ -1,6 +1,6 @@
@c -*-texinfo-*-
@c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990--1995, 1998--1999, 2001--2023 Free Software
+@c Copyright (C) 1990--1995, 1998--1999, 2001--2024 Free Software
@c Foundation, Inc.
@c See the file elisp.texi for copying conditions.
@node Searching and Matching
@@ -1972,6 +1972,17 @@ advice, don't be afraid of performing the matching in multiple
function calls, each using a simpler regexp where backtracking can
more easily be contained.
+@defun re--describe-compiled regexp &optional raw
+To help diagnose problems in your regexps or in the regexp engine
+itself, this function returns a string describing the compiled
+form of @var{regexp}. To make sense of it, it can be necessary
+to read at least the description of the @code{re_opcode_t} type in the
+@code{src/regex-emacs.c} file in Emacs' source code.
+
+It is currently able to give a meaningful description only if Emacs
+was compiled with @code{--enable-checking}.
+@end defun
+
@node Regexp Search
@section Regular Expression Searching
@cindex regular expression searching
@@ -2979,7 +2990,7 @@ values of the variables @code{sentence-end-double-space}
@section Emacs versus POSIX Regular Expressions
@cindex POSIX regular expressions
-Regular expression syntax varies signficantly among computer programs.
+Regular expression syntax varies significantly among computer programs.
When writing Elisp code that generates regular expressions for use by other
programs, it is helpful to know how syntax variants differ.
To give a feel for the variation, this section discusses how
diff --git a/doc/lispref/sequences.texi b/doc/lispref/sequences.texi
index dd5b723b479..f1f23f007a4 100644
--- a/doc/lispref/sequences.texi
+++ b/doc/lispref/sequences.texi
@@ -1,6 +1,6 @@
@c -*-texinfo-*-
@c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990--1995, 1998--1999, 2001--2023 Free Software
+@c Copyright (C) 1990--1995, 1998--1999, 2001--2024 Free Software
@c Foundation, Inc.
@c See the file elisp.texi for copying conditions.
@node Sequences Arrays Vectors
@@ -1645,7 +1645,8 @@ Refers to the element for character @var{char}
@item @code{(@var{from} . @var{to})}
A cons cell refers to all the characters in the inclusive range
-@samp{[@var{from}..@var{to}]}.
+@samp{[@var{from}..@var{to}]}. In this case, the function returns the
+value for the character specified by @var{from}.
@end table
@end defun
diff --git a/doc/lispref/streams.texi b/doc/lispref/streams.texi
index 896cf4caab5..d7e9200d52c 100644
--- a/doc/lispref/streams.texi
+++ b/doc/lispref/streams.texi
@@ -1,6 +1,6 @@
@c -*-texinfo-*-
@c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990--1994, 1998--1999, 2001--2023 Free Software
+@c Copyright (C) 1990--1994, 1998--1999, 2001--2024 Free Software
@c Foundation, Inc.
@c See the file elisp.texi for copying conditions.
@node Read and Print
diff --git a/doc/lispref/strings.texi b/doc/lispref/strings.texi
index 3d86a87516b..7097de49064 100644
--- a/doc/lispref/strings.texi
+++ b/doc/lispref/strings.texi
@@ -1,6 +1,6 @@
@c -*- mode: texinfo; coding: utf-8 -*-
@c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990--1995, 1998--1999, 2001--2023 Free Software
+@c Copyright (C) 1990--1995, 1998--1999, 2001--2024 Free Software
@c Foundation, Inc.
@c See the file elisp.texi for copying conditions.
@node Strings and Characters
@@ -754,7 +754,7 @@ ignores case differences.
@defun string-search needle haystack &optional start-pos
Return the position of the first instance of @var{needle} in
@var{haystack}, both of which are strings. If @var{start-pos} is
-non-@code{nil}, start searching from that position in @var{needle}.
+non-@code{nil}, start searching from that position in @var{haystack}.
Return @code{nil} if no match was found.
This function only considers the characters in the strings when doing
the comparison; text properties are ignored. Matching is always
@@ -1508,9 +1508,12 @@ has been capitalized. This means that the first character of each
word is converted to upper case, and the rest are converted to lower
case.
+@vindex case-symbols-as-words
The definition of a word is any sequence of consecutive characters that
are assigned to the word constituent syntax class in the current syntax
-table (@pxref{Syntax Class Table}).
+table (@pxref{Syntax Class Table}); if @code{case-symbols-as-words}
+is non-nil, characters assigned to the symbol constituent syntax
+class are also considered as word constituent.
When @var{string-or-char} is a character, this function does the same
thing as @code{upcase}.
@@ -1540,9 +1543,9 @@ letters other than the initials. It returns a new string whose
contents are a copy of @var{string-or-char}, in which each word has
had its initial letter converted to upper case.
-The definition of a word is any sequence of consecutive characters that
-are assigned to the word constituent syntax class in the current syntax
-table (@pxref{Syntax Class Table}).
+The definition of a word for this function is the same as described
+for @code{capitalize} above, and @code{case-symbols-as-words} has the
+same effect on word constituent characters.
When the argument to @code{upcase-initials} is a character,
@code{upcase-initials} has the same result as @code{upcase}.
diff --git a/doc/lispref/symbols.texi b/doc/lispref/symbols.texi
index 34db0caf3a8..6fe4189901a 100644
--- a/doc/lispref/symbols.texi
+++ b/doc/lispref/symbols.texi
@@ -1,6 +1,6 @@
@c -*-texinfo-*-
@c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990--1995, 1998--1999, 2001--2023 Free Software
+@c Copyright (C) 1990--1995, 1998--1999, 2001--2024 Free Software
@c Foundation, Inc.
@c See the file elisp.texi for copying conditions.
@node Symbols
@@ -783,10 +783,15 @@ Symbol forms whose names start with @samp{#_} are not transformed.
@cindex bare symbol
A @dfn{symbol with position} is a symbol, the @dfn{bare symbol},
-together with an unsigned integer called the @dfn{position}. These
-objects are intended for use by the byte compiler, which records in
-them the position of each symbol occurrence and uses those positions
-in warning and error messages.
+together with an unsigned integer called the @dfn{position}. Symbols
+with position don't themselves have entries in the obarray (though
+their bare symbols do; @pxref{Creating Symbols}).
+
+Symbols with position are for the use of the byte compiler, which
+records in them the position of each symbol occurrence and uses those
+positions in warning and error messages. They shouldn't normally be
+used otherwise. Doing so can cause unexpected results with basic
+Emacs functions such as @code{eq} and @code{equal}.
The printed representation of a symbol with position uses the hash
notation outlined in @ref{Printed Representation}. It looks like
@@ -798,11 +803,20 @@ the compiled Lisp file.
For most purposes, when the flag variable
@code{symbols-with-pos-enabled} is non-@code{nil}, symbols with
-positions behave just as bare symbols do. For example, @samp{(eq
-#<symbol foo at 12345> foo)} has a value @code{t} when that variable
-is set (but @code{nil} when it isn't set). Most of the time in Emacs this
-variable is @code{nil}, but the byte compiler binds it to @code{t}
-when it runs.
+positions behave just as their bare symbols would. For example,
+@samp{(eq #<symbol foo at 12345> foo)} has a value @code{t} when the
+variable is set; likewise, @code{equal} will treat a symbol with
+position argument as its bare symbol.
+
+When @code{symbols-with-pos-enabled} is @code{nil}, any symbols with
+position continue to exist, but do not behave as symbols, or have the
+other useful properties outlined in the previous paragraph. @code{eq}
+returns @code{t} when given identical arguments, and @code{equal}
+returns @code{t} when given arguments with @code{equal} components.
+
+Most of the time in Emacs @code{symbols-with-pos-enabled} is
+@code{nil}, but the byte compiler and the native compiler bind it to
+@code{t} when they run.
Typically, symbols with position are created by the byte compiler
calling the reader function @code{read-positioning-symbols}
@@ -810,17 +824,17 @@ calling the reader function @code{read-positioning-symbols}
@code{position-symbol}.
@defvar symbols-with-pos-enabled
-When this variable is non-@code{nil}, symbols with position behave
+When this variable is non-@code{nil}, a symbol with position behaves
like the contained bare symbol. Emacs runs a little more slowly in
this case.
@end defvar
@defvar print-symbols-bare
-When bound to non-@code{nil}, the Lisp printer prints only the bare symbol of
-a symbol with position, ignoring the position.
+When bound to non-@code{nil}, the Lisp printer prints only the bare
+symbol of a symbol with position, ignoring the position.
@end defvar
-@defun symbol-with-pos-p symbol.
+@defun symbol-with-pos-p symbol
This function returns @code{t} if @var{symbol} is a symbol with
position, @code{nil} otherwise.
@end defun
diff --git a/doc/lispref/syntax.texi b/doc/lispref/syntax.texi
index 2a4bd6f1585..83bbd19ca6f 100644
--- a/doc/lispref/syntax.texi
+++ b/doc/lispref/syntax.texi
@@ -1,6 +1,6 @@
@c -*-texinfo-*-
@c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990--1995, 1998--1999, 2001--2023 Free Software
+@c Copyright (C) 1990--1995, 1998--1999, 2001--2024 Free Software
@c Foundation, Inc.
@c See the file elisp.texi for copying conditions.
@node Syntax Tables
diff --git a/doc/lispref/text.texi b/doc/lispref/text.texi
index 4ffd5126e7e..3d14a5ad8be 100644
--- a/doc/lispref/text.texi
+++ b/doc/lispref/text.texi
@@ -1,6 +1,6 @@
@c -*-texinfo-*-
@c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990--1995, 1998--2023 Free Software Foundation, Inc.
+@c Copyright (C) 1990--1995, 1998--2024 Free Software Foundation, Inc.
@c See the file elisp.texi for copying conditions.
@node Text
@chapter Text
@@ -2808,22 +2808,21 @@ indentation in the text.
@deffn Command back-to-indentation
@comment !!SourceFile simple.el
This command moves point to the first non-whitespace character in the
-current line (which is the line in which point is located). It returns
-@code{nil}.
+current line (which is the line in which point is located).
@end deffn
@deffn Command backward-to-indentation &optional arg
@comment !!SourceFile simple.el
This command moves point backward @var{arg} lines and then to the
-first nonblank character on that line. It returns @code{nil}.
-If @var{arg} is omitted or @code{nil}, it defaults to 1.
+first nonblank character on that line. If @var{arg} is omitted or
+@code{nil}, it defaults to 1.
@end deffn
@deffn Command forward-to-indentation &optional arg
@comment !!SourceFile simple.el
This command moves point forward @var{arg} lines and then to the first
-nonblank character on that line. It returns @code{nil}.
-If @var{arg} is omitted or @code{nil}, it defaults to 1.
+nonblank character on that line. If @var{arg} is omitted or
+@code{nil}, it defaults to 1.
@end deffn
@node Case Changes
@@ -2946,7 +2945,10 @@ character.
Copying text between strings and buffers preserves the properties
along with the characters; this includes such diverse functions as
-@code{substring}, @code{insert}, and @code{buffer-substring}.
+@code{substring}, @code{insert}, and @code{buffer-substring}. Killing
+and then yanking text (@pxref{The Kill Ring}) also preserves the
+properties, except that some properties are handled specially and
+might be removed when text is yanked; @pxref{Yanking}.
@menu
* Examining Properties:: Looking at the properties of one character.
@@ -5487,7 +5489,11 @@ made by the transaction.
@defmac with-sqlite-transaction db body@dots{}
Like @code{progn} (@pxref{Sequencing}), but executes @var{body} with a
-transaction held, and commits the transaction at the end.
+transaction held, and commits the transaction at the end if @var{body}
+completes normally. If @var{body} signals an error, or committing the
+transaction fails, the changes in @var{db} performed by @var{body} are
+rolled back. The macro returns the value of @var{body} if it
+completes normally and commit succeeds.
@end defmac
@defun sqlite-pragma db pragma
@@ -5916,74 +5922,109 @@ Nevertheless, we can define two distinct APIs around the
@cindex JSONRPC application interfaces
@enumerate
-@item A user interface for building JSONRPC applications
+@item An API for building JSONRPC applications
@findex :request-dispatcher
@findex :notification-dispatcher
@findex jsonrpc-notify
@findex jsonrpc-request
@findex jsonrpc-async-request
-In this scenario, the JSONRPC application selects a concrete subclass
-of @code{jsonrpc-connection}, and proceeds to create objects of that
-subclass using @code{make-instance}. To initiate a contact to the
-remote endpoint, the JSONRPC application passes this object to the
-functions @code{jsonrpc-notify}, @code{jsonrpc-request}, and/or
-@code{jsonrpc-async-request}. For handling remotely initiated
-contacts, which generally come in asynchronously, the instantiation
-should include @code{:request-dispatcher} and
-@code{:notification-dispatcher} initargs, which are both functions of
-3 arguments: the connection object; a symbol naming the JSONRPC method
-invoked remotely; and a JSONRPC @code{params} object.
+In this scenario, a new aspiring JSONRPC-based application selects a
+concrete subclass of @code{jsonrpc-connection} that provides the
+transport for the JSONRPC messages to be exchanged between endpoints.
+
+The application creates objects of that subclass using
+@code{make-instance}. To initiate a contact to a remote endpoint, the
+application passes this object to the functions such as
+@code{jsonrpc-notify}, @code{jsonrpc-request}, or
+@code{jsonrpc-async-request}.
+
+For handling remotely initiated contacts, which generally come in
+asynchronously, the @code{make-instance} instantiation should
+initialize it the @code{:request-dispatcher} and
+@code{:notification-dispatcher} EIEIO keyword arguments. These are
+both functions of 3 arguments: the connection object; a symbol naming
+the JSONRPC method invoked remotely; and a JSONRPC @code{params}
+object.
@findex jsonrpc-error
The function passed as @code{:request-dispatcher} is responsible for
handling the remote endpoint's requests, which expect a reply from the
-local endpoint (in this case, the program you're building). Inside
-that function, you may either return locally (a normal return) or
-non-locally (an error return). A local return value must be a Lisp
-object that can be serialized as JSON (@pxref{Parsing JSON}). This
-determines a success response, and the object is forwarded to the
-server as the JSONRPC @code{result} object. A non-local return,
-achieved by calling the function @code{jsonrpc-error}, causes an error
-response to be sent to the server. The details of the accompanying
-JSONRPC @code{error} are filled out with whatever was passed to
+local endpoint (in this case, the application you're building).
+Inside that function, you may either return locally (a regular return)
+or non-locally (throw an error). Both exits from the request
+dispatcher cause a reply to the remote endpoint's request to be sent
+through the transport.
+
+A regular return determines a success response, and the return value
+must be a Lisp object that can be serialized as JSON (@pxref{Parsing
+JSON}). The result is forwarded to the server as the JSONRPC
+@code{result} object. A non-local return, achieved by calling the
+function @code{jsonrpc-error}, causes an error response to be sent to
+the server. The details of the accompanying JSONRPC @code{error}
+object are filled out with whatever was passed to
@code{jsonrpc-error}. A non-local return triggered by an unexpected
error of any other type also causes an error response to be sent
(unless you have set @code{debug-on-error}, in which case this calls
the Lisp debugger, @pxref{Error Debugging}).
-@item A inheritance interface for building JSONRPC transport implementations
-
-In this scenario, @code{jsonrpc-connection} is subclassed to implement
+@findex jsonrpc-convert-to-endpoint
+@findex jsonrpc-convert-from-endpoint
+It's possible to use the @code{jsonrpc} library to build applications
+based on transport protocols that can be described as
+``quasi-JSONRPC''. These are similar, but not quite identical to
+JSONRPC, such as the @uref{https://www.jsonrpc.org/, DAP (Debug
+Adapter Protocol)}. These protocols also define request, response and
+notification messages but the format is not quite the same as JSONRPC.
+The generic functions @code{jsonrpc-convert-to-endpoint} and
+@code{jsonrpc-convert-from-endpoint} can be customized for converting
+between the internal representation of JSONRPC and whatever the
+endpoint accepts (@pxref{Generic Functions}).
+
+@item An API for building JSONRPC transports
+
+In this scenario, @code{jsonrpc-connection} is sub-classed to implement
a different underlying transport strategy (for details on how to
subclass, see @ref{Inheritance,Inheritance,,eieio}.). Users of the
application-building interface can then instantiate objects of this
concrete class (using the @code{make-instance} function) and connect
-to JSONRPC endpoints using that strategy.
+to JSONRPC endpoints using that strategy. See @ref{Process-based
+JSONRPC connections} for a built-in transport implementation.
This API has mandatory and optional parts.
@findex jsonrpc-connection-send
To allow its users to initiate JSONRPC contacts (notifications or
-requests) or reply to endpoint requests, the subclass must have an
-implementation of the @code{jsonrpc-connection-send} method.
+requests) or reply to endpoint requests, the new transport
+implementation must equip the @code{jsonrpc-connection-send} generic
+function with a specialization for the the new subclass
+(@pxref{Generic Functions}). This generic function is called
+automatically by primitives such as @code{jsonrpc-request} and
+@code{jsonrpc-notify}. The specialization should ensure that the
+message described in the argument list is sent through whatever
+underlying communication mechanism (a.k.a.@: ``wire'') is used by the
+new transport to talk to endpoints. This ``wire'' may be a network
+socket, a serial interface, an HTTP connection, etc.
@findex jsonrpc-connection-receive
Likewise, for handling the three types of remote contacts (requests,
notifications, and responses to local requests), the transport
implementation must arrange for the function
-@code{jsonrpc-connection-receive} to be called after noticing a new
-JSONRPC message on the wire (whatever that "wire" may be).
+@code{jsonrpc-connection-receive} to be called from Elisp after
+noticing some data on the ``wire'' that can be used to craft a JSONRPC
+(or quasi-JSONRPC) message.
@findex jsonrpc-shutdown
@findex jsonrpc-running-p
Finally, and optionally, the @code{jsonrpc-connection} subclass should
-implement the @code{jsonrpc-shutdown} and @code{jsonrpc-running-p}
-methods if these concepts apply to the transport. If they do, then
-any system resources (e.g.@: processes, timers, etc.) used to listen for
-messages on the wire should be released in @code{jsonrpc-shutdown},
-i.e.@: they should only be needed while @code{jsonrpc-running-p} is
-non-@code{nil}.
+add specializations to the @code{jsonrpc-shutdown} and
+@code{jsonrpc-running-p} generic functions if these concepts apply to
+the transport. The specialization of @code{jsonrpc-shutdown} should
+ensure the release of any system resources (e.g.@: processes, timers,
+etc.) used to listen for messages on the wire. The specialization of
+@code{jsonrpc-running-p} should tell if these resources are still
+active or have already been released (via @code{jsonrpc-shutdown} or
+otherwise).
@end enumerate
@@ -6202,7 +6243,7 @@ cons it was set to at the time @code{prepare-change-group} was called.
If @code{buffer-undo-list} no longer contains that cons, Emacs will
lose track of any change groups, resulting in an error when the change
-group is cancelled. To avoid this, do not call any functions which
+group is canceled. To avoid this, do not call any functions which
may edit the undo list in such a manner, when a change group is
active: notably, ``amalgamating'' commands such as @code{delete-char},
which call @code{undo-auto-amalgamate}.
diff --git a/doc/lispref/threads.texi b/doc/lispref/threads.texi
index 43cf0da3508..2476603adc1 100644
--- a/doc/lispref/threads.texi
+++ b/doc/lispref/threads.texi
@@ -1,6 +1,6 @@
@c -*-texinfo-*-
@c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 2012--2023 Free Software Foundation, Inc.
+@c Copyright (C) 2012--2024 Free Software Foundation, Inc.
@c See the file elisp.texi for copying conditions.
@node Threads
@chapter Threads
diff --git a/doc/lispref/tips.texi b/doc/lispref/tips.texi
index f594d684338..0db9a35ac6f 100644
--- a/doc/lispref/tips.texi
+++ b/doc/lispref/tips.texi
@@ -1,6 +1,6 @@
@c -*- mode: texinfo; coding: utf-8 -*-
@c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990--1993, 1995, 1998--1999, 2001--2023 Free Software
+@c Copyright (C) 1990--1993, 1995, 1998--1999, 2001--2024 Free Software
@c Foundation, Inc.
@c See the file elisp.texi for copying conditions.
@node Tips
@@ -43,6 +43,7 @@ in batch mode, e.g., with a command run by @kbd{@w{M-x compile
@section Emacs Lisp Coding Conventions
@cindex coding conventions in Emacs Lisp
+@cindex conventions for Emacs Lisp programs
Here are conventions that you should follow when writing Emacs Lisp
code intended for widespread use:
@@ -97,7 +98,7 @@ alternative common prefixes, so long as they make sense.
@item
We recommend enabling @code{lexical-binding} in new code, and
converting existing Emacs Lisp code to enable @code{lexical-binding}
-if it doesn't already. @xref{Using Lexical Binding}.
+if it doesn't already. @xref{Selecting Lisp Dialect}.
@item
Put a call to @code{provide} at the end of each separate Lisp file.
@@ -264,6 +265,7 @@ which are lists of directory names.
@node Key Binding Conventions
@section Key Binding Conventions
@cindex key binding, conventions for
+@cindex conventions for key bindings
@itemize @bullet
@item
@@ -345,6 +347,7 @@ after @key{ESC}. In these states, you should define @kbd{@key{ESC}
@node Programming Tips
@section Emacs Programming Tips
@cindex programming conventions
+@cindex conventions for Emacs programming
Following these conventions will make your program fit better
into Emacs when it runs.
@@ -477,6 +480,7 @@ buffer and let the user switch back at will. @xref{Recursive Editing}.
@section Tips for Making Compiled Code Fast
@cindex execution speed
@cindex speedups
+@cindex tips for faster Lisp code
Here are ways of improving the execution speed of byte-compiled
Lisp programs.
@@ -531,6 +535,7 @@ the speed. @xref{Inline Functions}.
@node Warning Tips
@section Tips for Avoiding Compiler Warnings
@cindex byte compiler warnings, how to avoid
+@cindex warnings from byte compiler
@itemize @bullet
@item
@@ -585,6 +590,8 @@ is to put it inside @code{with-no-warnings}. @xref{Compiler Errors}.
@node Documentation Tips
@section Tips for Documentation Strings
@cindex documentation strings, conventions and tips
+@cindex tips for documentation strings
+@cindex conventions for documentation strings
@findex checkdoc-minor-mode
Here are some tips and conventions for the writing of documentation
@@ -624,7 +631,12 @@ first line with a capital letter and end it with a period.
For a function, the first line should briefly answer the question,
``What does this function do?'' For a variable, the first line should
-briefly answer the question, ``What does this value mean?''
+briefly answer the question, ``What does this value mean?'' Prefer to
+answer these questions in a way that will make sense to users and
+callers of the function or the variable. In particular, do @emph{not}
+tell what the function does by enumerating the actions of its code;
+instead, describe the role of these actions and the function's
+contract.
Don't limit the documentation string to one line; use as many lines as
you need to explain the details of how to use the function or
@@ -638,11 +650,11 @@ include before the first blank line so as to make this display useful.
@item
The first line should mention all the important arguments of the
-function, and should mention them in the order that they are written
-in a function call. If the function has many arguments, then it is
-not feasible to mention them all in the first line; in that case, the
-first line should mention the first few arguments, including the most
-important arguments.
+function (in particular, the mandatory arguments), and should mention
+them in the order that they are written in a function call. If the
+function has many arguments, then it is not feasible to mention them
+all in the first line; in that case, the first line should mention the
+first few arguments, including the most important arguments.
@item
When a function's documentation string mentions the value of an argument
@@ -915,6 +927,7 @@ versions, there is no need for this work-around.
@node Comment Tips
@section Tips on Writing Comments
@cindex comments, Lisp convention for
+@cindex conventions for Lisp comments
We recommend these conventions for comments:
@@ -1030,6 +1043,7 @@ semicolons.
@section Conventional Headers for Emacs Libraries
@cindex header comments
@cindex library header comments
+@cindex conventions for library header comments
Emacs has conventions for using special comments in Lisp libraries
to divide them into sections and give information such as who wrote
@@ -1169,6 +1183,21 @@ element) is equivalent to entry with version "0". For instance:
;; Package-Requires: ((gnus "1.0") (bubbles "2.7.2") cl-lib (seq))
@end smallexample
+Packages that don't need to support Emacs versions older than Emacs 27
+can have the @samp{Package-Requires} header split across multiple
+lines, like this:
+
+@smallexample
+@group
+;; Package-Requires: ((emacs "27.1")
+;; (compat "29.1.4.1"))
+@end group
+@end smallexample
+
+@noindent
+Note that with this format, you still need to start the list on the
+same line as @samp{Package-Requires}.
+
The package code automatically defines a package named @samp{emacs}
with the version number of the currently running Emacs. This can be
used to require a minimal version of Emacs for a package.
diff --git a/doc/lispref/two-volume-cross-refs.txt b/doc/lispref/two-volume-cross-refs.txt
index 741efe3baf8..fa876befa69 100644
--- a/doc/lispref/two-volume-cross-refs.txt
+++ b/doc/lispref/two-volume-cross-refs.txt
@@ -1,4 +1,4 @@
-Copyright (C) 2001-2023 Free Software Foundation, Inc.
+Copyright (C) 2001-2024 Free Software Foundation, Inc.
See end for copying conditions.
Two Volume Cross References
diff --git a/doc/lispref/two-volume.make b/doc/lispref/two-volume.make
index c412820748c..793a4425d3b 100644
--- a/doc/lispref/two-volume.make
+++ b/doc/lispref/two-volume.make
@@ -1,4 +1,4 @@
-# Copyright (C) 2007-2023 Free Software Foundation, Inc.
+# Copyright (C) 2007-2024 Free Software Foundation, Inc.
# See end for copying conditions.
# although it would be nice to use tex rather than pdftex to avoid
diff --git a/doc/lispref/variables.texi b/doc/lispref/variables.texi
index 93930d17587..705d3260063 100644
--- a/doc/lispref/variables.texi
+++ b/doc/lispref/variables.texi
@@ -1,6 +1,6 @@
@c -*-texinfo-*-
@c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990--1995, 1998--2023 Free Software Foundation, Inc.
+@c Copyright (C) 1990--1995, 1998--2024 Free Software Foundation, Inc.
@c See the file elisp.texi for copying conditions.
@node Variables
@chapter Variables
@@ -678,15 +678,15 @@ which are being phased out.)
it as safe or risky; see @ref{File Local Variables}.
When defining and initializing a variable that holds a complicated
-value (such as a keymap with bindings in it), it's best to put the
+value (such as a syntax table for a major mode), it's best to put the
entire computation of the value into the @code{defvar}, like this:
@example
-(defvar my-mode-map
- (let ((map (make-sparse-keymap)))
- (keymap-set map "C-c C-a" 'my-command)
+(defvar my-major-mode-syntax-table
+ (let ((table (make-syntax-table)))
+ (modify-syntax-entry ?# "<" table)
@dots{}
- map)
+ table)
@var{docstring})
@end example
@@ -696,9 +696,9 @@ loading the file, the variable is either still uninitialized or
initialized properly, never in-between. If it is still uninitialized,
reloading the file will initialize it properly. Second, reloading the
file once the variable is initialized will not alter it; that is
-important if the user has run hooks to alter part of the contents
-(such as, to rebind keys). Third, evaluating the @code{defvar} form
-with @kbd{C-M-x} will reinitialize the map completely.
+important if the user has changed its value. Third, evaluating the
+@code{defvar} form with @kbd{C-M-x} will reinitialize the variable
+completely.
@node Accessing Variables
@section Accessing Variable Values
@@ -976,184 +976,57 @@ Variables}). This section describes exactly what this means.
binding can be accessed. @dfn{Extent} refers to @emph{when}, as the
program is executing, the binding exists.
-@cindex dynamic binding
-@cindex dynamic scope
-@cindex dynamic extent
- By default, the local bindings that Emacs creates are @dfn{dynamic
-bindings}. Such a binding has @dfn{dynamic scope}, meaning that any
-part of the program can potentially access the variable binding. It
-also has @dfn{dynamic extent}, meaning that the binding lasts only
-while the binding construct (such as the body of a @code{let} form) is
-being executed.
-
@cindex lexical binding
@cindex lexical scope
@cindex indefinite extent
- Emacs can optionally create @dfn{lexical bindings}. A lexical
-binding has @dfn{lexical scope}, meaning that any reference to the
-variable must be located textually within the binding
+ For historical reasons, there are two dialects of Emacs Lisp,
+selected via the @code{lexical-binding} buffer-local variable.
+In the modern Emacs Lisp dialect, local bindings are lexical by default.
+A @dfn{lexical binding} has @dfn{lexical scope}, meaning that any
+reference to the variable must be located textually within the binding
construct@footnote{With some exceptions; for instance, a lexical
binding can also be accessed from the Lisp debugger.}. It also has
@dfn{indefinite extent}, meaning that under some circumstances the
binding can live on even after the binding construct has finished
-executing, by means of special objects called @dfn{closures}.
+executing, by means of objects called @dfn{closures}.
- The dynamic binding was (and still is) the default in Emacs for many
-years, but lately Emacs is moving towards using lexical binding in
-more and more places, with the goal of eventually making that the
-default.
+@cindex dynamic binding
+@cindex dynamic scope
+@cindex dynamic extent
+ Local bindings can also be dynamic, which they always are in the
+old Emacs Lisp dialect and optionally in the modern dialect.
+A @dfn{dynamic binding} has @dfn{dynamic scope}, meaning that any
+part of the program can potentially access the variable binding. It
+also has @dfn{dynamic extent}, meaning that the binding lasts only
+while the binding construct (such as the body of a @code{let} form) is
+being executed.
- The following subsections describe dynamic binding and lexical
+ The old dynamic-only Emacs Lisp dialect is still the default in code
+loaded or evaluated from Lisp files that lack a dialect declaration.
+Eventually the modern dialect will be made the default.
+All Lisp files should declare the dialect used to ensure that they
+keep working correctly in the future.
+
+ The following subsections describe lexical binding and dynamic
binding in greater detail, and how to enable lexical binding in Emacs
Lisp programs.
@menu
-* Dynamic Binding:: The default for binding local variables in Emacs.
+* Lexical Binding:: The standard type of local variable binding.
+* Dynamic Binding:: A different type of local variable binding.
* Dynamic Binding Tips:: Avoiding problems with dynamic binding.
-* Lexical Binding:: A different type of local variable binding.
-* Using Lexical Binding:: How to enable lexical binding.
+* Selecting Lisp Dialect:: How to select the Emacs Lisp dialect to use.
* Converting to Lexical Binding:: Convert existing code to lexical binding.
@end menu
-@node Dynamic Binding
-@subsection Dynamic Binding
-
- By default, the local variable bindings made by Emacs are dynamic
-bindings. When a variable is dynamically bound, its current binding
-at any point in the execution of the Lisp program is simply the most
-recently-created dynamic local binding for that symbol, or the global
-binding if there is no such local binding.
-
- Dynamic bindings have dynamic scope and extent, as shown by the
-following example:
-
-@example
-@group
-(defvar x -99) ; @r{@code{x} receives an initial value of @minus{}99.}
-
-(defun getx ()
- x) ; @r{@code{x} is used free in this function.}
-
-(let ((x 1)) ; @r{@code{x} is dynamically bound.}
- (getx))
- @result{} 1
-
-;; @r{After the @code{let} form finishes, @code{x} reverts to its}
-;; @r{previous value, which is @minus{}99.}
-
-(getx)
- @result{} -99
-@end group
-@end example
-
-@noindent
-The function @code{getx} refers to @code{x}. This is a @dfn{free}
-reference, in the sense that there is no binding for @code{x} within
-that @code{defun} construct itself. When we call @code{getx} from
-within a @code{let} form in which @code{x} is (dynamically) bound, it
-retrieves the local value (i.e., 1). But when we call @code{getx}
-outside the @code{let} form, it retrieves the global value (i.e.,
-@minus{}99).
-
- Here is another example, which illustrates setting a dynamically
-bound variable using @code{setq}:
-
-@example
-@group
-(defvar x -99) ; @r{@code{x} receives an initial value of @minus{}99.}
-
-(defun addx ()
- (setq x (1+ x))) ; @r{Add 1 to @code{x} and return its new value.}
-
-(let ((x 1))
- (addx)
- (addx))
- @result{} 3 ; @r{The two @code{addx} calls add to @code{x} twice.}
-
-;; @r{After the @code{let} form finishes, @code{x} reverts to its}
-;; @r{previous value, which is @minus{}99.}
-
-(addx)
- @result{} -98
-@end group
-@end example
-
- Dynamic binding is implemented in Emacs Lisp in a simple way. Each
-symbol has a value cell, which specifies its current dynamic value (or
-absence of value). @xref{Symbol Components}. When a symbol is given
-a dynamic local binding, Emacs records the contents of the value cell
-(or absence thereof) in a stack, and stores the new local value in the
-value cell. When the binding construct finishes executing, Emacs pops
-the old value off the stack, and puts it in the value cell.
-
- Note that when code using Dynamic Binding is native compiled the
-native compiler will not perform any Lisp specific optimization.
-
-@node Dynamic Binding Tips
-@subsection Proper Use of Dynamic Binding
-
- Dynamic binding is a powerful feature, as it allows programs to
-refer to variables that are not defined within their local textual
-scope. However, if used without restraint, this can also make
-programs hard to understand. There are two clean ways to use this
-technique:
-
-@itemize @bullet
-@item
-If a variable has no global definition, use it as a local variable
-only within a binding construct, such as the body of the @code{let}
-form where the variable was bound. If this convention is followed
-consistently throughout a program, the value of the variable will not
-affect, nor be affected by, any uses of the same variable symbol
-elsewhere in the program.
-
-@item
-Otherwise, define the variable with @code{defvar}, @code{defconst}
-(@pxref{Defining Variables}), or @code{defcustom} (@pxref{Variable
-Definitions}). Usually, the definition should be at top-level in an
-Emacs Lisp file. As far as possible, it should include a
-documentation string which explains the meaning and purpose of the
-variable. You should also choose the variable's name to avoid name
-conflicts (@pxref{Coding Conventions}).
-
-Then you can bind the variable anywhere in a program, knowing reliably
-what the effect will be. Wherever you encounter the variable, it will
-be easy to refer back to the definition, e.g., via the @kbd{C-h v}
-command (provided the variable definition has been loaded into Emacs).
-@xref{Name Help,,, emacs, The GNU Emacs Manual}.
-
-For example, it is common to use local bindings for customizable
-variables like @code{case-fold-search}:
-
-@example
-@group
-(defun search-for-abc ()
- "Search for the string \"abc\", ignoring case differences."
- (let ((case-fold-search t))
- (re-search-forward "abc")))
-@end group
-@end example
-@end itemize
-
@node Lexical Binding
@subsection Lexical Binding
- Lexical binding was introduced to Emacs, as an optional feature, in
-version 24.1. We expect its importance to increase with time.
-Lexical binding opens up many more opportunities for optimization, so
-programs using it are likely to run faster in future Emacs versions.
-Lexical binding is also more compatible with concurrency, which was
-added to Emacs in version 26.1.
-
- A lexically-bound variable has @dfn{lexical scope}, meaning that any
+Lexical binding is only available in the modern Emacs Lisp dialect.
+(@xref{Selecting Lisp Dialect}.)
+A lexically-bound variable has @dfn{lexical scope}, meaning that any
reference to the variable must be located textually within the binding
construct. Here is an example
-@iftex
-(see the next subsection, for how to actually enable lexical binding):
-@end iftex
-@ifnottex
-(@pxref{Using Lexical Binding}, for how to actually enable lexical binding):
-@end ifnottex
@example
@group
@@ -1186,17 +1059,6 @@ wants the current value of a variable, it looks first in the lexical
environment; if the variable is not specified in there, it looks in
the symbol's value cell, where the dynamic value is stored.
- (Internally, the lexical environment is a list whose members are
-usually cons cells that are symbol-value pairs, but some of its
-members can be symbols rather than cons cells. A symbol in the list
-means the lexical environment declared that symbol's variable as
-locally considered to be dynamically bound. This list can be passed
-as the second argument to the @code{eval} function, in order to
-specify a lexical environment in which to evaluate a form.
-@xref{Eval}. Most Emacs Lisp programs, however, should not interact
-directly with lexical environments in this way; only specialized
-programs like debuggers.)
-
@cindex closures, example of using
Lexical bindings have indefinite extent. Even after a binding
construct has finished executing, its lexical environment can be
@@ -1249,37 +1111,74 @@ functions which take a symbol argument (like @code{symbol-value},
variable's dynamic binding (i.e., the contents of its symbol's value
cell).
-@node Using Lexical Binding
-@subsection Using Lexical Binding
+@node Dynamic Binding
+@subsection Dynamic Binding
- When loading an Emacs Lisp file or evaluating a Lisp buffer, lexical
-binding is enabled if the buffer-local variable @code{lexical-binding}
-is non-@code{nil}:
+ Local variable bindings are dynamic in the modern Lisp dialect for
+special variables (see below), and for all variables in the old Lisp
+dialect. (@xref{Selecting Lisp Dialect}.)
+Dynamic variable bindings have their uses but are in general more
+error-prone and less efficient than lexical bindings, and the compiler
+is less able to find mistakes in code using dynamic bindings.
-@defvar lexical-binding
-If this buffer-local variable is non-@code{nil}, Emacs Lisp files and
-buffers are evaluated using lexical binding instead of dynamic
-binding. (However, special variables are still dynamically bound; see
-below.) If @code{nil}, dynamic binding is used for all local
-variables. This variable is typically set for a whole Emacs Lisp
-file, as a file local variable (@pxref{File Local Variables}).
-Note that unlike other such variables, this one must be set in the
-first line of a file.
-@end defvar
+ When a variable is dynamically bound, its current binding
+at any point in the execution of the Lisp program is simply the most
+recently-created dynamic local binding for that symbol, or the global
+binding if there is no such local binding.
+
+ Dynamic bindings have dynamic scope and extent, as shown by the
+following example:
+
+@example
+@group
+(defvar x -99) ; @r{@code{x} receives an initial value of @minus{}99.}
+
+(defun getx ()
+ x) ; @r{@code{x} is used free in this function.}
+
+(let ((x 1)) ; @r{@code{x} is dynamically bound.}
+ (getx))
+ @result{} 1
+
+;; @r{After the @code{let} form finishes, @code{x} reverts to its}
+;; @r{previous value, which is @minus{}99.}
+
+(getx)
+ @result{} -99
+@end group
+@end example
@noindent
-When evaluating Emacs Lisp code directly using an @code{eval} call,
-lexical binding is enabled if the @var{lexical} argument to
-@code{eval} is non-@code{nil}. @xref{Eval}.
+The function @code{getx} refers to @code{x}. This is a @dfn{free}
+reference, in the sense that there is no binding for @code{x} within
+that @code{defun} construct itself. When we call @code{getx} from
+within a @code{let} form in which @code{x} is (dynamically) bound, it
+retrieves the local value (i.e., 1). But when we call @code{getx}
+outside the @code{let} form, it retrieves the global value (i.e.,
+@minus{}99).
-@findex eval-expression@r{, and }lexical-binding
-Lexical binding is also enabled in Lisp Interaction and IELM mode,
-used in the @file{*scratch*} and @file{*ielm*} buffers, and also when
-evaluating expressions via @kbd{M-:} (@code{eval-expression}) and when
-processing the @option{--eval} command-line options of Emacs
-(@pxref{Action Arguments,,, emacs, The GNU Emacs Manual}) and
-@command{emacsclient} (@pxref{emacsclient Options,,, emacs, The GNU
-Emacs Manual}).
+ Here is another example, which illustrates setting a dynamically
+bound variable using @code{setq}:
+
+@example
+@group
+(defvar x -99) ; @r{@code{x} receives an initial value of @minus{}99.}
+
+(defun addx ()
+ (setq x (1+ x))) ; @r{Add 1 to @code{x} and return its new value.}
+
+(let ((x 1))
+ (addx)
+ (addx))
+ @result{} 3 ; @r{The two @code{addx} calls add to @code{x} twice.}
+
+;; @r{After the @code{let} form finishes, @code{x} reverts to its}
+;; @r{previous value, which is @minus{}99.}
+
+(addx)
+ @result{} -98
+@end group
+@end example
@cindex special variables
Even when lexical binding is enabled, certain variables will
@@ -1329,6 +1228,111 @@ for those that are only special in the current lexical scope.
The use of a special variable as a formal argument in a function is
not supported.
+ Dynamic binding is implemented in Emacs Lisp in a simple way. Each
+symbol has a value cell, which specifies its current dynamic value (or
+absence of value). @xref{Symbol Components}. When a symbol is given
+a dynamic local binding, Emacs records the contents of the value cell
+(or absence thereof) in a stack, and stores the new local value in the
+value cell. When the binding construct finishes executing, Emacs pops
+the old value off the stack, and puts it in the value cell.
+
+@node Dynamic Binding Tips
+@subsection Proper Use of Dynamic Binding
+
+ Dynamic binding is a powerful feature, as it allows programs to
+refer to variables that are not defined within their local textual
+scope. However, if used without restraint, this can also make
+programs hard to understand.
+
+First, choose the variable's name to avoid name conflicts
+(@pxref{Coding Conventions}).
+
+@itemize @bullet
+@item
+If the variable is only used when locally bound to a value, declare it
+special using a @code{defvar} form without an initial value, and never
+assign to it unless it is already bound. This way, any attempt to
+refer to the variable when unbound will result in a
+@code{void-variable} error.
+
+@item
+Otherwise, define the variable with @code{defvar}, @code{defconst}
+(@pxref{Defining Variables}), or @code{defcustom} (@pxref{Variable
+Definitions}). Usually, the definition should be at top-level in an
+Emacs Lisp file. As far as possible, it should include a
+documentation string which explains the meaning and purpose of the
+variable.
+
+Then you can bind the variable anywhere in a program, knowing reliably
+what the effect will be. Wherever you encounter the variable, it will
+be easy to refer back to the definition, e.g., via the @kbd{C-h v}
+command (provided the variable definition has been loaded into Emacs).
+@xref{Name Help,,, emacs, The GNU Emacs Manual}.
+
+For example, it is common to use local bindings for customizable
+variables like @code{case-fold-search}:
+
+@example
+@group
+(defun search-for-abc ()
+ "Search for the string \"abc\", ignoring case differences."
+ (let ((case-fold-search t))
+ (re-search-forward "abc")))
+@end group
+@end example
+@end itemize
+
+@node Selecting Lisp Dialect
+@subsection Selecting Lisp Dialect
+
+ When loading an Emacs Lisp file or evaluating a Lisp buffer, the
+Lisp dialect is selected using the buffer-local variable
+@code{lexical-binding}.
+
+@defvar lexical-binding
+If this buffer-local variable is non-@code{nil}, Emacs Lisp files and
+buffers are evaluated using the modern Lisp dialect that by default
+uses lexical binding instead of dynamic binding. If @code{nil}, the
+old dialect is used that uses dynamic binding for all local variables.
+This variable is typically set for a whole Emacs Lisp file, as a
+file-local variable (@pxref{File Local Variables}). Note that unlike
+other such variables, this one must be set in the first line of a
+file.
+@end defvar
+
+@noindent
+In practice, dialect selection means that the first line in an Emacs
+Lisp file looks like:
+
+@example
+;;; ... -*- lexical-binding: t -*-
+@end example
+
+@noindent
+for the modern lexical-binding dialect, and
+
+@example
+;;; ... -*- lexical-binding: nil -*-
+@end example
+
+@noindent
+for the old dynamic-only dialect. When no declaration is present the
+old dialect is used, but this may change in a future release.
+The compiler will warn if no declaration is present.
+
+When evaluating Emacs Lisp code directly using an @code{eval} call,
+lexical binding is enabled if the @var{lexical} argument to
+@code{eval} is non-@code{nil}. @xref{Eval}.
+
+@findex eval-expression@r{, and }lexical-binding
+Lexical binding is also enabled in Lisp Interaction and IELM mode,
+used in the @file{*scratch*} and @file{*ielm*} buffers, and also when
+evaluating expressions via @kbd{M-:} (@code{eval-expression}) and when
+processing the @option{--eval} command-line options of Emacs
+(@pxref{Action Arguments,,, emacs, The GNU Emacs Manual}) and
+@command{emacsclient} (@pxref{emacsclient Options,,, emacs, The GNU
+Emacs Manual}).
+
@node Converting to Lexical Binding
@subsection Converting to Lexical Binding
@@ -1891,7 +1895,7 @@ This makes its global value shadowed by the binding;
@code{default-value} will then return the value from that binding, not
the global value, and @code{set-default} will be prevented from
setting the global value (it will change the let-bound value instead).
-The following two functions allow to reference the global value even
+The following two functions allow referencing the global value even
if it's shadowed by a let-binding.
@cindex top-level default value
@@ -2483,9 +2487,10 @@ are unwound. Example:
@defvar connection-local-default-application
The default application, a symbol, to be applied in
-@code{with-connection-local-variables}. It defaults to @code{tramp},
-but you can let-bind it to change the application temporarily
-(@pxref{Local Variables}).
+@code{with-connection-local-variables}, @code{connection-local-p} and
+@code{connection-local-value}. It defaults to @code{tramp}, but you
+can let-bind it to change the application temporarily (@pxref{Local
+Variables}).
This variable must not be changed globally.
@end defvar
@@ -2541,6 +2546,22 @@ profile.
This variable must not be changed globally.
@end defvar
+@defmac connection-local-p symbol &optional application
+This macro returns non-@code{nil} if @var{symbol} has a
+connection-local binding for @var{application}. If @var{application}
+is @code{nil}, the value of
+@code{connection-local-default-application} is used.
+@end defmac
+
+@defmac connection-local-value symbol &optional application
+This macro returns the connection-local value of @var{symbol} for
+@var{application}. If @var{application} is @code{nil}, the value of
+@code{connection-local-default-application} is used.
+
+If @var{symbol} does not have a connection-local
+binding, the value is the default binding of the variable.
+@end defmac
+
@defvar enable-connection-local-variables
If @code{nil}, connection-local variables are ignored. This variable
shall be changed temporarily only in special modes.
@@ -2981,7 +3002,7 @@ meant to be used, here's a small example:
@lisp
@group
-(define-multisession-variable foo-var 0)
+(define-multisession-variable foo 0)
(defun my-adder (num)
(interactive "nAdd number: ")
(setf (multisession-value foo)
@@ -2991,7 +3012,7 @@ meant to be used, here's a small example:
@end lisp
@noindent
-This defines the variable @code{foo-var} and binds it to a special
+This defines the variable @code{foo} and binds it to a special
multisession object which is initialized with the value @samp{0} (if
the variable doesn't already exist from a previous session). The
@code{my-adder} command queries the user for a number, adds this to
@@ -3014,7 +3035,7 @@ specified by @var{package-symbol}. The combination of
@var{package-symbol} isn't given, this will default to the first
``segment'' of the @var{name} symbol's name, which is the part of its
name up to and excluding the first @samp{-}. For instance, if
-@var{name} is @code{foo-var} and @var{package-symbol} isn't given,
+@var{name} is @code{foo} and @var{package-symbol} isn't given,
@var{package-symbol} will default to @code{foo}.
@cindex synchronized multisession variables
@@ -3022,7 +3043,7 @@ name up to and excluding the first @samp{-}. For instance, if
Multisession variables can be @dfn{synchronized} if @var{bool} is
non-@code{nil}. This means that if there're two concurrent Emacs
instances running, and the other Emacs changes the multisession
-variable @code{foo-var}, the current Emacs instance will retrieve that
+variable @code{foo}, the current Emacs instance will retrieve that
modified data when accessing the value. If @var{synchronized} is
@code{nil} or missing, this won't happen, and the values in all
Emacs sessions using the variable will be independent of each other.
diff --git a/doc/lispref/windows.texi b/doc/lispref/windows.texi
index a49e63e49de..1e2fbc5f052 100644
--- a/doc/lispref/windows.texi
+++ b/doc/lispref/windows.texi
@@ -1,6 +1,6 @@
@c -*-texinfo-*-
@c This is part of the GNU Emacs Lisp Reference Manual.
-@c Copyright (C) 1990--1995, 1998--1999, 2001--2023 Free Software
+@c Copyright (C) 1990--1995, 1998--1999, 2001--2024 Free Software
@c Foundation, Inc.
@c See the file elisp.texi for copying conditions.
@node Windows
@@ -2847,8 +2847,8 @@ the left edge coordinate of the reference window. Its left edge
coordinate would equal the left edge coordinate of the frame's new
root window.
-Four special values for @code{direction} entries allow to implicitly
-specify the selected frame's main window as the reference window:
+Four special values for @code{direction} entries allow implicitly
+specifying the selected frame's main window as the reference window:
@code{leftmost}, @code{top}, @code{rightmost} and @code{bottom}. This
means that instead of, for example, @w{@code{(direction . left)
(window . main)}} one can just specify @w{@code{(direction
@@ -3268,6 +3268,15 @@ The value specifies an alist of frame parameters to give a new frame,
if one is created. @code{display-buffer-pop-up-frame} is its one and
only addressee.
+@vindex pop-up-frames@r{, a buffer display action alist entry}
+@item pop-up-frames
+The value controls whether @code{display-buffer} may display buffers
+by making new frames. It has the same meaning as the
+@code{pop-up-frames} variable and takes precedence over it when present.
+Its main intended purpose is to override a non-nil value of the
+variable for particular buffers which the user prefers to keep
+in the selected frame.
+
@vindex parent-frame@r{, a buffer display action alist entry}
@item parent-frame
The value specifies the parent frame to be used when the buffer is
@@ -3441,6 +3450,9 @@ A non-@code{nil} value also means that when @code{display-buffer} is
looking for a window already displaying @var{buffer-or-name}, it can
search any visible or iconified frame, not just the selected frame.
+An entry by the same name in @code{display-buffer}'s @var{alist}
+takes precedence over the variable.
+
This variable is provided mainly for backward compatibility. It is
obeyed by @code{display-buffer} via a special mechanism in
@code{display-buffer-fallback-action}, which calls the action function
@@ -3512,15 +3524,12 @@ functions it should try instead as, for example:
@item pop-up-frames
@vindex pop-up-frames@r{, replacement for}
-Instead of customizing this variable to @code{t}, customize
+Instead of customizing this variable to @code{t}, you can customize
@code{display-buffer-base-action}, for example, as follows:
@example
@group
-(setopt
- display-buffer-base-action
- '((display-buffer-reuse-window display-buffer-pop-up-frame)
- (reusable-frames . 0)))
+(setopt display-buffer-base-action '(nil (pop-up-frames . t)))
@end group
@end example
@@ -3759,7 +3768,7 @@ preferred way regardless of whether the display is also guided by an
@code{display-buffer-alist} differs from customizing
@code{display-buffer-base-action} in two major aspects: it is stronger
because it overrides the @var{action} argument of
-@code{display-buffer}, and it allows to explicitly specify the
+@code{display-buffer}, and it enables you to explicitly specify the
affected buffers. In fact, displaying other buffers is not affected
in any way by a customization for @file{*foo*}. For example,
@@ -4596,7 +4605,7 @@ window and a number of side windows surrounding that main window. The
main window is either a ``normal'' live window or specifies the area
containing all the normal windows.
- In their most simple form of use, side windows allow to display
+ In their most simple form of use, side windows allow displaying
specific buffers always in the same area of a frame. Hence they can
be regarded as a generalization of the concept provided by
@code{display-buffer-at-bottom} (@pxref{Buffer Display Action
@@ -6150,11 +6159,11 @@ up-to-date.
@section Mouse Window Auto-selection
@cindex window auto-selection
@cindex auto-selection of window
-The following option allows to automatically select the window under the
-mouse pointer. This accomplishes a policy similar to that of window
-managers that give focus to a frame (and thus trigger its subsequent
-selection) whenever the mouse pointer enters its window-system window
-(@pxref{Input Focus}).
+The following option enables automatically selecting the window under
+the mouse pointer. This accomplishes a policy similar to that of
+window managers that give focus to a frame (and thus trigger its
+subsequent selection) whenever the mouse pointer enters its
+window-system window (@pxref{Input Focus}).
@defopt mouse-autoselect-window
If this variable is non-@code{nil}, Emacs will try to automatically
@@ -6188,7 +6197,7 @@ and never deselects the active minibuffer window.
Mouse auto-selection can be used to emulate a focus follows mouse policy
for child frames (@pxref{Child Frames}) which usually are not tracked by
-the window manager. This requires to set the value of
+the window manager. This requires setting the value of
@code{focus-follows-mouse} (@pxref{Input Focus}) to a non-@code{nil}
value. If the value of @code{focus-follows-mouse} is @code{auto-raise},
entering a child frame with the mouse will raise it automatically above
@@ -6341,7 +6350,7 @@ and/or two columns.
@end defun
The functions @code{window-state-get} and @code{window-state-put} also
-allow to exchange the contents of two live windows. The following
+allow exchanging the contents of two live windows. The following
function does precisely that:
@deffn Command window-swap-states &optional window-1 window-2 size
diff --git a/doc/man/ChangeLog.1 b/doc/man/ChangeLog.1
index ccc53810547..b34480a98e9 100644
--- a/doc/man/ChangeLog.1
+++ b/doc/man/ChangeLog.1
@@ -74,7 +74,7 @@
* emacs.1: Small fixes.
-2010-10-12 Ulrich Mueller <ulm@gentoo.org>
+2010-10-12 Ulrich Müller <ulm@gentoo.org>
* emacs.1: Update license description.
@@ -82,7 +82,7 @@
* b2m.1: Remove file.
-2010-09-25 Ulrich Mueller <ulm@gentoo.org>
+2010-09-25 Ulrich Müller <ulm@gentoo.org>
* etags.1: xz compression is now supported.
@@ -176,7 +176,7 @@
;; coding: utf-8
;; End:
- Copyright (C) 2007-2023 Free Software Foundation, Inc.
+ Copyright (C) 2007-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/doc/man/ebrowse.1 b/doc/man/ebrowse.1
index 4ce96a44852..7b03f50bc30 100644
--- a/doc/man/ebrowse.1
+++ b/doc/man/ebrowse.1
@@ -82,7 +82,7 @@ should give you access to the complete manual.
was written by Gerd Moellmann.
.
.SH COPYING
-Copyright 2008-2023 Free Software Foundation, Inc.
+Copyright 2008-2024 Free Software Foundation, Inc.
.PP
Permission is granted to make and distribute verbatim copies of this
document provided the copyright notice and this permission notice are
diff --git a/doc/man/emacs.1.in b/doc/man/emacs.1.in
index 66b0741c0f9..d7a44fb8475 100644
--- a/doc/man/emacs.1.in
+++ b/doc/man/emacs.1.in
@@ -664,7 +664,7 @@ For detailed credits and acknowledgments, see the GNU Emacs manual.
.
.
.SH COPYING
-Copyright 1995, 1999-2023 Free Software Foundation, Inc.
+Copyright 1995, 1999-2024 Free Software Foundation, Inc.
.PP
Permission is granted to make and distribute verbatim copies of this
document provided the copyright notice and this permission notice are
diff --git a/doc/man/emacsclient.1 b/doc/man/emacsclient.1
index 83c8a366f8b..75f38e4e50e 100644
--- a/doc/man/emacsclient.1
+++ b/doc/man/emacsclient.1
@@ -1,5 +1,5 @@
.\" See section COPYING for conditions for redistribution.
-.TH EMACSCLIENT 1 "2022-09-05" "GNU Emacs" "GNU"
+.TH EMACSCLIENT 1 "2023-12-23" "GNU Emacs" "GNU"
.\" NAME should be all caps, SECTION should be 1-8, maybe w/ subsection
.\" other params are allowed: see man(7), man(1)
.SH NAME
@@ -62,9 +62,11 @@ This option applies only to the next file specified.
.TP
.B \-a, \-\-alternate-editor=COMMAND
If the Emacs server is not running, run the specified shell command instead.
-This can also be specified via the ALTERNATE_EDITOR environment variable.
-If the value of ALTERNATE_EDITOR is the empty string, run "emacs \-\-daemon" to
+If the empty string is specified, run "emacs \-\-daemon" to
start Emacs in daemon mode, and try to connect to it.
+
+See also the ALTERNATE_EDITOR environment variable, over which this
+option takes precedence.
.TP
.B -c, \-\-create-frame
Create a new frame instead of trying to use the current Emacs frame.
@@ -84,7 +86,11 @@ Lisp expressions.
.TP
.B \-f, \-\-server-file=FILENAME
Use TCP configuration file FILENAME for communication.
-This can also be specified via the EMACS_SERVER_FILE environment variable.
+Relative filenames are relative to "~/.emacs.d/server/" or
+"$XDG_CONFIG_HOME/emacs/server/", and the default is "server".
+
+See also the EMACS_SERVER_FILE environment variable, over which this
+option takes precedence.
.TP
.B \-n, \-\-no-wait
Return immediately without waiting for you to "finish" the buffer in
@@ -94,12 +100,42 @@ Emacs. If combined with --eval, this option is ignored.
How long to wait, in seconds, for Emacs to respond before giving up.
The default is 0, which means to wait forever.
.TP
-.B \-nw, \-t, \-\-tty
-Open a new Emacs frame on the current terminal.
+.B \-\-parent-id=ID
+Open an
+.B emacsclient
+frame as a client frame in the parent X window with id ID.
+.TP
+.B \-q, \-\-quiet
+Do not let
+.B emacsclient
+display messages about waiting for Emacs or connecting to remote
+server sockets.
+.TP
+.B \-u, \-\-suppress-output
+Do not let
+.B emacsclient
+display results returned from the server. Mostly useful in
+combination with --eval when the evaluation performed is for
+side-effect rather than result.
.TP
.B \-s, \-\-socket-name=FILENAME
Use socket named FILENAME for communication.
-This can also be specified via the EMACS_SOCKET_NAME environment variable.
+Relative filenames are relative to "$XDG_RUNTIME_DIR/emacs/" or "$TMPDIR/".
+
+See also the EMACS_SOCKET_NAME environment variable, over which this
+option takes precedence.
+.TP
+.B \-nw, \-t, \-\-tty
+Open a new Emacs frame on the current terminal.
+.TP
+.B \-T, \-\-tramp=PREFIX
+Set PREFIX to add to filenames for Emacs to locate files on remote
+machines using TRAMP. This is mostly useful in combination with using
+the Emacs server on a remote host (either using TCP with
+--server-file, or a socket forwarded over SSH).
+
+See also the EMACSCLIENT_TRAMP environment variable, over which this
+option takes precedence.
.TP
.B \-V, \-\-version
Print version information and exit.
@@ -109,10 +145,46 @@ Print this usage information message and exit.
.SH "EXIT STATUS"
Normally, the exit status is 0. If emacsclient shuts down due to
Emacs signaling an error, the exit status is 1.
+.SH ENVIRONMENT
+.TP
+.B ALTERNATE_EDITOR
+If the Emacs server is not running, run the shell command in this
+environment variable instead. If set to the empty string, run
+"emacs \-\-daemon" to start Emacs in daemon mode, and try to connect
+to it. Will be overridden by the
+.B \-\-alternate-editor
+option, if present.
+.TP
+.B EMACSCLIENT_TRAMP
+A prefix to add to filenames, intended to allow Emacs to locate files
+on remote machines using TRAMP. Will be overridden by the
+.B \-\-tramp
+option, if present.
+.TP
+.B EMACS_SERVER_FILE
+Look in this file to discover where to find a TCP Emacs server.
+Relative filenames are relative to "~/.emacs.d/server/" or
+"$XDG_CONFIG_HOME/emacs/server/", and the
+default is "server". Will be overridden by the
+.B \-\-server-file
+option, if present.
+.TP
+.B EMACS_SOCKET_NAME
+The filename of the socket to use for communication with the Emacs server.
+Relative filenames are relative to "$XDG_RUNTIME_DIR/emacs/" or "$TMPDIR/".
+Will be overridden by the
+.B \-\-socket-name
+option, if present.
.SH "SEE ALSO"
The program is documented fully in
.IR "Using Emacs as a Server"
available via the Info system.
+
+The XDG_ environment variables are described in detail in the
+.UR https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html
+XDG Base Directory Specification
+.UE .
+
.SH AUTHOR
This manual page was originally written by Stephane Bortzmeyer
<bortzmeyer@debian.org>, for the Debian GNU/Linux system, but is not
diff --git a/doc/man/etags.1 b/doc/man/etags.1
index 27870b67d70..ba1cd768fc4 100644
--- a/doc/man/etags.1
+++ b/doc/man/etags.1
@@ -290,7 +290,7 @@ Stallman.
.BR vi ( 1 ).
.SH COPYING
-Copyright 1992, 1999, 2001-2023 Free Software Foundation, Inc.
+Copyright 1992, 1999, 2001-2024 Free Software Foundation, Inc.
.PP
Permission is granted to make and distribute verbatim copies of this
document provided the copyright notice and this permission notice are
diff --git a/doc/misc/ChangeLog.1 b/doc/misc/ChangeLog.1
index 2cd3c3f6b54..03b5037229e 100644
--- a/doc/misc/ChangeLog.1
+++ b/doc/misc/ChangeLog.1
@@ -4374,7 +4374,7 @@
* sc.texi (Getting Connected): Remove old index entries.
-2011-02-12 Ulrich Mueller <ulm@gentoo.org>
+2011-02-12 Ulrich Müller <ulm@gentoo.org>
* url.texi: Remove duplicate @dircategory (Bug#7942).
@@ -5126,7 +5126,7 @@
* gnus.texi (NoCeM): Remove.
(Startup Variables): No jingle.
-2010-09-25 Ulrich Mueller <ulm@gentoo.org>
+2010-09-25 Ulrich Müller <ulm@gentoo.org>
* woman.texi (Interface Options): xz compression is now supported.
@@ -6011,7 +6011,7 @@
(RSS Feeds): New section.
(Built-in table editor): Document M-e and M-a navigate
inside table field.
- (Stuck projects): Docment that projects identified as
+ (Stuck projects): Document that projects identified as
un-stuck will still be searched for stuck sub-projects.
(Paragraphs): Document centering.
(Creating timestamps, Agenda commands): Document new
@@ -12111,7 +12111,7 @@
;; coding: utf-8
;; End:
- Copyright (C) 1993-1999, 2001-2023 Free Software Foundation, Inc.
+ Copyright (C) 1993-1999, 2001-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/doc/misc/Makefile.in b/doc/misc/Makefile.in
index 1831bbbb73f..2841916dc89 100644
--- a/doc/misc/Makefile.in
+++ b/doc/misc/Makefile.in
@@ -1,6 +1,6 @@
### @configure_input@
-# Copyright (C) 1994, 1996-2023 Free Software Foundation, Inc.
+# Copyright (C) 1994, 1996-2024 Free Software Foundation, Inc.
# This file is part of GNU Emacs.
diff --git a/doc/misc/auth.texi b/doc/misc/auth.texi
index 7b4e8fcfb39..f51a1446170 100644
--- a/doc/misc/auth.texi
+++ b/doc/misc/auth.texi
@@ -9,7 +9,7 @@
@copying
This file describes the Emacs auth-source library.
-Copyright @copyright{} 2008--2023 Free Software Foundation, Inc.
+Copyright @copyright{} 2008--2024 Free Software Foundation, Inc.
@quotation
Permission is granted to copy, distribute and/or modify this document
diff --git a/doc/misc/autotype.texi b/doc/misc/autotype.texi
index 4110b60a774..d927816c492 100644
--- a/doc/misc/autotype.texi
+++ b/doc/misc/autotype.texi
@@ -11,7 +11,7 @@
@c @cindex autotypist
@copying
-Copyright @copyright{} 1994--1995, 1999, 2001--2023 Free Software
+Copyright @copyright{} 1994--1995, 1999, 2001--2024 Free Software
Foundation, Inc.
@quotation
@@ -276,10 +276,10 @@ empty file is visited. This is accomplished by putting
@code{auto-insert-alist}. The @sc{car} of each element of this list
is either a mode name, making the element applicable when a buffer is
in that mode, or a string, which is a regexp matched against a
-buffer's file name (the latter allows to distinguish between different
-kinds of files that have the same mode in Emacs). The @sc{car} of an
-element may also be a cons cell, consisting of mode name or regexp, as
-above, and an additional descriptive string.
+buffer's file name (the latter enables you to distinguish between
+different kinds of files that have the same mode in Emacs). The
+@sc{car} of an element may also be a cons cell, consisting of mode
+name or regexp, as above, and an additional descriptive string.
When a matching element is found, the @sc{cdr} says what to do. It may
be a string, which is a file name, whose contents are to be inserted, if
diff --git a/doc/misc/bovine.texi b/doc/misc/bovine.texi
index 10b1a1fc654..5cef9ffbb93 100644
--- a/doc/misc/bovine.texi
+++ b/doc/misc/bovine.texi
@@ -24,7 +24,7 @@
@c %**end of header
@copying
-Copyright @copyright{} 1999--2004, 2012--2023 Free Software Foundation,
+Copyright @copyright{} 1999--2004, 2012--2024 Free Software Foundation,
Inc.
@quotation
diff --git a/doc/misc/calc.texi b/doc/misc/calc.texi
index 5064f76e7b8..7ae338307a5 100644
--- a/doc/misc/calc.texi
+++ b/doc/misc/calc.texi
@@ -95,7 +95,7 @@ This file documents Calc, the GNU Emacs calculator, included with
GNU Emacs @value{EMACSVER}.
@end ifnotinfo
-Copyright @copyright{} 1990--1991, 2001--2023 Free Software Foundation,
+Copyright @copyright{} 1990--1991, 2001--2024 Free Software Foundation,
Inc.
@quotation
@@ -1196,7 +1196,7 @@ bent, contributed ideas and algorithms for a number of Calc features
including modulo forms, primality testing, and float-to-fraction conversion.
Units were added at the eager insistence of Mass Sivilotti. Later,
-Ulrich Mueller at CERN and Przemek Klosowski at NIST provided invaluable
+Ulrich Müller at CERN and Przemek Klosowski at NIST provided invaluable
expert assistance with the units table. As far as I can remember, the
idea of using algebraic formulas and variables to represent units dates
back to an ancient article in Byte magazine about muMath, an early
@@ -11954,7 +11954,7 @@ trail pointer in various ways.
@cindex Retrieving previous results
The @kbd{t y} (@code{calc-trail-yank}) command reads the selected value in
the trail and pushes it onto the Calculator stack. It allows you to
-re-use any previously computed value without retyping. With a numeric
+reuse any previously computed value without retyping. With a numeric
prefix argument @var{n}, it yanks the value @var{n} lines above the current
trail pointer.
@@ -28032,7 +28032,7 @@ unit name on the stack and then reduce it to base units with @kbd{u b}.
The @kbd{u e} (@code{calc-explain-units}) command displays an English
description of the units of the expression on the stack. For example,
for the expression @samp{62 km^2 g / s^2 mol K}, the description is
-``Square-Kilometer Gram per (Second-squared Mole Degree-Kelvin).'' This
+``Square-Kilometer Gram per (Second-squared Mole Kelvin).'' This
command uses the English descriptions that appear in the righthand
column of the Units Table.
@@ -28066,8 +28066,8 @@ Canadian (@code{galC}), and British (@code{galUK}) definitions. Also,
note that @code{oz} is a standard ounce of mass, @code{ozt} is a Troy
ounce, and @code{ozfl} is a fluid ounce.
-The temperature units corresponding to degrees Kelvin and Centigrade
-(Celsius) are the same in this table, since most units commands treat
+The temperature units corresponding to Kelvin and degree Celsius
+are the same in this table, since most units commands treat
temperatures as being relative. The @code{calc-convert-temperature}
command has special rules for handling the different absolute magnitudes
of the various temperature scales.
diff --git a/doc/misc/cc-mode.texi b/doc/misc/cc-mode.texi
index 4ab95798468..7f299180fc6 100644
--- a/doc/misc/cc-mode.texi
+++ b/doc/misc/cc-mode.texi
@@ -167,7 +167,7 @@ CC Mode
@copying
This manual is for CC Mode in Emacs.
-Copyright @copyright{} 1995--2023 Free Software Foundation, Inc.
+Copyright @copyright{} 1995--2024 Free Software Foundation, Inc.
@quotation
Permission is granted to copy, distribute and/or modify this document
@@ -4507,6 +4507,13 @@ languages are syntactically equivalent to classes. Note however that
the keyword @code{class} is meaningless in C and Objective-C.}.
Similarly, line 18 is assigned @code{class-close} syntax.
+Note that @code{class-open} and @code{class-close} syntactic elements
+have two anchor points. The first is the position of the beginning of
+the statement, the second is the position of the keyword which defines
+the construct (e.g. @code{class}). These are usually the same
+position, but differ when the statement starts off with
+@code{template} (C++ Mode) or @code{generic} (Java Mode) or similar.
+
@ssindex inher-intro
@ssindex inher-cont
Line 2 introduces the inheritance list for the class so it is assigned
diff --git a/doc/misc/cl.texi b/doc/misc/cl.texi
index 5de33350f4f..65a29d955bc 100644
--- a/doc/misc/cl.texi
+++ b/doc/misc/cl.texi
@@ -7,7 +7,7 @@
@copying
This file documents the GNU Emacs Common Lisp emulation package.
-Copyright @copyright{} 1993, 2001--2023 Free Software Foundation, Inc.
+Copyright @copyright{} 1993, 2001--2024 Free Software Foundation, Inc.
@quotation
Permission is granted to copy, distribute and/or modify this document
@@ -55,6 +55,7 @@ modify this GNU manual.''
@menu
* Overview:: Basics, usage, organization, naming conventions.
+* Printing:: Human friendly printing with @code{cl-prin1}.
* Program Structure:: Arglists, @code{cl-eval-when}.
* Predicates:: Type predicates and equality predicates.
* Control Structure:: Assignment, conditionals, blocks, looping.
@@ -258,6 +259,160 @@ and @code{:key} is not used.
@noindent
[3] Only for one sequence argument or two list arguments.
+@node Printing
+@chapter Printing
+
+@noindent
+This chapter describes some enhancements to Emacs Lisp's
+@dfn{printing}, the action of representing Lisp objects in text form.
+The functions documented here are intended to produce output more for
+human readers than the standard printing functions such as
+@code{prin1} and @code{princ} (@pxref{Output Functions,,,elisp,GNU
+Emacs Lisp Reference Manual}).
+
+Several of these functions have a parameter @var{stream}; this
+specifies what to do with the characters printing produces. For
+example, it might be a buffer, a marker, @code{nil} (meaning use
+standard output), or @code{t} (use the echo area). @xref{Output
+Streams,,,elisp,GNU Emacs Lisp Reference Manual}, for a full
+description.
+
+@defvar cl-print-readably
+When this variable is non-@code{nil}, @code{cl-prin1} and other
+functions described here try to produce output which can later be read
+by the Lisp reader (@pxref{Input Functions,,,elisp,GNU Emacs Lisp
+Reference Manual}).
+@end defvar
+
+@defvar cl-print-compiled
+This variable controls how to print byte-compiled functions. Valid
+values are:
+@table @code
+@item nil
+The default: Just an internal hex identifier is printed.
+@item static
+The internal hex identifier together with the function's constant
+vector are printed.
+@item disassemble
+The byte code gets disassembled.
+@item raw
+The raw form of the function is printed by @code{prin1}.
+@end table
+
+Sometimes, a button is set on the output to allow you to disassemble
+the function. See @code{cl-print-compile-button}.
+@end defvar
+
+@defvar cl-print-compile-button
+When this variable is non-@code{nil} and a byte-compiled function has
+been printed to a buffer, you can click with the mouse or type
+@key{RET} on that output to disassemble the code. This doesn't apply
+when @code{cl-print-compiled} is set to @code{disassemble}.
+@end defvar
+
+@defvar cl-print-string-length
+The maximum length of a string to print before abbreviating it. A
+value of @code{nil}, the default, means no limit.
+
+When the CL printing functions abbreviate a string, they print the
+first @code{cl-print-string-length} characters of the string, followed
+by ``@enddots{}''. When the printing is to a buffer, you can click
+with the mouse or type @key{RET} on this ellipsis to expand the
+string.
+
+This variable has effect only in the @code{cl-prin*} functions, not in
+primitives such as @code{prin1}.
+@end defvar
+
+@defun cl-prin1 object &option stream
+@code{cl-print1} prints @var{object} on @var{stream} (see above)
+according to its type and the settings described above. The variables
+@code{print-length} and @code{print-level} and the other standard
+Emacs settings also affect the printing (@pxref{Output
+Variables,,,elisp,GNU Emacs Lisp Reference Manual}).
+@end defun
+
+@defun cl-prin1-to-string object
+This function is like @code{cl-prin1}, except the output characters
+are returned as a string from this function rather than being passed
+to a stream.
+@end defun
+
+@defun cl-print-to-string-with-limit print-function value limit
+This function returns a string containing a printed representation of
+@var{value}. It attempts to get the length of the returned string
+under @var{limit} characters with successively more restrictive
+settings of @code{print-level}, @code{print-length}, and
+@code{cl-print-string-length}. It uses @var{print-function} to print,
+a function which should take the arguments @var{value} and a stream
+(see above), and which should respect @code{print-length},
+@code{print-level}, and @code{cl-print-string-length}. @var{limit}
+may be @code{nil} or zero, in which case @var{print-function} will be
+called with these settings bound to @code{nil}; it can also be
+@code{t}, in which case @var{print-function} will be called with their
+current values.
+
+Use this function with @code{cl-prin1} to print an object, possibly
+abbreviating it with one or more ellipses to fit within the size
+limit.
+@end defun
+
+@defun cl-print-object object stream
+This function prints @var{object} on @var{stream} (see above). It is
+actually a @code{cl-defgeneric} (@pxref{Generic Functions,,,elisp,GNU
+Emacs Lisp Reference Manual}), which is defined for several types of
+@var{object}. Normally, you just call @code{cl-prin1} to print an
+@var{object} rather than calling this function directly.
+
+You can write @code{cl-print-object} @code{cl-defmethod}s for other
+types of @var{object}, thus extending @code{cl-prin1}. If such a
+method uses ellipses, you should also write a
+@code{cl-print-object-contents} method for the same type. For
+examples of these methods, see @file{emacs-lisp/cl-print.el} in the
+Emacs source directory.
+@end defun
+
+@defun cl-print-object-contents object start stream
+This function replaces an ellipsis in @var{stream} beginning at
+@var{start} with the text from the partially printed @var{object} it
+represents. It is also a @code{cl-defgeneric} defined for several
+types of @var{object}. @var{stream} is a buffer containing the text
+with the ellipsis. @var{start} specifies the starting position of the
+ellipsis in a manner dependent on the type; it will have been obtained
+from a text property on the ellipsis, having been put there by
+@code{cl-print-insert-ellipsis}.
+@end defun
+
+@defun cl-print-insert-ellipsis object start stream
+This function prints an ellipsis (``@dots{}'') to @var{stream} (see
+above). When @var{stream} is a buffer, the ellipsis will be given the
+@code{cl-print-ellipsis} text property. The value of the text
+property will contain state (including @var{start}) in order to print
+the elided part of @var{object} later. @var{start} should be nil if
+the whole @var{object} is being elided, otherwise it should be an
+index or other pointer into the internals of @var{object} which can be
+passed to `cl-print-object-contents' at a later time.
+@end defun
+
+@defvar cl-print-expand-ellipsis-function
+This variable holds a function which expands an ellipsis in the
+current buffer. The function takes four arguments: @var{begin} and
+@var{end}, which are the bounds of the ellipsis; @var{value}, which is
+the value of the @code{cl-print-ellipsis} text property on the
+ellipsis (typically set earlier by @code{cl-prin1}); and
+@var{line-length}, the desired maximum length of the output. Its
+return value is the buffer position after the expanded text.
+@end defvar
+
+@deffn Command cl-print-expand-ellipsis &optional button
+This command expands the ellipsis at point. Non-interactively, if
+@var{button} is non-@code{nil}, it should be either a buffer position
+or a button made by @code{cl-print-insert-ellipsis}
+(@pxref{Buttons,,,elisp,GNU Emacs Lisp Reference Manual}), which
+indicates the position of the ellipsis. The return value is the
+buffer position after the expanded text.
+@end deffn
+
@node Program Structure
@chapter Program Structure
diff --git a/doc/misc/dbus.texi b/doc/misc/dbus.texi
index 2bd6b9556c8..28ee64d6b89 100644
--- a/doc/misc/dbus.texi
+++ b/doc/misc/dbus.texi
@@ -10,7 +10,7 @@
@syncodeindex fn cp
@copying
-Copyright @copyright{} 2007--2023 Free Software Foundation, Inc.
+Copyright @copyright{} 2007--2024 Free Software Foundation, Inc.
@quotation
Permission is granted to copy, distribute and/or modify this document
@@ -1418,6 +1418,9 @@ The name @var{service} does not exist on the bus.
@item :not-owner
We are not an owner of the name @var{service}.
@end table
+
+When @var{service} is not a known name but a unique name, the function
+returns nil.
@end defun
When a name has been chosen, Emacs can offer its own methods, which
diff --git a/doc/misc/dired-x.texi b/doc/misc/dired-x.texi
index baddf7abc45..4cad016a0f6 100644
--- a/doc/misc/dired-x.texi
+++ b/doc/misc/dired-x.texi
@@ -20,7 +20,7 @@
@comment %**end of header (This is for running Texinfo on a region.)
@copying
-Copyright @copyright{} 1994--1995, 1999, 2001--2023 Free Software
+Copyright @copyright{} 1994--1995, 1999, 2001--2024 Free Software
Foundation, Inc.
@quotation
diff --git a/doc/misc/ebrowse.texi b/doc/misc/ebrowse.texi
index b6c9d3dabe4..dca6266d8ae 100644
--- a/doc/misc/ebrowse.texi
+++ b/doc/misc/ebrowse.texi
@@ -11,7 +11,7 @@
@copying
This file documents Ebrowse, a C++ class browser for GNU Emacs.
-Copyright @copyright{} 2000--2023 Free Software Foundation, Inc.
+Copyright @copyright{} 2000--2024 Free Software Foundation, Inc.
@quotation
Permission is granted to copy, distribute and/or modify this document
diff --git a/doc/misc/ede.texi b/doc/misc/ede.texi
index d49d2296aa7..15f7a329803 100644
--- a/doc/misc/ede.texi
+++ b/doc/misc/ede.texi
@@ -6,7 +6,7 @@
@copying
This file describes EDE, the Emacs Development Environment.
-Copyright @copyright{} 1998--2001, 2004--2005, 2008--2023 Free Software
+Copyright @copyright{} 1998--2001, 2004--2005, 2008--2024 Free Software
Foundation, Inc.
@quotation
@@ -1515,7 +1515,8 @@ Make sure placeholder @var{THIS} is replaced with the real thing, and pass throu
@table @code
@item eieio-speedbar-directory-button
@table @code
-@item @xref{ede-project-placeholder}.
+@item ede-project-placeholder
+@xref{ede-project-placeholder}.
@table @code
@item ede-project
@table @asis
@@ -1801,9 +1802,11 @@ Commit change to local variables in @var{PROJ}.
@table @code
@item eieio-speedbar-directory-button
@table @code
-@item @xref{ede-project-placeholder}.
+@item ede-project-placeholder
+@xref{ede-project-placeholder}.
@table @code
-@item @xref{ede-project}.
+@item ede-project
+@xref{ede-project}.
@table @code
@item ede-cpp-root-project
No children
@@ -1923,9 +1926,11 @@ This knows details about or source tree.
@table @code
@item eieio-speedbar-directory-button
@table @code
-@item @xref{ede-project-placeholder}.
+@item ede-project-placeholder
+@xref{ede-project-placeholder}.
@table @code
-@item @xref{ede-project}.
+@item ede-project
+@xref{ede-project}.
@table @code
@item ede-simple-project
No children
@@ -1953,9 +1958,11 @@ Commit any change to @var{PROJ} to its file.
@table @code
@item eieio-speedbar-directory-button
@table @code
-@item @xref{ede-project-placeholder}.
+@item ede-project-placeholder
+@xref{ede-project-placeholder}.
@table @code
-@item @xref{ede-project}.
+@item ede-project
+@xref{ede-project}.
@table @code
@item ede-simple-base-project
No children
@@ -1983,9 +1990,11 @@ This one project could control a tree of subdirectories.
@table @code
@item eieio-speedbar-directory-button
@table @code
-@item @xref{ede-project-placeholder}.
+@item ede-project-placeholder
+@xref{ede-project-placeholder}.
@table @code
-@item @xref{ede-project}.
+@item ede-project
+@xref{ede-project}.
@table @code
@item ede-proj-project
No children
@@ -2173,9 +2182,11 @@ Commit change to local variables in @var{PROJ}.
@table @code
@item eieio-speedbar-directory-button
@table @code
-@item @xref{ede-project-placeholder}.
+@item ede-project-placeholder
+@xref{ede-project-placeholder}.
@table @code
-@item @xref{ede-project}.
+@item ede-project
+@xref{ede-project}.
@table @code
@item project-am-makefile
No children
@@ -2215,9 +2226,11 @@ buffer being in order to provide a smart default target type.
@table @code
@item eieio-speedbar-directory-button
@table @code
-@item @xref{ede-project-placeholder}.
+@item ede-project-placeholder
+@xref{ede-project-placeholder}.
@table @code
-@item @xref{ede-project}.
+@item ede-project
+@xref{ede-project}.
@table @code
@item ede-step-project
No children
@@ -2577,7 +2590,8 @@ Retrieves the slot @code{menu} from an object of class @code{ede-target}
@table @code
@item eieio-speedbar-directory-button
@table @code
-@item @xref{ede-target}.
+@item ede-target
+@xref{ede-target}.
@table @code
@item ede-proj-target
@table @asis
@@ -2766,9 +2780,11 @@ sources variable.
@table @code
@item eieio-speedbar-directory-button
@table @code
-@item @xref{ede-target}.
+@item ede-target
+@xref{ede-target}.
@table @code
-@item @xref{ede-proj-target}.
+@item ede-proj-target
+@xref{ede-proj-target}.
@table @code
@item ede-proj-target-makefile
@table @asis
@@ -2864,11 +2880,14 @@ Use @var{CONFIGURATION} as the current configuration to query.
@table @code
@item eieio-speedbar-directory-button
@table @code
-@item @xref{ede-target}.
+@item ede-target
+@xref{ede-target}.
@table @code
-@item @xref{ede-proj-target}.
+@item ede-proj-target
+@xref{ede-proj-target}.
@table @code
-@item @xref{ede-proj-target-makefile}.
+@item ede-proj-target-makefile
+@xref{ede-proj-target-makefile}.
@table @code
@item semantic-ede-proj-target-grammar
No children
@@ -2918,11 +2937,14 @@ Argument @var{THIS} is the target that should insert stuff.
@table @code
@item eieio-speedbar-directory-button
@table @code
-@item @xref{ede-target}.
+@item ede-target
+@xref{ede-target}.
@table @code
-@item @xref{ede-proj-target}.
+@item ede-proj-target
+@xref{ede-proj-target}.
@table @code
-@item @xref{ede-proj-target-makefile}.
+@item ede-proj-target-makefile
+@xref{ede-proj-target-makefile}.
@table @code
@item ede-proj-target-makefile-objectcode
@table @asis
@@ -2980,13 +3002,17 @@ Argument @var{THIS} is the target to get sources from.
@table @code
@item eieio-speedbar-directory-button
@table @code
-@item @xref{ede-target}.
+@item ede-target
+@xref{ede-target}.
@table @code
-@item @xref{ede-proj-target}.
+@item ede-proj-target
+@xref{ede-proj-target}.
@table @code
-@item @xref{ede-proj-target-makefile}.
+@item ede-proj-target-makefile
+@xref{ede-proj-target-makefile}.
@table @code
-@item @xref{ede-proj-target-makefile-objectcode}.
+@item ede-proj-target-makefile-objectcode
+@xref{ede-proj-target-makefile-objectcode}.
@table @code
@item ede-proj-target-makefile-archive
No children
@@ -3023,13 +3049,17 @@ Makefile.am generator, so use it to add this important bin program.
@table @code
@item eieio-speedbar-directory-button
@table @code
-@item @xref{ede-target}.
+@item ede-target
+@xref{ede-target}.
@table @code
-@item @xref{ede-proj-target}.
+@item ede-proj-target
+@xref{ede-proj-target}.
@table @code
-@item @xref{ede-proj-target-makefile}.
+@item ede-proj-target-makefile
+@xref{ede-proj-target-makefile}.
@table @code
-@item @xref{ede-proj-target-makefile-objectcode}.
+@item ede-proj-target-makefile-objectcode
+@xref{ede-proj-target-makefile-objectcode}.
@table @code
@item ede-proj-target-makefile-program
@table @asis
@@ -3102,15 +3132,20 @@ Insert bin_PROGRAMS variables needed by target @var{THIS}.
@table @code
@item eieio-speedbar-directory-button
@table @code
-@item @xref{ede-target}.
+@item ede-target
+@xref{ede-target}.
@table @code
-@item @xref{ede-proj-target}.
+@item ede-proj-target
+@xref{ede-proj-target}.
@table @code
-@item @xref{ede-proj-target-makefile}.
+@item ede-proj-target-makefile
+@xref{ede-proj-target-makefile}.
@table @code
-@item @xref{ede-proj-target-makefile-objectcode}.
+@item ede-proj-target-makefile-objectcode
+@xref{ede-proj-target-makefile-objectcode}.
@table @code
-@item @xref{ede-proj-target-makefile-program}.
+@item ede-proj-target-makefile-program
+@xref{ede-proj-target-makefile-program}.
@table @code
@item ede-proj-target-makefile-shared-object
No children
@@ -3162,11 +3197,14 @@ Makefile.am generator, so use it to add this important bin program.
@table @code
@item eieio-speedbar-directory-button
@table @code
-@item @xref{ede-target}.
+@item ede-target
+@xref{ede-target}.
@table @code
-@item @xref{ede-proj-target}.
+@item ede-proj-target
+@xref{ede-proj-target}.
@table @code
-@item @xref{ede-proj-target-makefile}.
+@item ede-proj-target-makefile
+@xref{ede-proj-target-makefile}.
@table @code
@item ede-proj-target-elisp
@table @asis
@@ -3238,13 +3276,17 @@ is found, such as a @code{-version} variable, or the standard header.
@table @code
@item eieio-speedbar-directory-button
@table @code
-@item @xref{ede-target}.
+@item ede-target
+@xref{ede-target}.
@table @code
-@item @xref{ede-proj-target}.
+@item ede-proj-target
+@xref{ede-proj-target}.
@table @code
-@item @xref{ede-proj-target-makefile}.
+@item ede-proj-target-makefile
+@xref{ede-proj-target-makefile}.
@table @code
-@item @xref{ede-proj-target-elisp}.
+@item ede-proj-target-elisp
+@xref{ede-proj-target-elisp}.
@table @code
@item ede-proj-target-elisp-autoloads
No children
@@ -3353,11 +3395,14 @@ sources variable.
@table @code
@item eieio-speedbar-directory-button
@table @code
-@item @xref{ede-target}.
+@item ede-target
+@xref{ede-target}.
@table @code
-@item @xref{ede-proj-target}.
+@item ede-proj-target
+@xref{ede-proj-target}.
@table @code
-@item @xref{ede-proj-target-makefile}.
+@item ede-proj-target-makefile
+@xref{ede-proj-target-makefile}.
@table @code
@item ede-proj-target-makefile-miscelaneous
No children
@@ -3409,11 +3454,14 @@ Return a list of files which @var{THIS} target depends on.
@table @code
@item eieio-speedbar-directory-button
@table @code
-@item @xref{ede-target}.
+@item ede-target
+@xref{ede-target}.
@table @code
-@item @xref{ede-proj-target}.
+@item ede-proj-target
+@xref{ede-proj-target}.
@table @code
-@item @xref{ede-proj-target-makefile}.
+@item ede-proj-target-makefile
+@xref{ede-proj-target-makefile}.
@table @code
@item ede-proj-target-makefile-info
No children
@@ -3495,9 +3543,11 @@ when working in Automake mode.
@table @code
@item eieio-speedbar-directory-button
@table @code
-@item @xref{ede-target}.
+@item ede-target
+@xref{ede-target}.
@table @code
-@item @xref{ede-proj-target}.
+@item ede-proj-target
+@xref{ede-proj-target}.
@table @code
@item ede-proj-target-scheme
No children
@@ -3539,7 +3589,8 @@ Tweak the configure file (current buffer) to accommodate @var{THIS}.
@table @code
@item eieio-speedbar-directory-button
@table @code
-@item @xref{ede-target}.
+@item ede-target
+@xref{ede-target}.
@table @code
@item project-am-target
@table @asis
@@ -3577,9 +3628,11 @@ Edit the target associated with this file.
@table @code
@item eieio-speedbar-directory-button
@table @code
-@item @xref{ede-target}.
+@item ede-target
+@xref{ede-target}.
@table @code
-@item @xref{project-am-target}.
+@item project-am-target
+@xref{project-am-target}.
@table @code
@item project-am-objectcode
@table @asis
@@ -3622,11 +3675,14 @@ There are no default header files.
@table @code
@item eieio-speedbar-directory-button
@table @code
-@item @xref{ede-target}.
+@item ede-target
+@xref{ede-target}.
@table @code
-@item @xref{project-am-target}.
+@item project-am-target
+@xref{project-am-target}.
@table @code
-@item @xref{project-am-objectcode}.
+@item project-am-objectcode
+@xref{project-am-objectcode}.
@table @code
@item project-am-program
No children
@@ -3660,9 +3716,11 @@ Additional LD args.
@table @code
@item eieio-speedbar-directory-button
@table @code
-@item @xref{ede-target}.
+@item ede-target
+@xref{ede-target}.
@table @code
-@item @xref{project-am-target}.
+@item project-am-target
+@xref{project-am-target}.
@table @code
@item @w{project-am-header.}
@table @code
@@ -3693,9 +3751,11 @@ Return the default macro to 'edit' for this object.
@table @code
@item eieio-speedbar-directory-button
@table @code
-@item @xref{ede-target}.
+@item ede-target
+@xref{ede-target}.
@table @code
-@item @xref{project-am-target}.
+@item project-am-target
+@xref{project-am-target}.
@table @code
@item @w{project-am-header.}
@table @code
@@ -3726,9 +3786,11 @@ Return the default macro to 'edit' for this object.
@table @code
@item eieio-speedbar-directory-button
@table @code
-@item @xref{ede-target}.
+@item ede-target
+@xref{ede-target}.
@table @code
-@item @xref{project-am-target}.
+@item project-am-target
+@xref{project-am-target}.
@table @code
@item project-am-lisp
No children
@@ -3756,9 +3818,11 @@ Return the default macro to 'edit' for this object.
@table @code
@item eieio-speedbar-directory-button
@table @code
-@item @xref{ede-target}.
+@item ede-target
+@xref{ede-target}.
@table @code
-@item @xref{project-am-target}.
+@item project-am-target
+@xref{project-am-target}.
@table @code
@item project-am-texinfo
No children
@@ -3808,9 +3872,11 @@ files in the project.
@table @code
@item eieio-speedbar-directory-button
@table @code
-@item @xref{ede-target}.
+@item ede-target
+@xref{ede-target}.
@table @code
-@item @xref{project-am-target}.
+@item project-am-target
+@xref{project-am-target}.
@table @code
@item project-am-man
No children
@@ -4071,7 +4137,8 @@ Tweak the configure file (current buffer) to accommodate @var{THIS}.
@table @code
@item eieio-instance-inheritor
@table @code
-@item @xref{ede-compilation-program}.
+@item ede-compilation-program
+@xref{ede-compilation-program}.
@table @code
@item ede-compiler
@table @asis
@@ -4179,9 +4246,11 @@ Return a string based on @var{THIS} representing a make object variable.
@table @code
@item eieio-instance-inheritor
@table @code
-@item @xref{ede-compilation-program}.
+@item ede-compilation-program
+@xref{ede-compilation-program}.
@table @code
-@item @xref{ede-compiler}.
+@item ede-compiler
+@xref{ede-compiler}.
@table @code
@item ede-object-compiler
No children
@@ -4222,7 +4291,8 @@ Insert variables needed by the compiler @var{THIS}.
@table @code
@item eieio-instance-inheritor
@table @code
-@item @xref{ede-compilation-program}.
+@item ede-compilation-program
+@xref{ede-compilation-program}.
@table @code
@item ede-linker
No children
diff --git a/doc/misc/ediff.texi b/doc/misc/ediff.texi
index ce6cb8c9bd6..e8ecb218674 100644
--- a/doc/misc/ediff.texi
+++ b/doc/misc/ediff.texi
@@ -26,7 +26,7 @@
This file documents Ediff, a comprehensive visual interface to Unix diff
and patch utilities.
-Copyright @copyright{} 1995--2023 Free Software Foundation, Inc.
+Copyright @copyright{} 1995--2024 Free Software Foundation, Inc.
@quotation
Permission is granted to copy, distribute and/or modify this document
@@ -1368,13 +1368,13 @@ the variable @code{ediff-help-message}, which is local to
@node Window and Frame Configuration
@section Window and Frame Configuration
-On a non-windowing display, Ediff sets things up in one frame, splitting
+On a non-graphical display, Ediff sets things up in one frame, splitting
it between a small control window and the windows for buffers A, B, and C@.
The split between these windows can be horizontal or
vertical, which can be changed interactively by typing @kbd{|} while the
cursor is in the control window.
-On a window display, Ediff sets up a dedicated frame for Ediff Control
+On a graphical display, Ediff sets up a dedicated frame for Ediff Control
Panel and then it chooses windows as follows: If one of the buffers
is invisible, it is displayed in the currently selected frame. If
a buffer is visible, it is displayed in the frame where it is visible.
@@ -1477,7 +1477,7 @@ The multiframe setup is done by the
@code{ediff-setup-windows-multiframe} function, which is the default on
windowing displays. The plain setup, one where all windows are always
in one frame, is done by @code{ediff-setup-windows-plain}, which is the
-default on a non-windowing display (or in an xterm window). In fact,
+default on a non-graphical display (or in an xterm window). In fact,
under Emacs, you can switch freely between these two setups by executing
the command @code{ediff-toggle-multiframe} using the Minibuffer of the
Menubar.
diff --git a/doc/misc/edt.texi b/doc/misc/edt.texi
index 9146ebdb6d8..1a835f79d7f 100644
--- a/doc/misc/edt.texi
+++ b/doc/misc/edt.texi
@@ -6,7 +6,7 @@
@copying
This file documents the EDT emulation package for Emacs.
-Copyright @copyright{} 1986, 1992, 1994--1995, 1999--2023 Free Software
+Copyright @copyright{} 1986, 1992, 1994--1995, 1999--2024 Free Software
Foundation, Inc.
@quotation
diff --git a/doc/misc/efaq-w32.texi b/doc/misc/efaq-w32.texi
index 71d4b4e1fc2..9756345042e 100644
--- a/doc/misc/efaq-w32.texi
+++ b/doc/misc/efaq-w32.texi
@@ -15,7 +15,7 @@ Answers to Frequently asked Questions about using Emacs on Microsoft Windows.
@include emacsver.texi
@copying
-Copyright @copyright{} 2008, 2010--2023 Free Software Foundation, Inc.
+Copyright @copyright{} 2008, 2010--2024 Free Software Foundation, Inc.
@quotation
This list of frequently asked questions about GNU Emacs on MS Windows
@@ -1168,15 +1168,15 @@ binary and the Ctrl-M characters are significant.
@subsection CR/LF translation by file system
@cindex line ends, determining by filesystem
@cindex binary files, determining by filesystem
-@vindex untranslated-filesystem-list
-@findex add-untranslated-filesystem
-@findex remove-untranslated-filesystem
+@vindex w32-untranslated-filesystem-list
+@findex w32-add-untranslated-filesystem
+@findex w32-remove-untranslated-filesystem
-The variable @code{untranslated-filesystem-list} defines whole
+The variable @code{w32-untranslated-filesystem-list} defines whole
directory trees that should not have CR/LF autodetection performed on
them. The list can be manipulated with the functions
-@code{add-untranslated-filesystem} and
-@code{remove-untranslated-filesystem}. With auto-detection in
+@code{w32-add-untranslated-filesystem} and
+@code{w32-remove-untranslated-filesystem}. With auto-detection in
recent versions of Emacs, this is seldom useful for existing files,
but can still be used to influence the choice of line ends for newly
created files.
diff --git a/doc/misc/efaq.texi b/doc/misc/efaq.texi
index 0a0c375d273..25e6551f34b 100644
--- a/doc/misc/efaq.texi
+++ b/doc/misc/efaq.texi
@@ -8,7 +8,7 @@
@include emacsver.texi
@copying
-Copyright @copyright{} 2001--2023 Free Software Foundation, Inc.@*
+Copyright @copyright{} 2001--2024 Free Software Foundation, Inc.@*
Copyright @copyright{} 1994--2000 Reuven M. Lerner@*
Copyright @copyright{} 1992--1993 Steven Byrnes@*
Copyright @copyright{} 1990--1992 Joseph Brian Wells@*
@@ -1121,8 +1121,8 @@ feature, when you need to insert a single special character.
allows selection of one of the previous kills.
@item
-New minor mode @code{repeat-mode} allows to repeat commands with fewer
-keystrokes.
+New minor mode @code{repeat-mode} enables repeating commands with
+fewer keystrokes.
@item
Among the many internal changes in this release, we would like to
@@ -1721,7 +1721,7 @@ is better to write ``Emacs and XEmacs.''
* Editing MS-DOS files::
* Filling paragraphs with a single space::
* Escape sequences in shell output::
-* Fullscreen mode on MS-Windows::
+* Start Emacs maximized::
* Emacs in a Linux console::
@end menu
@@ -2832,9 +2832,12 @@ This may be inconvenient in some setups, so Emacs has mechanisms for
changing the locations of all these files.
@table @code
-@item auto-save-file-name-transforms (@pxref{Auto-Saving,,,elisp, GNU Emacs Lisp Reference Manual}).
-@item lock-file-name-transforms (@pxref{File Locks,,,elisp, GNU Emacs Lisp Reference Manual}).
-@item backup-directory-alist (@pxref{Making Backups,,,elisp, GNU Emacs Lisp Reference Manual}).
+@item auto-save-file-name-transforms
+(@pxref{Auto-Saving,,,elisp, GNU Emacs Lisp Reference Manual}).
+@item lock-file-name-transforms
+(@pxref{File Locks,,,elisp, GNU Emacs Lisp Reference Manual}).
+@item backup-directory-alist
+(@pxref{Making Backups,,,elisp, GNU Emacs Lisp Reference Manual}).
@end table
For instance, to write all these things to
@@ -3110,45 +3113,24 @@ prints using ANSI color escape sequences. Emacs includes the
@code{ansi-color} package, which lets Shell mode recognize these
escape sequences. It is enabled by default.
-@node Fullscreen mode on MS-Windows
-@section How can I start Emacs in fullscreen mode on MS-Windows?
+@node Start Emacs maximized
+@section How can I start Emacs in full screen?
@cindex Maximize frame
@cindex Fullscreen mode
-Beginning with Emacs 24.4 either run Emacs with the @samp{--maximized}
-command-line option or put the following form in your init file
-(@pxref{Setting up a customization file}):
-
-@lisp
-(add-hook 'emacs-startup-hook 'toggle-frame-maximized)
-@end lisp
-
-With older versions use the function @code{w32-send-sys-command}. For
-example, you can put the following in your init file:
+Run Emacs with the @samp{--maximized} command-line option or put the
+following form in your early init file (@pxref{Early Init File,,,
+emacs, The GNU Emacs Manual}).
@lisp
-(add-hook 'emacs-startup-hook
- (lambda () (w32-send-sys-command ?\xF030)))
-@end lisp
-
-To avoid the slightly distracting visual effect of Emacs starting with
-its default frame size and then growing to fullscreen, you can add an
-@samp{Emacs.Geometry} entry to the Windows Registry settings. @xref{X
-Resources,,, emacs, The GNU Emacs Manual}. To compute the correct
-values for width and height you use in the Registry settings, first
-maximize the Emacs frame and then evaluate @code{(frame-height)} and
-@code{(frame-width)} with @kbd{M-:}.
-
-Alternatively, you can avoid the visual effect of Emacs changing its
-frame size entirely in your init file (i.e., without using the
-Registry), like this:
-
-@lisp
-(setq frame-resize-pixelwise t)
-(set-frame-position nil 0 0)
-(set-frame-size nil (display-pixel-width) (display-pixel-height) t)
+(push '(fullscreen . maximized) default-frame-alist)
@end lisp
+Note that while some customizations of @code{default-frame-alist}
+could have undesirable effects when modified in the early init file,
+it is okay to do it in this particular case. Adding it to the normal
+init file will also work, but leads to a visible resizing of the
+window that some find distracting.
@node Emacs in a Linux console
@section How can I alleviate the limitations of the Linux console?
@@ -3156,9 +3138,9 @@ Registry), like this:
If possible, we recommend running Emacs inside @command{fbterm}, when
in a Linux console. This brings the Linux console on par with most
-terminal emulators under X. To do this, install @command{fbterm}, for
-example with the package manager of your GNU/Linux distribution, and
-execute the command
+terminal emulators under X@. To do this, install @command{fbterm},
+for example with the package manager of your GNU/Linux distribution,
+and execute the command
@example
$ fbterm
@@ -3301,12 +3283,12 @@ Emacs has an inherent fixed limitation on the size of buffers. This
limit is stricter than the maximum size of objects supported by other
programs on the same architecture.
-The maximum buffer size on 32-bit machines is 512 MBytes. If Emacs
-was built using the @code{--with-wide-int} flag, the maximum buffer
-size on 32-bit machines is 2 GB.
+The maximum buffer size on 64-bit machines is 2.3 exabytes
+(@code{most-positive-fixnum}).
-Emacs compiled on a 64-bit machine can handle much larger buffers; up
-to @code{most-positive-fixnum} (2.3 exabytes).
+Emacs compiled on a 32-bit machine can handle buffers up to 512
+MBytes. If Emacs was built using the @code{--with-wide-int} flag, the
+maximum buffer size on 32-bit machines is 2 GB.
Due to things like decoding of multibyte characters, you can only
visit files with a size that is roughly half the buffer size limit.
@@ -3839,13 +3821,28 @@ description of what they do and how they should be used.
The easiest way to add more features to your Emacs is to use the
command @kbd{M-x list-packages}. This contacts the
-@uref{https://elpa.gnu.org, GNU ELPA} (``Emacs Lisp Package Archive'')
-server and fetches the list of additional packages that it offers.
-These are GNU packages that are available for use with Emacs, but are
-distributed separately from Emacs itself, for reasons of space, etc.
-You can browse the resulting @file{*Packages*} buffer to see what is
-available, and then Emacs can automatically download and install the
-packages that you select. @xref{Packages,,, emacs, The GNU Emacs Manual}.
+@uref{https://elpa.gnu.org, GNU ELPA} and
+@uref{https://elpa.nongnu.org, NonGNU ELPA} (``Emacs Lisp Package
+Archive'') servers and fetches the list of additional packages that
+they offer. You can browse the resulting @file{*Packages*} buffer to
+see what is available, and then Emacs can automatically download and
+install the packages that you select. @xref{Packages,,, emacs, The
+GNU Emacs Manual}.
+
+GNU ELPA contains GNU packages that are available for use with Emacs,
+but are distributed separately from Emacs itself, for reasons of
+space, etc. NonGNU ELPA contains a selection of third-party packages
+that can not be included in GNU ELPA because their copyright has not
+yet been assigned to the Free Software Foundation.@footnote{For more
+information, see @uref{https://www.gnu.org/licenses/why-assign.html,
+Why the FSF Gets Copyright Assignments from Contributors}.}
+
+The @uref{https://lists.gnu.org/mailman/listinfo/gnu-emacs-sources,
+GNU Emacs sources mailing list} is automatically sent an email when a
+new version of a GNU ELPA or NonGNU ELPA package is
+released.@footnote{It used to be an official place where people could
+post or announce their extensions to Emacs. That is still allowed,
+but exceedingly rare these days.}
There are other Emacs Lisp package archives. To use additional
archives, you can customize the @code{package-archives} variable.
@@ -3855,23 +3852,19 @@ correctness and safety of the code, or they may give only cursory
attention.
Also, packages hosted on these other archives may encourage or require
-you to install and use other nonfree programs. Unless you can verify
+you to install and use nonfree programs. Unless you can verify
that a package is free software, and that it functions without
installing any nonfree software, we recommend for your freedom's sake
that you stay away from it.
-The @uref{https://lists.gnu.org/mailman/listinfo/gnu-emacs-sources,
-GNU Emacs sources mailing list} is an official place where people can
-post or announce their extensions to Emacs.
-
The @uref{https://emacswiki.org, Emacs Wiki} contains pointers to some
additional extensions. @uref{https://wikemacs.org, WikEmacs} is an
alternative wiki for Emacs.
It is impossible for us to list here all the sites that offer Emacs
Lisp packages. If you are interested in a specific feature, then
-after checking Emacs itself and GNU ELPA, a web search is often the
-best way to find results.
+after checking Emacs itself, GNU ELPA, and NonGNU ELPA, a web search
+is often the best way to find results.
@node Spell-checkers
@section Spell-checkers
diff --git a/doc/misc/eglot.texi b/doc/misc/eglot.texi
index 6eb212ca841..a5c3a967af1 100644
--- a/doc/misc/eglot.texi
+++ b/doc/misc/eglot.texi
@@ -10,7 +10,7 @@
@copying
This manual is for Eglot, the Emacs LSP client.
-Copyright @copyright{} 2022--2023 Free Software Foundation, Inc.
+Copyright @copyright{} 2022--2024 Free Software Foundation, Inc.
@quotation
Permission is granted to copy, distribute and/or modify this document
@@ -99,6 +99,7 @@ This manual documents how to configure, use, and customize Eglot.
* Using Eglot:: Important Eglot commands and variables.
* Customizing Eglot:: Eglot customization and advanced features.
* Advanced server configuration:: Fine-tune a specific language server
+* Extending Eglot:: Writing Eglot extensions in Elisp
* Troubleshooting Eglot:: Troubleshooting and reporting bugs.
* GNU Free Documentation License:: The license for this manual.
* Index::
@@ -137,17 +138,19 @@ Turn on Eglot for your project.
To start using Eglot for a project, type @kbd{M-x eglot @key{RET}} in
a buffer visiting any file that belongs to the project. This starts
the language server configured for the programming language of that
-buffer, and causes Eglot to start managing all the files of the
-project which use the same programming language. The notion of a
-``project'' used by Eglot is the same Emacs uses (@pxref{Projects,,,
-emacs, GNU Emacs Manual}): in the simplest case, the ``project'' is
-the single file you are editing, but it can also be all the files in a
-single directory or a directory tree under some version control
-system, such as Git.
-
-Alternatively, you can start Eglot automatically from the major-mode
-hook of the mode used for the programming language; see @ref{Starting
-Eglot}.
+buffer, and causes Eglot to start @dfn{managing} file-visiting buffers
+related to that programming language. This includes files that are
+already visited at the time the @code{eglot} command is invoked, as
+well as any files visited after this invocation.
+
+The notion of a ``project'' used by Eglot is the same Emacs uses
+(@pxref{Projects,,, emacs, GNU Emacs Manual}): in the simplest case,
+the ``project'' is the single file you are editing, but it can also be
+all the files in a single directory or a directory tree under some
+version control system, such as Git.
+
+There are alternate ways of starting Eglot; see @ref{Starting Eglot}
+for details.
@item
Use Eglot.
@@ -343,6 +346,12 @@ starting an Eglot session is non-interactive, so it should be used
only when you are confident that Eglot can be started reliably for any
file which may be visited with the major-mode in question.
+Note that it's often difficult to establish this confidence fully, so
+it may be wise to use the interactive command @code{eglot} instead.
+You only need to invoke it once per project, as all other files
+visited within the same project will automatically be managed with no
+further user intervention needed.
+
When Eglot connects to a language server for the first time in an
Emacs session, it runs the hook @code{eglot-connect-hook}
(@pxref{Eglot Variables}).
@@ -395,11 +404,13 @@ commands and variables.
@section Eglot Features
@cindex features in buffers supported by Eglot
-Once Eglot is enabled in a buffer, it uses LSP and the language-server
-capabilities to activate, enable, and enhance modern IDE features in
-Emacs. The features themselves are usually provided via other Emacs
-packages. Here's the list of the main features that Eglot enables and
-provides:
+While Eglot is enabled in a buffer, it is said to be @dfn{managing}
+it, using LSP and the specific capabilities of the language server to
+activate and enhance modern IDE features in Emacs. Some of these
+features are provided via other Emacs packages, and some via Eglot
+directly (@pxref{Eglot Commands}).
+
+Here's an overview of the main features that Eglot provides:
@itemize @bullet
@item
@@ -412,10 +423,11 @@ allows major modes to provide extensive help and documentation about
the program identifiers.
@item
-On-the-fly diagnostic annotations with server-suggested fixes, via the
-Flymake package (@pxref{Top,,, flymake, GNU Flymake manual}). This
-improves and enhances the Flymake diagnostics, replacing the other
-Flymake backends.
+On-the-fly diagnostic annotations, via the Flymake package
+(@pxref{Top,,, flymake, GNU Flymake manual}). Eglot's Flymake backend
+replaces other Flymake backends while it is managing a buffer, and
+enhances diagnostics with interactive server-suggested fixes
+(so-called @dfn{code actions}, @pxref{Eglot Commands})
@item
Finding definitions and uses of identifiers, via Xref (@pxref{Xref,,,
@@ -474,9 +486,17 @@ with @kbd{eglot-code-actions}. @xref{Eglot Commands}.
Not all servers support the full set of LSP capabilities, but most of
them support enough to enable the basic set of features mentioned
-above. Conversely, some servers offer capabilities for which no
-equivalent Emacs package exists yet, and so Eglot cannot (yet) expose
-these capabilities to Emacs users.
+above.
+
+Conversely, some servers offer capabilities for which no equivalent
+Emacs package exists yet, and so Eglot cannot (yet) expose these
+capabilities to Emacs users. However, @xref{Extending Eglot}.
+
+Finally, it's worth noting that, by default, Eglot generally turns on
+all features that it @emph{can} turn on. It's possible to opt out of
+some features via user options (@pxref{Customizing Eglot}) and a hook
+that runs after Eglot starts managing a buffer (@pxref{Eglot and
+Buffers}).
@node Eglot and Buffers
@section Buffers, Projects, and Eglot
@@ -682,12 +702,12 @@ This command reformats the current buffer, in the same manner as
These commands allow you to invoke the so-called @dfn{code actions}:
requests for the language server to provide editing commands for
correcting, refactoring or beautifying your code. These commands may
-affect more than one visited file belong to the project.
+affect more than one visited file belonging to the project.
-The command @code{eglot-code-actions} asks the server if there any
+The command @code{eglot-code-actions} asks the server if there are any
code actions for any point in the buffer or contained in the active
-region. If there are, you the choice to execute one of them via the
-minibuffer.
+region. If there are, you have the choice to execute one of them via
+the minibuffer.
A common use of code actions is fixing the Flymake error diagnostics
issued by Eglot (@pxref{Top,,, flymake, GNU Flymake manual}).
@@ -816,13 +836,13 @@ in the background. The value of @code{t} means block during the whole
waiting period. The value of @code{nil} or @code{0} means don't block at
all during the waiting period.
-@item eglot-events-buffer-size
-This determines the size of the Eglot events buffer. @xref{Eglot
-Commands, eglot-events-buffer}, for how to display that buffer. If
-the value is changed, for it to take effect the connection should be
-restarted using @kbd{M-x eglot-reconnect}.
+@item eglot-events-buffer-config
+This configures the size and format of the Eglot events buffer.
+@xref{Eglot Commands, eglot-events-buffer}, for how to access that
+buffer. If the value is changed, the connection should be restarted
+using @kbd{M-x eglot-reconnect} for the new value to take effect.
@c FIXME: Shouldn't the defcustom do this by itself using the :set
-@c attribute?
+@c attribute? Maybe not because reconnecting is a complex task.
@xref{Troubleshooting Eglot}, for when this could be useful.
@item eglot-autoshutdown
@@ -831,12 +851,14 @@ last buffer managed by it is killed. @xref{Shutting Down LSP Servers}.
The default is @code{nil}; if you want to shut down a server, use
@kbd{M-x eglot-shutdown} (@pxref{Eglot Commands}).
-@item eglot-confirm-server-initiated-edits
+@item eglot-confirm-server-edits
Various Eglot commands and code actions result in the language server
sending editing commands to Emacs. If this option's value is
-non-@code{nil} (the default), Eglot will ask for confirmation before
-performing edits initiated by the server or edits whose scope affects
-buffers other than the one where the user initiated the request.
+non-@code{nil}, Eglot will ask for confirmation before performing
+edits proposed by the language server. This option's value can be
+crafted to require this confirmation for specific commands or only
+when the edit affects files not yet visited by the user. Consult this
+option's docstring for more information.
@item eglot-ignored-server-capabilities
This variable's value is a list of language server capabilities that
@@ -1085,8 +1107,8 @@ To apply this to Eglot, and assuming you chose the
:fuzzy t)
:pylint (:enabled :json-false)))
:gopls (:usePlaceholders t)))))
- (python-mode . ((indent-tabs-mode . nil)))
- (go-mode . ((indent-tabs-mode . t))))
+ (python-base-mode . ((indent-tabs-mode . nil)))
+ (go-mode . ((indent-tabs-mode . t))))
@end lisp
@noindent
@@ -1101,7 +1123,7 @@ plists are used inside the value of
This following form may also be used:
@lisp
-((python-mode
+((python-base-mode
. ((eglot-workspace-configuration
. (:pylsp (:plugins (:jedi_completion (:include_params t
:fuzzy t)
@@ -1116,7 +1138,7 @@ This following form may also be used:
@noindent
This sets up the value of @code{eglot-workspace-configuration}
separately depending on the major mode of each of that project's
-buffers. @code{python-mode} buffers will have the variable set to
+buffers. @code{python-base-mode} buffers will have the variable set to
@code{(:pylsp (:plugins ...))}. @code{go-mode} buffers will have the
variable set to @code{(:gopls (:usePlaceholders t))}.
@@ -1127,7 +1149,7 @@ want to set a different option for @code{gopls.usePlaceholders} , you
may use something like:
@lisp
-((python-mode
+((python-base-mode
. ((eglot-workspace-configuration
. (:pylsp (:plugins (:jedi_completion (:include_params t
:fuzzy t)
@@ -1210,7 +1232,7 @@ in @ref{Project-specific configuration}. Here is an example:
@end lisp
Note that the global value of @code{eglot-workspace-configuration} is
-always overriden if a directory-local value is detected.
+always overridden if a directory-local value is detected.
@node JSONRPC objects in Elisp
@section JSONRPC objects in Elisp
@@ -1234,8 +1256,8 @@ For example, the plist
@lisp
(:pylsp (:plugins (:jedi_completion (:include_params t
:fuzzy t
- :cache_for ["pandas" "numpy"]
- :pylint (:enabled :json-false))))
+ :cache_for ["pandas" "numpy"])
+ :pylint (:enabled :json-false)))
:gopls (:usePlaceholders t))
@end lisp
@@ -1249,7 +1271,7 @@ is serialized by Eglot to the following JSON text:
"jedi_completion": @{
"include_params": true,
"fuzzy": true,
- "cache_for": [ "pandas", "numpy" ],
+ "cache_for": [ "pandas", "numpy" ]
@},
"pylint": @{
"enabled": false
@@ -1257,11 +1279,159 @@ is serialized by Eglot to the following JSON text:
@}
@},
"gopls": @{
- "usePlaceholders":true
- @},
+ "usePlaceholders": true
+ @}
@}
@end example
+@node Extending Eglot
+@chapter Extending Eglot
+
+Sometimes it may be useful to extend existing Eglot functionality
+using Elisp its public methods. A good example of when this need may
+arise is adding support for a custom LSP protocol extension only
+implemented by a specific server.
+
+The best source of documentation for this is probably Eglot source
+code itself, particularly the section marked ``API''.
+
+Most of the functionality is implemented with Common-Lisp style
+generic functions (@pxref{Generics,,,eieio,EIEIO}) that can be easily
+extended or overridden. The Eglot code itself is an example on how to
+do this.
+
+The following is a relatively simple example that adds support for the
+@code{inactiveRegions} experimental feature introduced in version 17
+of the @command{clangd} C/C++ language server++.
+
+Summarily, the feature works by first having the server detect the
+Eglot's advertisement of the @code{inactiveRegions} client capability
+during startup, whereupon the language server will report a list of
+regions of inactive code for each buffer. This is usually code
+surrounded by C/C++ @code{#ifdef} macros that the preprocessor removes
+based on compile-time information.
+
+The language server reports the regions by periodically sending a
+@code{textDocument/inactiveRegions} notification for each managed
+buffer (@pxref{Eglot and Buffers}). Normally, unknown server
+notifications are ignored by Eglot, but we're going change that.
+
+Both the announcement of the client capability and the handling of the
+new notification is done by adding methods to generic functions.
+
+@itemize @bullet
+@item
+The first method extends @code{eglot-client-capabilities} using a
+simple heuristic to detect if current server is @command{clangd} and
+enables the @code{inactiveRegion} capability.
+
+@lisp
+(cl-defmethod eglot-client-capabilities :around (server)
+ (let ((base (cl-call-next-method)))
+ (when (cl-find "clangd" (process-command
+ (jsonrpc--process server))
+ :test #'string-match)
+ (setf (cl-getf (cl-getf base :textDocument)
+ :inactiveRegionsCapabilities)
+ '(:inactiveRegions t)))
+ base))
+@end lisp
+
+Notice we use an internal function of the @code{jsonrpc.el} library,
+and a regexp search to detect @command{clangd}. An alternative would
+be to define a new EIEIO subclass of @code{eglot-lsp-server}, maybe
+called @code{eglot-clangd}, so that the method would be simplified:
+
+@lisp
+(cl-defmethod eglot-client-capabilities :around ((_s eglot-clangd))
+ (let ((base (cl-call-next-method)))
+ (setf (cl-getf (cl-getf base :textDocument)
+ :inactiveRegionsCapabilities)
+ '(:inactiveRegions t))))
+@end lisp
+
+However, this would require that users tweak
+@code{eglot-server-program} to tell Eglot instantiate such sub-classes
+instead of the generic @code{eglot-lsp-server} (@pxref{Setting Up LSP
+Servers}). For the purposes of this particular demonstration, we're
+going to use the more hacky regexp route which doesn't require that.
+
+Note, however, that detecting server versions before announcing new
+capabilities is generally not needed, as both server and client are
+required by LSP to ignore unknown capabilities advertised by their
+counterparts.
+
+@item
+The second method implements @code{eglot-handle-notification} to
+process the server notification for the LSP method
+@code{textDocument/inactiveRegions}. For each region received it
+creates an overlay applying the @code{shadow} face to the region.
+Overlays are recreated every time a new notification of this kind is
+received.
+
+To learn about how @command{clangd}'s special JSONRPC notification
+message is structured in detail you could consult that server's
+documentation. Another possibility is to evaluate the first
+capability-announcing method, reconnect to the server and peek in the
+events buffer (@pxref{Eglot Commands, eglot-events-buffer}). You
+could find something like:
+
+@lisp
+[server-notification] Mon Sep 4 01:10:04 2023:
+(:jsonrpc "2.0" :method "textDocument/inactiveRegions" :params
+ (:textDocument
+ (:uri "file:///path/to/file.cpp")
+ :regions
+ [(:start (:character 0 :line 18)
+ :end (:character 58 :line 19))
+ (:start (:character 0 :line 36)
+ :end (:character 1 :line 38))]))
+@end lisp
+
+This reveals that the @code{textDocument/inactiveRegions} notification
+contains a @code{:textDocument} property to designate the managed
+buffer and an array of LSP regions under the @code{:regions} property.
+Notice how the message (originally in JSON format), is represented as
+Elisp plists (@pxref{JSONRPC objects in Elisp}).
+
+The Eglot generic function machinery will automatically destructure
+the incoming message, so these two properties can simply be added to
+the new method's lambda list as @code{&key} arguments. Also, the
+@code{eglot-uri-to-path} and @code{eglot-range-region} may be used to
+easily parse the LSP @code{:uri} and @code{:start ... :end ...}
+objects to obtain Emacs objects for file names and positions.
+
+The remainder of the implementation consists of standard Elisp
+techniques to loop over arrays, manage buffers and overlays.
+
+@lisp
+(defvar-local eglot-clangd-inactive-region-overlays '())
+
+(cl-defmethod eglot-handle-notification
+ (_server (_method (eql textDocument/inactiveRegions))
+ &key regions textDocument &allow-other-keys)
+ (if-let* ((path (expand-file-name (eglot-uri-to-path
+ (cl-getf textDocument :uri))))
+ (buffer (find-buffer-visiting path)))
+ (with-current-buffer buffer
+ (mapc #'delete-overlay eglot-clangd-inactive-region-overlays)
+ (cl-loop
+ for r across regions
+ for (beg . end) = (eglot-range-region r)
+ for ov = (make-overlay beg end)
+ do
+ (overlay-put ov 'face 'shadow)
+ (push ov eglot-clangd-inactive-region-overlays)))))
+@end lisp
+
+@end itemize
+
+After evaluating these two additions and reconnecting to the
+@command{clangd} language server (version 17), the result will be that
+all the inactive code in the buffer will be nicely grayed out using
+the LSP server knowledge about current compile time preprocessor
+defines.
+
@node Troubleshooting Eglot
@chapter Troubleshooting Eglot
@cindex troubleshooting Eglot
@@ -1285,12 +1455,14 @@ indicate the problems or at least provide a hint.
@node Performance
@section Performance
@cindex performance problems, with Eglot
-A common and easy-to-fix cause of performance problems is the length
-of the Eglot events buffer because it represent additional work that
-Eglot must do. After verifying Eglot is operating correctly but
-slowly, try to customize the variable @code{eglot-events-buffer-size}
-(@pxref{Eglot Variables}) to 0. This will disable any debug logging
-and may speed things up.
+A common and easy-to-fix cause of performance problems in Eglot
+(especially in older versions) is its events buffer, since it
+represents additional work that Eglot must do (@pxref{Eglot Commands,
+eglot-events-buffer}). If you find Eglot is operating correctly but
+slowly, try to customize the variable
+@code{eglot-events-buffer-config} (@pxref{Eglot Variables}) and set
+its @code{:size} property to 0. This will disable recording any
+events and may speed things up.
In other situations, the cause of poor performance lies in the
language server itself. Servers use aggressive caching and other
diff --git a/doc/misc/eieio.texi b/doc/misc/eieio.texi
index 8838de38f86..02cb51e6fdd 100644
--- a/doc/misc/eieio.texi
+++ b/doc/misc/eieio.texi
@@ -12,7 +12,7 @@
@copying
This manual documents EIEIO, an object framework for Emacs Lisp.
-Copyright @copyright{} 2007--2023 Free Software Foundation, Inc.
+Copyright @copyright{} 2007--2024 Free Software Foundation, Inc.
@quotation
Permission is granted to copy, distribute and/or modify this document
diff --git a/doc/misc/emacs-gnutls.texi b/doc/misc/emacs-gnutls.texi
index fafb4c11594..c149531a8bd 100644
--- a/doc/misc/emacs-gnutls.texi
+++ b/doc/misc/emacs-gnutls.texi
@@ -9,7 +9,7 @@
@copying
This file describes the Emacs GnuTLS integration.
-Copyright @copyright{} 2012--2023 Free Software Foundation, Inc.
+Copyright @copyright{} 2012--2024 Free Software Foundation, Inc.
@quotation
Permission is granted to copy, distribute and/or modify this document
diff --git a/doc/misc/emacs-mime.texi b/doc/misc/emacs-mime.texi
index 19ff415bdaf..96a6328cd47 100644
--- a/doc/misc/emacs-mime.texi
+++ b/doc/misc/emacs-mime.texi
@@ -10,7 +10,7 @@
@copying
This file documents the Emacs MIME interface functionality.
-Copyright @copyright{} 1998--2023 Free Software Foundation, Inc.
+Copyright @copyright{} 1998--2024 Free Software Foundation, Inc.
@quotation
Permission is granted to copy, distribute and/or modify this document
diff --git a/doc/misc/epa.texi b/doc/misc/epa.texi
index 917fd588593..27a9e2b0ebb 100644
--- a/doc/misc/epa.texi
+++ b/doc/misc/epa.texi
@@ -10,7 +10,7 @@
@copying
This file describes EasyPG Assistant @value{VERSION}.
-Copyright @copyright{} 2007--2023 Free Software Foundation, Inc.
+Copyright @copyright{} 2007--2024 Free Software Foundation, Inc.
@quotation
Permission is granted to copy, distribute and/or modify this document
@@ -456,9 +456,9 @@ public key, it does not prompt for a passphrase for the buffer save,
but it will prompt for your passphrase for file reads every now and
then, depending on the GnuPG Agent cache configuration.
-@cindex tempory files created by easypg assistant
+@cindex temporary files created by easypg assistant
To encrypt and decrypt files as described above EasyPG Assistant under
-certain circumstances uses intermediate tempory files that contain the
+certain circumstances uses intermediate temporary files that contain the
plain-text contents of the files it processes. EasyPG Assistant
creates them below the directory returned by function
@code{temporary-file-directory} (@pxref{Unique File Names, ,
@@ -640,6 +640,9 @@ Customize variable @code{epg-pinentry-mode} to @code{loopback} in
Emacs.
@end enumerate
+Note that loopback Pinentry does not work with @command{gpgsm},
+therefore EasyPG will ignore this setting for it.
+
There are other options available to use Emacs as Pinentry, you might
come across a Pinentry called @command{pinentry-emacs} or
@command{gpg-agent} option @code{allow-emacs-pinentry}. However,
diff --git a/doc/misc/erc.texi b/doc/misc/erc.texi
index 6d7785a9b54..7fbe6f9766e 100644
--- a/doc/misc/erc.texi
+++ b/doc/misc/erc.texi
@@ -12,7 +12,7 @@
@copying
This manual is for ERC @value{ERCVER} @value{ERCDIST}.
-Copyright @copyright{} 2005--2023 Free Software Foundation, Inc.
+Copyright @copyright{} 2005--2024 Free Software Foundation, Inc.
@quotation
Permission is granted to copy, distribute and/or modify this document
@@ -412,16 +412,18 @@ One way to add functionality to ERC is to customize which of its many
modules are loaded.
There is a spiffy customize interface, which may be reached by typing
-@kbd{M-x customize-option @key{RET} erc-modules @key{RET}}.
-When removing a module outside of the Custom ecosystem, you may wish
-to ensure it's disabled by invoking its associated minor-mode toggle
-with a nonpositive prefix argument, for example, @kbd{C-u - M-x
+@kbd{M-x customize-option @key{RET} erc-modules @key{RET}}. When
+removing a module outside of Customize, you may wish to ensure it's
+disabled by invoking its associated minor-mode toggle with a
+nonpositive prefix argument, for example, @kbd{C-u - M-x
erc-spelling-mode @key{RET}}. Additionally, if you plan on loading
third-party modules that perform atypical setup on activation, you may
need to arrange for calling @code{erc-update-modules} in your init
file. Examples of such setup might include registering an
@code{erc-before-connect} hook, advising @code{erc-open}, and
-modifying @code{erc-modules} itself.
+modifying @code{erc-modules} itself. On Emacs 29 and greater, you can
+also run @code{erc-update-modules} indirectly, via @code{(setopt
+erc-modules erc-modules)}.
The following is a list of available modules.
@@ -448,6 +450,11 @@ Buttonize URLs, nicknames, and other text
@item capab-identify
Mark unidentified users on freenode and other servers supporting CAPAB.
+@cindex modules, command-indicator
+@item command-indicator
+Echo command lines for ``slash commands'', like @kbd{/JOIN #erc} and
+@kbd{/HELP join}
+
@cindex modules, completion
@cindex modules, pcomplete
@item completion (aka pcomplete)
@@ -652,6 +659,54 @@ buffers belonging to their connection (when called interactively).
And unlike global toggles, none of these ever mutates
@code{erc-modules}.
+@c FIXME add section to Advanced chapter for creating modules, and
+@c move this there.
+@anchor{Module Loading}
+@subheading Loading
+@cindex module loading
+
+ERC loads internal modules in alphabetical order and third-party
+modules as they appear in @code{erc-modules}. When defining your own
+module, take care to ensure ERC can find it. An easy way to do that
+is by mimicking the example in the doc string for
+@code{define-erc-module} (also shown below). For historical reasons,
+ERC falls back to @code{require}ing features. For example, if some
+module @code{my-module} in @code{erc-modules} lacks a corresponding
+@code{erc-my-module-mode} command, ERC will attempt to load the
+library @code{erc-my-module} prior to connecting. If this fails, ERC
+signals an error. Users defining personal modules in an init file
+should @code{(provide 'erc-my-module)} somewhere to placate ERC.
+Dynamically generating modules on the fly is not supported.
+
+Some packages have been known to autoload a module's definition
+instead of its minor-mode command, which severs the link between the
+library and the module. This means that enabling the mode by invoking
+its command toggle isn't enough to load its defining library. As
+such, packages should only supply module-related autoload cookies with
+an actual @code{autoload} form for their module's minor-mode command,
+like so:
+
+@lisp
+;;;###autoload(autoload 'erc-my-module-mode "erc-my-module" nil t)
+(define-erc-module my-module nil
+ "My doc string."
+ ((add-hook 'erc-insert-post-hook #'erc-my-module-on-insert-post))
+ ((remove-hook 'erc-insert-post-hook #'erc-my-module-on-insert-post)))
+@end lisp
+
+@noindent
+As implied earlier, packages can usually omit such cookies entirely so
+long as their module's prefixed name matches that of its defining
+library and the library's provided feature.
+
+Finally, packages have also been observed to run
+@code{erc-update-modules} in top-level forms, forcing ERC to take
+special precautions to avoid recursive invocations. Another
+unfortunate practice is mutating @code{erc-modules} itself upon
+loading @code{erc}, possibly by way of an autoload. Doing this tricks
+Customize into displaying the widget for @code{erc-modules}
+incorrectly, with built-in modules moved from the predefined checklist
+to the user-provided free-form area.
@c PRE5_4: Document every option of every module in its own subnode
@@ -863,16 +918,11 @@ In the latter case, if the first nick in the list is already in use,
other nicks are tried in the list order.
@end defopt
-@defopt erc-format-nick-function
-A function to format a nickname for message display
-
-You can set this to @code{erc-format-@@nick} to display user mode prefix
+@defopt erc-show-speaker-membership-status
+A boolean for including a channel member's @dfn{status prefix} in
+their display name when they speak.
@end defopt
-@example
-(setq erc-format-nick-function 'erc-format-@@nick)
-@end example
-
@defopt erc-nick-uniquifier
The string to append to the nick if it is already in use.
@end defopt
@@ -1011,14 +1061,14 @@ The name of an SASL subprotocol type as a @emph{lowercase} symbol.
The value can be one of the following:
@table @asis
-@item @code{plain} and @code{scram} (``password-based'')
+@item @code{plain} or @code{scram} (``password-based'')
Here, ``password'' refers to your account password, which is usually
your @samp{NickServ} password. To make this work, customize
@code{erc-sasl-user} and @code{erc-sasl-password} or specify the
@code{:user} and @code{:password} keyword arguments when invoking
@code{erc-tls}.
-@item @code{external} (via Client TLS Certificate)
+@item @code{external} (via client @acronym{TLS} certificate)
This works in conjunction with the @code{:client-certificate} keyword
offered by @code{erc-tls}. Just ensure you've registered your
fingerprint with the network beforehand. The fingerprint is usually a
@@ -1252,10 +1302,10 @@ settings (@pxref{Sample configuration via Customize}).
(use-package erc
:config
- ;; Prefer SASL to NickServ, colorize nicknames, interpret mIRC colors,
- ;; and list buffers and channel members in separate side panels.
+ ;; Prefer SASL to NickServ, colorize nicknames, and show side panels
+ ;; with joined channels and members
(setopt erc-modules
- (seq-union '(sasl nicks irccontrols bufbar nickbar scrolltobottom)
+ (seq-union '(sasl nicks bufbar nickbar scrolltobottom)
erc-modules))
:custom
@@ -1263,6 +1313,8 @@ settings (@pxref{Sample configuration via Customize}).
(erc-inhibit-multiline-input t)
(erc-send-whitespace-lines t)
(erc-ask-about-multiline-input t)
+ ;; Scroll all windows to prompt when submitting input.
+ (erc-scrolltobottom-all t)
;; Reconnect automatically using a fancy strategy.
(erc-server-reconnect-function #'erc-server-delayed-check-reconnect)
@@ -1346,13 +1398,13 @@ As mentioned, Customize users can accomplish nearly all of the above
via the Customize interface. Start by running @kbd{M-x
customize-group @key{RET} erc @key{RET}}, and search for ``Modules''
with @kbd{C-s modules @key{RET}}. Toggle open the flyout menu to
-reveal the full ``widget'' panel, a web-form-like interface for ``Erc
-Modules''. Tick the boxes for @samp{bufbar}, @samp{irccontrols},
-@samp{nickbar}, @samp{nicks}, @samp{sasl}, and @samp{scrolltobottom}.
+reveal the full @dfn{widget} panel, a web-form-like interface for
+``Erc Modules''. Tick the boxes for @samp{bufbar}, @samp{nickbar},
+@samp{nicks}, @samp{sasl}, and @samp{scrolltobottom}.
Next, search for the phrases ``Erc Ask About Multiline Input'', ``Erc
-Inhibit Mulitline Input'', and ``Erc Send Whitespace Lines''. These
-are the print names of three Boolean options that control how ERC
+Inhibit Multiline Input'', and ``Erc Send Whitespace Lines''. These
+are the print names of three boolean options that control how ERC
treats prompt input containing line breaks. When visiting each
option's section, twirl open its triangle icon to reveal its widget
UI, and click its @samp{[Toggle]} button to set its value to @code{t}.
@@ -1398,12 +1450,19 @@ To make sure you've got this, try quickly customizing the option
@code{erc-interactive-display}, which lives in the @samp{Erc Buffers}
group (@kbd{M-x customize-group @key{RET} erc-buffers @key{RET}}). As
its doc string explains, the option controls where new buffers show up
-when you do @kbd{M-x erc-tls @key{RET}} or issue certain ``slash''
-commands, like @kbd{/JOIN #emacs-beginners @key{RET}}, at ERC's
+when you do @kbd{M-x erc-tls @key{RET}} or issue certain @dfn{slash
+commands}, like @kbd{/JOIN #emacs-beginners @key{RET}}, at ERC's
prompt. Change its value to the symbol @code{buffer} by choosing
@samp{Use current window} (item @kbd{5}) from the option's
@samp{[Value Menu]}. Don't forget to save.
+If you need more practice, try enabling the boolean option
+@code{erc-scrolltobottom-all}, which lives in the @samp{Erc Display}
+group (@kbd{M-x customize-group @key{RET} erc-display @key{RET}}).
+When enabled, this option tells the @samp{scrolltobottom} module to
+adjust all ERC windows instead of just the one you're currently typing
+in.
+
Now it's time to set some key bindings for @code{erc-mode-map}, a
major-mode keymap active in all ERC buffers. In general, it's best to
do this part either entirely or in conjunction with some lisp code in
@@ -1480,8 +1539,8 @@ and save your changes. Next, customize the related option
@code{erc-track-priority-faces-only} to the @samp{[Value Menu]} choice
@samp{all}. Once again, save your changes.
-Let's say you'd like to enable a ``local module'' (ERC's version of a
-local minor mode) in a specific channel. One way to do that is by
+Let's say you'd like to enable a @dfn{local module} (ERC's version of
+a local minor mode) in a specific channel. One way to do that is by
running some code to activate the module if the channel's name
matches. Try that now by customizing the option @code{erc-join-hook}.
Add the following in the value field before saving your changes:
@@ -1493,7 +1552,7 @@ Add the following in the value field before saving your changes:
(erc-keep-place-indicator-mode +1)))
@end lisp
-Lastly, if you really want the two ``slash'' commands defined at the
+Lastly, if you really want the two @dfn{slash commands} defined at the
end of the previous section, you can put them in any file listed in
@code{erc-startup-file-list}, such as @file{~/.emacs.d/.ercrc.el}.
Make sure to put @code{(require 'erc-track)} near the top of the file.
@@ -1615,6 +1674,7 @@ with the default backend, netrc, put a line like the following in your
machine irc.example.net login mynick password sEcReT
@end example
+@anchor{auth-source Server Password}
@subsubheading Server Passwords
When retrieving passwords to accompany the IRC @samp{PASS} command
(@pxref{password parameter}), ERC asks auth-source to match the
@@ -1664,10 +1724,7 @@ auth-source experience. (@xref{SASL}.)
@subsubheading Default query behavior
When preparing entries for your backend, it may help to get a feel for
how ERC and its modules conduct searches, especially when exploring a
-new context, such as channel keys. (Hint: in such situations, try
-temporarily setting the variable @code{auth-source-debug} to @code{t}
-and checking @file{*Messages*} periodically for insights into how
-auth-source is operating.) Overall, though, ERC tries to be
+new context, such as channel keys. Overall, though, ERC tries to be
consistent in performing queries across various authentication
contexts. Here's what to expect with respect to the @samp{host}
field, which, by default, most heavily influences the fate of a query:
@@ -1751,6 +1808,33 @@ required by certain channels you join. When modifying a traditional
@samp{user} field (for example, @samp{login "#fsf"}, in netrc's case).
The actual key goes in the @samp{password} (or @samp{secret}) field.
+@anchor{auth-source Troubleshooting}
+@subheading Troubleshooting
+By default, ERC queries @code{auth-source} for channel keys and server
+passwords (@pxref{auth-source Server Password}), as well as other,
+module-specific credentials. In general, if you're having trouble
+calling @code{auth-source-search} in a custom query function, like
+@code{erc-auth-source-server-function}, try temporarily setting the
+variable @code{auth-source-debug} to @code{t} and checking
+@file{*Messages*} periodically for insights into how
+@code{auth-source} is operating.
+
+If you're using a @acronym{GPG}-encrypted file and find that
+customizing one of the function-valued query options doesn't solve
+your problem, explore options @code{epg-pinentry-mode} and
+@code{epg-debug} in the @code{epg} Custom group (@pxref{GnuPG
+Pinentry,,, epa, EasyPG Assistant}). Additionally, keep an eye out
+for an @file{*Error*} buffer, which may contain more specific clues
+about your situation. If you use the libsecrets integration
+(@pxref{Secret Service API,,, auth, Emacs auth-source}) with something
+like GNOME Keyring, you may need to check the ``remember'' box in the
+passphrase popup dialog to avoid being prompted for confirmation every
+time you run ERC. If it doesn't work at first, try logging out. And
+when in doubt, try using the Emacs command @code{secrets-show-secrets}
+to browse the @samp{Login} keyring. There should be a
+@samp{GnuPG/stored-by} entry with a value of @samp{GnuPG Pinentry} or
+similar.
+
@node display-buffer
@subsection display-buffer
@cindex display-buffer
@@ -1803,10 +1887,11 @@ Observe that ERC supplies the names of buffer-display options as
the symbols @samp{erc-tls} or @samp{url}, the full lineup of which are
listed below.
-In this second example, the user writes three predicates that somewhat
-resemble the ``@code{display-buffer}-like'' function above. These too
-look for @var{action} alist keys sharing the names of buffer-display
-options (and, in one case, a module's minor mode).
+In this second example, for Emacs 29 and above, the user writes three
+predicates that somewhat resemble the ``@code{display-buffer}-like''
+function above. These too look for @var{action} alist keys sharing
+the names of ERC's buffer-display options (and, in one case, a
+module's minor mode).
@lisp
(defun my-erc-disp-entry-p (_ action)
@@ -1821,7 +1906,7 @@ options (and, in one case, a module's minor mode).
(defun my-erc-disp-chan-p (_ action)
(or (assq 'erc-autojoin-mode action)
- (and (memq (cdr (assq 'erc-buffer-display alist)) 'JOIN)
+ (and (eq (cdr (assq 'erc-buffer-display action)) 'JOIN)
(member (erc-default-target) '("#emacs" "#fsf")))))
@end lisp
diff --git a/doc/misc/ert.texi b/doc/misc/ert.texi
index a6b62a058f2..bd2ad495142 100644
--- a/doc/misc/ert.texi
+++ b/doc/misc/ert.texi
@@ -15,7 +15,7 @@
@end direntry
@copying
-Copyright @copyright{} 2008, 2010--2023 Free Software Foundation, Inc.
+Copyright @copyright{} 2008, 2010--2024 Free Software Foundation, Inc.
@quotation
Permission is granted to copy, distribute and/or modify this document
@@ -526,6 +526,7 @@ to find where a test was defined if the test was loaded from a file.
* Tests and Their Environment:: Don't depend on customizations; no side effects.
* Useful Techniques:: Some examples.
* erts files:: Files containing many buffer tests.
+* Syntax Highlighting Tests:: Tests for face assignment.
@end menu
@@ -658,11 +659,30 @@ versions, specific architectures, etc.:
@cindex skipping tests
@cindex test preconditions
@cindex preconditions of a test
+@findex skip-when
+@findex skip-unless
Sometimes, it doesn't make sense to run a test due to missing
preconditions. A required Emacs feature might not be compiled in, the
function to be tested could call an external binary which might not be
-available on the test machine, you name it. In this case, the macro
-@code{skip-unless} could be used to skip the test:
+available on the test machine, you name it. In this case, the macros
+@code{skip-when} or @code{skip-unless} could be used to skip the
+test.@footnote{The @code{skip-when} macro was added in Emacs 30.1. If
+you need your tests to be compatible with older versions of Emacs, use
+@code{skip-unless} instead.}
+
+@noindent
+For example, this test is skipped on MS-Windows and macOS:
+
+@lisp
+(ert-deftest test-gnu-linux ()
+ "A test that is not relevant on MS-Windows and macOS."
+ (skip-when (memq system-type '(windows-nt ns))
+ ...))
+@end lisp
+
+@noindent
+This test is skipped if the feature @samp{dbusbind} is not present in
+the running Emacs:
@lisp
(ert-deftest test-dbus ()
@@ -923,6 +943,102 @@ non-@code{nil} value, the test will be skipped.
If you need to use the literal line single line @samp{=-=} in a test
section, you can quote it with a @samp{\} character.
+@node Syntax Highlighting Tests
+@section Syntax Highlighting Tests
+
+Syntax highlighting is normally provided by the Font Lock minor mode
+that assigns face properties to parts of the buffer. The
+@code{ert-font-lock} package makes it possible to introduce unit tests
+checking face assignment. Test assertions are included in code-level
+comments directly and can be read either from inline strings or files.
+
+Test assertion parser extracts tests from comment-only lines. Every
+comment assertion line starts either with a caret (@samp{^}) or an
+arrow (@samp{<-}). A caret/arrow should be followed immediately by the
+name of a face to be checked.
+
+The test then checks if the first non-assertion column above the caret
+contains a face expected by the assertion:
+
+@example
+var variable = 11;
+// ^ font-lock-variable-name-face
+// ^ font-lock-literal-face
+// ^ font-lock-punctuation-face
+// this is not an assertion, it's just a comment
+// ^ font-lock-comment-face
+@end example
+
+The arrow means that the first non-empty column of the assertion line
+will be used for the check:
+
+@example
+var variable = 1;
+// <- font-lock-keyword-face
+ 11;
+ // <- font-lock-literal-face
+@end example
+
+@findex ert-font-lock-test-string
+
+The @code{ert-font-lock-test-string} function extracts ERT assertions
+from an inline string. The @code{javascript-mode} symbol below
+specifies the major mode used for comments and font locking:
+
+@lisp
+(ert-deftest test-font-lock-test-string--correct ()
+ (ert-font-lock-test-string
+ "
+var abc = function(d) @{
+// <- font-lock-keyword-face
+// ^ font-lock-variable-name-face
+ // ^ font-lock-keyword-face
+ // ^ font-lock-variable-name-face
+@};
+"
+ 'javascript-mode))
+@end lisp
+
+@findex ert-font-lock-test-file
+
+It is also possible to extract test assertions from a file:
+
+@lisp
+(ert-deftest test-font-lock-test-file--correct ()
+ (ert-font-lock-test-file
+ (ert-resource-file "correct.js")
+ 'javascript-mode))
+@end lisp
+
+@findex ert-font-lock-deftest
+
+The @code{ert-font-lock-deftest} macro simplifies inline test
+definition:
+
+@lisp
+(ert-font-lock-deftest test-macro-test--inline
+ emacs-lisp-mode
+ "
+(defun fun ())
+;; ^ font-lock-keyword-face
+;; ^ font-lock-function-name-face")
+@end lisp
+
+@findex ert-font-lock-deftest-file
+
+The @code{ert-font-lock-deftest-file} macro reads assertions from a
+file:
+
+@lisp
+(ert-font-lock-deftest-file test-macro-test--file
+ "Test reading correct assertions from a file"
+ javascript-mode
+ "correct.js")
+@end lisp
+
+The @code{ert-font-lock-deftest} and @code{ert-font-lock-deftest-file}
+macros accept the same keyword parameters as @code{ert-deftest} i.e.,
+@code{:tag} and @code{:expected-result}.
@node How to Debug Tests
@chapter How to Debug Tests
diff --git a/doc/misc/eshell.texi b/doc/misc/eshell.texi
index 4897b410b76..fb9a563b696 100644
--- a/doc/misc/eshell.texi
+++ b/doc/misc/eshell.texi
@@ -10,7 +10,7 @@
@copying
This manual is for Eshell, the Emacs shell.
-Copyright @copyright{} 1999--2023 Free Software Foundation, Inc.
+Copyright @copyright{} 1999--2024 Free Software Foundation, Inc.
@quotation
Permission is granted to copy, distribute and/or modify this document
@@ -234,6 +234,9 @@ the foreground. That said, background processes invoked from Eshell
can be controlled the same way as any other background process in
Emacs.
+If a command exits abnormally, Eshell will display its exit code
+in the next prompt.
+
@subsection Command form
Command form looks much the same as in other shells. A command
consists of arguments separated by spaces; the first argument is the
@@ -334,7 +337,8 @@ As with other shells, you can escape special characters and spaces by
prefixing the character with a backslash (@samp{\}), or by surrounding
the string with apostrophes (@samp{''}) or double quotes (@samp{""}).
This is needed especially for file names with special characters like
-pipe (@samp{|}), which could be part of remote file names.
+pipe (@samp{|}) or square brackets (@samp{[} or @samp{]}), which could
+be part of remote file names.
When you escape a character with @samp{\} outside of any quotes, the
result is the literal character immediately following it. For
@@ -396,6 +400,14 @@ Return the buffer named @var{name}. This is equivalent to
@samp{$(get-buffer-create "@var{name}")} (@pxref{Creating Buffers, , ,
elisp, The Emacs Lisp Reference Manual}).
+@item #<marker @var{position} @var{buffer-or-name}>
+Return a marker at @var{position} in the buffer @var{buffer-or-name}.
+@var{buffer-or-name} can either be a string naming a buffer or an
+actual buffer object. This is roughly equivalent to creating a new
+marker and calling @samp{$(set-marker marker @var{position}
+@var{buffer-or-name})} (@pxref{Moving Markers, , , elisp, The Emacs
+Lisp Reference Manual}).
+
@item #<process @var{name}>
Return the process named @var{name}. This is equivalent to
@samp{$(get-process "@var{name}")} (@pxref{Process Information, , ,
@@ -619,10 +631,23 @@ environment.
@item eshell-debug
@cmindex eshell-debug
Toggle debugging information for Eshell itself. You can pass this
-command the argument @code{errors} to enable/disable Eshell trapping
-errors when evaluating commands, or the argument @code{commands} to
-show/hide command execution progress in the buffer @code{*eshell last
-cmd*}.
+command one or more of the following arguments:
+
+@itemize @bullet
+
+@item
+@code{error}, to enable/disable Eshell trapping errors when
+evaluating commands;
+
+@item
+@code{form}, to show/hide Eshell command form manipulation in the
+buffer @code{*eshell last cmd*}; or
+
+@item
+@code{process}, to show/hide external process events in the buffer
+@code{*eshell last cmd*}.
+
+@end itemize
@item exit
@cmindex exit
@@ -1094,6 +1119,13 @@ necessary. By default, its value is
@code{@var{emacs-version},eshell}. Other parts of Emacs, such as
Tramp, may add extra information to this value.
+@vindex $PAGER
+@item $PAGER
+This variable indicates the pager that commands should use when they
+wish to paginate long output. Its value is that of
+@code{comint-pager} if non-@code{nil}; otherwise, it uses the value of
+@code{$PAGER} from the @code{process-environment}.
+
@end table
@xref{Aliases}, for the built-in variables @samp{$*}, @samp{$1},
@@ -1205,11 +1237,20 @@ command containing @code{foo}. The n-th argument of the last command
beginning with @code{foo} is accessible by @code{!foo:n}.
@vindex eshell-history-file-name
-The history ring is loaded from a file at the start of every session,
-and written back to the file at the end of every session. The file path
-is specified in @code{eshell-history-file-name}. Unlike other shells,
-such as Bash, Eshell can not be configured to keep a history ring of a
-different size than that of the history file.
+@vindex eshell-history-append
+The history is loaded to the history ring from the file
+@code{eshell-history-file-name} at the start of every session, and
+saved to that file at the end of every session. The default history
+saving behavior is to overwrite the history file with the whole
+history ring of the session. If @code{eshell-history-append} is
+non-@code{nil}, the history will instead be saved by appending new
+entries from the session to the history file, which could prevent
+potential history loss with multiple Eshell sessions. Unlike other
+shells, such as Bash, Eshell cannot currently be configured to control
+the size of the history file. In particular, when
+@code{eshell-history-append} is non-@code{nil}, the size of the file
+will keep increasing, and the recommended way to truncate the file is
+to run the @samp{history -w} command in an Eshell session.
Since the default buffer navigation and searching key-bindings are
still present in the Eshell buffer, the commands for history
@@ -1361,9 +1402,15 @@ Concatenate the string representation of each value.
@node Dollars Expansion
@section Dollars Expansion
-Eshell has different @code{$} expansion syntax from other shells. There
-are some similarities, but don't let these lull you into a false sense
-of familiarity.
+Like in many other shells, you can use @code{$} expansions to insert
+various values into your Eshell invocations. While Eshell's @code{$}
+expansion syntax has some similarities to the syntax from other
+shells, there are also many differences. Don't let these similarities
+lull you into a false sense of familiarity.
+
+When using command form (@pxref{Invocation}), Eshell will ignore any
+leading nil values, so if @var{foo} is @code{nil}, @samp{$@var{foo}
+echo hello} is equivalent to @samp{echo hello}.
@table @code
@@ -2538,8 +2585,6 @@ A special associate array, which can take references of the form
@samp{$=[REGEXP]}. It indexes into the directory ring.
@end table
-@item Eshell scripts can't execute in the background
-
@item Support zsh's ``Parameter Expansion'' syntax, i.e., @samp{$@{@var{name}:-@var{val}@}}
@item Create a mode @code{eshell-browse}
@@ -2562,11 +2607,6 @@ If it's a Lisp function, input redirection implies @command{xargs} (in a
way@dots{}). If input redirection is added, also update the
@code{file-name-quote-list}, and the delimiter list.
-@item Allow @samp{#<@var{word} @var{arg}>} as a generic syntax
-
-With the handling of @emph{word} specified by an
-@code{eshell-special-alist}.
-
@item In @code{eshell-eval-using-options}, allow a @code{:complete} tag
It would be used to provide completion rules for that command. Then the
diff --git a/doc/misc/eudc.texi b/doc/misc/eudc.texi
index d82dec971cd..615ab76c326 100644
--- a/doc/misc/eudc.texi
+++ b/doc/misc/eudc.texi
@@ -14,7 +14,7 @@ This file documents EUDC version 1.40.0.
EUDC is the Emacs Unified Directory Client, a common interface to
directory servers and contact information.
-Copyright @copyright{} 1998, 2000--2023 Free Software Foundation, Inc.
+Copyright @copyright{} 1998, 2000--2024 Free Software Foundation, Inc.
@quotation
Permission is granted to copy, distribute and/or modify this document
diff --git a/doc/misc/eww.texi b/doc/misc/eww.texi
index abd498824c5..5e69b11d347 100644
--- a/doc/misc/eww.texi
+++ b/doc/misc/eww.texi
@@ -8,7 +8,7 @@
@copying
This file documents the GNU Emacs Web Wowser (EWW) package.
-Copyright @copyright{} 2014--2023 Free Software Foundation, Inc.
+Copyright @copyright{} 2014--2024 Free Software Foundation, Inc.
@quotation
Permission is granted to copy, distribute and/or modify this document
diff --git a/doc/misc/flymake.texi b/doc/misc/flymake.texi
index 237f0702778..84a74a9d6ab 100644
--- a/doc/misc/flymake.texi
+++ b/doc/misc/flymake.texi
@@ -13,7 +13,7 @@
@copying
This manual is for GNU Flymake (version @value{VERSION}, @value{UPDATED}).
-Copyright @copyright{} 2004--2023 Free Software Foundation, Inc.
+Copyright @copyright{} 2004--2024 Free Software Foundation, Inc.
@quotation
Permission is granted to copy, distribute and/or modify this document
@@ -59,12 +59,11 @@ types of diagnostics.
To learn about using Flymake, @pxref{Using Flymake}.
-Flymake is designed to be easily extended to support new backends via
-an Elisp interface. @xref{Extending Flymake}.
-
-Historically, Flymake used to accept diagnostics from a single
-backend. Although obsolete, it is still functional. To learn how to
-use and customize it, @pxref{The legacy Proc backend}.
+When the Emacs LSP support mode Eglot is enabled, Flymake will use
+that as an additional back-end. @xref{Eglot Features,,, eglot, Eglot:
+The Emacs LSP Client} Flymake is also designed to be easily extended
+to support new backends via an Elisp interface. @xref{Extending
+Flymake}.
@ifnottex
@insertcopying
@@ -93,6 +92,10 @@ already setup this hook for you, by adding @dfn{backend functions} to
@code{flymake-diagnostic-functions}. If you know Elisp you may also
write your own Flymake backend functions. @xref{Backend functions}.
+When the Emacs LSP support mode Eglot is enabled, Flymake will use
+that as an additional back-end automatically. @xref{Eglot Features,,,
+eglot, Eglot: The Emacs LSP Client}
+
@menu
* Starting Flymake::
* Finding diagnostics::
diff --git a/doc/misc/forms.texi b/doc/misc/forms.texi
index a7bc49c7dfd..e0221d90fd9 100644
--- a/doc/misc/forms.texi
+++ b/doc/misc/forms.texi
@@ -20,7 +20,7 @@
@copying
This file documents Forms mode, a form-editing major mode for GNU Emacs.
-Copyright @copyright{} 1989, 1997, 2001--2023 Free Software Foundation,
+Copyright @copyright{} 1989, 1997, 2001--2024 Free Software Foundation,
Inc.
@quotation
diff --git a/doc/misc/gnus-faq.texi b/doc/misc/gnus-faq.texi
index eb416fe47d6..33c9f3bea81 100644
--- a/doc/misc/gnus-faq.texi
+++ b/doc/misc/gnus-faq.texi
@@ -1,7 +1,7 @@
@c \input texinfo @c -*-texinfo-*-
@c Uncomment 1st line before texing this file alone.
@c %**start of header
-@c Copyright (C) 1995--2023 Free Software Foundation, Inc.
+@c Copyright (C) 1995--2024 Free Software Foundation, Inc.
@c
@c @setfilename gnus-faq.info
@c @settitle Frequently Asked Questions
diff --git a/doc/misc/gnus.texi b/doc/misc/gnus.texi
index f017b011d71..1d1c15f6494 100644
--- a/doc/misc/gnus.texi
+++ b/doc/misc/gnus.texi
@@ -8,7 +8,7 @@
@syncodeindex pg cp
@copying
-Copyright @copyright{} 1995--2023 Free Software Foundation, Inc.
+Copyright @copyright{} 1995--2024 Free Software Foundation, Inc.
@quotation
Permission is granted to copy, distribute and/or modify this document
@@ -3216,7 +3216,7 @@ if address "sender" "sieve-admin@@extundo.com" @{
@end example
To generate tests for multiple email-addresses use a group parameter
-like @code{(sieve address "sender" ("name@@one.org" else@@two.org"))}.
+like @code{(sieve address "sender" ("name@@one.org" "else@@two.org"))}.
When generating a sieve script (@pxref{Sieve Commands}) Sieve code
like the following is generated:
@@ -3372,7 +3372,7 @@ You can define different sorting to different groups via
group by reverse date to see the latest news at the top and an
@acronym{RSS} group by subject. In this example, the first group is the
Debian daily news group @code{gmane.linux.debian.user.news} from
-news.gmane.org. The @acronym{RSS} group corresponds to the Debian
+news.gmane.io. The @acronym{RSS} group corresponds to the Debian
weekly news RSS feed
@url{https://packages.debian.org/unstable/newpkg_main.en.rdf},
@xref{RSS}.
@@ -4426,7 +4426,7 @@ A select method can be very long, like:
@lisp
(nntp "gmane"
- (nntp-address "news.gmane.org")
+ (nntp-address "news.gmane.io")
(nntp-end-of-line "\n")
(nntp-open-connection-function
nntp-open-via-rlogin-and-telnet)
@@ -5868,15 +5868,23 @@ original message but ignore the @code{Reply-To} field
@findex gnus-summary-mail-forward
@c @icon{gnus-summary-mail-forward}
Forward the current article to some other person
-(@code{gnus-summary-mail-forward}). If no prefix is given, the message
-is forwarded according to the value of (@code{message-forward-as-mime})
-and (@code{message-forward-show-mml}); if the prefix is 1, decode the
-message and forward directly inline; if the prefix is 2, forward message
-as an rfc822 @acronym{MIME} section; if the prefix is 3, decode message and
-forward as an rfc822 @acronym{MIME} section; if the prefix is 4, forward message
-directly inline; otherwise, the message is forwarded as no prefix given
-but use the flipped value of (@code{message-forward-as-mime}). By
-default, the forwarded message is inlined into the mail.
+(@code{gnus-summary-mail-forward}). If no prefix is given, the
+message is forwarded according to the value of
+(@code{message-forward-as-mime}) and
+(@code{message-forward-show-mml}); if the prefix is 1, decode the
+message and forward directly inline; if the prefix is 2, forward
+message as an rfc822 @acronym{MIME} section; if the prefix is 3,
+decode message and forward as an rfc822 @acronym{MIME} section; if the
+prefix is 4, forward message directly inline; otherwise, the message
+is forwarded as no prefix given but use the negated value of
+(@code{message-forward-as-mime}). By default, the forwarded message
+is inlined into the mail.
+
+Which headers from the original message are included in the forwarded
+message is determined by options specific to @code{message-mode},
+@pxref{Forwarding,,, message}. In addition, this command can be given
+the symbolic prefix @samp{a}, using @kbd{M-i a}, to include most original
+headers.
@item S m
@itemx m
@@ -6235,13 +6243,6 @@ Presumably, you want to use the demon for sending due delayed articles.
Just don't forget to set that up :-)
@end table
-When delaying an article with @kbd{C-c C-j}, Message mode will
-automatically add a @code{"Date"} header with the current time. In
-many cases you probably want the @code{"Date"} header to reflect the
-time the message is sent instead. To do this, you have to delete
-@code{Date} from @code{message-draft-headers}.
-
-
@node Marking Articles
@section Marking Articles
@cindex article marking
@@ -7279,7 +7280,7 @@ The server has to support @acronym{NOV} for any of this to work.
@cindex Gmane, @code{gnus-fetch-old-headers}
This feature can seriously impact performance it ignores all locally
cached header entries. Setting it to @code{t} for groups for a server
-that doesn't expire articles (such as news.gmane.org), leads to very
+that doesn't expire articles (such as news.gmane.io), leads to very
slow summary generation.
@item gnus-fetch-old-ephemeral-headers
@@ -18020,7 +18021,7 @@ Here is an example:
(nnselect-args
. [["nnimap+work:mail" 595 100]
["nnimap+home:sent" 223 100]
- ["nntp+news.gmane.org:gmane.emacs.gnus.general" 23666 100]]))
+ ["nntp+news.gmane.io:gmane.emacs.gnus.general" 23666 100]]))
@end lisp
The function is the identity and the argument is just the list of
@@ -21596,7 +21597,7 @@ Search Groups}).
Search queries can be specified one of two ways: either using the
syntax of the engine responsible for the group you're searching, or
using Gnus' generalized search syntax. Set the option
-@code{gnus-search-use-parsed-queries} to a non-@code{nil} value to used the
+@code{gnus-search-use-parsed-queries} to a non-@code{nil} value to use the
generalized syntax. The advantage of this syntax is that, if you have
multiple backends indexed by different engines, you don't need to
remember which one you're searching---it's also possible to issue the
@@ -24526,8 +24527,8 @@ that is needed. It can also contain @samp{(@var{addr} @var{string}
@var{amount})} cells, where the @var{string} is the string to use
(normally the email address or newsgroup name is used).
-@item hashcash-path
-@vindex hashcash-path
+@item hashcash-program
+@vindex hashcash-program
Where the @code{hashcash} binary is installed. This variable should
be automatically set by @code{executable-find}, but if it's @code{nil}
(usually because the @code{hashcash} binary is not in your path)
@@ -24841,7 +24842,7 @@ ends such as Bogofilter (@pxref{Bogofilter}) and the Spam Statistics
package (@pxref{Spam Statistics Filtering}).
The spam and ham processors that apply to each group are determined by
-the group's@code{spam-process} group parameter. If this group
+the group's @code{spam-process} group parameter. If this group
parameter is not defined, they are determined by the variable
@code{gnus-spam-process-newsgroups}.
@@ -25155,9 +25156,9 @@ groups as spam and reports the to Gmane at group exit:
@end lisp
Additionally, I use @code{(setq spam-report-gmane-use-article-number nil)}
-because I don't read the groups directly from news.gmane.org, but
+because I don't read the groups directly from news.gmane.io, but
through my local news server (leafnode). I.e., the article numbers are
-not the same as on news.gmane.org, thus @code{spam-report.el} has to check
+not the same as on news.gmane.io, thus @code{spam-report.el} has to check
the @code{X-Report-Spam} header to find the correct number.
@node Spam Back Ends
@@ -25341,7 +25342,7 @@ added to a group's @code{spam-process} parameter, the spam-marked
articles groups will be reported to the Gmane administrators via a
HTTP request.
-Gmane was formerly found at @uref{http://gmane.org}.
+Gmane is at @uref{https://gmane.io}.
@emph{WARNING}
@@ -26434,12 +26435,12 @@ lines:
(setq gnus-refer-article-method
'(current
(nnregistry)
- (nnweb "gmane" (nnweb-type gmane))))
+ (nnweb "google" (nnweb-type google))))
@end example
The example above instructs Gnus to first look up the article in the
current group, or, alternatively, using the registry, and finally, if
-all else fails, using Gmane.
+all else fails, using Google.
@node Fancy splitting to parent
@subsection Fancy splitting to parent
@@ -28808,7 +28809,7 @@ be read correctly in Emacs 22 and below. If you want to use Gnus across
different Emacs versions, you may set @code{mm-auto-save-coding-system}
to @code{emacs-mule}.
@c FIXME: Untested. (Or did anyone test it?)
-@c Cf. http://thread.gmane.org/gmane.emacs.gnus.general/66251/focus=66344
+@c Cf. http://thread.gmane.org/gmane.emacs.gnus.general/66251/focus=66344 [dead link]
@item Lisp files are now installed in @file{.../site-lisp/gnus/} by default.
It defaulted to @file{.../site-lisp/} formerly. In addition to this,
@@ -29321,13 +29322,13 @@ have names like @samp{gnu.emacs.gnus}.
You can also have any number of foreign groups active at the same
time. These are groups that use non-native non-secondary back ends
for getting news. Foreign groups have names like
-@samp{nntp+news.gmane.org:gmane.emacs.gnus.devel}.
+@samp{nntp+news.gmane.io:gmane.emacs.gnus.devel}.
@item secondary
@cindex secondary
Secondary back ends are somewhere half-way between being native and
being foreign, but they mostly act like they are native, but they, too
-have names like @samp{nntp+news.gmane.org:gmane.emacs.gnus.devel}.
+have names like @samp{nntp+news.gmane.io:gmane.emacs.gnus.devel}.
@item article
@cindex article
diff --git a/doc/misc/htmlfontify.texi b/doc/misc/htmlfontify.texi
index fa45f9361ab..258c743ac8f 100644
--- a/doc/misc/htmlfontify.texi
+++ b/doc/misc/htmlfontify.texi
@@ -10,7 +10,7 @@
This manual documents Htmlfontify, a source code -> crosslinked +
formatted + syntax colorized html transformer.
-Copyright @copyright{} 2002--2023 Free Software Foundation, Inc.
+Copyright @copyright{} 2002--2024 Free Software Foundation, Inc.
@quotation
Permission is granted to copy, distribute and/or modify this document
diff --git a/doc/misc/idlwave.texi b/doc/misc/idlwave.texi
index 10fc4c85c7b..782812169ca 100644
--- a/doc/misc/idlwave.texi
+++ b/doc/misc/idlwave.texi
@@ -23,7 +23,7 @@ Emacs, and interacting with an IDL shell run as a subprocess.
This is edition @value{EDITION} of the IDLWAVE User Manual for IDLWAVE
@value{VERSION}.
-Copyright @copyright{} 1999--2023 Free Software Foundation, Inc.
+Copyright @copyright{} 1999--2024 Free Software Foundation, Inc.
@quotation
Permission is granted to copy, distribute and/or modify this document
@@ -3186,7 +3186,7 @@ the expression printed by IDL.
@defopt idlwave-shell-output-face
The face for @code{idlwave-shell-output-overlay}.
-Allows to choose the font, color and other properties for the most
+Allows you to choose the font, color and other properties for the most
recent output of IDL when examining an expression."
@end defopt
diff --git a/doc/misc/ido.texi b/doc/misc/ido.texi
index dca92f00069..ad293f41c2f 100644
--- a/doc/misc/ido.texi
+++ b/doc/misc/ido.texi
@@ -7,7 +7,7 @@
@copying
This file documents the Ido package for GNU Emacs.
-Copyright @copyright{} 2013--2023 Free Software Foundation, Inc.
+Copyright @copyright{} 2013--2024 Free Software Foundation, Inc.
@quotation
Permission is granted to copy, distribute and/or modify this document
diff --git a/doc/misc/info.texi b/doc/misc/info.texi
index ba00dbcf2bd..31b314cb9a0 100644
--- a/doc/misc/info.texi
+++ b/doc/misc/info.texi
@@ -15,7 +15,7 @@
This file describes how to use Info, the menu-driven GNU
documentation system.
-Copyright @copyright{} 1989, 1992, 1996--2023 Free Software Foundation,
+Copyright @copyright{} 1989, 1992, 1996--2024 Free Software Foundation,
Inc.
@quotation
diff --git a/doc/misc/mairix-el.texi b/doc/misc/mairix-el.texi
index 12016bee387..024d7bb038a 100644
--- a/doc/misc/mairix-el.texi
+++ b/doc/misc/mairix-el.texi
@@ -5,7 +5,7 @@
@include docstyle.texi
@copying
-Copyright @copyright{} 2008--2023 Free Software Foundation, Inc.
+Copyright @copyright{} 2008--2024 Free Software Foundation, Inc.
@quotation
Permission is granted to copy, distribute and/or modify this document
diff --git a/doc/misc/message.texi b/doc/misc/message.texi
index 8064af53fc6..d881244c735 100644
--- a/doc/misc/message.texi
+++ b/doc/misc/message.texi
@@ -9,7 +9,7 @@
@copying
This file documents Message, the Emacs message composition mode.
-Copyright @copyright{} 1996--2023 Free Software Foundation, Inc.
+Copyright @copyright{} 1996--2024 Free Software Foundation, Inc.
@quotation
Permission is granted to copy, distribute and/or modify this document
diff --git a/doc/misc/mh-e.texi b/doc/misc/mh-e.texi
index caee0ed2c70..3e98a14ecfc 100644
--- a/doc/misc/mh-e.texi
+++ b/doc/misc/mh-e.texi
@@ -25,7 +25,7 @@
This is version @value{VERSION}@value{EDITION} of @cite{The MH-E
Manual}, last updated @value{UPDATED}.
-Copyright @copyright{} 1995, 2001--2003, 2005--2023 Free Software
+Copyright @copyright{} 1995, 2001--2003, 2005--2024 Free Software
Foundation, Inc.
@c This dual license has been agreed upon by the FSF.
@@ -1479,7 +1479,6 @@ Binding} of @samp{m}.
@cindex @command{emacsclient}
@cindex @command{xbuffy}
-@cindex @samp{gnuserv}
@cindex Unix commands, @command{emacsclient}
@cindex Unix commands, @command{xbuffy}
@@ -8920,7 +8919,7 @@ Bill Wohler, August 2008
@c LocalWords: Baushke Bcc BBN Beranek bogofilter bogofilter's
@c LocalWords: cmd CMU contrib cron
@c LocalWords: DesBrisay Dcc devel dir dired docstring filll forw
-@c LocalWords: GECOS Gildea Gildea's Ginnean GnuCash goto gnuserv htm
+@c LocalWords: GECOS Gildea Gildea's Ginnean GnuCash goto htm
@c LocalWords: ImageMagick inbox ispell keychain
@c LocalWords: Larus licensor LocalWords lookup lpr
@c LocalWords: makeinfo mairix mbox mh mhbuild mhl mhpath mlisp
diff --git a/doc/misc/modus-themes.org b/doc/misc/modus-themes.org
index ae760624b6f..45f96778203 100644
--- a/doc/misc/modus-themes.org
+++ b/doc/misc/modus-themes.org
@@ -4,9 +4,9 @@
#+language: en
#+options: ':t toc:nil author:t email:t num:t
#+startup: content
-#+macro: stable-version 4.2.0
-#+macro: release-date 2023-05-30
-#+macro: development-version 4.3.0-dev
+#+macro: stable-version 4.3.0
+#+macro: release-date 2023-09-19
+#+macro: development-version 4.4.0-dev
#+macro: file @@texinfo:@file{@@$1@@texinfo:}@@
#+macro: space @@texinfo:@: @@
#+macro: kbd @@texinfo:@kbd{@@$1@@texinfo:}@@
@@ -52,7 +52,7 @@ Current development target is {{{development-version}}}.
:custom_id: h:b14c3fcb-13dd-4144-9d92-2c58b3ed16d3
:end:
-Copyright (C) 2020-2023 Free Software Foundation, Inc.
+Copyright (C) 2020-2024 Free Software Foundation, Inc.
#+begin_quote
Permission is granted to copy, distribute and/or modify this document
@@ -90,7 +90,7 @@ The Modus themes consist of eight themes, divided into four subgroups.
are variants of the two main themes. They slightly tone down the
intensity of the background and provide a bit more color variety.
~modus-operandi-tinted~ has a set of base tones that are shades of
- light ochre (earthly colors), while ~modus-vivendi-tinted~ gives a
+ light ocher (earthly colors), while ~modus-vivendi-tinted~ gives a
night sky impression.
- Deuteranopia themes :: ~modus-operandi-deuteranopia~ and its
@@ -581,11 +581,11 @@ Possible values:
All theme user options take effect when a theme is loaded. Any
subsequent changes require the theme to be reloaded.
-When this variable has a non-nil value, any change made via the Custom
+When this variable has a non-~nil~ value, any change made via the Custom
UI or related functions such as ~customize-set-variable~ and ~setopt~
(Emacs 29), will trigger a reload automatically.
-With a nil value, changes to user options have no further consequences:
+With a ~nil~ value, changes to user options have no further consequences:
the user must manually reload the theme ([[#h:3f3c3728-1b34-437d-9d0c-b110f5b161a9][Enable and load]]).
** Option for disabling other themes while loading Modus
@@ -605,20 +605,20 @@ Possible values:
1. ~nil~
2. ~t~ (default)
-When the value is non-nil, the commands ~modus-themes-toggle~ and
+When the value is non-~nil~, the commands ~modus-themes-toggle~ and
~modus-themes-select~, as well as the ~modus-themes-load-theme~
function, will disable all other themes while loading the specified
Modus theme. This is done to ensure that Emacs does not blend two or
more themes: such blends lead to awkward results that undermine the
work of the designer.
-When the value is nil, the aforementioned commands and function will
+When the value is ~nil~, the aforementioned commands and function will
only disable other themes within the Modus collection.
This option is provided because Emacs themes are not necessarily
limited to colors/faces: they can consist of an arbitrary set of
customizations. Users who use such customization bundles must set
-this variable to a nil value.
+this variable to a ~nil~ value.
** Option for more bold constructs
:properties:
@@ -794,7 +794,7 @@ followed by a description of the particularities:
#+end_src
The ~matches~ key refers to the highlighted characters that correspond
-to the user's input. When its properties are nil or an empty list,
+to the user's input. When its properties are ~nil~ or an empty list,
matching characters in the user interface will have a bold weight and
a colored foreground. The list of properties may include any of the
following symbols regardless of the order they may appear in:
@@ -810,7 +810,7 @@ following symbols regardless of the order they may appear in:
The ~selection~ key applies to the current line or currently matched
candidate, depending on the specifics of the user interface. When its
-properties are nil or an empty list, it has a subtle gray background,
+properties are ~nil~ or an empty list, it has a subtle gray background,
a bold weight, and the base foreground value for the text. The list
of properties it accepts is as follows (order is not significant):
@@ -861,10 +861,10 @@ Possible values:
2. ~gray-background~
3. ~tinted-background~
-Nil (the default) means that the block has no background of its own:
-it uses the one that applies to the rest of the buffer. In this case,
-the delimiter lines have a gray color for their text, making them look
-exactly like all other Org properties.
+Option ~nil~ (the default) means that the block has no background of
+its own: it uses the one that applies to the rest of the buffer.
+In this case, the delimiter lines have a gray color for their text,
+making them look exactly like all other Org properties.
Option ~gray-background~ applies a subtle gray background to the
block's contents. It also affects the begin and end lines of the
@@ -883,9 +883,9 @@ For this to take effect, the Org buffer needs to be restarted with
~org-mode-restart~.
Code blocks use their major mode's fontification (syntax highlighting)
-only when the variable ~org-src-fontify-natively~ is non-nil. While
+only when the variable ~org-src-fontify-natively~ is non-~nil~. While
quote/verse blocks require setting
-~org-fontify-quote-and-verse-blocks~ to a non-nil value.
+~org-fontify-quote-and-verse-blocks~ to a non-~nil~ value.
[[#h:f44cc6e3-b0f1-4a5e-8a90-9e48fa557b50][Update Org block delimiter fontification]].
@@ -2518,7 +2518,7 @@ manual, here is what Protesilaos uses:
;; Add a nuanced background as well.
(bg-prompt bg-magenta-nuanced)
(fg-prompt magenta-cooler)
- ;; Tweak some more constructs for stylistic constistency.
+ ;; Tweak some more constructs for stylistic consistency.
(name blue-warmer)
(identifier magenta-faint)
(keybind magenta-cooler)
@@ -2717,7 +2717,7 @@ For a more elaborate design, it is better to inspect the source code of
[[#h:51ba3547-b8c8-40d6-ba5a-4586477fd4ae][Use theme colors in code with modus-themes-with-colors]].
#+findex: modus-themes-get-color-value
-The fuction ~modus-themes-get-color-value~ can be called from Lisp to
+The function ~modus-themes-get-color-value~ can be called from Lisp to
return the value of a color from the active Modus theme palette. It
takea a =COLOR= argument and an optional =OVERRIDES=.
@@ -2730,7 +2730,7 @@ If the value is the name of another color entry in the palette (so a
mapping), this function recurs until it finds the underlying color
value.
-With an optional =OVERRIDES= argument as a non-nil value, it accounts
+With an optional =OVERRIDES= argument as a non-~nil~ value, it accounts
for palette overrides. Else it reads only the default palette.
[[#h:34c7a691-19bb-4037-8d2f-67a07edab150][Option for palette overrides]].
@@ -2884,9 +2884,9 @@ above:
#+end_src
The reason we no longer provide this option is because it depends on a
-non-nil value for ~x-underline-at-descent-line~. That variable
+non-~nil~ value for ~x-underline-at-descent-line~. That variable
affects ALL underlines, including those of links. The effect is
-intrusive and looks awkard in prose.
+intrusive and looks awkward in prose.
As such, the Modus themes no longer provide that option but instead
offer this piece of documentation to make the user fully aware of the
@@ -3150,20 +3150,20 @@ have something like this:
#+end_src
You could then use a variant of the following to inherit from a face
-that uses the styles you want and also to preserve the properties
-applied by the ~org-todo~ face (in case there is a difference between the
-two):
+that uses the styles you want and also to preserve the attributes
+applied by the ~org-todo~ face (in case there is a difference between
+the two):
#+begin_src emacs-lisp
(setq org-todo-keyword-faces
- '(("MEET" . '(bold org-todo))
- ("STUDY" . '(warning org-todo))
- ("WRITE" . '(shadow org-todo))))
+ '(("MEET" . (:inherit (bold org-todo)))
+ ("STUDY" . (:inherit (warning org-todo)))
+ ("WRITE" . (:inherit (shadow org-todo)))))
#+end_src
This will refashion the keywords you specify, while letting the other
-items in ~org-todo-keywords~ use their original styles (which are defined
-in the ~org-todo~ and ~org-done~ faces).
+items in ~org-todo-keywords~ use their original styles, which are
+defined in the ~org-todo~ and ~org-done~ faces.
If you want back the defaults, try specifying just the ~org-todo~ face:
@@ -3174,24 +3174,27 @@ If you want back the defaults, try specifying just the ~org-todo~ face:
("WRITE" . org-todo)))
#+end_src
-When you inherit from multiple faces, you need to quote the list as
+Or set ~org-todo-keyword-faces~ to ~nil~.
+
+When you inherit from multiple faces, you need to do it the way it is
shown further above. The order is significant: the first entry is
-applied on top of the second, overriding any properties that are
-explicitly set for both of them: any property that is not specified is
-not overridden, so, for example, if ~org-todo~ has a background and a
-foreground, while ~font-lock-type-face~ only has a foreground, the merged
-face will include the background of the former and the foreground of the
-latter. If you do not want to blend multiple faces, you do not need a
-quoted list. A pattern of =keyword . face= will suffice.
+applied on top of the second, overriding any attributes that are
+explicitly set for both of them: any attribute that is not specified
+is not overridden, so, for example, if ~org-todo~ has a background and
+a foreground, while ~font-lock-type-face~ only has a foreground, the
+merged face will include the background of the former and the
+foreground of the latter. If you do not want to blend multiple faces,
+you only specify one by name without parentheses or an =:inherit=
+keyword. A pattern of =keyword . face= will suffice.
Both approaches can be used simultaneously, as illustrated in this
configuration of the priority cookies:
#+begin_src emacs-lisp
(setq org-priority-faces
- '((?A . '(bold org-priority))
+ '((?A . (:inherit (bold org-priority)))
(?B . org-priority)
- (?C . '(shadow org-priority))))
+ (?C . (:inherit (shadow org-priority)))))
#+end_src
To find all the faces that are loaded in your current Emacs session, use
@@ -3226,7 +3229,7 @@ specification of that variable looks like this:
With the exception of ~org-verbatim~ and ~org-code~ faces, everything else
uses the corresponding type of emphasis: a bold typographic weight, or
-italicised, underlined, and struck through text.
+italicized, underlined, and struck through text.
The best way for users to add some extra attributes, such as a
foreground color, is to define their own faces and assign them to the
@@ -3636,6 +3639,10 @@ need to (provided they understand the implications).
:CUSTOM_ID: h:43bcb5d0-e25f-470f-828c-662cee9e21f1
:END:
+[ UPDATE 2023-06-25: Instead of following these instructions, you can
+ simply install my ~spacious-padding~ package from GNU ELPA. It
+ implements the padding and provides relevant user options. ]
+
By default, Emacs frames try to maximize the number of characters that
fit in the current visible portion of the buffer. Users may prefer to
have some extra padding instead. This can make Emacs frames look more
@@ -3847,6 +3854,7 @@ have lots of extensions, so the "full support" may not be 100% true…
+ avy
+ bbdb
+ binder
++ breadcrumb
+ bongo
+ boon
+ bookmark
@@ -3864,11 +3872,11 @@ have lots of extensions, so the "full support" may not be 100% true…
+ completions
+ consult
+ corfu
++ corfu-candidate-overlay
+ corfu-quick
+ counsel*
+ cperl-mode
+ crontab-mode
-+ css-mode
+ csv-mode
+ ctrlf
+ custom (what you get with {{{kbd(M-x customize)}}})
@@ -3905,6 +3913,7 @@ have lots of extensions, so the "full support" may not be 100% true…
+ epa
+ erc
+ ert
++ erts-mode
+ eshell
+ eshell-fringe-status
+ evil* (evil-mode)
@@ -3951,6 +3960,7 @@ have lots of extensions, so the "full support" may not be 100% true…
+ isearch, occur, etc.
+ ivy*
+ ivy-posframe
++ japanese-holidays
+ jira (org-jira)
+ jit-spell
+ jinx
@@ -3975,6 +3985,10 @@ have lots of extensions, so the "full support" may not be 100% true…
+ mpdel
+ mu4e
+ multiple-cursors
++ nerd-icons
++ nerd-icons-completion
++ nerd-icons-dired
++ nerd-icons-ibuffer
+ neotree
+ notmuch
+ num3-mode
@@ -4038,7 +4052,6 @@ have lots of extensions, so the "full support" may not be 100% true…
+ suggest
+ switch-window
+ swiper
-+ sx
+ symbol-overlay
+ syslog-mode
+ tab-bar-mode
@@ -4099,6 +4112,7 @@ supported by the themes.
+ bufler
+ counsel-notmuch
+ counsel-org-capture-string
++ css-mode
+ dashboard (emacs-dashboard)
+ define-word
+ denote
@@ -4382,7 +4396,7 @@ advanced customization options of the themes.
[[#h:f4651d55-8c07-46aa-b52b-bed1e53463bb][Advanced customization]].
In the following example, we are assuming that the user wants to (i)
-re-use color variables provided by the themes, (ii) be able to retain
+reuse color variables provided by the themes, (ii) be able to retain
their tweaks while switching between ~modus-operandi~ and ~modus-vivendi~,
and (iii) have the option to highlight either the foreground of the
parentheses or the background as well.
@@ -4402,7 +4416,7 @@ Then we can update our preference with this:
(setq my-highlight-parentheses-use-background nil)
#+end_src
-To re-use colors from the themes, we must wrap our code in the
+To reuse colors from the themes, we must wrap our code in the
~modus-themes-with-colors~ macro. Our implementation must interface with
the variables ~highlight-parentheses-background-colors~ and/or
~highlight-parentheses-colors~.
@@ -4722,7 +4736,7 @@ Consult the doc string of ~shr-use-colors~.
By default, packages that build on top of the Simple HTML Remember
(~shr~) use proportionately spaced fonts. This is controlled by the
user option ~shr-use-fonts~, which is set to non-~nil~ by default. To
-use the standard font instead, set that variable to nil.
+use the standard font instead, set that variable to ~nil~.
[[#h:defcf4fc-8fa8-4c29-b12e-7119582cc929][Font configurations for Org and others]].
@@ -4859,7 +4873,7 @@ consider including (or equivalent) this in their setup:
goto-address-mail-mouse-face 'highlight)
#+end_src
-My personal preference is to set ~goto-address-mail-face~ to nil, as
+My personal preference is to set ~goto-address-mail-face~ to ~nil~, as
it otherwise adds too much visual noise to the buffer (email addresses
stand out more, due to the use of the uncommon =@= character but also
because they are often enclosed in angled brackets).
@@ -5012,7 +5026,7 @@ more effective than trying to do the same with either red or blue (the
latter is the least effective in that regard).
When we need to work with several colors, it is always better to have
-sufficient manoeuvring space, especially since we cannot pick arbitrary
+sufficient maneuvering space, especially since we cannot pick arbitrary
colors but only those that satisfy the accessibility objectives of the
themes.
@@ -5066,7 +5080,7 @@ each of the three channels of light (red, green, blue). For example:
: xrandr --output LVDS1 --brightness 1.0 --gamma 0.76:0.75:0.68
Typography is another variable. Some font families are blurry at small
-point sizes. Others may have a regular weight that is lighter (thiner)
+point sizes. Others may have a regular weight that is lighter (thinner)
than that of their peers which may, under certain circumstances, cause a
halo effect around each glyph.
@@ -5118,7 +5132,7 @@ it is already understood that one must follow the indicator or headline
to view its contents and (ii) underlining everything would make the
interface virtually unusable.
-Again, one must exercise judgement in order to avoid discrimination,
+Again, one must exercise judgment in order to avoid discrimination,
where "discrimination" refers to:
+ The treatment of substantially different magnitudes as if they were of
@@ -5192,7 +5206,7 @@ the themes, which is partially fleshed out in this manual.
With regard to the artistic aspect (where "art" qua skill may amount to
an imprecise science), there is no hard-and-fast rule in effect as it
-requires one to exercize discretion and make decisions based on
+requires one to exercise discretion and make decisions based on
context-dependent information or constraints. As is true with most
things in life, when in doubt, do not cling on to the letter of the law
but try to understand its spirit.
@@ -5345,8 +5359,9 @@ The Modus themes are a collective effort. Every bit of work matters.
Matthew Stevenson, Mauro Aranda, Nacho Barrientos, Nicolas De
Jaeghere, Paul David, Philip Kaludercic, Pierre Téchoueyres, Rudolf
Adamkovič, Sergey Nichiporchik, Shreyas Ragavan, Stefan Kangas,
- Stephen Gildea, Steve Downey, Tomasz Hołubowicz, Utkarsh Singh,
- Vincent Murphy, Xinglu Chen, Yuanchen Xie, okamsn.
+ Stephen Berman, Stephen Gildea, Steve Downey, Tomasz Hołubowicz,
+ Utkarsh Singh, Vincent Murphy, Xinglu Chen, Yuanchen Xie, fluentpwn,
+ okamsn.
+ Ideas and user feedback :: Aaron Jensen, Adam Porter, Adam Spiers,
Adrian Manea, Aleksei Pirogov, Alex Griffin, Alex Koen, Alex
@@ -5363,25 +5378,25 @@ The Modus themes are a collective effort. Every bit of work matters.
Ferguson, Jeremy Friesen, Jerry Zhang, Johannes Grødem, John Haman,
Jonas Collberg, Jorge Morais, Joshua O'Connor, Julio C. Villasante,
Kenta Usami, Kevin Fleming, Kévin Le Gouguec, Kevin Kainan Li,
- Kostadin Ninev, Laith Bahodi, Len Trigg, Lennart C. Karssen, Luis
- Miguel Castañeda, Magne Hov, Manuel Giraud, Manuel Uberti, Mark
- Bestley, Mark Burton, Mark Simpson, Marko Kocic, Markus Beppler,
- Matt Armstrong, Matthias Fuchs, Mattias Engdegård, Mauro Aranda,
- Maxime Tréca, Michael Goldenberg, Morgan Smith, Morgan Willcock,
- Murilo Pereira, Nicky van Foreest, Nicolas De Jaeghere, Nicolas
- Semrau, Oliver Epper, Pablo Stafforini, Paul Poloskov, Pengji Zhang,
- Pete Kazmier, Peter Wu, Philip Kaludercic, Pierre Téchoueyres,
- Przemysław Kryger, Robert Hepple, Roman Rudakov, Russell Sim, Ryan
- Phillips, Rytis Paškauskas, Rudolf Adamkovič, Sam Kleinman, Samuel
- Culpepper, Saša Janiška, Shreyas Ragavan, Simon Pugnet, Steve
- Downey, Tassilo Horn, Thanos Apollo, Thibaut Verron, Thomas
- Heartman, Togan Muftuoglu, Tony Zorman, Trey Merkley, Tomasz
- Hołubowicz, Toon Claes, Uri Sharf, Utkarsh Singh, Vincent Foley,
- Zoltan Kiraly. As well as users: Ben, CsBigDataHub1, Emacs Contrib,
- Eugene, Fourchaux, Fredrik, Moesasji, Nick, Summer Emacs, TheBlob42,
- TitusMu, Trey, bepolymathe, bit9tream, bangedorrunt, derek-upham,
- doolio, fleimgruber, gitrj95, iSeeU, jixiuf, okamsn, pRot0ta1p,
- soaringbird, tumashu, wakamenod.
+ Kostadin Ninev, Laith Bahodi, Lasse Lindner, Len Trigg, Lennart
+ C. Karssen, Luis Miguel Castañeda, Magne Hov, Manuel Giraud, Manuel
+ Uberti, Mark Bestley, Mark Burton, Mark Simpson, Marko Kocic, Markus
+ Beppler, Matt Armstrong, Matthias Fuchs, Mattias Engdegård, Mauro
+ Aranda, Maxime Tréca, Michael Goldenberg, Morgan Smith, Morgan
+ Willcock, Murilo Pereira, Nicky van Foreest, Nicolas De Jaeghere,
+ Nicolas Semrau, Olaf Meeuwissen, Oliver Epper, Pablo Stafforini,
+ Paul Poloskov, Pengji Zhang, Pete Kazmier, Peter Wu, Philip
+ Kaludercic, Pierre Téchoueyres, Przemysław Kryger, Robert Hepple,
+ Roman Rudakov, Russell Sim, Ryan Phillips, Rytis Paškauskas, Rudolf
+ Adamkovič, Sam Kleinman, Samuel Culpepper, Saša Janiška, Shreyas
+ Ragavan, Simon Pugnet, Steve Downey, Tassilo Horn, Thanos Apollo,
+ Thibaut Verron, Thomas Heartman, Togan Muftuoglu, Tony Zorman, Trey
+ Merkley, Tomasz Hołubowicz, Toon Claes, Uri Sharf, Utkarsh Singh,
+ Vincent Foley, Zoltan Kiraly. As well as users: Ben, CsBigDataHub1,
+ Emacs Contrib, Eugene, Fourchaux, Fredrik, Moesasji, Nick, Summer
+ Emacs, TheBlob42, TitusMu, Trey, bepolymathe, bit9tream,
+ bangedorrunt, derek-upham, doolio, fleimgruber, gitrj95, iSeeU,
+ jixiuf, okamsn, pRot0ta1p, soaringbird, tumashu, wakamenod.
+ Packaging :: Basil L.{{{space()}}} Contovounesios, Eli Zaretskii,
Glenn Morris, Mauro Aranda, Richard Stallman, Stefan Kangas (core
diff --git a/doc/misc/newsticker.texi b/doc/misc/newsticker.texi
index 4a0311cad42..a2ceedf7399 100644
--- a/doc/misc/newsticker.texi
+++ b/doc/misc/newsticker.texi
@@ -15,7 +15,7 @@ This manual documents Newsticker, a feed reader for Emacs. It
corresponds to Emacs version @value{EMACSVER}.
@noindent
-Copyright @copyright{} 2004--2023 Free Software Foundation, Inc.
+Copyright @copyright{} 2004--2024 Free Software Foundation, Inc.
@quotation
Permission is granted to copy, distribute and/or modify this document
diff --git a/doc/misc/nxml-mode.texi b/doc/misc/nxml-mode.texi
index a19c6a8db6b..90a8858fcbf 100644
--- a/doc/misc/nxml-mode.texi
+++ b/doc/misc/nxml-mode.texi
@@ -9,7 +9,7 @@
This manual documents nXML mode, an Emacs major mode for editing
XML with RELAX NG support.
-Copyright @copyright{} 2007--2023 Free Software Foundation, Inc.
+Copyright @copyright{} 2007--2024 Free Software Foundation, Inc.
@quotation
Permission is granted to copy, distribute and/or modify this document
diff --git a/doc/misc/octave-mode.texi b/doc/misc/octave-mode.texi
index 9f82af45203..437aac35292 100644
--- a/doc/misc/octave-mode.texi
+++ b/doc/misc/octave-mode.texi
@@ -6,7 +6,7 @@
@c %**end of header
@copying
-Copyright @copyright{} 1996--2023 Free Software Foundation, Inc.
+Copyright @copyright{} 1996--2024 Free Software Foundation, Inc.
@quotation
Permission is granted to copy, distribute and/or modify this document
@@ -146,9 +146,7 @@ An error is signaled if no block to close is found.
@findex octave-insert-defun
Insert a function skeleton, prompting for the function's name, arguments
and return values which have to be entered without parentheses
-(@code{octave-insert-defun}).
-@noindent
-in one of your Emacs startup files.
+(@code{octave-insert-defun}) in one of your Emacs startup files.
@end table
The following variables can be used to customize Octave mode.
@@ -421,7 +419,7 @@ when Octave is waiting for input, or done sending output.
@bye
-@c TODO Update
+@c TODO Update (and change gnuserv to emacsclient)
@c @node Using the Emacs Info Reader for Octave
@c @chapter Using the Emacs Info Reader for Octave
diff --git a/doc/misc/org-setup.org b/doc/misc/org-setup.org
index e6ace716077..50fdd57bd8a 100644
--- a/doc/misc/org-setup.org
+++ b/doc/misc/org-setup.org
@@ -1,6 +1,6 @@
# SETUPFILE for Org manual
-# Copyright (C) 2021-2023 Free Software Foundation, Inc.
+# Copyright (C) 2021-2024 Free Software Foundation, Inc.
#
# This file is part of GNU Emacs.
#
diff --git a/doc/misc/org.org b/doc/misc/org.org
index a4ce53cc6cb..05ab5b36ca0 100644
--- a/doc/misc/org.org
+++ b/doc/misc/org.org
@@ -4606,7 +4606,7 @@ checked.
#+cindex: statistics, for checkboxes
#+cindex: checkbox statistics
#+cindex: @samp{COOKIE_DATA}, property
-#+vindex: org-hierarchical-checkbox-statistics
+#+vindex: org-checkbox-hierarchical-statistics
The =[2/4]= and =[1/3]= in the first and second line are cookies
indicating how many checkboxes present in this entry have been checked
off, and the total number of checkboxes present. This can give you an
@@ -4614,7 +4614,7 @@ idea on how many checkboxes remain, even without opening a folded
entry. The cookies can be placed into a headline or into (the first
line of) a plain list item. Each cookie covers checkboxes of direct
children structurally below the headline/item on which the cookie
-appears[fn:: Set the variable ~org-hierarchical-checkbox-statistics~
+appears[fn:: Set the variable ~org-checkbox-hierarchical-statistics~
if you want such cookies to count all checkboxes below the cookie, not
just those belonging to direct children.]. You have to insert the
cookie yourself by typing either =[/]= or =[%]=. With =[/]= you get
@@ -9431,7 +9431,7 @@ the estimated effort of an entry (see [[*Effort Estimates]]).
#+vindex: org-agenda-effort-filter-preset
#+vindex: org-agenda-regexp-filter-preset
Agenda built-in or custom commands are statically defined. Agenda
-filters and limits allow to flexibly narrow down the list of agenda
+filters and limits allow flexibly narrowing down the list of agenda
entries.
/Filters/ only change the visibility of items, are very fast and are
@@ -20266,12 +20266,12 @@ packages are documented here.
#+vindex: org-table-formula-constants
Org can use names for constants in formulas in tables. Org can also
- use calculation suffixes for units, such as =M= for =Mega=. For
- a standard collection of such constants, install the =constants=
+ use calculation suffixes for units, such as =M= for =Mega=. For a
+ standard collection of such constants, install the =constants=
package. Install version 2.0 of this package, available at
- [[http://www.astro.uva.nl/~dominik/Tools]]. Org checks if the function
- ~constants-get~ has been autoloaded. Installation instructions are
- in the file =constants.el=.
+ [[https://github.com/cdominik/constants-for-Emacs]]. Org checks if the
+ function ~constants-get~ has been autoloaded. Installation
+ instructions are in the file =constants.el=.
- =cdlatex.el= by Carsten Dominik ::
#+cindex: @file{cdlatex.el}
@@ -22315,7 +22315,7 @@ that are mentioned in the manual. For a more complete list, use
This manual is for Org version {{{version}}}.
-Copyright \copy 2004--2023 Free Software Foundation, Inc.
+Copyright \copy 2004--2024 Free Software Foundation, Inc.
#+begin_quote
Permission is granted to copy, distribute and/or modify this document
diff --git a/doc/misc/pcl-cvs.texi b/doc/misc/pcl-cvs.texi
index b64eaf2667e..e1504b08a3a 100644
--- a/doc/misc/pcl-cvs.texi
+++ b/doc/misc/pcl-cvs.texi
@@ -7,7 +7,7 @@
@c %**end of header
@copying
-Copyright @copyright{} 1991--2023 Free Software Foundation, Inc.
+Copyright @copyright{} 1991--2024 Free Software Foundation, Inc.
@quotation
Permission is granted to copy, distribute and/or modify this document
diff --git a/doc/misc/pgg.texi b/doc/misc/pgg.texi
index ea69499a140..9cb7b937fff 100644
--- a/doc/misc/pgg.texi
+++ b/doc/misc/pgg.texi
@@ -10,7 +10,7 @@
This file describes PGG @value{VERSION}, an Emacs interface to various
PGP implementations.
-Copyright @copyright{} 2001, 2003--2023 Free Software Foundation, Inc.
+Copyright @copyright{} 2001, 2003--2024 Free Software Foundation, Inc.
@quotation
Permission is granted to copy, distribute and/or modify this document
diff --git a/doc/misc/rcirc.texi b/doc/misc/rcirc.texi
index 6b10d1ab2a4..9ae4bb4a17c 100644
--- a/doc/misc/rcirc.texi
+++ b/doc/misc/rcirc.texi
@@ -6,7 +6,7 @@
@c %**end of header
@copying
-Copyright @copyright{} 2006--2023 Free Software Foundation, Inc.
+Copyright @copyright{} 2006--2024 Free Software Foundation, Inc.
@quotation
Permission is granted to copy, distribute and/or modify this document
@@ -929,6 +929,7 @@ Manual}, for details.
@cindex date time
@cindex format time stamp
@vindex rcirc-time-format
+@vindex rcirc-log-time-format
@code{rcirc-time-format} is the format used for the time stamp. Here's
how to include the date in the time stamp:
@@ -937,6 +938,9 @@ how to include the date in the time stamp:
(setopt rcirc-time-format "%Y-%m-%d %H:%M ")
@end example
+For log files, a different time format can be specified using the
+@code{rcirc-log-time-format} user option.
+
@findex rcirc-when
If you don't wish to use verbose time formatting all the time, you can
use the @code{rcirc-when} command to display a complete timestamp for
diff --git a/doc/misc/reftex.texi b/doc/misc/reftex.texi
index 72c4283aa46..5adc616e798 100644
--- a/doc/misc/reftex.texi
+++ b/doc/misc/reftex.texi
@@ -45,7 +45,7 @@ This manual documents @RefTeX{} (version @value{VERSION}), a package
to do labels, references, citations and indices for LaTeX documents
with Emacs.
-Copyright @copyright{} 1997--2023 Free Software Foundation, Inc.
+Copyright @copyright{} 1997--2024 Free Software Foundation, Inc.
@quotation
Permission is granted to copy, distribute and/or modify this document
diff --git a/doc/misc/remember.texi b/doc/misc/remember.texi
index 03bc4a0e868..dabd2e6b161 100644
--- a/doc/misc/remember.texi
+++ b/doc/misc/remember.texi
@@ -10,7 +10,7 @@
@copying
This manual is for Remember Mode, as distributed with Emacs @value{EMACSVER}.
-Copyright @copyright{} 2001, 2004--2005, 2007--2023 Free Software
+Copyright @copyright{} 2001, 2004--2005, 2007--2024 Free Software
Foundation, Inc.
@quotation
diff --git a/doc/misc/sasl.texi b/doc/misc/sasl.texi
index 89d32b8e916..7abee48e8d8 100644
--- a/doc/misc/sasl.texi
+++ b/doc/misc/sasl.texi
@@ -9,7 +9,7 @@
@copying
This file describes the Emacs SASL library, version @value{VERSION}.
-Copyright @copyright{} 2000, 2004--2023 Free Software Foundation, Inc.
+Copyright @copyright{} 2000, 2004--2024 Free Software Foundation, Inc.
@quotation
Permission is granted to copy, distribute and/or modify this document
diff --git a/doc/misc/sc.texi b/doc/misc/sc.texi
index 9bf7c36b481..5176797cde8 100644
--- a/doc/misc/sc.texi
+++ b/doc/misc/sc.texi
@@ -15,7 +15,7 @@
This document describes Supercite, an Emacs package for citing and
attributing replies to mail and news messages.
-Copyright @copyright{} 1993, 2001--2023 Free Software Foundation, Inc.
+Copyright @copyright{} 1993, 2001--2024 Free Software Foundation, Inc.
@quotation
Permission is granted to copy, distribute and/or modify this document
diff --git a/doc/misc/sem-user.texi b/doc/misc/sem-user.texi
index d7995550e2a..a00c91207ad 100644
--- a/doc/misc/sem-user.texi
+++ b/doc/misc/sem-user.texi
@@ -1,5 +1,5 @@
@c This is part of the Semantic manual.
-@c Copyright (C) 1999--2005, 2007, 2009--2023 Free Software Foundation,
+@c Copyright (C) 1999--2005, 2007, 2009--2024 Free Software Foundation,
@c Inc.
@c See file semantic.texi for copying conditions.
diff --git a/doc/misc/semantic.texi b/doc/misc/semantic.texi
index af3619a75a6..f6cabed6ea6 100644
--- a/doc/misc/semantic.texi
+++ b/doc/misc/semantic.texi
@@ -25,7 +25,7 @@
@copying
This manual documents the Semantic library and utilities.
-Copyright @copyright{} 1999--2023 Free Software Foundation, Inc.
+Copyright @copyright{} 1999--2024 Free Software Foundation, Inc.
@quotation
Permission is granted to copy, distribute and/or modify this document
diff --git a/doc/misc/ses.texi b/doc/misc/ses.texi
index 15722056f33..b48ed0c1949 100644
--- a/doc/misc/ses.texi
+++ b/doc/misc/ses.texi
@@ -12,7 +12,7 @@
@copying
This file documents @acronym{SES}: the Simple Emacs Spreadsheet.
-Copyright @copyright{} 2002--2023 Free Software Foundation, Inc.
+Copyright @copyright{} 2002--2024 Free Software Foundation, Inc.
@quotation
Permission is granted to copy, distribute and/or modify this document
@@ -91,8 +91,8 @@ To report bugs, use @kbd{M-x report-emacs-bug}.
@item Printer functions for control of cell appearance.
@item Intuitive keystroke commands: C-o = insert row, M-o = insert column, etc.
@item ``Spillover'' of lengthy cell values into following blank cells.
-@item Header line shows column letters or a selected row.
-@item Completing-read for entering symbols as cell values.
+@item Header line shows column letters.
+@item Completing-read for entering symbols of named cells when editing formulas.
@item Cut, copy, and paste can transfer formulas and printer functions.
@item Import and export of tab-separated values or tab-separated formulas.
@item Plaintext, easily-hacked file format.
@@ -109,12 +109,12 @@ If you want to get started quickly and think that you know what to
expect from a simple spreadsheet, this chapter may be all that you
need.
-First, visit a new file with the @file{.ses} extension.
+First, visit a new file with the @file{.ses} file name extension.
Emacs presents you with an empty spreadsheet containing a single cell.
-Begin by inserting a headline: @kbd{"Income"@key{RET}}. The double
-quotes indicate that this is a text cell. (Notice that Emacs
-automatically inserts the closing quotation mark.)
+Begin by inserting a headline: @kbd{"Income@key{RET}}. The double
+quotes indicate that you are editing a text cell, it is not part of
+the cell value, and no closing quotation mark is needed.
To insert your first income value, you must first resize the
spreadsheet. Press @key{TAB} to add a new cell and navigate back up
@@ -138,9 +138,10 @@ To add up the values, enter a Lisp expression:
(+ A2 A3 A4 A5)
@end example
-Perhaps you want to add a cell to the right of cell A4 to explain
-why you have a negative entry. Pressing @kbd{TAB} in that cell
-adds an entire new column @samp{B}, where you can add such a note.
+Perhaps you want to add a cell to the right of cell @samp{A4} to
+explain why you have a negative entry. Pressing @kbd{TAB} in that
+cell adds an entire new column @samp{B}, where you can add such a
+note.
The column is fairly narrow by default, but pressing @kbd{w} allows
you to resize it as needed. Make it 20 characters wide. You can
@@ -158,19 +159,24 @@ A B
@end group
@end example
-By default, the labels in column B are right-justified. To change
-that, you can enter a printer function for the whole column, using
-e.g., @kbd{M-p ("%s")}. You can override a column's printer function
-in any individual cell using @kbd{p}.
+By default, the cell value print-out is right aligned, that is the
+reason for such an alignment for the notes in column @samp{B}. To
+change that, you can enter a printer function for the whole column,
+using e.g., @kbd{M-p ("%s")}. Enclosing @code{"%s"} into a list tells
+@acronym{SES} to align left. You can override a column's printer
+function in any individual cell using @kbd{p}.
+
+@c TODO : propagate extra explanation from the French version.
If Joe pays back his loan, you might blank that entry; e.g., by
-positioning the cursor in cell A5 and pressing @kbd{C-d} twice.
-If you do that, the total cell will display @samp{######}. That is
-because the regular @code{+} operator does not handle a range that
-contains some empty cells. Instead of emptying the cell, you could
-enter a literal @samp{0}, or delete the entire row using @kbd{C-k}.
-An alternative is to use the special function @code{ses+} instead of
-the regular @code{+}:
+positioning the cursor in cell A5 and pressing @kbd{C-d}. If you do
+that, the total printed out in cell A6 will display @samp{######}.
+That is because the value in an empty cell is typically @code{nil},
+and the regular @code{+} operator fails to handle a range that
+contains that value. Instead of emptying the cell, you could enter a
+literal @samp{0}, or delete the entire row using @kbd{C-k}. An
+alternative is to use the special function @code{ses+} instead of the
+regular @code{+}:
@example
(ses+ A2 A3 A4 A5)
@@ -188,13 +194,18 @@ the end-points, e.g.:
@emph{list} of values. This allows for more complex possibilities.)
Alternatively you can use the @code{!} modifier of @code{ses-range} to
-remove blank cells from the returned list, which allows to use
+remove blank cells from the returned list, which enables using
@code{+} instead of @code{ses+}:
@lisp
(apply '+ (ses-range A2 A5 !))
@end lisp
+Actually, both options are not exactly equivalent as the former makes
+the summing in reversed order of argument, and the latter in the same
+order. You can also reverse the order of arguments returned by
+@code{ses-range} with the @code{<} modifier.
+
@c ===================================================================
@node The Basics
@@ -209,7 +220,7 @@ remove blank cells from the returned list, which allows to use
@findex keyboard-quit
To create a new spreadsheet, visit a nonexistent file whose name ends
-with ".ses". For example, @kbd{C-x C-f test.ses @key{RET}}.
+with @file{.ses}. For example, @kbd{C-x C-f test.ses @key{RET}}.
A @dfn{cell identifier} is a symbol with a column letter and a row
@@ -224,18 +235,18 @@ Moves point to cell, specified by identifier (@code{ses-jump}). Unless
the cell is a renamed cell, the identifier is case-insensitive. A
prefix argument @math{n} move to cell with coordinates @math{(n\div R,
n \% C)} for a spreadsheet of @math{R} rows and @math{C} columns, and
-A1 being of coordinates @math{(0,0)}. The way the identifier or the
-command prefix argument are interpreted can be customized through
+@samp{A1} being of coordinates @math{(0,0)}. The way the identifier or
+the command prefix argument are interpreted can be customized through
variables @code{ses-jump-cell-name-function} and
@code{ses-jump-prefix-function}.
@end table
Point is always at the left edge of a cell, or at the empty endline.
When mark is inactive, the current cell is underlined. When mark is
-active, the range is the highlighted rectangle of cells (@acronym{SES} always
-uses transient mark mode). Drag the mouse from A1 to A3 to create the
-range A1-A2. Many @acronym{SES} commands operate only on single cells, not
-ranges.
+active, the range is the highlighted rectangle of cells (@acronym{SES}
+always uses transient mark mode). Drag the mouse from @samp{A1} to
+@samp{A3} to create the range @samp{A1-A2}. Many @acronym{SES}
+commands operate only on single cells, not ranges.
@table @kbd
@item C-@key{SPC}
@@ -288,11 +299,11 @@ Self-insert a digit (@code{ses-read-cell}).
Self-insert a negative number (@code{ses-read-cell}).
@item .
-Self-insert a fractional number (@code{ses-read-cell}).
+Self-insert a decimal number (@code{ses-read-cell}).
@item "
-Self-insert a quoted string. The ending double-quote
-is inserted for you (@code{ses-read-cell}).
+Self-insert a string. The ending double-quote is inserted for you
+(@code{ses-read-cell}).
@item (
Self-insert an expression. The right-parenthesis is inserted for you
@@ -308,9 +319,10 @@ to list the named cells symbols in a help buffer.
@end table
@item ' @r{(apostrophe)}
-Enter a symbol (ses-read-symbol). @acronym{SES} remembers all symbols that have
-been used as formulas, so you can type just the beginning of a symbol
-and use @kbd{@key{SPC}}, @kbd{@key{TAB}}, and @kbd{?} to complete it.
+Enter a symbol (@code{ses-read-symbol}). @acronym{SES} remembers all
+symbols that have been used as formulas, so you can type just the
+beginning of a symbol and use @kbd{@key{SPC}}, @kbd{@key{TAB}}, and
+@kbd{?} to complete it.
@end table
To enter something else (e.g., a vector), begin with a digit, then
@@ -421,8 +433,8 @@ string is right-aligned within the print cell. To get left-alignment,
use parentheses: @samp{("$%.2f")}.
@item
A printer can also be a one-argument function, the result of which is
-a string (right-aligned) or list of one string (left-aligned). Such a
-function can be in turn configured as:
+a string (to get right alignment) or list of one string (to get left
+alignment). Such a function can be in turn configured as:
@itemize
@item
A lambda expression, for instance:
@@ -495,7 +507,7 @@ To list the local printers in a help buffer.
Except for @code{ses-prin1}, the other standard printers are suitable
only for cells, not columns or default, because they format the value
using the column-printer (or default-printer if @code{nil}) and then
-center the result:
+post-proces the result, eg.@: center it:
@ftable @code
@item ses-center
@@ -505,13 +517,13 @@ Just centering.
Centering with spill-over to following blank cells.
@item ses-dashfill
-Centering using dashes (-) instead of spaces.
+Centering using dashes (@samp{-}) instead of spaces.
@item ses-dashfill-span
Centering with dashes and spill-over.
@item ses-tildefill-span
-Centering with tildes (~) and spill-over.
+Centering with tildes (@samp{~}) and spill-over.
@item ses-prin1
This is the fallback printer, used when calling the configured printer
@@ -545,9 +557,9 @@ you can add some code like this to your @file{.emacs} init file:
'euro
(lambda (x)
(cond
- ((null x) "")
- ((numberp x) (format "%.2f€" x))
- (t (ses-center-span x ?# 'ses-prin1)))))))
+ ((null x) "")
+ ((numberp x) (format "%.2f€" x))
+ (t (ses-center-span x ?# 'ses-prin1)))))))
(add-hook 'ses-mode-hook 'my-ses-mode-hook)
@end lisp
@@ -599,29 +611,31 @@ s-expression (using @code{ses-prin1}), centered and surrounded by
@code{#} filling.
@end itemize
-Another precaution to take is to avoid stack overflow due to a
-printer function calling itself indefinitely. This mistake can
-happen when you use a local printer as a column printer,
-and this local printer implicitly calls the current column printer, so it
-will call itself recursively. Imagine for instance that you want to
-create some local printer @code{=fill} that would center the content
-of a cell and surround it by equal signs @code{=}, and you do it this
+Another precaution to take is to avoid stack overflow due to a printer
+function calling itself indefinitely. This mistake can happen when
+you use a local printer as a column printer, and this local printer
+implicitly calls the current column printer, so it will call itself
+recursively. Imagine for instance that you want to create some local
+printer @code{=fill} that would center the content of a cell and
+surround it by equal signs @code{=}, and you do it (errounously) this
way:
@lisp
+;; ERRONEOUS CODE
(lambda (x)
(cond
((null x) "")
(t (ses-center x 0 ?=))))
@end lisp
-Because @code{=fill} uses the standard printer @code{ses-center} without
-explicitly passing any printer to it, @code{ses-center} will call the
-current column printer if any, or the spreadsheet default printer
-otherwise. So using @code{=fill} as a column printer will result in a
-stack overflow in this column. SES does not check for that;
-you just have to be careful. For instance, re-write @code{=fill} like
-this:
+Because @code{=fill} uses the standard printer @code{ses-center}
+without explicitly passing any printer to it, @code{ses-center} will
+call the current column printer if any, or the spreadsheet default
+printer otherwise. So using @code{=fill} as a column printer will
+result in a stack overflow in this column on any non empty cell as
+@code{ses-center} will recursively recall the function that has called
+it. @acronym{SES} does not check for that; you just have to be
+careful. For instance, re-write @code{=fill} like this:
@lisp
(lambda (x)
@@ -631,11 +645,17 @@ this:
(t (ses-center-span x ?# 'ses-prin1))))
@end lisp
+The code above is fixed as @code{ses-center} and
+@code{ses-center-span} are both called with an explicit last
+@var{printer} argument, respectively @code{" %s "} and
+@code{'ses-prin1}.
+
The code above applies the @code{=} filling only to strings; it also
surrounds the string by one space on each side before filling with
-@code{=} signs. So the string @samp{Foo} will be displayed like @samp{@w{===
-Foo ===}} in an 11 character wide column. Anything other than an empty cell
-or a non-string is displayed as an error by using @code{#} filling.
+@code{=} signs. So the string @samp{Foo} will be displayed like
+@samp{@w{=== Foo ===}} in an 11 character wide column. Any value that
+is neither @code{nil} (ie.@: an empty cell) nor a string is displayed
+as an error by using @code{#} filling.
@node Clearing cells
@section Clearing cells
@@ -647,7 +667,7 @@ These commands set both formula and printer to @code{nil}:
@table @kbd
@item @key{DEL}
-Clear cell and move left (@code{ses-clear-cell-backward}).
+Move left and clear cell (@code{ses-clear-cell-backward}).
@item C-d
Clear cell and move right (@code{ses-clear-cell-forward}).
@@ -699,9 +719,10 @@ Paste from kill ring (@code{yank}). The paste functions behave
differently depending on the format of the text being inserted:
@itemize @bullet
@item
-When pasting cells that were cut from a @acronym{SES} buffer, the print text is
-ignored and only the attached formula and printer are inserted; cell
-references in the formula are relocated unless you use @kbd{C-u}.
+When pasting cells that were cut or copied from a @acronym{SES}
+buffer, the print text is ignored and only the attached formula and
+printer are inserted; cell references in the formula are relocated
+unless you use @kbd{C-u}.
@item
The pasted text overwrites a rectangle of cells whose top left corner
is the current cell. If part of the rectangle is beyond the edges of
@@ -738,8 +759,11 @@ By default, a newly-created spreadsheet has 1 row and 1 column. The
column width is 7 and the default printer is @samp{"%.7g"}. Each of these
can be customized. Look in group ``ses''.
-After entering a cell value, point normally moves right to the next
-cell. You can customize @code{ses-after-entry-functions} to move left or
+After entering a cell value, normally, @code{forward-char} is called,
+which moves point right to the next cell@c TODO propagate extra
+ @c explanation from the French
+ @c version.
+. You can customize @code{ses-after-entry-functions} to move left or
up or down. For diagonal movement, select two functions from the
list.
@@ -747,6 +771,7 @@ list.
@code{ses-jump-cell-name-function} is a customizable variable by
default set to the @code{upcase} function. This function is called
when you pass a cell name to the @command{ses-jump} command (@kbd{j}),
+@c TODO : propagate extra explanation from the French version.
it changes the entered cell name to that where to jump. The default
setting @code{upcase} allows you to enter the cell name in low
case. Another use of @code{ses-jump-cell-name-function} could be some
@@ -763,8 +788,9 @@ when you give a prefix argument to the @command{ses-jump} command
the prefix argument. Cell coordinates are in the form of a cons, for
instance @code{(1 . 0)} for cell @code{A2}. The default setting
@code{ses-jump-prefix} will number cells left to right and then top
-down, so assuming a 4x3 spreadsheet prefix argument 0 jumps to cell
-A1, prefix argument 2 jumps to C1, prefix argument 3 jumps to A2, etc.
+down, so assuming a 4x3 spreadsheet prefix argument @samp{0} jumps to
+cell @samp{A1}, prefix argument @samp{2} jumps to @samp{C1}, prefix
+argument @samp{3} jumps to @samp{A2}, etc.
@vindex ses-mode-hook
@code{ses-mode-hook} is a normal mode hook (list of functions to
@@ -813,7 +839,7 @@ Rename a cell from a standard A1-like name to any string that can be a
valid local variable name (See also @ref{Nonrelocatable references}).
@item M-x ses-repair-cell-reference-all
@findex ses-repair-cell-reference-all
-When you interrupt a cell formula update by clicking @kbd{C-g}, then
+When you interrupt a cell formula update by typing @kbd{C-g}, then
the cell reference link may be broken, which will jeopardize automatic
cell update when any other cell on which it depends is changed. To
repair that use function @code{ses-repair-cell-reference-all}
@@ -891,17 +917,17 @@ and the new row is included in the sum.
While entering or editing a formula in the minibuffer, you can select
a range in the spreadsheet (using mouse or keyboard), then paste a
representation of that range into your formula. Suppose you select
-A1-C1:
+@samp{A1-C1}:
@table @kbd
@item [S-mouse-3]
-Inserts "A1 B1 C1" @code{(ses-insert-range-click})
+Inserts @samp{A1 B1 C1} (@code{ses-insert-range-click})
@item C-c C-r
Keyboard version (@code{ses-insert-range}).
@item [C-S-mouse-3]
-Inserts "(ses-range A1 C1)" (@code{ses-insert-ses-range-click}).
+Inserts @samp{(ses-range A1 C1)} (@code{ses-insert-ses-range-click}).
@item C-c C-s
Keyboard version (@code{ses-insert-ses-range}).
@@ -909,7 +935,8 @@ Keyboard version (@code{ses-insert-ses-range}).
If you delete the @var{from} or @var{to} cell for a range, the nearest
still-existing cell is used instead. If you delete the entire range,
-the formula relocator will delete the ses-range from the formula.
+the formula relocator will delete the @samp{ses-range} from the
+formula.
If you insert a new row just beyond the end of a one-column range, or
a new column just beyond a one-row range, the new cell is included in
@@ -1007,7 +1034,7 @@ are some useful functions to call from your formulas:
@item (ses-delete-blanks &rest @var{args})
Returns a list from which all blank cells (value is either @code{nil}
or '*skip*) have been deleted. Order of args is reverted. Please note
-that @code{ses-range} has a @code{!} modifier that allows to remove
+that @code{ses-range} has a @code{!} modifier that enables removing
blanks, so it is possible to write:
@lisp
(ses-range A1 A5 !)
@@ -1018,7 +1045,7 @@ instead of
@end lisp
@item (ses+ &rest @var{args})
-Sum of non-blank arguments.
+Sum of non-blank arguments taken in reverse order.
@item (ses-average @var{list})
Average of non-blank elements in @var{list}. Here the list is passed
@@ -1033,13 +1060,15 @@ as a single argument, since you'll probably use it with @code{ses-range}.
Special cell values:
@itemize
-@item nil prints the same as "", but allows previous cell to spill over.
+@item nil prints typically the same as "", but allows previous cell to spill over.
@item '*skip* replaces nil when the previous cell actually does spill over;
nothing is printed for it.
@item '*error* indicates that the formula signaled an error instead of
producing a value: the print cell is filled with hash marks (#).
@end itemize
+@c TODO propagate extra explanation from the French version.
+
If the result from the printer function is too wide for the cell and
the following cell is @code{nil}, the result will spill over into the
following cell. Very wide results can spill over several cells. If
@@ -1066,12 +1095,14 @@ this to undo the effect of @kbd{t}.
When a printer function signals an error, the fallback printer
@findex ses-prin1
-@code{ses-prin1} is substituted. This is useful when your column printer
-is numeric-only and you use a string as a cell value. Note that the
-standard default printer is @samp{"%.7g"} which is numeric-only, so cells
-that are empty of contain strings will use the fallback printer.
-@kbd{c} on such cells will display ``Format specifier doesn't match
-argument type''.
+@code{ses-prin1} is substituted. This is useful when your printer is
+numeric-only and you use a string as a cell value. Note that the
+standard default printer is @samp{"%.7g"} which is numeric-only, so
+cells for which the standard default printer applies, and that are not
+empty and do not contain a number will use the fallback printer
+@code{ses-prin1}, for instance cells that contain strings will do
+that. @kbd{c} on such cells will display ``Format specifier doesn't
+match argument type''.
@node Import and export
@@ -1103,11 +1134,11 @@ the spreadsheet, it receives a ``needs safety check'' marking. Later,
when the formula or printer is evaluated for the first time, it is
checked for safety using the @code{unsafep} predicate; if found to be
``possibly unsafe'', the questionable formula or printer is displayed
-and you must press Y to approve it or N to use a substitute. The
-substitute always signals an error.
+and you must press @kbd{Y} to approve it or @kbd{N} to use a
+substitute. The substitute always signals an error.
Formulas or printers that you type in are checked immediately for
-safety. If found to be possibly unsafe and you press N to disapprove,
+safety. If found to be possibly unsafe and you press @kbd{N} to disapprove,
the action is canceled and the old formula or printer will remain.
Besides viruses (which try to copy themselves to other files),
@@ -1143,13 +1174,15 @@ Example of use:
@lisp
(ses-average (ses-select (ses-range A1 A5) 'Smith (ses-range B1 B5)))
@end lisp
-This computes the average of the B column values for those rows whose
-A column value is the symbol 'Smith.
+This computes the average of the @samp{B} column values for those rows
+whose @samp{A} column value is the symbol @samp{'Smith}.
Arguably one could specify only @var{fromrange} plus
@var{to-row-offset} and @var{to-column-offset}. The @var{torange} is
stated explicitly to ensure that the formula will be recalculated if
any cell in either range is changed.
+@c TODO reword this paragraph more clearly as in the French version
+
File @file{etc/ses-example.el} in the Emacs distribution is an example of a
details-and-summary spreadsheet.
@@ -1166,7 +1199,7 @@ details-and-summary spreadsheet.
* Nonrelocatable references::
* The data area::
* Buffer-local variables in spreadsheets::
-* Uses of defadvice in @acronym{SES}::
+* Uses of advice-add in @acronym{SES}::
@end menu
@node Deferred updates
@@ -1179,12 +1212,13 @@ To save time by avoiding redundant computations, cells that need
recalculation due to changes in other cells are added to a set. At
the end of the command, each cell in the set is recalculated once.
This can create a new set of cells that need recalculation. The
-process is repeated until either the set is empty or it stops changing
-(due to circular references among the cells). In extreme cases, you
-might see progress messages of the form ``Recalculating... (@var{nnn}
-cells left)''. If you interrupt the calculation using @kbd{C-g}, the
-spreadsheet will be left in an inconsistent state, so use @kbd{C-_} or
-@kbd{C-c C-l} to fix it.
+process is repeated until either the set is empty or a circular
+references are detected. In extreme cases, and notably if a circular
+cell reference is under detection, you might see progress messages of
+the form ``Recalculating... (@var{nnn} cells left)''. If you
+interrupt the calculation using @kbd{C-g}, the spreadsheet will be
+left in an inconsistent state, so use @kbd{C-_} or @kbd{C-c C-l} to
+fix it.
To save even more time by avoiding redundant writes, cells that have
changes are added to a set instead of being written immediately to the
@@ -1194,11 +1228,12 @@ progress message of the form ``Writing... (@var{nnn} cells left)''.
These deferred cell-writes cannot be interrupted by @kbd{C-g}, so
you'll just have to wait.
-@acronym{SES} uses @code{run-with-idle-timer} to move the cell underline when
-Emacs will be scrolling the buffer after the end of a command, and
-also to narrow and underline after @kbd{C-x C-v}. This is visible as
-a momentary glitch after C-x C-v and certain scrolling commands. You
-can type ahead without worrying about the glitch.
+@acronym{SES} uses @code{run-with-idle-timer} to move the cell
+underline when Emacs will be scrolling the buffer after the end of a
+command, and also to narrow and underline after visiting a file. This
+may be visible as a momentary glitch after visiting and certain
+scrolling commands. You can type ahead without worrying about the
+glitch.
@node Nonrelocatable references
@@ -1210,8 +1245,8 @@ can type ahead without worrying about the glitch.
@kbd{C-u C-y} relocates none of the cell-references. What about mixed
cases?
-The best way is to rename cells that you do not want to be relocatable
-by using @code{ses-rename-cell}.
+The best way is to rename cells that you do @emph{not} want to be
+relocatable by using @code{ses-rename-cell}.
@findex ses-rename-cell
Cells that do not have an A1-like name style are not relocated on
yank. Using this method, the concerned cells won't be relocated
@@ -1219,7 +1254,7 @@ whatever formula they appear in. Please note however that when a
formula contains some range @code{(ses-range @var{cell1} @var{cell2})}
then in the yanked formula each range bound @var{cell1} and
@var{cell2} are relocated, or not, independently, depending on whether
-they are A1-like or renamed.
+they are @samp{A1}-like or renamed.
An alternative method is to use
@lisp
@@ -1227,9 +1262,9 @@ An alternative method is to use
@end lisp
to make an @dfn{absolute reference}. The formula relocator skips over
quoted things, so this will not be relocated when pasted or when
-rows/columns are inserted/deleted. However, B3 will not be recorded
-as a dependency of this cell, so this cell will not be updated
-automatically when B3 is changed, this is why using
+rows/columns are inserted/deleted. However, @samp{B3} will not be
+recorded as a dependency of this cell, so this cell will not be
+updated automatically when @samp{B3} is changed, this is why using
@code{ses-rename-cell} is most of the time preferable.
The variables @code{row} and @code{col} are dynamically bound while a
@@ -1246,12 +1281,13 @@ kind of dependency is also not recorded.
@cindex data area
@findex ses-reconstruct-all
-Begins with an 014 character, followed by sets of cell-definition
-macros for each row, followed by the set of local printer
-definitions, followed by column-widths, column-printers,
-default-printer, and header-row. Then there's the global parameters
-(file-format ID, row count, column count, local printer count) and the
-local variables (specifying @acronym{SES} mode for the buffer, etc.).
+Begins with an form feed character (whose ASCII code is 014 in octal
+notation), followed by sets of cell-definition macros for each row,
+followed by the set of local printer definitions, followed by
+column-widths, column-printers, default-printer, and header-row. Then
+there's the global parameters (file-format ID, row count, column
+count, local printer count) and the local variables (specifying
+@acronym{SES} mode for the buffer, etc.).
When a @acronym{SES} file is loaded, first the global parameters are
loaded, then the entire data area is @code{eval}ed, and finally the local
@@ -1263,10 +1299,10 @@ counting newlines. Use @kbd{C-x C-e} at the end of a line to install
your edits into the spreadsheet data structures (this does not update
the print area, use, e.g., @kbd{C-c C-l} for that).
-The data area is maintained as an image of spreadsheet data
-structures that area stored in buffer-local variables. If the data
-area gets messed up, you can try reconstructing the data area from the
-data structures:
+The data area is maintained as an image of spreadsheet data structures
+as stored in buffer-local variables from initially loading the area.
+If the data area gets messed up in the sequel, you can try
+reconstructing the data area from the data structures:
@table @kbd
@item C-c M-C-l
@@ -1283,7 +1319,7 @@ You can add additional local variables to the list at the bottom of
the data area, such as hidden constants you want to refer to in your
formulas.
-You can override the variable @code{ses--symbolic-formulas} to be a list of
+You can initialize the variable @code{ses--symbolic-formulas} to be a list of
symbols (as parenthesized strings) to show as completions for the @kbd{'}
command. This initial completions list is used instead of the actual
set of symbols-as-formulas in the spreadsheet.
@@ -1308,30 +1344,23 @@ avoid virus warnings, each function used in a formula needs
(put 'your-function-name 'safe-function t)
@end lisp
-@node Uses of defadvice in @acronym{SES}
-@section Uses of defadvice in @acronym{SES}
-@findex defadvice
-@findex undo-more
+@node Uses of advice-add in @acronym{SES}
+@section Uses of advice-add in @acronym{SES}
+@findex advice-add
@findex copy-region-as-kill
@findex yank
@table @code
-@item undo-more
-Defines a new undo element format (@var{fun} . @var{args}), which
-means ``undo by applying @var{fun} to @var{args}''. For spreadsheet
-buffers, it allows undos in the data area even though that's outside
-the narrowing.
-
@item copy-region-as-kill
When copying from the print area of a spreadsheet, treat the region as
-a rectangle and attach each cell's formula and printer as 'ses
+a rectangle and attach each cell's formula and printer as @code{'ses}
properties.
@item yank
When yanking into the print area of a spreadsheet, first try to yank
-as cells (if the yank text has 'ses properties), then as tab-separated
-formulas, then (if all else fails) as a single formula for the current
-cell.
+as cells (if the yank text has @code{'ses} properties), then as
+tab-separated formulas, then (if all else fails) as a single formula
+for the current cell.
@end table
@c ===================================================================
@@ -1352,7 +1381,9 @@ Jonathan Yavner,
@c monnier@@gnu.org
Stefan Monnier,
@c shigeru.fukaya@@gmail.com
-Shigeru Fukaya
+Shigeru Fukaya,
+@c vincent.belaiche@@sourceforge.net
+Vincent Belaïche
@end quotation
@noindent
@@ -1361,7 +1392,9 @@ Texinfo manual by:
@c jyavner@@member.fsf.org
Jonathan Yavner,
@c brad@@chenla.org
-Brad Collins
+Brad Collins,
+@c vincent.belaiche@@sourceforge.net
+Vincent Belaïche
@end quotation
@noindent
@@ -1402,7 +1435,9 @@ Luc Teirlinck,
@c jotto@@pobox.com
J. Otto Tennant,
@c jphil@@acs.pagesjaunes.fr
-Jean-Philippe Theberge
+Jean-Philippe Theberge,
+@c rrandresf@@hotmail.com
+Andrés Ramírez
@end quotation
@c ===================================================================
diff --git a/doc/misc/sieve.texi b/doc/misc/sieve.texi
index 639a2daee02..156e0120a38 100644
--- a/doc/misc/sieve.texi
+++ b/doc/misc/sieve.texi
@@ -10,7 +10,7 @@
@copying
This file documents the Emacs Sieve package, for server-side mail filtering.
-Copyright @copyright{} 2001--2023 Free Software Foundation, Inc.
+Copyright @copyright{} 2001--2024 Free Software Foundation, Inc.
@quotation
Permission is granted to copy, distribute and/or modify this document
diff --git a/doc/misc/smtpmail.texi b/doc/misc/smtpmail.texi
index 99363483827..33f4d558aad 100644
--- a/doc/misc/smtpmail.texi
+++ b/doc/misc/smtpmail.texi
@@ -4,7 +4,7 @@
@include docstyle.texi
@syncodeindex vr fn
@copying
-Copyright @copyright{} 2003--2023 Free Software Foundation, Inc.
+Copyright @copyright{} 2003--2024 Free Software Foundation, Inc.
@quotation
Permission is granted to copy, distribute and/or modify this document
@@ -264,12 +264,14 @@ file, @pxref{Top,,auth-source, auth, Emacs auth-source Library}.
@cindex CRAM-MD5
@cindex PLAIN
@cindex LOGIN
+@cindex OAuth2
+@cindex OAuth 2.0
The process by which the @acronym{SMTP} library authenticates you to
the server is known as ``Simple Authentication and Security Layer''
(@acronym{SASL}). There are various @acronym{SASL} mechanisms, and
-this library supports three of them: @code{cram-md5}, @code{plain},
+this library supports four of them: @code{cram-md5}, @code{plain},
@code{login} and @code{xoauth2}, where the first uses a form of
-encryption to obscure your password, while the other two do not. It
+encryption to obscure your password, while the others do not. It
tries each of them, in that order, until one succeeds.
(@code{xoauth2} requires using the @file{oauth2.el} library. You can
override this by assigning a specific authentication mechanism to a
diff --git a/doc/misc/speedbar.texi b/doc/misc/speedbar.texi
index aae9ab762da..f4b9ee702a7 100644
--- a/doc/misc/speedbar.texi
+++ b/doc/misc/speedbar.texi
@@ -5,7 +5,7 @@
@syncodeindex fn cp
@copying
-Copyright @copyright{} 1999--2023 Free Software Foundation, Inc.
+Copyright @copyright{} 1999--2024 Free Software Foundation, Inc.
@quotation
Permission is granted to copy, distribute and/or modify this document
diff --git a/doc/misc/srecode.texi b/doc/misc/srecode.texi
index 84173f0e0f6..6a4560d5920 100644
--- a/doc/misc/srecode.texi
+++ b/doc/misc/srecode.texi
@@ -16,7 +16,7 @@
@c %**end of header
@copying
-Copyright @copyright{} 2007--2023 Free Software Foundation, Inc.
+Copyright @copyright{} 2007--2024 Free Software Foundation, Inc.
@quotation
Permission is granted to copy, distribute and/or modify this document
diff --git a/doc/misc/texinfo.tex b/doc/misc/texinfo.tex
index 6e521944b22..7fd371c1d9d 100644
--- a/doc/misc/texinfo.tex
+++ b/doc/misc/texinfo.tex
@@ -3,9 +3,9 @@
% Load plain if necessary, i.e., if running under initex.
\expandafter\ifx\csname fmtname\endcsname\relax\input plain\fi
%
-\def\texinfoversion{2023-07-27.21}
+\def\texinfoversion{2024-01-02.10}
%
-% Copyright 1985, 1986, 1988, 1990-2023 Free Software Foundation, Inc.
+% Copyright 1985--1986, 1988, 1990--2024 Free Software Foundation, Inc.
%
% This texinfo.tex file is free software: you can redistribute it and/or
% modify it under the terms of the GNU General Public License as
diff --git a/doc/misc/todo-mode.texi b/doc/misc/todo-mode.texi
index 62376195023..9f259b0e65b 100644
--- a/doc/misc/todo-mode.texi
+++ b/doc/misc/todo-mode.texi
@@ -9,7 +9,7 @@
@c %**end of header
@copying
-Copyright @copyright{} 2013--2023 Free Software Foundation, Inc.
+Copyright @copyright{} 2013--2024 Free Software Foundation, Inc.
@quotation
Permission is granted to copy, distribute and/or modify this document
diff --git a/doc/misc/tramp.texi b/doc/misc/tramp.texi
index 6189ef2d41d..7e938d0f97f 100644
--- a/doc/misc/tramp.texi
+++ b/doc/misc/tramp.texi
@@ -12,7 +12,7 @@
@footnotestyle end
@copying
-Copyright @copyright{} 1999--2023 Free Software Foundation, Inc.
+Copyright @copyright{} 1999--2024 Free Software Foundation, Inc.
@quotation
Permission is granted to copy, distribute and/or modify this document
@@ -1094,11 +1094,11 @@ decode programs.
@cindex method @option{sudoedit}
@cindex @option{sudoedit} method
-The @option{sudoedit} method allows to edit a file as a different user
-on the local host. You could regard this as @value{tramp}'s
+The @option{sudoedit} method facilitates editing a file as a different
+user on the local host. You could regard this as @value{tramp}'s
implementation of the @command{sudoedit}. Contrary to the
@option{sudo} method, all magic file name functions are implemented by
-single @command{sudo @dots{}} commands. The purpose is to make
+single @command{sudo @dots{}} commands. The purpose is to make
editing such a file as secure as possible; there must be no session
running in the Emacs background which could be attacked from inside
Emacs.
@@ -1383,7 +1383,7 @@ possible, @value{tramp} emulates those operations otherwise.
@cindex @option{rclone} method
@vindex tramp-rclone-program
-The program @command{rclone} allows to access different system
+The program @command{rclone} enables accessing different system
storages in the cloud, see @uref{https://rclone.org/} for a list of
supported systems. If the @command{rclone} program isn't found in
your @env{PATH} environment variable, you can tell @value{tramp} its
@@ -2366,7 +2366,7 @@ connection information}. If you want, for example, use
@end group
@end lisp
-This works only for connection methods which allow to override the
+This works only for connection methods which allow overriding the
remote login shell, like @option{sshx} or @option{plink}. See
@ref{Inline methods} and @ref{External methods} for connection methods
which support this.
@@ -2436,8 +2436,10 @@ which may not be the same as the local login shell prompt,
@value{tramp} sets a similar default value for both prompts.
@item @code{tramp-password-prompt-regexp}
+@item @code{tramp-otp-password-prompt-regexp}
@item @code{tramp-wrong-passwd-regexp}
@vindex tramp-password-prompt-regexp
+@vindex tramp-otp-password-prompt-regexp
@vindex tramp-wrong-passwd-regexp
@value{tramp} uses @code{tramp-password-prompt-regexp} to
@@ -2471,6 +2473,10 @@ This user option is, by default, initialized from
is usually more convenient to add new passphrases to that user option
instead of altering this user option.
+The user option @code{tramp-otp-password-prompt-regexp} has a similar
+purpose, but for one-time passwords. Those passwords are not cached
+by @value{tramp} for reuse.
+
Similar localization may be necessary for handling wrong password
prompts, for which @value{tramp} uses @code{tramp-wrong-passwd-regexp}.
@@ -2978,7 +2984,7 @@ connection cleanup or on Emacs exiting.
@cindex rclone setup
The default arguments of the @command{rclone} operations
-@command{mount}, @command{coopyto}, @command{moveto} and
+@command{mount}, @command{copyto}, @command{moveto} and
@command{about} are declared in the variable @code{tramp-methods} as
method specific parameters. Usually, they don't need to be overwritten.
@@ -3665,7 +3671,7 @@ ssh@value{postfixhop}you@@remotehost@value{postfix}/path @key{RET}}
Each involved method must be an inline method (@pxref{Inline methods}).
@value{tramp} adds the ad-hoc definitions on the fly to
-@code{tramp-default-proxies-alist} and is available for re-use during
+@code{tramp-default-proxies-alist} and is available for reuse during
that Emacs session. Subsequent @value{tramp} connections to the same
remote host can then use the shortcut form:
@samp{@trampfn{ssh,you@@remotehost,/path}}.
@@ -3704,6 +3710,47 @@ host name of the previous hop is reused. Therefore, the following
file name is equivalent to the previous example:
@samp{@trampfn{ssh@value{postfixhop}remotehost|su,,}}.
+@defopt tramp-completion-multi-hop-methods
+When this list includes the last method in a multi-hop connection, the
+remote host will be queried for a list of completion candidates. This
+can, for example, provide a list of running docker or podman
+containers on the remote host.
+
+@lisp
+(customize-set-variable 'tramp-completion-multi-hop-methods
+ `(,tramp-docker-method ,tramp-podman-method))
+@end lisp
+@end defopt
+
+A common use case for ad-hoc specifications is to visit a file or a
+directory with proper permissions, for example with the @option{sudo}
+method. The command @code{tramp-revert-buffer-with-sudo} supports
+this.
+
+@deffn Command tramp-revert-buffer-with-sudo
+This command shows the current buffer with @option{sudo} permissions.
+The buffer must either visit a file, or a directory
+(@code{dired-mode}).
+@end deffn
+
+@defopt tramp-file-name-with-method
+The method @code{tramp-revert-buffer-with-sudo} shows an alternate
+buffer. It defaults to @code{sudo}, other valid methods are
+@code{su}, @code{doas}, and @code{ksu}.
+
+@lisp
+(customize-set-variable 'tramp-file-name-with-method "doas")
+@end lisp
+@end defopt
+
+These methods apply the user @samp{root} as default. If another user
+shall be taken, add a proper rule to the user option
+@code{tramp-default-user-alist} (@pxref{Default User}):
+
+@lisp
+(add-to-list 'tramp-default-user-alist '("sudo" "remotehost" "admin"))
+@end lisp
+
@node Home directories
@section Expanding @file{~} to home directory
@@ -4154,7 +4201,7 @@ To open @command{powershell} as a remote shell, use this:
@subsection Remote process connection type
@vindex process-connection-type
-@cindex tramp-process-connection-type
+@vindex tramp-process-connection-type
Asynchronous processes behave differently based on whether they use a
pseudo tty or not. This is controlled by the variable
@@ -4291,7 +4338,7 @@ called @code{tramp-connection-local-*-ps-profile} and
@end group
@end lisp
-@cindex proced
+@cindex @code{proced}
@vindex proced-show-remote-processes
If you want to see a listing of remote system processes when calling
@code{proced}, set user option @code{proced-show-remote-processes} to
@@ -4359,9 +4406,6 @@ It does not report the remote terminal name via @code{process-tty-name}.
@item
It does not set process property @code{remote-pid}.
-
-@item
-It does not use @code{tramp-remote-path}.
@end itemize
In order to gain even more performance, it is recommended to bind
@@ -5193,7 +5237,7 @@ Yes. @command{OpenSSH} has added support for @acronym{FIDO} hardware
devices via special key types @option{*-sk}. @value{tramp} supports
the additional handshaking messages for them. This requires at least
@command{OpenSSH} 8.2, and a @acronym{FIDO} @acronym{U2F} compatible
-security key, like yubikey, solokey, or nitrokey.
+security key, like yubikey, solokey, nitrokey, or titankey.
@item
@@ -5252,30 +5296,11 @@ How to get notified after @value{tramp} completes file transfers?
Make Emacs beep after reading from or writing to the remote host with
the following code in @file{~/.emacs}.
+@vindex tramp-handle-write-region-hook
+@vindex tramp-handle-file-local-copy-hook
@lisp
-@group
-(defadvice tramp-handle-write-region
- (after tramp-write-beep-advice activate)
- "Make @value{tramp} beep after writing a file."
- (interactive)
- (beep))
-@end group
-
-@group
-(defadvice tramp-handle-do-copy-or-rename-file
- (after tramp-copy-beep-advice activate)
- "Make @value{tramp} beep after copying a file."
- (interactive)
- (beep))
-@end group
-
-@group
-(defadvice tramp-handle-insert-file-contents
- (after tramp-insert-beep-advice activate)
- "Make @value{tramp} beep after inserting a file."
- (interactive)
- (beep))
-@end group
+(add-hook 'tramp-handle-write-region-hook 'beep)
+(add-hook 'tramp-handle-file-local-copy-hook 'beep)
@end lisp
@@ -5294,17 +5319,39 @@ customization is explained in user option
@item
Remote host does not understand default options for directory listing
-Emacs computes the @command{dired} options based on the local host but
-if the remote host cannot understand the same @command{ls} command,
-then set them with a hook as follows:
+@vindex dired-listing-switches
+Emacs computes the @command{dired} options based on the local host.
+Since @w{Emacs 30}, these options can be set connection-local.
+@ifinfo
+@xref{Connection Variables, , , emacs}.
+@end ifinfo
+
+@lisp
+@group
+(connection-local-set-profile-variables
+ 'my-dired-profile
+ '((dired-listing-switches . "-ahl")))
+@end group
+
+@group
+(connection-local-set-profiles
+ '(:application tramp :machine "remotehost")
+ 'my-dired-profile)
+@end group
+@end lisp
+
+@vindex dired-actual-switches
+In older Emacsen, you can set the @command{dired} options with a hook
+as follows:
@lisp
@group
(add-hook
'dired-before-readin-hook
(lambda ()
- (when (file-remote-p default-directory)
- (setq dired-actual-switches "-al"))))
+ (when (string-equal
+ (file-remote-p default-directory 'host) "remotehost")
+ (setq dired-actual-switches "-ahl"))))
@end group
@end lisp
@@ -5528,9 +5575,8 @@ minibuffer:
@end group
@group
-(defadvice minibuffer-complete
- (before my-minibuffer-complete activate)
- (expand-abbrev))
+(advice-add 'minibuffer-complete
+ :before 'expand-abbrev)
@end group
@end lisp
@@ -5727,6 +5773,8 @@ If you find the cleanup disturbing, because the file names in
two forms in your @file{~/.emacs} after loading the @code{tramp} and
@code{recentf} packages:
+@vindex tramp-cleanup-connection-hook
+@vindex tramp-cleanup-all-connections-hook
@lisp
@group
(remove-hook
@@ -6060,20 +6108,23 @@ wrapping the timer function body as follows:
to 10. @value{tramp} does not display all messages; only those with a
verbosity level less than or equal to @code{tramp-verbose}.
+@noindent
The verbosity levels are
- @w{ 0} silent (no @value{tramp} messages at all)
-@*@indent @w{ 1} errors
-@*@indent @w{ 2} warnings
-@*@indent @w{ 3} connection to remote hosts (default verbosity)
-@*@indent @w{ 4} activities
-@*@indent @w{ 5} internal
-@*@indent @w{ 6} sent and received strings
-@*@indent @w{ 7} connection properties
-@*@indent @w{ 8} file caching
-@*@indent @w{ 9} test commands
-@*@indent @w{10} traces (huge)
-@*@indent @w{11} call traces (maintainer only)
+@itemize @w{}
+@item @w{ 0} Silent (no @value{tramp} messages at all)
+@item @w{ 1} Errors
+@item @w{ 2} Warnings
+@item @w{ 3} Connection to remote hosts (default verbosity)
+@item @w{ 4} Activities
+@item @w{ 5} Internal
+@item @w{ 6} Sent and received strings
+@item @w{ 7} Connection properties
+@item @w{ 8} File caching
+@item @w{ 9} Test commands
+@item @w{10} Traces (huge)
+@item @w{11} Call traces (maintainer only)
+@end itemize
With @code{tramp-verbose} greater than or equal to 4, messages are
also written to the @value{tramp} debug buffer @file{*debug
diff --git a/doc/misc/trampver.texi b/doc/misc/trampver.texi
index 2f505c6acea..a239c091889 100644
--- a/doc/misc/trampver.texi
+++ b/doc/misc/trampver.texi
@@ -2,7 +2,7 @@
@c texi/trampver.texi. Generated from trampver.texi.in by configure.
@c This is part of the Emacs manual.
-@c Copyright (C) 2003--2023 Free Software Foundation, Inc.
+@c Copyright (C) 2003--2024 Free Software Foundation, Inc.
@c See file doclicense.texi for copying conditions.
@c In the Tramp GIT, the version number and the bug report address
diff --git a/doc/misc/transient.texi b/doc/misc/transient.texi
index be9e8698ab4..f76edc6b1e4 100644
--- a/doc/misc/transient.texi
+++ b/doc/misc/transient.texi
@@ -8,7 +8,7 @@
@copying
@quotation
-Copyright (C) 2018--2023 Free Software Foundation, Inc.
+Copyright (C) 2018--2024 Free Software Foundation, Inc.
You can redistribute this document and/or modify it under the terms
of the GNU General Public License as published by the Free Software
@@ -31,7 +31,7 @@ General Public License for more details.
@finalout
@titlepage
@title Transient User and Developer Manual
-@subtitle for version 0.4.1
+@subtitle for version 0.5.2
@author Jonas Bernoulli
@page
@vskip 0pt plus 1filll
@@ -44,37 +44,16 @@ General Public License for more details.
@node Top
@top Transient User and Developer Manual
-Taking inspiration from prefix keys and prefix arguments, Transient
-implements a similar abstraction involving a prefix command, infix
-arguments and suffix commands. We could call this abstraction a
-“transient command”, but because it always involves at least two
-commands (a prefix and a suffix) we prefer to call it just a
-“transient”.
-
-When the user calls a transient prefix command, a transient
-(temporary) keymap is activated, which binds the transient's infix
-and suffix commands, and functions that control the transient state
-are added to @code{pre-command-hook} and @code{post-command-hook}. The available
-suffix and infix commands and their state are shown in a popup buffer
-until the transient is exited by invoking a suffix command.
-
-Calling an infix command causes its value to be changed, possibly by
-reading a new value in the minibuffer.
+Transient is the library used to implement the keyboard-driven ``menus''
+in Magit. It is distributed as a separate package, so that it can be
+used to implement similar menus in other packages.
-Calling a suffix command usually causes the transient to be exited
-but suffix commands can also be configured to not exit the transient.
-
-@quotation
-The second part of this manual, which describes how to modify existing
-transients and create new transients from scratch, can be hard to
-digest if you are just getting started. A useful resource to get over
-that hurdle is Psionic K's interactive tutorial, available at
-@uref{https://github.com/positron-solutions/transient-showcase}.
-
-@end quotation
+This manual can be bit hard to digest when getting started. A useful
+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.4.1.
+This manual is for Transient version 0.5.2.
@insertcopying
@end ifnottex
@@ -85,7 +64,6 @@ This manual is for Transient version 0.4.1.
* Modifying Existing Transients::
* Defining New Commands::
* Classes and Methods::
-* Related Abstractions and Packages::
* FAQ::
* Keystroke Index::
* Command and Function Index::
@@ -110,6 +88,7 @@ Usage
Defining New Commands
+* Technical Introduction::
* Defining Transients::
* Binding Suffix and Infix Commands::
* Defining Suffix and Infix Commands::
@@ -139,136 +118,87 @@ Suffix Methods
* Suffix Format Methods::
-Related Abstractions and Packages
-
-* Comparison With Prefix Keys and Prefix Arguments::
-* Comparison With Other Packages::
-
@end detailmenu
@end menu
@node Introduction
@chapter Introduction
-Taking inspiration from prefix keys and prefix arguments, Transient
-implements a similar abstraction involving a prefix command, infix
-arguments and suffix commands. We could call this abstraction a
-“transient command”, but because it always involves at least two
-commands (a prefix and a suffix) we prefer to call it just a
-“transient”.
-
-@cindex transient prefix command
-@quotation
-Transient keymaps are a feature provided by Emacs. Transients as
-implemented by this package involve the use of transient keymaps.
-
-Emacs provides a feature that it calls @dfn{prefix commands}. When we
-talk about “prefix commands” in this manual, then we mean our own kind
-of “prefix commands”, unless specified otherwise. To avoid ambiguity
-we sometimes use the terms @dfn{transient prefix command} for our kind and
-“regular prefix command” for Emacs' kind.
-
-@end quotation
-
-When the user calls a transient prefix command, a transient
-(temporary) keymap is activated, which binds the transient's infix and
-suffix commands, and functions that control the transient state are
-added to @code{pre-command-hook} and @code{post-command-hook}. The available suffix
-and infix commands and their state are shown in a popup buffer until
-the transient state is exited by invoking a suffix command.
-
-Calling an infix command causes its value to be changed. How that is
-done depends on the type of the infix command. The simplest case is
-an infix command that represents a command-line argument that does not
-take a value. Invoking such an infix command causes the switch to be
-toggled on or off. More complex infix commands may read a value from
-the user, using the minibuffer.
-
-Calling a suffix command usually causes the transient to be exited;
-the transient keymaps and hook functions are removed, the popup buffer
-no longer shows information about the (no longer bound) suffix
-commands, the values of some public global variables are set, while
-some internal global variables are unset, and finally the command is
-actually called. Suffix commands can also be configured to not exit
-the transient.
-
-A suffix command can, but does not have to, use the infix arguments in
-much the same way any command can choose to use or ignore the prefix
-arguments. For a suffix command that was invoked from a transient, the
-variable @code{transient-current-suffixes} and the function @code{transient-args}
-serve about the same purpose as the variables @code{prefix-arg} and
-@code{current-prefix-arg} do for any command that was called after the prefix
-arguments have been set using a command such as @code{universal-argument}.
-
-The information shown in the popup buffer while a transient is active
-looks a bit like this:
-
-@example
-,-----------------------------------------
-|Arguments
-| -f Force (--force)
-| -a Annotate (--annotate)
-|
-|Create
-| t tag
-| r release
-`-----------------------------------------
-@end example
-
-@quotation
-This is a simplified version of @code{magit-tag}. Info manuals do not
-support images or colored text, so the above “screenshot” lacks some
-information; in practice you would be able to tell whether the
-arguments @code{--force} and @code{--annotate} are enabled or not based on their
-color.
-
-@end quotation
-
-@cindex command dispatchers
-Transient can be used to implement simple “command dispatchers”. The
-main benefit then is that the user can see all the available commands
-in a popup buffer. That is useful by itself because it frees the user
-from having to remember all the keys that are valid after a certain
-prefix key or command. Magit's @code{magit-dispatch} (on @kbd{C-x M-g}) command is
-an example of using Transient to merely implement a command
-dispatcher.
-
-In addition to that, Transient also allows users to interactively pass
-arguments to commands. These arguments can be much more complex than
-what is reasonable when using prefix arguments. There is a limit to
-how many aspects of a command can be controlled using prefix
-arguments. Furthermore, what a certain prefix argument means for
-different commands can be completely different, and users have to read
-documentation to learn and then commit to memory what a certain prefix
-argument means to a certain command.
+Transient is the library used to implement the keyboard-driven @dfn{menus}
+in Magit. It is distributed as a separate package, so that it can be
+used to implement similar menus in other packages.
-Transient suffix commands, on the other hand, can accept dozens of
-different arguments without the user having to remember anything.
-When using Transient, one can call a command with arguments that are
-just as complex as when calling the same function non-interactively
-from Lisp.
+This manual can be bit hard to digest when getting started. A useful
+resource to get over that hurdle is Psionic K's interactive tutorial,
+available at @uref{https://github.com/positron-solutions/transient-showcase}.
-Invoking a transient command with arguments is similar to invoking a
-command in a shell with command-line completion and history enabled.
-One benefit of the Transient interface is that it remembers history
-not only on a global level (“this command was invoked using these
-arguments, and previously it was invoked using those other arguments”),
-but also remembers the values of individual arguments independently.
-@xref{Using History}.
+@anchor{Some things that Transient can do}
+@heading Some things that Transient can do
-After a transient prefix command is invoked, @kbd{C-h @var{KEY}} can be used to
-show the documentation for the infix or suffix command that @kbd{@var{KEY}} is
-bound to (@pxref{Getting Help for Suffix Commands}), and infixes and
-suffixes can be removed from the transient using @kbd{C-x l @var{KEY}}. Infixes
-and suffixes that are disabled by default can be enabled the same way.
-@xref{Enabling and Disabling Suffixes}.
+@itemize
+@item
+Display current state of arguments
+@item
+Display and manage lifecycle of modal bindings
+@item
+Contextual user interface
+@item
+Flow control for wizard-like composition of interactive forms
+@item
+History & persistence
+@item
+Rendering arguments for controlling CLI programs
+@end itemize
-Transient ships with support for a few different types of specialized
-infix commands. A command that sets a command line option, for example,
-has different needs than a command that merely toggles a boolean flag.
-Additionally, Transient provides abstractions for defining new types,
-which the author of Transient did not anticipate (or didn't get around
-to implementing yet).
+@anchor{Complexity in CLI programs}
+@heading Complexity in CLI programs
+
+Complexity tends to grow with time. How do you manage the complexity
+of commands? Consider the humble shell command @samp{ls}. It now has over
+@emph{fifty} command line options. Some of these are boolean flags (@samp{ls -l}).
+Some take arguments (@samp{ls --sort=s}). Some have no effect unless paired
+with other flags (@samp{ls -lh}). Some are mutually exclusive. Some shell
+commands even have so many options that they introduce @emph{subcommands}
+(@samp{git branch}, @samp{git commit}), each with their own rich set of options
+(@samp{git branch -f}).
+
+@anchor{Using Transient for composing interactive commands}
+@heading Using Transient for composing interactive commands
+
+What about Emacs commands used interactively? How do these handle
+options? One solution is to make many versions of the same command,
+so you don't need to! Consider: @samp{delete-other-windows} vs.
+@samp{delete-other-windows-vertically} (among many similar examples).
+
+Some Emacs commands will simply prompt you for the next "argument"
+(@samp{M-x switch-to-buffer}). Another common solution is to use prefix
+arguments which usually start with @samp{C-u}. Sometimes these are sensibly
+numerical in nature (@samp{C-u 4 M-x forward-paragraph} to move forward 4
+paragraphs). But sometimes they function instead as boolean
+"switches" (@samp{C-u C-SPACE} to jump to the last mark instead of just
+setting it, @samp{C-u C-u C-SPACE} to unconditionally set the mark). Since
+there aren't many standards for the use of prefix options, you have to
+read the command's documentation to find out what the possibilities
+are.
+
+But when an Emacs command grows to have a truly large set of options
+and arguments, with dependencies between them, lots of option values,
+etc., these simple approaches just don't scale. Transient is designed
+to solve this issue. Think of it as the humble prefix argument @samp{C-u},
+@emph{raised to the power of 10}. Like @samp{C-u}, it is key driven. Like the
+shell, it supports boolean "flag" options, options that take
+arguments, and even "sub-commands", with their own options. But
+instead of searching through a man page or command documentation,
+well-designed transients @emph{guide} their users to the relevant set of
+options (and even their possible values!) directly, taking into
+account any important pre-existing Emacs settings. And while for
+shell commands like @samp{ls}, there is only one way to "execute" (hit
+@samp{Return}!), transients can "execute" using multiple different keys tied
+to one of many self-documenting @emph{actions} (imagine having 5 different
+colored return keys on your keyboard!). Transients make navigating
+and setting large, complex groups of command options and arguments
+easy. Fun even. Once you've tried it, it's hard to go back to the
+@samp{C-u what can I do here again?} way.
@node Usage
@chapter Usage
@@ -349,7 +279,7 @@ it returns to the previous transient, if any.
Transient's predecessor bound @kbd{q} instead of @kbd{C-g} to the quit command.
To learn how to get that binding back see @code{transient-bind-q-to-quit}'s
-doc string.
+documentation string.
@table @asis
@item @kbd{C-q} (@code{transient-quit-all})
@@ -365,7 +295,7 @@ suspended transients, if any.
Like @code{transient-quit-all}, this command quits an incomplete key
sequence, if any, and all transients. Additionally, it saves the
stack of transients so that it can easily be resumed (which is
-particularly useful if you quickly need to do “something else” and
+particularly useful if you quickly need to do ``something else'' and
the stack is deeper than a single transient, and/or you have already
changed the values of some infix arguments).
@@ -392,7 +322,7 @@ as well as some other commands that are all bound to @kbd{C-x @var{KEY}}. After
@kbd{C-x} is pressed, a section featuring all these common commands is
temporarily shown in the popup buffer. After invoking one of them,
the section disappears again. Note, however, that one of these
-commands is described as “Show common permanently”; invoke that if you
+commands is described as ``Show common permanently''; invoke that if you
want the common commands to always be shown for all transients.
@table @asis
@@ -545,8 +475,8 @@ What sort of documentation is shown depends on how the transient was
defined. For infix commands that represent command-line arguments
this ideally shows the appropriate manpage. @code{transient-help} then tries
to jump to the correct location within that. Info manuals are also
-supported. The fallback is to show the command's doc string, for
-non-infix suffixes this is usually appropriate.
+supported. The fallback is to show the command's documentation
+string, for non-infix suffixes this is usually appropriate.
@node Enabling and Disabling Suffixes
@section Enabling and Disabling Suffixes
@@ -572,7 +502,7 @@ displayed at any level.
The levels of individual transients and/or their individual suffixes
can be changed interactively, by invoking the transient and then
-pressing @kbd{C-x l} to enter the “edit” mode, see below.
+pressing @kbd{C-x l} to enter the ``edit'' mode, see below.
The default level for both transients and their suffixes is 4. The
@code{transient-default-level} option only controls the default for
@@ -620,6 +550,13 @@ not. The predicates also apply in edit mode.
Therefore, to control which suffixes are available given a certain
state, you have to make sure that that state is currently active.
+
+@item @kbd{C-x a} (@code{transient-toggle-level-limit})
+@kindex C-x a
+@findex transient-toggle-level-limit
+This command toggle whether suffixes that are on levels lower than
+the level specified by @code{transient-default-level} are temporarily
+available anyway.
@end table
@node Other Commands
@@ -765,27 +702,31 @@ If @code{nil}, then the buffer has no mode-line. If the buffer is not
displayed right above the echo area, then this probably is not a
good value.
-If @code{line} (the default), then the buffer also has no mode-line, but a
-thin line is drawn instead, using the background color of the face
-@code{transient-separator}. Text-mode frames cannot display thin lines,
-and therefore fall back to treating @code{line} like @code{nil}.
+If @code{line} (the default) or a natural number, then the buffer
+has no mode-line, but a line is drawn is drawn in its place.
+If a number is used, that specifies the thickness of the line.
+On termcap frames we cannot draw lines, so there @code{line} and
+numbers are synonyms for @code{nil}.
+
+The color of the line is used to indicate if non-suffixes are
+allowed and whether they exit the transient. The foreground
+color of @code{transient-key-noop} (if non-suffix are disallowed),
+@code{transient-key-stay} (if allowed and transient stays active), or
+@code{transient-key-exit} (if allowed and they exit the transient) is
+used to draw the line.
Otherwise this can be any mode-line format. @xref{Mode Line
Format,,,elisp,}, for details.
@end defopt
@defopt transient-semantic-coloring
-This option controls whether prefixes and suffixes are colored in
-a Hydra-like fashion.
+This option controls whether colors are used to indicate the
+transient behavior of commands.
If non-@code{nil}, then the key binding of each suffix is colorized to
indicate whether it exits the transient state or not. The color of
the prefix is indicated using the line that is drawn when the value
of @code{transient-mode-line-format} is @code{line}.
-
-For more information about how Hydra uses colors see
-@uref{https://github.com/abo-abo/hydra#color} and
-@uref{https://oremacs.com/2015/02/19/hydra-colors-reloaded}.
@end defopt
@defopt transient-highlight-mismatched-keys
@@ -922,8 +863,8 @@ The following functions share a few arguments:
@item
@var{SUFFIX} is a transient infix or suffix specification in the same form
as expected by @code{transient-define-prefix}. Note that an infix is a
-special kind of suffix. Depending on context “suffixes” means
-“suffixes (including infixes)” or “non-infix suffixes”. Here it
+special kind of suffix. Depending on context ``suffixes'' means
+``suffixes (including infixes)'' or ``non-infix suffixes''. Here it
means the former. @xref{Suffix Specifications}.
@var{SUFFIX} may also be a group in the same form as expected by
@@ -998,6 +939,7 @@ signal an error.
@chapter Defining New Commands
@menu
+* Technical Introduction::
* Defining Transients::
* Binding Suffix and Infix Commands::
* Defining Suffix and Infix Commands::
@@ -1005,6 +947,106 @@ signal an error.
* Transient State::
@end menu
+@node Technical Introduction
+@section Technical Introduction
+
+Taking inspiration from prefix keys and prefix arguments, Transient
+implements a similar abstraction involving a prefix command, infix
+arguments and suffix commands.
+
+When the user calls a transient prefix command, a transient
+(temporary) keymap is activated, which binds the transient's infix and
+suffix commands, and functions that control the transient state are
+added to @code{pre-command-hook} and @code{post-command-hook}. The available suffix
+and infix commands and their state are shown in a popup buffer until
+the transient state is exited by invoking a suffix command.
+
+Calling an infix command causes its value to be changed. How that is
+done depends on the type of the infix command. The simplest case is
+an infix command that represents a command-line argument that does not
+take a value. Invoking such an infix command causes the switch to be
+toggled on or off. More complex infix commands may read a value from
+the user, using the minibuffer.
+
+Calling a suffix command usually causes the transient to be exited;
+the transient keymaps and hook functions are removed, the popup buffer
+no longer shows information about the (no longer bound) suffix
+commands, the values of some public global variables are set, while
+some internal global variables are unset, and finally the command is
+actually called. Suffix commands can also be configured to not exit
+the transient.
+
+A suffix command can, but does not have to, use the infix arguments in
+much the same way any command can choose to use or ignore the prefix
+arguments. For a suffix command that was invoked from a transient, the
+variable @code{transient-current-suffixes} and the function @code{transient-args}
+serve about the same purpose as the variables @code{prefix-arg} and
+@code{current-prefix-arg} do for any command that was called after the prefix
+arguments have been set using a command such as @code{universal-argument}.
+
+@cindex command dispatchers
+Transient can be used to implement simple ``command dispatchers''. The
+main benefit then is that the user can see all the available commands
+in a popup buffer, which can be thought of as a ``menus''. That is
+useful by itself because it frees the user from having to remember all
+the keys that are valid after a certain prefix key or command.
+Magit's @code{magit-dispatch} (on @kbd{C-x M-g}) command is an example of using
+Transient to merely implement a command dispatcher.
+
+In addition to that, Transient also allows users to interactively pass
+arguments to commands. These arguments can be much more complex than
+what is reasonable when using prefix arguments. There is a limit to
+how many aspects of a command can be controlled using prefix
+arguments. Furthermore, what a certain prefix argument means for
+different commands can be completely different, and users have to read
+documentation to learn and then commit to memory what a certain prefix
+argument means to a certain command.
+
+Transient suffix commands, on the other hand, can accept dozens of
+different arguments without the user having to remember anything.
+When using Transient, one can call a command with arguments that are
+just as complex as when calling the same function non-interactively
+from Lisp.
+
+Invoking a transient suffix command with arguments is similar to
+invoking a command in a shell with command-line completion and history
+enabled. One benefit of the Transient interface is that it remembers
+history not only on a global level (``this command was invoked using
+these arguments, and previously it was invoked using those other
+arguments''), but also remembers the values of individual arguments
+independently. See @ref{Using History}.
+
+After a transient prefix command is invoked, @kbd{C-h @var{KEY}} can be used to
+show the documentation for the infix or suffix command that @kbd{@var{KEY}} is
+bound to (see @ref{Getting Help for Suffix Commands}), and infixes and
+suffixes can be removed from the transient using @kbd{C-x l @var{KEY}}. Infixes
+and suffixes that are disabled by default can be enabled the same way.
+See @ref{Enabling and Disabling Suffixes}.
+
+Transient ships with support for a few different types of specialized
+infix commands. A command that sets a command line option, for example,
+has different needs than a command that merely toggles a boolean flag.
+Additionally, Transient provides abstractions for defining new types,
+which the author of Transient did not anticipate (or didn't get around
+to implementing yet).
+
+Note that suffix commands also support regular prefix arguments. A
+suffix command may even be called with both infix and prefix arguments
+at the same time. If you invoke a command as a suffix of a transient
+prefix command, but also want to pass prefix arguments to it, then
+first invoke the prefix command, and only after doing that invoke the
+prefix arguments, before finally invoking the suffix command. If you
+instead began by providing the prefix arguments, then those would
+apply to the prefix command, not the suffix command. Likewise, if you
+want to change infix arguments before invoking a suffix command with
+prefix arguments, then change the infix arguments before invoking the
+prefix arguments. In other words, regular prefix arguments always
+apply to the next command, and since transient prefix, infix and
+suffix commands are just regular commands, the same applies to them.
+(Regular prefix keys behave differently because they are not commands
+at all, instead they are just incomplete key sequences, and those
+cannot be interrupted with prefix commands.)
+
@node Defining Transients
@section Defining Transients
@@ -1049,7 +1091,7 @@ however, call that function only when some condition is satisfied.
All transients have a (possibly @code{nil}) value, which is exported when
suffix commands are called, so that they can consume that value.
For some transients it might be necessary to have a sort of
-secondary value, called a “scope”. Such a scope would usually be
+secondary value, called a ``scope''. Such a scope would usually be
set in the command's @code{interactive} form and has to be passed to the
setup function:
@@ -1070,10 +1112,9 @@ Transients}) and adds the transient's infix and suffix bindings, as
described below.
Users and third-party packages can add additional bindings using
-functions such as @code{transient-insert-suffix} (@pxref{Modifying
-Existing Transients}). These functions take a “suffix
-specification” as one of their arguments, which has the same form as
-the specifications used in @code{transient-define-prefix}.
+functions such as @code{transient-insert-suffix} (@pxref{Modifying Existing Transients}). These functions take a ``suffix specification'' as one of
+their arguments, which has the same form as the specifications used in
+@code{transient-define-prefix}.
@menu
* Group Specifications::
@@ -1207,8 +1248,8 @@ The same form is also used when later binding additional commands
using functions such as @code{transient-insert-suffix}, see @ref{Modifying Existing Transients}.
Note that an infix is a special kind of suffix. Depending on context
-“suffixes” means “suffixes (including infixes)” or “non-infix
-suffixes”. Here it means the former.
+``suffixes'' means ``suffixes (including infixes)'' or ``non-infix
+suffixes''. Here it means the former.
Suffix specifications have this form:
@@ -1234,10 +1275,10 @@ the object's values just for the binding inside this transient.
@item
@var{DESCRIPTION} is the description, either a string or a function that
-returns a string. The function should be a lambda expression to
-avoid ambiguity. In some cases a symbol that is bound as a function
-would also work but to be safe you should use @code{:description} in that
-case.
+takes zero or one arguments (the suffix object) and returns a string.
+The function should be a lambda expression to avoid ambiguity. In
+some cases a symbol that is bound as a function would also work but
+to be safe you should use @code{:description} in that case.
@end itemize
The next element is either a command or an argument. This is the only
@@ -1302,8 +1343,8 @@ argument supported by the constructor of that class. See @ref{Suffix Slots}.
@cindex defining infix commands
Note that an infix is a special kind of suffix. Depending on context
-“suffixes” means “suffixes (including infixes)” or “non-infix
-suffixes”.
+``suffixes'' means ``suffixes (including infixes)'' or ``non-infix
+suffixes''.
@defmac transient-define-suffix name arglist [docstring] [keyword value]@dots{} body@dots{}
This macro defines @var{NAME} as a transient suffix command.
@@ -1436,7 +1477,7 @@ returned value is a symbol, the transient prefix command.
@cindex transient state
-Invoking a transient prefix command “activates” the respective
+Invoking a transient prefix command ``activates'' the respective
transient, i.e., it puts a transient keymap into effect, which binds
the transient's infix and suffix commands.
@@ -1448,73 +1489,65 @@ Invoking an infix command does not affect the transient state; the
transient remains active.
@item
-Invoking a (non-infix) suffix command “deactivates” the transient
+Invoking a (non-infix) suffix command ``deactivates'' the transient
state by removing the transient keymap and performing some
additional cleanup.
@item
Invoking a command that is bound in a keymap other than the
transient keymap is disallowed and trying to do so results in a
-warning. This does not “deactivate” the transient.
+warning. This does not ``deactivate'' the transient.
@end itemize
-But these are just the defaults. Whether a certain command
-deactivates or “exits” the transient is configurable. There is more
-than one way in which a command can be “transient” or “non-transient”;
-the exact behavior is implemented by calling a so-called “pre-command”
-function. Whether non-suffix commands are allowed to be called is
-configurable per transient.
+The behavior can be changed for all suffixes of a particular prefix
+and/or for individual suffixes. The values should nearly always be
+booleans, but certain functions, called ``pre-commands'', can also be
+used. These functions are named @code{transient--do-VERB}, and the symbol
+@code{VERB} can be used as a shorthand.
-@itemize
-@item
-The transient-ness of suffix commands (including infix commands) is
-controlled by the value of their @code{transient} slot, which can be set
-either when defining the command or when adding a binding to a
-transient while defining the respective transient prefix command.
+A boolean is interpreted as answering the question "does the
+transient stay active, when this command is invoked?" @code{t} means that
+the transient stays active, while @code{nil} means that invoking the command
+exits the transient.
-Valid values are booleans and the pre-commands described below.
+Note that when the suffix is a ``sub-prefix'', invoking that command
+always activates that sub-prefix, causing the outer prefix to no
+longer be active and displayed. Here @code{t} means that when you exit the
+inner prefix, then the outer prefix becomes active again, while @code{nil}
+means that all outer prefixes are exited at once.
@itemize
@item
-@code{t} is equivalent to @code{transient--do-stay}.
-@item
-@code{nil} is equivalent to @code{transient--do-exit}.
-@item
-If @code{transient} is unbound (and that is actually the default for
-non-infix suffixes) then the value of the prefix's
-@code{transient-suffix} slot is used instead. The default value of that
-slot is @code{nil}, so the suffix's @code{transient} slot being unbound is
-essentially equivalent to it being @code{nil}.
-@end itemize
+The behavior for non-suffixes can be set for a particular prefix,
+by the prefix's @code{transient-non-suffix} slot to a boolean, a suitable
+pre-command function, or a shorthand for such a function. See
+@ref{Pre-commands for Non-Suffixes}.
@item
-A suffix command can be a prefix command itself, i.e., a
-“sub-prefix”. While a sub-prefix is active we nearly always want
-@kbd{C-g} to take the user back to the “super-prefix”. However in rare
-cases this may not be desirable, and that makes the following
-complication necessary:
+The common behavior for the suffixes of a particular prefix can be
+set using the prefix's @code{transient-suffixes} slot.
-For @code{transient-suffix} objects the @code{transient} slot is unbound. We can
-ignore that for the most part because, as stated above, @code{nil} and the
-slot being unbound are equivalent, and mean “do exit”. That isn't
-actually true for suffixes that are sub-prefixes though. For such
-suffixes unbound means “do exit but allow going back”, which is the
-default, while @code{nil} means “do exit permanently”, which requires that
-slot to be explicitly set to that value.
+The value specified in this slot does @strong{not} affect infixes. Because
+it affects both regular suffixes as well as sub-prefixes, which
+have different needs, it is best to avoid explicitly specifying a
+function.
@item
-The transient-ness of certain built-in suffix commands is specified
-using @code{transient-predicate-map}. This is a special keymap, which
-binds commands to pre-commands (as opposed to keys to commands) and
-takes precedence over the @code{transient} slot.
+The behavior of an individual suffix can be changed using its
+@code{transient} slot. While it is usually best to use a boolean, for this
+slot it can occasionally make sense to specify a function explicitly.
+
+Note that this slot can be set when defining a suffix command using
+@code{transient-define-suffix} and/or in the definition of the prefix. If
+set in both places, then the latter takes precedence, as usual.
@end itemize
-The available pre-command functions are documented below. They are
-called by @code{transient--pre-command}, a function on @code{pre-command-hook} and
-the value that they return determines whether the transient is exited.
-To do so the value of one of the constants @code{transient--exit} or
-@code{transient--stay} is used (that way we don't have to remember if @code{t} means
-“exit” or “stay”).
+The available pre-command functions are documented in the following
+sub-sections. They are called by @code{transient--pre-command}, a function
+on @code{pre-command-hook}, and the value that they return determines whether
+the transient is exited. To do so the value of one of the constants
+@code{transient--exit} or @code{transient--stay} is used (that way we don't have to
+remember if @code{t} means ``exit'' or ``stay'').
Additionally, these functions may change the value of @code{this-command}
(which explains why they have to be called using @code{pre-command-hook}),
@@ -1522,11 +1555,39 @@ call @code{transient-export}, @code{transient--stack-zap} or @code{transient--st
and set the values of @code{transient--exitp}, @code{transient--helpp} or
@code{transient--editp}.
+For completeness sake, some notes about complications:
+
+@itemize
+@item
+The transient-ness of certain built-in suffix commands is specified
+using @code{transient-predicate-map}. This is a special keymap, which
+binds commands to pre-commands (as opposed to keys to commands) and
+takes precedence over the prefix's @code{transient-suffix} slot, but not
+the suffix's @code{transient} slot.
+
+@item
+While a sub-prefix is active we nearly always want @kbd{C-g} to take the
+user back to the ``super-prefix'', even when the other suffixes don't
+do that. However, in rare cases this may not be desirable, and that
+makes the following complication necessary:
+
+For @code{transient-suffix} objects the @code{transient} slot is unbound. We can
+ignore that for the most part because @code{nil} and the slot being unbound
+are treated as equivalent, and mean ``do exit''. That isn't actually
+true for suffixes that are sub-prefixes though. For such suffixes
+unbound means ``do exit but allow going back'', which is the default,
+while @code{nil} means ``do exit permanently'', which requires that slot to
+be explicitly set to that value.
+@end itemize
+
@anchor{Pre-commands for Infixes}
@subheading Pre-commands for Infixes
The default for infixes is @code{transient--do-stay}. This is also the only
-function that makes sense for infixes.
+function that makes sense for infixes, which is why this predicate is
+used even if the value of the prefix's @code{transient-suffix} slot is @code{t}. In
+extremely rare cases, one might want to use something else, which can
+be done by setting the infix's @code{transient} slot directly.
@defun transient--do-stay
Call the command without exporting variables and stay transient.
@@ -1537,23 +1598,16 @@ Call the command without exporting variables and stay transient.
By default, invoking a suffix causes the transient to be exited.
-If you want a different default behavior for a certain transient
-prefix command, then set its @code{:transient-suffix} slot. The value can be
-a boolean, answering the question "does the transient stay active,
-when a suffix command is invoked?" @code{t} means that the transient stays
-active, while @code{nil} means that invoking a suffix exits the transient.
-In either case, the exact behavior depends on whether the suffix is
-itself a prefix (i.e., a sub-prefix), an infix or a regular suffix.
-
The behavior for an individual suffix command can be changed by
-setting its @code{transient} slot to one of the following pre-commands.
+setting its @code{transient} slot to a boolean (which is highly recommended),
+or to one of the following pre-commands.
@defun transient--do-exit
Call the command after exporting variables and exit the transient.
@end defun
@defun transient--do-return
-Call the command after exporting variables and return to parent
+Call the command after exporting variables and return to the parent
prefix. If there is no parent prefix, then call @code{transient--do-exit}.
@end defun
@@ -1561,9 +1615,10 @@ prefix. If there is no parent prefix, then call @code{transient--do-exit}.
Call the command after exporting variables and stay transient.
@end defun
-The following pre-commands are suitable for sub-prefixes. Only the
-first should ever explicitly be set as the value of the @code{transient}
-slot.
+The following pre-commands are only suitable for sub-prefixes. It is
+not necessary to explicitly use these predicates because the correct
+predicate is automatically picked based on the value of the @code{transient}
+slot for the sub-prefix itself.
@defun transient--do-recurse
Call the transient prefix command, preparing for return to active
@@ -1571,15 +1626,25 @@ transient.
Whether we actually return to the parent transient is ultimately
under the control of each invoked suffix. The difference between
-this pre-command and @code{transient--do-replace} is that it changes the
-value of the @code{transient-suffix} slot to @code{transient--do-return}.
+this pre-command and @code{transient--do-stack} is that it changes the
+value of the @code{transient-suffix} slot to @code{t}.
If there is no parent transient, then only call this command and
skip the second step.
@end defun
+@defun transient--do-stack
+Call the transient prefix command, stacking the active transient.
+Push the active transient to the transient stack.
+
+Unless @code{transient--do-recurse} is explicitly used, this pre-command
+is automatically used for suffixes that are prefixes themselves,
+i.e., for sub-prefixes.
+@end defun
+
@defun transient--do-replace
Call the transient prefix command, replacing the active transient.
+Do not push the active transient to the transient stack.
Unless @code{transient--do-recurse} is explicitly used, this pre-command
is automatically used for suffixes that are prefixes themselves,
@@ -1590,7 +1655,7 @@ i.e., for sub-prefixes.
Suspend the active transient, saving the transient stack.
This is used by the command @code{transient-suspend} and optionally also by
-“external events” such as @code{handle-switch-frame}. Such bindings should
+``external events'' such as @code{handle-switch-frame}. Such bindings should
be added to @code{transient-predicate-map}.
@end defun
@@ -1601,17 +1666,17 @@ By default, non-suffixes (commands that are bound in other keymaps
beside the transient keymap) cannot be invoked. Trying to invoke
such a command results in a warning and the transient stays active.
-If you want a different behavior, then set the @code{:transient-non-suffix}
-slot of the transient prefix command. The value can be a boolean,
-answering the question, "is it allowed to invoke non-suffix commands?"
+If you want a different behavior, then set the @code{transient-non-suffix}
+slot of the transient prefix command. The value should be a boolean,
+answering the question, "is it allowed to invoke non-suffix commands?,
+a pre-command function, or a shorthand for such a function.
-If the value is @code{t} or @code{transient--do-stay}, then non-suffixes can be
-invoked, when it is @code{nil} or @code{transient--do-warn} (the default) then they
-cannot be invoked.
+If the value is @code{t}, then non-suffixes can be invoked, when it is @code{nil}
+(the default) then they cannot be invoked.
-The only other recommended value is @code{transient--do-leave}. If that is
-used, then non-suffixes can be invoked, but if one is invoked, then
-that exits the transient.
+The only other recommended value is @code{leave}. If that is used, then
+non-suffixes can be invoked, but if one is invoked, then that exits
+the transient.
@defun transient--do-warn
Call @code{transient-undefined} and stay transient.
@@ -1716,7 +1781,7 @@ The abstract @code{transient-child} class is the base class of both
@code{transient-group} (and therefore all groups) as well as of
@code{transient-suffix} (and therefore all suffix and infix commands).
-This class exists because the elements (or “children”) of certain
+This class exists because the elements (or ``children'') of certain
groups can be other groups instead of suffix and infix commands.
@item
@@ -1726,7 +1791,7 @@ group classes.
@item
The @code{transient-column} class is the simplest group.
-This is the default “flat” group. If the class is not specified
+This is the default ``flat'' group. If the class is not specified
explicitly and the first element is not a vector (i.e., not a group),
then this class is used.
@@ -1742,7 +1807,7 @@ Direct elements have to be groups whose elements have to be commands
or strings. Each subgroup represents a column. This class takes
care of inserting the subgroups' elements.
-This is the default “nested” group. If the class is not specified
+This is the default ``nested'' group. If the class is not specified
explicitly and the first element is a vector (i.e., a group), then
this class is used.
@@ -1853,6 +1918,24 @@ indicates that all remaining arguments are files.
@item
Classes used for infix commands that represent variables should
derived from the abstract @code{transient-variable} class.
+
+@item
+The @code{transient-information} class is special in that suffixes that use
+this class are not associated with a command and thus also not with
+any key binding. Such suffixes are only used to display arbitrary
+information, and that anywhere a suffix can appear. Display-only
+suffix specifications take this form:
+
+@lisp
+([LEVEL] :info DESCRIPTION [KEYWORD VALUE]...)
+@end lisp
+
+The @code{:info} keyword argument replaces the @code{:description} keyword used for
+other suffix classes. Other keyword arguments that you might want to
+set, include @code{:face}, predicate keywords (such as @code{:if}), and @code{:format}.
+By default the value of @code{:format} includes @code{%k}, which for this class is
+replaced with the empty string or spaces, if keys are being padded in
+the containing group.
@end itemize
Magit defines additional classes, which can serve as examples for the
@@ -1920,7 +2003,7 @@ function is how the value of a transient is determined so that the
invoked suffix command can use it.
Currently most values are strings, but that is not set in stone.
-@code{nil} is not a value, it means “no value”.
+@code{nil} is not a value, it means ``no value''.
Usually only infixes have a value, but see the method for
@code{transient-suffix}.
@@ -1973,12 +2056,13 @@ Show help for the prefix, infix or suffix command represented by
For prefixes, show the info manual, if that is specified using the
@code{info-manual} slot. Otherwise, show the manpage if that is specified
-using the @code{man-page} slot. Otherwise, show the command's doc string.
+using the @code{man-page} slot. Otherwise, show the command's
+documentation string.
-For suffixes, show the command's doc string.
+For suffixes, show the command's documentation string.
For infixes, show the manpage if that is specified. Otherwise show
-the command's doc string.
+the command's documentation string.
@end defun
@node Prefix Slots
@@ -2003,14 +2087,27 @@ remains active/transient when a suffix or arbitrary non-suffix
command is invoked. @xref{Transient State}.
@item
+@code{refresh-suffixes} Normally suffix objects and keymaps are only setup
+once, when the prefix is invoked. Setting this to @code{t}, causes them to
+be recreated after every command. This is useful when using @code{:if...}
+predicates, and those need to be rerun for some reason. Doing this
+is somewhat costly, and there is a risk of losing state, so this is
+disabled by default and still considered experimental.
+
+@item
@code{incompatible} A list of lists. Each sub-list specifies a set of
mutually exclusive arguments. Enabling one of these arguments
causes the others to be disabled. An argument may appear in
-multiple sub-lists.
+multiple sub-lists. Arguments must me given in the same form as
+used in the @code{argument} or @code{argument-format} slot of the respective
+suffix objects, usually something like @code{--switch} or @code{--option=%s}. For
+options and @code{transient-switches} suffixes it is also possible to match
+against a specific value, as returned by @code{transient-infix-value},
+for example, @code{--option=one}.
@item
@code{scope} For some transients it might be necessary to have a sort of
-secondary value, called a “scope”. See @code{transient-define-prefix}.
+secondary value, called a ``scope''. See @code{transient-define-prefix}.
@end itemize
@anchor{Internal Prefix Slots}
@@ -2082,8 +2179,14 @@ It must contain the following %-placeholders:
@end itemize
@item
-@code{description} The description, either a string or a function that is
-called with no argument and returns a string.
+@code{description} The description, either a string or a function, which is
+called with zero or one argument (the suffix object), and returns a
+string.
+
+@item
+@code{face} Face used for the description. In simple cases it is easier
+to use this instead of using a function as @code{description} and adding
+the styling there. @code{face} is appended using @code{add-face-text-property}.
@item
@code{show-help} A function used to display help for the suffix. If
@@ -2172,8 +2275,10 @@ function that takes the object as the only argument and which
returns a prompt string.
@item
-@code{choices} A list of valid values. How exactly that is used depends on
-the class of the object.
+@code{choices} A list of valid values, or a function that returns such a
+list. The latter is not implemented for @code{transient-switches}, because
+I couldn't think of a use-case. How exactly the choices are used
+varies depending on the class of the suffix.
@end itemize
@anchor{Slots of @code{transient-variable}}
@@ -2224,6 +2329,10 @@ what happens if you use more than one.
@code{if-not-derived} Enable if major-mode does not derive from value.
@end itemize
+By default these predicates run when the prefix command is invoked,
+but this can be changes, using the @code{refresh-suffixes} prefix slot.
+See @ref{Prefix Slots}.
+
One more slot is shared between group and suffix classes, @code{level}. Like
the slots documented above, it is a predicate, but it is used for a
different purpose. The value has to be an integer between 1
@@ -2231,336 +2340,9 @@ and 7. @code{level} controls whether a suffix or a group should be
available depending on user preference.
@xref{Enabling and Disabling Suffixes}.
-@node Related Abstractions and Packages
-@chapter Related Abstractions and Packages
-
-@menu
-* Comparison With Prefix Keys and Prefix Arguments::
-* Comparison With Other Packages::
-@end menu
-
-@node Comparison With Prefix Keys and Prefix Arguments
-@section Comparison With Prefix Keys and Prefix Arguments
-
-While transient commands were inspired by regular prefix keys and
-prefix arguments, they are also quite different and much more complex.
-
-The following diagrams illustrate some of the differences.
-
-@itemize
-@item
-@samp{(c)} represents a return to the command loop.
-@item
-@samp{(+)} represents the user's choice to press one key or another.
-@item
-@samp{@{WORD@}} are possible behaviors.
-@item
-@samp{@{NUMBER@}} is a footnote.
-@end itemize
-
-@anchor{Regular Prefix Commands}
-@subheading Regular Prefix Commands
-
-@xref{Prefix Keys,,,elisp,}.
-
-@example
- ,--> command1 --> (c)
- |
-(c)-(+)-> prefix command or key --+--> command2 --> (c)
- |
- `--> command3 --> (c)
-@end example
-
-@anchor{Regular Prefix Arguments}
-@subheading Regular Prefix Arguments
-
-@xref{Prefix Command Arguments,,,elisp,}.
-
-@example
- ,----------------------------------,
- | |
- v |
-(c)-(+)---> prefix argument command --(c)-(+)-> any command --> (c)
- | ^ |
- | | |
- `-- sets or changes --, ,-- maybe used --' |
- | | |
- v | |
- prefix argument state |
- ^ |
- | |
- `-------- discards --------'
-@end example
-
-@anchor{Transients}
-@subheading Transients
-
-(∩`-´)⊃━☆゚.*・。゚
-
-This diagram ignores the infix value and external state:
-
-@example
-(c)
- | ,- @{stay@} ------<-,-<------------<-,-<---,
-(+) | | | |
- | | | | |
- | | ,--> infix1 --| | |
- | | | | | |
- | | |--> infix2 --| | |
- v v | | | |
- prefix -(c)-(+)-> infix3 --' ^ |
- | | |
- |---------------> suffix1 -->--| |
- | | |
- |---------------> suffix2 ----@{1@}------> @{exit@} --> (c)
- | |
- |---------------> suffix3 -------------> @{exit@} --> (c)
- | |
- `--> any command --@{2@}-> @{warn@} -->--|
- | |
- |--> @{noop@} -->--|
- | |
- |--> @{call@} -->--'
- |
- `------------------> @{exit@} --> (c)
-@end example
-
-This diagram takes the infix value into account to an extend, while
-still ignoring external state:
-
-@example
-(c)
- | ,- @{stay@} ------<-,-<------------<-,-<---,
-(+) | | | |
- | | | | |
- | | ,--> infix1 --| | |
- | | | | | | |
- | | ,--> infix2 --| | |
- v v | | | | |
- prefix -(c)-(+)-> infix3 --' | |
- | | ^ |
- | | | |
- |---------------> suffix1 -->--| |
- | | ^ | |
- | | | | |
- |---------------> suffix2 ----@{1@}------> @{exit@} --> (c)
- | | ^ | |
- | | | | v
- | | | | |
- |---------------> suffix3 -------------> @{exit@} --> (c)
- | | ^ | |
- | sets | | v
- | | maybe | |
- | | used | |
- | | | | |
- | | infix --' | |
- | `---> value | |
- | ^ | |
- | | | |
- | hides | |
- | | | |
- | `--------------------------<---|
- | | |
- `--> any command --@{2@}-> @{warn@} -->--| |
- | | |
- |--> @{noop@} -->--| |
- | | |
- |--> @{call@} -->--' ^
- | |
- `------------------> @{exit@} --> (c)
-@end example
-
-This diagram provides more information about the infix value
-and also takes external state into account.
-
-@example
- ,----sets--- "anything"
- |
- v
- ,---------> external
- | state
- | | |
- | initialized | ☉‿⚆
- sets from |
- | | maybe
- | ,----------' used
- | | |
-(c) | | v
- | ,- @{stay@} --|---<-,-<------|-----<-,-<---,
-(+) | | | | | | |
- | | | v | | | |
- | | ,--> infix1 --| | | |
- | | | | | | | | |
- | | | | v | | | |
- | | ,--> infix2 --| | | |
- | | | | ^ | | | |
- v v | | | | | | |
- prefix -(c)-(+)-> infix3 --' | | |
- | | ^ | ^ |
- | | | v | |
- |---------------> suffix1 -->--| |
- | | | ^ | | |
- | | | | v | |
- |---------------> suffix2 ----@{1@}------> @{exit@} --> (c)
- | | | ^ | | |
- | | | | | | v
- | | | | v | |
- |---------------> suffix3 -------------> @{exit@} --> (c)
- | | | ^ | |
- | sets | | | v
- | | initialized maybe | |
- | | from used | |
- | | | | | |
- | | `-- infix ---' | |
- | `---> value -----------------------------> persistent
- | ^ ^ | | across
- | | | | | invocations -,
- | hides | | | |
- | | `----------------------------------------------'
- | | | |
- | `--------------------------<---|
- | | |
- `--> any command --@{2@}-> @{warn@} -->--| |
- | | |
- |--> @{noop@} -->--| |
- | | |
- |--> @{call@} -->--' ^
- | |
- `------------------> @{exit@} --> (c)
-@end example
-
-@itemize
-@item
-@samp{@{1@}} Transients can be configured to be exited when a suffix command
-is invoked. The default is to do so for all suffixes except for
-those that are common to all transients and which are used to
-perform tasks such as providing help and saving the value of the
-infix arguments for future invocations. The behavior can also be
-specified for individual suffix commands and may even depend on
-state.
-
-@item
-@samp{@{2@}} Transients can be configured to allow the user to invoke
-non-suffix commands. The default is to not allow that and instead
-warn the user.
-@end itemize
-
-Despite already being rather complex, even the last diagram leaves out
-many details. Most importantly it implies that the decision whether
-to remain transient is made later than it actually is made (for the
-most part a function on @code{pre-command-hook} is responsible). But such
-implementation details are of little relevance to users and are
-covered elsewhere.
-
-@node Comparison With Other Packages
-@section Comparison With Other Packages
-
-@anchor{Magit-Popup}
-@subheading Magit-Popup
-
-Transient is the successor to Magit-Popup (@pxref{Top,,,magit-popup,}).
-
-One major difference between these two implementations of the same
-ideas is that while Transient uses transient keymaps and embraces the
-command-loop, Magit-Popup implemented an inferior mechanism that does
-not use transient keymaps and that instead of using the command-loop
-implements a naive alternative based on @code{read-char}.
-
-Magit-Popup does not use classes and generic functions and defining a
-new command type is near impossible as it involves adding hard-coded
-special-cases to many functions. Because of that only a single new
-type was added, which was not already part of Magit-Popup's initial
-release.
-
-A lot of things are hard-coded in Magit-Popup. One random example is
-that the key bindings for switches must begin with @code{-} and those for
-options must begin with @code{=}.
-
-@anchor{Hydra}
-@subheading Hydra
-
-Hydra (see @uref{https://github.com/abo-abo/hydra}) is another package that
-provides features similar to those of Transient.
-
-Both packages use transient keymaps to make a set of commands
-temporarily available and show the available commands in a popup
-buffer.
-
-A Hydra “body” is equivalent to a Transient “prefix” and a Hydra
-“head” is equivalent to a Transient “suffix”. Hydra has no equivalent
-of a Transient “infix”.
-
-Both hydras and transients can be used as simple command dispatchers.
-Used like this they are similar to regular prefix commands and prefix
-keys, except that the available commands are shown in the popup buffer.
-
-(Another package that does this is @code{which-key}. It does so automatically
-for any incomplete key sequence. The advantage of that approach is
-that no additional work is necessary; the disadvantage is that the
-available commands are not organized semantically.)
-
-Both Hydra and Transient provide features that go beyond simple
-command dispatchers:
-
-@itemize
-@item
-Invoking a command from a hydra does not necessarily exit the hydra.
-That makes it possible to invoke the same command again, but using a
-shorter key sequence (i.e., the key that was used to enter the hydra
-does not have to be pressed again).
-
-Transient supports that too, but for now this feature is not a focus
-and the interface is a bit more complicated. A very basic example
-using the current interface:
-
-@lisp
-(transient-define-prefix outline-navigate ()
- :transient-suffix 'transient--do-stay
- :transient-non-suffix 'transient--do-warn
- [("p" "previous visible heading" outline-previous-visible-heading)
- ("n" "next visible heading" outline-next-visible-heading)])
-@end lisp
-
-@item
-Transient supports infix arguments; values that are set by infix
-commands and then consumed by the invoked suffix command(s).
-
-To my knowledge, Hydra does not support that.
-@end itemize
-
-Both packages make it possible to specify how exactly the available
-commands are outlined:
-
-@itemize
-@item
-With Hydra this is often done using an explicit format string, which
-gives authors a lot of flexibility and makes it possible to do fancy
-things.
-
-The downside of this is that it becomes harder for a user to add
-additional commands to an existing hydra and to change key bindings.
-
-@item
-Transient allows the author of a transient to organize the commands
-into groups and the use of generic functions allows authors of
-transients to control exactly how a certain command type is
-displayed.
-
-However while Transient supports giving sections a heading it does
-not currently support giving the displayed information more
-structure by, for example, using box-drawing characters.
-
-That could be implemented by defining a new group class, which lets
-the author specify a format string. It should be possible to
-implement that without modifying any existing code, but it does not
-currently exist.
-@end itemize
-
@node FAQ
@appendix FAQ
-
-
@anchor{Can I control how the popup buffer is displayed?}
@appendixsec Can I control how the popup buffer is displayed?
@@ -2569,10 +2351,10 @@ Yes, see @code{transient-display-buffer-action} in @ref{Configuration}.
@anchor{How can I copy text from the popup buffer?}
@appendixsec How can I copy text from the popup buffer?
-To be able to mark text in any transient popup buffer using the mouse,
-you have to add the following binding. Note that the region won't be
-visualized, while doing so. After you have quit the transient popup,
-you will be able to yank it another buffer.
+To be able to mark text in Transient's popup buffer using the mouse,
+you have to add the below binding. Note that for technical reasons,
+the region won't be visualized, while doing so. After you have quit
+the transient popup, you will be able to yank it in another buffer.
@lisp
(keymap-set transient-predicate-map
@@ -2580,6 +2362,16 @@ you will be able to yank it another buffer.
#'transient--do-stay)
@end lisp
+@anchor{How does Transient compare to prefix keys and universal arguments?}
+@appendixsec How does Transient compare to prefix keys and universal arguments?
+
+See @uref{https://github.com/magit/transient/wiki/Comparison-with-prefix-keys-and-universal-arguments}.
+
+@anchor{How does Transient compare to Magit-Popup and Hydra?}
+@appendixsec How does Transient compare to Magit-Popup and Hydra?
+
+See @uref{https://github.com/magit/transient/wiki/Comparison-with-other-packages}.
+
@anchor{Why did some of the key bindings change?}
@appendixsec Why did some of the key bindings change?
@@ -2599,14 +2391,14 @@ bindings. The bindings that do use a prefix do so to avoid wasting
too many non-prefix bindings, keeping them available for use in
individual transients. The bindings that do not use a prefix and that
are @strong{not} grayed out are very important bindings that are @strong{always}
-available, even when invoking the “common command key prefix” or @strong{any
+available, even when invoking the ``common command key prefix'' or @strong{any
other} transient-specific prefix. The non-prefix keys that @strong{are} grayed
out however, are not available when any incomplete prefix key sequence
-is active. They do not use the “common command key prefix” because it
+is active. They do not use the ``common command key prefix'' because it
is likely that users want to invoke them several times in a row and
e.g., @kbd{M-p M-p M-p} is much more convenient than @kbd{C-x M-p C-x M-p C-x M-p}.
-You may also have noticed that the “Set” command is bound to @kbd{C-x s},
+You may also have noticed that the ``Set'' command is bound to @kbd{C-x s},
while Magit-Popup used to bind @kbd{C-c C-c} instead. I have seen several
users praise the latter binding (sic), so I did not change it
willy-nilly. The reason that I changed it is that using different
@@ -2642,7 +2434,7 @@ for @kbd{q}.
If you want to get @kbd{q}'s old binding back then you can do so. Doing
that is a bit more complicated than changing a single key binding, so
I have implemented a function, @code{transient-bind-q-to-quit} that makes the
-necessary changes. See its doc string for more information.
+necessary changes. See its documentation string for more information.
@node Keystroke Index
@appendix Keystroke Index
diff --git a/doc/misc/url.texi b/doc/misc/url.texi
index b5a6cb0e6a1..db717633faf 100644
--- a/doc/misc/url.texi
+++ b/doc/misc/url.texi
@@ -21,7 +21,7 @@
@copying
This is the manual for the @code{url} Emacs Lisp library.
-Copyright @copyright{} 1993--1999, 2002, 2004--2023 Free Software
+Copyright @copyright{} 1993--1999, 2002, 2004--2024 Free Software
Foundation, Inc.
@quotation
@@ -1083,16 +1083,18 @@ This is a regular expression that matches the shell prompt.
@defopt socks-server
This specifies the default server, it takes the form
@w{@code{("Default server" @var{server} @var{port} @var{version})}}
-where @var{version} can be either 4 or 5.
+where @var{version} can be 4, 4a, or 5.
@end defopt
@defvar socks-password
If this is @code{nil} then you will be asked for the password,
otherwise it will be used as the password for authenticating you to
-the @sc{socks} server.
+the @sc{socks} server. You can often set this to @code{""} for
+servers on your local network.
@end defvar
@defvar socks-username
This is the username to use when authenticating yourself to the
-@sc{socks} server. By default this is your login name.
+@sc{socks} server. By default, this is your login name. In versions
+4 and 4a, ERC uses this for the @samp{ID} field.
@end defvar
@defvar socks-timeout
This controls how long, in seconds, to wait for responses from the
@@ -1149,40 +1151,6 @@ If this variable is non-@code{nil} new network connections are never
opened by the URL library.
@end defvar
-@c @node Broken hostname resolution
-@c @subsection Broken Hostname Resolution
-
-@c @cindex hostname resolver
-@c @cindex resolver, hostname
-@c Some C libraries do not include the hostname resolver routines in
-@c their static libraries. If Emacs was linked statically, and was not
-@c linked with the resolver libraries, it will not be able to get to any
-@c machines off the local network. This is characterized by being able
-@c to reach someplace with a raw ip number, but not its hostname
-@c (@url{https://129.79.254.191/} works, but
-@c @url{https://www.cs.indiana.edu/} doesn't). This used to happen on
-@c SunOS4 and Ultrix, but is now probably now rare. If Emacs can't be
-@c rebuilt linked against the resolver library, it can use the external
-@c @command{nslookup} program instead.
-
-@c @defopt url-gateway-broken-resolution
-@c @cindex @code{nslookup} program
-@c @cindex program, @code{nslookup}
-@c If non-@code{nil}, this variable says to use the program specified by
-@c @code{url-gateway-nslookup-program} program to do hostname resolution.
-@c @end defopt
-
-@c @defopt url-gateway-nslookup-program
-@c The name of the program to do hostname lookup if Emacs can't do it
-@c directly. This program should expect a single argument on the command
-@c line---the hostname to resolve---and should produce output similar to
-@c the standard Unix @command{nslookup} program:
-@c @example
-@c Name: www.cs.indiana.edu
-@c Address: 129.79.254.191
-@c @end example
-@c @end defopt
-
@node History
@section History
@@ -1263,8 +1231,6 @@ the @file{*URL-DEBUG*} buffer.
A number means log all messages and show them with @code{message}.
It may also be a list of the types of messages to be logged.
@end defopt
-@defopt url-personal-mail-address
-@end defopt
@defopt url-privacy-level
@end defopt
@defopt url-lastloc-privacy-level
diff --git a/doc/misc/use-package.texi b/doc/misc/use-package.texi
index 55e56f7ce4e..d834e1be754 100644
--- a/doc/misc/use-package.texi
+++ b/doc/misc/use-package.texi
@@ -13,7 +13,7 @@
@copying
This manual is for use-package @value{USEP_VER} @value{USEP_DIST}.
-Copyright @copyright{} 2022--2023 Free Software Foundation, Inc.
+Copyright @copyright{} 2022--2024 Free Software Foundation, Inc.
@quotation
Permission is granted to copy, distribute and/or modify this document
@@ -451,7 +451,7 @@ docstring of @code{system-type} for other valid values.
@item
Window system
-The example below loads a package only on macOS and X. See the
+The example below loads a package only on macOS and X@. See the
docstring of @code{window-system} for valid values.
@lisp
@@ -940,7 +940,7 @@ Examples:
Remapping of commands with @code{:bind} and @code{bind-key} works as
expected, because when the binding is a vector, it is passed straight
to @code{define-key}. @xref{Remapping Commands,,, elisp, GNU Emacs
-Lisp Reference Manual}), for more information about command remapping.
+Lisp Reference Manual}, for more information about command remapping.
For example, the following declaration will rebind
@code{fill-paragraph} (bound to @kbd{M-q} by default) to
@code{unfill-toggle}:
diff --git a/doc/misc/vhdl-mode.texi b/doc/misc/vhdl-mode.texi
index a5ad92ca01e..86df723aa5a 100644
--- a/doc/misc/vhdl-mode.texi
+++ b/doc/misc/vhdl-mode.texi
@@ -10,7 +10,7 @@
@copying
This file documents VHDL Mode, an Emacs mode for editing VHDL code.
-Copyright @copyright{} 1995--2008, 2010, 2012, 2015--2023 Free Software
+Copyright @copyright{} 1995--2008, 2010, 2012, 2015--2024 Free Software
Foundation, Inc.
@quotation
diff --git a/doc/misc/vip.texi b/doc/misc/vip.texi
index f5a6dfe9f8c..0248edb328f 100644
--- a/doc/misc/vip.texi
+++ b/doc/misc/vip.texi
@@ -4,7 +4,7 @@
@include docstyle.texi
@copying
-Copyright @copyright{} 1987, 2001--2023 Free Software Foundation, Inc.
+Copyright @copyright{} 1987, 2001--2024 Free Software Foundation, Inc.
@quotation
Permission is granted to copy, distribute and/or modify this document
diff --git a/doc/misc/viper.texi b/doc/misc/viper.texi
index 3e038520287..01e94de4e48 100644
--- a/doc/misc/viper.texi
+++ b/doc/misc/viper.texi
@@ -8,8 +8,7 @@
@include docstyle.texi
@copying
-Copyright @copyright{} 1995--1997, 2001--2023 Free Software Foundation,
-Inc.
+Copyright @copyright{} 1995--2024 Free Software Foundation, Inc.
@quotation
Permission is granted to copy, distribute and/or modify this document
@@ -1700,7 +1699,7 @@ a text-formatting function, @code{indent-for-tab-command} (which facilitates
programming and document writing). Instead, the tab is inserted via the
command @code{viper-insert-tab}, which is bound to @kbd{S-tab} (shift + tab).
-On some non-windowing terminals, Shift doesn't modify the @key{TAB} key, so
+On some text terminals, Shift doesn't modify the @key{TAB} key, so
@kbd{S-tab} behaves as if it were @key{TAB}. In such a case, you will have
to bind @code{viper-insert-tab} to some other convenient key.
@@ -2232,7 +2231,7 @@ For this reason, Viper doesn't change the standard Emacs binding of
(except for users at level 1). Instead, in Viper, the key
@kbd{S-tab} (shift+ tab) is chosen to emulate Vi's @key{TAB}.
-We should note that on some non-windowing terminals, Shift doesn't modify
+We should note that on some text terminals, Shift doesn't modify
the @key{TAB} key, so @kbd{S-tab} behaves as if it were @key{TAB}. In such
a case, you will have to bind @code{viper-insert-tab} to some other
convenient key.
diff --git a/doc/misc/vtable.texi b/doc/misc/vtable.texi
index de652eb227f..a4f2ed29d93 100644
--- a/doc/misc/vtable.texi
+++ b/doc/misc/vtable.texi
@@ -12,7 +12,7 @@
@copying
This file documents the GNU vtable.el package.
-Copyright @copyright{} 2022--2023 Free Software Foundation, Inc.
+Copyright @copyright{} 2022--2024 Free Software Foundation, Inc.
@quotation
Permission is granted to copy, distribute and/or modify this document
diff --git a/doc/misc/widget.texi b/doc/misc/widget.texi
index 13b37ab5b54..93b7606b01e 100644
--- a/doc/misc/widget.texi
+++ b/doc/misc/widget.texi
@@ -9,7 +9,7 @@
@c %**end of header
@copying
-Copyright @copyright{} 2000--2023 Free Software Foundation, Inc.
+Copyright @copyright{} 2000--2024 Free Software Foundation, Inc.
@quotation
Permission is granted to copy, distribute and/or modify this document
@@ -49,14 +49,16 @@ modify this GNU manual.''
* Introduction::
* User Interface::
* Programming Example::
+* Widgets Basics::
* Setting Up the Buffer::
-* Basic Types::
-* Sexp Types::
-* Widget Properties::
+* Working with Widgets::
+* Widgets and the Buffer::
+* Widget Gallery::
* Defining New Widgets::
-* Widget Browser::
+* Inspecting Widgets::
* Widget Minor Mode::
* Utilities::
+* Customization::
* Widget Wishlist::
* GNU Free Documentation License::
* Index::
@@ -68,7 +70,7 @@ modify this GNU manual.''
Most graphical user interface toolkits provide a number of standard
user interface controls (sometimes known as ``widgets'' or ``gadgets'').
Emacs doesn't really support anything like this, except for an
-incredibly powerful text ``widget.'' On the other hand, Emacs does
+incredibly powerful text ``widget''. On the other hand, Emacs does
provide the necessary primitives to implement many other widgets
within a text buffer. The @code{widget} package simplifies this task.
@@ -85,13 +87,13 @@ Like link, but intended for stand-alone buttons.
@item editable-field
An editable text field. It can be either variable or fixed length.
@item menu-choice
-Allows the user to choose one of multiple options from a menu, each
-option is itself a widget. Only the selected option will be visible in
-the buffer.
+Allows the user to choose one of multiple options from a menu, where
+each option is itself a widget. Only the selected option is visible
+in the buffer.
@item radio-button-choice
Allows the user to choose one of multiple options by activating radio
-buttons. The options are implemented as widgets. All options will be
-visible in the buffer.
+buttons. The options are implemented as widgets. All options are
+visible in the buffer, with the selected one marked as chosen.
@item item
A simple constant widget intended to be used in the @code{menu-choice} and
@code{radio-button-choice} widgets.
@@ -137,9 +139,9 @@ Editing happens in the buffer, not in the mini-buffer.
Packages using the library get a uniform look, making them easier for
the user to learn.
@item
-As support for embedded graphics improve, the widget library will be
+As support for embedded graphics improve, the Widget library will be
extended to use the GUI features. This means that your code using the
-widget library will also use the new graphic features automatically.
+Widget library will also use the new graphic features automatically.
@end enumerate
@node User Interface
@@ -201,12 +203,6 @@ middle of another field is prohibited.
Editable text fields are created by the @code{editable-field} widget.
-@strong{Warning:} In an @code{editable-field} widget, the editable
-field must not be adjacent to another widget---that won't work.
-You must put some text in between. Either make this text part of
-the @code{editable-field} widget itself, or insert it with
-@code{widget-insert}.
-
The @code{:format} keyword is useful for generating the necessary
text; for instance, if you give it a value of @code{"Name: %v "},
the @samp{Name: } part will provide the necessary separating text
@@ -215,17 +211,9 @@ separating text after the field. If you don't include the
@code{:size} keyword, the field will extend to the end of the
line, and the terminating newline will provide separation after.
-@strong{Warning:} In an @code{editable-field} widget, the @samp{%v} escape
-must be preceded by some other text in the @code{:format} string
-(if specified).
-
The editing text fields are highlighted with the
@code{widget-field-face} face, making them easy to find.
-@deffn Face widget-field-face
-Face used for other editing fields.
-@end deffn
-
@section Buttons
@cindex widget buttons
@@ -233,24 +221,9 @@ Face used for other editing fields.
Some portions of the buffer have an associated @dfn{action}, which can
be @dfn{invoked} by a standard key or mouse command. These portions
are called @dfn{buttons}. The default commands for activating a button
-are:
-
-@table @kbd
-@item @key{RET}
-@deffn Command widget-button-press @var{pos} &optional @var{event}
-Invoke the button at @var{pos}, defaulting to point.
-If point is not located on a button, invoke the binding in
-@code{widget-global-map} (by default the global map).
-@end deffn
-
-@kindex mouse-2 @r{(on button widgets})
-@item mouse-2
-@deffn Command widget-button-click @var{event}
-Invoke the button at the location of the mouse pointer. If the mouse
-pointer is located in an editable text field, invoke the binding in
-@code{widget-global-map} (by default the global map).
-@end deffn
-@end table
+are @code{widget-button-press} and @code{widget-button-click}. The
+user typically interacts with the buttons with a key, like @key{RET},
+or with the mouse buttons.
There are several different kind of buttons, all of which are present in
the example:
@@ -286,33 +259,15 @@ main difference from the @code{link} widget is that the buttons will be
displayed as GUI buttons when possible.
@end table
-To make them easier to locate, buttons are emphasized in the buffer.
-
-@deffn Face widget-button-face
-Face used for buttons.
-@end deffn
-
-@defopt widget-mouse-face
-Face used for highlighting a button when the mouse pointer moves across
-it.
-@end defopt
+To make them easier to locate, buttons are emphasized in the buffer
+with a distinctive face, like @code{widget-button-face} or
+@code{widget-mouse-face}.
@section Navigation
You can use all the normal Emacs commands to move around in a form
-buffer, plus you will have these additional commands:
-
-@table @kbd
-@item @key{TAB}
-@deffn Command widget-forward &optional count
-Move point @var{count} buttons or editing fields forward.
-@end deffn
-@item @kbd{M-@key{TAB}}
-@itemx @kbd{S-@key{TAB}}
-@deffn Command widget-backward &optional count
-Move point @var{count} buttons or editing fields backward.
-@end deffn
-@end table
+buffer, plus you will have these additional commands to navigate from
+widget to widget: @code{widget-forward} and @code{widget-backward}.
@node Programming Example
@chapter Programming Example
@@ -414,85 +369,598 @@ Interface}).
(widget-setup))
@end lisp
+@node Widgets Basics
+@chapter Widgets Basics
+@cindex widget object
+The Widget Library deals with widgets objects. A widget object has
+properties whose value may be anything, be it numbers, strings,
+symbols, functions, etc. Those properties are referred to as keywords
+and are responsible for the way a widget is represented in a buffer,
+and control the way a user or a program can interact with it.
+
+@cindex widget inheritance
+The library defines several widget types, and gives you a way to
+define new types as well. In addition, widgets can derive from other
+types, creating a sort of widget inheritance. In fact, all widgets
+defined in the Widget Library share a common parent, the @dfn{default}
+widget. In this manual, when we talk about a default behavior, we
+usually mean the behavior as defined by this @code{default} widget.
+@xref{Widget Gallery}, for a description of each defined widget.
+
+Defining a new type that derives from a previous one is not mandatory
+to create widgets that work very different from a specified type.
+When creating a widget, you can override any default property,
+including functions, that control the widget. That is, you can
+specialize a widget on creation, without having to define it as a new
+type of widget.
+
+In addition to the function for defining a widget, this library
+provides functions to create widgets, query and change its properties,
+respond to user events and destroy them. The following sections
+describe them.
+
+@cindex widget value
+One important property of a widget is its @dfn{value}. All widgets
+may have a value, which is stored in a so-called @dfn{internal format}.
+For the rest of Emacs, the widget presents its value in a so-called
+@dfn{external format}. Both formats can be equal or different, and
+each widget is responsible for defining how the conversion between
+each format should happen.
+
+@c FIXME: Briefly describe inline widgets?
+@c The inline concept is described elsewhere, and it's difficult to
+@c describe.
+
+The value property is an important property for almost all widgets,
+and perhaps more important for @code{editable-field} widgets. This
+type of widgets allow the user to edit them via the usual editing
+commands in Emacs. They can also be edited programmatically.
+@strong{Important:} You @emph{must} call @code{widget-setup} after
+modifying the value of a widget before the user is allowed to edit the
+widget again. It is enough to call @code{widget-setup} once if you
+modify multiple widgets. This is currently only necessary if the widget
+contains an editing field, but may be necessary for other widgets in the
+future.
+
+@cindex widget properties
+If your application needs to associate some information with the widget
+objects, for example a reference to the item being edited, it can be
+done with the @code{widget-put} and @code{widget-get} functions. The
+property names, as shown, are keywords, so they must begin with a
+@samp{:}.
+
@node Setting Up the Buffer
@chapter Setting Up the Buffer
+@cindex widget creation, widget conversion
+To show the widgets in a buffer, you have to create them. Widget
+creation is actually a two-step process: conversion and creation per
+se. With simple projects, usually the conversion step isn't really
+important, and you only care about widget creation, so feel free to
+skip the conversion description until you really need to know it.
+
+Widget conversion is the process that involves taking a widget
+specification and transforming it into a @dfn{widget} object, suitable
+to be created, queried and manipulated with other widget functions.
+Widget creation is the process that takes a widget object and actually
+inserts it in the buffer.
+
+The simplest function to create a widget is @code{widget-create}, which
+gets a widget specification and returns a widget object.
+
+@defun widget-create type [ keyword argument ]@dots{} args
+Create and return a widget of type @var{type}, converting it.
+
+@var{type} is a symbol that specifies a widget type. @var{keyword}
+may be one of the properties supported by the widget type, and
+@var{argument} specify the value for that property. These keyword
+arguments can be used to overwrite the keyword arguments that are part
+of @var{type} by default, as well as to provide other properties not
+present in @var{type} by default. @var{args} holds additional
+information for the creation of @var{type} and each widget type is
+responsible for handling that information in a specific way.
+
+The syntax for the @var{type} argument is described in @ref{Widget
+Gallery}, and in more detail in every widget where it's relevant.
+@end defun
-Widgets are created with @code{widget-create}, which returns a
-@dfn{widget} object. This object can be queried and manipulated by
-other widget functions, until it is deleted with @code{widget-delete}.
-After the widgets have been created, @code{widget-setup} must be called
-to enable them.
+There are other functions for creating widgets, useful when you work
+with composite widgets. That is, widgets that are part of other
+widgets.
-@defun widget-create type [ keyword argument ]@dots{}
-Create and return a widget of type @var{type}.
-The syntax for the @var{type} argument is described in @ref{Basic Types}.
+@defun widget-create-child-and-convert parent type &rest args
+Create a widget of type @var{type} as a child of @var{parent}.
-The keyword arguments can be used to overwrite the keyword arguments
-that are part of @var{type}.
+Before creating it, converts @var{type} using the keyword arguments
+provided in @var{args}.
+@c FIXME: Is this description useful?
+Adds the @code{:indent} property, unless it is already present, and
+sets it to the sum of the values of: @code{:indent} and @code{:offset}
+from @var{parent} and @code{:extra-offset} from @var{type}.
+
+Returns a widget object, with the property @code{:parent} set to
+@var{PARENT}.
@end defun
-@defun widget-delete widget
-Delete @var{widget} and remove it from the buffer.
+@defun widget-create-child parent type
+Create a widget of type @var{type} as a child of @var{parent}.
+
+This function is like @code{widget-create-child-and-convert} but it
+doesn't convert @var{type}, so it expects an already converted widget.
+@end defun
+
+@defun widget-create-child-value parent type value
+Create a widget of type @var{type} as a child of @var{parent} with
+value @var{value}.
+
+This function is like @code{widget-create-child}, but it lets you
+specify a value for the widget.
+
+Converts @var{value} to the internal format, as specified by
+@var{type}, and stores it into the @code{:value} property of @var{type}.
+That means, @var{value} should be in the external format, as
+specified by @var{type}.
@end defun
+All these creating functions described here use the function stored in
+the @code{:create} property. So, to modify the creation logic for a
+widget, you can provide a different @code{:create} function.
+
+When you're done creating widgets and you're ready for the user to
+interact with the buffer, use the function @code{widget-setup}.
+
@defun widget-setup
-Set up a buffer to support widgets.
+Setup the current buffer, so that editable widgets can be edited.
This should be called after creating all the widgets and before allowing
the user to edit them.
@end defun
-If you want to insert text outside the widgets in the form, the
-recommended way to do that is with @code{widget-insert}.
+As mentioned, all these functions return a widget object. That widget
+object can be queried and manipulated with widget functions that
+take widgets as arguments, until deleting it with the widgets
+functions available to delete widgets. Even if you don't save the
+returned widget object, you still can interact programmatically with
+the widget. @xref{Working with Widgets}.
-@defun widget-insert
-Insert the arguments, either strings or characters, at point.
-The inserted text will be read-only.
+@defun widget-delete widget
+Delete the widget @var{widget} and remove it from the buffer.
@end defun
-There is a standard widget keymap which you might find useful.
+@defun widget-children-value-delete widget
+Delete all children and buttons in widget @var{widget}.
-@findex widget-button-press
-@findex widget-button-click
+This function does not delete @var{widget} itself, only the widgets
+stored in the @code{:children} and @code{:buttons} properties. It
+also sets those properties to @code{nil}.
+@end defun
+
+As with the creation mechanism, the function stored in @code{:delete}
+controls the deletion mechanism for a widget.
+
+Additionally, the library provides a way to make a copy of a widget.
+
+@defun widget-copy widget
+Makes a copy of widget @var{widget} and returns it.
+
+It uses the function stored in the @code{:copy} property of @var{widget}
+and returns the widget that that function returns.
+@end defun
+
+As discussed, there is a conversion step when creating a widget. To
+do the conversion without actually creating the widget, you can use
+the @code{widget-convert} function.
+
+@defun widget-convert type &rest args
+Convert @var{type} to a widget object, using keyword arguments @var{args}.
+
+Returns a widget object, suitable for creation. It calls the function
+stored in the @code{:convert-widget} property, after putting into the
+@code{:args} property the arguments that the widget in question needs.
+If @var{type} has a @code{:value} property, either originally or after
+doing the conversion, this function converts the value stored in
+@code{:value} to the internal format, and stores it into @code{:value}.
+@end defun
+
+Apart from only creating widgets in the buffer, It's useful to have
+plain text. For inserting text, the recommended way is with the
+@code{widget-insert} function.
+
+@defun widget-insert &rest args
+Insert @var{args}, either strings or characters, at point.
+
+Uses @code{insert} to perform the insertion, passing @var{args} as
+argument. @xref{Insertion,,,elisp, the Emacs Lisp Reference Manual},
+for more information about @var{args}.
+
+The resulting text will be read-only.
+@end defun
+
+@node Working with Widgets
+@chapter Working with Widgets
+This section covers the more important functions needed to query and
+manipulate widgets in a generic way. Widgets may have additional
+functions for interacting with them, those are described in the
+description for each widget. @xref{Widget Gallery}.
+
+@defun widgetp widget
+Non-@code{nil} if @var{widget} is a widget.
+@end defun
+
+@defun widget-type widget
+Return the type of widget @var{widget}, a symbol.
+
+This function is useful to find out which kind of widget @var{widget}
+represents, i.e., the name of the widget type when the widget
+was created.
+@end defun
+
+@defun widget-member widget property
+Non-@code{nil} if widget @var{widget} has a value (even @code{nil}) for
+property @var{property}.
+@end defun
+
+@defun widget-get widget property
+For widget @var{widget}, return the value of the property @var{property}.
+
+@var{property} should be a keyword, and the value is what was last set by
+@code{widget-put} for @var{property}.
+@end defun
+
+@defun widget-put widget property value
+For widget @var{widget}, set the property @var{property} to @var{value}.
+@var{property} should be a keyword, while @var{value} can be anything.
+@end defun
+
+@defun widget-at &optional pos
+Return the widget at position @var{pos}, or at point if @var{pos} is @code{nil}.
+@end defun
+
+@defun widget-field-at pos
+Return the widget field at position POS, or @code{nil} if there is none.
+@end defun
+
+@defun widget-apply widget property &rest args
+Apply the function stored in @var{property} to @var{widget}, passing @var{args}
+as additional arguments to the function.
+
+Returns the result of that function call.
+@end defun
+
+@defun widget-value widget
+Return the current value contained in @var{widget}.
+
+Note that the value returned by this function might differ from what's
+stored in the @code{:value} property of @var{widget}. This is because
+this function extracts the current value of @var{widget} from the
+buffer, taking editions into account.
+
+The value returned is in the external format, after getting it with
+the @code{:value-get} function.
+
+It is an error to call this function on an uninitialized widget.
+@end defun
+
+@defun widget-value-set widget value
+Set the value contained in @var{widget} to @var{value}.
+
+Converts @var{value} to the internal format, and then sets it by
+applying the @code{:value-set} function.
+
+It is an error to call this function with an invalid @var{value}, that
+is, a value that @var{widget} cannot represent.
+@end defun
+
+@defun widget-default-get widget
+Return the default external value of widget @var{widget}.
+
+The default value is the one stored in @code{:value} or the result of
+applying the @code{:default-get} function to the arguments of
+@var{widget}, as stored in @code{:args}. A value of @code{nil} is
+ignored by default, so in order for a widget to respect @code{nil} as
+a value, it has to override the @code{:default-get} function.
+@end defun
+
+@defun widget-type-default-get widget
+Convert the @code{:type} attribute in @var{widget} and return its
+default value.
+@end defun
+
+@defun widget-child-value-get widget
+Return the value of the first member of @code{:children} in
+@var{widget}.
+@end defun
+
+@defun widget-child-value-inline widget
+Return the inline value of the first member of @code{:children} in
+@var{widget}.
+
+The inline value is whatever the function stored in
+@code{:value-inline} returns.
+@end defun
+
+@defun widget-type-value-create widget
+Create a child widget for @var{widget}, of type stored in
+@code{:type}.
+
+Creates the child widget taking the value from the @code{:value}
+property and stores the newly created widget in the @code{:children}
+property of @var{widget}.
+
+The value stored in @code{:type} should be an unconverted widget
+type.
+@end defun
+
+@defun widget-value-convert-widget widget
+Initializes the @code{:value} property of @var{widget} from
+@code{:args}.
+
+Sets @code{:args} to @code{nil} and returns the modified widget
+@var{widget}.
+@end defun
+
+@defun widget-value-value-get widget
+Return the value stored in @code{:value} for widget @var{widget}.
+
+This is different to getting the current value for @var{widget} with
+@code{widget-value}, since that function extracts the value from the
+buffer.
+@end defun
+
+@defun widget-apply-action widget &optional event
+Apply the function stored in @code{:action} to @var{widget}, in
+response to @var{event}.
+
+It is an error to call this function with an inactive widget.
+@end defun
+
+@defun widget-parent-action widget &optional event
+Tell @code{:parent} of @var{widget} to handle @var{event}.
+
+Optional @var{event} is the event that triggered the action.
+@end defun
+
+@defun widget-child-validate widget
+Check that the first member of @code{:children} in @var{widget} is valid.
+
+To be valid means that the widget value passes the checks that the
+function stored in @code{:validate} makes.
+@end defun
+
+@defun widget-children-validate widget
+Check that all @code{:children} in @var{widget} are valid.
+
+Returns @code{nil} on success, or the first child that isn't valid.
+@end defun
+
+@defun widget-type-match widget value
+Return non-@code{nil} if @var{VALUE} matches the value for the
+@code{:type} widget.
+
+As with the other type functions, the widget stored in @code{:type}
+should be an unconverted widget.
+@end defun
+
+@defun widget-types-copy widget
+Copy the @code{:args} value in @var{widget} and store them in @code{:args}.
+
+Makes the copies by calling @code{widget-copy} on each element present
+in @code{:args}. Returns the modified widget @var{widget}.
+@end defun
+
+@defun widget-types-convert-widget widget
+Convert the @code{:args} value in @var{widget} and store them in
+@code{args}.
+
+Returns the modified widget @var{widget}.
+@end defun
+
+@node Widgets and the Buffer
+@chapter Widgets and the Buffer
+This chapter describes commands that are specific to buffers that
+contain widgets.
+
+@cindex widget keybindings
@defvr Const widget-keymap
-@key{TAB} and @kbd{C-@key{TAB}} are bound to @code{widget-forward} and
-@code{widget-backward}, respectively. @key{RET} and @kbd{mouse-2}
-are bound to @code{widget-button-press} and
-@code{widget-button-click}.
+Keymap containing useful bindings for buffers containing widgets.
+
+Binds @key{TAB} and @kbd{C-@key{TAB}} to @code{widget-forward} and
+@code{widget-backward}, respectively. It also binds @key{RET} to
+@code{widget-button-press} and @kbd{down-mouse-1} and
+@kbd{down-mouse-2} to @code{widget-button-click}.
@end defvr
+There's also a keymap for events that the Widget library doesn't need
+to handle.
+
@defvar widget-global-map
Keymap used by @code{widget-button-press} and @code{widget-button-click}
when not on a button. By default this is @code{global-map}.
@end defvar
-@node Basic Types
-@chapter Basic Types
+In addition to these two keymaps, each widget might define a keymap of
+its own, active when events happen at that widget.
+
+@cindex widget navigation
+The following navigation commands are available:
+
+@table @kbd
+@item @key{TAB}
+@deffn Command widget-forward &optional count
+Move point @var{count} buttons or editing fields forward.
+@end deffn
+@item @kbd{M-@key{TAB}}
+@itemx @kbd{S-@key{TAB}}
+@deffn Command widget-backward &optional count
+Move point @var{count} buttons or editing fields backward.
+@end deffn
+@end table
+
+
+When editing an @code{editable-field} widget, the following commands
+are available:
-This is the general syntax of a type specification:
+@table @kbd
+@item @key{C-e}
+@deffn Command widget-end-of-line
+Move point to the end of field or end of line, whichever is first.
+@end deffn
+
+@item @kbd{C-k}
+@deffn Command widget-kill-line
+Kill to end of field or end of line, whichever is first.
+@end deffn
+
+@item @kbd{M-TAB}
+@deffn Command widget-complete
+Complete the content of the editable field at point.
+@end deffn
+
+@item @kbd{C-m}
+@deffn Command widget-field-activate
+Invoke the editable field at point.
+@end deffn
+@end table
+The following two are commands that can execute widget actions.
+@table @kbd
+@item @key{RET}
+@findex widget-button-press
+@deffn Command widget-button-press @var{pos} &optional @var{event}
+Invoke the button at @var{pos}, defaulting to point.
+
+Invocation means to run the function stored in the @code{:action}
+property.
+
+If point is not located on a button, invoke the binding in
+@code{widget-global-map} (by default the global map).
+@end deffn
+
+@kindex mouse-2 @r{(on button widgets})
+@item mouse-2
+@findex widget-button-click
+@deffn Command widget-button-click @var{event}
+Invoke the button at the location of the mouse pointer.
+
+If the mouse pointer is located in an editable text field, invoke the
+binding in @code{widget-global-map} (by default the global map).
+
+In case the mouse-click is on a widget, calls the function stored in
+the @code{:mouse-down-action} property.
+@end deffn
+@end table
+
+@node Widget Gallery
+@chapter Widget Gallery
+@cindex widget syntax
+All widgets can be created from a type specification. The general
+syntax of a type specification is:
+
+@c FIXME: Add BNF reference here? If yes, what reference?
@example
@var{name} ::= (@var{name} [@var{keyword} @var{argument}]... @var{args})
| @var{name}
@end example
-Where, @var{name} is a widget name, @var{keyword} is the name of a
-property, @var{argument} is the value of the property, and @var{args}
-are interpreted in a widget specific way.
+Where @var{name} is a widget name, as defined with
+@code{define-widget}, @var{keyword} is the name of a property and
+@var{argument} is the value for that property, and @var{args} are
+interpreted in a widget specific way. @xref{Defining New Widgets}.
+
+@menu
+* Basic Types::
+* Sexp Types::
+@end menu
+
+@node Basic Types
+@section Basic Types
+
+@menu
+* default::
+* item::
+* link::
+* url-link::
+* info-link::
+* function-link::
+* variable-link::
+* face-link::
+* file-link::
+* emacs-library-link::
+* emacs-commentary-link::
+* push-button::
+* editable-field::
+* text::
+* menu-choice::
+* radio-button-choice::
+* choice-item::
+* toggle::
+* radio-button-toggle::
+* checkbox::
+* checklist::
+* editable-list::
+* group::
+* documentation-string::
+@end menu
+
+@node default
+@subsection The @code{default} Widget
+@findex default@r{ widget}
+The most basic widget in the Widget Library is the @dfn{default}
+widget. It provides the basic behavior for all other widgets, and all
+its properties are present by default in derived widgets. You're
+seldom (if ever) going to effectively create a default widget, but
+here we describe its properties and behavior, so that we can describe
+other widgets only by mentioning the properties and behavior those
+other widgets specialize.
+
+@deffn Widget default
+Widget used as a base for other widgets.
+
+It provides most of the functionality that is referred to as ``by
+default'' in this text. If you want to define a new widget from
+scratch, use the @code{default} widget as its base.
+@end deffn
@cindex keyword arguments
The following keyword arguments apply to all widgets:
@table @code
+@vindex create@r{ keyword}
+@item :create
+Function to create a widget from scratch.
+
+The function takes one argument, a widget type, and creates a widget
+of that type, inserts it in the buffer, and returns a widget object.
+
+By default, it inserts the widget at point, using the format provided
+in the @code{:format} property.
+
+@vindex delete@r{ keyword}
+@item :delete
+Function to delete a widget.
+
+The function should take one argument, a widget, and should remove all
+traces of the widget from the buffer.
+
+The default value is:
+
+@defun widget-default-delete widget
+Remove @var{widget} from the buffer.
+Delete all @code{:children} and @code{:buttons} in @var{widget}.
+@end defun
+
+In most cases you should not change this value, but instead use
+@code{:value-delete} to make any additional cleanup.
+
@cindex internal format
@cindex external format
@vindex value@r{ keyword}
@item :value
-The initial value for widgets of this type. Typically, a widget
-represents its value in two formats: external and internal. The
-external format is the value as the rest of Emacs sees it, and the
-internal format is a representation that the widget defines and uses
-in a widget specific way.
+The initial value for widgets of this type.
+
+Typically, a widget represents its value in two formats: external and
+internal. The external format is the value as the rest of Emacs sees
+it, and the internal format is a representation that the widget
+defines and uses in a widget specific way.
Both formats might be the same for certain widgets and might differ
for others, and there is no guarantee about which format the value
@@ -500,6 +968,68 @@ stored in the @code{:value} property has. However, when creating a
widget or defining a new one (@pxref{Defining New Widgets}), the
@code{:value} should be in the external format.
+@vindex value-to-internal@r{ keyword}
+@item :value-to-internal
+Function to convert the value to the internal format.
+
+The function takes two arguments, a widget and an external value, and
+returns the internal value. The function is called on the present
+@code{:value} when the widget is created, and on any value set later
+with @code{widget-value-set}.
+
+@vindex value-to-external@r{ keyword}
+@item :value-to-external
+Function to convert the value to the external format.
+
+The function takes two arguments, a widget and an internal value, and
+returns the value in the external format.
+
+@vindex value-create@r{ keyword}
+@item :value-create
+Function to expand the @samp{%v} escape in the format string.
+
+It will be called with the widget as its argument and should insert a
+representation of the widget's value in the buffer.
+
+@vindex value-delete@r{ keyword}
+@item :value-delete
+A function that should remove the representation of the widget's value
+from the buffer.
+
+It will be called with the widget as its argument. It doesn't have to
+remove the text, but it should release markers and delete nested widgets
+if these are not listed in @code{:children} or @code{:buttons}.
+
+By default, it's a no-op.
+
+@vindex value-get@r{ keyword}
+@item :value-get
+Function to extract the value of a widget, as it is displayed in the
+buffer.
+
+@vindex value-set@r{ keyword}
+@item :value-set
+Function that takes a widget and a value as arguments, and recreates
+it.
+
+The value must already be in the internal format for widget. By
+default, it deletes the widget with the @code{:delete} function and
+creates it again with the @code{:create} function.
+
+@vindex value-inline@r{ keyword}
+@item :value-inline
+Function that takes a widget and returns its value, inlined.
+
+Inlined means that if the widget is not inline (i.e., its
+@code{:inline} property is @code{nil}), the return value is wrapped in
+a list.
+
+@vindex default-get@r{ keyword}
+@item :default-get
+Function that takes a widget and returns its default value.
+
+By default, it just returns the value stored in @code{:value}.
+
@vindex format@r{ keyword}
@item :format
This string will be inserted in the buffer when you create a widget.
@@ -513,14 +1043,6 @@ The text inside will be marked as a button.
By default, the text will be shown in @code{widget-button-face}, and
surrounded by brackets.
-@defopt widget-button-prefix
-String to prefix buttons.
-@end defopt
-
-@defopt widget-button-suffix
-String to suffix buttons.
-@end defopt
-
@item %@{
@itemx %@}
The text inside will be displayed with the face specified by
@@ -530,9 +1052,6 @@ The text inside will be displayed with the face specified by
This will be replaced with the buffer representation of the widget's
value. What this is depends on the widget type.
-@strong{Warning:} In an @code{editable-field} widget, the @samp{%v} escape
-must be preceded by some other text in the format string (if specified).
-
@item %d
Insert the string specified by @code{:doc} here.
@@ -561,6 +1080,11 @@ Face used to highlight text inside %[ %] in the format.
@vindex button-suffix@r{ keyword}
@item :button-prefix
@itemx :button-suffix
+Strings used as prefix and suffix for widgets that are buttons.
+
+By default, the values are @code{widget-button-prefix} and
+@code{widget-button-suffix}.
+
Text around %[ %] in the format.
These can be
@@ -594,10 +1118,11 @@ Emacsen that supports it.
@item :help-echo
Specifies how to display a message whenever you move to the widget with
either @code{widget-forward} or @code{widget-backward} or move the mouse
-over it (using the standard @code{help-echo} mechanism). The argument
-is either a string to display, a function of one argument, the widget,
-which should return a string to display, or a form that evaluates to
-such a string.
+over it (using the standard @code{help-echo} mechanism).
+
+The value is either a string to display, or a function of one
+argument, the widget. If a function, it should return a string to
+display, or a form that evaluates to such a string.
@vindex follow-link@r{ keyword}
@item :follow-link
@@ -607,7 +1132,12 @@ Specifies how to interpret a @key{mouse-1} click on the widget.
@vindex indent@r{ keyword}
@item :indent
An integer indicating the absolute number of spaces to indent children
-of this widget.
+of this widget. Its value might be @code{nil} too, which corresponds
+to a value of 0.
+
+The default @code{:create} functions and the functions that create the
+value per se use this property as a rudimentary layout mechanism for
+the widgets.
@vindex offset@r{ keyword}
@item :offset
@@ -619,14 +1149,6 @@ grandchildren compared to this widget.
An integer indicating how many extra spaces to add to the widget's
children compared to this widget.
-@vindex notify@r{ keyword}
-@item :notify
-A function called each time the widget or a nested widget is changed.
-The function is called with two or three arguments. The first argument
-is the widget itself, the second argument is the widget that was
-changed, and the third argument is the event leading to the change, if
-any.
-
@vindex menu-tag@r{ keyword}
@item :menu-tag
Tag used in the menu when the widget is used as an option in a
@@ -634,10 +1156,12 @@ Tag used in the menu when the widget is used as an option in a
@vindex menu-tag-get@r{ keyword}
@item :menu-tag-get
-Function used for finding the tag when the widget is used as an option
-in a @code{menu-choice} widget. By default, the tag used will be either the
-@code{:menu-tag} or @code{:tag} property if present, or the @code{princ}
-representation of the @code{:value} property if not.
+Function that takes a widget and returns the tag when the widget is
+used as an option in a @code{menu-choice} widget.
+
+By default, the tag used will be either the @code{:menu-tag} or
+@code{:tag} property if present, or the @code{princ} representation of
+the @code{:value} property if not.
@vindex match@r{ keyword}
@item :match
@@ -648,22 +1172,19 @@ represent the specified value.
@vindex validate@r{ keyword}
@item :validate
A function which takes a widget as an argument, and returns @code{nil}
-if the widget's current value is valid for the widget. Otherwise it
-should return the widget containing the invalid data, and set that
-widget's @code{:error} property to a string explaining the error.
+if the widget's current value is valid for the widget.
-The following predefined function can be used:
+Otherwise, it should return the widget containing the invalid data,
+and set that widget's @code{:error} property to a string explaining
+the error.
-@defun widget-children-validate widget
-All the @code{:children} of @var{widget} must be valid.
-@end defun
+By default, it always returns @code{nil}.
@vindex tab-order@r{ keyword}
@item :tab-order
Specify the order in which widgets are traversed with
@code{widget-forward} or @code{widget-backward}. This is only partially
implemented.
-
@enumerate a
@item
Widgets with tabbing order @code{-1} are ignored.
@@ -690,39 +1211,208 @@ This keyword is only used for members of a @code{radio-button-choice} or
arguments, which will be used when creating the @code{radio-button} or
@code{checkbox} associated with this item.
+@vindex completions-function@r{ keyword}
+@item :completions-function
+Function that takes a widget and returns completion data for that
+widget, like @code{completion-at-point-functions} would.
+@xref{Completion,,,elisp, the Emacs Lisp Reference Manual}. It's
+used by @code{editable-field} widgets to provide completions.
+
+By default, it looks into the property @code{:completions}, which
+should be a completion table. If @code{:completions} is @code{nil},
+then it calls the function stored either in the @code{:complete} or
+@code{:complete-function} property.
+
+@vindex format-handler@r{ keyword}
+@item :format-handler
+Function to handle unknown @samp{%} escapes in the format string.
+
+It takes a widget and the character that follows the @samp{%} as
+arguments. You can set this to allow your widget to handle
+non-standard escapes in your own specialized widgets.
+
+@findex widget-default-format-handler
+You should end up calling @code{widget-default-format-handler} to handle
+unknown escape sequences, which will handle the @samp{%h} and any future
+escape sequences, as well as give an error for unknown escapes.
+
+@vindex button-face-get@r{ keyword}
+@item :button-face-get
+Function to return the face used to fontify a widget button.
+
+Takes a widget and returns an appropriate face for the widget. By
+default, it either returns the face stored in the @code{:button-face}
+property, or calls the @code{:button-face-get} function from the
+parent of the widget, if it has one.
+
+@vindex mouse-face-get@r{ keyword}
+@item :mouse-face-get
+Function to return the face used to fontify a widget when the mouse
+pointer hovers over it.
+
+Takes a widget and returns an appropriate face. By default, it either
+returns the face stored in the @code{:mouse-face} property, or calls
+the @code{:button-face-get} function from the parent of the widget, if
+it has one.
+
+@vindex copy@r{ keyword}
+@item :copy
+Function to deep copy a widget type.
+
+It takes a shallow copy of the widget type as an argument (made by
+@code{copy-sequence}), and returns a deep copy. The purpose of this
+is to avoid having different instances of combined widgets share
+nested attributes.
+
+Its value by default is @code{identity}.
+
+@vindex active@r{ keyword}
+@item :active
+Function that takes a widget and returns @code{t} if it is active.
+
+A widget might be effectively always active, if its
+@code{:always-active} property is @code{t}.
+
+@cindex active widget
+@cindex inactive widget
+@cindex activate a widget
+@cindex deactivate a widget
+Widgets can be in two states: active, which means they are modifiable by
+the user, or inactive, which means they cannot be modified by the user.
+You can query or set the state with the following code:
+
+@lisp
+;; Examine if @var{widget} is active or not.
+(if (widget-apply @var{widget} :active)
+ (message "Widget is active.")
+ (message "Widget is inactive.")
+
+;; Make @var{widget} inactive.
+(widget-apply @var{widget} :deactivate)
+
+;; Make @var{widget} active.
+(widget-apply @var{widget} :activate)
+@end lisp
+
+A widget is inactive if it, or any of its ancestors (found by
+following the @code{:parent} link), have been deactivated. To make sure
+a widget is really active, you must therefore activate both it and
+all its ancestors.
+
+@lisp
+(while widget
+ (widget-apply widget :activate)
+ (setq widget (widget-get widget :parent)))
+@end lisp
+
+You can check if a widget has been made inactive by examining the value
+of the @code{:inactive} keyword. If this is non-@code{nil}, the widget itself
+has been deactivated. This is different from using the @code{:active}
+keyword, in that the latter tells you if the widget @strong{or} any of
+its ancestors have been deactivated. Do not attempt to set the
+@code{:inactive} keyword directly. Use the @code{:activate}
+@code{:deactivate} functions instead.
+
+@vindex activate@r{ keyword}
+@item :activate
+Function that takes a widget and makes it active for user
+modifications.
+
+@vindex deactivate@r{ keyword}
+@item :deactivate
+Function that takes a widget and makes it inactive for user
+modifications.
+
+@vindex action@r{ keyword}
+@item :action
+Function that takes a widget and optionally an event, and handles a
+user initiated event.
+
+By default, uses the @code{:notify} function to notify the widget's
+parent about the event.
+
+@vindex mouse-down-action@r{ keyword}
+@item :mouse-down-action
+Function that takes a widget and optionally an event, and handles a
+mouse click on the widget.
+
+By default, it does nothing.
+
+@vindex notify@r{ keyword}
+@item :notify
+A function called each time the widget or a nested widget is changed.
+
+The function is called with two or three arguments. The first argument
+is the widget itself, the second argument is the widget that was
+changed, and the third argument is the event leading to the change, if
+any.
+
+By default, it passes the notification to the widget's parent.
+
+@vindex prompt-value@r{ keyword}
+@item :prompt-value
+Function to prompt for a value in the minibuffer.
+
+The function should take four arguments, a widget, a prompt (a
+string), a value and a boolean, and should return a value for the
+widget, entered by the user.
+
+The prompt is the prompt to use. The value is the default value to
+use, unless the fourtha argument is non-@code{nil}, in which case
+there is no default value.
+
+The function should read the value using the method most natural for
+this widget, and does not have to check that it matches.
@end table
-@deffn {User Option} widget-image-directory
-Directory where Widget should look for images.
-Widget will look here for a file with the same name as specified for the
-image, with either a @file{.xpm} (if supported) or @file{.xbm} extension.
-@end deffn
+@node item
+@subsection The @code{item} Widget
+@findex item@r{ widget}
-@deffn{User Option} widget-image-enable
-If non-@code{nil}, allow images to appear on displays where they are supported.
-@end deffn
+Syntax:
+@example
+@var{type} ::= (item [@var{keyword} @var{argument}]... @var{value})
+@end example
-@menu
-* link::
-* url-link::
-* info-link::
-* push-button::
-* editable-field::
-* text::
-* menu-choice::
-* radio-button-choice::
-* item::
-* choice-item::
-* toggle::
-* checkbox::
-* checklist::
-* editable-list::
-* group::
-@end menu
+A useful widget that holds a constant value, and can be included in
+other widgets. Its super is the @code{default} widget.
+
+As can be seen in the syntax, the @code{item} widget is one of the
+widget that handles the @var{args} argument to @code{widget-create} in
+a specific way. If present, @var{value} is used to initialize the
+@code{:value} property. When created, it inserts the value as a
+string in the buffer.
+
+By default, it has the following properties:
+
+@table @code
+@item :convert-widget
+The function that allows it to handle @var{value}.
+
+@item :value-create
+Prints the representation of @code{:value} in the buffer.
+
+@item :value-get
+Returns the value stored in @code{:value}.
+
+@item :match
+A value matches the @code{item} widget if it's @code{equal} to its
+@code{:value}.
+
+@item :match-inline
+Inline values match the @code{item} widget if @code{:value} is a
+sublist of values.
+
+@item :action
+The @code{item} widget notifies itself of an event.
+
+@item :format
+By default, the @code{item} widget inserts its tag in the buffer.
+@end table
@node link
-@section The @code{link} Widget
+@subsection The @code{link} Widget
@findex link@r{ widget}
Syntax:
@@ -731,22 +1421,42 @@ Syntax:
@var{type} ::= (link [@var{keyword} @var{argument}]... [ @var{value} ])
@end example
+A widget to represent an embedded link. Its super is the @code{item}
+widget.
+
The @var{value}, if present, is used to initialize the @code{:value}
property. The value should be a string, which will be inserted in the
buffer.
-By default the link will be shown in brackets.
+By default, it has the following properties:
-@defopt widget-link-prefix
-String to prefix links.
-@end defopt
+@table @code
+@item :button-prefix
+The value of @code{widget-link-prefix}.
-@defopt widget-link-suffix
-String to suffix links.
-@end defopt
+@item :button-suffix
+The value of @code{widget-link-suffix}.
+
+@item :keymap
+A custom keymap for the link widget, so that it can respond to mouse clicks.
+
+@item :follow-link
+This property allows the link to respect the value of
+@code{mouse-1-click-follows-link}. @xref{Clickable Text,,,elisp, the Emacs Lisp Reference Manual}.
+
+@item :format
+Buttonizes the link, to make it clickable.
+
+If you override this property, you should make sure to provide the
+@samp{%[} and @samp{%]} escape sequences, so that the link is
+clickable.
+
+@end table
+
+By default the link will be shown in brackets.
@node url-link
-@section The @code{url-link} Widget
+@subsection The @code{url-link} Widget
@findex url-link@r{ widget}
Syntax:
@@ -755,12 +1465,14 @@ Syntax:
@var{type} ::= (url-link [@var{keyword} @var{argument}]... @var{url})
@end example
-@findex browse-url-browser-function@r{, and @code{url-link} widget}
-When this link is invoked, the @acronym{WWW} browser specified by
-@code{browse-url-browser-function} will be called with @var{url}.
+A widget to represent a link to a web page. Its super is the
+@code{link} widget.
+
+It overrides the @code{:action} property to open up the @var{url}
+specified.
@node info-link
-@section The @code{info-link} Widget
+@subsection The @code{info-link} Widget
@findex info-link@r{ widget}
Syntax:
@@ -769,11 +1481,104 @@ Syntax:
@var{type} ::= (info-link [@var{keyword} @var{argument}]... @var{address})
@end example
-When this link is invoked, the built-in Info reader is started on
-@var{address}.
+A widget to represent a link to an info file. Its super is the
+@code{link} widget.
+
+It overrides the @code{:action} property, to a function to start the
+built-in Info reader on @var{address}, when invoked.
+
+@node function-link
+@subsection The @code{function-link} Widget
+@findex function-link@r{ widget}
+Syntax:
+
+@example
+@var{type} ::= (function-link [@var{keyword} @var{argument}]... @var{function})
+@end example
+
+A widget to represent a link to an Emacs function. Its super is the
+@code{link} widget.
+
+It overrides the @code{:action} property, to a function to describe
+@var{function}.
+
+@node variable-link
+@subsection The @code{variable-link} Widget
+@findex variable-link@r{ widget}
+Syntax:
+
+@example
+@var{type} ::= (variable-link [@var{keyword} @var{argument}]... @var{var})
+@end example
+
+A widget to represent a link to an Emacs variable. Its super is the
+@code{link} widget.
+
+It overrides the @code{:action} property, to a function to describe
+@var{var}.
+
+@node face-link
+@subsection The @code{face-link} Widget
+@findex face-link@r{ widget}
+Syntax:
+
+@example
+@var{type} ::= (face-link [@var{keyword} @var{argument}]... @var{face})
+@end example
+
+A widget to represent a link to an Emacs face. Its super is the
+@code{link} widget.
+
+It overrides the @code{:action} property, to a function to describe
+@var{face}.
+
+@node file-link
+@subsection The @code{file-link} Widget
+@findex file-link@r{ widget}
+Syntax:
+
+@example
+@var{type} ::= (file-link [@var{keyword} @var{argument}]... @var{file})
+@end example
+
+A widget to represent a link to a file. Its super is the
+@code{link} widget.
+
+It overrides the @code{:action} property, to a function to find the file
+@var{file}.
+
+@node emacs-library-link
+@subsection The @code{emacs-library-link} Widget
+@findex emacs-library-link@r{ widget}
+Syntax:
+
+@example
+@var{type} ::= (emacs-library-link [@var{keyword} @var{argument}]... @var{file})
+@end example
+
+A widget to represent a link to an Emacs Lisp file. Its super is the
+@code{link} widget.
+
+It overrides the @code{:action} property, to a function to find the file
+@var{file}.
+
+@node emacs-commentary-link
+@subsection The @code{emacs-commentary-link} Widget
+@findex emacs-commentary-link@r{ widget}
+Syntax:
+
+@example
+@var{type} ::= (emacs-commentary-link [@var{keyword} @var{argument}]... @var{file})
+@end example
+
+A widget to represent a link to the Comment section of an Emacs Lisp
+file. Its super is the @code{link} widget.
+
+It overrides the @code{:action} property, to a function to find the file
+@var{file} and put point in the Comment section.
@node push-button
-@section The @code{push-button} Widget
+@subsection The @code{push-button} Widget
@findex push-button@r{ widget}
Syntax:
@@ -782,22 +1587,37 @@ Syntax:
@var{type} ::= (push-button [@var{keyword} @var{argument}]... [ @var{value} ])
@end example
+A widget that acts as a pushable button. Its super is the @code{item}
+widget.
+
The @var{value}, if present, is used to initialize the @code{:value}
property. The value should be a string, which will be inserted in the
buffer.
-By default the tag will be shown in brackets.
+By default, it has the following properties:
+@table @code
+@item :button-prefix
+The empty string.
-@defopt widget-push-button-prefix
-String to prefix push buttons.
-@end defopt
+@item :button-suffix
+The empty string.
-@defopt widget-push-button-suffix
-String to suffix push buttons.
-@end defopt
+@item :value-create
+Inserts a representation of the ``on'' and ``off'' states for the push
+button.
+
+The representation might be an image, stored in the @code{:tag-glyph}
+property, or text. If it is text, it might be the value of the
+@code{:tag} property, or the @code{:value} of the widget, surrounded
+with @code{widget-push-button-prefix} and
+@code{widget-push-button-suffix}. @xref{Customization}.
+
+@item :format
+Buttonizes the widget, to make it clickable.
+@end table
@node editable-field
-@section The @code{editable-field} Widget
+@subsection The @code{editable-field} Widget
@findex editable-field@r{ widget}
Syntax:
@@ -806,56 +1626,137 @@ Syntax:
@var{type} ::= (editable-field [@var{keyword} @var{argument}]... [ @var{value} ])
@end example
+A widget that can be edited by the user. Its super is the
+@code{default} widget.
+
The @var{value}, if present, is used to initialize the @code{:value}
property. The value should be a string, which will be inserted in the
-field. This widget will match all string values.
+field. If not present, @code{:value} is the empty string.
-The following extra properties are recognized:
+@strong{Warning:} In an @code{editable-field} widget, the editable
+field must not be adjacent to another widget---that won't work.
+You must put some text in between. Either make this text part of
+the @code{editable-field} widget itself, or insert it with
+@code{widget-insert}.
+
+This widget either overrides or adds the following properties:
@table @code
+@item :convert-widget
+Just like the @code{item} widget, this function allows it to
+initialize @code{:value} from @var{value}.
+
+@vindex keymap@r{ keyword}
+@vindex widget-field-keymap
+@item :keymap
+Keymap used in the editable field.
+
+The default value is @code{widget-field-keymap}, which allows the user
+to use all the normal editing commands, even if the buffer's major
+mode suppresses some of them. Pressing @key{RET} invokes the function
+specified by @code{:action}.
+
+@item :format
+By default, it specifies to insert only the widget's value.
+
+@strong{Warning:} In an @code{editable-field} widget, the @samp{%v} escape
+must be preceded by some other text in the @code{:format} string (if
+specified).
+
@vindex size@r{ keyword}
@item :size
-The width of the editable field.@*
+The width of the editable field.
+
By default the field will reach to the end of the line.
@vindex value-face@r{ keyword}
@item :value-face
-Face used for highlighting the editable field. Default is
-@code{widget-field-face}, see @ref{User Interface}.
+Face used for highlighting the editable field.
+
+Default is @code{widget-field-face}, @pxref{User Interface}.
@vindex secret@r{ keyword}
@item :secret
-Character used to display the value. You can set this to, e.g., @code{?*}
-if the field contains a password or other secret information. By
-default, this is @code{nil}, and the value is not secret.
+Character used to display the value.
+
+You can set this to, e.g., @code{?*} if the field contains a password
+or other secret information. By default, this is @code{nil}, and the
+value is not secret.
@vindex valid-regexp@r{ keyword}
@item :valid-regexp
By default the @code{:validate} function will match the content of the
-field with the value of this attribute. The default value is @code{""}
-which matches everything.
+field with the value of this attribute.
-@vindex keymap@r{ keyword}
-@vindex widget-field-keymap
-@item :keymap
-Keymap used in the editable field. The default value is
-@code{widget-field-keymap}, which allows you to use all the normal
-editing commands, even if the buffer's major mode suppresses some of
-them. Pressing @key{RET} invokes the function specified by
-@code{:action}.
+The default value is @code{""} which matches everything.
+
+@item :validate
+Returns @code{nil} if the current value of the widget matches the
+@code{:valid-regexp} value.
+
+@item :prompt-internal
+A function to read a value for widget, used by the
+@code{:prompt-value} function.
+
+@item :prompt-history
+A variable that holds the history of field minibuffer edits.
+
+@item :prompt-value
+A function that uses the @code{:prompt-internal} function and the
+@code{:prompt-history} value to prompt for a string, and return the
+user response in the external format.
+
+@item :action
+When invoked, moves point to the next field.
+
+@item :value-create
+Function that takes care of creating the widget, respecting its
+@code{:size} and @code{:value}.
+
+@item :value-set
+Function to use to modify programmatically the current value of the
+widget.
+
+@item :value-delete
+Function that removes the widget so it cannot be edited anymore.
+
+@item :value-get
+Function to return the current text in the widget.
+
+It takes an optional argument, @var{no-truncate}. If
+@var{no-truncate} is nil, truncates trailing spaces.
+
+@item :match
+Function that makes the widget match any string value.
@end table
@node text
-@section The @code{text} Widget
+@subsection The @code{text} Widget
@findex text@r{ widget}
+Syntax:
+
+@example
+@var{type} ::= (text [@var{keyword} @var{argument}]... [ @var{value} ])
+@end example
+
+A widget just like the @code{editable-field} widget, but intended for
+multiline text fields. Its super is the @code{editable-field} widget.
+
+It overrides the following properties:
+
+@table @code
+@item :format
+By default, prints a tag and the value.
+
@vindex widget-text-keymap
-This is just like @code{editable-field}, but intended for multiline text
-fields. The default @code{:keymap} is @code{widget-text-keymap}, which
-does not rebind the @key{RET} key.
+@item :keymap
+The default is @code{widget-text-keymap}, which does not rebind the
+@key{RET} key.
+@end table
@node menu-choice
-@section The @code{menu-choice} Widget
+@subsection The @code{menu-choice} Widget
@findex menu-choice@r{ widget}
Syntax:
@@ -864,21 +1765,37 @@ Syntax:
@var{type} ::= (menu-choice [@var{keyword} @var{argument}]... @var{type} ... )
@end example
+A widget to represent a menu of options. Its super is the
+@code{default} widget.
+
The @var{type} argument represents each possible choice. The widget's
-value will be that of the chosen @var{type} argument. This widget will
-match any value matching at least one of the specified @var{type}
-arguments.
+value will be that of the chosen @var{type} argument.
+
+It either overrides or adds the following properties:
@table @code
+@item :convert-widget
+A function that takes care of converting each possible choice.
+
+@item :copy
+A function to copy each possible choice.
+
+@item :format
+By default, buttonize the tag and show the value.
+
@vindex void@r{ keyword}
@item :void
Widget type used as a fallback when the value does not match any of the
specified @var{type} arguments.
+By default this is an @code{item} widget.
+
@vindex case-fold@r{ keyword}
@item :case-fold
-Set this to @code{nil} if you don't want to ignore case when prompting for a
-choice through the minibuffer.
+If @code{nil} don't ignore case when prompting for a choice through
+the minibuffer.
+
+By default, its value is @code{t}.
@vindex children@r{ keyword}
@item :children
@@ -892,10 +1809,54 @@ The current chosen type.
@vindex args@r{ keyword}
@item :args
The list of types.
+
+@item :value-create
+The function that inserts the current value for the widget.
+
+It inserts the first choice that matches, as with the @code{:match}
+function, the value of the widget.
+
+@item :value-get
+Returns the value of the first child for the widget (see the
+description for @code{:children} above).
+
+@item :value-inline
+Returns the inline value of the first child for the widget.
+
+@item :default-get
+The default value for this widget is the default value for the first
+choice, in case @code{:value} is missing.
+
+This means that if you want a specific default value for the
+@code{menu-choice} widget, you should either pass a @code{:value}
+property when creating it, or arrange the choices so that the first
+one can hold your desired default value.
+
+@item :mouse-down-action
+A function that takes care of showing a menu, if possible and desired.
+
+@item :action
+A function that takes care of getting a new choice for the widget.
+
+Depending on the number of choices available, it may show a menu or
+just toggle the choices, or even do nothing at all.
+
+After getting the choice, it recreates the widget and notifies it.
+
+@item :validate
+Returns @code{nil} if the widget's value is a valid choice.
+
+@item :match
+This widget will match any value matching at least one of the
+specified @var{type} arguments.
+
+@item :match-inline
+A function that returns non-@code{nil} if the values match the widget,
+taking into account the @code{:inline} property.
@end table
@node radio-button-choice
-@section The @code{radio-button-choice} Widget
+@subsection The @code{radio-button-choice} Widget
@findex radio-button-choice@r{ widget}
Syntax:
@@ -904,14 +1865,28 @@ Syntax:
@var{type} ::= (radio-button-choice [@var{keyword} @var{argument}]... @var{type} ... )
@end example
-The component types specify the choices, with one radio button for
+A widget to represent a choice from multiple options. Its super is
+the @code{default} widget.
+
+The component @var{types} specify the choices, with one radio button for
each. The widget's value will be that of the chosen @var{type}
-argument. This widget matches any value that matches at least one of
-the specified @var{type} arguments.
+argument.
-The following extra properties are recognized.
+It overrides the following properties:
@table @code
+@item :convert-widget
+As other composite widgets, a function that takes care of converting
+each available choice.
+
+@item :copy
+A function to copy each available choice.
+
+@item :action
+A function that checks if any radio button was pressed and activates
+the pressed one, possibly deactivating an old one. Then, it notifies
+itself.
+
@vindex entry-format@r{ keyword}
@item :entry-format
This string will be inserted for each entry in the list.
@@ -925,6 +1900,9 @@ Replace with the radio button.
Insert a literal @samp{%}.
@end table
+@item :format
+By default, it inserts its value.
+
@vindex button-args@r{ keyword}
@item :button-args
A list of keywords to pass to the radio buttons. Useful for setting,
@@ -940,11 +1918,38 @@ The widgets representing each type.
@vindex choice@r{ keyword}
@item :choice
-The current chosen type
+The current chosen type.
@vindex args@r{ keyword}
@item :args
The list of types.
+
+@item :value-create
+A function to insert all available choices.
+
+@item :value-get
+Returns the value for the chosen widget.
+
+@item :value-set
+A function to set the value to one of its available options.
+
+@item :value-inline
+A function that returns the inline value of the child widget.
+
+@item :offset
+By default, this widget has an offset of 4.
+
+@item :validate
+The widget validates if the current value is valid for one of its
+children.
+
+@item :match
+This widget matches any value that matches at least one of
+the specified @var{type} arguments.
+
+@item :match-inline
+Like the @code{:match} function, but taking into account inline
+values.
@end table
You can add extra radio button items to a @code{radio-button-choice}
@@ -960,22 +1965,8 @@ Please note that such items added after the @code{radio-button-choice}
widget has been created will @strong{not} be properly destructed when
you call @code{widget-delete}.
-@node item
-@section The @code{item} Widget
-@findex item@r{ widget}
-
-Syntax:
-
-@example
-@var{item} ::= (item [@var{keyword} @var{argument}]... @var{value})
-@end example
-
-The @var{value}, if present, is used to initialize the @code{:value}
-property. The value should be a string, which will be inserted in the
-buffer. This widget will only match the specified value.
-
@node choice-item
-@section The @code{choice-item} Widget
+@subsection The @code{choice-item} Widget
@findex choice-item@r{ widget}
Syntax:
@@ -984,14 +1975,26 @@ Syntax:
@var{item} ::= (choice-item [@var{keyword} @var{argument}]... @var{value})
@end example
+A widget to represent a choice in a @code{menu-choice} widget. Its
+super is the @code{item} widget.
+
The @var{value}, if present, is used to initialize the @code{:value}
-property. The value should be a string, which will be inserted in the
-buffer as a button. Activating the button of a @code{choice-item} is
-equivalent to activating the parent widget. This widget will only match
-the specified value.
+property.
+
+It overrides the following properties:
+
+@table @code
+@item :action
+Activating the button of a @code{choice-item} is equivalent to
+activating the parent widget.
+
+@item :format
+By default, it buttonizes the tag (i.e., its value) and adds a newline
+character at the end of the widget.
+@end table
@node toggle
-@section The @code{toggle} Widget
+@subsection The @code{toggle} Widget
@findex toggle@r{ widget}
Syntax:
@@ -1000,43 +2003,136 @@ Syntax:
@var{type} ::= (toggle [@var{keyword} @var{argument}]...)
@end example
+A widget that can toggle between two states. Its super is the
+@code{item} widget.
+
The widget has two possible states, @samp{on} and @samp{off}, which
correspond to a @code{t} or @code{nil} value, respectively.
-The following extra properties are recognized:
+It either overrides or adds the following properties:
@table @code
+@item :format
+By default, it buttonizes the value and adds a newline at the end of
+the widget.
+
@item :on
A string representing the @samp{on} state. By default the string
@samp{on}.
+
@item :off
A string representing the @samp{off} state. By default the string
@samp{off}.
+
@vindex on-glyph@r{ keyword}
@item :on-glyph
Name of a glyph to be used instead of the @samp{:on} text string, on
emacsen that supports this.
+
@vindex off-glyph@r{ keyword}
@item :off-glyph
Name of a glyph to be used instead of the @samp{:off} text string, on
emacsen that supports this.
+
+@item :value-create
+A function for creating the widget's value, according to its
+@samp{:on} or @samp{:off} state.
+
+@item :action
+Function to toggle the state of the widget. After toggling, it
+notifies itself.
+
+@item :match
+This widget matches anything.
+@end table
+
+@node radio-button-toggle
+@subsection The @code{radio-button-toggle} Widget
+@findex radio-button-toggle@r{ widget}
+Syntax:
+
+@example
+@var{type} ::= (radio-button-toggle [@var{keyword} @var{argument}]...)
+@end example
+
+A toggle to use in the @code{radio} widget.
+
+It overrides the following properties:
+
+@table @code
+@item :button-prefix
+The empty string.
+
+@item :button-suffix
+The empty string.
+
+@item :on
+The string ``(*)'', to represent the @samp{on} state.
+
+@item :off
+The string ``( )'', to represent the @samp{off} state.
+
+@item :on-glyph
+The name of an image to represent the @samp{on} state.
+
+@item :off-glpyh
+The name of an image to represent the @samp{off} state.
+
+@item :format
+By default, it buttonizes its value.
+
+@item :notify
+A function to notify its parent.
@end table
@node checkbox
-@section The @code{checkbox} Widget
+@subsection The @code{checkbox} Widget
@findex checkbox@r{ widget}
-This widget has two possible states, @samp{selected} and
-@samp{unselected}, which corresponds to a @code{t} or @code{nil} value.
-
Syntax:
@example
@var{type} ::= (checkbox [@var{keyword} @var{argument}]...)
@end example
+A widget to represent a toggle widget, with a checkbox. Its super is
+the @code{toggle} widget.
+
+This widget has two possible states, @samp{selected} and
+@samp{unselected}, which corresponds to a @code{t} or @code{nil}
+value, respectively.
+
+It either overrides or adds the following properties:
+
+@table @code
+@item :button-prefix
+The empty string.
+
+@item :button-suffix
+The empty string.
+
+@item :format
+By default, buttonizes the value.
+
+@item :on
+By default, the string ``[X]''.
+
+@item :off
+By default, the string ``[ ]''.
+
+@item :on-glyph
+The name of the image to use when the state is @samp{on}.
+
+@item :off-glyph
+The name of the image to use when the state is @samp{off}.
+
+@item :action
+A function that toggles the checkbox, notifies the parents and in the
+@samp{on} state, activates its siblings.
+@end table
+
@node checklist
-@section The @code{checklist} Widget
+@subsection The @code{checklist} Widget
@findex checklist@r{ widget}
Syntax:
@@ -1045,14 +2141,26 @@ Syntax:
@var{type} ::= (checklist [@var{keyword} @var{argument}]... @var{type} ... )
@end example
+A widget to represent a multiplice choice. Its super is the
+@code{default} widget.
+
The @var{type} arguments represent each checklist item. The widget's
value will be a list containing the values of all checked @var{type}
-arguments. The checklist widget will match a list whose elements all
-match at least one of the specified @var{type} arguments.
+arguments.
-The following extra properties are recognized:
+It either overrides or adds the following properties:
@table @code
+@item :convert-widget
+As other composite widgets, a function that takes care of converting
+each checklist item.
+
+@item :copy
+A function to copy each checklist item.
+
+@item :format
+By default, it inserts its value.
+
@vindex entry-format@r{ keyword}
@item :entry-format
This string will be inserted for each entry in the list.
@@ -1066,14 +2174,6 @@ Replace with the checkbox.
Insert a literal @samp{%}.
@end table
-@vindex greedy@r{ keyword}
-@item :greedy
-Usually a checklist will only match if the items are in the exact
-sequence given in the specification. By setting @code{:greedy} to
-non-@code{nil}, it will allow the items to come in any sequence.
-However, if you extract the value they will be in the sequence given
-in the checklist, i.e., the original sequence is forgotten.
-
@vindex button-args@r{ keyword}
@item :button-args
A list of keywords to pass to the checkboxes. Useful for setting,
@@ -1090,10 +2190,35 @@ The widgets representing each type.
@vindex args@r{ keyword}
@item :args
The list of types.
+
+@item :value-create
+The function that takes care of inserting all values.
+
+@item :value-get
+A function that returns all values of selected items.
+
+@item :validate
+A function that ensures all selected children are valid.
+
+@item :match
+The checklist widget will match a list whose elements all
+match at least one of the specified @var{type} arguments.
+
+@item :match-inline
+Like the @code{:match} function, but taking into account the
+@code{:inline} property.
+
+@vindex greedy@r{ keyword}
+@item :greedy
+Usually a checklist will only match if the items are in the exact
+sequence given in the specification. By setting @code{:greedy} to
+non-@code{nil}, it will allow the items to come in any sequence.
+However, if you extract the value they will be in the sequence given
+in the checklist, i.e., the original sequence is forgotten.
@end table
@node editable-list
-@section The @code{editable-list} Widget
+@subsection The @code{editable-list} Widget
@findex editable-list@r{ widget}
Syntax:
@@ -1102,12 +2227,19 @@ Syntax:
@var{type} ::= (editable-list [@var{keyword} @var{argument}]... @var{type})
@end example
-The value is a list, where each member represents one widget of type
-@var{type}.
+A widget that can hold a variable list of widgets of the same type,
+represented by @var{type}. Its super is the @code{default} widget.
-The following extra properties are recognized:
+It either overrides or adds the following properties:
@table @code
+@item :convert-widget
+As other composite widgets, a function that takes care of converting
+each type in @var{type}.
+
+@item :copy
+A function to copy the types given in @var{type}.
+
@vindex entry-format@r{ keyword}
@item :entry-format
This string will be inserted for each entry in the list.
@@ -1117,9 +2249,9 @@ The following @samp{%} escapes are available:
This will be replaced with the buffer representation of the @var{type}
widget.
@item %i
-Insert the @b{[INS]} button.
+Insert the @b{[INS]} button, a widget of type @code{insert-button}.
@item %d
-Insert the @b{[DEL]} button.
+Insert the @b{[DEL]} button, a widget of type @code{delete-button}.
@item %%
Insert a literal @samp{%}.
@end table
@@ -1140,6 +2272,18 @@ A list of keyword arguments to pass to the trailing insert button.
@item :buttons
The widgets representing the insert and delete buttons.
+@item :format
+By default, insert its value and at the and adds an insert button.
+
+This is useful so that new elements can be added to the list upon user
+request.
+
+@item :format-handler
+A function that recognize the escape for inserting an insert button.
+
+@item :offset
+By default, this widget has an offset of 12.
+
@vindex children@r{ keyword}
@item :children
The widgets representing the elements of the list.
@@ -1147,24 +2291,124 @@ The widgets representing the elements of the list.
@vindex args@r{ keyword}
@item :args
List whose @sc{car} is the type of the list elements.
+
+@item :insert-before
+Function to insert a new widget as a child of the @code{editable-list}
+widget.
+
+This function inserts a recently deleted child, if there is one. That
+is useful, so that the user can move elements in a list easily. If
+there is not a recently deleted child, it inserts a child with its
+default value.
+
+@item :delete-at
+Function to delete a child from the widget, and store it into the
+@code{:last-deleted} list, so that it can be reinserted when the
+@code{:insert-before} function executes.
+
+@item :value-create
+The function that takes care of inserting all values.
+
+@item :value-get
+Function that returns a list with the value of the child widgets.
+
+@item :validate
+This widget validates if all children validate.
+
+@item :match
+To match, the value must be a list and all the list members must match
+the specified @var{type}.
+
+@item :match-inline
+Like the @code{:match} function, but taking into account inline
+values and widgets.
@end table
@node group
-@section The @code{group} Widget
+@subsection The @code{group} Widget
@findex group@r{ widget}
-This widget simply group other widgets together.
-
Syntax:
@example
@var{type} ::= (group [@var{keyword} @var{argument}]... @var{type}...)
@end example
-The value is a list, with one member for each @var{type}.
+A widget to group other widgets. Its super is the @code{default}
+widget.
+
+Its value is a list, with one member for each @var{type}.
+
+It overrides the following properties:
+
+@table @code
+@item :convert-widget
+As other composite widgets, a function that takes care of converting
+each widget in @var{type}.
+
+@item :copy
+A function to copy the types given in @var{type}.
+
+@item :format
+By default, displays a newline character and its value.
+
+@item :value-create
+A function to create each of its components.
+
+@item :value-get
+The same function used by the @code{editable-list} widget.
+
+@item :default-get
+A function that returns a list whose members are the default values of
+each widget it groups.
+
+@item :validate
+This widget validates if all of its children validate.
+
+@item :match
+This widget matches a value that matches each of its components.
+
+@item :match-inline
+As @code{:match}, but taking into account widgets and values that are
+inline.
+@end table
+
+@node documentation-string
+@subsection The @code{documentation-string} Widget
+@findex documentation-string@r{ widget}
+Syntax:
+
+@example
+@var{type} ::= (documentation-string [@var{keyword} @var{argument}]... @var{value})
+@end example
+
+A widget to represent a documentation string. Its super is the
+@code{item} widget.
+
+It either overrides or adds the following properties:
+
+@table @code
+@item :format
+By default, insert its value.
+
+@item :value-create
+Function to insert a documentation string, possibly hiding part of the
+documentation if its large.
+
+To show or hide the rest of the documentation, uses a
+@code{visibility} widget.
+
+@item :action
+Function to toggle showing the documentation upon an event.
+
+@item :visibility-widget
+A symbol, the type of the widget to use for the visibility widget.
+
+This is, by default, the symbol @code{visibility}.
+@end table
@node Sexp Types
-@chapter Sexp Types
+@section Sexp Types
@cindex sexp types
A number of widgets for editing @dfn{s-expressions} (Lisp types), sexp
@@ -1179,7 +2423,7 @@ categories described in this section.
@end menu
@node constants
-@section The Constant Widgets
+@subsection The Constant Widgets
@cindex constant widgets
The @code{const} widget can contain any Lisp expression, but the user is
@@ -1192,19 +2436,26 @@ The syntax for the @code{const} widget is:
@var{type} ::= (const [@var{keyword} @var{argument}]... [ @var{value} ])
@end example
-The @var{value}, if present, is used to initialize the @code{:value}
-property and can be any s-expression.
+Its super is the @code{item} widget. The @var{value}, if present, is
+used to initialize the @code{:value} property and can be any
+s-expression.
@deffn Widget const
This will display any valid s-expression in an immutable part of the
buffer.
+
+It overrides the @code{:prompt-value} function, to avoid prompting and
+just return the widget's value.
@end deffn
There are two variations of the @code{const} widget, namely
@code{variable-item} and @code{function-item}. These should contain a
-symbol with a variable or function binding. The major difference from
-the @code{const} widget is that they will allow the user to see the
-variable or function documentation for the symbol.
+symbol with a variable or function binding, respectively. The major
+difference from the @code{const} widget is that they will allow the
+user to see the variable or function documentation for the symbol.
+
+This is accomplished via using the @samp{%h} format escape, and adding
+an appropriate @code{:documentation-property} function for each widget.
@deffn Widget variable-item
An immutable symbol that is bound as a variable.
@@ -1215,7 +2466,7 @@ An immutable symbol that is bound as a function.
@end deffn
@node generic
-@section Generic Sexp Widget
+@subsection Generic Sexp Widget
@cindex generic sexp widget
The @code{sexp} widget can contain any Lisp expression, and allows the
@@ -1228,23 +2479,42 @@ The syntax for the @code{sexp} widget is:
@end example
@deffn Widget sexp
-This will allow you to edit any valid s-expression in an editable buffer
-field.
+This widget represents an editable field that's useful to edit any
+valid s-expression.
The @code{sexp} widget takes the same keyword arguments as the
@code{editable-field} widget. @xref{editable-field}.
+
+Its default value is @code{nil}.
+@end deffn
+
+@deffn Widget restricted-sexp
+A widget to edit Lisp expressions restricted to certain values or
+types. Its super is the @code{sexp} widget.
+
+It works just like the sexp widget, but it overrides the @code{:match}
+function to match for certain values. To use this widget, either you
+must define a @code{:match} function or give a
+@code{:match-alternatives} property. The @code{:match-alternatives}
+property holds a list of predicate functions to call when checking if
+a given value matches the widget. Each predicate function will be
+called with one argument, the value to be matched, and should return
+non-@code{nil} on success.
+
+As an example, the @code{integer} widget overrides
+@code{:match-alternatives} to @code{(integerp)}.
@end deffn
@node atoms
-@section Atomic Sexp Widgets
+@subsection Atomic Sexp Widgets
@cindex atomic sexp widget
The atoms are s-expressions that do not consist of other s-expressions.
For example, a string, a file name, or a symbol are atoms, while a list
is a composite type. You can edit the value of an atom with the
-following widgets.
+widgets described in this section.
-The syntax for all the atoms are:
+The syntax for all the atoms is:
@example
@var{type} ::= (@var{construct} [@var{keyword} @var{argument}]... [ @var{value} ])
@@ -1252,68 +2522,151 @@ The syntax for all the atoms are:
The @var{value}, if present, is used to initialize the @code{:value}
property and must be an expression of the same type as the widget.
-That is, the string widget can only be initialized with a string.
+That is, for example, the string widget can only be initialized with a
+string.
All the atom widgets take the same keyword arguments as the
@code{editable-field} widget. @xref{editable-field}.
@deffn Widget string
-Allows you to edit a string in an editable field.
+An editable field widget that can represent any Lisp string.
+
+It offers completion via the ispell library and the @code{:complete}
+property.
@end deffn
@deffn Widget regexp
-Allows you to edit a regular expression in an editable field.
+An editable field widget that can represent a regular expression.
+
+Overrides the @code{:match} and the @code{:validate} properties to
+check that the value is a valid regexp.
@end deffn
@deffn Widget character
-Allows you to enter a character in an editable field.
+An editable field widget that can represent a character.
+
+The character widget represents some characters (like the newline
+character) in a special manner, to make it easier for the user to see
+what's the content of the character field.
@end deffn
@deffn Widget file
-Allows you to edit a file name in an editable field.
+A widget for editing file names.
Keywords:
@table @code
+@item :completions
+Offers file name completion to the user.
+
+@item :prompt-value
+A function to read a file name from the minibuffer.
+
@vindex must-match@r{ keyword}
@item :must-match
-If this is set to non-@code{nil}, only existing file names will be
-allowed in the minibuffer.
+If this is set to non-@code{nil}, only existing file names are allowed
+when prompting for a value in the minibuffer.
+
+@item :match
+The widget matches if the value is a string, and the file whose name
+is that string is an existing file, or if @code{:must-match} is
+@code{nil}.
+
+@item :validate
+The widget is valid if its value matches.
+
@end table
@end deffn
@deffn Widget directory
-Allows you to edit a directory name in an editable field.
-Similar to the @code{file} widget.
+A widget for editing directory names.
+
+Its super is the @code{file} widget, and it overrides the
+@code{:completions} property, to offer completions only for
+directories.
@end deffn
@deffn Widget symbol
-Allows you to edit a Lisp symbol in an editable field.
+A widget for editing a Lisp symbol.
+
+Its value by default is @code{nil}.
@end deffn
@deffn Widget function
-Allows you to edit a lambda expression, or a function name with completion.
+A widget for editing a lambda expression, or a function name, offering
+completion. Its super is the @code{restricted-sexp} widget.
@end deffn
@deffn Widget variable
-Allows you to edit a variable name, with completion.
+A widget for editing variable names, offering completion. Its super
+is the @code{symbol} widget.
@end deffn
@deffn Widget integer
-Allows you to edit an integer in an editable field.
+A widget for editing integers in an editable field. Its super is the
+@code{restricted-sexp} widget.
+
+It has a default @code{:value} of 0.
+@end deffn
+
+@deffn Widget natnum
+A widget for editing non-negative integers. Its super is the
+@code{restricted-sexp} widget.
+
+It has a default @code{:value} of 0.
+@end deffn
+
+@deffn Widget float
+A widget for editing a floating point number. Its super is the
+@code{restricted-sexp} widget.
+
+It has a default @code{:value} of 0.0.
@end deffn
@deffn Widget number
-Allows you to edit a number in an editable field.
+A widget for editing a number, either floating point or integer. Its
+super is the @code{restricted-sexp} widget.
+
+It has a default @code{:value} of 0.0.
@end deffn
@deffn Widget boolean
-Allows you to edit a boolean. In Lisp this means a variable which is
-either @code{nil} meaning false, or non-@code{nil} meaning true.
+A widget for editing a boolean value. Its super is the @code{toggle}
+widget.
+
+Its value may be @code{nil}, meaning false, or non-@code{nil}, meaning
+true.
+@end deffn
+
+@deffn Widget color
+A widget to edit a color name.
+
+In addition, shows a sample that shows the selected color, if any.
@end deffn
+@deffn Widget other
+A widget useful as the last item in a @code{choice} widget, since it
+matches any value.
+
+Its super is the @code{sexp} widget, and its @code{:value} is
+@code{other}, by default.
+@end deffn
+
+@deffn Widget coding-system
+A widget that can represent a coding system name, offering
+completions. @xref{Coding Systems,,,elisp, the Emacs Lisp Reference
+Manual}. Its super is the @code{symbol} widget.
+
+It has a default value of @code{undecided}.
+@end deffn
+
+@deffn Widget key
+A widget to represent a key sequence.
+
+It uses a special keymap as the @code{:keymap}.
+@end deffn
@node composite
-@section Composite Sexp Widgets
+@subsection Composite Sexp Widgets
@cindex composite sexp widgets
The syntax for the composite widget construct is:
@@ -1327,6 +2680,9 @@ where each @var{component} must be a widget type. Each component widget
will be displayed in the buffer, and will be editable by the user.
@deffn Widget cons
+A widget to edit cons-cell values. Its super is the @code{group}
+widget.
+
The value of a @code{cons} widget must be a cons-cell whose @sc{car}
and @sc{cdr} have two specified types. It uses this syntax:
@@ -1336,8 +2692,10 @@ and @sc{cdr} have two specified types. It uses this syntax:
@end deffn
@deffn Widget choice
-The value matched by a @code{choice} widget must have one of a fixed
-set of types. The widget's syntax is as follows:
+A widget to hold a value of one of a fixed set of types. Its super is
+the @code{menu-choice} widget.
+
+The widget's syntax is as follows:
@example
@var{type} ::= (choice [@var{keyword} @var{argument}]... @var{type} ... )
@@ -1345,9 +2703,19 @@ set of types. The widget's syntax is as follows:
The value of a @code{choice} widget can be anything that matches any of the
@var{types}.
+
+This widget only displays the widget that corresponds to the current
+choice.
+@end deffn
+
+@deffn Widget radio
+A widget to hold a value of one of a fixed set of options. Its super is
+the @code{radio-button-choice} widget.
@end deffn
@deffn Widget list
+A widget to edit a list value. Its super is the @code{group} widget.
+
The value of a @code{list} widget must be a list whose element types
match the specified component types:
@@ -1355,15 +2723,18 @@ match the specified component types:
@var{type} ::= (list [@var{keyword} @var{argument}]... @var{component-type}...)
@end example
-Thus, @code{(list string number)} matches lists of two elements,
-the first being a string and the second being a number.
+Thus, for example, @code{(list string number)} matches lists of two
+elements, the first being a string and the second being a number.
@end deffn
@deffn Widget vector
+A widget to edit a vector value. Its super is the @code{group}
+widget.
+
The @code{vector} widget is like the @code{list} widget but matches
-vectors instead of lists. Thus, @code{(vector string number)} matches
-vectors of two elements, the first being a string and the second being
-a number.
+vectors instead of lists. Thus, for example, @code{(vector string
+number)} matches vectors of two elements, the first being a string and
+the second being a number.
@end deffn
The above suffice for specifying fixed size lists and vectors. To get
@@ -1393,8 +2764,12 @@ trying to explain it here, I'll just suggest you meditate over it for
a while.
@deffn Widget set
-Specifies a type whose values are the lists whose elements all belong
-to a given set. The order of elements of the list is not significant.
+A widget to hold a list of members from a fixed set. Its super is the
+@code{checklist} widget.
+
+Its value is a list where the elements all belong to a given set. The
+order of elements of the list is not significant.
+
Here's the syntax:
@example
@@ -1407,111 +2782,55 @@ Use @code{const} to specify each permitted element, like this:
@deffn Widget repeat
Specifies a list of any number of elements that fit a certain type.
+Its super is the @code{editable-list} widget.
@example
@var{type} ::= (repeat [@var{keyword} @var{argument}]... @var{type})
@end example
@end deffn
-@node Widget Properties
-@chapter Properties
-@cindex properties of widgets
-@cindex widget properties
-
-You can examine or set the value of a widget by using the widget object
-that was returned by @code{widget-create}.
-
-@defun widget-value widget
-Return the current value contained in @var{widget}.
-It is an error to call this function on an uninitialized widget.
-@end defun
-
-@defun widget-value-set widget value
-Set the value contained in @var{widget} to @var{value}.
-It is an error to call this function with an invalid @var{value}.
-@end defun
-
-@strong{Important:} You @emph{must} call @code{widget-setup} after
-modifying the value of a widget before the user is allowed to edit the
-widget again. It is enough to call @code{widget-setup} once if you
-modify multiple widgets. This is currently only necessary if the widget
-contains an editing field, but may be necessary for other widgets in the
-future.
-
-If your application needs to associate some information with the widget
-objects, for example a reference to the item being edited, it can be
-done with @code{widget-put} and @code{widget-get}. The property names
-must begin with a @samp{:}.
-
-@defun widget-put widget property value
-In @var{widget} set @var{property} to @var{value}.
-@var{property} should be a symbol, while @var{value} can be anything.
-@end defun
-
-@defun widget-get widget property
-In @var{widget} return the value for @var{property}.
-@var{property} should be a symbol, the value is what was last set by
-@code{widget-put} for @var{property}.
-@end defun
-
-@defun widget-member widget property
-Non-@code{nil} if @var{widget} has a value (even @code{nil}) for
-property @var{property}.
-@end defun
-
-@defun widget-apply widget property &rest args
-Apply the value of @var{property} to @var{widget}, passing @var{args}
-as additional arguments to the function. Return the result of that
-function call.
-@end defun
+@deffn Widget plist
+A widget to edit property lists. Its super is the @code{list} widget.
-Occasionally it can be useful to know which kind of widget you have,
-i.e., the name of the widget type you gave when the widget was created.
+It recognizes the following properties:
-@defun widget-type widget
-Return the name of @var{widget}, a symbol.
-@end defun
-
-@cindex active widget
-@cindex inactive widget
-@cindex activate a widget
-@cindex deactivate a widget
-Widgets can be in two states: active, which means they are modifiable by
-the user, or inactive, which means they cannot be modified by the user.
-You can query or set the state with the following code:
+@table @code
+@item :options
+A given set of recommended key-value values for the @code{plist}
+widget. Each option shows up as a checklist item.
-@lisp
-;; Examine if @var{widget} is active or not.
-(if (widget-apply @var{widget} :active)
- (message "Widget is active.")
- (message "Widget is inactive.")
+@item :key-type
+The widget type to use for the plist keys. By default, it uses the
+@code{symbol} widget.
-;; Make @var{widget} inactive.
-(widget-apply @var{widget} :deactivate)
+@item :value-type
+The widget type to use for the plist values. By default, it uses the
+@code{sexp} widget.
+@end table
+@end deffn
-;; Make @var{widget} active.
-(widget-apply @var{widget} :activate)
-@end lisp
+@deffn Widget alist
+A widget to edit association lists. Its super is the @code{list}
+widget.
-A widget is inactive if it, or any of its ancestors (found by
-following the @code{:parent} link), have been deactivated. To make sure
-a widget is really active, you must therefore activate both it and
-all its ancestors.
+It recognizes the same properties that the @code{plist} widget, with
+the difference that the @code{:key-type} uses by default a @code{sexp}
+widget.
+@end deffn
-@lisp
-(while widget
- (widget-apply widget :activate)
- (setq widget (widget-get widget :parent)))
-@end lisp
+Most composite widgets do not allow for recursion. That is, none of
+the contained widgets may be of the same type that is currently being
+defined. To allow for this kind of widgets, there's the @code{lazy}
+widget.
-You can check if a widget has been made inactive by examining the value
-of the @code{:inactive} keyword. If this is non-@code{nil}, the widget itself
-has been deactivated. This is different from using the @code{:active}
-keyword, in that the latter tells you if the widget @strong{or} any of
-its ancestors have been deactivated. Do not attempt to set the
-@code{:inactive} keyword directly. Use the @code{:activate}
-@code{:deactivate} keywords instead.
+@deffn Widget lazy
+A base widget for recursive data structures. Its super is the
+@code{default} widget.
+When instantiated, it contains a single inferior widget of the widget
+type specified in the @code{:type} property. Its value is the same as
+the value of this inferior widget.
+@end deffn
@node Defining New Widgets
@chapter Defining New Widgets
@@ -1520,19 +2839,27 @@ its ancestors have been deactivated. Do not attempt to set the
You can define specialized widgets with @code{define-widget}. It allows
you to create a shorthand for more complex widgets, including specifying
-component widgets and new default values for the keyword
-arguments.
+component widgets and new default values for the keyword arguments.
@defun define-widget name class doc &rest args
-Define a new widget type named @var{name} from @code{class}.
+Define a new widget type named @var{name} that derives from @var{class}.
-@var{name} and class should both be symbols, @code{class} should be one
-of the existing widget types.
+@var{name} and @var{class} should both be symbols, and @var{class}
+should be one of the existing widget types.
The third argument @var{doc} is a documentation string for the widget.
-After the new widget has been defined, the following two calls will
-create identical widgets:
+@var{args} should be key-value pairs, overriding keyword values of
+@var{class}, or adding new recognized keywords for @var{name}.
+
+Usually, you'll want to derive from an existing widget type, like the
+@code{editable-field} widget, or the @code{default} widget, but it's
+also possible to derive from nothing, by passing a value of @code{nil}
+as @var{class}. Note that if you do this, you're entirely responsible
+for defining a whole new default behavior for your widgets.
+
+After using this function, the following two calls will create
+identical widgets:
@itemize @bullet
@item
@@ -1555,170 +2882,67 @@ in the @code{widget-type} property of @var{name}, which is what
If you only want to specify defaults for keywords with no complex
conversions, you can use @code{identity} as your conversion function.
-The following additional keyword arguments are useful when defining new
-widgets:
+When defining new widgets, the @code{:convert-widget} property might
+be useful:
+
@table @code
@vindex convert-widget@r{ keyword}
@item :convert-widget
Function to convert a widget type before creating a widget of that
-type. It takes a widget type as an argument, and returns the converted
-widget type. When a widget is created, this function is called for the
-widget type and all the widget's parent types, most derived first.
-
-The following predefined functions can be used here:
-
-@defun widget-types-convert-widget widget
-Convert @code{:args} as widget types in @var{widget}.
-@end defun
-
-@defun widget-value-convert-widget widget
-Initialize @code{:value} from @code{:args} in @var{widget}.
-@end defun
-
-@vindex copy@r{ keyword}
-@item :copy
-Function to deep copy a widget type. It takes a shallow copy of the
-widget type as an argument (made by @code{copy-sequence}), and returns a
-deep copy. The purpose of this is to avoid having different instances
-of combined widgets share nested attributes.
-
-The following predefined functions can be used here:
-
-@defun widget-types-copy widget
-Copy @code{:args} as widget types in @var{widget}.
-@end defun
-
-@vindex value-to-internal@r{ keyword}
-@item :value-to-internal
-Function to convert the value to the internal format. The function
-takes two arguments, a widget and an external value, and returns the
-internal value. The function is called on the present @code{:value}
-when the widget is created, and on any value set later with
-@code{widget-value-set}.
-
-@vindex value-to-external@r{ keyword}
-@item :value-to-external
-Function to convert the value to the external format. The function
-takes two arguments, a widget and an internal value, and returns the
-external value.
-
-@vindex create@r{ keyword}
-@item :create
-Function to create a widget from scratch. The function takes one
-argument, a widget type, and creates a widget of that type, inserts it
-in the buffer, and returns a widget object.
-
-@vindex delete@r{ keyword}
-@item :delete
-Function to delete a widget. The function takes one argument, a widget,
-and should remove all traces of the widget from the buffer.
+type.
-The default value is:
+It takes a widget type as an argument, and returns the converted
+widget type. When a widget is created, this function is called for
+the widget type and all the widget's parent types, most derived first.
-@defun widget-default-delete widget
-Remove @var{widget} from the buffer.
-Delete all @code{:children} and @code{:buttons} in @var{widget}.
-@end defun
-
-In most cases you should not change this value, but instead use
-@code{:value-delete} to make any additional cleanup.
-
-@vindex value-create@r{ keyword}
-@item :value-create
-Function to expand the @samp{%v} escape in the format string. It will
-be called with the widget as its argument and should insert a
-representation of the widget's value in the buffer.
-
-Nested widgets should be listed in @code{:children} or @code{:buttons}
-to make sure they are automatically deleted.
-
-@vindex value-delete@r{ keyword}
-@item :value-delete
-Should remove the representation of the widget's value from the buffer.
-It will be called with the widget as its argument. It doesn't have to
-remove the text, but it should release markers and delete nested widgets
-if these are not listed in @code{:children} or @code{:buttons}.
-
-@vindex value-get@r{ keyword}
-@item :value-get
-Function to extract the value of a widget, as it is displayed in the
-buffer.
-
-The following predefined function can be used here:
-
-@defun widget-value-value-get widget
-Return the @code{:value} property of @var{widget}.
-@end defun
-
-@vindex format-handler@r{ keyword}
-@item :format-handler
-Function to handle unknown @samp{%} escapes in the format string. It
-will be called with the widget and the character that follows the
-@samp{%} as arguments. You can set this to allow your widget to handle
-non-standard escapes.
-
-@findex widget-default-format-handler
-You should end up calling @code{widget-default-format-handler} to handle
-unknown escape sequences, which will handle the @samp{%h} and any future
-escape sequences, as well as give an error for unknown escapes.
-
-@vindex action@r{ keyword}
-@item :action
-Function to handle user initiated events. By default, @code{:notify}
-the parent.
-
-The following predefined function can be used here:
-
-@defun widget-parent-action widget &optional event
-Tell @code{:parent} of @var{widget} to handle the @code{:action}.
-Optional @var{event} is the event that triggered the action.
-@end defun
-
-@vindex prompt-value@r{ keyword}
-@item :prompt-value
-Function to prompt for a value in the minibuffer. The function should
-take four arguments, @var{widget}, @var{prompt}, @var{value}, and
-@var{unbound} and should return a value for widget entered by the user.
-@var{prompt} is the prompt to use. @var{value} is the default value to
-use, unless @var{unbound} is non-@code{nil}, in which case there is no default
-value. The function should read the value using the method most natural
-for this widget, and does not have to check that it matches.
+The predefined functions @code{widget-types-convert-widget} and
+@code{widget-value-convert-widget} can be used here.
@end table
-If you want to define a new widget from scratch, use the @code{default}
-widget as its base.
-
-@deffn Widget default
-Widget used as a base for other widgets.
-
-It provides most of the functionality that is referred to as ``by
-default'' in this text.
-@end deffn
-
-@node Widget Browser
-@chapter Widget Browser
+@node Inspecting Widgets
+@chapter Inspecting Widgets
@cindex widget browser
-There is a separate package to browse widgets. This is intended to help
-programmers who want to examine the content of a widget. The browser
-shows the value of each keyword, but uses links for certain keywords
-such as @samp{:parent}, which avoids printing cyclic structures.
+There is a separate package to browse widgets, in
+@samp{wid-browse.el}. This is intended to help programmers who want
+to examine the content of a widget. The browser shows the value of
+each keyword, but uses links for certain keywords such as
+@samp{:parent}, which avoids printing cyclic structures.
@deffn Command widget-browse @var{widget}
Create a widget browser for @var{widget}.
+
When called interactively, prompt for @var{widget}.
@end deffn
@deffn Command widget-browse-other-window @var{widget}
Create a widget browser for @var{widget} and show it in another window.
+
When called interactively, prompt for @var{widget}.
@end deffn
@deffn Command widget-browse-at @var{pos}
Create a widget browser for the widget at @var{pos}.
+
When called interactively, use the position of point.
@end deffn
+In addition, there's a function to describe the widget at point.
+
+@deffn Command widget-describe &optional widget-or-pos
+Describe the widget at point.
+
+When called from Lisp, @var{widget-or-pos} might be the widget to
+describe or a buffer position where a widget is present. If
+@var{widget-or-pos} is @code{nil}, the widget to describe is the
+widget at point.
+
+This command sets up a help buffer for providing information about the
+widget, mainly its @code{:action} and @code{:mouse-down-action}
+functions, and provides links to describe it in more detail using the
+@code{widget-browse} commands described above.
+@end deffn
+
@node Widget Minor Mode
@chapter Widget Minor Mode
@cindex widget minor mode
@@ -1740,14 +2964,24 @@ Keymap used in @code{widget-minor-mode}.
@chapter Utilities
@cindex utility functions for widgets
+Here we describe some utility functions that don't really have a place
+earlier in this manual.
+
@defun widget-prompt-value widget prompt [ value unbound ]
Prompt for a value matching @var{widget}, using @var{prompt}.
The current value is assumed to be @var{value}, unless @var{unbound} is
non-@code{nil}.
+
+Converts @var{widget} before prompting, and for prompting it uses the
+@code{:prompt-value} function. This function returns the user
+``answer'', and it's an error if that answer doesn't match the widget,
+as with the @code{:match} function.
+
+If the answer matches the widget, returns the answer.
@end defun
@defun widget-get-sibling widget
-Get the item which @var{widget} is assumed to toggle.
+Get the item which @var{widget} should toggle.
This is only meaningful for radio buttons or checkboxes in a list.
@end defun
@@ -1773,6 +3007,142 @@ the form (@var{name} . @var{value}) (i.e., the simplified format),
then the return value is the @var{value} of the chosen element.
@end defun
+@defun widget-image-find image
+Create a graphical button from @var{image}, an image or a file name
+sans extension.
+
+If @var{image} is a file name, the file should be in
+@code{widget-image-directory}, or in a place where @code{find-image}
+will find it.
+@end defun
+
+@defun widget-image-insert widget tag image
+As part of @var{widget}, insert the text @var{tag} or, if supported,
+the image @var{image}.
+
+@var{image} should be as described in @code{widget-image-find}.
+@end defun
+
+@defun widget-echo-help pos
+Display help-echo text for the widget at @var{pos}.
+
+Uses the value of @code{:help-echo}. If it is a function, it calls it
+to get a string. Otherwise, it @code{eval}s it.
+@end defun
+
+@node Customization
+@chapter Customization
+This chapter is about the customization options for the Widget
+library, for the end user.
+
+@deffn Face widget-field-face
+Face used for other editing fields.
+@end deffn
+
+@deffn Face widget-button-face
+Face used for buttons.
+@end deffn
+
+@defopt widget-mouse-face
+Face used for highlighting a button when the mouse pointer moves
+across it.
+
+The default value is @code{highlight}.
+@end defopt
+
+@defopt widget-image-directory
+Directory where Widget should look for images.
+
+Widget will look here for a file with the same name as specified for the
+image, with either a @file{.xpm} (if supported) or @file{.xbm} extension.
+@end defopt
+
+@defopt widget-image-enable
+If non-@code{nil}, allow images to appear on displays where they are supported.
+@end defopt
+
+@defopt widget-image-conversion
+An alist to convert symbols from image formats to file name suffixes.
+
+Each element is a cons cell (@var{format} . @var{suffix}), where
+@var{format} is a symbol that represents an image format and
+@var{suffix} is its correspondent suffix.
+@end defopt
+
+@defopt widget-button-prefix
+String to prefix buttons.
+@end defopt
+
+@defopt widget-button-suffix
+String to suffix buttons.
+@end defopt
+
+@defopt widget-push-button-prefix
+String to prefix push buttons.
+@end defopt
+
+@defopt widget-push-button-suffix
+String to suffix push buttons.
+@end defopt
+
+@defopt widget-link-prefix
+String to prefix links.
+@end defopt
+
+@defopt widget-link-suffix
+String to suffix links.
+@end defopt
+
+@defopt widget-choice-toggle
+If non-@code{nil}, toggle when there are just two options.
+
+By default, its value is @code{nil}.
+@end defopt
+
+@defopt widget-documentation-links
+If non-@code{nil}, add hyperlinks to documentation strings.
+@end defopt
+
+@defopt widget-documentation-link-regexp
+A regexp that matches potential links in documentation strings. The
+link itself should match to the first group.
+@end defopt
+
+@defopt widget-documentation-link-p
+A predicate function to test if a string is useful as a link. The
+function is called with one argument, a string, and should return
+non-@code{nil} if there should be a link for that string.
+
+By default, the value is @code{intern-soft}.
+@end defopt
+
+@defopt widget-documentation-link-type
+A symbol that represents a widget type to use for links in
+documentation strings.
+
+By default, the value is @code{documentation-link}.
+@end defopt
+
+@defopt widget-menu-max-size
+Maximum size for a popup menu. By default, its value is 40.
+
+If a function ask you to choose from a menu that is larger than this
+value, it will use the minibuffer.
+@end defopt
+
+@defopt widget-menu-max-shortcuts
+Largest number of items for which it works to choose one with a
+character.
+
+For a larger number, use the minibuffer.
+@end defopt
+
+@defopt widget-menu-minibuffer-flag
+Whether to use the minibuffer to ask for a choice.
+
+If @code{nil}, the default, read a single character.
+@end defopt
+
@node Widget Wishlist
@chapter Wishlist
@cindex todo
@@ -1809,15 +3179,6 @@ Find a way to disable mouse highlight for inactive widgets.
Find a way to make glyphs look inactive.
@item
-Add @code{property-list} widget.
-
-@item
-Add @code{association-list} widget.
-
-@item
-Add @code{key-binding} widget.
-
-@item
Add @code{widget} widget for editing widget specifications.
@item
diff --git a/doc/misc/wisent.texi b/doc/misc/wisent.texi
index 2d9fedadcc5..9738d790259 100644
--- a/doc/misc/wisent.texi
+++ b/doc/misc/wisent.texi
@@ -24,7 +24,7 @@
@c %**end of header
@copying
-Copyright @copyright{} 1988--1993, 1995, 1998--2004, 2007, 2012--2023
+Copyright @copyright{} 1988--1993, 1995, 1998--2004, 2007, 2012--2024
Free Software Foundation, Inc.
@c Since we are both GNU manuals, we do not need to ack each other here.
@@ -383,7 +383,8 @@ On the other hand, @var{precedence} explicitly assign the precedence
level of the given terminal to a rule.
@cindex semantic actions
-@item @anchor{action}action
+@anchor{action}
+@item action
An action is an optional Emacs Lisp function call, like this:
@code{(identity $1)}
diff --git a/doc/misc/woman.texi b/doc/misc/woman.texi
index 32543b9e48d..ecef81996ec 100644
--- a/doc/misc/woman.texi
+++ b/doc/misc/woman.texi
@@ -15,7 +15,7 @@
This file documents WoMan: A program to browse Unix manual pages ``W.O.
(without) man''.
-Copyright @copyright{} 2001--2023 Free Software Foundation, Inc.
+Copyright @copyright{} 2001--2024 Free Software Foundation, Inc.
@quotation
Permission is granted to copy, distribute and/or modify this document
diff --git a/etc/AUTHORS b/etc/AUTHORS
index 27d01ed9eb9..5fc54f1909f 100644
--- a/etc/AUTHORS
+++ b/etc/AUTHORS
@@ -280,6 +280,8 @@ Amin Bandali: changed erc.el erc.texi erc-backend.el erc-button.el
Amos Bird: changed xfns.c
+Amritpal Singh: changed decompress.c
+
Anand Mitra: changed gnus-sum.el
Anders Holst: wrote hippie-exp.el
@@ -296,9 +298,9 @@ Anders Waldenborg: changed emacsclient.c
Andrea Corallo: wrote comp-cstr-tests.el comp-cstr.el comp-tests.el
comp.el
and changed comp.c pdumper.c lread.c bytecomp.el startup.el configure.ac
- comp.h loadup.el lisp.h data.c alloc.c emacs.c .gitlab-ci.yml
- cl-macs.el elisp-mode.el nadvice.el comp-test-funcs.el lisp/Makefile.in
- subr.el Makefile.in advice.el and 70 other files
+ comp.h loadup.el lisp.h data.c elisp-mode.el alloc.c emacs.c subr.el
+ .gitlab-ci.yml cl-macs.el nadvice.el comp-test-funcs.el
+ lisp/Makefile.in Makefile.in advice.el and 70 other files
André A. Gomes: changed ispell.el
@@ -535,6 +537,8 @@ Aubrey Jaffer: changed info.el unexelf.c
August Feng: changed bookmark.el
+Augustin Chéneau: changed treesit.el
+
Augusto Stoffel: co-wrote ansi-osc.el
and changed progmodes/python.el isearch.el eglot.el comint.el eldoc.el
project.el README.md font-lock.el man.el misc.texi modes.texi
@@ -578,8 +582,8 @@ Bartosz Duszel: changed allout.el bib-mode.el cc-cmds.el hexl.el icon.el
Basil L. Contovounesios: changed simple.el subr.el message.el eww.el
modes.texi custom.el text.texi bibtex.el gnus-sum.el internals.texi
- customize.texi display.texi files.texi gnus-group.el gnus-win.el
- gnus.texi gravatar.el js.el json.el map.el shr.el and 345 other files
+ js.el customize.texi display.texi files.texi gnus-group.el gnus-win.el
+ gnus.texi gravatar.el json.el map.el shr.el and 345 other files
Bastian Beischer: changed semantic/complete.el calc-yank.el include.el
mru-bookmark.el refs.el senator.el
@@ -702,9 +706,9 @@ Bob Olson: co-wrote cperl-mode.el
Bob Rogers: wrote ietf-drums-date-tests.el ietf-drums-date.el
ietf-drums-tests.el
-and changed ietf-drums.el vc-dir.el vc-svn.el cperl-mode.el diff.el
- ewoc.el ffap.el files.el maintaining.texi sql.el thingatpt.el
- time-date.el vc.el vc1-xtra.texi
+and changed ietf-drums.el vc-dir.el time-date.el vc-svn.el cperl-mode.el
+ diff.el ewoc.el ffap.el files.el maintaining.texi os.texi sql.el
+ thingatpt.el vc.el vc1-xtra.texi
Bob Weiner: changed info.el quail.el dframe.el etags.c rmail.el
rmailsum.el speedbar.el
@@ -1014,6 +1018,8 @@ Christopher Wellons: changed emacs-lisp/cl-lib.el hashcash.el
Christophe Troestler: changed gnus-icalendar.el epg.el newcomment.el
+Christoph Göttschkes: changed make-mode.el
+
Christoph Scholtes: changed README.W32 progmodes/python.el stdint.h
INSTALL maintaining.texi INSTALL.REPO admin.el bookmark.el
configure.bat control.texi cua-base.el help-mode.el help.el ibuffer.el
@@ -1158,7 +1164,7 @@ Daniele Nicolodi: changed url-http.el
Daniel Fleischer: changed TUTORIAL browse-url.el startup.el
-Daniel Freeman: changed eglot.el eglot.texi
+Daniel Freeman: changed eglot.el js.el eglot.texi
Daniel Gröber: changed rxvt.el
@@ -1190,7 +1196,7 @@ Daniel Martín: changed c-ts-mode.el nsterm.m shortdoc.el ns-win.el
simple.el diff-mode-tests.el erc.texi files.el files.texi indent.erts
msdos-xtra.texi progmodes/python.el search.texi .lldbinit basic.texi
c-ts-mode-tests.el cmacexp.el compilation.txt compile-tests.el
- compile.texi configure.ac and 45 other files
+ compile.texi configure.ac and 46 other files
Daniel McClanahan: changed lisp-mode.el
@@ -1316,7 +1322,7 @@ David Edmondson: changed message.el erc.el mml2015.el process.c
gnus-cite.el gnus-cloud.el gnus.texi imap.el mm-uu.el mm-view.el
nnfolder.el nnimap.el nnml.el rcirc.el shr.el
-Davide Masserut: changed bindings.el sh-script.el basic.texi
+Davide Masserut: changed bindings.el sh-script.el Makefile.in basic.texi
dictionary.el eglot.el faces.el go-ts-mode-tests.el go-ts-mode.el
indent.erts
@@ -1420,8 +1426,8 @@ David Ponce: wrote bovine/grammar.el cedet.el comp.el java-tags.el
and co-wrote util-modes.el
and changed w32menu.c w32term.c close.png close.xpm empty.png empty.xpm
end-guide.png end-guide.xpm files.el guide.png guide.xpm handle.png
- handle.xpm keyboard.c leaf.png leaf.xpm no-guide.png no-guide.xpm
- no-handle.png no-handle.xpm open.png and 22 other files
+ handle.xpm image.el keyboard.c leaf.png leaf.xpm no-guide.png
+ no-guide.xpm no-handle.png no-handle.xpm and 22 other files
David Raynes: changed ns-win.el
@@ -1496,7 +1502,7 @@ Detlev Zundel: wrote re-builder.el
and changed buffer.c
Devon Sean McCullough: changed url-http.el buff-menu.el comint.el
- ns-win.el
+ iso-transl.el ns-win.el
Dhruva Krishnamurthy: changed emacsclient.c fontset.c image.c sound.c
w32proc.c
@@ -1660,9 +1666,9 @@ Eli Zaretskii: wrote [bidirectional display in xdisp.c]
chartab-tests.el coding-tests.el etags-tests.el rxvt.el tty-colors.el
and co-wrote help-tests.el
and changed xdisp.c display.texi w32.c msdos.c simple.el w32fns.c
- files.el fileio.c keyboard.c emacs.c text.texi w32term.c configure.ac
+ files.el fileio.c keyboard.c emacs.c text.texi configure.ac w32term.c
dispnew.c frames.texi w32proc.c files.texi xfaces.c window.c
- dispextern.h lisp.h and 1330 other files
+ dispextern.h lisp.h and 1334 other files
Eliza Velasquez: changed server.el
@@ -1808,7 +1814,7 @@ Ernesto Alfonso: changed simple.el
E Sabof: changed hi-lock.el image-dired.el
-Eshel Yaron: changed eglot.el eww.el
+Eshel Yaron: changed eglot.el emacs.texi eww.el indent.texi
Espen Skoglund: wrote pascal.el
@@ -1877,10 +1883,8 @@ and changed minibuf.c esh-var.el minibuf.texi mouse.el package.el rect.el
edebug.el em-dirs.el eshell-tests.el eww.el fileio-tests.el fileio.c
files.texi gamegrid.el keyboard.c and 8 other files
-Felician Nemeth: changed rmc.el
-
Felicián Németh: changed eglot.el EGLOT-NEWS README.md eglot-tests.el
- project.el xref.el
+ project.el rmc.el xref.el
Felipe Ochoa: changed faces.el js.el paren.el
@@ -2154,12 +2158,10 @@ and changed tar-mode.el
Greg Minshall: changed eldoc.el
-Gregoire Jadi: changed proced.el
-
Grégoire Jadi: changed org.texi configure.ac emacsgtkfixed.c keyboard.c
rcirc.el xwidget.c xwidget.el Makefile.in bibtex-tests.el bibtex.el
cl-generic.el dispextern.h dispnew.c emacs.c latin-post.el lisp.h
- ob-core.el org-id.el org.el print.c reporter.el and 8 other files
+ ob-core.el org-id.el org.el print.c proced.el and 9 other files
Gregorio Gervasio, Jr.: changed gnus-sum.el
@@ -2342,7 +2344,8 @@ Igor Kuzmin: wrote cconv.el
Igor Saprykin: changed ftfont.c
Ihor Radchenko: wrote org-fold-core.el org-fold.el org-persist.el
-and changed ox.el fns.c help-mode.el oc.el org-element.el
+and changed ox.el fns.c emacsclient.desktop help-mode.el oc.el
+ org-element.el
Iku Iwasa: changed auth-source-pass-tests.el auth-source-pass.el
@@ -2504,7 +2507,7 @@ James TD Smith: changed org.el org-colview.el org-clock.el
org-remember.el org-plot.el org-agenda.el org-compat.el org-habit.el
org.texi
-James Thomas: changed quail/indian.el gnus-msg.el ind-util.el
+James Thomas: changed quail/indian.el gnus-msg.el ind-util.el nnmail.el
James Troup: changed gnus-sum.el
@@ -2545,10 +2548,8 @@ Jan Seeger: changed ox-publish.el parse-time.el
Jan Stranik: changed ebrowse.c
-Jan Synacek: changed emacs-lisp-intro.texi minibuffer.el mwheel.el
- vc-git.el
-
-Jan Synáček: changed maintaining.texi project.el
+Jan Synáček: changed emacs-lisp-intro.texi maintaining.texi minibuffer.el
+ mwheel.el project.el vc-git.el
Jan Tatarik: wrote gnus-icalendar-tests.el gnus-icalendar.el
and changed gnus-score.el gnus-logic.el
@@ -2686,8 +2687,8 @@ and changed mml-sec.el gnus-util.el message.texi mml-smime.el mml1991.el
Jens Petersen: wrote find-func.el
and changed mule-cmds.el pcmpl-rpm.el
-Jens Schmidt: changed epa.texi plstore.el auth.texi comint.el gnus.texi
- isearch.el ldap.el
+Jens Schmidt: changed plstore.el epa.texi auth.texi comint.el
+ elisp-mode.el epa-file.el epg.el gnus.texi isearch.el ldap.el
Jens Toivo Berger Thielemann: changed word-help.el
@@ -2766,7 +2767,7 @@ Jim Porter: changed eshell.texi esh-cmd.el esh-var-tests.el
esh-util.el eshell-tests-helpers.el em-pred.el esh-arg.el
esh-cmd-tests.el tramp.el em-pred-tests.el em-dirs-tests.el server.el
em-basic.el em-extpipe-tests.el esh-opt-tests.el esh-opt.el
- and 90 other files
+ and 92 other files
Jim Radford: changed gnus-start.el
@@ -2778,12 +2779,13 @@ Jim Wilson: changed alloca.c oldXMenu/Makefile.in
Jin Choi: changed progmodes/python.el
-Jindrich Makovicka: changed eval.c fns.c
-
-Jindřich Makovička: changed pgtkfns.c pgtkselect.c pgtkterm.c
+Jindřich Makovička: changed eval.c fns.c pgtkfns.c pgtkselect.c
+ pgtkterm.c
Jirka Kosek: changed mule.el
+J M: changed csharp-mode.el
+
Joachim Nilsson: changed cc-styles.el
Joachim Reiter: changed org-footnote.el
@@ -2920,7 +2922,7 @@ John Mastro: changed auth-source.el ibuffer.el w32heap.c
John Mongan: changed progmodes/f90.el
-John Muhl: changed calculator.el
+John Muhl: changed calculator.el sqlite-mode.el
John Paul Wallington: changed ibuffer.el ibuf-ext.el subr.el help-fns.el
rmail.el files.el thumbs.el bindings.el fns.c xfns.c arc-mode.el
@@ -3044,7 +3046,7 @@ and changed xterm.c xfns.c keyboard.c screen.c dispnew.c xdisp.c window.c
Joseph M. Kelsey: changed fileio.c skeleton.el
-Joseph Turner: changed package-vc.el
+Joseph Turner: changed package-vc.el subr.el
Josh Elsasser: changed eglot.el README.md configure.ac
@@ -3125,8 +3127,8 @@ Juri Linkov: wrote compose.el emoji.el files-x.el misearch.el
repeat-tests.el replace-tests.el tab-bar-tests.el tab-bar.el
tab-line.el
and changed isearch.el simple.el info.el replace.el dired.el dired-aux.el
- progmodes/grep.el minibuffer.el window.el subr.el vc.el mouse.el
- outline.el diff-mode.el repeat.el image-mode.el files.el menu-bar.el
+ progmodes/grep.el minibuffer.el window.el subr.el vc.el outline.el
+ mouse.el diff-mode.el repeat.el image-mode.el files.el menu-bar.el
search.texi startup.el progmodes/compile.el and 473 other files
Jussi Lahdenniemi: changed w32fns.c ms-w32.h msdos.texi w32.c w32.h
@@ -3387,8 +3389,6 @@ Kishore Kumar: changed terminal.el
Kiso Katsuyuki: changed tab-line.el
-Kjartan Oli Agustsson: changed doc-view.el
-
Kjartan Óli Ágústsson: changed doc-view.el
Klaus Straubinger: changed url-http.el url-history.el pcmpl-rpm.el
@@ -3666,7 +3666,7 @@ Manuel Giraud: changed vc.el ox-html.el bookmark.el image-dired.el
longlines.el ox-publish.el keyboard.c paragraphs.el simple.el
basic.texi battery.el bookmark-tests.el cus-start.el dired.texi
dispextern.h easymenu.el find-dired.el ibuf-ext.el ibuf-macs.el
- idlwave.el image.c and 11 other files
+ idlwave.el image-mode.el and 12 other files
Manuel Gómez: changed speedbar.el
@@ -3935,6 +3935,8 @@ Matthew Mundell: changed calendar.texi diary-lib.el files.texi
Matthew Newton: changed imenu.el
+Matthew Tromp: changed ielm.el
+
Matthew White: changed buffer.c bookmark-tests.el bookmark.el
test-list.bmk
@@ -3988,7 +3990,7 @@ Mauro Aranda: changed wid-edit.el cus-edit.el custom.el wid-edit-tests.el
widget.texi perl-mode.el custom-tests.el checkdoc-tests.el checkdoc.el
cperl-mode-tests.el cus-edit-tests.el cus-theme.el customize.texi
files.texi gnus.texi octave.el pong.el align.el auth-source.el
- autorevert.el button.el and 45 other files
+ autorevert.el base.el and 56 other files
Maxime Edouard Robert Froumentin: changed gnus-art.el mml.el
@@ -4011,8 +4013,8 @@ and co-wrote tramp-cache.el tramp-sh.el tramp.el
and changed tramp.texi tramp-adb.el trampver.el trampver.texi dbusbind.c
files.el ange-ftp.el files.texi file-notify-tests.el dbus.texi
gitlab-ci.yml autorevert.el tramp-fish.el kqueue.c Dockerfile.emba
- os.texi tramp-gw.el test/Makefile.in README shell.el files-x.el
- and 308 other files
+ os.texi tramp-gw.el test/Makefile.in README shell.el files-tests.el
+ and 309 other files
Michael Ben-Gershon: changed acorn.h configure.ac riscix1-1.h riscix1-2.h
unexec.c
@@ -4453,6 +4455,8 @@ and changed rsz-mini.el emacs-buffer.gdb comint.el files.el Makefile
Noah Lavine: changed tramp.el
+Noah Peart: changed treesit.el
+
Noah Swainland: changed calc.el goto-addr.el misc.texi
Noam Postavsky: changed progmodes/python.el lisp-mode.el bytecomp.el
@@ -4795,9 +4799,10 @@ Philipp Stephani: wrote callint-tests.el checkdoc-tests.el
cl-preloaded-tests.el ediff-diff-tests.el eval-tests.el ido-tests.el
lread-tests.el mouse-tests.el startup-tests.el xt-mouse-tests.el
and changed emacs-module.c emacs-module-tests.el configure.ac json.c
- process.c eval.c internals.texi json-tests.el process-tests.el alloc.c
- emacs-module.h.in emacs.c lread.c nsterm.m pdumper.c bytecomp.el lisp.h
- seccomp-filter.c callproc.c cl-macs.el gtkutil.c and 188 other files
+ process.c eval.c internals.texi json-tests.el process-tests.el
+ pdumper.c alloc.c emacs-module.h.in emacs.c lread.c nsterm.m
+ bytecomp.el lisp.h seccomp-filter.c callproc.c cl-macs.el gtkutil.c
+ and 188 other files
Phillip Dixon: changed eglot.el
@@ -5092,7 +5097,7 @@ and changed configure.ac process.c blocks.awk keymap.el font.c
network-stream-tests.el processes.texi custom.texi emoji-zwj.awk
ftfont.c gtkutil.c process-tests.el unicode vc-git.el terminal.c
char-fold.el gnutls.el keymaps.texi network-stream.el nsm.el nsterm.m
- and 192 other files
+ and 193 other files
Robert Thorpe: changed cus-start.el indent.el rmail.texi
@@ -5154,6 +5159,8 @@ Ross Donaldson: changed progmodes/python.el
Ross Patterson: co-wrote org-protocol.el
+Ross Timson: changed eglot.el
+
Roy Hashimoto: changed mm-view.el
Roy Liu: changed ns-win.el
@@ -5324,6 +5331,8 @@ Sebastian Kremer: wrote dired-aux.el dired.el ls-lisp.el
and co-wrote dired-x.el find-dired.el
and changed add-log.el
+Sebastian Miele: changed strings.texi
+
Sebastian Reuße: changed find-dired.el
Sebastian Rose: co-wrote org-protocol.el
@@ -5515,10 +5524,10 @@ Stefan Kangas: wrote bookmark-tests.el cal-julian-tests.el
studly-tests.el tabify-tests.el time-tests.el timezone-tests.el
underline-tests.el uudecode-tests.el wallpaper.el warnings-tests.el
and co-wrote help-tests.el keymap-tests.el
-and changed image-dired.el package.el efaq.texi cperl-mode.el subr.el
- checkdoc.el help.el bookmark.el simple.el dired.el files.el dired-x.el
- gnus.texi keymap.c image-mode.el erc.el ediff-util.el speedbar.el
- browse-url.el bytecomp-tests.el bytecomp.el and 1657 other files
+and changed image-dired.el efaq.texi package.el cperl-mode.el help.el
+ subr.el checkdoc.el bookmark.el simple.el dired.el files.el gnus.texi
+ dired-x.el keymap.c image-mode.el erc.el ediff-util.el speedbar.el
+ woman.el browse-url.el bytecomp-tests.el and 1678 other files
Stefan Merten: co-wrote rst.el
@@ -5571,7 +5580,7 @@ and co-wrote todo-mode.el
and changed wdired.el todo-mode.texi wdired-tests.el diary-lib.el
dired.el dired-tests.el doc-view.el files.el info.el minibuffer.el
outline.el todo-test-1.todo allout.el eww.el find-dired.el frames.texi
- hl-line.el menu-bar.el mouse.el otodo-mode.el subr.el
+ hl-line.el menu-bar.el mouse.el otodo-mode.el simple.el
and 63 other files
Stephen C. Gilardi: changed configure.ac
@@ -5781,7 +5790,7 @@ Thamer Mahmoud: changed arabic.el
Theodore Jump: changed makefile.nt makefile.def w32-win.el w32faces.c
Theodor Thornhill: changed typescript-ts-mode.el java-ts-mode.el
- c-ts-mode.el eglot.el js.el csharp-mode.el css-mode.el project.el
+ c-ts-mode.el eglot.el csharp-mode.el js.el css-mode.el project.el
json-ts-mode.el treesit.el c-ts-common.el eglot-tests.el EGLOT-NEWS
README.md c-ts-mode-tests.el compile-tests.el go-ts-mode.el
indent-bsd.erts indent.erts maintaining.texi mwheel.el
@@ -5833,6 +5842,8 @@ and changed soap-inspect.el eudc.el eudc-vars.el eudc.texi ldap.el
README authinfo bbdb diary-lib.el display.texi eudc-capf.el
and 8 other files
+Thomas Hilke: changed sqlite-mode.el
+
Thomas Horsley: changed cxux-crt0.s cxux.h cxux7.h emacs.c nh3000.h
nh4000.h simple.el sysdep.c xterm.c
@@ -6075,8 +6086,8 @@ Ulrich Leodolter: changed w32proc.c
Ulrich Müller: changed configure.ac calc-units.el
emacsclient-mail.desktop lib-src/Makefile.in src/Makefile.in version.el
Makefile.in doctor.el emacs.1 files.el gamegrid.el gud.el server.el
- ChgPane.c ChgSel.c HELLO INSTALL XMakeAssoc.c authors.el bytecomp.el
- case-table.el and 44 other files
+ ChgPane.c ChgSel.c HELLO INSTALL XMakeAssoc.c authors.el bindings.el
+ bytecomp.el and 45 other files
Ulrich Neumerkel: changed xterm.c
@@ -6151,7 +6162,8 @@ Vincent Bernat: changed gnus-int.el nnimap.el xsettings.c
Vincent Del Vecchio: changed info.el mh-utils.el
-Vincenzo Pupillo: changed js.el typescript-ts-mode.el java-ts-mode.el
+Vincenzo Pupillo: changed cmake-ts-mode.el js.el typescript-ts-mode.el
+ java-ts-mode.el
Vince Salvino: changed msdos.texi w32.c w32fns.c
diff --git a/etc/CALC-NEWS b/etc/CALC-NEWS
index 8fd5365011f..06d4a3fc948 100644
--- a/etc/CALC-NEWS
+++ b/etc/CALC-NEWS
@@ -1,4 +1,4 @@
-Copyright (C) 2001-2023 Free Software Foundation, Inc.
+Copyright (C) 2001-2024 Free Software Foundation, Inc.
See the end of the file for license conditions.
Calc is an advanced desk calculator for GNU Emacs.
@@ -856,7 +856,7 @@ For changes in Emacs 23.1 and later, see the main Emacs NEWS file.
** Fixed obsolete trail tags gsmp, gneg, ginv to jsmp, jneg, jinv.
-** Fixed some errors and made improvements in units table [Ulrich Mueller].
+** Fixed some errors and made improvements in units table [Ulrich Müller].
* Version 1.07:
diff --git a/etc/ChangeLog.1 b/etc/ChangeLog.1
index 68c15fc6e69..0c7e432bba9 100644
--- a/etc/ChangeLog.1
+++ b/etc/ChangeLog.1
@@ -1778,7 +1778,7 @@
* refcards/orgcard.tex: Cleanup.
-2010-11-27 Ulrich Mueller <ulm@gentoo.org>
+2010-11-27 Ulrich Müller <ulm@gentoo.org>
* HELLO: Add ancient Greek (Bug#7418).
@@ -2497,7 +2497,7 @@
* NEWS: New function `locate-user-emacs-file'.
-2008-10-18 Ulrich Mueller <ulm@gentoo.org>
+2008-10-18 Ulrich Müller <ulm@gentoo.org>
* MACHINES: Add section for SuperH.
@@ -2914,7 +2914,7 @@
emacs48_mac.png, emacs256_mac.png, and emacs512_mac.png,
respectively.
-2007-12-08 Ulrich Mueller <ulm@gentoo.org> (tiny change)
+2007-12-08 Ulrich Müller <ulm@gentoo.org> (tiny change)
* emacs.desktop (Exec, Icon, Categories): Fix entries.
@@ -6891,7 +6891,7 @@
;; coding: utf-8
;; End:
- Copyright (C) 1993-1999, 2001-2023 Free Software Foundation, Inc.
+ Copyright (C) 1993-1999, 2001-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/etc/DEBUG b/etc/DEBUG
index 6455152bd50..181e24e0057 100644
--- a/etc/DEBUG
+++ b/etc/DEBUG
@@ -1,6 +1,6 @@
Debugging GNU Emacs
-Copyright (C) 1985, 2000-2023 Free Software Foundation, Inc.
+Copyright (C) 1985, 2000-2024 Free Software Foundation, Inc.
See the end of the file for license conditions.
** Preliminaries
@@ -472,6 +472,16 @@ and, assuming that "xtype" says that args[0] is a symbol:
** Debugging Emacs redisplay problems
+The Emacs display code includes special debugging code, but it is normally
+disabled. Configuring Emacs with --enable-checking='yes,glyphs' enables it.
+
+Building Emacs like that activates many assertions which scrutinize display
+code operation more than Emacs does normally. (To see the code which tests
+these assertions, look for calls to the 'eassert' macros.) Any assertion that
+is reported to fail should be investigated. Redisplay problems that cause
+aborts or segfaults in production builds of Emacs will many times be caught by
+these assertions before they cause a crash.
+
If you configured Emacs with --enable-checking='glyphs', you can use redisplay
tracing facilities from a running Emacs session.
@@ -481,21 +491,18 @@ code paths taken by the display engine under various conditions, especially if
some redisplay optimizations produce wrong results. (You know that redisplay
optimizations might be involved if "M-x redraw-display RET", or even just
typing "M-x", causes Emacs to correct the bad display.) Since the cursor
-blinking feature triggers periodic redisplay cycles, we recommend disabling
-'blink-cursor-mode' before invoking 'trace-redisplay', so that you have less
-clutter in the trace. You can also have up to 30 last trace messages dumped to
-standard error by invoking the 'dump-redisplay-history' command.
+blinking feature and ElDoc trigger periodic redisplay cycles, we recommend
+disabling 'blink-cursor-mode' and 'global-eldoc-mode' before invoking
+'trace-redisplay', so that you have less clutter in the trace. You can also
+have up to 30 last trace messages dumped to standard error by invoking the
+'dump-redisplay-history' command.
To find the code paths which were taken by the display engine, search xdisp.c
for the trace messages you see.
The command 'dump-glyph-matrix' is useful for producing on standard error
stream a full dump of the selected window's glyph matrix. See the function's
-doc string for more details. If you are debugging redisplay issues in
-text-mode frames, you may find the command 'dump-frame-glyph-matrix' useful.
-
-Other commands useful for debugging redisplay are 'dump-glyph-row' and
-'dump-tool-bar-row'.
+doc string for more details.
If you run Emacs under GDB, you can print the contents of any glyph matrix by
just calling that function with the matrix as its argument. For example, the
@@ -507,13 +514,11 @@ whose pointer is in 'w':
(The second argument 2 tells dump_glyph_matrix to print the glyphs in
a long form.)
-The Emacs display code includes special debugging code, but it is normally
-disabled. Configuring Emacs with --enable-checking='yes,glyphs' enables it.
+If you are debugging redisplay issues in text-mode frames, you may find the
+command 'dump-frame-glyph-matrix' useful.
-Building Emacs like that activates many assertions which scrutinize
-display code operation more than Emacs does normally. (To see the
-code which tests these assertions, look for calls to the 'eassert'
-macros.) Any assertion that is reported to fail should be investigated.
+Other commands useful for debugging redisplay are 'dump-glyph-row' and
+'dump-tool-bar-row'.
When you debug display problems running emacs under X, you can use
the 'ff' command to flush all pending display updates to the screen.
@@ -535,36 +540,40 @@ object of the relevant type as argument. For example, 'pgrowx' dumps all
glyphs in its argument, which must be of type 'struct glyph_row'.
Since redisplay is performed by Emacs very frequently, you need to place your
-breakpoints cleverly to avoid hitting them all the time, when the issue you are
-debugging did not (yet) happen. Here are some useful techniques for that:
-
- . Put a breakpoint at 'Fredraw_display' before running Emacs. Then do
- whatever is required to reproduce the bad display, and invoke "M-x
- redraw-display". The debugger will kick in, and you can set or enable
- breakpoints in strategic places, knowing that the bad display will be
+breakpoints cleverly to avoid hitting them all the time, when the issue you
+are debugging did not (yet) happen. Here are some useful techniques for that:
+
+ . Put a breakpoint at 'Frecenter' or 'Fredraw_display' before running Emacs.
+ Then do whatever is required to reproduce the bad display, and type C-l or
+ "M-x redraw-display" just before invoking the last action that reproduces
+ the bug. The debugger will kick in, and you can set or enable breakpoints
+ in strategic places, knowing that the bad display will happen soon. With a
+ breakpoint at 'Fredraw_display', you can even reproduce the bug and invoke
+ "M-x redraw-display" afterwards, knowing that the bad display will be
redrawn from scratch.
- . For debugging incorrect cursor position, a good place to put a breakpoint is
- in 'set_cursor_from_row'. The first time this function is called as part of
- 'redraw-display', Emacs is redrawing the minibuffer window, which is usually
- not what you want; type "continue" to get to the call you want. In general,
- always make sure 'set_cursor_from_row' is called for the right window and
- buffer by examining the value of w->contents: it should be the buffer whose
- display you are debugging.
+ . For debugging incorrect cursor position, a good place to put a breakpoint
+ is in 'set_cursor_from_row'. The first time this function is called as
+ part of 'redraw-display', Emacs is redrawing the minibuffer window, which
+ is usually not what you want; type "continue" to get to the call you want.
+ In general, always make sure 'set_cursor_from_row' is called for the right
+ window and buffer by examining the value of w->contents: it should be the
+ buffer whose display you are debugging.
. 'set_cursor_from_row' is also a good place to look at the contents of a
screen line (a.k.a. "glyph row"), by means of the 'pgrow' GDB command. Of
course, you need first to make sure the cursor is on the screen line which
- you want to investigate. If you have set a breakpoint in 'Fredraw_display',
- as advised above, move cursor to that line before invoking 'redraw-display'.
+ you want to investigate. If you have set a breakpoint in 'Fredraw_display'
+ or 'Frecenter', as advised above, move cursor to that line before invoking
+ these commands.
. If the problem happens only at some specific buffer position or for some
- specific rarely-used character, you can make your breakpoints conditional on
- those values. The display engine maintains the buffer and string position
- it is processing in the it->current member; for example, the buffer
- character position is in it->current.pos.charpos. Most redisplay functions
- accept a pointer to a 'struct it' object as their argument, so you can make
- conditional breakpoints in those functions, like this:
+ specific rarely-used character, you can make your breakpoints conditional
+ on those values. The display engine maintains the buffer and string
+ position it is processing in the it->current member; for example, the
+ buffer character position is in it->current.pos.charpos. Most redisplay
+ functions accept a pointer to a 'struct it' object as their argument, so
+ you can make conditional breakpoints in those functions, like this:
(gdb) break x_produce_glyphs if it->current.pos.charpos == 1234
@@ -578,6 +587,16 @@ debugging did not (yet) happen. Here are some useful techniques for that:
GET_FROM_IMAGE for displaying an image, etc. See 'enum it_method' in
dispextern.h for the full list of values.
+ . When the display engine is processing a 'display' text property or an
+ overlay string, it pushes on the iterator stack the state variables
+ describing its iteration of buffer text, then reinitializes the iterator
+ object for processing the property or overlay. The it->sp ("stack
+ pointer") member, if it is greater than zero, means the iterator's stack
+ was pushed at least once. You can therefore condition your breakpoints on
+ the value of it->sp being positive or being of a certain positive value, to
+ debug display problems that happen only with display properties or
+ overlays.
+
** Debugging problems with native-compiled Lisp.
When you encounter problems specific to native-compilation of Lisp, we
@@ -586,7 +605,17 @@ recommend to follow the procedure below to try to identify the cause:
. Reduce the problematic .el file to the minimum by bisection, and
try identifying the function that causes the problem.
- . Reduce the problematic function to the minimal code that still
+ . Try natively compiling the problematic file with
+ 'native-comp-speed' set to 1 or even zero. If doing that solves
+ the problem, you can use
+
+ (declare (speed 1))
+
+ at the beginning of the body of suspected function(s) to change
+ 'native-comp-speed' only for those functions -- this could help you
+ identify the function(s) which cause(s) the problem.
+
+ . Reduce the problematic function(s) to the minimal code that still
reproduces the problem.
. Study the problem's artifacts, like Lisp or C backtraces, to try
@@ -1123,7 +1152,7 @@ one to upload, like so:
../java/debug.sh --gdbserver /path/to/gdbserver
This Gdbserver should be statically linked or compiled using the
-Android NDK, and must target the same architecture as the debugee
+Android NDK, and must target the same architecture as the debugged
Emacs binary. Older versions of the Android NDK (such as r24)
distribute suitable Gdbserver binaries, usually located within
diff --git a/etc/DISTRIB b/etc/DISTRIB
index 359422ae895..66f28858298 100644
--- a/etc/DISTRIB
+++ b/etc/DISTRIB
@@ -1,7 +1,7 @@
-*- text -*-
GNU Emacs availability information
-Copyright (C) 1986-1993, 1995, 1998, 2000-2023 Free Software Foundation,
+Copyright (C) 1986-1993, 1995, 1998, 2000-2024 Free Software Foundation,
Inc.
See the end of the file for license conditions.
diff --git a/etc/EGLOT-NEWS b/etc/EGLOT-NEWS
index 01f0498eb81..1f913f81236 100644
--- a/etc/EGLOT-NEWS
+++ b/etc/EGLOT-NEWS
@@ -1,6 +1,6 @@
Eglot NEWS -*- outline -*-
-Copyright (C) 2018-2023 Free Software Foundation, Inc.
+Copyright (C) 2018-2024 Free Software Foundation, Inc.
See the end of the file for license conditions.
Please send Eglot bug reports to 'bug-gnu-emacs@gnu.org', and Cc (or
@@ -20,6 +20,31 @@ https://github.com/joaotavora/eglot/issues/1234.
* Changes in upcoming Eglot
+
+* Changes in Eglot 1.16 (27/12/2023)
+
+** Code actions can be previewed in diff format
+
+The variable 'eglot-confirm-server-edits' replaces the obsolete
+'eglot-confirm-server-initiated-edits' and brings about a new
+confirmation model for code actions, making it possible to have only
+certain commands require user confirmation. It allows a temporary
+'diff-mode' buffer to display the proposed changes, so the user can
+apply them one by one. See bug#60338.
+
+** Completion sorting has been fixed
+
+In some situations, Eglot was not respecting the completion sort order
+decided by the language server, falling back on the sort order
+determined by the 'flex' completion style instead. See github#1306.
+
+** Improve mouse invocation of code actions
+
+When invoking code actions by middle clicking with the mouse on
+Flymake diagnostics, it was often the case that Eglot didn't request
+code actions correctly and thus no actions were offered to the user.
+This has been fixed. See github#1295.
+
** Optimized file-watching capability
Some servers, like the Pyright language server, issue too many file
@@ -27,12 +52,44 @@ watching requests. This change slightly reduces the number of file
watcher objects requested from the operating system, which can be a
problem, particularly on Mac OS. See github#1228 and github#1226.
-** Fixed "onTypeFormatting" feature
+** Faster, more accurate, event logging
+
+The Eglot events buffer takes advantage of new functionality in
+Jsonrpc 1.23. By default, Lisp-style printing of JSON-RPC message (a
+common cause of performance degradation) is disabled. The full
+original JSON message is presented instead. See new variable
+'eglot-events-buffer-config', which replaces the obsolete
+'eglot-events-buffer-size'.
+
+** 'textdocument/onTypeFormatting' feature has been fixed
For 'newline' commands, Eglot sometimes sent the wrong character code
-to the server. Also made this feature less chatty in the mode-line
+to the server. Also this feature is now less chatty in the mode-line
and messages buffer.
+** Partial fix C-M-i "middle-of-symbol" completions (github#1339)
+
+** Add "Extending Eglot" section to manual
+
+** Fixed Elisp interface 'eglot-lsp-context' (github#1336, github#1337)
+
+** Supports LSP's 'window/showRequest' (bug#62116)
+
+** The self-upgrade command is now called 'eglot-upgrade-eglot'
+
+** Newly added directories also watched (github#1228)
+
+** Send correct ':language-id' for JavaScript server (bug#67150)
+
+** New servers have been added to 'eglot-server-programs'.
+
+- nls (bug#63603)
+- nixd (bug#64214)
+- lexical (bug#65359)
+- terraform-ls (bug#65671)
+- ruff-lsp (bug#67441)
+- uiua (bug#67850)
+
* Changes in Eglot 1.15 (29/4/2023)
diff --git a/etc/ERC-NEWS b/etc/ERC-NEWS
index 94452514e6d..c51b6f05458 100644
--- a/etc/ERC-NEWS
+++ b/etc/ERC-NEWS
@@ -1,6 +1,6 @@
ERC NEWS
-Copyright (C) 2006-2023 Free Software Foundation, Inc.
+Copyright (C) 2006-2024 Free Software Foundation, Inc.
See the end of the file for license conditions.
Please send ERC bug reports to 'bug-gnu-emacs@gnu.org',
@@ -100,7 +100,7 @@ one's optionally accessible from the keyboard, just like any other
side window. Hit '<RET>' over a nick to spawn a "/QUERY" or a
"Lastlog" (Occur) session. See 'erc-nickbar-mode' for more.
-** The option 'erc-timestamp-use-align-to' is more versatile.
+** Option 'erc-timestamp-use-align-to' more versatile.
While this option has always offered to right-align stamps via the
'display' text property, it's now more effective at doing so when set
to a number indicating an offset from the right edge. Users of the
@@ -131,13 +131,6 @@ connectivity before attempting to reconnect in earnest. See option
'erc-server-reconnect-function' and new local module 'services-regain'
(also experimental) to get started.
-** Module 'fill' can add a bit of space between messages.
-On graphical displays, it's now possible to add some breathing room
-around certain messages via the new option 'erc-fill-line-spacing'.
-This is especially handy when using the option 'erc-fill-wrap-merge'
-to omit repeated speaker tags, which can make message boundaries less
-detectable by tired eyes.
-
** Modules rather than their libraries set major-mode keybindings.
To put it another way, simply loading a built-in module's library no
longer modifies 'erc-mode-map'. Instead, modifications occur during
@@ -149,7 +142,7 @@ minor-mode maps, and new third-party modules should do the same.
** Option 'erc-timestamp-format-right' deprecated.
Having to account for this option prevented other ERC modules from
-easily determining what right-hand stamps would look like before
+easily determining what right-sided stamps would look like before
insertion, which is knowledge needed for certain UI decisions. The
way ERC has chosen to address this is imperfect and boils down to
asking users who've customized this option to switch to
@@ -157,6 +150,32 @@ asking users who've customized this option to switch to
that some other solution, like automatic migration, is justified,
please make that known on the bug list.
+** Module 'noncommands' deprecated, replaced by 'command-indicator'.
+Command-line echoing has returned to ERC after a near decade-long
+hiatus. This means you can elect to have ERC leave a trail of (most)
+slash-command input submitted at the prompt, in a manner resembling
+that of a shell or a REPL. The particulars are likely of little
+interest to most users, but the gist is that this functionality was
+removed in 5.3.x (Emacs 24.5) without mention in this document or a
+change log. Everything's mostly been restored, except that the
+feature is now opt-in. The only real gotcha is that related faces and
+options, like 'erc-command-indicator', have moved to the 'erc-goodies'
+library, although their Custom groups remain the same. Add
+'command-indicator' to 'erc-modules' to get started.
+
+** Option 'erc-track-faces-normal-list' slightly more influential.
+This option has always been a source of confusion for users, mainly
+because its influence rode heavily on the makeup of faces in a given
+message. Historically, when a buffer's current mode-line face was a
+member of this option's value, ERC would only swap it out for a fellow
+"normal" if it was absent from the message being processed. Beginning
+with this release, ERC now looks to other ranked and, if necessary,
+unranked "normals" instead of sustaining the same face between
+messages. This was done to better honor the stated purpose of the
+option, which is to provide consistent visual feedback when buffer
+activity occurs. If you experience problems with this development,
+see the compatibility flag 'erc-track-ignore-normal-contenders-p'.
+
** 'erc-button-alist' and 'erc-nick-popup-alist' have evolved slightly.
It's no secret that the 'buttons' module treats potential nicknames
specially. This is perhaps most evident in its treatment of the
@@ -171,6 +190,23 @@ s-expressions, which ERC will continue to honor. Although the default
lineup remains functionally equivalent, its members have all been
updated accordingly.
+** 'erc-track-faces-priority-list' and 'erc-track-faces-normal-list' slimmed.
+These options have been purged of certain 'button'-related face
+combinations. Originally added in ERC 5.3, these combinations
+described the effect of "buttonizing" atop faces added by the 'match'
+module, like '(erc-nick-default-face erc-pal-face)'. However, since
+at least Emacs 27, 'match' has run before 'button' in
+'erc-insert-modify-hook', meaning such permutations aren't possible.
+
+More importantly, users who've customized either of these options
+should update them with the new default value of the option
+'erc-button-nickname-face'. Like 'erc-nick-default-face', which it
+replaces, the new 'erc-button-nick-default-face' is also a "real"
+face. Its sole reason for existing is to make it easier for users and
+modules to distinguish between basic buttonized faces and
+'erc-nick-default-face', which is now reserved to mean the base
+"speaker" face.
+
** Option 'erc-query-on-unjoined-chan-privmsg' restored and renamed.
This option was accidentally removed from the default client in ERC
5.5 and was thus prevented from influencing PRIVMSG routing. It's now
@@ -178,12 +214,40 @@ been restored with a slightly revised role contingent on a few
assumptions explained in its doc string. For clarity, it has been
renamed 'erc-ensure-target-buffer-on-privmsg'.
+** A smarter, more responsive prompt.
+ERC's prompt can be told to respond dynamically to incoming and
+outgoing messages by leveraging the familiar function variant of the
+option 'erc-prompt'. With this release, only predefined functions can
+take full advantage of this new dynamism, but an interface to empower
+third parties with the same possibilities may follow suit. To get
+started, customize 'erc-prompt' to 'erc-prompt-format', and see the
+option of the same name ('erc-prompt-format') for a rudimentary
+templating facility reminiscent of 'erc-mode-line-format'.
+
+** Module 'scrolltobottom' now optionally more aggressive.
+Enabling the experimental option 'erc-scrolltobottom-all' makes ERC
+more vigilant about staking down the input area in all ERC windows.
+And the option's 'relaxed' variant makes ERC's prompt stationary
+wherever it happens to reside instead of forcing it to the bottom of a
+window, meaning new input appears above the prompt, scrolling existing
+messages upward to compensate.
+
** Subtle changes in two fundamental faces.
Users of the default theme may notice that 'erc-action-face' and
'erc-notice-face' now appear slightly less bold on systems supporting
a weight of 'semi-bold'. This was done to make buttons detectable and
to spare users from resorting to tweaking these faces, or options like
-'erc-notice-highlight-type', just to achieve this effect.
+'erc-notice-highlight-type', just to achieve this effect. It's
+currently most prominent in "/ME" messages, where 'erc-action-face'
+sits beneath 'erc-input-face', as well as 'erc-my-nick-face' in the
+speaker portion.
+
+** Fewer nick buttons in QUIT, JOIN, and PART messages.
+Common messages that show a nickname followed by a "userhost" often
+end up with redundant buttons because the nick reappears in or is the
+same as the "~user" portion. ERC now tamps down on this to make
+<TAB>ing around more convenient. To opt out, see the new variable
+'erc-button-highlight-nick-once'.
** Improved interplay between buffer truncation and message logging.
While most of these improvements are subtle, some affect everyday use.
@@ -196,16 +260,79 @@ these changes has been the deprecation of the ancient option
'erc-truncate-buffer-on-save'. Users of the 'log' module can achieve
the same effect by issuing a "/CLEAR" at the prompt.
+** The 'truncate' module no longer enables logging automatically.
+Users expecting 'truncate' to perform logging based on the option
+'erc-enable-logging' need to instead add 'log' to 'erc-modules' for
+continued integration. Under the original design, merely loading the
+library 'erc-log' caused 'truncate' to start writing logs, possibly
+against a user's wishes.
+
+** The function 'erc-echo-timestamp' is now a command.
+The option 'erc-echo-timestamps' (plural) has always enabled the
+contextual printing of timestamps to the echo area when moving between
+messages in an ERC buffer. Similar functionality is now available on
+demand by invoking the newly interactive function 'erc-echo-timestamp'
+atop any message. The new companion option 'erc-echo-timestamp-zone'
+determines the default timezone when not specified with a prefix
+argument.
+
+** Option 'erc-remove-parsed-property' deprecated.
+This option's nil behavior serves no practical purpose yet has the
+potential to degrade the user experience by competing for space with
+forthcoming features powered by next generation extensions. Anyone
+with a legitimate use for this option likely also possesses the
+knowledge to rig up a suitable analog with minimal effort. That said,
+the road to removal is long.
+
+** The 'track' module always ignores date stamps.
+Users of the stamp module who leave 'erc-insert-timestamp-function'
+set to its default of 'erc-insert-timestamp-left-and-right' will find
+that date stamps no longer affect the mode line, even for IRC commands
+not included in 'erc-track-exclude-types'.
+
+** Option 'erc-warn-about-blank-lines' is more informative.
+Enabled by default, this option now produces more useful feedback
+whenever ERC rejects prompt input containing whitespace-only lines.
+When paired with option 'erc-send-whitespace-lines', ERC echoes a
+tally of blank lines padded and trailing blanks culled.
+
+** A context-dependent mode segment in header and mode lines.
+The "%m" specifier has traditionally expanded to a lone "+" in server
+and query buffers and a string containing all switch modes (plus
+"limit" and "key" args) in channel buffers. It now becomes a string
+of user modes in server buffers and disappears completely in query
+buffers. In channels, it's grown to include all letters and their
+possibly truncated arguments, with the exception of stateful list
+modes, like "b".
+
+** In-buffer "status messages" are now a thing.
+The ancient option 'erc-ensure-target-buffer-on-privmsg' has been
+repurposed slightly to express a third state denoted by the symbol
+'status'. It tells ERC to revert to the old default behavior in which
+separate, "pseudo" target buffers for status-prefixed conversing
+co-existed alongside actual target buffers. Instead of this awkward
+arrangement, ERC now acts like other clients by default and inserts
+so-called "status messages" in situ, right between other messages.
+Similar insertion-routing behavior now also applies to CTCP ACTIONs
+directed at status-prefixed channels. Unfortunately, outgoing "/msg
+@#chan hi" messages aren't yet shown in the same fashion, but the
+groundwork has been laid, making such an addition almost trivial.
+
+** An easier way to see channel-membership prefixes on speakers.
+The option 'erc-format-@nick' has been deprecated in favor of the new
+boolean option 'erc-show-speaker-membership-status', a simple switch
+to enable the displaying of status prefixes on the speaker nicks of
+incoming chat messages. Prefixes on your speaker nick for outgoing
+chat messages continue to always be present.
+
** Miscellaneous UX changes.
Some minor quality-of-life niceties have finally made their way to
-ERC. For example, the function 'erc-echo-timestamp' is now
-interactive and can be invoked on any message to view its timestamp in
-the echo area. Fool visibility has become togglable with the new
+ERC. For example, fool visibility has become togglable with the new
command 'erc-match-toggle-hidden-fools'. The 'button' module's
-'erc-button-previous' now moves to the beginning instead of the end of
-buttons. A new command, 'erc-news', can be invoked to visit this very
-file. And the 'irccontrols' module now supports additional colors and
-special handling for "spoilers" (hidden text).
+'erc-button-previous' command now moves to the beginning instead of
+the end of buttons. A new command, 'erc-news', can be invoked to
+visit this very file. And the 'irccontrols' module now supports
+additional colors and special handling for "spoilers" (hidden text).
** Changes in the library API.
@@ -221,55 +348,138 @@ sparingly, and the latter two have only been around for one minor
release cycle, so their removal hopefully won't cause much churn.
*** Some ERC-applied text properties have changed.
-Chiefly, 'rear-sticky' has been replaced by 'erc-command', which
-records the IRC command (or numeric) associated with a message. Less
-impactfully, the value of the 'field' property for ERC's prompt has
-changed from 't' to the more useful 'erc-prompt', although the
-property of the same name has been retained and now has a value of
-'hidden' when disconnected.
+Chiefly, a new set of metadata-oriented properties, the details of
+which should be considered internal, now occupy the first character of
+all inserted messages, including local notices, date stamps, and
+interactive feedback. These properties will likely form the basis for
+a new message-traversal/insertion/deletion API in future versions.
+Less impactfully, the no-op property 'rear-sticky' has been removed,
+and the value of the 'field' property for ERC's prompt has changed
+from 't' to the more useful 'erc-prompt', although the property of the
+same name has been retained and now has a value of 'hidden' when
+disconnected.
+
+*** Lists of faces in buttonized text are no longer nested.
+Previously, when "buttonizing" a new region, ERC would combine faces
+by blindly consing the new onto the existing. In theory, this kept a
+nice record of all modifications to a given region. However, it also
+complicated life for other modules wanting to analyze and operate on
+these regions. Beginning with this release, ERC now merges combined
+faces together when creating buttons, although the odd nested list may
+still crop up here and there.
*** Members of insert- and send-related hooks have been reordered.
-Built-in and third-party modules rely on certain hooks for adjusting
-incoming and outgoing messages upon insertion. And some modules only
-want to do so after others have done their damage. Traditionally,
-this required various hacks and finagling to achieve. And while this
-release makes an effort to load modules in a more consistent order,
-that alone isn't enough to ensure similar predictability among
-essential members of important hooks.
+As anyone reading this is no doubt aware, both built-in and
+third-party modules rely on certain hooks for adjusting incoming and
+outgoing messages upon insertion. And some modules only want to do so
+after others have done their damage. Traditionally, this has required
+various hacks and finagling to achieve. And while this release makes
+an effort to load modules in a more consistent order, that alone isn't
+enough to ensure predictability among essential members of important
+hooks.
Luckily, ERC now leverages a feature introduced in Emacs 27, "hook
depth," to secure the positions of a few key members of
'erc-insert-modify-hook' and 'erc-send-modify-hook'. So far, this
-includes the functions 'erc-button-add-buttons', 'erc-fill',
-'erc-match-message', and 'erc-add-timestamp', which now appear in that
-order, when present, at depths beginning at 20 and ending below 80.
-Of most interest to module authors is the new relative positioning of
-the first two, 'erc-button-add-buttons' and 'erc-fill', which have
-been swapped with respect to their previous places in recent ERC
-versions.
+includes the functions 'erc-button-add-buttons', 'erc-match-message',
+'erc-fill', and 'erc-add-timestamp', which now appear in that order,
+when present, at depths beginning at 20 and ending below 80. Of most
+interest to module authors is the new relative positioning of the
+first three, which have been rotated leftward with respect to their
+previous places in recent ERC versions (fill, button, match ,stamp).
+
+ERC also provisionally reserves the same depth interval for
+'erc-insert-pre-hook' and possibly other, similar hooks, but will
+continue to modify non-ERC hooks locally whenever possible, especially
+in new code.
+
+*** A singular entry point for inserting messages.
+Displaying "local" messages, like help text and interactive-command
+feedback, in ERC buffers has never been straightforward. As such,
+ancient patterns, like the pairing of preformatted "notice" text with
+ERC's oldest insertion function, 'erc-display-line', still appear
+quite frequently in the wild despite having been largely phased out of
+ERC's own code base in 2002. That this example has endured makes some
+sense because it's probably seen as less cumbersome than fiddling with
+the more powerful and complicated 'erc-display-message'.
+
+The latest twist in this tale comes with this release, for which a
+healthy helping of "pre-insertion" business has permanently ensconced
+itself in none other than 'erc-display-message'. While this would
+seem to put antiquated patterns, like the above mentioned
+'erc-make-notice' combo, at risk of having messages ignored or subject
+to degraded treatment by built-in modules, an adaptive measure has
+been introduced that recasts 'erc-display-line' as a thin wrapper
+around 'erc-display-message'. And though nothing of the sort has been
+done for the lower-level 'erc-display-line-1' (now an obsolete alias
+for 'erc-insert-line'), some last-ditch fallback code has been
+introduced to guarantee baseline functionality. As always, if you
+find these developments disturbing, please say so on the tracker.
*** ERC now manages timestamp-related properties a bit differently.
-For starters, the 'cursor-sensor-functions' property no longer
+For starters, the 'cursor-sensor-functions' text property is absent by
+default unless the option 'erc-echo-timestamps' is already enabled on
+module init. And when present, the property's value no longer
contains unique closures and thus no longer proves effective for
-traversing messages. To compensate, a new property, 'erc-timestamp',
-now spans message bodies but not the newlines delimiting them. Also
-affecting the `stamp' module is the deprecation of the function
+traversing inserted messages. For now, ERC only provides an internal
+means of visiting messages, but a public interface is forthcoming.
+Also affecting the 'stamp' module is the deprecation of the function
'erc-insert-aligned' and its removal from client code. Additionally,
the module now merges its 'invisible' property with existing ones and
includes all white space around stamps when doing so.
-This "propertizing" of surrounding white space also extends to all
+This "propertizing" of surrounding white space extends to all
'stamp'-applied properties, like 'field', in all intervening space
between message text and timestamps. Technically, this constitutes a
breaking change from the perspective of detecting a timestamp's
bounds. However, ERC has always propertized leading space before
-right-sided stamps on the same line as message text but not those
-folded onto the next line. Such inconsistency made stamp detection
-overly complex and produced uneven results when toggling stamp
-visibility.
+right-sided stamps on the same line as message text but not before
+those folded onto the next line. Such inconsistency made stamp
+detection overly complex and produced uneven results when toggling
+stamp visibility.
+
+*** Invisible message insertions not automatically made 'intangible'.
+Previously, when 'erc-display-message' and friends spotted the
+'invisible' text property with a value of t anywhere in text to be
+inserted, it would apply that property to the entire message, along
+with a t-valued 'intangible' property. Beginning with ERC 5.6, users
+expecting this behavior will have to instead perform the treatment
+themselves. To help with the transition, a temporary escape hatch has
+been made available to regain this behavior, but its existence is only
+guaranteed for this one minor version alone. See source code in the
+vicinity of 'erc-insert-line' for more.
+
+*** Date stamps have become independent messages.
+ERC now inserts "date stamps" generated from the option
+'erc-timestamp-format-left' as separate, standalone messages. This
+currently only matters if 'erc-insert-timestamp-function' is set to
+its default value of 'erc-insert-timestamp-left-and-right', however
+plans exist to decouple these features. In any case, ERC's near-term
+UI goals require exposing these stamps to existing code designed to
+operate on complete messages. For example, users likely expect date
+stamps to be togglable with 'erc-toggle-timestamps' while also being
+immune to hiding from commands like 'erc-match-toggle-hidden-fools'.
+Before this change, meeting such expectations demanded brittle
+heuristics that checked for the presence of these stamps in the
+leading portion of message bodies as well as special casing to act on
+these areas without inflicting collateral damage.
+
+Despite the rationale, this move admittedly ushers in a heightened
+potential for disruption because third-party members of ERC's
+modification hooks may not take kindly to encountering stamp-only
+messages. They may also expect members of 'erc-insert-pre-hook' and
+'erc-insert-done-hook' to run unconditionally, even though ERC
+suppresses those hooks when inserting date stamps. Third parties may
+also not appreciate that 'erc-timestamp-last-inserted-left' no longer
+records the final trailing newline in 'erc-timestamp-format-left'. If
+these inconveniences prove too encumbering to deal with right away,
+see the escape hatch 'erc-stamp-prepend-date-stamps-p', which should
+help ease the transition. As for detecting these new stamp-only
+messages from members of 'erc-insert-modify-hook' and friends, see the
+function 'erc-stamp-inserting-date-stamp-p'.
*** The role of a module's Custom group is now more clearly defined.
-Associating built-in modules with Custom groups and provided library
+Associating built-in modules with Custom groups and "provided" library
features has improved. More specifically, a module's group now enjoys
the singular purpose of determining where the module's minor mode
variable lives in the Customize interface. And although ERC is now
@@ -287,13 +497,47 @@ like bridges to other protocols.
Some IRC "slash" commands are hierarchical and require users to
specify a subcommand to actually carry out anything of consequence.
Built-in modules can now provide more detailed help for a particular
-subcommand by telling ERC to defer to a specialized handler.
+subcommand by telling ERC to defer to a specialized handler. This
+facility can be opened up to third parties should any one request it.
+
+*** Message-formatting templates in 'notify' renamed.
+All templates beginning with the prefix "erc-message-english-notify_"
+have been renamed to begin with "erc-message-english-notify-". For
+example, the variable 'erc-message-english-notify_current' is now
+'erc-message-english-notify_current'. The old names have been
+preserved as obsolete aliases.
*** Longtime quasi modules made proper.
The 'fill' module is now defined by 'define-erc-module'. The same
goes for ERC's imenu integration, which has 'imenu' now appearing in
the default value of 'erc-modules'.
+*** Function 'erc-get-user-mode-prefix' renamed.
+This utility has been renamed to 'erc-get-channel-membership-prefix'
+to better reflect its role of delivering a formatted "status prefix",
+like "+" (for "voice"), and to avoid confusion with user modes, like
+"+i" (for "invisible"). Additionally, its lone parameter is now
+overloaded to accept an 'erc-channel-user' object as well as a string.
+
+*** Channel-membership table 'erc-channel-users' renamed.
+Distinguishing between 'erc-channel-user' objects and values of the
+'erc-channel-users' (plural) hash-table has been a constant source of
+confusion, even within ERC's own code base. The hash-table's values
+are cons cells whose CDR slot is an 'erc-channel-user'. To help keep
+things sane, 'erc-channel-users' (plural) is now officially being
+redubbed 'erc-channel-members'. Similarly, the utility function
+'erc-get-channel-user' has been renamed to 'erc-get-channel-member'.
+Expect deprecations of the old names to follow in a future release.
+
+*** The 'erc-channel-user' struct has a changed internally.
+The five boolean slots for membership prefixes have been folded
+("encoded") into a single integer slot. However, the old 'setf'-able
+accessors remain available, and the constructor's signature remains
+unchanged. Since third-party code must be recompiled when upgrading
+ERC anyway, users shouldn't experience any churn. The only caveat is
+that third-party code using the literal read-syntax of these objects,
+for example, in unit tests, will have to be updated.
+
*** Hidden messages contain a preceding rather than trailing newline.
ERC has traditionally only offered to hide messages involving fools,
but plans are to make hiding more powerful. Anyone depending on the
@@ -320,7 +564,10 @@ than lone ones.
ERC now adjusts input lines to fall within allowed length limits
before showing hook members the result. For compatibility,
third-party code can request that the final input be adjusted again
-prior to being sent. See doc string for details.
+prior to being sent. To facilitate this, the 'erc-input' object
+shared among hook members has gained a "phony" 'refoldp' slot that's
+only accessible from 'erc-pre-send-functions'. See doc string for
+details.
*** ERC's prompt survives the insertion of user input and messages.
Previously, ERC's prompt and its input marker disappeared while
@@ -343,6 +590,72 @@ use of 'insert-before-markers' instead of 'insert'. As always, users
feeling unduly inconvenienced by these changes are encouraged to voice
their concerns on the bug list.
+*** Introducing new ways to detect ERC buffer types.
+The old standby 'erc-default-target' has served ERC well for over two
+decades. But a lesser known gotcha affecting its use has always
+haunted an unlucky few, that is, the function has always returned
+non-nil in "unjoined" channel buffers (those that the client has
+parted with or been kicked from). While perhaps not itself a major
+footgun, recessive pitfalls rooted in this subtlety continue to affect
+dependent functions, like 'erc-get-buffer'.
+
+To discourage misuse of 'erc-default-target', ERC 5.6 offers an
+alternative in the function 'erc-target', which is identical to the
+former except for its disregard for "joinedness." As a related bonus,
+the dependent function 'erc-server-buffer-p' is being rebranded as
+'erc-server-or-unjoined-channel-buffer-p'. Unfortunately, this
+release lacks a similar solution for detecting "joinedness" directly,
+but users can turn to 'xor'-ing 'erc-default-target' and 'erc-target'
+as a makeshift kludge.
+
+*** Channel-mode handling has become stricter and more predictable.
+ERC has always processed channel modes using "standardized" letters
+and popular status prefixes. Starting with this release, ERC will
+begin preferring advertised "CHANMODES" when interpreting letters and
+their arguments. To facilitate this transition, the functions
+'erc-set-modes', 'erc-parse-modes', and 'erc-update-modes', have all
+been provisionally deprecated. Expect a new, replacement API for
+handling specific "MODE" types and letters in coming releases. If
+you'd like a say in shaping how this transpires, please share your
+ideas and use cases on the tracker.
+
+*** A better way to define message-formatting templates.
+The functions 'erc-define-catalog-entry' and 'erc-define-catalog' have
+been deprecated in favor of 'erc-define-message-format-catalog', a new
+macro for defining template "catalogs" at the top level of libraries.
+
+*** Interface for determining display names renamed.
+The option 'erc-format-nick-function' has been renamed to
+'erc-speaker-from-channel-member-function' to better reflect its
+actual role. So too has the related function 'erc-format-nick', which
+is now 'erc-determine-speaker-from user'.
+
+*** A template-based approach to formatting inserted chat messages.
+Predicting and influencing how ERC formats messages containing a
+leading "<speaker>" has never been straightforward. The characters
+bracketing the speaker and the faces used for each component have
+always been hard-coded, with 'erc-format-query-as-channel-p' being the
+only knob of any consequence. With this release, ERC begins its
+transition to a unified formatting paradigm that builds upon the
+already familiar "language catalog" templating system. Using a
+separate "speaker catalog" keyed by contextual symbols, like
+'query-privmsg', ERC (and eventually everyone) will more easily be
+able to influence how inserted messages take shape in buffers.
+
+*** New format templates for inserted CTCP ACTION messages.
+In 5.5 and earlier, ERC displayed outgoing CTCP ACTION messages in
+'erc-input-face' alone (before buttonizing). Incoming ACTION messages
+mirrored this, except with 'erc-action-face' throughout. Going
+forward, inserted outgoing "/ME" messages will also incorporate
+'erc-action-face', only underneath 'erc-input-face', with
+'erc-my-nick-face' sitting atop both in the leading "speaker" nickname
+portion (again, pre-buttonizing). This new behavior sidesteps the
+traditional format template 'erc-message-english-ACTION' from the
+default "language catalog" in favor of an entry from the new internal
+"speaker catalog". Users needing to access the old behavior can do so
+by toggling a provided compatibility switch. See source code around
+the function 'erc-send-action' for details.
+
*** Miscellaneous changes
Two helper macros from GNU ELPA's Compat library are now available to
third-party modules as 'erc-compat-call' and 'erc-compat-function'.
@@ -1539,7 +1852,7 @@ Only the macros in cl-macs.el are used.
** Make flood protection toggle-able as on/off, removing the 'strict option.
-** If possible, re-use channel buffers when reconnecting to a server.
+** If possible, reuse channel buffers when reconnecting to a server.
** Text in ERC buffers is now read-only by default.
To get the previous behavior,
diff --git a/etc/ETAGS.EBNF b/etc/ETAGS.EBNF
index f2aa45de43f..2d67de68928 100644
--- a/etc/ETAGS.EBNF
+++ b/etc/ETAGS.EBNF
@@ -94,7 +94,7 @@ those.
===================== end of discussion of tag names =====================
-Copyright (C) 2002-2023 Free Software Foundation, Inc.
+Copyright (C) 2002-2024 Free Software Foundation, Inc.
COPYING PERMISSIONS:
diff --git a/etc/ETAGS.README b/etc/ETAGS.README
index 8308da52171..3264dae01cc 100644
--- a/etc/ETAGS.README
+++ b/etc/ETAGS.README
@@ -28,7 +28,7 @@ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-Copyright (C) 1984, 1987-1989, 1993-1995, 1998-2023 Free Software
+Copyright (C) 1984, 1987-1989, 1993-1995, 1998-2024 Free Software
Foundation, Inc.
This file is not considered part of GNU Emacs.
diff --git a/etc/HELLO b/etc/HELLO
index a589e69bf03..84868b6d75e 100644
--- a/etc/HELLO
+++ b/etc/HELLO
@@ -131,7 +131,7 @@ Wancho (𞋒𞋀𞋉𞋃𞋕) 𞋂𞋈𞋛
-Copyright (C) 2001-2023 Free Software Foundation, Inc.
+Copyright (C) 2001-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/etc/MACHINES b/etc/MACHINES
index c9f6ec265d8..3e0628a64d0 100644
--- a/etc/MACHINES
+++ b/etc/MACHINES
@@ -1,6 +1,6 @@
Emacs machines list
-Copyright (C) 1989-1990, 1992-1993, 1998, 2001-2023 Free Software
+Copyright (C) 1989-1990, 1992-1993, 1998, 2001-2024 Free Software
Foundation, Inc.
See the end of the file for license conditions.
diff --git a/etc/MH-E-NEWS b/etc/MH-E-NEWS
index b2b05c3d024..2ec2faebc98 100644
--- a/etc/MH-E-NEWS
+++ b/etc/MH-E-NEWS
@@ -1,6 +1,6 @@
* COPYRIGHT
-Copyright (C) 2001-2023 Free Software Foundation, Inc.
+Copyright (C) 2001-2024 Free Software Foundation, Inc.
See the end of the file for license conditions.
* Changes in MH-E 8.6
diff --git a/etc/NEWS b/etc/NEWS
index 66a5fcf6a62..a6b0beb6ee5 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -1,6 +1,6 @@
GNU Emacs NEWS -- history of user-visible changes.
-Copyright (C) 2022-2023 Free Software Foundation, Inc.
+Copyright (C) 2022-2024 Free Software Foundation, Inc.
See the end of the file for license conditions.
Please send Emacs bug reports to 'bug-gnu-emacs@gnu.org'.
@@ -24,6 +24,7 @@ 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.
@@ -31,6 +32,14 @@ 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
+libgccjit is present and functional on the system. To disable native
+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
@@ -43,9 +52,75 @@ ALSA on these operating systems instead.
* Startup Changes in Emacs 30.1
+** On GNU/Linux, Emacs is now the default application for 'org-protocol'.
+Org mode provides a way to quickly capture bookmarks, notes, and links
+using 'emacsclient':
+
+ emacsclient "org-protocol://store-link?url=URL&title=TITLE"
+
+Previously, users had to manually configure their GNU/Linux desktop
+environment to open 'org-protocol' links in Emacs. These links should
+now open in Emacs automatically, as the "emacsclient.desktop" file now
+arranges for Emacs to be the default application for the 'org-protocol'
+URI scheme. See the Org mode manual, Info node "(org) Protocols" for
+more details.
+
+
+* Incompatible Changes in Emacs 30.1
+
++++
+** 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'.
+
++++
+** 'completion-auto-help' now affects 'icomplete-in-buffer'.
+Previously, completion-auto-help mostly affected only minibuffer
+completion. Now, if 'completion-auto-help' has the value 'lazy', then
+Icomplete's in-buffer display of possible completions will only appear
+after the 'completion-at-point' command has been invoked twice, and if
+'completion-auto-help' is nil, then Icomplete's in-buffer display is
+completely suppressed. Thus, if you use 'icomplete-in-buffer', ensure
+'completion-auto-help' is not customized to 'lazy' or nil.
+
++++
+** The *Completions* buffer now always accompanies 'icomplete-in-buffer'.
+Previously, it was not consistent when the *Completions* buffer would
+appear when using 'icomplete-in-buffer'. Now the *Completions* buffer
+and Icomplete's in-buffer display of possible completions always
+appear together. If you would prefer to see only Icomplete's
+in-buffer display, and not the *Completions* buffer, you can add this
+to your init:
+
+ (advice-add 'completion-at-point :after #'minibuffer-hide-completions)
+
* Changes in Emacs 30.1
+** Emacs now supports Unicode Standard version 15.1.
+
+** Network Security Manager
+
++++
+*** The Network Security Manager now warns about 3DES by default.
+This cypher is no longer recommended owing to a major vulnerability
+disclosed in 2016, and its small 112 bit key size. Emacs now warns
+about its use also when 'network-security-level' is set to 'medium'
+(the default). See 'network-security-protocol-checks'.
+
+---
+*** The Network Security Manager now warns about <2048 bits in DH key exchange.
+Emacs used to warn for Diffie-Hellman key exchanges with prime numbers
+smaller than 1024 bits. Since more servers now support it, this
+number has been bumped to 2048 bits.
+
** Help
*** 'describe-function' shows function inferred type when available.
@@ -53,9 +128,9 @@ 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'.
+*** New user option 'describe-bindings-outline-rules'.
This user option controls outline visibility in the output buffer of
-'describe-bindings' when 'describe-bindings-outline' in non-nil.
+'describe-bindings' when 'describe-bindings-outline' is non-nil.
** X selection requests are now handled much faster and asynchronously.
This means it should be less necessary to disable the likes of
@@ -119,6 +194,22 @@ window systems other than Nextstep.
When this minor mode is enabled, buttons representing modifier keys
are displayed along the tool bar.
++++
+** "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
@@ -128,27 +219,100 @@ 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'.
+** Tab Bars and Tab Lines
+
+*** New user option 'tab-bar-tab-name-format-functions'.
+It can be used to add, remove and reorder functions that change
+the appearance of every tab on the tab bar.
+
++++
+** New 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 you want to modify.
+
+** Miscellaneous
+
+---
+*** 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.
+
+---
+*** 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'.
+
+** Emacs Server and Client
+
+---
+*** '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).
+
++++
+** '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 'ffap-lax-url' to t but this broke remote file
+name detection.
+
* Editing Changes in Emacs 30.1
++++
+** 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
@@ -226,11 +390,26 @@ or narrow (if the variable is customized to the nil value).
This setting affects the results of 'string-width' and similar
functions in CJK locales.
+---
+*** New input methods for the Urdu, Pashto, and Sindhi languages.
+These languages are spoken in Pakistan and Afganistan.
+
+*** 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'.
+
* Changes in Specialized Modes and Packages in Emacs 30.1
++++
+** New command 'lldb'.
+Run the LLDB debugger, analogous to the 'gud-gdb' command.
+
+** gdb-mi
+
---
-** Variable order and truncation can now be configured in 'gdb-many-windows'.
+*** Variable order and truncation can now be configured in 'gdb-many-windows'.
The new user option 'gdb-locals-table-row-config' allows users to
configure the order and max length of various properties in the local
variables buffer when using 'gdb-many-windows'.
@@ -245,6 +424,13 @@ 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
+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'.
@@ -254,15 +440,89 @@ equivalent to the "--heading" option of some tools such as 'git grep'
and 'rg'. The headings are displayed using the new 'grep-heading'
face.
+** Compilation mode
+
+---
+*** The 'omake' matching rule is now disabled by default.
+This is because it partly acts by modifying other rules which may
+occasionally be surprising. It can be re-enabled by adding 'omake' to
+'compilation-error-regexp-alist'.
+
+** Project
+
++++
+*** New user option 'project-mode-line'.
+When non-nil, display the name of the current project on the mode
+line. Clicking 'mouse-1' on the project name pops up the project
+menu. The default value is nil.
+
+*** New user option 'project-file-history-behavior'.
+Customizing it to 'relativize' makes commands like 'project-find-file'
+and 'project-find-dir' display previous history entries relative to
+the current project.
+
+*** New user option 'project-key-prompt-style'.
+The look of the key prompt in the project switcher has been changed
+slightly. To get the previous one, set this option to 'brackets'.
+
+*** '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
+(if any), so that the ignore rules for that repository are used, and
+the file listing's performance is still optimized.
+
+*** New commands 'project-any-command' and 'project-prefix-or-any-command'.
+The former is now bound to 'C-x p o' by default.
+The latter is designed primarily for use as a value of
+'project-switch-commands'. If instead of a short menu you prefer to
+have access to all keys defined inside 'project-prefix-map', as well
+as global bindings (to run other commands inside the project root),
+you can add this to your init script:
+
+ (setopt project-switch-commands #'project-prefix-or-any-command)
+
** VC
---
+*** Log-Edit buffers now display a tool bar.
+This tool bar contains items for committing log entries and editing or
+generating log entries, among other editing operations.
+
+---
*** New user option 'vc-git-shortlog-switches'.
This is a string or a list of strings that specifies the Git log
switches for shortlogs, such as the one produced by 'C-x v L'.
'vc-git-log-switches' is no longer used for shortlogs.
-** Diff Mode
+---
+*** New value 'no-backend' for user option 'vc-display-status'.
+With this value only the revision number is displayed on the mode-line.
+
+---
+*** Obsolete command 'vc-switch-backend' re-added as 'vc-change-backend'.
+The command was previously obsoleted and unbound in Emacs 28.
+
+*** Support for viewing VC change history across renames.
+When a fileset's VC change history ('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.
+
+---
+*** '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.
+
+*** New option 'vc-git-file-name-changes-switches'.
+It allows tweaking the thresholds for rename and copy detection.
+
+** Diff mode
+++
*** 'diff-ignore-whitespace-hunk' can now be applied to all hunks.
@@ -276,6 +536,71 @@ 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
+
+---
+*** New user option 'dired-movement-style'.
+When non-nil, make 'dired-next-line', 'dired-previous-line',
+'dired-next-dirline', 'dired-prev-dirline' skip empty lines.
+It also controls how to move point when encountering a boundary
+(e.g., if every line is visible, invoking 'dired-next-line' at
+the last line will move to the first line). The default is nil.
+
+*** New user option 'dired-filename-display-length'.
+It is an integer representing the maximum display length of filenames.
+The middle part of a filename whose length exceeds the restriction is
+hidden and an ellipsis is displayed instead. A value of 'window'
+means using the right edge of window as the display restriction. The
+default is nil.
+
+*** New user option 'shell-command-guess-functions'.
+It defines how to populate a list of commands available
+for 'M-!', 'M-&', '!', '&' and the context menu "Open With"
+based on marked files in Dired. Possible backends are
+'dired-guess-default', MIME types, XDG configuration
+and a universal command such as "open" or "start"
+that delegates to the OS.
+
+*** New command 'dired-do-open'.
+This command is bound to "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.
+
++++
+*** '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 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
---
@@ -305,6 +630,14 @@ For more information, see the "(eshell) Built-ins" node in the Eshell
manual.
+++
+*** New special reference type '#<marker POSITION BUFFER>'.
+This special reference type returns a marker at 'POSITION' in
+'BUFFER'. You can insert it by typing or using the new interactive
+command 'eshell-insert-marker'. You can also insert markers of any
+type with the new command 'eshell-insert-special-reference'. See the
+"(eshell) Arguments" node in the Eshell manual for more details.
+
++++
*** New splice operator for Eshell dollar expansions.
Dollar expansions in Eshell now let you splice the elements of the
expansion in-place using '$@expr'. This makes it easier to fill lists
@@ -349,6 +682,9 @@ this to your configuration:
(keymap-set eshell-mode-map "<home>" #'eshell-bol-ignoring-prompt)
+This also means you no longer need to adjust 'eshell-prompt-regexp'
+when customizing your Eshell prompt.
+
---
*** You can now properly unload Eshell.
Calling '(unload-feature 'eshell)' no longer signals an error, and now
@@ -364,6 +700,46 @@ to load the edited aliases.
Running 'rgrep' in Eshell now uses the Emacs grep facility instead of
calling external rgrep.
++++
+*** If a command exits abnormally, the Eshell prompt now shows its exit code.
+
++++
+*** New user option 'eshell-history-append'.
+If non-nil, each Eshell session will save history by appending new
+entries of that session to the history file rather than overwriting
+the file with the whole history of the session. The default is nil.
+
+** Minibuffer and Completions
+
+*** New commands 'previous-line-completion' and 'next-line-completion'.
+Bound to '<up>' and '<down>' arrow keys, respectively, they navigate
+the "*Completions*" buffer vertically by lines, wrapping at the
+top/bottom when 'completion-auto-wrap' is non-nil.
+
+*** New user option 'minibuffer-visible-completions'.
+When customized to non-nil, you can use arrow keys in the minibuffer
+to navigate the completions displayed in the "*Completions*" window.
+Typing 'RET' selects the highlighted candidate. 'C-g' hides the
+completions window. When the completions window is not visible,
+then all these keys have their usual meaning in the minibuffer.
+This option is supported for in-buffer completion as well.
+
+*** Selected completion candidates are deselected on typing.
+When you type at the minibuffer prompt, the current completion
+candidate will be un-highlighted, and point in the "*Completions*" window
+will be moved off that candidate. 'minibuffer-choose-completion'
+('M-RET') will still choose a previously-selected completion
+candidate, but the new command 'minibuffer-choose-completion-or-exit'
+(bound to 'RET' by 'minibuffer-visible-completions') will exit with
+the minibuffer contents instead. This deselection behavior can be
+controlled with the new user option 'completion-auto-deselect', which
+is t by default.
+
+*** New value 'historical' for user option 'completions-sort'.
+When 'completions-sort' is set to 'historical', completion candidates
+will be first sorted alphabetically, and then re-sorted by their order
+in the minibuffer history, with more recent candidates appearing first.
+
** Pcomplete
---
@@ -372,7 +748,11 @@ When this option is non-nil, remote file names are not completed by
Pcomplete. Packages, like 'shell-mode', could set this in order to
suppress remote file name completion at all.
-** Shell Mode
+---
+*** Completion for the 'doas' command has been added.
+Command completion for 'doas' in Eshell and Shell mode will now work.
+
+** Shell mode
+++
*** New user option 'shell-get-old-input-include-continuation-lines'.
@@ -380,7 +760,14 @@ When this user option is non-nil, 'shell-get-old-input' ('C-RET')
includes multiple shell "\" continuation lines from command output.
Default is nil.
-** Prog Mode
+** 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'.
@@ -389,10 +776,10 @@ 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.
-** Which Function Mode
+** Which Function mode
+++
-*** Which Function Mode can now display function names on the header line.
+*** Which Function mode can now display function names on the header line.
The new user option 'which-func-display' allows choosing where the
function name is displayed. The default is 'mode' to display in the
mode line. 'header' will display in the header line;
@@ -410,8 +797,8 @@ sandboxes provided by Flatpak.
The host name for Kubernetes connections can be of kind [CONTAINER.]POD,
in order to specify a dedicated container. If there is just the pod
name, the first container in the pod is taken. The new user options
-'tramp-kubernetes-context' and 'tramp-kubernetes-namespace' allow to
-access pods with different context or namespace but the default one.
+'tramp-kubernetes-context' and 'tramp-kubernetes-namespace' allow
+accessing pods with different context or namespace but the default one.
+++
*** Rename 'tramp-use-ssh-controlmaster-options' to 'tramp-use-connection-share'.
@@ -424,7 +811,7 @@ sessions, respectively.
+++
*** New command 'tramp-cleanup-some-buffers'.
-It allows to kill only selected remote buffers, controlled by user
+It kills only a subset of opened remote buffers, subject to the user
option 'tramp-cleanup-some-buffers-hook'.
+++
@@ -440,6 +827,30 @@ This macro could wrap code which handles local files only. Due to the
temporary deactivation of remote files, it results in a slightly
improved performance of file name handling in Emacs.
++++
+*** New user option 'tramp-completion-multi-hop-methods'.
+It contains a list of connection methods for which completion should
+be attempted at the end of a multi-hop chain. This allows completion
+candidates to include a list of, for example, containers running on a
+remote docker host.
+
++++
+*** New command 'tramp-revert-buffer-with-sudo'.
+It reverts the current buffer to visit with "sudo" permissions. The
+buffer must either visit a file, or it must run 'dired-mode'. Another
+method but "sudo" can be configured with user option
+'tramp-file-name-with-method'.
+
+---
+*** Direct asynchronous processes use 'tramp-remote-path'.
+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
+++
@@ -482,13 +893,20 @@ This command adds a docstring comment to the current defun. If a
comment already exists, point is only moved to the comment. It is
bound to 'C-c C-d' in 'go-ts-mode'.
-** Man-mode
+** Man mode
+++
*** New user option 'Man-prefer-synchronous-call'.
-When this is non-nil, call the 'man' program synchronously rather than
+When this is non-nil, run the 'man' command synchronously rather than
asynchronously (which is the default behavior).
++++
+*** New user option 'Man-support-remote-systems'.
+This option controls whether the man page is formatted on the remote
+system when the current buffer's default-directory is remote. You can
+invoke the 'man' command with a prefix argument to countermand the
+value of this option for the current invocation of 'man'.
+
** DocView
---
@@ -532,9 +950,9 @@ project, that you can quickly select using 'project-switch-project'
('C-x p p').
---
-*** New user option 'package-vc-allow-side-effects'.
-When non-nil, package specifications with side-effects for building
-software will be used when building a package.
+*** New user option 'package-vc-allow-build-commands'.
+Controls for which packages Emacs runs extra build commands when
+installing directly from the package VCS repository.
---
*** New command to start an inferior Emacs loading only specific packages.
@@ -555,7 +973,14 @@ distracting and easily confused with actual code, or a significant
early aid that relieves you from moving the buffer or reaching for the
mouse to consult an error message.
-** Python Mode
+** JS mode.
+The binding 'M-.' has been removed from the major mode keymaps in
+'js-mode' and 'js-ts-mode', having it default to the global binding
+which calls 'xref-find-definitions'. If the previous one worked
+better for you, use 'define-key' in your init script to bind
+'js-find-symbol' to that combination again.
+
+** Python mode
---
*** New user option 'python-indent-block-paren-deeper'.
@@ -583,15 +1008,23 @@ interactive Python interpreter specified by 'python-interpreter'.
*** New ':vc' keyword.
This keyword enables the user to install packages using 'package-vc'.
+** Gnus
+
+*** 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'.
+
** Rmail
---
*** New commands for reading mailing lists.
The new Rmail commands 'rmail-mailing-list-post',
'rmail-mailing-list-unsubscribe', 'rmail-mailing-list-help', and
-'rmail-mailing-list-archive' allow to, respectively, post to,
-unsubscribe from, request help about, and browse the archives, of the
-mailing list from which the current email message was delivered.
+'rmail-mailing-list-archive' allow, respectively, posting to,
+unsubscribing from, requesting help about, and browsing the archives
+of, the mailing list from which the current email message was
+delivered.
** Dictionary
@@ -664,6 +1097,22 @@ which makes them visually distinct from subroutine prototypes.
CPerl mode supports the new keywords for exception handling and the
object oriented syntax which were added in Perl 5.36 and 5.38.
+*** New user option 'cperl-fontify-trailer'.
+This user option takes the values 'perl-code' or 'comment' and treats
+text after an "__END__" or "__DATA__" token accordingly. The default
+value of 'perl-code' is useful for trailing POD and for AutoSplit
+modules, the value 'comment' makes CPerl mode treat trailers as
+comment, like Perl mode does.
+
+*** Commands using the Perl info page are obsolete.
+The Perl documentation in info format is no longer distributed with
+Perl or on CPAN since more than 10 years. Perl documentation can be
+read with 'cperl-perldoc' instead.
+
+*** Highlighting trailing whitespace has been removed.
+The user option 'cperl-invalid-face' is now obsolete, and does
+nothing. See the user option 'show-trailing-whitespace' instead.
+
** Emacs Sessions (Desktop)
+++
@@ -686,7 +1135,7 @@ of the accessibility of remote files can now time out if
** Notifications
+++
-*** Allow to use Icon Naming Specification for ':app-icon'.
+*** 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:
@@ -698,6 +1147,75 @@ without specifying a file, like this:
*** New user option 'image-dired-thumb-naming'.
You can now configure how a thumbnail is named using this option.
+** ERT
+
++++
+*** New macro 'skip-when' to skip 'ert-deftest' tests.
+This can help avoid some awkward skip conditions. For example
+'(skip-unless (not noninteractive))' can be changed to the easier
+to read '(skip-when noninteractive)'.
+
++++
+*** Syntax highlighting unit testing support.
+An ERT extension ('ert-font-lock') now provides support for face
+assignment unit testing. For more information, see the "(ert) Syntax
+Highlighting Tests" node in the ERT manual.
+
+** 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
+
++++
+*** Socks supports version 4a.
+The 'socks-server' user option accepts '4a' as a value for its version
+field.
+
+** Edmacro
+
++++
+*** New command 'edmacro-set-macro-to-region-lines'.
+Bound to 'C-c C-r', this command replaces the macro text with the
+lines of the region. If needed, the region is extended to include
+whole lines. If the region ends at the beginning of a line, that last
+line is excluded.
+
++++
+*** New user option 'edmacro-reverse-macro-lines'.
+When this is non-nil, the lines of key sequences are displayed with
+the most recent line first. This is can be useful when working with
+macros with many lines, such as from 'kmacro-edit-lossage'.
+
+** 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.
+
+---
+*** 'bug-reference-mode' now supports 'thing-at-point'.
+Now, calling '(thing-at-point 'url)' when point is on a bug reference
+will return the URL for that bug.
+
++++
+*** New user option 'rcirc-log-time-format'
+This allows for rcirc logs to use a custom timestamp format, than the
+chat buffers use by default.
+
+** Customize
+
++++
+*** New command 'customize-dirlocals'.
+This command pops up a buffer to edit the settings in ".dir-locals.el".
+
* New Modes and Packages in Emacs 30.1
@@ -714,8 +1232,26 @@ 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.
+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.
+
+** 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.
---
** The highly accessible Modus themes collection has eight items.
@@ -732,6 +1268,27 @@ showcases all their customization options.
* Incompatible Lisp Changes in Emacs 30.1
++++
+** 'M-TAB' now invokes 'completion-at-point' also in Text mode.
+Text mode no longer binds 'M-TAB' to 'ispell-complete-word', and
+instead this mode arranges for 'completion-at-point', globally bound
+to 'M-TAB', to perform word completion as well. If you want 'M-TAB'
+to invoke 'ispell-complete-word', as it did in previous Emacs
+versions, customize the new user option
+'text-mode-meta-tab-ispell-complete-word' to non-nil.
+
+** '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
+an unreliable hack to try and support condition predicates that
+don't accept this optional arg.
+The new semantics makes no such accommodation, but the code still
+supports it (with a warning) for backward compatibility.
+
+** 'post-gc-hook' runs after updating 'gcs-done' and 'gcs-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
@@ -751,7 +1308,7 @@ This user option has been obsoleted in Emacs 27, use
---
** User options 'eshell-NAME-unload-hook' are now obsolete.
These hooks were named incorrectly, and so they never actually ran
-when unloading the correspending feature. Instead, you should use
+when unloading the corresponding feature. Instead, you should use
hooks named after the feature name, like 'esh-mode-unload-hook'.
+++
@@ -807,12 +1364,84 @@ The compatibility aliases 'x-defined-colors', 'x-color-defined-p',
** '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.
+
* Lisp Changes in Emacs 30.1
++++
+** New function 'require-with-check' to detect new versions shadowing.
+This is like 'require', but it checks whether the argument 'feature'
+is already loaded, in which case it either signals an error or
+forcibly reloads the file that defines the feature.
+
++++
+** New 'pop-up-frames' action alist entry for 'display-buffer'.
+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.
+
+** New API for 'derived-mode-p' and control of the graph of major modes.
+
+*** 'derived-mode-p' now takes the list of modes as a single argument.
+The same holds for 'provided-mode-derived-p'.
+The old calling convention where multiple modes are passed as
+separate arguments is deprecated.
+
+*** New functions to access the graph of major modes.
+While 'define-derived-mode' still only supports single inheritance,
+modes can declare additional parents (for tests like 'derived-mode-p')
+with 'derived-mode-add-parents'.
+Accessing the 'derived-mode-parent' property directly is now
+deprecated in favor of the new functions 'derived-mode-set-parent'
+and 'derived-mode-all-parents'.
+
++++
+** Drag-and-drop functions can now be called once for compound drops.
+It is now possible for drag-and-drop handler functions to respond to
+drops incorporating more than one URL. Functions capable of this must
+set their 'dnd-multiple-handler' symbol properties to a non-nil value.
+See the Info node "(elisp) Drag and Drop".
+
+Incident to this change, the function 'dnd-handle-one-url' has been
+made obsolete, for it cannot take these new handlers into account.
+
+** 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.
+
++++
+** 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" node for help converting them
-to use 'advice-add' or 'define-advice' instead.
+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.
+++
** Desktop notifications are now supported on the Haiku operating system.
@@ -835,9 +1464,18 @@ within 'function-key-map' or 'input-decode-map' around those calls.
** New variables describing the names of built in programs.
The new variables 'ctags-program-name', 'ebrowse-program-name',
'etags-program-name', 'hexl-program-name', 'emacsclient-program-name'
-and 'movemail-program-name' should be used instead of "ctags",
-"ebrowse", "etags", "hexl", and "emacsclient", when starting one of
-these built in programs in a subprocess.
+'movemail-program-name', and 'rcs2log-program-name' should be used
+instead of "ctags", "ebrowse", "etags", "hexl", "emacsclient", and
+"rcs2log", when starting one of these built in programs in a
+subprocess.
+
++++
+** New variable 'case-symbols-as-words' affects case operations for symbols.
+If non-nil, then case operations such as 'upcase-initials' or
+'replace-match' (with nil FIXEDCASE) will treat the entire symbol name
+as a single word. This is useful for programming languages and styles
+where only the first letter of a symbol's name is ever capitalized.
+The default value of this variable is nil.
+++
** 'x-popup-menu' now understands touch screen events.
@@ -867,6 +1505,14 @@ with Emacs.
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.
+
** Functions and variables to transpose sexps
+++
@@ -894,28 +1540,45 @@ Major modes can now set this variable to customize the behavior of the
The previous implementation of 'forward-sentence' is moved into its
own function, to be bound by 'forward-sentence-function'.
-*** New buffer-local variable 'treesit-sentence-type-regexp'.
-Similarly to 'treesit-defun-type-regexp', this variable is used to
-define "sentences" in tree-sitter enabled modes.
-
*** New function 'treesit-forward-sentence'.
-All tree-sitter enabled modes that define 'treesit-sentence-type-regexp'
-now set 'forward-sentence-function' to call '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 buffer-local variable 'treesit-sexp-type-regexp'.
-Similarly to 'treesit-defun-type-regexp', this variable is used to
-define "sexps" in tree-sitter enabled modes.
-
*** New function 'treesit-forward-sexp'.
Tree-sitter conditionally sets 'forward-sexp-function' for major modes
-that have defined 'treesit-sexp-type-regexp' to enable sexp-related
-motion commands.
+that have defined 'sexp' in 'treesit-thing-settings' to enable
+sexp-related motion commands.
** New or changed byte-compilation warnings
---
+*** Warn about missing 'lexical-binding' directive.
+The compiler now warns if an Elisp file lacks the standard
+'-*- lexical-binding: ... -*-' cookie on the first line.
+This line typically looks something like
+
+ ;;; My little pony mode -*- lexical-binding: t -*-
+
+It is needed to inform the compiler about which dialect of ELisp
+your code is using: the modern dialect with lexical binding or
+the old dialect with only dynamic binding.
+
+Lexical binding avoids some name conflicts and allows the compiler to
+detect more mistakes and generate more efficient code, so it is
+recommended. For how to adapt your code to lexical binding, see the
+manual section "(elisp) Converting to Lexical Binding".
+
+If your code cannot be converted to lexical binding, you can insert
+the line
+
+ ;;; -*- lexical-binding: nil -*-
+
+first in the file to declare that it uses the old dialect.
+
+---
*** Warn about empty bodies for more special forms and macros.
The compiler now warns about an empty body argument to 'when',
'unless', 'ignore-error' and 'with-suppressed-warnings' in addition to
@@ -990,6 +1653,21 @@ This warning can be suppressed using 'with-suppressed-warnings' with
the warning name 'suspicious'.
---
+*** Warn about useless trailing 'cond' clauses.
+The compiler now warns when a 'cond' form contains clauses following a
+default (unconditional) clause. Example:
+
+ (cond ((= x 0) (say "none"))
+ (t (say "some"))
+ (say "goodbye"))
+
+Such a clause will never be executed but is likely to be a mistake,
+perhaps due to misplaced brackets.
+
+This warning can be suppressed using 'with-suppressed-warnings' with
+the warning name 'suspicious'.
+
+---
*** Warn about mutation of constant values.
The compiler now warns about code that modifies program constants in
some obvious cases. Examples:
@@ -1027,6 +1705,10 @@ name 'ignored-return-value'.
The warning will only be issued for calls to functions declared
'important-return-value' or 'side-effect-free' (but not 'error-free').
+---
+*** The warning about wide docstrings can now be disabled separately.
+Its warning name is 'docstrings-wide'.
+
+++
** New function declaration and property 'important-return-value'.
The declaration '(important-return-value t)' sets the
@@ -1054,6 +1736,25 @@ 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
+default to use 'LANGUAGE'.
+
+---
+** New optional argument to 'modify-dir-local-variable'.
+A 5th argument, optional, has been added to
+'modify-dir-local-variable'. It can be used to specify which
+dir-locals file to modify.
+
+** Connection local variables
+
++++
+*** New macros 'connection-local-p' and 'connection-local-value'.
+The former macro returns non-nil if a variable has a connection-local
+binding. The latter macro returns the connection-local value of a
+variable if any, or its current value.
+
* Changes in Emacs 30.1 on Non-Free Operating Systems
diff --git a/etc/NEWS.1-17 b/etc/NEWS.1-17
index 952b5e5c3fb..64626060c94 100644
--- a/etc/NEWS.1-17
+++ b/etc/NEWS.1-17
@@ -1,6 +1,6 @@
GNU Emacs NEWS -- history of user-visible changes. 26-Mar-1986
-Copyright (C) 1985-1986, 2006-2023 Free Software Foundation, Inc.
+Copyright (C) 1985-1986, 2006-2024 Free Software Foundation, Inc.
See the end of the file for license conditions.
diff --git a/etc/NEWS.18 b/etc/NEWS.18
index a1df6245e09..f94d89eab7e 100644
--- a/etc/NEWS.18
+++ b/etc/NEWS.18
@@ -1,6 +1,6 @@
GNU Emacs NEWS -- history of user-visible changes. 17-Aug-1988
-Copyright (C) 1988, 2006-2023 Free Software Foundation, Inc.
+Copyright (C) 1988, 2006-2024 Free Software Foundation, Inc.
See the end of the file for license conditions.
diff --git a/etc/NEWS.19 b/etc/NEWS.19
index 18d6d630d5b..fb43e80feac 100644
--- a/etc/NEWS.19
+++ b/etc/NEWS.19
@@ -1,6 +1,6 @@
GNU Emacs NEWS -- history of user-visible changes. 1992.
-Copyright (C) 1993-1995, 2001, 2006-2023 Free Software Foundation, Inc.
+Copyright (C) 1993-1995, 2001, 2006-2024 Free Software Foundation, Inc.
See the end of the file for license conditions.
diff --git a/etc/NEWS.20 b/etc/NEWS.20
index 8143cfcf3cd..ad41c873c1d 100644
--- a/etc/NEWS.20
+++ b/etc/NEWS.20
@@ -1,6 +1,6 @@
GNU Emacs NEWS -- history of user-visible changes. 2006-05-31
-Copyright (C) 1999-2001, 2006-2023 Free Software Foundation, Inc.
+Copyright (C) 1999-2001, 2006-2024 Free Software Foundation, Inc.
See the end of the file for license conditions.
@@ -1250,7 +1250,7 @@ for large documents), you can reuse these buffers by setting
*** References to external documents.
-The LaTeX package 'xr' allows to cross-reference labels in external
+The LaTeX package 'xr' allows cross-referencing labels in external
documents. RefTeX can provide information about the external
documents as well. To use this feature, set up the \externaldocument
macros required by the 'xr' package and rescan the document with
@@ -3260,7 +3260,7 @@ can connect to an Emacs server started by a non-root user.
it to return immediately without waiting for you to "finish" the
buffer in Emacs.
-*** The new option --alternate-editor allows to specify an editor to
+*** The new option --alternate-editor allows specifying an editor to
use if Emacs is not running. The environment variable
ALTERNATE_EDITOR can be used for the same effect; the command line
option takes precedence.
diff --git a/etc/NEWS.21 b/etc/NEWS.21
index e68d7fe8fae..d7f5ba184a5 100644
--- a/etc/NEWS.21
+++ b/etc/NEWS.21
@@ -1,6 +1,6 @@
GNU Emacs NEWS -- history of user-visible changes. 2006-05-31
-Copyright (C) 2000-2023 Free Software Foundation, Inc.
+Copyright (C) 2000-2024 Free Software Foundation, Inc.
See the end of the file for license conditions.
@@ -1424,7 +1424,7 @@ digest message.
*** The new user option 'rmail-automatic-folder-directives' specifies
in which folder to put messages automatically.
-*** The new function 'rmail-redecode-body' allows to fix a message
+*** The new function 'rmail-redecode-body' allows fixing a message
with non-ASCII characters if Emacs happens to decode it incorrectly
due to missing or malformed "charset=" header.
@@ -1437,7 +1437,7 @@ use the -f option when sending mail.
** The Rmail command 'o' ('rmail-output-to-rmail-file') now writes the
current message in the internal 'emacs-mule' encoding, rather than in
the encoding taken from the variable 'buffer-file-coding-system'.
-This allows to save messages whose characters cannot be safely encoded
+This allows saving messages whose characters cannot be safely encoded
by the buffer's coding system, and makes sure the message will be
displayed correctly when you later visit the target Rmail file.
@@ -1465,7 +1465,7 @@ other than 'emacs-mule', you can customize the variable
sorted *Index* buffer which looks like the final index. Entries
can be edited from that buffer.
-*** Label and citation key selection now allow to select several
+*** Label and citation key selection now allow selecting several
items and reference them together (use 'm' to mark items, 'a' or
'A' to use all marked entries).
@@ -1804,7 +1804,7 @@ to phrases and to highlight entire lines containing a match.
*** The new package zone.el plays games with Emacs' display when
Emacs is idle.
-*** The new package tildify.el allows to add hard spaces or other text
+*** The new package tildify.el allows adding hard spaces or other text
fragments in accordance with the current major mode.
*** The new package xml.el provides a simple but generic XML
@@ -1826,7 +1826,7 @@ provides an alternative interface to VC-dired for CVS. It comes with
'log-view-mode' to view RCS and SCCS logs and 'log-edit-mode' used to
enter check-in log messages.
-*** The new package called 'woman' allows to browse Unix man pages
+*** The new package called 'woman' allows browsing Unix man pages
without invoking external programs.
The command `M-x woman' formats manual pages entirely in Emacs Lisp
@@ -2011,8 +2011,8 @@ recent file list can be displayed:
- sorted by file paths, file names, ascending or descending.
- showing paths relative to the current default-directory
-The 'recentf-filter-changer' menu filter function allows to
-dynamically change the menu appearance.
+The 'recentf-filter-changer' menu filter function allows
+dynamically changing the menu appearance.
*** 'elide-head' provides a mechanism for eliding boilerplate header
text.
@@ -2139,7 +2139,7 @@ new command M-x strokes-list-strokes.
** Hexl contains a new command 'hexl-insert-hex-string' which inserts
a string of hexadecimal numbers read from the mini-buffer.
-** Hexl mode allows to insert non-ASCII characters.
+** Hexl mode allows inserting non-ASCII characters.
The non-ASCII characters are encoded using the same encoding as the
file you are visiting in Hexl mode.
@@ -2369,7 +2369,7 @@ allows the animated display of strings.
** The new function 'interactive-form' can be used to obtain the
interactive form of a function.
-** The keyword :set-after in defcustom allows to specify dependencies
+** The keyword :set-after in defcustom allows specifying dependencies
between custom options. Example:
(defcustom default-input-method nil
@@ -3629,7 +3629,7 @@ Each face can specify the following display attributes:
13. Whether or not a box should be drawn around characters, its
color, the width of the box lines, and 3D appearance.
-Faces are frame-local by nature because Emacs allows to define the
+Faces are frame-local by nature because Emacs allows defining the
same named face (face names are symbols) differently for different
frames. Each frame has an alist of face definitions for all named
faces. The value of a named face in such an alist is a Lisp vector
diff --git a/etc/NEWS.22 b/etc/NEWS.22
index 804dab00859..848b9afda4b 100644
--- a/etc/NEWS.22
+++ b/etc/NEWS.22
@@ -1,6 +1,6 @@
GNU Emacs NEWS -- history of user-visible changes.
-Copyright (C) 2001-2023 Free Software Foundation, Inc.
+Copyright (C) 2001-2024 Free Software Foundation, Inc.
See the end of the file for license conditions.
Please send Emacs bug reports to bug-gnu-emacs@gnu.org.
@@ -2408,7 +2408,7 @@ called with a prefix argument. Related new options are
The new command 'reftex-create-bibtex-file' creates a BibTeX database
with all entries referenced in the current document. The keys "e" and
-"E" allow to produce a BibTeX database file from entries marked in a
+"E" allow producing a BibTeX database file from entries marked in a
citation selection buffer.
The command 'reftex-citation' uses the word in the buffer before the
diff --git a/etc/NEWS.23 b/etc/NEWS.23
index 22408197f7d..3ba5bdd180c 100644
--- a/etc/NEWS.23
+++ b/etc/NEWS.23
@@ -1,6 +1,6 @@
GNU Emacs NEWS -- history of user-visible changes.
-Copyright (C) 2007-2023 Free Software Foundation, Inc.
+Copyright (C) 2007-2024 Free Software Foundation, Inc.
See the end of the file for license conditions.
Please send Emacs bug reports to bug-gnu-emacs@gnu.org.
@@ -1200,7 +1200,7 @@ of the region to comment, rather than the leftmost column.
*** The new commands 'pp-macroexpand-expression' and
'pp-macroexpand-last-sexp' pretty-print macro expansions.
-*** The new command 'set-file-modes' allows to set file's mode bits.
+*** The new command 'set-file-modes' allows setting file's mode bits.
The mode bits can be specified in symbolic notation, like with GNU
Coreutils, in addition to an octal number. 'chmod' is a new
convenience alias for this function.
@@ -1540,7 +1540,7 @@ authentication respectively.
*** New macro 'with-help-window' should set up help windows better
than 'with-output-to-temp-buffer' with 'print-help-return-message'.
-*** New option 'help-window-select' permits to customize whether help
+*** New option 'help-window-select' permits customizing whether help
window shall be automatically selected when invoking help.
*** New variable 'help-window-point-marker' permits one to specify a new
@@ -1670,7 +1670,7 @@ Previously, this information was hidden.
** TeX modes
*** New option 'latex-indent-within-escaped-parens'
-permits to customize indentation of LaTeX environments delimited
+permits customizing indentation of LaTeX environments delimited
by escaped parens.
** T-mouse Mode
@@ -1726,7 +1726,7 @@ and Bzr. VC will now pass a multiple-file commit to these systems as
a single changeset.
*** 'vc-dir' is a new command that displays file names and their VC
-status. It allows to apply various VC operations to a file, a
+status. It allows applying various VC operations to a file, a
directory or a set of files/directories.
*** VC switches are no longer appended, rather the first non-nil value is used.
diff --git a/etc/NEWS.24 b/etc/NEWS.24
index 1e1206d058f..f2e434352a7 100644
--- a/etc/NEWS.24
+++ b/etc/NEWS.24
@@ -1,6 +1,6 @@
GNU Emacs NEWS -- history of user-visible changes.
-Copyright (C) 2010-2023 Free Software Foundation, Inc.
+Copyright (C) 2010-2024 Free Software Foundation, Inc.
See the end of the file for license conditions.
Please send Emacs bug reports to bug-gnu-emacs@gnu.org.
@@ -872,7 +872,7 @@ name and arguments.
** Tramp
-*** New connection method "adb", which allows to access Android
+*** New connection method "adb", which allows accessing Android
devices by the Android Debug Bridge. The variable 'tramp-adb-program'
can be used to adapt the path of the "adb" program, if needed.
@@ -2703,12 +2703,12 @@ specified by 'display-buffer-fallback-action'.
display actions, taking precedence over 'display-buffer-base-action'.
*** New option 'window-combination-limit'.
-The new option 'window-combination-limit' allows to return the space
+The new option 'window-combination-limit' allows returning the space
obtained for resizing or creating a window more reliably to the window
from which such space was obtained.
*** New option 'window-combination-resize'.
-The new option 'window-combination-resize' allows to split a window that
+The new option 'window-combination-resize' allows splitting a window that
otherwise cannot be split because it's too small by stealing space from
other windows in the same combination. Subsequent resizing or deletion
of the window will resize all windows in the same combination as well.
@@ -2721,7 +2721,7 @@ frame, or quitting a window showing a buffer in a frame of its own.
These maximize and minimize the size of a window within its frame.
*** New commands 'switch-to-prev-buffer' and 'switch-to-next-buffer'.
-These functions allow to navigate through the live buffers that have
+These functions allow navigating through the live buffers that have
been shown in a specific window.
** Minibuffer changes
@@ -3496,7 +3496,7 @@ and 'window-body-height' are provided.
For each window you can specify a parameter to override the default
behavior of a number of functions like 'split-window', 'delete-window'
and 'delete-other-windows'. The variable 'ignore-window-parameters'
-allows to ignore processing such parameters.
+allows ignoring processing such parameters.
*** New semantics of third argument of 'split-window'.
The third argument of 'split-window' has been renamed to SIDE and can be
@@ -3554,7 +3554,7 @@ are user-customizable variables.
See the docstring of 'display-buffer' for details.
*** New functions 'window-state-get' and 'window-state-put'.
-These functions allow to save and restore the state of an arbitrary
+These functions allow saving and restoring the state of an arbitrary
frame or window as an Elisp object.
** Completion
diff --git a/etc/NEWS.25 b/etc/NEWS.25
index 3fa604bd92d..3c5e9569b49 100644
--- a/etc/NEWS.25
+++ b/etc/NEWS.25
@@ -1,6 +1,6 @@
GNU Emacs NEWS -- history of user-visible changes.
-Copyright (C) 2014-2023 Free Software Foundation, Inc.
+Copyright (C) 2014-2024 Free Software Foundation, Inc.
See the end of the file for license conditions.
Please send Emacs bug reports to bug-gnu-emacs@gnu.org.
diff --git a/etc/NEWS.26 b/etc/NEWS.26
index 29eee5eb4a2..b374c8b5ed3 100644
--- a/etc/NEWS.26
+++ b/etc/NEWS.26
@@ -1,6 +1,6 @@
GNU Emacs NEWS -- history of user-visible changes.
-Copyright (C) 2016-2023 Free Software Foundation, Inc.
+Copyright (C) 2016-2024 Free Software Foundation, Inc.
See the end of the file for license conditions.
Please send Emacs bug reports to 'bug-gnu-emacs@gnu.org'.
@@ -38,7 +38,7 @@ in its NEWS.)
** Installing Emacs now installs the emacs-module.h file.
The emacs-module.h file is now installed in the system-wide include
-directory as part of the Emacs installation. This allows to build
+directory as part of the Emacs installation. This allows building
Emacs modules outside of the Emacs source tree.
diff --git a/etc/NEWS.27 b/etc/NEWS.27
index 3e1b4a49946..2617e1a48f4 100644
--- a/etc/NEWS.27
+++ b/etc/NEWS.27
@@ -1,6 +1,6 @@
GNU Emacs NEWS -- history of user-visible changes.
-Copyright (C) 2017-2023 Free Software Foundation, Inc.
+Copyright (C) 2017-2024 Free Software Foundation, Inc.
See the end of the file for license conditions.
Please send Emacs bug reports to 'bug-gnu-emacs@gnu.org'.
diff --git a/etc/NEWS.28 b/etc/NEWS.28
index 89ef25bb32d..ac65eaa986f 100644
--- a/etc/NEWS.28
+++ b/etc/NEWS.28
@@ -1,6 +1,6 @@
GNU Emacs NEWS -- history of user-visible changes.
-Copyright (C) 2019-2023 Free Software Foundation, Inc.
+Copyright (C) 2019-2024 Free Software Foundation, Inc.
See the end of the file for license conditions.
Please send Emacs bug reports to 'bug-gnu-emacs@gnu.org'.
diff --git a/etc/NEWS.29 b/etc/NEWS.29
index e74cbee4a53..069661866ce 100644
--- a/etc/NEWS.29
+++ b/etc/NEWS.29
@@ -1,6 +1,6 @@
GNU Emacs NEWS -- history of user-visible changes.
-Copyright (C) 2021-2023 Free Software Foundation, Inc.
+Copyright (C) 2021-2024 Free Software Foundation, Inc.
See the end of the file for license conditions.
Please send Emacs bug reports to 'bug-gnu-emacs@gnu.org'.
@@ -27,6 +27,19 @@ applies, and please also update docstrings as needed.
* Startup Changes in Emacs 29.2
+** On GNU/Linux, Emacs is now the default application for 'org-protocol'.
+Org mode provides a way to quickly capture bookmarks, notes, and links
+using 'emacsclient':
+
+ emacsclient "org-protocol://store-link?url=URL&title=TITLE"
+
+Previously, users had to manually configure their GNU/Linux desktop
+environment to open 'org-protocol' links in Emacs. These links should
+now open in Emacs automatically, as the "emacsclient.desktop" file now
+arranges for Emacs to be the default application for the 'org-protocol'
+URI scheme. See the Org mode manual, Info node "(org) Protocols" for
+more details.
+
* Changes in Emacs 29.2
@@ -49,6 +62,11 @@ of showing the shortcuts.
* Incompatible Lisp Changes in Emacs 29.2
++++
+** 'with-sqlite-transaction' rolls back changes if its BODY fails.
+If the BODY of the macro signals an error, or committing the results
+of the transaction fails, the changes will now be rolled back.
+
* Lisp Changes in Emacs 29.2
diff --git a/etc/NEXTSTEP b/etc/NEXTSTEP
index 547f146c623..25c14c6af21 100644
--- a/etc/NEXTSTEP
+++ b/etc/NEXTSTEP
@@ -1,4 +1,4 @@
-Copyright (C) 2008-2023 Free Software Foundation, Inc.
+Copyright (C) 2008-2024 Free Software Foundation, Inc.
See the end of the file for license conditions.
This file contains information about GNU Emacs on "Nextstep" platforms.
diff --git a/etc/NXML-NEWS b/etc/NXML-NEWS
index 2bd2cc6e326..2efc4544f1e 100644
--- a/etc/NXML-NEWS
+++ b/etc/NXML-NEWS
@@ -1,4 +1,4 @@
-Copyright (C) 2007-2023 Free Software Foundation, Inc.
+Copyright (C) 2007-2024 Free Software Foundation, Inc.
See the end of the file for license conditions.
diff --git a/etc/ORG-NEWS b/etc/ORG-NEWS
index 5f92c056018..d07ce53ab20 100644
--- a/etc/ORG-NEWS
+++ b/etc/ORG-NEWS
@@ -6,7 +6,7 @@ ORG NEWS -- history of user-visible changes. -*- mode: org; coding: utf-8 -*-
#+LINK: msg https://list.orgmode.org/%s/
#+LINK: git https://git.savannah.gnu.org/cgit/emacs/org-mode.git/commit/?id=%s
-Copyright (C) 2012-2023 Free Software Foundation, Inc.
+Copyright (C) 2012-2024 Free Software Foundation, Inc.
See the end of the file for license conditions.
Please send Org bug reports to mailto:emacs-orgmode@gnu.org.
@@ -1098,7 +1098,7 @@ Conversion to SVG exposes a number of additional customizations that
give the user full control over the contents of the latex source
block. ~org-babel-latex-preamble~, ~org-babel-latex-begin-env~ and
~org-babel-latex-end-env~ are new customization options added to allow
-the user to specify the preamble and code that preceedes and proceeds
+the user to specify the preamble and code that precedes and proceeds
the contents of the source block.
*** New option ~org-html-meta-tags~ allows for HTML meta tags customization
diff --git a/etc/PROBLEMS b/etc/PROBLEMS
index c139f25e086..4d3b236ab03 100644
--- a/etc/PROBLEMS
+++ b/etc/PROBLEMS
@@ -1,6 +1,6 @@
Known Problems with GNU Emacs
-Copyright (C) 1987-1989, 1993-1999, 2001-2023 Free Software Foundation,
+Copyright (C) 1987-1989, 1993-1999, 2001-2024 Free Software Foundation,
Inc.
See the end of the file for license conditions.
@@ -441,6 +441,17 @@ environment.
** Keyboard problems
+*** PGTK build of Emacs running on Wayland doesn't recognize Hyper modifier
+
+If you arrange for the Wayland compositor to send the Hyper key
+modifier (e.g., via XKB customizations), the Hyper modifier will still
+not be reported to Emacs.
+
+The reason is that GDK 3.x doesn't recognize the Hyper key modifier.
+Since GDK 3.x is no longer developed, this bug in GDK will probably
+never be solved. And the Emacs PGTK build cannot yet support GTK4,
+where this problem is reportedly solved.
+
*** Unable to enter the M-| key on some German keyboards.
Some users have reported that M-| suffers from "keyboard ghosting".
This can't be fixed by Emacs, as the keypress never gets passed to it
@@ -521,7 +532,28 @@ The solution is to use gawk (GNU awk).
This is known to happen with GnuPG v2.4.1. The only known workaround
is to downgrade to a version of GnuPG older than 2.4.1 (or, in the
future, upgrade to a newer version which solves the problem, when such
-a fixed version becomes available).
+a fixed version becomes available). Note that GnuPG v2.2.42 and later
+also has this problem, so you should also avoid those later 2.2.4x
+versions; v2.2.41 is reported to work fine.
+
+*** EasyPG loopback pinentry does not work with gpgsm.
+
+This happens with the 'gpgsm' command from all versions of GnuPG.
+EasyPG relies on the machine-parseable interface that is provided by
+'gpg2' with option '--status-fd', but gpgsm does not support this.
+
+As a workaround, input the passphrase with a GUI-capable pinentry
+program like 'pinentry-gnome' or 'pinentry-qt5'. Alternatively, you
+can use the 'pinentry' package from Emacs 25.
+
+*** Emacs running on WSL receives stray characters as input.
+
+For example, you could see Emacs inserting 'z' characters even though
+nothing is typed on the keyboard, and even if you unplug the keyboard.
+
+The reason is a bug in the WSL X server's handling of key-press and
+key-repeat events. A workaround is to use the Cygwin or native
+MS-Windows build of Emacs instead.
** Problems with hostname resolution
@@ -816,7 +848,7 @@ On many systems, it is possible to set LD_LIBRARY_PATH in your
environment to specify additional directories where shared libraries
can be found.
-Other systems allow to set LD_RUN_PATH in a similar way, but before
+Other systems allow setting LD_RUN_PATH in a similar way, but before
Emacs is linked. With LD_RUN_PATH set, the linker will include a
specified run-time search path in the executable.
@@ -1638,6 +1670,18 @@ to normal, do
(set-scroll-bar-mode 'left)
+*** Redisplay with scaled images is slow in Emacs built with Cairo.
+
+Cairo expends a noticeable amount of CPU time displaying large images
+with applied transforms. These images most frequently appear within
+EWW buffers or in Image Mode buffers after executing the image scaling
+commands `i +' or `i -', and their presence incurs a performance
+penalty of hundereds of milliseconds to seconds upon redisplay. The
+remedy is to build Emacs without Cairo after verifying the XRender
+extension is present on your X server and its headers are present on
+your system, in which case Emacs will use XRender to efficiently
+perform image transforms within the X server.
+
*** Error messages about undefined colors on X.
The messages might say something like this:
@@ -1972,7 +2016,7 @@ remote X server, try this:
*** Dropping text on xterm doesn't work.
-Emacs sends sythetic button events to legacy clients such as xterm
+Emacs sends synthetic button events to legacy clients such as xterm
that do not support either the XDND or Motif drag-and-drop protocols
in order to "paste" the text that was dropped. Unfortunately, xterm
is configured to ignore these events by default. Add the following to
@@ -1985,6 +2029,16 @@ modern X servers have so many other ways to send input to clients
without signifying that the event is synthesized that it does not
matter.
+*** Programs which use XSendEvent cannot send input events to Emacs.
+
+Emacs built to use the X Input Extension cannot receive core input
+events sent through the SendEvent server request, since these events
+intercepted by the X server when sent to input extension clients.
+
+For such programs to function again, Emacs must be run on an X server
+where the input extension is disabled, or alternatively be configured
+with the "--without-xinput2" option.
+
* Runtime problems on character terminals
** The meta key does not work on xterm.
@@ -2508,7 +2562,7 @@ keyboard; printing that file on a PostScript printer will show what
keys can serve as Meta.
The 'xkeycaps' also shows a visual representation of the current
-keyboard settings. It also allows to modify them.
+keyboard settings. It also allows modifying them.
*** GNU/Linux: slow startup on Linux-based GNU systems.
@@ -2762,7 +2816,7 @@ one, you could use the following workarounds:
directory to that new home directory.
. Move all the *.eln files from ~/.emacs.d/eln-cache to a directory
out of the C:\Users tree, and customize Emacs to use that
- directory for *.eln files. This requires to call the function
+ directory for *.eln files. This requires calling the function
startup-redirect-eln-cache in your init file, to force Emacs to
write *.eln files compiled at run time to that directory.
. Delete all *.eln files in your ~/.emacs.d/eln-cache directory, and
@@ -3487,13 +3541,25 @@ The Microsoft scaler and FreeType promptly disregard such points.
Nothing in the TrueType specifications implies that points "hidden" in
this fashion should be afforded any special treatment, and thus Emacs
-eschews doing so. Consequentially, black streaks are displayed as
+eschews doing so. Consequently, black streaks are displayed as
Emacs interpolates glyph edges between points within the glyph and
points the test font attempts to hide.
Since this behavior does not influence the display of real fonts, no
action will be taken to address this problem.
+** Some other font's instruction code produces undesirable results.
+
+Executing instruction code is not a strict requirement for producing
+correct display results from most current fonts. If a font's
+instruction code produces results that are merely unpleasing, but not
+incorrect, then the font was presumably not designed for Emacs's
+scaler. If its uninstructed glyphs are satisfactory (such as if your
+screen resolution is high to the extent that scaling artifacts prove
+invisible), disable instruction code execution by appending its family
+name to the variable 'sfnt-uninstructable-font-regexp', then
+restarting Emacs.
+
** CJK text does not display in Emacs, but does in other programs.
When inserting CJK text into a buffer or visiting a file containing
@@ -3513,6 +3579,27 @@ port is a large undertaking that we are looking for volunteers to
perform. If you are interested in taking responsibility for this
task, please contact <emacs-devel@gnu.org>.
+** Emacs can only execute spasmodically in the background.
+
+Recent Android releases impose "battery optimization" on programs for
+which it is not expressly disabled; such optimization inhibits the
+execution of background services outside brief windows of time
+distributed at intervals of several dozens of minutes. Such programs
+as ERC which must send "keep-alive" packets at a rate beyond that at
+which these windows arrive consequently lose, yielding connection
+timeouts after Emacs has been in the background long enough that
+battery optimization enters into effect.
+
+This optimization can be disabled through the Settings app: navigate
+to "Apps & notifications", "Emacs", "Battery", "Battery Optimization",
+before clicking the drop-down menu labeled "Not Optimized", selecting
+the option "All Apps", scrolling to "Emacs", clicking on its entry and
+selecting "Don't Optimize" in the dialog box thus displayed.
+
+The organization of the Settings app might disagree with that
+illustrated above, which if true you should consult the documentation
+or any search mechanism for it.
+
* Build-time problems
** Configuration
diff --git a/etc/README b/etc/README
index 2884b0a039a..8ec120c1ce4 100644
--- a/etc/README
+++ b/etc/README
@@ -7,5 +7,5 @@ COPYRIGHT AND LICENSE INFORMATION FOR IMAGE FILES
File: emacs.icon
Author: Sun Microsystems, Inc
- Copyright (C) 1999, 2001-2023 Free Software Foundation, Inc.
+ Copyright (C) 1999, 2001-2024 Free Software Foundation, Inc.
License: GNU General Public License version 3 or later (see COPYING)
diff --git a/etc/TERMS b/etc/TERMS
index 444e194f8c0..b1b857c8391 100644
--- a/etc/TERMS
+++ b/etc/TERMS
@@ -1,4 +1,4 @@
-Copyright (C) 1999, 2001-2023 Free Software Foundation, Inc.
+Copyright (C) 1999, 2001-2024 Free Software Foundation, Inc.
See the end of the file for copying permissions.
This file describes what you must or might want to do to termcap entries
diff --git a/etc/TODO b/etc/TODO
index a918f496863..a3674c452a3 100644
--- a/etc/TODO
+++ b/etc/TODO
@@ -1,6 +1,6 @@
Emacs TODO List -*-outline-*-
-Copyright (C) 2001-2023 Free Software Foundation, Inc.
+Copyright (C) 2001-2024 Free Software Foundation, Inc.
See the end of the file for license conditions.
@@ -133,6 +133,20 @@ This should use a heuristic of some kind?
** In Emacs Info, examples of using Customize should be clickable
They should create Custom buffers when clicked.
+** Replacements under 'Info-hide-note-references' should be language-sensitive
+Currently, we replace the "*note" cross-reference indicators with a
+hard-coded "see", which is English-centric and doesn't look well in
+manuals written in languages other than English. To fix this, we need
+a change in the Texinfo's 'makeinfo' program so that it records the
+document's language (specified via the @documentlanguage directive in
+Texinfo) in a variable in the Local Variables section of the produced
+Info file. Then 'Info-fontify-node' should be modified to look up the
+translation of "see" to that language in a database (which should be
+added), and should use that translation instead of "see". See this
+discussion on the Texinfo mailing list for more details:
+
+ https://lists.gnu.org/archive/html/help-texinfo/2023-12/msg00011.html
+
** Add function to redraw the tool bar
** Redesign the load-history data structure
@@ -419,41 +433,6 @@ modify them. Also, when properties are looked up during redisplay, we
generally can't run Elisp code, whereas we generally can do that when
properties are added.
-*** Move overlays to intervals.c
-Currently overlays are implemented as (two) sorted singly linked lists (one
-for overlays_before some position and one for overlay_after that
-position, for some quirky definition of "before" and "after").
-The function 'overlay-recenter' changes the position used for the split
-(and is called internally in various situations).
-
-Each overlay is itself implemented with two markers (which keep track of
-the overlay-start and overlay-end). Markers are implemented as
-a non-sorted singly linked list of markers. So every text
-insertion/deletion requires O(N) time, where N is the number of markers
-since we have to go down that list to update those markers that are
-affected by the modification.
-
-You can start in src/buffer.[ch], maybe grepping for overlays_before for
-a starting point.
-
-Text-properties, OTOH, are implemented with a (mostly) balanced binary
-tree. This is implemented in src/intervals.[ch].
-
-So we'd like to change overlays so that they don't use markers (and we
-don't keep them in two sorted singly-linked lists) any more. Instead,
-we'll store them inside the balanced binary tree used for
-text-properties. I think we can use the "augmented tree" approach
-described in https://en.wikipedia.org/wiki/Interval_tree.
-
-To ease up debugging during development, I'd guess the implementation
-would first add the new stuff, keeping the old stuff (i.e. add to
-Lisp_Overlay whichever fields are needed for the new code, while keeping
-the old ones, add needed overlay fields to the intervals tree, but keep
-the old fields, the overlays_before etc...). This way, you can add
-consistency checks that make sure the new code computes the same results
-as the old code. And once that works well, we can remove the old code
-and old fields.
-
** Implement Unicode-compliant display of "default-ignorable" characters
See the "Characters Ignored for Display" section of paragraph 5.21 in
the Unicode Standard for the details.
@@ -473,6 +452,24 @@ wrapping of long lines under 'visual-line-mode'. The algorithm for
selecting the wrap point may also need be changed to break at the soft
hyphen.
+** Support external rules for indentation
+This should teach Emacs to read indentation rules from a file and use
+them in preference to the user customizations and the built-in
+defaults. An example of such rule files is '.clang-format', see
+
+ https://clang.llvm.org/docs/ClangFormatStyleOptions.html
+
+As a minimum, there should be a command, a variant of indent-region,
+which could be told to use the rules from such a file, and should then
+reformat the region of source code according to the rules.
+
+The next step is to use these rules during editing of files residing
+in a directory that has such an indentation-rules spec in it.
+
+For some discussion and implementation ideas (including possibly using
+LSP), see the thread starting at
+https://lists.gnu.org/archive/html/emacs-devel/2023-09/msg00609.html
+
** FFI (foreign function interface)
See eg https://lists.gnu.org/r/emacs-devel/2013-10/msg00246.html
@@ -480,15 +477,6 @@ One way of doing this is to start with fx's dynamic loading, and use it
to implement things like auto-loaded buffer parsers and database
access in cases which need more than Lisp.
-** Fix portable dumping so that you can redump without using -batch
-
-*** Redumps and native compiler "preloaded" sub-folder.
-In order to depose new .eln files being compiled into the "preloaded"
-sub-folder the native compiler needs to know in advance if this file
-will be preloaded or not. As .eln files are not moved afterwards
-subsequent redumps might refer to .eln file out of the "preloaded"
-sub-folder.
-
** Imenu could be extended into a file-structure browsing mechanism
This could use code like that of customize-groups.
@@ -905,6 +893,46 @@ It would make it easy to add (and remove) mappings like
* Things to be done for specific packages or features
+** Native compiler improvements
+
+*** Performance
+
+**** Intra compilation unit call optimization
+
+We could have a mechanism similar to what we use for optimizing calls
+to primitive functions. IE using a link table for each compilation
+unit (CU) such that calls from functions in a CU targeting functions
+in the same CU don't have to go through funcall. If one of these
+functions is redefined, a trampoline is compiled and installed to
+restore the redirection through funcall.
+
+*** Features to be improved or missing
+
+**** Diagnostic
+
+***** Filtering async warnings
+
+Add a new 'native-comp-async-report-warnings-errors' value such that
+we filter out all the uninteresting warnings (that the programmer
+already got during byte compilation) but we still report the important
+ones ('the function ‘xxx’ is not known to be defined.').
+
+This way even if the package developer doesn't use native compilation
+it can get the bug report for the issue and
+'*Async-native-compile-log*' is not too crowded.
+
+This new value for 'native-comp-async-report-warnings-errors' should
+be default.
+
+**** Fix portable dumping so that you can redump without using -batch
+
+***** Redumps and native compiler "preloaded" sub-folder.
+In order to depose new .eln files being compiled into the "preloaded"
+sub-folder the native compiler needs to know in advance if this file
+will be preloaded or not. As .eln files are not moved afterwards
+subsequent redumps might refer to .eln file out of the "preloaded"
+sub-folder.
+
** NeXTstep port
*** Missing features
@@ -1246,7 +1274,7 @@ Necessary for indirect buffers to work?
*** Locating schemas
-**** Should 'rng-validate-mode' allow to specify a schema?
+**** Should 'rng-validate-mode' allow specifying a schema?
Give the user an opportunity to specify a schema if there is currently
none? Or should it at least give a hint to the user how to specify a
non-vacuous schema?
diff --git a/etc/charsets/README b/etc/charsets/README
index 4916972b2d6..361a6449451 100644
--- a/etc/charsets/README
+++ b/etc/charsets/README
@@ -1,6 +1,6 @@
# README file for charset mapping files in this directory.
-# Copyright (C) 2003-2023 Free Software Foundation, Inc.
+# Copyright (C) 2003-2024 Free Software Foundation, Inc.
# Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
# National Institute of Advanced Industrial Science and Technology (AIST)
# Registration Number H13PRO009
diff --git a/etc/compilation.txt b/etc/compilation.txt
index 5f6ecb09cc2..c03d30afa79 100644
--- a/etc/compilation.txt
+++ b/etc/compilation.txt
@@ -702,7 +702,7 @@ Compilation segmentation fault at Thu Jul 13 10:55:49
Compilation finished at Thu Jul 21 15:02:15
-Copyright (C) 2004-2023 Free Software Foundation, Inc.
+Copyright (C) 2004-2024 Free Software Foundation, Inc.
COPYING PERMISSIONS:
diff --git a/etc/edt-user.el b/etc/edt-user.el
index 1a9216adaed..0813a97856d 100644
--- a/etc/edt-user.el
+++ b/etc/edt-user.el
@@ -1,6 +1,6 @@
;;; edt-user.el --- Sample user customizations for Emacs EDT emulation -*- lexical-binding: t -*-
-;; Copyright (C) 1986, 1992-1993, 2000-2023 Free Software Foundation,
+;; Copyright (C) 1986, 1992-1993, 2000-2024 Free Software Foundation,
;; Inc.
;; Author: Kevin Gallagher <kevin.gal@verizon.net>
diff --git a/etc/emacs-buffer.gdb b/etc/emacs-buffer.gdb
index dd01d48855c..e36452af004 100644
--- a/etc/emacs-buffer.gdb
+++ b/etc/emacs-buffer.gdb
@@ -1,6 +1,6 @@
# emacs-buffer.gdb --- gdb macros for recovering buffers from emacs coredumps
-# Copyright (C) 2005-2023 Free Software Foundation, Inc.
+# Copyright (C) 2005-2024 Free Software Foundation, Inc.
# Author: Noah Friedman <friedman@splode.com>
# Created: 2005-04-28
diff --git a/etc/emacs.metainfo.xml b/etc/emacs.metainfo.xml
index 65b0eda62ec..80bbd690217 100644
--- a/etc/emacs.metainfo.xml
+++ b/etc/emacs.metainfo.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2014-2023 Free Software Foundation, Inc. -->
+<!-- Copyright (C) 2014-2024 Free Software Foundation, Inc. -->
<component type="desktop-application">
<id>org.gnu.emacs</id>
<metadata_license>GFDL-1.3+</metadata_license>
diff --git a/etc/emacs_lldb.py b/etc/emacs_lldb.py
index 609815613bf..fdf4314e2d0 100644
--- a/etc/emacs_lldb.py
+++ b/etc/emacs_lldb.py
@@ -1,4 +1,4 @@
-# Copyright (C) 2022-2023 Free Software Foundation, Inc.
+# Copyright (C) 2022-2024 Free Software Foundation, Inc.
#
# This file is part of GNU Emacs.
#
@@ -78,22 +78,22 @@ class Lisp_Object:
# Object construction/initialization.
def __init__(self, lisp_obj):
- self.lisp_obj = lisp_obj
- self.frame = lisp_obj.GetFrame()
+ self.tagged = lisp_obj
+ self.unsigned = None
self.lisp_type = None
self.pvec_type = None
- self.value = None
+ self.untagged = None
self.init_unsigned()
self.init_lisp_types()
self.init_values()
def init_unsigned(self):
- if self.lisp_obj.GetNumChildren() != 0:
+ if self.tagged.GetType().GetTypeClass() == lldb.eTypeClassStruct:
# Lisp_Object is actually a struct.
- lisp_word = self.lisp_obj.GetValueForExpressionPath(".i")
+ lisp_word = self.tagged.GetValueForExpressionPath(".i")
self.unsigned = lisp_word.GetValueAsUnsigned()
else:
- self.unsigned = self.lisp_obj.GetValueAsUnsigned()
+ self.unsigned = self.tagged.GetValueAsUnsigned()
# Initialize self.lisp_type to the C Lisp_Type enumerator of the
# Lisp_Object, as a string. Initialize self.pvec_type likewise to
@@ -117,59 +117,64 @@ class Lisp_Object:
f">> More_Lisp_Bits::PSEUDOVECTOR_AREA_BITS)")
self.pvec_type = enumerator_name(typ)
- # Initialize self.value according to lisp_type and pvec_type.
+ # Initialize self.untagged according to lisp_type and pvec_type.
def init_values(self):
if self.lisp_type == "Lisp_Symbol":
offset = self.get_lisp_pointer("char").GetValueAsUnsigned()
- self.value = self.eval(f"(struct Lisp_Symbol *)"
- f" ((char *) &lispsym + {offset})")
+ self.untagged = self.eval(f"(struct Lisp_Symbol *)"
+ f" ((char *) &lispsym + {offset})",
+ True)
elif self.lisp_type == "Lisp_String":
- self.value = self.get_lisp_pointer("struct Lisp_String")
+ self.untagged = self.get_lisp_pointer("struct Lisp_String", True)
elif self.lisp_type == "Lisp_Vectorlike":
c_type = Lisp_Object.pvec2type[self.pvec_type]
- self.value = self.get_lisp_pointer(c_type)
+ self.untagged = self.get_lisp_pointer(c_type, True)
elif self.lisp_type == "Lisp_Cons":
- self.value = self.get_lisp_pointer("struct Lisp_Cons")
+ self.untagged = self.get_lisp_pointer("struct Lisp_Cons", True)
elif self.lisp_type == "Lisp_Float":
- self.value = self.get_lisp_pointer("struct Lisp_Float")
+ self.untagged = self.get_lisp_pointer("struct Lisp_Float", True)
elif self.lisp_type in ("Lisp_Int0", "Lisp_Int1"):
- self.value = self.eval(f"((EMACS_INT) {self.unsigned}) "
- f">> (GCTYPEBITS - 1)")
+ self.untagged = self.eval(f"((EMACS_INT) {self.unsigned}) "
+ f">> (GCTYPEBITS - 1)", True)
+ elif self.lisp_type == "Lisp_Type_Unused0":
+ self.untagged = self.unsigned
else:
- assert False, "Unknown Lisp type"
-
- # Create an SBValue for EXPR with name NAME.
- def create_value(self, name, expr):
- return self.lisp_obj.CreateValueFromExpression(name, expr)
+ assert False, f"Unknown Lisp type {self.lisp_type}"
# Evaluate EXPR in the context of the current frame.
- def eval(self, expr):
- return self.frame.EvaluateExpression(expr)
+ def eval(self, expr, make_var=False):
+ frame = self.tagged.GetFrame()
+ if make_var:
+ return frame.EvaluateExpression(expr)
+ options = lldb.SBExpressionOptions()
+ options.SetSuppressPersistentResult(True)
+ return frame.EvaluateExpression(expr, options)
# Return an SBValue for this object denoting a pointer of type
# TYP*.
- def get_lisp_pointer(self, typ):
+ def get_lisp_pointer(self, typ, make_var=False):
return self.eval(f"({typ}*) (((EMACS_INT) "
- f"{self.unsigned}) & VALMASK)")
+ f"{self.unsigned}) & VALMASK)",
+ make_var)
# If this is a Lisp_String, return an SBValue for its string data.
# Return None otherwise.
def get_string_data(self):
if self.lisp_type == "Lisp_String":
- return self.value.GetValueForExpressionPath("->u.s.data")
+ return self.untagged.GetValueForExpressionPath("->u.s.data")
return None
# if this is a Lisp_Symbol, return an SBBalue for its name.
# Return None otherwise.
def get_symbol_name(self):
if self.lisp_type == "Lisp_Symbol":
- name = self.value.GetValueForExpressionPath("->u.s.name")
+ name = self.untagged.GetValueForExpressionPath("->u.s.name")
return Lisp_Object(name).get_string_data()
return None
# Return a summary string for this object.
def summary(self):
- return str(self.value)
+ return str(self.untagged)
########################################################################
@@ -206,6 +211,50 @@ def xdebug_print(debugger, command, result, internal_dict):
def type_summary_Lisp_Object(obj, internal_dict):
return Lisp_Object(obj).summary()
+class Lisp_Object_Provider:
+ """Synthetic children provider for Lisp_Objects.
+ Supposedly only used by 'frame variable', where -P <n> can be used
+ to specify a printing depth. """
+ def __init__(self, valobj, internal_dict):
+ self.valobj = valobj
+ self.children = {}
+
+ def update(self):
+ lisp_obj = Lisp_Object(self.valobj)
+ lisp_type = lisp_obj.lisp_type
+ try:
+ if lisp_type == "Lisp_Symbol":
+ child = lisp_obj.get_symbol_name()
+ self.children["name"] = child
+ elif lisp_type == "Lisp_String":
+ child = lisp_obj.get_string_data()
+ self.children["data"] = child
+ elif lisp_type == "Lisp_Cons":
+ car = lisp_obj.untagged.GetValueForExpressionPath("->u.s.car")
+ cdr = lisp_obj.untagged.GetValueForExpressionPath("->u.s.u.cdr")
+ self.children["car"] = car
+ self.children["cdr"] = cdr
+ else:
+ self.children["untagged"] = lisp_obj.untagged
+ except:
+ print(f"*** exception in child provider update for {lisp_type}")
+ pass
+
+ def num_children(self):
+ return len(self.children)
+
+ def get_child_index(self, name):
+ index = 0
+ for child_name, child in self.children:
+ if child_name == name:
+ return index
+ index = index + 1
+ return -1
+
+ def get_child_at_index(self, index):
+ key = list(self.children)[index]
+ return self.children[key]
+
########################################################################
# Initialization
@@ -239,6 +288,17 @@ def define_type_summary(debugger, regex, function):
f"--python-function {python_function} "
+ regex)
+# Define Python class CLS as a children provider for the types
+# matching REFEXP. Providers are defined in the category Emacs, and
+# can be seen with 'type synthetic list -w Emacs', and deleted in a
+# similar way.
+def define_type_synthetic(debugger, regex, cls):
+ python_class = __name__ + "." + cls.__name__
+ debugger.HandleCommand(f"type synthetic add "
+ f"--category Emacs "
+ f"--python-class {python_class} "
+ + regex)
+
# Enable a given category of type summary providers.
def enable_type_category(debugger, category):
debugger.HandleCommand(f"type category enable {category}")
@@ -248,6 +308,7 @@ def __lldb_init_module(debugger, internal_dict):
define_command(debugger, xbacktrace)
define_command(debugger, xdebug_print)
define_type_summary(debugger, "Lisp_Object", type_summary_Lisp_Object)
+ define_type_synthetic(debugger, "Lisp_Object", Lisp_Object_Provider)
enable_type_category(debugger, "Emacs")
print('Emacs debugging support has been installed.')
diff --git a/etc/emacsclient-mail.desktop b/etc/emacsclient-mail.desktop
index 0a2420ddead..4f7f00ebefd 100644
--- a/etc/emacsclient-mail.desktop
+++ b/etc/emacsclient-mail.desktop
@@ -1,10 +1,7 @@
[Desktop Entry]
Categories=Network;Email;
Comment=GNU Emacs is an extensible, customizable text editor - and more
-# We want to pass the following commands to the shell wrapper:
-# u=$(echo "$1" | sed 's/[\"]/\\&/g'); exec emacsclient --alternate-editor= --display="$DISPLAY" --eval "(message-mailto \"$u\")"
-# Special chars '"', '$', and '\' must be escaped as '\\"', '\\$', and '\\\\'.
-Exec=sh -c "u=\\$(echo \\"\\$1\\" | sed 's/[\\\\\\"]/\\\\\\\\&/g'); exec emacsclient --alternate-editor= --display=\\"\\$DISPLAY\\" --eval \\"(message-mailto \\\\\\"\\$u\\\\\\")\\"" sh %u
+Exec=emacsclient --alternate-editor= --eval "(message-mailto (pop server-eval-args-left))" %u
Icon=emacs
Name=Emacs (Mail, Client)
MimeType=x-scheme-handler/mailto;
@@ -16,7 +13,7 @@ Actions=new-window;new-instance;
[Desktop Action new-window]
Name=New Window
-Exec=sh -c "u=\\$(echo \\"\\$1\\" | sed 's/[\\\\\\"]/\\\\\\\\&/g'); exec emacsclient --alternate-editor= --create-frame --eval \\"(message-mailto \\\\\\"\\$u\\\\\\")\\"" sh %u
+Exec=emacsclient --alternate-editor= --create-frame --eval "(message-mailto (pop server-eval-args-left))" %u
[Desktop Action new-instance]
Name=New Instance
diff --git a/etc/emacsclient.desktop b/etc/emacsclient.desktop
index a9f840c7033..4395d3b02bc 100644
--- a/etc/emacsclient.desktop
+++ b/etc/emacsclient.desktop
@@ -2,7 +2,7 @@
Name=Emacs (Client)
GenericName=Text Editor
Comment=Edit text
-MimeType=text/english;text/plain;text/x-makefile;text/x-c++hdr;text/x-c++src;text/x-chdr;text/x-csrc;text/x-java;text/x-moc;text/x-pascal;text/x-tcl;text/x-tex;application/x-shellscript;text/x-c;text/x-c++;
+MimeType=text/english;text/plain;text/x-makefile;text/x-c++hdr;text/x-c++src;text/x-chdr;text/x-csrc;text/x-java;text/x-moc;text/x-pascal;text/x-tcl;text/x-tex;application/x-shellscript;text/x-c;text/x-c++;x-scheme-handler/org-protocol;
Exec=sh -c "if [ -n \\"\\$*\\" ]; then exec emacsclient --alternate-editor= --display=\\"\\$DISPLAY\\" \\"\\$@\\"; else exec emacsclient --alternate-editor= --create-frame; fi" sh %F
Icon=emacs
Type=Application
diff --git a/etc/enriched.txt b/etc/enriched.txt
index 5828a6e68a7..a3bd3f21f5d 100644
--- a/etc/enriched.txt
+++ b/etc/enriched.txt
@@ -259,7 +259,7 @@ it.</indent>
-Copyright (C) 1995, 1997, 2001-2023 Free Software Foundation, Inc.
+Copyright (C) 1995, 1997, 2001-2024 Free Software Foundation, Inc.
COPYING PERMISSIONS:
diff --git a/etc/forms/forms-d2.el b/etc/forms/forms-d2.el
index afdf5119bb4..b1f378cbc39 100644
--- a/etc/forms/forms-d2.el
+++ b/etc/forms/forms-d2.el
@@ -1,6 +1,6 @@
;;; forms-d2.el --- demo forms-mode -*- lexical-binding:t -*-
-;; Copyright (C) 1991, 1994-1997, 2001-2023 Free Software Foundation,
+;; Copyright (C) 1991, 1994-1997, 2001-2024 Free Software Foundation,
;; Inc.
;; Author: Johan Vromans <jvromans@squirrel.nl>
diff --git a/etc/gnus-tut.txt b/etc/gnus-tut.txt
index 9212a81be27..02b4b7e2193 100644
--- a/etc/gnus-tut.txt
+++ b/etc/gnus-tut.txt
@@ -24,7 +24,7 @@ was done by moi, yours truly, your humble servant, Lars Magne
Ingebrigtsen. If you have a WWW browser, you can investigate to your
heart's delight at <URL:http://www.ifi.uio.no/~larsi/larsi.html>.
-;; Copyright (C) 1995, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1995, 2001-2024 Free Software Foundation, Inc.
;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
;; Keywords: news
diff --git a/etc/grep.txt b/etc/grep.txt
index 99e6d3641be..653123344dc 100644
--- a/etc/grep.txt
+++ b/etc/grep.txt
@@ -104,7 +104,7 @@ grep -nH -e "xyzxyz" ../info/*
* Miscellaneous
-Copyright (C) 2005-2023 Free Software Foundation, Inc.
+Copyright (C) 2005-2024 Free Software Foundation, Inc.
COPYING PERMISSIONS:
diff --git a/etc/images/README b/etc/images/README
index 5886f641536..a778d9ce6c3 100644
--- a/etc/images/README
+++ b/etc/images/README
@@ -27,19 +27,19 @@ COPYRIGHT AND LICENSE INFORMATION FOR IMAGE FILES
File: mh-logo.xpm
Author: Satyaki Das
- Copyright (C) 2003-2023 Free Software Foundation, Inc.
+ Copyright (C) 2003-2024 Free Software Foundation, Inc.
Files: gnus.pbm
Author: Luis Fernandes <elf@ee.ryerson.ca>
- Copyright (C) 2001-2023 Free Software Foundation, Inc.
+ Copyright (C) 2001-2024 Free Software Foundation, Inc.
Files: splash.png, splash.svg, splash.pbm, splash.xpm
Author: Francesc Rocher <francesc.rocher@gmail.com>
- Copyright (C) 2008-2023 Free Software Foundation, Inc.
+ Copyright (C) 2008-2024 Free Software Foundation, Inc.
Files: checked.xpm, unchecked.xpm
Author: Chong Yidong <cyd@stupidchicken.com>
- Copyright (C) 2010-2023 Free Software Foundation, Inc.
+ Copyright (C) 2010-2024 Free Software Foundation, Inc.
* The following icons are from GTK+ 2.x. They are not part of Emacs, but
@@ -67,21 +67,25 @@ Emacs images and their source in the GNOME icons stock/ directory:
attach.xpm document/stock_attach
bookmark_add.xpm actions/bookmark_add
cancel.xpm slightly modified generic/stock_stop
- connect.xpm net/stock_connect
+ commit.xpm code/stock_run
connect-to-url.xpm net/stock_connect-to-url
+ connect.xpm net/stock_connect
contact.xpm net/stock_contact
data-save.xpm data/stock_data-save
delete.xpm generic/stock_delete
describe.xpm generic/stock_properties
disconnect.xpm net/stock_disconnect
exit.xpm generic/stock_exit
+ gen-changelog.xpm text/stock_autoformat
+ ins-changelog.xpm form/stock_show-form-dialog
+ load-changelog.xpm text/stock_insert_endnote
lock-broken.xpm data/stock_lock-broken
lock-ok.xpm data/stock_lock-ok
lock.xpm data/stock_lock
- redo.xpm generic/stock_redo
- search-replace.xpm slightly modified generic/stock_search-and-replace
next-page.xpm navigation/stock_next-page
+ redo.xpm generic/stock_redo
refresh.xpm generic/stock_refresh
+ search-replace.xpm slightly modified generic/stock_search-and-replace
separator.xpm ?
show.xpm slightly modified document/stock_new
sort-ascending.xpm slightly modified data/stock_sort-ascending
@@ -89,6 +93,7 @@ Emacs images and their source in the GNOME icons stock/ directory:
sort-criteria.xpm data/stock_sort-criteria
sort-descending.xpm slightly modified data/stock_sort-descending
sort-row-ascending.xpm data/stock_sort-row-ascending
+ view-diff.xpm text/stock_list_enum-restart
zoom-in.xpm navigation/stock_zoom-in
zoom-out.xpm navigation/stock_zoom-out
diff --git a/etc/images/commit.pbm b/etc/images/commit.pbm
new file mode 100644
index 00000000000..11fe690ac1b
--- /dev/null
+++ b/etc/images/commit.pbm
Binary files differ
diff --git a/etc/images/commit.xpm b/etc/images/commit.xpm
new file mode 100644
index 00000000000..1730f155811
--- /dev/null
+++ b/etc/images/commit.xpm
@@ -0,0 +1,101 @@
+/* XPM */
+static char *commit[] = {
+/* columns rows colors chars-per-pixel */
+"24 24 71 1 ",
+" c None",
+". c black",
+"X c gray13",
+"o c gray14",
+"O c #252525",
+"+ c gray25",
+"@ c gray33",
+"# c #555555",
+"$ c #565656",
+"% c #5A5A5A",
+"& c #5D5D5D",
+"* c gray40",
+"= c #6C6C6C",
+"- c #DF421E",
+"; c #46A046",
+": c #625B81",
+"> c #887FA3",
+", c #848484",
+"< c gray53",
+"1 c #888888",
+"2 c #8E8E8E",
+"3 c #979797",
+"4 c #9A9A9A",
+"5 c #A0A0A0",
+"6 c gray65",
+"7 c #A9A9A9",
+"8 c #AEAEAE",
+"9 c gray75",
+"0 c #BBB6CA",
+"q c #C2C2C1",
+"w c gray76",
+"e c #C3C3C2",
+"r c #C3C3C3",
+"t c gray77",
+"y c #C7C7C6",
+"u c #C8C8C8",
+"i c gray79",
+"p c #C5C1D2",
+"a c #CAC6D6",
+"s c gray84",
+"d c #D8D8D8",
+"f c gray88",
+"g c #E1E1E1",
+"h c #E6E6E6",
+"j c #EDEDEB",
+"k c #EEEEED",
+"l c #EFEFEF",
+"z c #ECEAF0",
+"x c #ECEBF0",
+"c c #F0EFF3",
+"v c gray94",
+"b c #F1F1F0",
+"n c #F2F2F1",
+"m c #F4F4F3",
+"M c #F4F3F6",
+"N c #F5F5F4",
+"B c gray96",
+"V c #F6F6F5",
+"C c #F6F6F6",
+"Z c gray97",
+"A c #F8F8F7",
+"S c #F7F6F8",
+"D c #F8F8F8",
+"F c #F9F9F9",
+"G c gray98",
+"H c #FCFCFB",
+"J c gray99",
+"K c #FDFDFC",
+"L c #FDFDFD",
+"P c #FEFEFE",
+"I c white",
+/* pixels */
+" ...... ",
+" .xx00. ",
+" ..xp>>..",
+" .Spa>>>.",
+"+++++++++## .Mp>>. ",
+"IIIIIIIIIGs<o .c>. ",
+"IIIIIIIIIGhv5. .. ",
+"IIIIIIIIIGdIB3o ",
+"IIIIIIIIIBiIIg1X ",
+";:IIIIIIIB9gsiw2 ",
+"IIIIIIIIHB7*&#%<. ",
+":::G::::GBvsy64=. ",
+"GGGGGGGGGGGGGGG8. ",
+"--::G:::GGGGGGGw. ",
+"GGGGGGGGGGGGGGGy. ",
+"::A::AAAAAAAAAAy. ",
+"BBBBBBBBBBBBBBBy. ",
+"BBBBBBBBBBBBBBBw. ",
+":mmmmmmmmmmmmmmw. ",
+"vvvvvvvvvvvvvvvw. ",
+"---v:v:::v:::vvw. ",
+"lllllllllllllllw. ",
+"::::l--:lllllllw. ",
+"jjjjjjjjjjjjjjjw. "
+};
diff --git a/etc/images/custom/README b/etc/images/custom/README
index 7ed66523ecd..235303c3dd3 100644
--- a/etc/images/custom/README
+++ b/etc/images/custom/README
@@ -6,5 +6,5 @@ COPYRIGHT AND LICENSE INFORMATION FOR IMAGE FILES
Files: down.xpm down-pushed.xpm right.xpm right-pushed.xpm
Author: Juri Linkov
-Copyright (C) 2008-2023 Free Software Foundation, Inc.
+Copyright (C) 2008-2024 Free Software Foundation, Inc.
License: GNU General Public License version 3 or later (see COPYING)
diff --git a/etc/images/ezimage/README b/etc/images/ezimage/README
index 4d2482de515..02178819211 100644
--- a/etc/images/ezimage/README
+++ b/etc/images/ezimage/README
@@ -7,5 +7,5 @@ Files: bits.xpm bitsbang.xpm box-minus.xpm box-plus.xpm
tag-gt.xpm tag-minus.xpm tag-plus.xpm tag-type.xpm tag-v.xpm
tag.xpm unlock.xpm
Author: Eric M. Ludlam
-Copyright (C) 1999-2023 Free Software Foundation, Inc.
+Copyright (C) 1999-2024 Free Software Foundation, Inc.
License: GNU General Public License version 3 or later (see COPYING)
diff --git a/etc/images/gen-changelog.pbm b/etc/images/gen-changelog.pbm
new file mode 100644
index 00000000000..40bea125b06
--- /dev/null
+++ b/etc/images/gen-changelog.pbm
Binary files differ
diff --git a/etc/images/gen-changelog.xpm b/etc/images/gen-changelog.xpm
new file mode 100644
index 00000000000..65ea7c16f04
--- /dev/null
+++ b/etc/images/gen-changelog.xpm
@@ -0,0 +1,152 @@
+/* XPM */
+static char *gen_changelog[] = {
+/* columns rows colors chars-per-pixel */
+"24 24 122 2 ",
+" c None",
+". c black",
+"X c gray10",
+"o c #353535",
+"O c #442D0E",
+"+ c #5E4417",
+"@ c #7D5A22",
+"# c #645435",
+"$ c #464646",
+"% c #505050",
+"& c gray32",
+"* c #535353",
+"= c gray33",
+"- c #585858",
+"; c gray35",
+": c #675E46",
+"> c gray39",
+", c #6E6E6C",
+"< c gray43",
+"1 c gray44",
+"2 c #787775",
+"3 c #797979",
+"4 c #7B7B7B",
+"5 c #88601F",
+"6 c #A27E36",
+"7 c #9A8558",
+"8 c #9F8B5F",
+"9 c #A09069",
+"0 c #BAA069",
+"q c #C7AF7A",
+"w c #CCB176",
+"e c #868583",
+"r c #868686",
+"t c gray53",
+"y c #8B8A86",
+"u c #888888",
+"i c #898989",
+"p c #8B8B88",
+"a c gray54",
+"s c #8B8B8B",
+"d c #8C8C89",
+"f c gray55",
+"g c #8D8D8D",
+"h c #8E8E8E",
+"j c gray56",
+"k c #909090",
+"l c gray57",
+"z c #929292",
+"x c #939393",
+"c c #969592",
+"v c gray58",
+"b c #959595",
+"n c #979797",
+"m c #9B9996",
+"M c #9C9B97",
+"N c #B8B39B",
+"B c #A4A4A4",
+"V c gray65",
+"C c #A8A7A3",
+"Z c #AAAAAA",
+"A c #B0AFAC",
+"S c gray70",
+"D c #B4B4B4",
+"F c #B6B6B6",
+"G c #C0BFBD",
+"H c #D6C08E",
+"J c #D9C28B",
+"K c #DEC58D",
+"L c #D8C291",
+"P c #DFCA96",
+"I c #E1CC99",
+"U c #C2C1BD",
+"Y c #F3E5BE",
+"T c #C5C5C5",
+"R c #C6C6C6",
+"E c gray79",
+"W c #CACACA",
+"Q c gray80",
+"! c #CECECE",
+"~ c #D2D0D0",
+"^ c #DBDAD8",
+"/ c gray86",
+"( c gainsboro",
+") c #DDDDDD",
+"_ c #F4E7C2",
+"` c #EBE8D3",
+"' c gray88",
+"] c #E1E1E1",
+"[ c #E2E2E2",
+"{ c gray89",
+"} c #E4E4E4",
+"| c gray90",
+" . c #E6E6E6",
+".. c #E7E7E7",
+"X. c #EAE8E3",
+"o. c gray91",
+"O. c #E9E9E9",
+"+. c #EAEAEA",
+"@. c gray92",
+"#. c #EFEDE9",
+"$. c #ECECEC",
+"%. c gray93",
+"&. c #EEEEEE",
+"*. c #EFEFEF",
+"=. c #FEFCE8",
+"-. c #FEFEED",
+";. c gray94",
+":. c #F1F1F1",
+">. c gray95",
+",. c #F3F3F3",
+"<. c #F4F4F4",
+"1. c gray96",
+"2. c #F6F6F6",
+"3. c gray97",
+"4. c #F8F8F8",
+"5. c #F9F9F9",
+"6. c gray98",
+"7. c #FBFBFB",
+"8. c gray99",
+"9. c #FDFDFD",
+"0. c #FEFEFE",
+"q. c white",
+/* pixels */
+" . . . . . . . . . . . . . . . . . . . . ",
+". [ >.>.>.>.>.>.>.<.<.<.<.<.<.<.<.<.<.<.) . ",
+". >.[ [ [ [ [ } } } } o.o.o.o.o.$.$.$.$.$.. ",
+". >.[ r r r r i i ; . & i o.o.$.$.$.$.>.>.. ",
+". >.[ [ [ } } } [ . N . [ $.$.$.$.$.>.>.>.. ",
+". >.[ r i i i i < . ` . = g g g g >.>.>.>.. ",
+". >.} } } } } 3 . . -.. . 3 o.>.>.>.>.>.<.. ",
+". >.} i i ; . . : _ =.6 # . . D >.>.>.<.<.. ",
+". <.} } o.. 7 q J P Y w I K 8 . T <.<.<.<.. ",
+". <.} i i & . . O @ 0 5 + . . n <.<.<.<.<.. ",
+". <.o.o.o.o.[ k . . H . X $ . <.<.<.<.<.4.. ",
+". <.o.i g g g g > . L . ; d C . <.<.4.4.4.. ",
+". <.o.$.$.$.$.$.o.. 9 o . 2 G U . 4.4.4.4.. ",
+". <.o.g g g g g g & . 1 T . i ~ C . 4.4.9.. ",
+". <.$.$.$.$.>.>.>.>.T ) T T . M ^ A . 9.9.. ",
+". <.$.g g g g k >.<.<.<.) ) S . C #.c . 9.. ",
+". 4.>.>.>.>.>.<.<.<.<.4.4.[ E D . M X.e . . ",
+". 4.>.k k k k k k k k n n n [ Q B . m X.< . ",
+". >.>.<.<.<.<.<.<.4.4.4.4.9.9.} Q B . c X.2 . ",
+". E $.4.<.<.<.4.4.4.4.4.9.9.9.9.} Q Z . y X.2 . ",
+" . . . . . . . . . . . . . . . . . . . . y X.. ",
+" . . ",
+" ",
+" "
+};
diff --git a/etc/images/gnus/README b/etc/images/gnus/README
index f05cf0f7f10..40bdc103f11 100644
--- a/etc/images/gnus/README
+++ b/etc/images/gnus/README
@@ -7,7 +7,7 @@ COPYRIGHT AND LICENSE INFORMATION FOR IMAGE FILES
Files: important.xpm, unimportant.xpm
Author: Simon Josefsson <simon@josefsson.org>
-Copyright (C) 2001-2023 Free Software Foundation, Inc.
+Copyright (C) 2001-2024 Free Software Foundation, Inc.
Files: catchup.pbm catchup.xpm cu-exit.pbm cu-exit.xpm
describe-group.pbm describe-group.xpm exit-gnus.pbm exit-gnus.xpm
@@ -21,11 +21,11 @@ Files: catchup.pbm catchup.xpm cu-exit.pbm cu-exit.xpm
unsubscribe.pbm unsubscribe.xpm uu-decode.pbm uu-decode.xpm
uu-post.pbm uu-post.xpm
Author: Luis Fernandes <elf@ee.ryerson.ca>
-Copyright (C) 2001-2023 Free Software Foundation, Inc.
+Copyright (C) 2001-2024 Free Software Foundation, Inc.
Files: gnus.png, gnus.svg
Author: Francesc Rocher <rocher@member.fsf.org>
- Copyright (C) 2008-2023 Free Software Foundation, Inc.
+ Copyright (C) 2008-2024 Free Software Foundation, Inc.
* The following icons are from GNOME 2.x. They are not part of Emacs,
diff --git a/etc/images/gnus/gnus-pointer.svg b/etc/images/gnus/gnus-pointer.svg
new file mode 100644
index 00000000000..590e0f56d89
--- /dev/null
+++ b/etc/images/gnus/gnus-pointer.svg
@@ -0,0 +1,94 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Gnu Emacs Logo
+
+ Copyright (C) 2008-2024 Free Software Foundation, Inc.
+
+ Author: Francesc Rocher <f.rocher@member.fsf.org>
+
+ This file is part of GNU Emacs.
+
+ GNU Emacs is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ GNU Emacs is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+-->
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ width="23.6206187542"
+ height="16"
+ version="1.0"
+ style="display:inline"
+ id="svg1"
+ sodipodi:docname="gnus-pointer.svg"
+ inkscape:version="1.3 (0e150ed6c4, 2023-07-21)"
+ viewBox="0 0 167.68044 113.58242"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:dc="http://purl.org/dc/elements/1.1/">
+ <defs
+ id="defs1" />
+ <sodipodi:namedview
+ id="namedview1"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:showpageshadow="2"
+ inkscape:pageopacity="0.0"
+ inkscape:pagecheckerboard="0"
+ inkscape:deskcolor="#d1d1d1"
+ inkscape:zoom="2.7948886"
+ inkscape:cx="128.09097"
+ inkscape:cy="123.26073"
+ inkscape:current-layer="layer1" />
+ <metadata
+ id="metadata2166">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <cc:license
+ rdf:resource="https://www.gnu.org/copyleft/gpl.html" />
+ <dc:title>gnus</dc:title>
+ <dc:date>2008/06/28</dc:date>
+ <dc:creator>
+ <cc:Agent>
+ <dc:title>Francesc Rocher</dc:title>
+ </cc:Agent>
+ </dc:creator>
+ <dc:rights>
+ <cc:Agent>
+ <dc:title>GPL</dc:title>
+ </cc:Agent>
+ </dc:rights>
+ <dc:description>gnus icon image</dc:description>
+ <cc:license
+ rdf:resource="https://www.gnu.org/copyleft/gpl.html" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(-214.53867,-140.13329)">
+ <path
+ style="fill-opacity:1"
+ d="m 321.70896,253.17911 c -0.36667,-0.36666 -0.67201,-5.20416 -0.67854,-10.75 -0.019,-16.11278 -3.80254,-26.01429 -11.53101,-30.17635 -1.90142,-1.02398 -3.45712,-2.07087 -3.45712,-2.32642 0,-1.43357 10.45296,-16.08056 11.47604,-16.08056 2.47319,0 9.23725,5.87604 10.97182,9.53138 5.03752,10.61578 4.34103,30.55989 -1.50929,43.21862 -3.28874,7.11606 -3.93373,7.9215 -5.2719,6.58333 z m -77.16152,-8.46295 c -4.45468,-3.91126 -4.44465,-5.90837 0.0814,-16.20837 6.498,-14.78751 34.5082,-54.96722 36.7536,-52.72182 1.31908,1.31908 -1.58012,6.7064 -6.9201,12.85902 -5.10867,5.88611 -15.27729,21.00949 -18.79544,27.95371 -3.51862,6.94514 -2.86216,9.83677 2.56492,11.29813 2.18779,0.58911 5.33413,0.77321 6.99187,0.4091 6.2872,-1.3809 18.78154,-10.37638 34.82869,-25.07544 1.63528,-1.49791 2.98143,-2.00796 3.86245,-1.46346 2.11637,1.30799 -7.3484,14.40921 -15.90222,22.01199 -16.20847,14.40636 -27.60611,21.67016 -36.7152,23.39889 -2.68566,0.50969 -3.8489,0.0855 -6.75,-2.46175 z m 106.49485,-47.00332 c -2.5122,-0.71522 -8.01566,-5.45017 -19.5,-16.77699 -12.82987,-12.6539 -16.81552,-16.00934 -20.11602,-16.9353 -9.0949,-2.5516 -16.05869,-0.67634 -18.98403,5.11216 -1.7056,3.37495 -5.29744,7.73307 -6.37338,7.73307 -0.34364,0 -1.1778,-1.5293 -1.8537,-3.39846 -1.42445,-3.93926 -8.55314,-10.8615 -13.72556,-13.32805 -3.4655,-1.65258 -3.70255,-1.63465 -7.9122,0.59856 -2.38681,1.26621 -5.39614,3.78466 -6.68739,5.59656 -2.99038,4.19616 -18.42665,18.22292 -22.26047,20.22784 -3.6871,1.92819 -10.16611,1.16914 -12.83946,-1.5042 -1.25983,-1.25984 -2.63141,-5.30077 -3.84411,-11.32548 -1.03697,-5.15172 -2.08806,-10.26677 -2.33574,-11.36677 -0.24769,-1.1 0.16855,-2.83295 0.92497,-3.85101 1.33079,-1.79111 1.50083,-1.78047 5.25386,0.32885 2.13321,1.19893 4.96021,3.93001 6.28222,6.06908 2.91698,4.71978 6.42385,5.78889 11.14802,3.3986 5.61805,-2.84256 13.87615,-9.63484 17.51425,-14.40546 5.80084,-7.60662 11.27676,-12.99393 13.86896,-13.64453 1.35462,-0.33999 4.82023,0.14973 7.70136,1.08827 4.00736,1.3054 6.38479,2.98928 10.11649,7.16527 l 4.87808,5.45885 1.83587,-3.01884 c 2.46937,-4.06056 10.61011,-8.08908 16.34622,-8.08908 7.64657,0 14.07091,3.70799 23.59667,13.61949 4.6942,4.88428 9.67621,10.28189 11.07114,11.99468 9.1173,11.19486 23.8278,13.70046 29.6705,5.0537 1.25211,-1.85302 3.42939,-4.44884 4.83841,-5.7685 l 2.56185,-2.39937 -0.72231,3.87057 c -1.32367,7.09295 -6.50404,19.06241 -9.26864,21.41558 -8.2221,6.99849 -14.31844,9.03606 -21.18586,7.08091 z"
+ id="path1" />
+ </g>
+</svg>
diff --git a/etc/images/gnus/gnus.svg b/etc/images/gnus/gnus.svg
index 14f96da5e55..42aee872bf0 100644
--- a/etc/images/gnus/gnus.svg
+++ b/etc/images/gnus/gnus.svg
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Gnu Emacs Logo
- Copyright (C) 2008-2023 Free Software Foundation, Inc.
+ Copyright (C) 2008-2024 Free Software Foundation, Inc.
Author: Francesc Rocher <f.rocher@member.fsf.org>
diff --git a/etc/images/gud/README b/etc/images/gud/README
index 6a06a2671ac..6cdcce35fba 100644
--- a/etc/images/gud/README
+++ b/etc/images/gud/README
@@ -1,7 +1,7 @@
COPYRIGHT AND LICENSE INFORMATION FOR IMAGE FILES
The following icons were created by Nick Roberts <nickrob@snap.net.nz>.
-Copyright (C) 2002-2023 Free Software Foundation, Inc.
+Copyright (C) 2002-2024 Free Software Foundation, Inc.
License: GNU General Public License version 3 or later (see COPYING)
break.pbm, nexti.pbm, go.pbm, pp.pbm, print.pbm, pstar.pbm, remove.pbm
diff --git a/etc/images/icons/README b/etc/images/icons/README
index bb455980ca7..c7d755dc1b9 100644
--- a/etc/images/icons/README
+++ b/etc/images/icons/README
@@ -6,7 +6,7 @@ Files: hicolor/16x16/apps/emacs.png hicolor/24x24/apps/emacs.png
hicolor/scalable/mimetypes/emacs-document.svg
Author: Nicolas Petton <nicolas@petton.fr>
-Copyright (C) 2015-2023 Free Software Foundation, Inc.
+Copyright (C) 2015-2024 Free Software Foundation, Inc.
License: GNU General Public License version 3 or later (see COPYING)
Files: hicolor/16x16/apps/emacs23.png hicolor/24x24/apps/emacs23.png
@@ -14,7 +14,7 @@ Files: hicolor/16x16/apps/emacs23.png hicolor/24x24/apps/emacs23.png
hicolor/128x128/apps/emacs23.png hicolor/scalable/apps/emacs23.svg
Author: Kentaro Ohkouchi <nanasess@fsm.ne.jp>
-Copyright (C) 2007-2023 Free Software Foundation, Inc.
+Copyright (C) 2007-2024 Free Software Foundation, Inc.
License: GNU General Public License version 3 or later (see COPYING)
@@ -22,7 +22,7 @@ Files: hicolor/16x16/apps/emacs22.png hicolor/24x24/apps/emacs22.png
hicolor/32x32/apps/emacs22.png hicolor/48x48/apps/emacs22.png
Author: Andrew Zhilin <andrew_zhilin@yahoo.com>
-Copyright (C) 2005-2023 Free Software Foundation, Inc.
+Copyright (C) 2005-2024 Free Software Foundation, Inc.
License: GNU General Public License version 3 or later (see COPYING)
Files: allout-widgets-dark-bg/closed.png
@@ -71,5 +71,5 @@ Files: allout-widgets-dark-bg/closed.png
allout-widgets-light-bg/through-descender.xpm
Author: Ken Manheimer <ken.manheimer@gmail.com>
-Copyright (C) 2011-2023 Free Software Foundation, Inc.
+Copyright (C) 2011-2024 Free Software Foundation, Inc.
License: GNU General Public License version 3 or later (see COPYING)
diff --git a/etc/images/icons/hicolor/scalable/apps/emacs.svg b/etc/images/icons/hicolor/scalable/apps/emacs.svg
index a7da237a720..d352f184db2 100644
--- a/etc/images/icons/hicolor/scalable/apps/emacs.svg
+++ b/etc/images/icons/hicolor/scalable/apps/emacs.svg
@@ -15,7 +15,7 @@
id="metadata70"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><!-- Gnu Emacs Icon
- Copyright (C) 2008-2023 Free Software Foundation, Inc.
+ Copyright (C) 2008-2024 Free Software Foundation, Inc.
Author: Nicolas Petton <nicolas@petton.fr>
diff --git a/etc/images/icons/hicolor/scalable/apps/emacs23.svg b/etc/images/icons/hicolor/scalable/apps/emacs23.svg
index 966c265ffcf..a4122d67547 100644
--- a/etc/images/icons/hicolor/scalable/apps/emacs23.svg
+++ b/etc/images/icons/hicolor/scalable/apps/emacs23.svg
@@ -10,7 +10,7 @@
id="svg4768"
xml:space="preserve">
<!-- Gnu Emacs Icon
- Copyright (C) 2008-2023 Free Software Foundation, Inc.
+ Copyright (C) 2008-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/etc/images/icons/hicolor/scalable/mimetypes/emacs-document23.svg b/etc/images/icons/hicolor/scalable/mimetypes/emacs-document23.svg
index 23373c6ad08..7abcb917712 100644
--- a/etc/images/icons/hicolor/scalable/mimetypes/emacs-document23.svg
+++ b/etc/images/icons/hicolor/scalable/mimetypes/emacs-document23.svg
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Gnu Emacs Document Icon
- Copyright (C) 2008-2023 Free Software Foundation, Inc.
+ Copyright (C) 2008-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/etc/images/ins-changelog.pbm b/etc/images/ins-changelog.pbm
new file mode 100644
index 00000000000..fb97cf7d5d8
--- /dev/null
+++ b/etc/images/ins-changelog.pbm
@@ -0,0 +1,3 @@
+P4
+24 24
+ \ No newline at end of file
diff --git a/etc/images/ins-changelog.xpm b/etc/images/ins-changelog.xpm
new file mode 100644
index 00000000000..24deee3c344
--- /dev/null
+++ b/etc/images/ins-changelog.xpm
@@ -0,0 +1,67 @@
+/* XPM */
+static char *ins_changelog[] = {
+/* columns rows colors chars-per-pixel */
+"24 24 37 1 ",
+" c None",
+". c black",
+"X c #161616",
+"o c gray25",
+"O c #4B4B49",
+"+ c #5D5D5D",
+"@ c #494066",
+"# c #767676",
+"$ c gray52",
+"% c #A0A0A0",
+"& c gray66",
+"* c gray68",
+"= c #BBBBBB",
+"- c #BCBCBC",
+"; c gray74",
+": c #C1C1C1",
+"> c gray76",
+", c #C3C3C3",
+"< c gray88",
+"1 c #E2E2E2",
+"2 c gray89",
+"3 c #E4E4E4",
+"4 c gray90",
+"5 c #E6E6E6",
+"6 c #E7E7E7",
+"7 c gray91",
+"8 c #EAEAEA",
+"9 c gray92",
+"0 c #ECECEC",
+"q c gray93",
+"w c #EEEEEE",
+"e c #EFEFEF",
+"r c gray94",
+"t c #F1F1F1",
+"y c #FBFBFB",
+"u c #FDFDFD",
+"i c #FEFEFE",
+/* pixels */
+" ",
+" ",
+" @ @@ @@ @@ @@ ",
+" @ ",
+" @ ",
+" @ @ ",
+" @ ",
+" ......... ",
+" @ .iiiiiii2>. ",
+" @ .itttttt>y&. ",
+" .itttttt*#+o. ",
+" @ .it@@@@t2$OX. ",
+" @ .iteeeeeeee=. ",
+" .ie@@@@@@@e=. ",
+" @ .ieeeeeeee9=. ",
+" @ .ie@@@@@@@9=. ",
+" .i999999499=. ",
+" @@ @@ @@.i9@@@@@@@4=. ",
+" .i944444444=. ",
+" .i4@@@@@@@4=. ",
+" .i444444222=. ",
+" .>-----====%. ",
+" ........... ",
+" "
+};
diff --git a/etc/images/load-changelog.pbm b/etc/images/load-changelog.pbm
new file mode 100644
index 00000000000..43f1a1b221f
--- /dev/null
+++ b/etc/images/load-changelog.pbm
Binary files differ
diff --git a/etc/images/load-changelog.xpm b/etc/images/load-changelog.xpm
new file mode 100644
index 00000000000..6d317b6afa2
--- /dev/null
+++ b/etc/images/load-changelog.xpm
@@ -0,0 +1,82 @@
+/* XPM */
+static char *load_changelog[] = {
+/* columns rows colors chars-per-pixel */
+"24 24 52 1 ",
+" c None",
+". c black",
+"X c #434343",
+"o c gray33",
+"O c #DF421E",
+"+ c #8B8B8B",
+"@ c gray55",
+"# c #8D8D8D",
+"$ c #8E8E8E",
+"% c gray56",
+"& c #909090",
+"* c gray57",
+"= c #929292",
+"- c #939393",
+"; c gray58",
+": c #959595",
+"> c gray66",
+", c #B7B7B7",
+"< c gray74",
+"1 c #C0C0C0",
+"2 c gray79",
+"3 c #CACACA",
+"4 c gray84",
+"5 c gray85",
+"6 c #DADADA",
+"7 c #DDDDDD",
+"8 c #DFDFDF",
+"9 c gray90",
+"0 c gray91",
+"q c #E9E9E9",
+"w c #EAEAEA",
+"e c gray92",
+"r c #ECECEC",
+"t c gray93",
+"y c #EEEEEE",
+"u c #EFEFEF",
+"i c gray94",
+"p c #F1F1F1",
+"a c gray95",
+"s c #F3F3F3",
+"d c #F4F4F4",
+"f c gray96",
+"g c #F6F6F6",
+"h c gray97",
+"j c #F8F8F8",
+"k c #F9F9F9",
+"l c gray98",
+"z c #FBFBFB",
+"x c gray99",
+"c c #FDFDFD",
+"v c #FEFEFE",
+"b c white",
+/* pixels */
+" .. .. .. .. ",
+" .d3..51..7>..d,.. ",
+" .d00tttttiiiiddd4. ",
+" .d0+$$$$$$&&&$jjt. ",
+" .d00ttiiiidddjjX5. ",
+" .d0$$$&9OOOOcjj........",
+" .dttiiidddddjjjo7. .",
+" .dttiiiddddddjjc5. .",
+" .jiidddddjjjcccc7. .",
+" .ji&&&&&&;;;;;cc7. .",
+" .jiiiddddjjjjccc7. .",
+" .ji&&&&&;;;;cccc7. .",
+" .iiidddjjjjccccct. .",
+" .3tjdjjjjjccccct<. .",
+" ................ .",
+" .",
+" .",
+" . .",
+" .. .",
+" OOOOOOOOOOOOO ......",
+" OOOOOOOOOOOOO .. ",
+" . ",
+" ",
+" "
+};
diff --git a/etc/images/mpc/README b/etc/images/mpc/README
index 27e1b356dc5..17b347e13d6 100644
--- a/etc/images/mpc/README
+++ b/etc/images/mpc/README
@@ -2,5 +2,5 @@ COPYRIGHT AND LICENSE INFORMATION FOR IMAGE FILES
Files: add.xpm ffwd.xpm next.xpm pause.xpm play.xpm prev.xpm rewind.xpm stop.xpm
Author: Stefan Monnier <monnier@iro.umontreal.ca>
-Copyright (C) 2009-2023 Free Software Foundation, Inc.
+Copyright (C) 2009-2024 Free Software Foundation, Inc.
License: GNU General Public License version 3 or later (see COPYING)
diff --git a/etc/images/newsticker/README b/etc/images/newsticker/README
index dafa77ea186..65d1782829b 100644
--- a/etc/images/newsticker/README
+++ b/etc/images/newsticker/README
@@ -4,5 +4,5 @@ Files: browse-url.xpm get-all.xpm mark-immortal.xpm mark-read.xpm
narrow.xpm next-feed.xpm next-item.xpm prev-feed.xpm
prev-item.xpm rss-feed.png rss-feed.svg update.xpm
Author: Ulf Jasper
-Copyright (C) 2011-2023 Free Software Foundation, Inc.
+Copyright (C) 2011-2024 Free Software Foundation, Inc.
License: GNU General Public License version 3 or later (see COPYING)
diff --git a/etc/images/smilies/README b/etc/images/smilies/README
index 20a17376bf7..7e000ae7def 100644
--- a/etc/images/smilies/README
+++ b/etc/images/smilies/README
@@ -3,5 +3,5 @@ Files: blink.pbm blink.xpm braindamaged.xpm cry.xpm dead.xpm evil.xpm
sad.xpm smile.pbm smile.xpm wry.pbm wry.xpm
Authors: Reiner Steib, Simon Josefsson, Kai Grossjohann, Alex
Schroeder, Oliver Scholz, Per Abrahamsen, Kim F. Storm.
-Copyright (C) 1999-2023 Free Software Foundation, Inc.
+Copyright (C) 1999-2024 Free Software Foundation, Inc.
License: GNU General Public License version 3 or later (see COPYING)
diff --git a/etc/images/smilies/grayscale/README b/etc/images/smilies/grayscale/README
index 5b3422866dd..b41d7eb19d3 100644
--- a/etc/images/smilies/grayscale/README
+++ b/etc/images/smilies/grayscale/README
@@ -3,5 +3,5 @@ Files: blink.xpm braindamaged.xpm cry.xpm dead.xpm evil.xpm forced.xpm
frown.xpm grin.xpm indifferent.xpm reverse-smile.xpm sad.xpm
smile.xpm wry.xpm
Author: Adam Sjøgren
-Copyright (C) 2007-2023 Free Software Foundation, Inc.
+Copyright (C) 2007-2024 Free Software Foundation, Inc.
License: GNU General Public License version 3 or later (see COPYING)
diff --git a/etc/images/smilies/medium/README b/etc/images/smilies/medium/README
index 5b3422866dd..b41d7eb19d3 100644
--- a/etc/images/smilies/medium/README
+++ b/etc/images/smilies/medium/README
@@ -3,5 +3,5 @@ Files: blink.xpm braindamaged.xpm cry.xpm dead.xpm evil.xpm forced.xpm
frown.xpm grin.xpm indifferent.xpm reverse-smile.xpm sad.xpm
smile.xpm wry.xpm
Author: Adam Sjøgren
-Copyright (C) 2007-2023 Free Software Foundation, Inc.
+Copyright (C) 2007-2024 Free Software Foundation, Inc.
License: GNU General Public License version 3 or later (see COPYING)
diff --git a/etc/images/splash.svg b/etc/images/splash.svg
index cfb027b8f94..114b637bfaf 100644
--- a/etc/images/splash.svg
+++ b/etc/images/splash.svg
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Gnu Emacs Logo
- Copyright (C) 2008-2023 Free Software Foundation, Inc.
+ Copyright (C) 2008-2024 Free Software Foundation, Inc.
Author: Francesc Rocher <francesc.rocher@gmail.com>
Based on the original work by Luis Fernandes <elf@ee.ryerson.ca>
diff --git a/etc/images/symbols/README b/etc/images/symbols/README
index f69a4ba8760..24429302e63 100644
--- a/etc/images/symbols/README
+++ b/etc/images/symbols/README
@@ -4,7 +4,7 @@ COPYRIGHT AND LICENSE INFORMATION FOR IMAGE FILES
Files: *.svg
Author: Yuan Fu <casouri@gmail.com>
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
License: GNU General Public License version 3 or later (see COPYING)
How I made these icons: I made them with Figma, and exported them into
diff --git a/etc/images/symbols/dot_large_16.pbm b/etc/images/symbols/dot_large_16.pbm
new file mode 100644
index 00000000000..03154adb813
--- /dev/null
+++ b/etc/images/symbols/dot_large_16.pbm
Binary files differ
diff --git a/etc/images/symbols/dot_large_16.svg b/etc/images/symbols/dot_large_16.svg
new file mode 100644
index 00000000000..dcc8eee380b
--- /dev/null
+++ b/etc/images/symbols/dot_large_16.svg
@@ -0,0 +1,3 @@
+<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
+<circle cx="8" cy="8" r="6" />
+</svg>
diff --git a/etc/images/symbols/dot_medium_16.pbm b/etc/images/symbols/dot_medium_16.pbm
new file mode 100644
index 00000000000..d5af22f50c0
--- /dev/null
+++ b/etc/images/symbols/dot_medium_16.pbm
Binary files differ
diff --git a/etc/images/symbols/dot_medium_16.svg b/etc/images/symbols/dot_medium_16.svg
new file mode 100644
index 00000000000..18250ef12c6
--- /dev/null
+++ b/etc/images/symbols/dot_medium_16.svg
@@ -0,0 +1,3 @@
+<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
+<circle cx="8" cy="8" r="4" />
+</svg>
diff --git a/etc/images/symbols/dot_small_16.pbm b/etc/images/symbols/dot_small_16.pbm
new file mode 100644
index 00000000000..6feef99ef53
--- /dev/null
+++ b/etc/images/symbols/dot_small_16.pbm
Binary files differ
diff --git a/etc/images/symbols/dot_small_16.svg b/etc/images/symbols/dot_small_16.svg
new file mode 100644
index 00000000000..1d6a279b5dc
--- /dev/null
+++ b/etc/images/symbols/dot_small_16.svg
@@ -0,0 +1,3 @@
+<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
+<circle cx="8" cy="8" r="2" />
+</svg>
diff --git a/etc/images/symbols/minus_16.pbm b/etc/images/symbols/minus_16.pbm
index 4f73340f179..c564ca290d8 100644
--- a/etc/images/symbols/minus_16.pbm
+++ b/etc/images/symbols/minus_16.pbm
Binary files differ
diff --git a/etc/images/symbols/minus_16.svg b/etc/images/symbols/minus_16.svg
index 9cb61d8d379..f0769763e5d 100644
--- a/etc/images/symbols/minus_16.svg
+++ b/etc/images/symbols/minus_16.svg
@@ -1,3 +1,3 @@
<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<path d="M13 7H3V9H13V7Z" />
+<path d="M12.5 7H3.5V9H12.5V7Z" />
</svg>
diff --git a/etc/images/symbols/plus_16.pbm b/etc/images/symbols/plus_16.pbm
index c369231b636..2d8a45a5db4 100644
--- a/etc/images/symbols/plus_16.pbm
+++ b/etc/images/symbols/plus_16.pbm
Binary files differ
diff --git a/etc/images/symbols/plus_16.svg b/etc/images/symbols/plus_16.svg
index a4d2f84f318..573a5e5ca76 100644
--- a/etc/images/symbols/plus_16.svg
+++ b/etc/images/symbols/plus_16.svg
@@ -1,3 +1,3 @@
<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<path d="M9 3H7V7H3V9H7V13H9V9H13V7H9V3Z" />
+<path d="M9 3.5H7V7H3.5V9H7V12.5H9V9H12.5V7H9V3.5Z" />
</svg>
diff --git a/etc/images/tabs/README b/etc/images/tabs/README
index d9a1b814b72..1b646812882 100644
--- a/etc/images/tabs/README
+++ b/etc/images/tabs/README
@@ -4,5 +4,5 @@ COPYRIGHT AND LICENSE INFORMATION FOR IMAGE FILES
Files: close.xpm new.xpm left-arrow.xpm right-arrow.xpm
Author: Juri Linkov <juri@linkov.net>
-Copyright (C) 2019-2023 Free Software Foundation, Inc.
+Copyright (C) 2019-2024 Free Software Foundation, Inc.
License: GNU General Public License version 3 or later (see COPYING)
diff --git a/etc/images/tree-widget/default/README b/etc/images/tree-widget/default/README
index 88e9328d52e..16f98c82d8e 100644
--- a/etc/images/tree-widget/default/README
+++ b/etc/images/tree-widget/default/README
@@ -5,5 +5,5 @@ Files: close.png close.xpm empty.png empty.xpm end-guide.png end-guide.xpm
no-guide.png no-guide.xpm no-handle.png no-handle.xpm open.png
open.xpm
Author: David Ponce <david.ponce@wanadoo.fr>
-Copyright (C) 2004-2023 Free Software Foundation, Inc.
+Copyright (C) 2004-2024 Free Software Foundation, Inc.
License: GNU General Public License version 3 or later (see COPYING)
diff --git a/etc/images/tree-widget/folder/README b/etc/images/tree-widget/folder/README
index 992159dff2a..b3d11f20558 100644
--- a/etc/images/tree-widget/folder/README
+++ b/etc/images/tree-widget/folder/README
@@ -5,5 +5,5 @@ Files: close.png close.xpm empty.png empty.xpm end-guide.png
leaf.png leaf.xpm no-guide.png no-guide.xpm no-handle.png
no-handle.xpm open.png open.xpm
Author: David Ponce <david.ponce@wanadoo.fr>
-Copyright (C) 2004-2023 Free Software Foundation, Inc.
+Copyright (C) 2004-2024 Free Software Foundation, Inc.
License: GNU General Public License version 3 or later (see COPYING)
diff --git a/etc/images/view-diff.pbm b/etc/images/view-diff.pbm
new file mode 100644
index 00000000000..35aabdabb1e
--- /dev/null
+++ b/etc/images/view-diff.pbm
Binary files differ
diff --git a/etc/images/view-diff.xpm b/etc/images/view-diff.xpm
new file mode 100644
index 00000000000..3ebd0b3002b
--- /dev/null
+++ b/etc/images/view-diff.xpm
@@ -0,0 +1,93 @@
+/* XPM */
+static char *view_diff[] = {
+/* columns rows colors chars-per-pixel */
+"24 24 63 1 ",
+" c None",
+". c black",
+"X c gray43",
+"o c #6F6F6F",
+"O c gray44",
+"+ c #717171",
+"@ c #727272",
+"# c gray45",
+"$ c #747474",
+"% c gray46",
+"& c #767676",
+"* c #777777",
+"= c gray47",
+"- c #DF421E",
+"; c #E3846E",
+": c #838383",
+"> c gray74",
+", c #E19989",
+"< c #E29A8A",
+"1 c #E39B8B",
+"2 c #E59C8B",
+"3 c #E49C8C",
+"4 c #E4AB9E",
+"5 c #E8AEA1",
+"6 c #C5C5C5",
+"7 c gray79",
+"8 c gray81",
+"9 c #DADADA",
+"0 c gray86",
+"q c #DDDDDD",
+"w c #EAD4CE",
+"e c gray88",
+"r c #E1E1E1",
+"t c #E2E2E2",
+"y c gray89",
+"u c #E4E4E4",
+"i c gray90",
+"p c #E6E6E6",
+"a c #E7E7E7",
+"s c gray91",
+"d c #E9E9E9",
+"f c #EAEAEA",
+"g c gray92",
+"h c #ECECEC",
+"j c gray93",
+"k c #EEEEEE",
+"l c #EFEFEF",
+"z c gray94",
+"x c #F1F1F1",
+"c c gray95",
+"v c #F3F3F3",
+"b c #F4F4F4",
+"n c gray96",
+"m c #F6F6F6",
+"M c gray97",
+"N c #F8F8F8",
+"B c #F9F9F9",
+"V c gray98",
+"C c #FBFBFB",
+"Z c gray99",
+"A c #FDFDFD",
+"S c #FEFEFE",
+"D c white",
+/* pixels */
+" .................... ",
+".tcccccccbbbbbbbbbbbq. ",
+".ctttttiiiidddddhhhhh. ",
+".ctttti8Xidddddhhhhcc. ",
+".cttti8XXdd+++++++ccc. ",
+".ctiiiiiXddhhhhhhcccc. ",
+".c,---id+dd++++++$ccb. ",
+".ci,--dd+dhhhhchcccbb. ",
+".bi-,-dddhh+++$cbcbbb. ",
+".b-4d3dhhhhhccccbbbbb. ",
+".b-ddhhhhhhccccbbbNNN. ",
+".b-ddhhhhccccbbbbNNNN. ",
+".b;-whh6$0cccbbbbNNNN. ",
+".bd2-5h+c$b:$$$$$=NNZ. ",
+".bhhhhccq$bbbbbNNNNZZ. ",
+".bhhhcc0$qb$$$$==NZZZ. ",
+".Nccccc$$$bNNNNNZZZZZ. ",
+".NcccbbbbbNNNZZZZZZZZ. ",
+".ccbbbbbbNNNZZZZZZZZh. ",
+".7hNbbbNNNNNZZZZZZZh>. ",
+" .................... ",
+" ",
+" ",
+" "
+};
diff --git a/etc/org.gnu.emacs.defaults.gschema.xml b/etc/org.gnu.emacs.defaults.gschema.xml
index 06ff42c438f..9fedadb92c6 100644
--- a/etc/org.gnu.emacs.defaults.gschema.xml
+++ b/etc/org.gnu.emacs.defaults.gschema.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2019-2020, 2022-2023 Free Software Foundation, Inc. -->
+<!-- Copyright (C) 2019-2020, 2022-2024 Free Software Foundation, Inc. -->
<schemalist>
<schema id="org.gnu.emacs.defaults">
diff --git a/etc/org/README b/etc/org/README
index 3737c8df9ac..7944bcb207c 100644
--- a/etc/org/README
+++ b/etc/org/README
@@ -1,7 +1,7 @@
The files OrgOdtContentTemplate.xml and OrgOdtStyles.xml have the
following copyright information:
-Copyright (C) 2010-2023 Free Software Foundation, Inc.
+Copyright (C) 2010-2024 Free Software Foundation, Inc.
These files are part of GNU Emacs.
diff --git a/etc/ps-prin0.ps b/etc/ps-prin0.ps
index ba35337e4e4..a9471de2093 100644
--- a/etc/ps-prin0.ps
+++ b/etc/ps-prin0.ps
@@ -1,7 +1,7 @@
% === BEGIN ps-print prologue 0
% version: 6.0
-% Copyright (C) 2000-2023 Free Software Foundation, Inc.
+% Copyright (C) 2000-2024 Free Software Foundation, Inc.
% This file is part of GNU Emacs.
diff --git a/etc/ps-prin1.ps b/etc/ps-prin1.ps
index 37512a86ab9..34bde99c420 100644
--- a/etc/ps-prin1.ps
+++ b/etc/ps-prin1.ps
@@ -1,7 +1,7 @@
% === BEGIN ps-print prologue 1
% version: 6.1
-% Copyright (C) 2000-2023 Free Software Foundation, Inc.
+% Copyright (C) 2000-2024 Free Software Foundation, Inc.
% This file is part of GNU Emacs.
diff --git a/etc/publicsuffix.txt b/etc/publicsuffix.txt
index 9d0dfc04ea9..79248a73f04 100644
--- a/etc/publicsuffix.txt
+++ b/etc/publicsuffix.txt
@@ -1051,8 +1051,7 @@ fm
// fo : https://en.wikipedia.org/wiki/.fo
fo
-// fr : http://www.afnic.fr/
-// domaines descriptifs : https://www.afnic.fr/medias/documents/Cadre_legal/Afnic_Naming_Policy_12122016_VEN.pdf
+// fr : https://www.afnic.fr/ https://www.afnic.fr/wp-media/uploads/2022/12/afnic-naming-policy-2023-01-01.pdf
fr
asso.fr
com.fr
@@ -1060,22 +1059,11 @@ gouv.fr
nom.fr
prd.fr
tm.fr
-// domaines sectoriels : https://www.afnic.fr/en/products-and-services/the-fr-tld/sector-based-fr-domains-4.html
-aeroport.fr
-avocat.fr
+// Other SLDs now selfmanaged out of AFNIC range. Former "domaines sectoriels", still registration suffixes
avoues.fr
cci.fr
-chambagri.fr
-chirurgiens-dentistes.fr
-experts-comptables.fr
-geometre-expert.fr
greta.fr
huissier-justice.fr
-medecin.fr
-notaires.fr
-pharmacien.fr
-port.fr
-veterinaire.fr
// ga : https://en.wikipedia.org/wiki/.ga
ga
@@ -4070,555 +4058,8 @@ ac.mu
co.mu
or.mu
-// museum : http://about.museum/naming/
-// http://index.museum/
+// museum : https://welcome.museum/wp-content/uploads/2018/05/20180525-Registration-Policy-MUSEUM-EN_VF-2.pdf https://welcome.museum/buy-your-dot-museum-2/
museum
-academy.museum
-agriculture.museum
-air.museum
-airguard.museum
-alabama.museum
-alaska.museum
-amber.museum
-ambulance.museum
-american.museum
-americana.museum
-americanantiques.museum
-americanart.museum
-amsterdam.museum
-and.museum
-annefrank.museum
-anthro.museum
-anthropology.museum
-antiques.museum
-aquarium.museum
-arboretum.museum
-archaeological.museum
-archaeology.museum
-architecture.museum
-art.museum
-artanddesign.museum
-artcenter.museum
-artdeco.museum
-arteducation.museum
-artgallery.museum
-arts.museum
-artsandcrafts.museum
-asmatart.museum
-assassination.museum
-assisi.museum
-association.museum
-astronomy.museum
-atlanta.museum
-austin.museum
-australia.museum
-automotive.museum
-aviation.museum
-axis.museum
-badajoz.museum
-baghdad.museum
-bahn.museum
-bale.museum
-baltimore.museum
-barcelona.museum
-baseball.museum
-basel.museum
-baths.museum
-bauern.museum
-beauxarts.museum
-beeldengeluid.museum
-bellevue.museum
-bergbau.museum
-berkeley.museum
-berlin.museum
-bern.museum
-bible.museum
-bilbao.museum
-bill.museum
-birdart.museum
-birthplace.museum
-bonn.museum
-boston.museum
-botanical.museum
-botanicalgarden.museum
-botanicgarden.museum
-botany.museum
-brandywinevalley.museum
-brasil.museum
-bristol.museum
-british.museum
-britishcolumbia.museum
-broadcast.museum
-brunel.museum
-brussel.museum
-brussels.museum
-bruxelles.museum
-building.museum
-burghof.museum
-bus.museum
-bushey.museum
-cadaques.museum
-california.museum
-cambridge.museum
-can.museum
-canada.museum
-capebreton.museum
-carrier.museum
-cartoonart.museum
-casadelamoneda.museum
-castle.museum
-castres.museum
-celtic.museum
-center.museum
-chattanooga.museum
-cheltenham.museum
-chesapeakebay.museum
-chicago.museum
-children.museum
-childrens.museum
-childrensgarden.museum
-chiropractic.museum
-chocolate.museum
-christiansburg.museum
-cincinnati.museum
-cinema.museum
-circus.museum
-civilisation.museum
-civilization.museum
-civilwar.museum
-clinton.museum
-clock.museum
-coal.museum
-coastaldefence.museum
-cody.museum
-coldwar.museum
-collection.museum
-colonialwilliamsburg.museum
-coloradoplateau.museum
-columbia.museum
-columbus.museum
-communication.museum
-communications.museum
-community.museum
-computer.museum
-computerhistory.museum
-comunicações.museum
-contemporary.museum
-contemporaryart.museum
-convent.museum
-copenhagen.museum
-corporation.museum
-correios-e-telecomunicações.museum
-corvette.museum
-costume.museum
-countryestate.museum
-county.museum
-crafts.museum
-cranbrook.museum
-creation.museum
-cultural.museum
-culturalcenter.museum
-culture.museum
-cyber.museum
-cymru.museum
-dali.museum
-dallas.museum
-database.museum
-ddr.museum
-decorativearts.museum
-delaware.museum
-delmenhorst.museum
-denmark.museum
-depot.museum
-design.museum
-detroit.museum
-dinosaur.museum
-discovery.museum
-dolls.museum
-donostia.museum
-durham.museum
-eastafrica.museum
-eastcoast.museum
-education.museum
-educational.museum
-egyptian.museum
-eisenbahn.museum
-elburg.museum
-elvendrell.museum
-embroidery.museum
-encyclopedic.museum
-england.museum
-entomology.museum
-environment.museum
-environmentalconservation.museum
-epilepsy.museum
-essex.museum
-estate.museum
-ethnology.museum
-exeter.museum
-exhibition.museum
-family.museum
-farm.museum
-farmequipment.museum
-farmers.museum
-farmstead.museum
-field.museum
-figueres.museum
-filatelia.museum
-film.museum
-fineart.museum
-finearts.museum
-finland.museum
-flanders.museum
-florida.museum
-force.museum
-fortmissoula.museum
-fortworth.museum
-foundation.museum
-francaise.museum
-frankfurt.museum
-franziskaner.museum
-freemasonry.museum
-freiburg.museum
-fribourg.museum
-frog.museum
-fundacio.museum
-furniture.museum
-gallery.museum
-garden.museum
-gateway.museum
-geelvinck.museum
-gemological.museum
-geology.museum
-georgia.museum
-giessen.museum
-glas.museum
-glass.museum
-gorge.museum
-grandrapids.museum
-graz.museum
-guernsey.museum
-halloffame.museum
-hamburg.museum
-handson.museum
-harvestcelebration.museum
-hawaii.museum
-health.museum
-heimatunduhren.museum
-hellas.museum
-helsinki.museum
-hembygdsforbund.museum
-heritage.museum
-histoire.museum
-historical.museum
-historicalsociety.museum
-historichouses.museum
-historisch.museum
-historisches.museum
-history.museum
-historyofscience.museum
-horology.museum
-house.museum
-humanities.museum
-illustration.museum
-imageandsound.museum
-indian.museum
-indiana.museum
-indianapolis.museum
-indianmarket.museum
-intelligence.museum
-interactive.museum
-iraq.museum
-iron.museum
-isleofman.museum
-jamison.museum
-jefferson.museum
-jerusalem.museum
-jewelry.museum
-jewish.museum
-jewishart.museum
-jfk.museum
-journalism.museum
-judaica.museum
-judygarland.museum
-juedisches.museum
-juif.museum
-karate.museum
-karikatur.museum
-kids.museum
-koebenhavn.museum
-koeln.museum
-kunst.museum
-kunstsammlung.museum
-kunstunddesign.museum
-labor.museum
-labour.museum
-lajolla.museum
-lancashire.museum
-landes.museum
-lans.museum
-läns.museum
-larsson.museum
-lewismiller.museum
-lincoln.museum
-linz.museum
-living.museum
-livinghistory.museum
-localhistory.museum
-london.museum
-losangeles.museum
-louvre.museum
-loyalist.museum
-lucerne.museum
-luxembourg.museum
-luzern.museum
-mad.museum
-madrid.museum
-mallorca.museum
-manchester.museum
-mansion.museum
-mansions.museum
-manx.museum
-marburg.museum
-maritime.museum
-maritimo.museum
-maryland.museum
-marylhurst.museum
-media.museum
-medical.museum
-medizinhistorisches.museum
-meeres.museum
-memorial.museum
-mesaverde.museum
-michigan.museum
-midatlantic.museum
-military.museum
-mill.museum
-miners.museum
-mining.museum
-minnesota.museum
-missile.museum
-missoula.museum
-modern.museum
-moma.museum
-money.museum
-monmouth.museum
-monticello.museum
-montreal.museum
-moscow.museum
-motorcycle.museum
-muenchen.museum
-muenster.museum
-mulhouse.museum
-muncie.museum
-museet.museum
-museumcenter.museum
-museumvereniging.museum
-music.museum
-national.museum
-nationalfirearms.museum
-nationalheritage.museum
-nativeamerican.museum
-naturalhistory.museum
-naturalhistorymuseum.museum
-naturalsciences.museum
-nature.museum
-naturhistorisches.museum
-natuurwetenschappen.museum
-naumburg.museum
-naval.museum
-nebraska.museum
-neues.museum
-newhampshire.museum
-newjersey.museum
-newmexico.museum
-newport.museum
-newspaper.museum
-newyork.museum
-niepce.museum
-norfolk.museum
-north.museum
-nrw.museum
-nyc.museum
-nyny.museum
-oceanographic.museum
-oceanographique.museum
-omaha.museum
-online.museum
-ontario.museum
-openair.museum
-oregon.museum
-oregontrail.museum
-otago.museum
-oxford.museum
-pacific.museum
-paderborn.museum
-palace.museum
-paleo.museum
-palmsprings.museum
-panama.museum
-paris.museum
-pasadena.museum
-pharmacy.museum
-philadelphia.museum
-philadelphiaarea.museum
-philately.museum
-phoenix.museum
-photography.museum
-pilots.museum
-pittsburgh.museum
-planetarium.museum
-plantation.museum
-plants.museum
-plaza.museum
-portal.museum
-portland.museum
-portlligat.museum
-posts-and-telecommunications.museum
-preservation.museum
-presidio.museum
-press.museum
-project.museum
-public.museum
-pubol.museum
-quebec.museum
-railroad.museum
-railway.museum
-research.museum
-resistance.museum
-riodejaneiro.museum
-rochester.museum
-rockart.museum
-roma.museum
-russia.museum
-saintlouis.museum
-salem.museum
-salvadordali.museum
-salzburg.museum
-sandiego.museum
-sanfrancisco.museum
-santabarbara.museum
-santacruz.museum
-santafe.museum
-saskatchewan.museum
-satx.museum
-savannahga.museum
-schlesisches.museum
-schoenbrunn.museum
-schokoladen.museum
-school.museum
-schweiz.museum
-science.museum
-scienceandhistory.museum
-scienceandindustry.museum
-sciencecenter.museum
-sciencecenters.museum
-science-fiction.museum
-sciencehistory.museum
-sciences.museum
-sciencesnaturelles.museum
-scotland.museum
-seaport.museum
-settlement.museum
-settlers.museum
-shell.museum
-sherbrooke.museum
-sibenik.museum
-silk.museum
-ski.museum
-skole.museum
-society.museum
-sologne.museum
-soundandvision.museum
-southcarolina.museum
-southwest.museum
-space.museum
-spy.museum
-square.museum
-stadt.museum
-stalbans.museum
-starnberg.museum
-state.museum
-stateofdelaware.museum
-station.museum
-steam.museum
-steiermark.museum
-stjohn.museum
-stockholm.museum
-stpetersburg.museum
-stuttgart.museum
-suisse.museum
-surgeonshall.museum
-surrey.museum
-svizzera.museum
-sweden.museum
-sydney.museum
-tank.museum
-tcm.museum
-technology.museum
-telekommunikation.museum
-television.museum
-texas.museum
-textile.museum
-theater.museum
-time.museum
-timekeeping.museum
-topology.museum
-torino.museum
-touch.museum
-town.museum
-transport.museum
-tree.museum
-trolley.museum
-trust.museum
-trustee.museum
-uhren.museum
-ulm.museum
-undersea.museum
-university.museum
-usa.museum
-usantiques.museum
-usarts.museum
-uscountryestate.museum
-usculture.museum
-usdecorativearts.museum
-usgarden.museum
-ushistory.museum
-ushuaia.museum
-uslivinghistory.museum
-utah.museum
-uvic.museum
-valley.museum
-vantaa.museum
-versailles.museum
-viking.museum
-village.museum
-virginia.museum
-virtual.museum
-virtuel.museum
-vlaanderen.museum
-volkenkunde.museum
-wales.museum
-wallonie.museum
-war.museum
-washingtondc.museum
-watchandclock.museum
-watch-and-clock.museum
-western.museum
-westfalen.museum
-whaling.museum
-wildlife.museum
-williamsburg.museum
-windmill.museum
-workshop.museum
-york.museum
-yorkshire.museum
-yosemite.museum
-youth.museum
-zoological.museum
-zoology.museum
-ירושלים.museum
-иком.museum
// mv : https://en.wikipedia.org/wiki/.mv
// "mv" included because, contra Wikipedia, google.mv exists.
@@ -5694,52 +5135,60 @@ turystyka.pl
// Government domains
gov.pl
ap.gov.pl
+griw.gov.pl
ic.gov.pl
is.gov.pl
-us.gov.pl
kmpsp.gov.pl
+konsulat.gov.pl
kppsp.gov.pl
-kwpsp.gov.pl
-psp.gov.pl
-wskr.gov.pl
kwp.gov.pl
+kwpsp.gov.pl
+mup.gov.pl
mw.gov.pl
-ug.gov.pl
-um.gov.pl
-umig.gov.pl
-ugim.gov.pl
-upow.gov.pl
-uw.gov.pl
-starostwo.gov.pl
+oia.gov.pl
+oirm.gov.pl
+oke.gov.pl
+oow.gov.pl
+oschr.gov.pl
+oum.gov.pl
pa.gov.pl
+pinb.gov.pl
+piw.gov.pl
po.gov.pl
+pr.gov.pl
+psp.gov.pl
psse.gov.pl
pup.gov.pl
rzgw.gov.pl
sa.gov.pl
+sdn.gov.pl
+sko.gov.pl
so.gov.pl
sr.gov.pl
-wsa.gov.pl
-sko.gov.pl
+starostwo.gov.pl
+ug.gov.pl
+ugim.gov.pl
+um.gov.pl
+umig.gov.pl
+upow.gov.pl
+uppo.gov.pl
+us.gov.pl
+uw.gov.pl
uzs.gov.pl
+wif.gov.pl
wiih.gov.pl
winb.gov.pl
-pinb.gov.pl
wios.gov.pl
witd.gov.pl
-wzmiuw.gov.pl
-piw.gov.pl
wiw.gov.pl
-griw.gov.pl
-wif.gov.pl
-oum.gov.pl
-sdn.gov.pl
-zp.gov.pl
-uppo.gov.pl
-mup.gov.pl
+wkz.gov.pl
+wsa.gov.pl
+wskr.gov.pl
+wsse.gov.pl
wuoz.gov.pl
-konsulat.gov.pl
-oirm.gov.pl
+wzmiuw.gov.pl
+zp.gov.pl
+zpisdn.gov.pl
// pl regional domains (http://www.dns.pl/english/index.html)
augustow.pl
babia-gora.pl
@@ -5861,7 +5310,7 @@ zarow.pl
zgora.pl
zgorzelec.pl
-// pm : http://www.afnic.fr/medias/documents/AFNIC-naming-policy2012.pdf
+// pm : https://www.afnic.fr/wp-media/uploads/2022/12/afnic-naming-policy-2023-01-01.pdf
pm
// pn : http://www.government.pn/PnRegistry/policies.htm
@@ -5959,7 +5408,7 @@ net.qa
org.qa
sch.qa
-// re : http://www.afnic.re/obtenir/chartes/nommage-re/annexe-descriptifs
+// re : https://www.afnic.fr/wp-media/uploads/2022/12/afnic-naming-policy-2023-01-01.pdf
re
asso.re
com.re
@@ -6216,7 +5665,7 @@ td
// http://www.telnic.org/
tel
-// tf : https://en.wikipedia.org/wiki/.tf
+// tf : https://www.afnic.fr/wp-media/uploads/2022/12/afnic-naming-policy-2023-01-01.pdf
tf
// tg : https://en.wikipedia.org/wiki/.tg
@@ -6424,6 +5873,7 @@ kiev.ua
kirovograd.ua
km.ua
kr.ua
+kropyvnytskyi.ua
krym.ua
ks.ua
kv.ua
@@ -6431,6 +5881,7 @@ kyiv.ua
lg.ua
lt.ua
lugansk.ua
+luhansk.ua
lutsk.ua
lv.ua
lviv.ua
@@ -6454,11 +5905,13 @@ te.ua
ternopil.ua
uz.ua
uzhgorod.ua
+uzhhorod.ua
vinnica.ua
vinnytsia.ua
vn.ua
volyn.ua
yalta.ua
+zakarpattia.ua
zaporizhzhe.ua
zaporizhzhia.ua
zhitomir.ua
@@ -6570,7 +6023,6 @@ k12.ca.us
k12.co.us
k12.ct.us
k12.dc.us
-k12.de.us
k12.fl.us
k12.ga.us
k12.gu.us
@@ -6812,20 +6264,89 @@ k12.vi
net.vi
org.vi
-// vn : https://www.dot.vn/vnnic/vnnic/domainregistration.jsp
+// vn : https://www.vnnic.vn/en/domain/cctld-vn
+// https://vnnic.vn/sites/default/files/tailieu/vn.cctld.domains.txt
vn
+ac.vn
+ai.vn
+biz.vn
com.vn
-net.vn
-org.vn
edu.vn
gov.vn
-int.vn
-ac.vn
-biz.vn
+health.vn
+id.vn
info.vn
+int.vn
+io.vn
name.vn
+net.vn
+org.vn
pro.vn
-health.vn
+
+// vn geographical names
+angiang.vn
+bacgiang.vn
+backan.vn
+baclieu.vn
+bacninh.vn
+baria-vungtau.vn
+bentre.vn
+binhdinh.vn
+binhduong.vn
+binhphuoc.vn
+binhthuan.vn
+camau.vn
+cantho.vn
+caobang.vn
+daklak.vn
+daknong.vn
+danang.vn
+dienbien.vn
+dongnai.vn
+dongthap.vn
+gialai.vn
+hagiang.vn
+haiduong.vn
+haiphong.vn
+hanam.vn
+hanoi.vn
+hatinh.vn
+haugiang.vn
+hoabinh.vn
+hungyen.vn
+khanhhoa.vn
+kiengiang.vn
+kontum.vn
+laichau.vn
+lamdong.vn
+langson.vn
+laocai.vn
+longan.vn
+namdinh.vn
+nghean.vn
+ninhbinh.vn
+ninhthuan.vn
+phutho.vn
+phuyen.vn
+quangbinh.vn
+quangnam.vn
+quangngai.vn
+quangninh.vn
+quangtri.vn
+soctrang.vn
+sonla.vn
+tayninh.vn
+thaibinh.vn
+thainguyen.vn
+thanhhoa.vn
+thanhphohochiminh.vn
+thuathienhue.vn
+tiengiang.vn
+travinh.vn
+tuyenquang.vn
+vinhlong.vn
+vinhphuc.vn
+yenbai.vn
// vu : https://en.wikipedia.org/wiki/.vu
// http://www.vunic.vu/
@@ -6835,7 +6356,7 @@ edu.vu
net.vu
org.vu
-// wf : http://www.afnic.fr/medias/documents/AFNIC-naming-policy2012.pdf
+// wf : https://www.afnic.fr/wp-media/uploads/2022/12/afnic-naming-policy-2023-01-01.pdf
wf
// ws : https://en.wikipedia.org/wiki/.ws
@@ -6847,7 +6368,7 @@ org.ws
gov.ws
edu.ws
-// yt : http://www.afnic.fr/medias/documents/AFNIC-naming-policy2012.pdf
+// yt : https://www.afnic.fr/wp-media/uploads/2022/12/afnic-naming-policy-2023-01-01.pdf
yt
// IDN ccTLDs
@@ -7189,3447 +6710,4502 @@ org.zw
// newGTLDs
-// List of new gTLDs imported from https://www.icann.org/resources/registries/gtlds/v2/gtlds.json on 2023-03-18T15:13:13Z
+// List of new gTLDs imported from https://www.icann.org/resources/registries/gtlds/v2/gtlds.json on 2023-12-06T15:14:09Z
// This list is auto-generated, don't edit it manually.
-// aaa : 2015-02-26 American Automobile Association, Inc.
+// aaa : American Automobile Association, Inc.
+// https://www.iana.org/domains/root/db/aaa.html
aaa
-// aarp : 2015-05-21 AARP
+// aarp : AARP
+// https://www.iana.org/domains/root/db/aarp.html
aarp
-// abarth : 2015-07-30 Fiat Chrysler Automobiles N.V.
-abarth
-
-// abb : 2014-10-24 ABB Ltd
+// abb : ABB Ltd
+// https://www.iana.org/domains/root/db/abb.html
abb
-// abbott : 2014-07-24 Abbott Laboratories, Inc.
+// abbott : Abbott Laboratories, Inc.
+// https://www.iana.org/domains/root/db/abbott.html
abbott
-// abbvie : 2015-07-30 AbbVie Inc.
+// abbvie : AbbVie Inc.
+// https://www.iana.org/domains/root/db/abbvie.html
abbvie
-// abc : 2015-07-30 Disney Enterprises, Inc.
+// abc : Disney Enterprises, Inc.
+// https://www.iana.org/domains/root/db/abc.html
abc
-// able : 2015-06-25 Able Inc.
+// able : Able Inc.
+// https://www.iana.org/domains/root/db/able.html
able
-// abogado : 2014-04-24 Registry Services, LLC
+// abogado : Registry Services, LLC
+// https://www.iana.org/domains/root/db/abogado.html
abogado
-// abudhabi : 2015-07-30 Abu Dhabi Systems and Information Centre
+// abudhabi : Abu Dhabi Systems and Information Centre
+// https://www.iana.org/domains/root/db/abudhabi.html
abudhabi
-// academy : 2013-11-07 Binky Moon, LLC
+// academy : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/academy.html
academy
-// accenture : 2014-08-15 Accenture plc
+// accenture : Accenture plc
+// https://www.iana.org/domains/root/db/accenture.html
accenture
-// accountant : 2014-11-20 dot Accountant Limited
+// accountant : dot Accountant Limited
+// https://www.iana.org/domains/root/db/accountant.html
accountant
-// accountants : 2014-03-20 Binky Moon, LLC
+// accountants : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/accountants.html
accountants
-// aco : 2015-01-08 ACO Severin Ahlmann GmbH & Co. KG
+// aco : ACO Severin Ahlmann GmbH & Co. KG
+// https://www.iana.org/domains/root/db/aco.html
aco
-// actor : 2013-12-12 Dog Beach, LLC
+// actor : Dog Beach, LLC
+// https://www.iana.org/domains/root/db/actor.html
actor
-// ads : 2014-12-04 Charleston Road Registry Inc.
+// ads : Charleston Road Registry Inc.
+// https://www.iana.org/domains/root/db/ads.html
ads
-// adult : 2014-10-16 ICM Registry AD LLC
+// adult : ICM Registry AD LLC
+// https://www.iana.org/domains/root/db/adult.html
adult
-// aeg : 2015-03-19 Aktiebolaget Electrolux
+// aeg : Aktiebolaget Electrolux
+// https://www.iana.org/domains/root/db/aeg.html
aeg
-// aetna : 2015-05-21 Aetna Life Insurance Company
+// aetna : Aetna Life Insurance Company
+// https://www.iana.org/domains/root/db/aetna.html
aetna
-// afl : 2014-10-02 Australian Football League
+// afl : Australian Football League
+// https://www.iana.org/domains/root/db/afl.html
afl
-// africa : 2014-03-24 ZA Central Registry NPC trading as Registry.Africa
+// africa : ZA Central Registry NPC trading as Registry.Africa
+// https://www.iana.org/domains/root/db/africa.html
africa
-// agakhan : 2015-04-23 Fondation Aga Khan (Aga Khan Foundation)
+// agakhan : Fondation Aga Khan (Aga Khan Foundation)
+// https://www.iana.org/domains/root/db/agakhan.html
agakhan
-// agency : 2013-11-14 Binky Moon, LLC
+// agency : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/agency.html
agency
-// aig : 2014-12-18 American International Group, Inc.
+// aig : American International Group, Inc.
+// https://www.iana.org/domains/root/db/aig.html
aig
-// airbus : 2015-07-30 Airbus S.A.S.
+// airbus : Airbus S.A.S.
+// https://www.iana.org/domains/root/db/airbus.html
airbus
-// airforce : 2014-03-06 Dog Beach, LLC
+// airforce : Dog Beach, LLC
+// https://www.iana.org/domains/root/db/airforce.html
airforce
-// airtel : 2014-10-24 Bharti Airtel Limited
+// airtel : Bharti Airtel Limited
+// https://www.iana.org/domains/root/db/airtel.html
airtel
-// akdn : 2015-04-23 Fondation Aga Khan (Aga Khan Foundation)
+// akdn : Fondation Aga Khan (Aga Khan Foundation)
+// https://www.iana.org/domains/root/db/akdn.html
akdn
-// alfaromeo : 2015-07-31 Fiat Chrysler Automobiles N.V.
-alfaromeo
-
-// alibaba : 2015-01-15 Alibaba Group Holding Limited
+// alibaba : Alibaba Group Holding Limited
+// https://www.iana.org/domains/root/db/alibaba.html
alibaba
-// alipay : 2015-01-15 Alibaba Group Holding Limited
+// alipay : Alibaba Group Holding Limited
+// https://www.iana.org/domains/root/db/alipay.html
alipay
-// allfinanz : 2014-07-03 Allfinanz Deutsche Vermögensberatung Aktiengesellschaft
+// allfinanz : Allfinanz Deutsche Vermögensberatung Aktiengesellschaft
+// https://www.iana.org/domains/root/db/allfinanz.html
allfinanz
-// allstate : 2015-07-31 Allstate Fire and Casualty Insurance Company
+// allstate : Allstate Fire and Casualty Insurance Company
+// https://www.iana.org/domains/root/db/allstate.html
allstate
-// ally : 2015-06-18 Ally Financial Inc.
+// ally : Ally Financial Inc.
+// https://www.iana.org/domains/root/db/ally.html
ally
-// alsace : 2014-07-02 Region Grand Est
+// alsace : Region Grand Est
+// https://www.iana.org/domains/root/db/alsace.html
alsace
-// alstom : 2015-07-30 ALSTOM
+// alstom : ALSTOM
+// https://www.iana.org/domains/root/db/alstom.html
alstom
-// amazon : 2019-12-19 Amazon Registry Services, Inc.
+// amazon : Amazon Registry Services, Inc.
+// https://www.iana.org/domains/root/db/amazon.html
amazon
-// americanexpress : 2015-07-31 American Express Travel Related Services Company, Inc.
+// americanexpress : American Express Travel Related Services Company, Inc.
+// https://www.iana.org/domains/root/db/americanexpress.html
americanexpress
-// americanfamily : 2015-07-23 AmFam, Inc.
+// americanfamily : AmFam, Inc.
+// https://www.iana.org/domains/root/db/americanfamily.html
americanfamily
-// amex : 2015-07-31 American Express Travel Related Services Company, Inc.
+// amex : American Express Travel Related Services Company, Inc.
+// https://www.iana.org/domains/root/db/amex.html
amex
-// amfam : 2015-07-23 AmFam, Inc.
+// amfam : AmFam, Inc.
+// https://www.iana.org/domains/root/db/amfam.html
amfam
-// amica : 2015-05-28 Amica Mutual Insurance Company
+// amica : Amica Mutual Insurance Company
+// https://www.iana.org/domains/root/db/amica.html
amica
-// amsterdam : 2014-07-24 Gemeente Amsterdam
+// amsterdam : Gemeente Amsterdam
+// https://www.iana.org/domains/root/db/amsterdam.html
amsterdam
-// analytics : 2014-12-18 Campus IP LLC
+// analytics : Campus IP LLC
+// https://www.iana.org/domains/root/db/analytics.html
analytics
-// android : 2014-08-07 Charleston Road Registry Inc.
+// android : Charleston Road Registry Inc.
+// https://www.iana.org/domains/root/db/android.html
android
-// anquan : 2015-01-08 Beijing Qihu Keji Co., Ltd.
+// anquan : Beijing Qihu Keji Co., Ltd.
+// https://www.iana.org/domains/root/db/anquan.html
anquan
-// anz : 2015-07-31 Australia and New Zealand Banking Group Limited
+// anz : Australia and New Zealand Banking Group Limited
+// https://www.iana.org/domains/root/db/anz.html
anz
-// aol : 2015-09-17 Oath Inc.
+// aol : Oath Inc.
+// https://www.iana.org/domains/root/db/aol.html
aol
-// apartments : 2014-12-11 Binky Moon, LLC
+// apartments : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/apartments.html
apartments
-// app : 2015-05-14 Charleston Road Registry Inc.
+// app : Charleston Road Registry Inc.
+// https://www.iana.org/domains/root/db/app.html
app
-// apple : 2015-05-14 Apple Inc.
+// apple : Apple Inc.
+// https://www.iana.org/domains/root/db/apple.html
apple
-// aquarelle : 2014-07-24 Aquarelle.com
+// aquarelle : Aquarelle.com
+// https://www.iana.org/domains/root/db/aquarelle.html
aquarelle
-// arab : 2015-11-12 League of Arab States
+// arab : League of Arab States
+// https://www.iana.org/domains/root/db/arab.html
arab
-// aramco : 2014-11-20 Aramco Services Company
+// aramco : Aramco Services Company
+// https://www.iana.org/domains/root/db/aramco.html
aramco
-// archi : 2014-02-06 Identity Digital Limited
+// archi : Identity Digital Limited
+// https://www.iana.org/domains/root/db/archi.html
archi
-// army : 2014-03-06 Dog Beach, LLC
+// army : Dog Beach, LLC
+// https://www.iana.org/domains/root/db/army.html
army
-// art : 2016-03-24 UK Creative Ideas Limited
+// art : UK Creative Ideas Limited
+// https://www.iana.org/domains/root/db/art.html
art
-// arte : 2014-12-11 Association Relative à la Télévision Européenne G.E.I.E.
+// arte : Association Relative à la Télévision Européenne G.E.I.E.
+// https://www.iana.org/domains/root/db/arte.html
arte
-// asda : 2015-07-31 Wal-Mart Stores, Inc.
+// asda : Wal-Mart Stores, Inc.
+// https://www.iana.org/domains/root/db/asda.html
asda
-// associates : 2014-03-06 Binky Moon, LLC
+// associates : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/associates.html
associates
-// athleta : 2015-07-30 The Gap, Inc.
+// athleta : The Gap, Inc.
+// https://www.iana.org/domains/root/db/athleta.html
athleta
-// attorney : 2014-03-20 Dog Beach, LLC
+// attorney : Dog Beach, LLC
+// https://www.iana.org/domains/root/db/attorney.html
attorney
-// auction : 2014-03-20 Dog Beach, LLC
+// auction : Dog Beach, LLC
+// https://www.iana.org/domains/root/db/auction.html
auction
-// audi : 2015-05-21 AUDI Aktiengesellschaft
+// audi : AUDI Aktiengesellschaft
+// https://www.iana.org/domains/root/db/audi.html
audi
-// audible : 2015-06-25 Amazon Registry Services, Inc.
+// audible : Amazon Registry Services, Inc.
+// https://www.iana.org/domains/root/db/audible.html
audible
-// audio : 2014-03-20 XYZ.COM LLC
+// audio : XYZ.COM LLC
+// https://www.iana.org/domains/root/db/audio.html
audio
-// auspost : 2015-08-13 Australian Postal Corporation
+// auspost : Australian Postal Corporation
+// https://www.iana.org/domains/root/db/auspost.html
auspost
-// author : 2014-12-18 Amazon Registry Services, Inc.
+// author : Amazon Registry Services, Inc.
+// https://www.iana.org/domains/root/db/author.html
author
-// auto : 2014-11-13 XYZ.COM LLC
+// auto : XYZ.COM LLC
+// https://www.iana.org/domains/root/db/auto.html
auto
-// autos : 2014-01-09 XYZ.COM LLC
+// autos : XYZ.COM LLC
+// https://www.iana.org/domains/root/db/autos.html
autos
-// avianca : 2015-01-08 Avianca Inc.
+// avianca : Avianca Inc.
+// https://www.iana.org/domains/root/db/avianca.html
avianca
-// aws : 2015-06-25 AWS Registry LLC
+// aws : AWS Registry LLC
+// https://www.iana.org/domains/root/db/aws.html
aws
-// axa : 2013-12-19 AXA Group Operations SAS
+// axa : AXA Group Operations SAS
+// https://www.iana.org/domains/root/db/axa.html
axa
-// azure : 2014-12-18 Microsoft Corporation
+// azure : Microsoft Corporation
+// https://www.iana.org/domains/root/db/azure.html
azure
-// baby : 2015-04-09 XYZ.COM LLC
+// baby : XYZ.COM LLC
+// https://www.iana.org/domains/root/db/baby.html
baby
-// baidu : 2015-01-08 Baidu, Inc.
+// baidu : Baidu, Inc.
+// https://www.iana.org/domains/root/db/baidu.html
baidu
-// banamex : 2015-07-30 Citigroup Inc.
+// banamex : Citigroup Inc.
+// https://www.iana.org/domains/root/db/banamex.html
banamex
-// bananarepublic : 2015-07-31 The Gap, Inc.
+// bananarepublic : The Gap, Inc.
+// https://www.iana.org/domains/root/db/bananarepublic.html
bananarepublic
-// band : 2014-06-12 Dog Beach, LLC
+// band : Dog Beach, LLC
+// https://www.iana.org/domains/root/db/band.html
band
-// bank : 2014-09-25 fTLD Registry Services LLC
+// bank : fTLD Registry Services LLC
+// https://www.iana.org/domains/root/db/bank.html
bank
-// bar : 2013-12-12 Punto 2012 Sociedad Anonima Promotora de Inversion de Capital Variable
+// bar : Punto 2012 Sociedad Anonima Promotora de Inversion de Capital Variable
+// https://www.iana.org/domains/root/db/bar.html
bar
-// barcelona : 2014-07-24 Municipi de Barcelona
+// barcelona : Municipi de Barcelona
+// https://www.iana.org/domains/root/db/barcelona.html
barcelona
-// barclaycard : 2014-11-20 Barclays Bank PLC
+// barclaycard : Barclays Bank PLC
+// https://www.iana.org/domains/root/db/barclaycard.html
barclaycard
-// barclays : 2014-11-20 Barclays Bank PLC
+// barclays : Barclays Bank PLC
+// https://www.iana.org/domains/root/db/barclays.html
barclays
-// barefoot : 2015-06-11 Gallo Vineyards, Inc.
+// barefoot : Gallo Vineyards, Inc.
+// https://www.iana.org/domains/root/db/barefoot.html
barefoot
-// bargains : 2013-11-14 Binky Moon, LLC
+// bargains : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/bargains.html
bargains
-// baseball : 2015-10-29 MLB Advanced Media DH, LLC
+// baseball : MLB Advanced Media DH, LLC
+// https://www.iana.org/domains/root/db/baseball.html
baseball
-// basketball : 2015-08-20 Fédération Internationale de Basketball (FIBA)
+// basketball : Fédération Internationale de Basketball (FIBA)
+// https://www.iana.org/domains/root/db/basketball.html
basketball
-// bauhaus : 2014-04-17 Werkhaus GmbH
+// bauhaus : Werkhaus GmbH
+// https://www.iana.org/domains/root/db/bauhaus.html
bauhaus
-// bayern : 2014-01-23 Bayern Connect GmbH
+// bayern : Bayern Connect GmbH
+// https://www.iana.org/domains/root/db/bayern.html
bayern
-// bbc : 2014-12-18 British Broadcasting Corporation
+// bbc : British Broadcasting Corporation
+// https://www.iana.org/domains/root/db/bbc.html
bbc
-// bbt : 2015-07-23 BB&T Corporation
+// bbt : BB&T Corporation
+// https://www.iana.org/domains/root/db/bbt.html
bbt
-// bbva : 2014-10-02 BANCO BILBAO VIZCAYA ARGENTARIA, S.A.
+// bbva : BANCO BILBAO VIZCAYA ARGENTARIA, S.A.
+// https://www.iana.org/domains/root/db/bbva.html
bbva
-// bcg : 2015-04-02 The Boston Consulting Group, Inc.
+// bcg : The Boston Consulting Group, Inc.
+// https://www.iana.org/domains/root/db/bcg.html
bcg
-// bcn : 2014-07-24 Municipi de Barcelona
+// bcn : Municipi de Barcelona
+// https://www.iana.org/domains/root/db/bcn.html
bcn
-// beats : 2015-05-14 Beats Electronics, LLC
+// beats : Beats Electronics, LLC
+// https://www.iana.org/domains/root/db/beats.html
beats
-// beauty : 2015-12-03 XYZ.COM LLC
+// beauty : XYZ.COM LLC
+// https://www.iana.org/domains/root/db/beauty.html
beauty
-// beer : 2014-01-09 Registry Services, LLC
+// beer : Registry Services, LLC
+// https://www.iana.org/domains/root/db/beer.html
beer
-// bentley : 2014-12-18 Bentley Motors Limited
+// bentley : Bentley Motors Limited
+// https://www.iana.org/domains/root/db/bentley.html
bentley
-// berlin : 2013-10-31 dotBERLIN GmbH & Co. KG
+// berlin : dotBERLIN GmbH & Co. KG
+// https://www.iana.org/domains/root/db/berlin.html
berlin
-// best : 2013-12-19 BestTLD Pty Ltd
+// best : BestTLD Pty Ltd
+// https://www.iana.org/domains/root/db/best.html
best
-// bestbuy : 2015-07-31 BBY Solutions, Inc.
+// bestbuy : BBY Solutions, Inc.
+// https://www.iana.org/domains/root/db/bestbuy.html
bestbuy
-// bet : 2015-05-07 Identity Digital Limited
+// bet : Identity Digital Limited
+// https://www.iana.org/domains/root/db/bet.html
bet
-// bharti : 2014-01-09 Bharti Enterprises (Holding) Private Limited
+// bharti : Bharti Enterprises (Holding) Private Limited
+// https://www.iana.org/domains/root/db/bharti.html
bharti
-// bible : 2014-06-19 American Bible Society
+// bible : American Bible Society
+// https://www.iana.org/domains/root/db/bible.html
bible
-// bid : 2013-12-19 dot Bid Limited
+// bid : dot Bid Limited
+// https://www.iana.org/domains/root/db/bid.html
bid
-// bike : 2013-08-27 Binky Moon, LLC
+// bike : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/bike.html
bike
-// bing : 2014-12-18 Microsoft Corporation
+// bing : Microsoft Corporation
+// https://www.iana.org/domains/root/db/bing.html
bing
-// bingo : 2014-12-04 Binky Moon, LLC
+// bingo : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/bingo.html
bingo
-// bio : 2014-03-06 Identity Digital Limited
+// bio : Identity Digital Limited
+// https://www.iana.org/domains/root/db/bio.html
bio
-// black : 2014-01-16 Identity Digital Limited
+// black : Identity Digital Limited
+// https://www.iana.org/domains/root/db/black.html
black
-// blackfriday : 2014-01-16 Registry Services, LLC
+// blackfriday : Registry Services, LLC
+// https://www.iana.org/domains/root/db/blackfriday.html
blackfriday
-// blockbuster : 2015-07-30 Dish DBS Corporation
+// blockbuster : Dish DBS Corporation
+// https://www.iana.org/domains/root/db/blockbuster.html
blockbuster
-// blog : 2015-05-14 Knock Knock WHOIS There, LLC
+// blog : Knock Knock WHOIS There, LLC
+// https://www.iana.org/domains/root/db/blog.html
blog
-// bloomberg : 2014-07-17 Bloomberg IP Holdings LLC
+// bloomberg : Bloomberg IP Holdings LLC
+// https://www.iana.org/domains/root/db/bloomberg.html
bloomberg
-// blue : 2013-11-07 Identity Digital Limited
+// blue : Identity Digital Limited
+// https://www.iana.org/domains/root/db/blue.html
blue
-// bms : 2014-10-30 Bristol-Myers Squibb Company
+// bms : Bristol-Myers Squibb Company
+// https://www.iana.org/domains/root/db/bms.html
bms
-// bmw : 2014-01-09 Bayerische Motoren Werke Aktiengesellschaft
+// bmw : Bayerische Motoren Werke Aktiengesellschaft
+// https://www.iana.org/domains/root/db/bmw.html
bmw
-// bnpparibas : 2014-05-29 BNP Paribas
+// bnpparibas : BNP Paribas
+// https://www.iana.org/domains/root/db/bnpparibas.html
bnpparibas
-// boats : 2014-12-04 XYZ.COM LLC
+// boats : XYZ.COM LLC
+// https://www.iana.org/domains/root/db/boats.html
boats
-// boehringer : 2015-07-09 Boehringer Ingelheim International GmbH
+// boehringer : Boehringer Ingelheim International GmbH
+// https://www.iana.org/domains/root/db/boehringer.html
boehringer
-// bofa : 2015-07-31 Bank of America Corporation
+// bofa : Bank of America Corporation
+// https://www.iana.org/domains/root/db/bofa.html
bofa
-// bom : 2014-10-16 Núcleo de Informação e Coordenação do Ponto BR - NIC.br
+// bom : Núcleo de Informação e Coordenação do Ponto BR - NIC.br
+// https://www.iana.org/domains/root/db/bom.html
bom
-// bond : 2014-06-05 ShortDot SA
+// bond : ShortDot SA
+// https://www.iana.org/domains/root/db/bond.html
bond
-// boo : 2014-01-30 Charleston Road Registry Inc.
+// boo : Charleston Road Registry Inc.
+// https://www.iana.org/domains/root/db/boo.html
boo
-// book : 2015-08-27 Amazon Registry Services, Inc.
+// book : Amazon Registry Services, Inc.
+// https://www.iana.org/domains/root/db/book.html
book
-// booking : 2015-07-16 Booking.com B.V.
+// booking : Booking.com B.V.
+// https://www.iana.org/domains/root/db/booking.html
booking
-// bosch : 2015-06-18 Robert Bosch GMBH
+// bosch : Robert Bosch GMBH
+// https://www.iana.org/domains/root/db/bosch.html
bosch
-// bostik : 2015-05-28 Bostik SA
+// bostik : Bostik SA
+// https://www.iana.org/domains/root/db/bostik.html
bostik
-// boston : 2015-12-10 Registry Services, LLC
+// boston : Registry Services, LLC
+// https://www.iana.org/domains/root/db/boston.html
boston
-// bot : 2014-12-18 Amazon Registry Services, Inc.
+// bot : Amazon Registry Services, Inc.
+// https://www.iana.org/domains/root/db/bot.html
bot
-// boutique : 2013-11-14 Binky Moon, LLC
+// boutique : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/boutique.html
boutique
-// box : 2015-11-12 Intercap Registry Inc.
+// box : Intercap Registry Inc.
+// https://www.iana.org/domains/root/db/box.html
box
-// bradesco : 2014-12-18 Banco Bradesco S.A.
+// bradesco : Banco Bradesco S.A.
+// https://www.iana.org/domains/root/db/bradesco.html
bradesco
-// bridgestone : 2014-12-18 Bridgestone Corporation
+// bridgestone : Bridgestone Corporation
+// https://www.iana.org/domains/root/db/bridgestone.html
bridgestone
-// broadway : 2014-12-22 Celebrate Broadway, Inc.
+// broadway : Celebrate Broadway, Inc.
+// https://www.iana.org/domains/root/db/broadway.html
broadway
-// broker : 2014-12-11 Dog Beach, LLC
+// broker : Dog Beach, LLC
+// https://www.iana.org/domains/root/db/broker.html
broker
-// brother : 2015-01-29 Brother Industries, Ltd.
+// brother : Brother Industries, Ltd.
+// https://www.iana.org/domains/root/db/brother.html
brother
-// brussels : 2014-02-06 DNS.be vzw
+// brussels : DNS.be vzw
+// https://www.iana.org/domains/root/db/brussels.html
brussels
-// build : 2013-11-07 Plan Bee LLC
+// build : Plan Bee LLC
+// https://www.iana.org/domains/root/db/build.html
build
-// builders : 2013-11-07 Binky Moon, LLC
+// builders : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/builders.html
builders
-// business : 2013-11-07 Binky Moon, LLC
+// business : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/business.html
business
-// buy : 2014-12-18 Amazon Registry Services, Inc.
+// buy : Amazon Registry Services, Inc.
+// https://www.iana.org/domains/root/db/buy.html
buy
-// buzz : 2013-10-02 DOTSTRATEGY CO.
+// buzz : DOTSTRATEGY CO.
+// https://www.iana.org/domains/root/db/buzz.html
buzz
-// bzh : 2014-02-27 Association www.bzh
+// bzh : Association www.bzh
+// https://www.iana.org/domains/root/db/bzh.html
bzh
-// cab : 2013-10-24 Binky Moon, LLC
+// cab : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/cab.html
cab
-// cafe : 2015-02-11 Binky Moon, LLC
+// cafe : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/cafe.html
cafe
-// cal : 2014-07-24 Charleston Road Registry Inc.
+// cal : Charleston Road Registry Inc.
+// https://www.iana.org/domains/root/db/cal.html
cal
-// call : 2014-12-18 Amazon Registry Services, Inc.
+// call : Amazon Registry Services, Inc.
+// https://www.iana.org/domains/root/db/call.html
call
-// calvinklein : 2015-07-30 PVH gTLD Holdings LLC
+// calvinklein : PVH gTLD Holdings LLC
+// https://www.iana.org/domains/root/db/calvinklein.html
calvinklein
-// cam : 2016-04-21 Cam Connecting SARL
+// cam : Cam Connecting SARL
+// https://www.iana.org/domains/root/db/cam.html
cam
-// camera : 2013-08-27 Binky Moon, LLC
+// camera : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/camera.html
camera
-// camp : 2013-11-07 Binky Moon, LLC
+// camp : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/camp.html
camp
-// canon : 2014-09-12 Canon Inc.
+// canon : Canon Inc.
+// https://www.iana.org/domains/root/db/canon.html
canon
-// capetown : 2014-03-24 ZA Central Registry NPC trading as ZA Central Registry
+// capetown : ZA Central Registry NPC trading as ZA Central Registry
+// https://www.iana.org/domains/root/db/capetown.html
capetown
-// capital : 2014-03-06 Binky Moon, LLC
+// capital : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/capital.html
capital
-// capitalone : 2015-08-06 Capital One Financial Corporation
+// capitalone : Capital One Financial Corporation
+// https://www.iana.org/domains/root/db/capitalone.html
capitalone
-// car : 2015-01-22 XYZ.COM LLC
+// car : XYZ.COM LLC
+// https://www.iana.org/domains/root/db/car.html
car
-// caravan : 2013-12-12 Caravan International, Inc.
+// caravan : Caravan International, Inc.
+// https://www.iana.org/domains/root/db/caravan.html
caravan
-// cards : 2013-12-05 Binky Moon, LLC
+// cards : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/cards.html
cards
-// care : 2014-03-06 Binky Moon, LLC
+// care : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/care.html
care
-// career : 2013-10-09 dotCareer LLC
+// career : dotCareer LLC
+// https://www.iana.org/domains/root/db/career.html
career
-// careers : 2013-10-02 Binky Moon, LLC
+// careers : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/careers.html
careers
-// cars : 2014-11-13 XYZ.COM LLC
+// cars : XYZ.COM LLC
+// https://www.iana.org/domains/root/db/cars.html
cars
-// casa : 2013-11-21 Registry Services, LLC
+// casa : Registry Services, LLC
+// https://www.iana.org/domains/root/db/casa.html
casa
-// case : 2015-09-03 Digity, LLC
+// case : Digity, LLC
+// https://www.iana.org/domains/root/db/case.html
case
-// cash : 2014-03-06 Binky Moon, LLC
+// cash : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/cash.html
cash
-// casino : 2014-12-18 Binky Moon, LLC
+// casino : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/casino.html
casino
-// catering : 2013-12-05 Binky Moon, LLC
+// catering : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/catering.html
catering
-// catholic : 2015-10-21 Pontificium Consilium de Comunicationibus Socialibus (PCCS) (Pontifical Council for Social Communication)
+// catholic : Pontificium Consilium de Comunicationibus Socialibus (PCCS) (Pontifical Council for Social Communication)
+// https://www.iana.org/domains/root/db/catholic.html
catholic
-// cba : 2014-06-26 COMMONWEALTH BANK OF AUSTRALIA
+// cba : COMMONWEALTH BANK OF AUSTRALIA
+// https://www.iana.org/domains/root/db/cba.html
cba
-// cbn : 2014-08-22 The Christian Broadcasting Network, Inc.
+// cbn : The Christian Broadcasting Network, Inc.
+// https://www.iana.org/domains/root/db/cbn.html
cbn
-// cbre : 2015-07-02 CBRE, Inc.
+// cbre : CBRE, Inc.
+// https://www.iana.org/domains/root/db/cbre.html
cbre
-// cbs : 2015-08-06 CBS Domains Inc.
-cbs
-
-// center : 2013-11-07 Binky Moon, LLC
+// center : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/center.html
center
-// ceo : 2013-11-07 CEOTLD Pty Ltd
+// ceo : XYZ.COM LLC
+// https://www.iana.org/domains/root/db/ceo.html
ceo
-// cern : 2014-06-05 European Organization for Nuclear Research ("CERN")
+// cern : European Organization for Nuclear Research ("CERN")
+// https://www.iana.org/domains/root/db/cern.html
cern
-// cfa : 2014-08-28 CFA Institute
+// cfa : CFA Institute
+// https://www.iana.org/domains/root/db/cfa.html
cfa
-// cfd : 2014-12-11 ShortDot SA
+// cfd : ShortDot SA
+// https://www.iana.org/domains/root/db/cfd.html
cfd
-// chanel : 2015-04-09 Chanel International B.V.
+// chanel : Chanel International B.V.
+// https://www.iana.org/domains/root/db/chanel.html
chanel
-// channel : 2014-05-08 Charleston Road Registry Inc.
+// channel : Charleston Road Registry Inc.
+// https://www.iana.org/domains/root/db/channel.html
channel
-// charity : 2018-04-11 Public Interest Registry
+// charity : Public Interest Registry
+// https://www.iana.org/domains/root/db/charity.html
charity
-// chase : 2015-04-30 JPMorgan Chase Bank, National Association
+// chase : JPMorgan Chase Bank, National Association
+// https://www.iana.org/domains/root/db/chase.html
chase
-// chat : 2014-12-04 Binky Moon, LLC
+// chat : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/chat.html
chat
-// cheap : 2013-11-14 Binky Moon, LLC
+// cheap : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/cheap.html
cheap
-// chintai : 2015-06-11 CHINTAI Corporation
+// chintai : CHINTAI Corporation
+// https://www.iana.org/domains/root/db/chintai.html
chintai
-// christmas : 2013-11-21 XYZ.COM LLC
+// christmas : XYZ.COM LLC
+// https://www.iana.org/domains/root/db/christmas.html
christmas
-// chrome : 2014-07-24 Charleston Road Registry Inc.
+// chrome : Charleston Road Registry Inc.
+// https://www.iana.org/domains/root/db/chrome.html
chrome
-// church : 2014-02-06 Binky Moon, LLC
+// church : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/church.html
church
-// cipriani : 2015-02-19 Hotel Cipriani Srl
+// cipriani : Hotel Cipriani Srl
+// https://www.iana.org/domains/root/db/cipriani.html
cipriani
-// circle : 2014-12-18 Amazon Registry Services, Inc.
+// circle : Amazon Registry Services, Inc.
+// https://www.iana.org/domains/root/db/circle.html
circle
-// cisco : 2014-12-22 Cisco Technology, Inc.
+// cisco : Cisco Technology, Inc.
+// https://www.iana.org/domains/root/db/cisco.html
cisco
-// citadel : 2015-07-23 Citadel Domain LLC
+// citadel : Citadel Domain LLC
+// https://www.iana.org/domains/root/db/citadel.html
citadel
-// citi : 2015-07-30 Citigroup Inc.
+// citi : Citigroup Inc.
+// https://www.iana.org/domains/root/db/citi.html
citi
-// citic : 2014-01-09 CITIC Group Corporation
+// citic : CITIC Group Corporation
+// https://www.iana.org/domains/root/db/citic.html
citic
-// city : 2014-05-29 Binky Moon, LLC
+// city : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/city.html
city
-// cityeats : 2014-12-11 Lifestyle Domain Holdings, Inc.
-cityeats
-
-// claims : 2014-03-20 Binky Moon, LLC
+// claims : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/claims.html
claims
-// cleaning : 2013-12-05 Binky Moon, LLC
+// cleaning : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/cleaning.html
cleaning
-// click : 2014-06-05 Internet Naming Company LLC
+// click : Internet Naming Company LLC
+// https://www.iana.org/domains/root/db/click.html
click
-// clinic : 2014-03-20 Binky Moon, LLC
+// clinic : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/clinic.html
clinic
-// clinique : 2015-10-01 The Estée Lauder Companies Inc.
+// clinique : The Estée Lauder Companies Inc.
+// https://www.iana.org/domains/root/db/clinique.html
clinique
-// clothing : 2013-08-27 Binky Moon, LLC
+// clothing : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/clothing.html
clothing
-// cloud : 2015-04-16 Aruba PEC S.p.A.
+// cloud : Aruba PEC S.p.A.
+// https://www.iana.org/domains/root/db/cloud.html
cloud
-// club : 2013-11-08 Registry Services, LLC
+// club : Registry Services, LLC
+// https://www.iana.org/domains/root/db/club.html
club
-// clubmed : 2015-06-25 Club Méditerranée S.A.
+// clubmed : Club Méditerranée S.A.
+// https://www.iana.org/domains/root/db/clubmed.html
clubmed
-// coach : 2014-10-09 Binky Moon, LLC
+// coach : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/coach.html
coach
-// codes : 2013-10-31 Binky Moon, LLC
+// codes : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/codes.html
codes
-// coffee : 2013-10-17 Binky Moon, LLC
+// coffee : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/coffee.html
coffee
-// college : 2014-01-16 XYZ.COM LLC
+// college : XYZ.COM LLC
+// https://www.iana.org/domains/root/db/college.html
college
-// cologne : 2014-02-05 dotKoeln GmbH
+// cologne : dotKoeln GmbH
+// https://www.iana.org/domains/root/db/cologne.html
cologne
-// comcast : 2015-07-23 Comcast IP Holdings I, LLC
+// comcast : Comcast IP Holdings I, LLC
+// https://www.iana.org/domains/root/db/comcast.html
comcast
-// commbank : 2014-06-26 COMMONWEALTH BANK OF AUSTRALIA
+// commbank : COMMONWEALTH BANK OF AUSTRALIA
+// https://www.iana.org/domains/root/db/commbank.html
commbank
-// community : 2013-12-05 Binky Moon, LLC
+// community : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/community.html
community
-// company : 2013-11-07 Binky Moon, LLC
+// company : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/company.html
company
-// compare : 2015-10-08 Registry Services, LLC
+// compare : Registry Services, LLC
+// https://www.iana.org/domains/root/db/compare.html
compare
-// computer : 2013-10-24 Binky Moon, LLC
+// computer : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/computer.html
computer
-// comsec : 2015-01-08 VeriSign, Inc.
+// comsec : VeriSign, Inc.
+// https://www.iana.org/domains/root/db/comsec.html
comsec
-// condos : 2013-12-05 Binky Moon, LLC
+// condos : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/condos.html
condos
-// construction : 2013-09-16 Binky Moon, LLC
+// construction : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/construction.html
construction
-// consulting : 2013-12-05 Dog Beach, LLC
+// consulting : Dog Beach, LLC
+// https://www.iana.org/domains/root/db/consulting.html
consulting
-// contact : 2015-01-08 Dog Beach, LLC
+// contact : Dog Beach, LLC
+// https://www.iana.org/domains/root/db/contact.html
contact
-// contractors : 2013-09-10 Binky Moon, LLC
+// contractors : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/contractors.html
contractors
-// cooking : 2013-11-21 Registry Services, LLC
+// cooking : Registry Services, LLC
+// https://www.iana.org/domains/root/db/cooking.html
cooking
-// cookingchannel : 2015-07-02 Lifestyle Domain Holdings, Inc.
-cookingchannel
-
-// cool : 2013-11-14 Binky Moon, LLC
+// cool : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/cool.html
cool
-// corsica : 2014-09-25 Collectivité de Corse
+// corsica : Collectivité de Corse
+// https://www.iana.org/domains/root/db/corsica.html
corsica
-// country : 2013-12-19 Internet Naming Company LLC
+// country : Internet Naming Company LLC
+// https://www.iana.org/domains/root/db/country.html
country
-// coupon : 2015-02-26 Amazon Registry Services, Inc.
+// coupon : Amazon Registry Services, Inc.
+// https://www.iana.org/domains/root/db/coupon.html
coupon
-// coupons : 2015-03-26 Binky Moon, LLC
+// coupons : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/coupons.html
coupons
-// courses : 2014-12-04 Registry Services, LLC
+// courses : Registry Services, LLC
+// https://www.iana.org/domains/root/db/courses.html
courses
-// cpa : 2019-06-10 American Institute of Certified Public Accountants
+// cpa : American Institute of Certified Public Accountants
+// https://www.iana.org/domains/root/db/cpa.html
cpa
-// credit : 2014-03-20 Binky Moon, LLC
+// credit : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/credit.html
credit
-// creditcard : 2014-03-20 Binky Moon, LLC
+// creditcard : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/creditcard.html
creditcard
-// creditunion : 2015-01-22 DotCooperation LLC
+// creditunion : DotCooperation LLC
+// https://www.iana.org/domains/root/db/creditunion.html
creditunion
-// cricket : 2014-10-09 dot Cricket Limited
+// cricket : dot Cricket Limited
+// https://www.iana.org/domains/root/db/cricket.html
cricket
-// crown : 2014-10-24 Crown Equipment Corporation
+// crown : Crown Equipment Corporation
+// https://www.iana.org/domains/root/db/crown.html
crown
-// crs : 2014-04-03 Federated Co-operatives Limited
+// crs : Federated Co-operatives Limited
+// https://www.iana.org/domains/root/db/crs.html
crs
-// cruise : 2015-12-10 Viking River Cruises (Bermuda) Ltd.
+// cruise : Viking River Cruises (Bermuda) Ltd.
+// https://www.iana.org/domains/root/db/cruise.html
cruise
-// cruises : 2013-12-05 Binky Moon, LLC
+// cruises : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/cruises.html
cruises
-// cuisinella : 2014-04-03 SCHMIDT GROUPE S.A.S.
+// cuisinella : SCHMIDT GROUPE S.A.S.
+// https://www.iana.org/domains/root/db/cuisinella.html
cuisinella
-// cymru : 2014-05-08 Nominet UK
+// cymru : Nominet UK
+// https://www.iana.org/domains/root/db/cymru.html
cymru
-// cyou : 2015-01-22 ShortDot SA
+// cyou : ShortDot SA
+// https://www.iana.org/domains/root/db/cyou.html
cyou
-// dabur : 2014-02-06 Dabur India Limited
+// dabur : Dabur India Limited
+// https://www.iana.org/domains/root/db/dabur.html
dabur
-// dad : 2014-01-23 Charleston Road Registry Inc.
+// dad : Charleston Road Registry Inc.
+// https://www.iana.org/domains/root/db/dad.html
dad
-// dance : 2013-10-24 Dog Beach, LLC
+// dance : Dog Beach, LLC
+// https://www.iana.org/domains/root/db/dance.html
dance
-// data : 2016-06-02 Dish DBS Corporation
+// data : Dish DBS Corporation
+// https://www.iana.org/domains/root/db/data.html
data
-// date : 2014-11-20 dot Date Limited
+// date : dot Date Limited
+// https://www.iana.org/domains/root/db/date.html
date
-// dating : 2013-12-05 Binky Moon, LLC
+// dating : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/dating.html
dating
-// datsun : 2014-03-27 NISSAN MOTOR CO., LTD.
+// datsun : NISSAN MOTOR CO., LTD.
+// https://www.iana.org/domains/root/db/datsun.html
datsun
-// day : 2014-01-30 Charleston Road Registry Inc.
+// day : Charleston Road Registry Inc.
+// https://www.iana.org/domains/root/db/day.html
day
-// dclk : 2014-11-20 Charleston Road Registry Inc.
+// dclk : Charleston Road Registry Inc.
+// https://www.iana.org/domains/root/db/dclk.html
dclk
-// dds : 2015-05-07 Registry Services, LLC
+// dds : Registry Services, LLC
+// https://www.iana.org/domains/root/db/dds.html
dds
-// deal : 2015-06-25 Amazon Registry Services, Inc.
+// deal : Amazon Registry Services, Inc.
+// https://www.iana.org/domains/root/db/deal.html
deal
-// dealer : 2014-12-22 Intercap Registry Inc.
+// dealer : Intercap Registry Inc.
+// https://www.iana.org/domains/root/db/dealer.html
dealer
-// deals : 2014-05-22 Binky Moon, LLC
+// deals : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/deals.html
deals
-// degree : 2014-03-06 Dog Beach, LLC
+// degree : Dog Beach, LLC
+// https://www.iana.org/domains/root/db/degree.html
degree
-// delivery : 2014-09-11 Binky Moon, LLC
+// delivery : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/delivery.html
delivery
-// dell : 2014-10-24 Dell Inc.
+// dell : Dell Inc.
+// https://www.iana.org/domains/root/db/dell.html
dell
-// deloitte : 2015-07-31 Deloitte Touche Tohmatsu
+// deloitte : Deloitte Touche Tohmatsu
+// https://www.iana.org/domains/root/db/deloitte.html
deloitte
-// delta : 2015-02-19 Delta Air Lines, Inc.
+// delta : Delta Air Lines, Inc.
+// https://www.iana.org/domains/root/db/delta.html
delta
-// democrat : 2013-10-24 Dog Beach, LLC
+// democrat : Dog Beach, LLC
+// https://www.iana.org/domains/root/db/democrat.html
democrat
-// dental : 2014-03-20 Binky Moon, LLC
+// dental : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/dental.html
dental
-// dentist : 2014-03-20 Dog Beach, LLC
+// dentist : Dog Beach, LLC
+// https://www.iana.org/domains/root/db/dentist.html
dentist
-// desi : 2013-11-14 Desi Networks LLC
+// desi
+// https://www.iana.org/domains/root/db/desi.html
desi
-// design : 2014-11-07 Registry Services, LLC
+// design : Registry Services, LLC
+// https://www.iana.org/domains/root/db/design.html
design
-// dev : 2014-10-16 Charleston Road Registry Inc.
+// dev : Charleston Road Registry Inc.
+// https://www.iana.org/domains/root/db/dev.html
dev
-// dhl : 2015-07-23 Deutsche Post AG
+// dhl : Deutsche Post AG
+// https://www.iana.org/domains/root/db/dhl.html
dhl
-// diamonds : 2013-09-22 Binky Moon, LLC
+// diamonds : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/diamonds.html
diamonds
-// diet : 2014-06-26 XYZ.COM LLC
+// diet : XYZ.COM LLC
+// https://www.iana.org/domains/root/db/diet.html
diet
-// digital : 2014-03-06 Binky Moon, LLC
+// digital : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/digital.html
digital
-// direct : 2014-04-10 Binky Moon, LLC
+// direct : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/direct.html
direct
-// directory : 2013-09-20 Binky Moon, LLC
+// directory : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/directory.html
directory
-// discount : 2014-03-06 Binky Moon, LLC
+// discount : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/discount.html
discount
-// discover : 2015-07-23 Discover Financial Services
+// discover : Discover Financial Services
+// https://www.iana.org/domains/root/db/discover.html
discover
-// dish : 2015-07-30 Dish DBS Corporation
+// dish : Dish DBS Corporation
+// https://www.iana.org/domains/root/db/dish.html
dish
-// diy : 2015-11-05 Lifestyle Domain Holdings, Inc.
+// diy : Internet Naming Company LLC
+// https://www.iana.org/domains/root/db/diy.html
diy
-// dnp : 2013-12-13 Dai Nippon Printing Co., Ltd.
+// dnp : Dai Nippon Printing Co., Ltd.
+// https://www.iana.org/domains/root/db/dnp.html
dnp
-// docs : 2014-10-16 Charleston Road Registry Inc.
+// docs : Charleston Road Registry Inc.
+// https://www.iana.org/domains/root/db/docs.html
docs
-// doctor : 2016-06-02 Binky Moon, LLC
+// doctor : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/doctor.html
doctor
-// dog : 2014-12-04 Binky Moon, LLC
+// dog : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/dog.html
dog
-// domains : 2013-10-17 Binky Moon, LLC
+// domains : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/domains.html
domains
-// dot : 2015-05-21 Dish DBS Corporation
+// dot : Dish DBS Corporation
+// https://www.iana.org/domains/root/db/dot.html
dot
-// download : 2014-11-20 dot Support Limited
+// download : dot Support Limited
+// https://www.iana.org/domains/root/db/download.html
download
-// drive : 2015-03-05 Charleston Road Registry Inc.
+// drive : Charleston Road Registry Inc.
+// https://www.iana.org/domains/root/db/drive.html
drive
-// dtv : 2015-06-04 Dish DBS Corporation
+// dtv : Dish DBS Corporation
+// https://www.iana.org/domains/root/db/dtv.html
dtv
-// dubai : 2015-01-01 Dubai Smart Government Department
+// dubai : Dubai Smart Government Department
+// https://www.iana.org/domains/root/db/dubai.html
dubai
-// dunlop : 2015-07-02 The Goodyear Tire & Rubber Company
+// dunlop : The Goodyear Tire & Rubber Company
+// https://www.iana.org/domains/root/db/dunlop.html
dunlop
-// dupont : 2015-06-25 DuPont Specialty Products USA, LLC
+// dupont : DuPont Specialty Products USA, LLC
+// https://www.iana.org/domains/root/db/dupont.html
dupont
-// durban : 2014-03-24 ZA Central Registry NPC trading as ZA Central Registry
+// durban : ZA Central Registry NPC trading as ZA Central Registry
+// https://www.iana.org/domains/root/db/durban.html
durban
-// dvag : 2014-06-23 Deutsche Vermögensberatung Aktiengesellschaft DVAG
+// dvag : Deutsche Vermögensberatung Aktiengesellschaft DVAG
+// https://www.iana.org/domains/root/db/dvag.html
dvag
-// dvr : 2016-05-26 DISH Technologies L.L.C.
+// dvr : DISH Technologies L.L.C.
+// https://www.iana.org/domains/root/db/dvr.html
dvr
-// earth : 2014-12-04 Interlink Systems Innovation Institute K.K.
+// earth : Interlink Systems Innovation Institute K.K.
+// https://www.iana.org/domains/root/db/earth.html
earth
-// eat : 2014-01-23 Charleston Road Registry Inc.
+// eat : Charleston Road Registry Inc.
+// https://www.iana.org/domains/root/db/eat.html
eat
-// eco : 2016-07-08 Big Room Inc.
+// eco : Big Room Inc.
+// https://www.iana.org/domains/root/db/eco.html
eco
-// edeka : 2014-12-18 EDEKA Verband kaufmännischer Genossenschaften e.V.
+// edeka : EDEKA Verband kaufmännischer Genossenschaften e.V.
+// https://www.iana.org/domains/root/db/edeka.html
edeka
-// education : 2013-11-07 Binky Moon, LLC
+// education : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/education.html
education
-// email : 2013-10-31 Binky Moon, LLC
+// email : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/email.html
email
-// emerck : 2014-04-03 Merck KGaA
+// emerck : Merck KGaA
+// https://www.iana.org/domains/root/db/emerck.html
emerck
-// energy : 2014-09-11 Binky Moon, LLC
+// energy : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/energy.html
energy
-// engineer : 2014-03-06 Dog Beach, LLC
+// engineer : Dog Beach, LLC
+// https://www.iana.org/domains/root/db/engineer.html
engineer
-// engineering : 2014-03-06 Binky Moon, LLC
+// engineering : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/engineering.html
engineering
-// enterprises : 2013-09-20 Binky Moon, LLC
+// enterprises : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/enterprises.html
enterprises
-// epson : 2014-12-04 Seiko Epson Corporation
+// epson : Seiko Epson Corporation
+// https://www.iana.org/domains/root/db/epson.html
epson
-// equipment : 2013-08-27 Binky Moon, LLC
+// equipment : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/equipment.html
equipment
-// ericsson : 2015-07-09 Telefonaktiebolaget L M Ericsson
+// ericsson : Telefonaktiebolaget L M Ericsson
+// https://www.iana.org/domains/root/db/ericsson.html
ericsson
-// erni : 2014-04-03 ERNI Group Holding AG
+// erni : ERNI Group Holding AG
+// https://www.iana.org/domains/root/db/erni.html
erni
-// esq : 2014-05-08 Charleston Road Registry Inc.
+// esq : Charleston Road Registry Inc.
+// https://www.iana.org/domains/root/db/esq.html
esq
-// estate : 2013-08-27 Binky Moon, LLC
+// estate : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/estate.html
estate
-// etisalat : 2015-09-03 Emirates Telecommunications Corporation (trading as Etisalat)
-etisalat
-
-// eurovision : 2014-04-24 European Broadcasting Union (EBU)
+// eurovision : European Broadcasting Union (EBU)
+// https://www.iana.org/domains/root/db/eurovision.html
eurovision
-// eus : 2013-12-12 Puntueus Fundazioa
+// eus : Puntueus Fundazioa
+// https://www.iana.org/domains/root/db/eus.html
eus
-// events : 2013-12-05 Binky Moon, LLC
+// events : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/events.html
events
-// exchange : 2014-03-06 Binky Moon, LLC
+// exchange : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/exchange.html
exchange
-// expert : 2013-11-21 Binky Moon, LLC
+// expert : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/expert.html
expert
-// exposed : 2013-12-05 Binky Moon, LLC
+// exposed : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/exposed.html
exposed
-// express : 2015-02-11 Binky Moon, LLC
+// express : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/express.html
express
-// extraspace : 2015-05-14 Extra Space Storage LLC
+// extraspace : Extra Space Storage LLC
+// https://www.iana.org/domains/root/db/extraspace.html
extraspace
-// fage : 2014-12-18 Fage International S.A.
+// fage : Fage International S.A.
+// https://www.iana.org/domains/root/db/fage.html
fage
-// fail : 2014-03-06 Binky Moon, LLC
+// fail : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/fail.html
fail
-// fairwinds : 2014-11-13 FairWinds Partners, LLC
+// fairwinds : FairWinds Partners, LLC
+// https://www.iana.org/domains/root/db/fairwinds.html
fairwinds
-// faith : 2014-11-20 dot Faith Limited
+// faith : dot Faith Limited
+// https://www.iana.org/domains/root/db/faith.html
faith
-// family : 2015-04-02 Dog Beach, LLC
+// family : Dog Beach, LLC
+// https://www.iana.org/domains/root/db/family.html
family
-// fan : 2014-03-06 Dog Beach, LLC
+// fan : Dog Beach, LLC
+// https://www.iana.org/domains/root/db/fan.html
fan
-// fans : 2014-11-07 ZDNS International Limited
+// fans : ZDNS International Limited
+// https://www.iana.org/domains/root/db/fans.html
fans
-// farm : 2013-11-07 Binky Moon, LLC
+// farm : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/farm.html
farm
-// farmers : 2015-07-09 Farmers Insurance Exchange
+// farmers : Farmers Insurance Exchange
+// https://www.iana.org/domains/root/db/farmers.html
farmers
-// fashion : 2014-07-03 Registry Services, LLC
+// fashion : Registry Services, LLC
+// https://www.iana.org/domains/root/db/fashion.html
fashion
-// fast : 2014-12-18 Amazon Registry Services, Inc.
+// fast : Amazon Registry Services, Inc.
+// https://www.iana.org/domains/root/db/fast.html
fast
-// fedex : 2015-08-06 Federal Express Corporation
+// fedex : Federal Express Corporation
+// https://www.iana.org/domains/root/db/fedex.html
fedex
-// feedback : 2013-12-19 Top Level Spectrum, Inc.
+// feedback : Top Level Spectrum, Inc.
+// https://www.iana.org/domains/root/db/feedback.html
feedback
-// ferrari : 2015-07-31 Fiat Chrysler Automobiles N.V.
+// ferrari : Fiat Chrysler Automobiles N.V.
+// https://www.iana.org/domains/root/db/ferrari.html
ferrari
-// ferrero : 2014-12-18 Ferrero Trading Lux S.A.
+// ferrero : Ferrero Trading Lux S.A.
+// https://www.iana.org/domains/root/db/ferrero.html
ferrero
-// fiat : 2015-07-31 Fiat Chrysler Automobiles N.V.
-fiat
-
-// fidelity : 2015-07-30 Fidelity Brokerage Services LLC
+// fidelity : Fidelity Brokerage Services LLC
+// https://www.iana.org/domains/root/db/fidelity.html
fidelity
-// fido : 2015-08-06 Rogers Communications Canada Inc.
+// fido : Rogers Communications Canada Inc.
+// https://www.iana.org/domains/root/db/fido.html
fido
-// film : 2015-01-08 Motion Picture Domain Registry Pty Ltd
+// film : Motion Picture Domain Registry Pty Ltd
+// https://www.iana.org/domains/root/db/film.html
film
-// final : 2014-10-16 Núcleo de Informação e Coordenação do Ponto BR - NIC.br
+// final : Núcleo de Informação e Coordenação do Ponto BR - NIC.br
+// https://www.iana.org/domains/root/db/final.html
final
-// finance : 2014-03-20 Binky Moon, LLC
+// finance : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/finance.html
finance
-// financial : 2014-03-06 Binky Moon, LLC
+// financial : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/financial.html
financial
-// fire : 2015-06-25 Amazon Registry Services, Inc.
+// fire : Amazon Registry Services, Inc.
+// https://www.iana.org/domains/root/db/fire.html
fire
-// firestone : 2014-12-18 Bridgestone Licensing Services, Inc
+// firestone : Bridgestone Licensing Services, Inc
+// https://www.iana.org/domains/root/db/firestone.html
firestone
-// firmdale : 2014-03-27 Firmdale Holdings Limited
+// firmdale : Firmdale Holdings Limited
+// https://www.iana.org/domains/root/db/firmdale.html
firmdale
-// fish : 2013-12-12 Binky Moon, LLC
+// fish : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/fish.html
fish
-// fishing : 2013-11-21 Registry Services, LLC
+// fishing : Registry Services, LLC
+// https://www.iana.org/domains/root/db/fishing.html
fishing
-// fit : 2014-11-07 Registry Services, LLC
+// fit : Registry Services, LLC
+// https://www.iana.org/domains/root/db/fit.html
fit
-// fitness : 2014-03-06 Binky Moon, LLC
+// fitness : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/fitness.html
fitness
-// flickr : 2015-04-02 Flickr, Inc.
+// flickr : Flickr, Inc.
+// https://www.iana.org/domains/root/db/flickr.html
flickr
-// flights : 2013-12-05 Binky Moon, LLC
+// flights : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/flights.html
flights
-// flir : 2015-07-23 FLIR Systems, Inc.
+// flir : FLIR Systems, Inc.
+// https://www.iana.org/domains/root/db/flir.html
flir
-// florist : 2013-11-07 Binky Moon, LLC
+// florist : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/florist.html
florist
-// flowers : 2014-10-09 XYZ.COM LLC
+// flowers : XYZ.COM LLC
+// https://www.iana.org/domains/root/db/flowers.html
flowers
-// fly : 2014-05-08 Charleston Road Registry Inc.
+// fly : Charleston Road Registry Inc.
+// https://www.iana.org/domains/root/db/fly.html
fly
-// foo : 2014-01-23 Charleston Road Registry Inc.
+// foo : Charleston Road Registry Inc.
+// https://www.iana.org/domains/root/db/foo.html
foo
-// food : 2016-04-21 Lifestyle Domain Holdings, Inc.
+// food : Internet Naming Company LLC
+// https://www.iana.org/domains/root/db/food.html
food
-// foodnetwork : 2015-07-02 Lifestyle Domain Holdings, Inc.
-foodnetwork
-
-// football : 2014-12-18 Binky Moon, LLC
+// football : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/football.html
football
-// ford : 2014-11-13 Ford Motor Company
+// ford : Ford Motor Company
+// https://www.iana.org/domains/root/db/ford.html
ford
-// forex : 2014-12-11 Dog Beach, LLC
+// forex : Dog Beach, LLC
+// https://www.iana.org/domains/root/db/forex.html
forex
-// forsale : 2014-05-22 Dog Beach, LLC
+// forsale : Dog Beach, LLC
+// https://www.iana.org/domains/root/db/forsale.html
forsale
-// forum : 2015-04-02 Fegistry, LLC
+// forum : Fegistry, LLC
+// https://www.iana.org/domains/root/db/forum.html
forum
-// foundation : 2013-12-05 Public Interest Registry
+// foundation : Public Interest Registry
+// https://www.iana.org/domains/root/db/foundation.html
foundation
-// fox : 2015-09-11 FOX Registry, LLC
+// fox : FOX Registry, LLC
+// https://www.iana.org/domains/root/db/fox.html
fox
-// free : 2015-12-10 Amazon Registry Services, Inc.
+// free : Amazon Registry Services, Inc.
+// https://www.iana.org/domains/root/db/free.html
free
-// fresenius : 2015-07-30 Fresenius Immobilien-Verwaltungs-GmbH
+// fresenius : Fresenius Immobilien-Verwaltungs-GmbH
+// https://www.iana.org/domains/root/db/fresenius.html
fresenius
-// frl : 2014-05-15 FRLregistry B.V.
+// frl : FRLregistry B.V.
+// https://www.iana.org/domains/root/db/frl.html
frl
-// frogans : 2013-12-19 OP3FT
+// frogans : OP3FT
+// https://www.iana.org/domains/root/db/frogans.html
frogans
-// frontdoor : 2015-07-02 Lifestyle Domain Holdings, Inc.
-frontdoor
-
-// frontier : 2015-02-05 Frontier Communications Corporation
+// frontier : Frontier Communications Corporation
+// https://www.iana.org/domains/root/db/frontier.html
frontier
-// ftr : 2015-07-16 Frontier Communications Corporation
+// ftr : Frontier Communications Corporation
+// https://www.iana.org/domains/root/db/ftr.html
ftr
-// fujitsu : 2015-07-30 Fujitsu Limited
+// fujitsu : Fujitsu Limited
+// https://www.iana.org/domains/root/db/fujitsu.html
fujitsu
-// fun : 2016-01-14 Radix FZC
+// fun : Radix FZC DMCC
+// https://www.iana.org/domains/root/db/fun.html
fun
-// fund : 2014-03-20 Binky Moon, LLC
+// fund : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/fund.html
fund
-// furniture : 2014-03-20 Binky Moon, LLC
+// furniture : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/furniture.html
furniture
-// futbol : 2013-09-20 Dog Beach, LLC
+// futbol : Dog Beach, LLC
+// https://www.iana.org/domains/root/db/futbol.html
futbol
-// fyi : 2015-04-02 Binky Moon, LLC
+// fyi : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/fyi.html
fyi
-// gal : 2013-11-07 Asociación puntoGAL
+// gal : Asociación puntoGAL
+// https://www.iana.org/domains/root/db/gal.html
gal
-// gallery : 2013-09-13 Binky Moon, LLC
+// gallery : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/gallery.html
gallery
-// gallo : 2015-06-11 Gallo Vineyards, Inc.
+// gallo : Gallo Vineyards, Inc.
+// https://www.iana.org/domains/root/db/gallo.html
gallo
-// gallup : 2015-02-19 Gallup, Inc.
+// gallup : Gallup, Inc.
+// https://www.iana.org/domains/root/db/gallup.html
gallup
-// game : 2015-05-28 XYZ.COM LLC
+// game : XYZ.COM LLC
+// https://www.iana.org/domains/root/db/game.html
game
-// games : 2015-05-28 Dog Beach, LLC
+// games : Dog Beach, LLC
+// https://www.iana.org/domains/root/db/games.html
games
-// gap : 2015-07-31 The Gap, Inc.
+// gap : The Gap, Inc.
+// https://www.iana.org/domains/root/db/gap.html
gap
-// garden : 2014-06-26 Registry Services, LLC
+// garden : Registry Services, LLC
+// https://www.iana.org/domains/root/db/garden.html
garden
-// gay : 2019-05-23 Top Level Design, LLC
+// gay : Registry Services, LLC
+// https://www.iana.org/domains/root/db/gay.html
gay
-// gbiz : 2014-07-17 Charleston Road Registry Inc.
+// gbiz : Charleston Road Registry Inc.
+// https://www.iana.org/domains/root/db/gbiz.html
gbiz
-// gdn : 2014-07-31 Joint Stock Company "Navigation-information systems"
+// gdn : Joint Stock Company "Navigation-information systems"
+// https://www.iana.org/domains/root/db/gdn.html
gdn
-// gea : 2014-12-04 GEA Group Aktiengesellschaft
+// gea : GEA Group Aktiengesellschaft
+// https://www.iana.org/domains/root/db/gea.html
gea
-// gent : 2014-01-23 Easyhost BV
+// gent : Easyhost BV
+// https://www.iana.org/domains/root/db/gent.html
gent
-// genting : 2015-03-12 Resorts World Inc Pte. Ltd.
+// genting : Resorts World Inc Pte. Ltd.
+// https://www.iana.org/domains/root/db/genting.html
genting
-// george : 2015-07-31 Wal-Mart Stores, Inc.
+// george : Wal-Mart Stores, Inc.
+// https://www.iana.org/domains/root/db/george.html
george
-// ggee : 2014-01-09 GMO Internet, Inc.
+// ggee : GMO Internet, Inc.
+// https://www.iana.org/domains/root/db/ggee.html
ggee
-// gift : 2013-10-17 DotGift, LLC
+// gift : DotGift, LLC
+// https://www.iana.org/domains/root/db/gift.html
gift
-// gifts : 2014-07-03 Binky Moon, LLC
+// gifts : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/gifts.html
gifts
-// gives : 2014-03-06 Public Interest Registry
+// gives : Public Interest Registry
+// https://www.iana.org/domains/root/db/gives.html
gives
-// giving : 2014-11-13 Public Interest Registry
+// giving : Public Interest Registry
+// https://www.iana.org/domains/root/db/giving.html
giving
-// glass : 2013-11-07 Binky Moon, LLC
+// glass : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/glass.html
glass
-// gle : 2014-07-24 Charleston Road Registry Inc.
+// gle : Charleston Road Registry Inc.
+// https://www.iana.org/domains/root/db/gle.html
gle
-// global : 2014-04-17 Identity Digital Limited
+// global : Identity Digital Limited
+// https://www.iana.org/domains/root/db/global.html
global
-// globo : 2013-12-19 Globo Comunicação e Participações S.A
+// globo : Globo Comunicação e Participações S.A
+// https://www.iana.org/domains/root/db/globo.html
globo
-// gmail : 2014-05-01 Charleston Road Registry Inc.
+// gmail : Charleston Road Registry Inc.
+// https://www.iana.org/domains/root/db/gmail.html
gmail
-// gmbh : 2016-01-29 Binky Moon, LLC
+// gmbh : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/gmbh.html
gmbh
-// gmo : 2014-01-09 GMO Internet, Inc.
+// gmo : GMO Internet, Inc.
+// https://www.iana.org/domains/root/db/gmo.html
gmo
-// gmx : 2014-04-24 1&1 Mail & Media GmbH
+// gmx : 1&1 Mail & Media GmbH
+// https://www.iana.org/domains/root/db/gmx.html
gmx
-// godaddy : 2015-07-23 Go Daddy East, LLC
+// godaddy : Go Daddy East, LLC
+// https://www.iana.org/domains/root/db/godaddy.html
godaddy
-// gold : 2015-01-22 Binky Moon, LLC
+// gold : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/gold.html
gold
-// goldpoint : 2014-11-20 YODOBASHI CAMERA CO.,LTD.
+// goldpoint : YODOBASHI CAMERA CO.,LTD.
+// https://www.iana.org/domains/root/db/goldpoint.html
goldpoint
-// golf : 2014-12-18 Binky Moon, LLC
+// golf : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/golf.html
golf
-// goo : 2014-12-18 NTT Resonant Inc.
+// goo : NTT DOCOMO, INC.
+// https://www.iana.org/domains/root/db/goo.html
goo
-// goodyear : 2015-07-02 The Goodyear Tire & Rubber Company
+// goodyear : The Goodyear Tire & Rubber Company
+// https://www.iana.org/domains/root/db/goodyear.html
goodyear
-// goog : 2014-11-20 Charleston Road Registry Inc.
+// goog : Charleston Road Registry Inc.
+// https://www.iana.org/domains/root/db/goog.html
goog
-// google : 2014-07-24 Charleston Road Registry Inc.
+// google : Charleston Road Registry Inc.
+// https://www.iana.org/domains/root/db/google.html
google
-// gop : 2014-01-16 Republican State Leadership Committee, Inc.
+// gop : Republican State Leadership Committee, Inc.
+// https://www.iana.org/domains/root/db/gop.html
gop
-// got : 2014-12-18 Amazon Registry Services, Inc.
+// got : Amazon Registry Services, Inc.
+// https://www.iana.org/domains/root/db/got.html
got
-// grainger : 2015-05-07 Grainger Registry Services, LLC
+// grainger : Grainger Registry Services, LLC
+// https://www.iana.org/domains/root/db/grainger.html
grainger
-// graphics : 2013-09-13 Binky Moon, LLC
+// graphics : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/graphics.html
graphics
-// gratis : 2014-03-20 Binky Moon, LLC
+// gratis : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/gratis.html
gratis
-// green : 2014-05-08 Identity Digital Limited
+// green : Identity Digital Limited
+// https://www.iana.org/domains/root/db/green.html
green
-// gripe : 2014-03-06 Binky Moon, LLC
+// gripe : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/gripe.html
gripe
-// grocery : 2016-06-16 Wal-Mart Stores, Inc.
+// grocery : Wal-Mart Stores, Inc.
+// https://www.iana.org/domains/root/db/grocery.html
grocery
-// group : 2014-08-15 Binky Moon, LLC
+// group : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/group.html
group
-// guardian : 2015-07-30 The Guardian Life Insurance Company of America
+// guardian : The Guardian Life Insurance Company of America
+// https://www.iana.org/domains/root/db/guardian.html
guardian
-// gucci : 2014-11-13 Guccio Gucci S.p.a.
+// gucci : Guccio Gucci S.p.a.
+// https://www.iana.org/domains/root/db/gucci.html
gucci
-// guge : 2014-08-28 Charleston Road Registry Inc.
+// guge : Charleston Road Registry Inc.
+// https://www.iana.org/domains/root/db/guge.html
guge
-// guide : 2013-09-13 Binky Moon, LLC
+// guide : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/guide.html
guide
-// guitars : 2013-11-14 XYZ.COM LLC
+// guitars : XYZ.COM LLC
+// https://www.iana.org/domains/root/db/guitars.html
guitars
-// guru : 2013-08-27 Binky Moon, LLC
+// guru : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/guru.html
guru
-// hair : 2015-12-03 XYZ.COM LLC
+// hair : XYZ.COM LLC
+// https://www.iana.org/domains/root/db/hair.html
hair
-// hamburg : 2014-02-20 Hamburg Top-Level-Domain GmbH
+// hamburg : Hamburg Top-Level-Domain GmbH
+// https://www.iana.org/domains/root/db/hamburg.html
hamburg
-// hangout : 2014-11-13 Charleston Road Registry Inc.
+// hangout : Charleston Road Registry Inc.
+// https://www.iana.org/domains/root/db/hangout.html
hangout
-// haus : 2013-12-05 Dog Beach, LLC
+// haus : Dog Beach, LLC
+// https://www.iana.org/domains/root/db/haus.html
haus
-// hbo : 2015-07-30 HBO Registry Services, Inc.
+// hbo : HBO Registry Services, Inc.
+// https://www.iana.org/domains/root/db/hbo.html
hbo
-// hdfc : 2015-07-30 HOUSING DEVELOPMENT FINANCE CORPORATION LIMITED
+// hdfc : HOUSING DEVELOPMENT FINANCE CORPORATION LIMITED
+// https://www.iana.org/domains/root/db/hdfc.html
hdfc
-// hdfcbank : 2015-02-12 HDFC Bank Limited
+// hdfcbank : HDFC Bank Limited
+// https://www.iana.org/domains/root/db/hdfcbank.html
hdfcbank
-// health : 2015-02-11 DotHealth, LLC
+// health : Registry Services, LLC
+// https://www.iana.org/domains/root/db/health.html
health
-// healthcare : 2014-06-12 Binky Moon, LLC
+// healthcare : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/healthcare.html
healthcare
-// help : 2014-06-26 Innovation service Limited
+// help : Innovation service Limited
+// https://www.iana.org/domains/root/db/help.html
help
-// helsinki : 2015-02-05 City of Helsinki
+// helsinki : City of Helsinki
+// https://www.iana.org/domains/root/db/helsinki.html
helsinki
-// here : 2014-02-06 Charleston Road Registry Inc.
+// here : Charleston Road Registry Inc.
+// https://www.iana.org/domains/root/db/here.html
here
-// hermes : 2014-07-10 HERMES INTERNATIONAL
+// hermes : HERMES INTERNATIONAL
+// https://www.iana.org/domains/root/db/hermes.html
hermes
-// hgtv : 2015-07-02 Lifestyle Domain Holdings, Inc.
-hgtv
-
-// hiphop : 2014-03-06 Dot Hip Hop, LLC
+// hiphop : Dot Hip Hop, LLC
+// https://www.iana.org/domains/root/db/hiphop.html
hiphop
-// hisamitsu : 2015-07-16 Hisamitsu Pharmaceutical Co.,Inc.
+// hisamitsu : Hisamitsu Pharmaceutical Co.,Inc.
+// https://www.iana.org/domains/root/db/hisamitsu.html
hisamitsu
-// hitachi : 2014-10-31 Hitachi, Ltd.
+// hitachi : Hitachi, Ltd.
+// https://www.iana.org/domains/root/db/hitachi.html
hitachi
-// hiv : 2014-03-13 Internet Naming Company LLC
+// hiv : Internet Naming Company LLC
+// https://www.iana.org/domains/root/db/hiv.html
hiv
-// hkt : 2015-05-14 PCCW-HKT DataCom Services Limited
+// hkt : PCCW-HKT DataCom Services Limited
+// https://www.iana.org/domains/root/db/hkt.html
hkt
-// hockey : 2015-03-19 Binky Moon, LLC
+// hockey : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/hockey.html
hockey
-// holdings : 2013-08-27 Binky Moon, LLC
+// holdings : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/holdings.html
holdings
-// holiday : 2013-11-07 Binky Moon, LLC
+// holiday : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/holiday.html
holiday
-// homedepot : 2015-04-02 Home Depot Product Authority, LLC
+// homedepot : Home Depot Product Authority, LLC
+// https://www.iana.org/domains/root/db/homedepot.html
homedepot
-// homegoods : 2015-07-16 The TJX Companies, Inc.
+// homegoods : The TJX Companies, Inc.
+// https://www.iana.org/domains/root/db/homegoods.html
homegoods
-// homes : 2014-01-09 XYZ.COM LLC
+// homes : XYZ.COM LLC
+// https://www.iana.org/domains/root/db/homes.html
homes
-// homesense : 2015-07-16 The TJX Companies, Inc.
+// homesense : The TJX Companies, Inc.
+// https://www.iana.org/domains/root/db/homesense.html
homesense
-// honda : 2014-12-18 Honda Motor Co., Ltd.
+// honda : Honda Motor Co., Ltd.
+// https://www.iana.org/domains/root/db/honda.html
honda
-// horse : 2013-11-21 Registry Services, LLC
+// horse : Registry Services, LLC
+// https://www.iana.org/domains/root/db/horse.html
horse
-// hospital : 2016-10-20 Binky Moon, LLC
+// hospital : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/hospital.html
hospital
-// host : 2014-04-17 Radix FZC
+// host : Radix FZC DMCC
+// https://www.iana.org/domains/root/db/host.html
host
-// hosting : 2014-05-29 XYZ.COM LLC
+// hosting : XYZ.COM LLC
+// https://www.iana.org/domains/root/db/hosting.html
hosting
-// hot : 2015-08-27 Amazon Registry Services, Inc.
+// hot : Amazon Registry Services, Inc.
+// https://www.iana.org/domains/root/db/hot.html
hot
-// hoteles : 2015-03-05 Travel Reservations SRL
-hoteles
-
-// hotels : 2016-04-07 Booking.com B.V.
+// hotels : Booking.com B.V.
+// https://www.iana.org/domains/root/db/hotels.html
hotels
-// hotmail : 2014-12-18 Microsoft Corporation
+// hotmail : Microsoft Corporation
+// https://www.iana.org/domains/root/db/hotmail.html
hotmail
-// house : 2013-11-07 Binky Moon, LLC
+// house : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/house.html
house
-// how : 2014-01-23 Charleston Road Registry Inc.
+// how : Charleston Road Registry Inc.
+// https://www.iana.org/domains/root/db/how.html
how
-// hsbc : 2014-10-24 HSBC Global Services (UK) Limited
+// hsbc : HSBC Global Services (UK) Limited
+// https://www.iana.org/domains/root/db/hsbc.html
hsbc
-// hughes : 2015-07-30 Hughes Satellite Systems Corporation
+// hughes : Hughes Satellite Systems Corporation
+// https://www.iana.org/domains/root/db/hughes.html
hughes
-// hyatt : 2015-07-30 Hyatt GTLD, L.L.C.
+// hyatt : Hyatt GTLD, L.L.C.
+// https://www.iana.org/domains/root/db/hyatt.html
hyatt
-// hyundai : 2015-07-09 Hyundai Motor Company
+// hyundai : Hyundai Motor Company
+// https://www.iana.org/domains/root/db/hyundai.html
hyundai
-// ibm : 2014-07-31 International Business Machines Corporation
+// ibm : International Business Machines Corporation
+// https://www.iana.org/domains/root/db/ibm.html
ibm
-// icbc : 2015-02-19 Industrial and Commercial Bank of China Limited
+// icbc : Industrial and Commercial Bank of China Limited
+// https://www.iana.org/domains/root/db/icbc.html
icbc
-// ice : 2014-10-30 IntercontinentalExchange, Inc.
+// ice : IntercontinentalExchange, Inc.
+// https://www.iana.org/domains/root/db/ice.html
ice
-// icu : 2015-01-08 ShortDot SA
+// icu : ShortDot SA
+// https://www.iana.org/domains/root/db/icu.html
icu
-// ieee : 2015-07-23 IEEE Global LLC
+// ieee : IEEE Global LLC
+// https://www.iana.org/domains/root/db/ieee.html
ieee
-// ifm : 2014-01-30 ifm electronic gmbh
+// ifm : ifm electronic gmbh
+// https://www.iana.org/domains/root/db/ifm.html
ifm
-// ikano : 2015-07-09 Ikano S.A.
+// ikano : Ikano S.A.
+// https://www.iana.org/domains/root/db/ikano.html
ikano
-// imamat : 2015-08-06 Fondation Aga Khan (Aga Khan Foundation)
+// imamat : Fondation Aga Khan (Aga Khan Foundation)
+// https://www.iana.org/domains/root/db/imamat.html
imamat
-// imdb : 2015-06-25 Amazon Registry Services, Inc.
+// imdb : Amazon Registry Services, Inc.
+// https://www.iana.org/domains/root/db/imdb.html
imdb
-// immo : 2014-07-10 Binky Moon, LLC
+// immo : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/immo.html
immo
-// immobilien : 2013-11-07 Dog Beach, LLC
+// immobilien : Dog Beach, LLC
+// https://www.iana.org/domains/root/db/immobilien.html
immobilien
-// inc : 2018-03-10 Intercap Registry Inc.
+// inc : Intercap Registry Inc.
+// https://www.iana.org/domains/root/db/inc.html
inc
-// industries : 2013-12-05 Binky Moon, LLC
+// industries : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/industries.html
industries
-// infiniti : 2014-03-27 NISSAN MOTOR CO., LTD.
+// infiniti : NISSAN MOTOR CO., LTD.
+// https://www.iana.org/domains/root/db/infiniti.html
infiniti
-// ing : 2014-01-23 Charleston Road Registry Inc.
+// ing : Charleston Road Registry Inc.
+// https://www.iana.org/domains/root/db/ing.html
ing
-// ink : 2013-12-05 Top Level Design, LLC
+// ink : Registry Services, LLC
+// https://www.iana.org/domains/root/db/ink.html
ink
-// institute : 2013-11-07 Binky Moon, LLC
+// institute : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/institute.html
institute
-// insurance : 2015-02-19 fTLD Registry Services LLC
+// insurance : fTLD Registry Services LLC
+// https://www.iana.org/domains/root/db/insurance.html
insurance
-// insure : 2014-03-20 Binky Moon, LLC
+// insure : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/insure.html
insure
-// international : 2013-11-07 Binky Moon, LLC
+// international : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/international.html
international
-// intuit : 2015-07-30 Intuit Administrative Services, Inc.
+// intuit : Intuit Administrative Services, Inc.
+// https://www.iana.org/domains/root/db/intuit.html
intuit
-// investments : 2014-03-20 Binky Moon, LLC
+// investments : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/investments.html
investments
-// ipiranga : 2014-08-28 Ipiranga Produtos de Petroleo S.A.
+// ipiranga : Ipiranga Produtos de Petroleo S.A.
+// https://www.iana.org/domains/root/db/ipiranga.html
ipiranga
-// irish : 2014-08-07 Binky Moon, LLC
+// irish : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/irish.html
irish
-// ismaili : 2015-08-06 Fondation Aga Khan (Aga Khan Foundation)
+// ismaili : Fondation Aga Khan (Aga Khan Foundation)
+// https://www.iana.org/domains/root/db/ismaili.html
ismaili
-// ist : 2014-08-28 Istanbul Metropolitan Municipality
+// ist : Istanbul Metropolitan Municipality
+// https://www.iana.org/domains/root/db/ist.html
ist
-// istanbul : 2014-08-28 Istanbul Metropolitan Municipality
+// istanbul : Istanbul Metropolitan Municipality
+// https://www.iana.org/domains/root/db/istanbul.html
istanbul
-// itau : 2014-10-02 Itau Unibanco Holding S.A.
+// itau : Itau Unibanco Holding S.A.
+// https://www.iana.org/domains/root/db/itau.html
itau
-// itv : 2015-07-09 ITV Services Limited
+// itv : ITV Services Limited
+// https://www.iana.org/domains/root/db/itv.html
itv
-// jaguar : 2014-11-13 Jaguar Land Rover Ltd
+// jaguar : Jaguar Land Rover Ltd
+// https://www.iana.org/domains/root/db/jaguar.html
jaguar
-// java : 2014-06-19 Oracle Corporation
+// java : Oracle Corporation
+// https://www.iana.org/domains/root/db/java.html
java
-// jcb : 2014-11-20 JCB Co., Ltd.
+// jcb : JCB Co., Ltd.
+// https://www.iana.org/domains/root/db/jcb.html
jcb
-// jeep : 2015-07-30 FCA US LLC.
+// jeep : FCA US LLC.
+// https://www.iana.org/domains/root/db/jeep.html
jeep
-// jetzt : 2014-01-09 Binky Moon, LLC
+// jetzt : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/jetzt.html
jetzt
-// jewelry : 2015-03-05 Binky Moon, LLC
+// jewelry : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/jewelry.html
jewelry
-// jio : 2015-04-02 Reliance Industries Limited
+// jio : Reliance Industries Limited
+// https://www.iana.org/domains/root/db/jio.html
jio
-// jll : 2015-04-02 Jones Lang LaSalle Incorporated
+// jll : Jones Lang LaSalle Incorporated
+// https://www.iana.org/domains/root/db/jll.html
jll
-// jmp : 2015-03-26 Matrix IP LLC
+// jmp : Matrix IP LLC
+// https://www.iana.org/domains/root/db/jmp.html
jmp
-// jnj : 2015-06-18 Johnson & Johnson Services, Inc.
+// jnj : Johnson & Johnson Services, Inc.
+// https://www.iana.org/domains/root/db/jnj.html
jnj
-// joburg : 2014-03-24 ZA Central Registry NPC trading as ZA Central Registry
+// joburg : ZA Central Registry NPC trading as ZA Central Registry
+// https://www.iana.org/domains/root/db/joburg.html
joburg
-// jot : 2014-12-18 Amazon Registry Services, Inc.
+// jot : Amazon Registry Services, Inc.
+// https://www.iana.org/domains/root/db/jot.html
jot
-// joy : 2014-12-18 Amazon Registry Services, Inc.
+// joy : Amazon Registry Services, Inc.
+// https://www.iana.org/domains/root/db/joy.html
joy
-// jpmorgan : 2015-04-30 JPMorgan Chase Bank, National Association
+// jpmorgan : JPMorgan Chase Bank, National Association
+// https://www.iana.org/domains/root/db/jpmorgan.html
jpmorgan
-// jprs : 2014-09-18 Japan Registry Services Co., Ltd.
+// jprs : Japan Registry Services Co., Ltd.
+// https://www.iana.org/domains/root/db/jprs.html
jprs
-// juegos : 2014-03-20 Internet Naming Company LLC
+// juegos : Internet Naming Company LLC
+// https://www.iana.org/domains/root/db/juegos.html
juegos
-// juniper : 2015-07-30 JUNIPER NETWORKS, INC.
+// juniper : JUNIPER NETWORKS, INC.
+// https://www.iana.org/domains/root/db/juniper.html
juniper
-// kaufen : 2013-11-07 Dog Beach, LLC
+// kaufen : Dog Beach, LLC
+// https://www.iana.org/domains/root/db/kaufen.html
kaufen
-// kddi : 2014-09-12 KDDI CORPORATION
+// kddi : KDDI CORPORATION
+// https://www.iana.org/domains/root/db/kddi.html
kddi
-// kerryhotels : 2015-04-30 Kerry Trading Co. Limited
+// kerryhotels : Kerry Trading Co. Limited
+// https://www.iana.org/domains/root/db/kerryhotels.html
kerryhotels
-// kerrylogistics : 2015-04-09 Kerry Trading Co. Limited
+// kerrylogistics : Kerry Trading Co. Limited
+// https://www.iana.org/domains/root/db/kerrylogistics.html
kerrylogistics
-// kerryproperties : 2015-04-09 Kerry Trading Co. Limited
+// kerryproperties : Kerry Trading Co. Limited
+// https://www.iana.org/domains/root/db/kerryproperties.html
kerryproperties
-// kfh : 2014-12-04 Kuwait Finance House
+// kfh : Kuwait Finance House
+// https://www.iana.org/domains/root/db/kfh.html
kfh
-// kia : 2015-07-09 KIA MOTORS CORPORATION
+// kia : KIA MOTORS CORPORATION
+// https://www.iana.org/domains/root/db/kia.html
kia
-// kids : 2021-08-13 DotKids Foundation Limited
+// kids : DotKids Foundation Limited
+// https://www.iana.org/domains/root/db/kids.html
kids
-// kim : 2013-09-23 Identity Digital Limited
+// kim : Identity Digital Limited
+// https://www.iana.org/domains/root/db/kim.html
kim
-// kinder : 2014-11-07 Ferrero Trading Lux S.A.
-kinder
-
-// kindle : 2015-06-25 Amazon Registry Services, Inc.
+// kindle : Amazon Registry Services, Inc.
+// https://www.iana.org/domains/root/db/kindle.html
kindle
-// kitchen : 2013-09-20 Binky Moon, LLC
+// kitchen : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/kitchen.html
kitchen
-// kiwi : 2013-09-20 DOT KIWI LIMITED
+// kiwi : DOT KIWI LIMITED
+// https://www.iana.org/domains/root/db/kiwi.html
kiwi
-// koeln : 2014-01-09 dotKoeln GmbH
+// koeln : dotKoeln GmbH
+// https://www.iana.org/domains/root/db/koeln.html
koeln
-// komatsu : 2015-01-08 Komatsu Ltd.
+// komatsu : Komatsu Ltd.
+// https://www.iana.org/domains/root/db/komatsu.html
komatsu
-// kosher : 2015-08-20 Kosher Marketing Assets LLC
+// kosher : Kosher Marketing Assets LLC
+// https://www.iana.org/domains/root/db/kosher.html
kosher
-// kpmg : 2015-04-23 KPMG International Cooperative (KPMG International Genossenschaft)
+// kpmg : KPMG International Cooperative (KPMG International Genossenschaft)
+// https://www.iana.org/domains/root/db/kpmg.html
kpmg
-// kpn : 2015-01-08 Koninklijke KPN N.V.
+// kpn : Koninklijke KPN N.V.
+// https://www.iana.org/domains/root/db/kpn.html
kpn
-// krd : 2013-12-05 KRG Department of Information Technology
+// krd : KRG Department of Information Technology
+// https://www.iana.org/domains/root/db/krd.html
krd
-// kred : 2013-12-19 KredTLD Pty Ltd
+// kred : KredTLD Pty Ltd
+// https://www.iana.org/domains/root/db/kred.html
kred
-// kuokgroup : 2015-04-09 Kerry Trading Co. Limited
+// kuokgroup : Kerry Trading Co. Limited
+// https://www.iana.org/domains/root/db/kuokgroup.html
kuokgroup
-// kyoto : 2014-11-07 Academic Institution: Kyoto Jyoho Gakuen
+// kyoto : Academic Institution: Kyoto Jyoho Gakuen
+// https://www.iana.org/domains/root/db/kyoto.html
kyoto
-// lacaixa : 2014-01-09 Fundación Bancaria Caixa d’Estalvis i Pensions de Barcelona, “la Caixa”
+// lacaixa : Fundación Bancaria Caixa d’Estalvis i Pensions de Barcelona, “la Caixa”
+// https://www.iana.org/domains/root/db/lacaixa.html
lacaixa
-// lamborghini : 2015-06-04 Automobili Lamborghini S.p.A.
+// lamborghini : Automobili Lamborghini S.p.A.
+// https://www.iana.org/domains/root/db/lamborghini.html
lamborghini
-// lamer : 2015-10-01 The Estée Lauder Companies Inc.
+// lamer : The Estée Lauder Companies Inc.
+// https://www.iana.org/domains/root/db/lamer.html
lamer
-// lancaster : 2015-02-12 LANCASTER
+// lancaster : LANCASTER
+// https://www.iana.org/domains/root/db/lancaster.html
lancaster
-// lancia : 2015-07-31 Fiat Chrysler Automobiles N.V.
-lancia
-
-// land : 2013-09-10 Binky Moon, LLC
+// land : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/land.html
land
-// landrover : 2014-11-13 Jaguar Land Rover Ltd
+// landrover : Jaguar Land Rover Ltd
+// https://www.iana.org/domains/root/db/landrover.html
landrover
-// lanxess : 2015-07-30 LANXESS Corporation
+// lanxess : LANXESS Corporation
+// https://www.iana.org/domains/root/db/lanxess.html
lanxess
-// lasalle : 2015-04-02 Jones Lang LaSalle Incorporated
+// lasalle : Jones Lang LaSalle Incorporated
+// https://www.iana.org/domains/root/db/lasalle.html
lasalle
-// lat : 2014-10-16 XYZ.COM LLC
+// lat : XYZ.COM LLC
+// https://www.iana.org/domains/root/db/lat.html
lat
-// latino : 2015-07-30 Dish DBS Corporation
+// latino : Dish DBS Corporation
+// https://www.iana.org/domains/root/db/latino.html
latino
-// latrobe : 2014-06-16 La Trobe University
+// latrobe : La Trobe University
+// https://www.iana.org/domains/root/db/latrobe.html
latrobe
-// law : 2015-01-22 Registry Services, LLC
+// law : Registry Services, LLC
+// https://www.iana.org/domains/root/db/law.html
law
-// lawyer : 2014-03-20 Dog Beach, LLC
+// lawyer : Dog Beach, LLC
+// https://www.iana.org/domains/root/db/lawyer.html
lawyer
-// lds : 2014-03-20 IRI Domain Management, LLC
+// lds : IRI Domain Management, LLC
+// https://www.iana.org/domains/root/db/lds.html
lds
-// lease : 2014-03-06 Binky Moon, LLC
+// lease : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/lease.html
lease
-// leclerc : 2014-08-07 A.C.D. LEC Association des Centres Distributeurs Edouard Leclerc
+// leclerc : A.C.D. LEC Association des Centres Distributeurs Edouard Leclerc
+// https://www.iana.org/domains/root/db/leclerc.html
leclerc
-// lefrak : 2015-07-16 LeFrak Organization, Inc.
+// lefrak : LeFrak Organization, Inc.
+// https://www.iana.org/domains/root/db/lefrak.html
lefrak
-// legal : 2014-10-16 Binky Moon, LLC
+// legal : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/legal.html
legal
-// lego : 2015-07-16 LEGO Juris A/S
+// lego : LEGO Juris A/S
+// https://www.iana.org/domains/root/db/lego.html
lego
-// lexus : 2015-04-23 TOYOTA MOTOR CORPORATION
+// lexus : TOYOTA MOTOR CORPORATION
+// https://www.iana.org/domains/root/db/lexus.html
lexus
-// lgbt : 2014-05-08 Identity Digital Limited
+// lgbt : Identity Digital Limited
+// https://www.iana.org/domains/root/db/lgbt.html
lgbt
-// lidl : 2014-09-18 Schwarz Domains und Services GmbH & Co. KG
+// lidl : Schwarz Domains und Services GmbH & Co. KG
+// https://www.iana.org/domains/root/db/lidl.html
lidl
-// life : 2014-02-06 Binky Moon, LLC
+// life : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/life.html
life
-// lifeinsurance : 2015-01-15 American Council of Life Insurers
+// lifeinsurance : American Council of Life Insurers
+// https://www.iana.org/domains/root/db/lifeinsurance.html
lifeinsurance
-// lifestyle : 2014-12-11 Lifestyle Domain Holdings, Inc.
+// lifestyle : Internet Naming Company LLC
+// https://www.iana.org/domains/root/db/lifestyle.html
lifestyle
-// lighting : 2013-08-27 Binky Moon, LLC
+// lighting : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/lighting.html
lighting
-// like : 2014-12-18 Amazon Registry Services, Inc.
+// like : Amazon Registry Services, Inc.
+// https://www.iana.org/domains/root/db/like.html
like
-// lilly : 2015-07-31 Eli Lilly and Company
+// lilly : Eli Lilly and Company
+// https://www.iana.org/domains/root/db/lilly.html
lilly
-// limited : 2014-03-06 Binky Moon, LLC
+// limited : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/limited.html
limited
-// limo : 2013-10-17 Binky Moon, LLC
+// limo : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/limo.html
limo
-// lincoln : 2014-11-13 Ford Motor Company
+// lincoln : Ford Motor Company
+// https://www.iana.org/domains/root/db/lincoln.html
lincoln
-// link : 2013-11-14 Nova Registry Ltd
+// link : Nova Registry Ltd
+// https://www.iana.org/domains/root/db/link.html
link
-// lipsy : 2015-06-25 Lipsy Ltd
+// lipsy : Lipsy Ltd
+// https://www.iana.org/domains/root/db/lipsy.html
lipsy
-// live : 2014-12-04 Dog Beach, LLC
+// live : Dog Beach, LLC
+// https://www.iana.org/domains/root/db/live.html
live
-// living : 2015-07-30 Lifestyle Domain Holdings, Inc.
+// living : Internet Naming Company LLC
+// https://www.iana.org/domains/root/db/living.html
living
-// llc : 2017-12-14 Identity Digital Limited
+// llc : Identity Digital Limited
+// https://www.iana.org/domains/root/db/llc.html
llc
-// llp : 2019-08-26 Intercap Registry Inc.
+// llp : Intercap Registry Inc.
+// https://www.iana.org/domains/root/db/llp.html
llp
-// loan : 2014-11-20 dot Loan Limited
+// loan : dot Loan Limited
+// https://www.iana.org/domains/root/db/loan.html
loan
-// loans : 2014-03-20 Binky Moon, LLC
+// loans : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/loans.html
loans
-// locker : 2015-06-04 Dish DBS Corporation
+// locker : Orange Domains LLC
+// https://www.iana.org/domains/root/db/locker.html
locker
-// locus : 2015-06-25 Locus Analytics LLC
+// locus : Locus Analytics LLC
+// https://www.iana.org/domains/root/db/locus.html
locus
-// lol : 2015-01-30 XYZ.COM LLC
+// lol : XYZ.COM LLC
+// https://www.iana.org/domains/root/db/lol.html
lol
-// london : 2013-11-14 Dot London Domains Limited
+// london : Dot London Domains Limited
+// https://www.iana.org/domains/root/db/london.html
london
-// lotte : 2014-11-07 Lotte Holdings Co., Ltd.
+// lotte : Lotte Holdings Co., Ltd.
+// https://www.iana.org/domains/root/db/lotte.html
lotte
-// lotto : 2014-04-10 Identity Digital Limited
+// lotto : Identity Digital Limited
+// https://www.iana.org/domains/root/db/lotto.html
lotto
-// love : 2014-12-22 Merchant Law Group LLP
+// love : Merchant Law Group LLP
+// https://www.iana.org/domains/root/db/love.html
love
-// lpl : 2015-07-30 LPL Holdings, Inc.
+// lpl : LPL Holdings, Inc.
+// https://www.iana.org/domains/root/db/lpl.html
lpl
-// lplfinancial : 2015-07-30 LPL Holdings, Inc.
+// lplfinancial : LPL Holdings, Inc.
+// https://www.iana.org/domains/root/db/lplfinancial.html
lplfinancial
-// ltd : 2014-09-25 Binky Moon, LLC
+// ltd : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/ltd.html
ltd
-// ltda : 2014-04-17 InterNetX, Corp
+// ltda : InterNetX, Corp
+// https://www.iana.org/domains/root/db/ltda.html
ltda
-// lundbeck : 2015-08-06 H. Lundbeck A/S
+// lundbeck : H. Lundbeck A/S
+// https://www.iana.org/domains/root/db/lundbeck.html
lundbeck
-// luxe : 2014-01-09 Registry Services, LLC
+// luxe : Registry Services, LLC
+// https://www.iana.org/domains/root/db/luxe.html
luxe
-// luxury : 2013-10-17 Luxury Partners, LLC
+// luxury : Luxury Partners, LLC
+// https://www.iana.org/domains/root/db/luxury.html
luxury
-// madrid : 2014-05-01 Comunidad de Madrid
+// madrid : Comunidad de Madrid
+// https://www.iana.org/domains/root/db/madrid.html
madrid
-// maif : 2014-10-02 Mutuelle Assurance Instituteur France (MAIF)
+// maif : Mutuelle Assurance Instituteur France (MAIF)
+// https://www.iana.org/domains/root/db/maif.html
maif
-// maison : 2013-12-05 Binky Moon, LLC
+// maison : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/maison.html
maison
-// makeup : 2015-01-15 XYZ.COM LLC
+// makeup : XYZ.COM LLC
+// https://www.iana.org/domains/root/db/makeup.html
makeup
-// man : 2014-12-04 MAN SE
+// man : MAN SE
+// https://www.iana.org/domains/root/db/man.html
man
-// management : 2013-11-07 Binky Moon, LLC
+// management : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/management.html
management
-// mango : 2013-10-24 PUNTO FA S.L.
+// mango : PUNTO FA S.L.
+// https://www.iana.org/domains/root/db/mango.html
mango
-// map : 2016-06-09 Charleston Road Registry Inc.
+// map : Charleston Road Registry Inc.
+// https://www.iana.org/domains/root/db/map.html
map
-// market : 2014-03-06 Dog Beach, LLC
+// market : Dog Beach, LLC
+// https://www.iana.org/domains/root/db/market.html
market
-// marketing : 2013-11-07 Binky Moon, LLC
+// marketing : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/marketing.html
marketing
-// markets : 2014-12-11 Dog Beach, LLC
+// markets : Dog Beach, LLC
+// https://www.iana.org/domains/root/db/markets.html
markets
-// marriott : 2014-10-09 Marriott Worldwide Corporation
+// marriott : Marriott Worldwide Corporation
+// https://www.iana.org/domains/root/db/marriott.html
marriott
-// marshalls : 2015-07-16 The TJX Companies, Inc.
+// marshalls : The TJX Companies, Inc.
+// https://www.iana.org/domains/root/db/marshalls.html
marshalls
-// maserati : 2015-07-31 Fiat Chrysler Automobiles N.V.
-maserati
-
-// mattel : 2015-08-06 Mattel Sites, Inc.
+// mattel : Mattel Sites, Inc.
+// https://www.iana.org/domains/root/db/mattel.html
mattel
-// mba : 2015-04-02 Binky Moon, LLC
+// mba : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/mba.html
mba
-// mckinsey : 2015-07-31 McKinsey Holdings, Inc.
+// mckinsey : McKinsey Holdings, Inc.
+// https://www.iana.org/domains/root/db/mckinsey.html
mckinsey
-// med : 2015-08-06 Medistry LLC
+// med : Medistry LLC
+// https://www.iana.org/domains/root/db/med.html
med
-// media : 2014-03-06 Binky Moon, LLC
+// media : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/media.html
media
-// meet : 2014-01-16 Charleston Road Registry Inc.
+// meet : Charleston Road Registry Inc.
+// https://www.iana.org/domains/root/db/meet.html
meet
-// melbourne : 2014-05-29 The Crown in right of the State of Victoria, represented by its Department of State Development, Business and Innovation
+// melbourne : The Crown in right of the State of Victoria, represented by its Department of State Development, Business and Innovation
+// https://www.iana.org/domains/root/db/melbourne.html
melbourne
-// meme : 2014-01-30 Charleston Road Registry Inc.
+// meme : Charleston Road Registry Inc.
+// https://www.iana.org/domains/root/db/meme.html
meme
-// memorial : 2014-10-16 Dog Beach, LLC
+// memorial : Dog Beach, LLC
+// https://www.iana.org/domains/root/db/memorial.html
memorial
-// men : 2015-02-26 Exclusive Registry Limited
+// men : Exclusive Registry Limited
+// https://www.iana.org/domains/root/db/men.html
men
-// menu : 2013-09-11 Dot Menu Registry, LLC
+// menu : Dot Menu Registry, LLC
+// https://www.iana.org/domains/root/db/menu.html
menu
-// merckmsd : 2016-07-14 MSD Registry Holdings, Inc.
+// merckmsd : MSD Registry Holdings, Inc.
+// https://www.iana.org/domains/root/db/merckmsd.html
merckmsd
-// miami : 2013-12-19 Registry Services, LLC
+// miami : Registry Services, LLC
+// https://www.iana.org/domains/root/db/miami.html
miami
-// microsoft : 2014-12-18 Microsoft Corporation
+// microsoft : Microsoft Corporation
+// https://www.iana.org/domains/root/db/microsoft.html
microsoft
-// mini : 2014-01-09 Bayerische Motoren Werke Aktiengesellschaft
+// mini : Bayerische Motoren Werke Aktiengesellschaft
+// https://www.iana.org/domains/root/db/mini.html
mini
-// mint : 2015-07-30 Intuit Administrative Services, Inc.
+// mint : Intuit Administrative Services, Inc.
+// https://www.iana.org/domains/root/db/mint.html
mint
-// mit : 2015-07-02 Massachusetts Institute of Technology
+// mit : Massachusetts Institute of Technology
+// https://www.iana.org/domains/root/db/mit.html
mit
-// mitsubishi : 2015-07-23 Mitsubishi Corporation
+// mitsubishi : Mitsubishi Corporation
+// https://www.iana.org/domains/root/db/mitsubishi.html
mitsubishi
-// mlb : 2015-05-21 MLB Advanced Media DH, LLC
+// mlb : MLB Advanced Media DH, LLC
+// https://www.iana.org/domains/root/db/mlb.html
mlb
-// mls : 2015-04-23 The Canadian Real Estate Association
+// mls : The Canadian Real Estate Association
+// https://www.iana.org/domains/root/db/mls.html
mls
-// mma : 2014-11-07 MMA IARD
+// mma : MMA IARD
+// https://www.iana.org/domains/root/db/mma.html
mma
-// mobile : 2016-06-02 Dish DBS Corporation
+// mobile : Dish DBS Corporation
+// https://www.iana.org/domains/root/db/mobile.html
mobile
-// moda : 2013-11-07 Dog Beach, LLC
+// moda : Dog Beach, LLC
+// https://www.iana.org/domains/root/db/moda.html
moda
-// moe : 2013-11-13 Interlink Systems Innovation Institute K.K.
+// moe : Interlink Systems Innovation Institute K.K.
+// https://www.iana.org/domains/root/db/moe.html
moe
-// moi : 2014-12-18 Amazon Registry Services, Inc.
+// moi : Amazon Registry Services, Inc.
+// https://www.iana.org/domains/root/db/moi.html
moi
-// mom : 2015-04-16 XYZ.COM LLC
+// mom : XYZ.COM LLC
+// https://www.iana.org/domains/root/db/mom.html
mom
-// monash : 2013-09-30 Monash University
+// monash : Monash University
+// https://www.iana.org/domains/root/db/monash.html
monash
-// money : 2014-10-16 Binky Moon, LLC
+// money : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/money.html
money
-// monster : 2015-09-11 XYZ.COM LLC
+// monster : XYZ.COM LLC
+// https://www.iana.org/domains/root/db/monster.html
monster
-// mormon : 2013-12-05 IRI Domain Management, LLC
+// mormon : IRI Domain Management, LLC
+// https://www.iana.org/domains/root/db/mormon.html
mormon
-// mortgage : 2014-03-20 Dog Beach, LLC
+// mortgage : Dog Beach, LLC
+// https://www.iana.org/domains/root/db/mortgage.html
mortgage
-// moscow : 2013-12-19 Foundation for Assistance for Internet Technologies and Infrastructure Development (FAITID)
+// moscow : Foundation for Assistance for Internet Technologies and Infrastructure Development (FAITID)
+// https://www.iana.org/domains/root/db/moscow.html
moscow
-// moto : 2015-06-04 Motorola Trademark Holdings, LLC
+// moto : Motorola Trademark Holdings, LLC
+// https://www.iana.org/domains/root/db/moto.html
moto
-// motorcycles : 2014-01-09 XYZ.COM LLC
+// motorcycles : XYZ.COM LLC
+// https://www.iana.org/domains/root/db/motorcycles.html
motorcycles
-// mov : 2014-01-30 Charleston Road Registry Inc.
+// mov : Charleston Road Registry Inc.
+// https://www.iana.org/domains/root/db/mov.html
mov
-// movie : 2015-02-05 Binky Moon, LLC
+// movie : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/movie.html
movie
-// msd : 2015-07-23 MSD Registry Holdings, Inc.
+// msd : MSD Registry Holdings, Inc.
+// https://www.iana.org/domains/root/db/msd.html
msd
-// mtn : 2014-12-04 MTN Dubai Limited
+// mtn : MTN Dubai Limited
+// https://www.iana.org/domains/root/db/mtn.html
mtn
-// mtr : 2015-03-12 MTR Corporation Limited
+// mtr : MTR Corporation Limited
+// https://www.iana.org/domains/root/db/mtr.html
mtr
-// music : 2021-05-04 DotMusic Limited
+// music : DotMusic Limited
+// https://www.iana.org/domains/root/db/music.html
music
-// mutual : 2015-04-02 Northwestern Mutual MU TLD Registry, LLC
-mutual
-
-// nab : 2015-08-20 National Australia Bank Limited
+// nab : National Australia Bank Limited
+// https://www.iana.org/domains/root/db/nab.html
nab
-// nagoya : 2013-10-24 GMO Registry, Inc.
+// nagoya : GMO Registry, Inc.
+// https://www.iana.org/domains/root/db/nagoya.html
nagoya
-// natura : 2015-03-12 NATURA COSMÉTICOS S.A.
+// natura : NATURA COSMÉTICOS S.A.
+// https://www.iana.org/domains/root/db/natura.html
natura
-// navy : 2014-03-06 Dog Beach, LLC
+// navy : Dog Beach, LLC
+// https://www.iana.org/domains/root/db/navy.html
navy
-// nba : 2015-07-31 NBA REGISTRY, LLC
+// nba : NBA REGISTRY, LLC
+// https://www.iana.org/domains/root/db/nba.html
nba
-// nec : 2015-01-08 NEC Corporation
+// nec : NEC Corporation
+// https://www.iana.org/domains/root/db/nec.html
nec
-// netbank : 2014-06-26 COMMONWEALTH BANK OF AUSTRALIA
+// netbank : COMMONWEALTH BANK OF AUSTRALIA
+// https://www.iana.org/domains/root/db/netbank.html
netbank
-// netflix : 2015-06-18 Netflix, Inc.
+// netflix : Netflix, Inc.
+// https://www.iana.org/domains/root/db/netflix.html
netflix
-// network : 2013-11-14 Binky Moon, LLC
+// network : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/network.html
network
-// neustar : 2013-12-05 NeuStar, Inc.
+// neustar : NeuStar, Inc.
+// https://www.iana.org/domains/root/db/neustar.html
neustar
-// new : 2014-01-30 Charleston Road Registry Inc.
+// new : Charleston Road Registry Inc.
+// https://www.iana.org/domains/root/db/new.html
new
-// news : 2014-12-18 Dog Beach, LLC
+// news : Dog Beach, LLC
+// https://www.iana.org/domains/root/db/news.html
news
-// next : 2015-06-18 Next plc
+// next : Next plc
+// https://www.iana.org/domains/root/db/next.html
next
-// nextdirect : 2015-06-18 Next plc
+// nextdirect : Next plc
+// https://www.iana.org/domains/root/db/nextdirect.html
nextdirect
-// nexus : 2014-07-24 Charleston Road Registry Inc.
+// nexus : Charleston Road Registry Inc.
+// https://www.iana.org/domains/root/db/nexus.html
nexus
-// nfl : 2015-07-23 NFL Reg Ops LLC
+// nfl : NFL Reg Ops LLC
+// https://www.iana.org/domains/root/db/nfl.html
nfl
-// ngo : 2014-03-06 Public Interest Registry
+// ngo : Public Interest Registry
+// https://www.iana.org/domains/root/db/ngo.html
ngo
-// nhk : 2014-02-13 Japan Broadcasting Corporation (NHK)
+// nhk : Japan Broadcasting Corporation (NHK)
+// https://www.iana.org/domains/root/db/nhk.html
nhk
-// nico : 2014-12-04 DWANGO Co., Ltd.
+// nico : DWANGO Co., Ltd.
+// https://www.iana.org/domains/root/db/nico.html
nico
-// nike : 2015-07-23 NIKE, Inc.
+// nike : NIKE, Inc.
+// https://www.iana.org/domains/root/db/nike.html
nike
-// nikon : 2015-05-21 NIKON CORPORATION
+// nikon : NIKON CORPORATION
+// https://www.iana.org/domains/root/db/nikon.html
nikon
-// ninja : 2013-11-07 Dog Beach, LLC
+// ninja : Dog Beach, LLC
+// https://www.iana.org/domains/root/db/ninja.html
ninja
-// nissan : 2014-03-27 NISSAN MOTOR CO., LTD.
+// nissan : NISSAN MOTOR CO., LTD.
+// https://www.iana.org/domains/root/db/nissan.html
nissan
-// nissay : 2015-10-29 Nippon Life Insurance Company
+// nissay : Nippon Life Insurance Company
+// https://www.iana.org/domains/root/db/nissay.html
nissay
-// nokia : 2015-01-08 Nokia Corporation
+// nokia : Nokia Corporation
+// https://www.iana.org/domains/root/db/nokia.html
nokia
-// northwesternmutual : 2015-06-18 Northwestern Mutual Registry, LLC
-northwesternmutual
-
-// norton : 2014-12-04 NortonLifeLock Inc.
+// norton : NortonLifeLock Inc.
+// https://www.iana.org/domains/root/db/norton.html
norton
-// now : 2015-06-25 Amazon Registry Services, Inc.
+// now : Amazon Registry Services, Inc.
+// https://www.iana.org/domains/root/db/now.html
now
-// nowruz : 2014-09-04 Asia Green IT System Bilgisayar San. ve Tic. Ltd. Sti.
+// nowruz : Asia Green IT System Bilgisayar San. ve Tic. Ltd. Sti.
+// https://www.iana.org/domains/root/db/nowruz.html
nowruz
-// nowtv : 2015-05-14 Starbucks (HK) Limited
+// nowtv : Starbucks (HK) Limited
+// https://www.iana.org/domains/root/db/nowtv.html
nowtv
-// nra : 2014-05-22 NRA Holdings Company, INC.
+// nra : NRA Holdings Company, INC.
+// https://www.iana.org/domains/root/db/nra.html
nra
-// nrw : 2013-11-21 Minds + Machines GmbH
+// nrw : Minds + Machines GmbH
+// https://www.iana.org/domains/root/db/nrw.html
nrw
-// ntt : 2014-10-31 NIPPON TELEGRAPH AND TELEPHONE CORPORATION
+// ntt : NIPPON TELEGRAPH AND TELEPHONE CORPORATION
+// https://www.iana.org/domains/root/db/ntt.html
ntt
-// nyc : 2014-01-23 The City of New York by and through the New York City Department of Information Technology & Telecommunications
+// nyc : The City of New York by and through the New York City Department of Information Technology & Telecommunications
+// https://www.iana.org/domains/root/db/nyc.html
nyc
-// obi : 2014-09-25 OBI Group Holding SE & Co. KGaA
+// obi : OBI Group Holding SE & Co. KGaA
+// https://www.iana.org/domains/root/db/obi.html
obi
-// observer : 2015-04-30 Dog Beach, LLC
+// observer : Fegistry, LLC
+// https://www.iana.org/domains/root/db/observer.html
observer
-// office : 2015-03-12 Microsoft Corporation
+// office : Microsoft Corporation
+// https://www.iana.org/domains/root/db/office.html
office
-// okinawa : 2013-12-05 BRregistry, Inc.
+// okinawa : BRregistry, Inc.
+// https://www.iana.org/domains/root/db/okinawa.html
okinawa
-// olayan : 2015-05-14 Crescent Holding GmbH
+// olayan : Competrol (Luxembourg) Sarl
+// https://www.iana.org/domains/root/db/olayan.html
olayan
-// olayangroup : 2015-05-14 Crescent Holding GmbH
+// olayangroup : Competrol (Luxembourg) Sarl
+// https://www.iana.org/domains/root/db/olayangroup.html
olayangroup
-// oldnavy : 2015-07-31 The Gap, Inc.
+// oldnavy : The Gap, Inc.
+// https://www.iana.org/domains/root/db/oldnavy.html
oldnavy
-// ollo : 2015-06-04 Dish DBS Corporation
+// ollo : Dish DBS Corporation
+// https://www.iana.org/domains/root/db/ollo.html
ollo
-// omega : 2015-01-08 The Swatch Group Ltd
+// omega : The Swatch Group Ltd
+// https://www.iana.org/domains/root/db/omega.html
omega
-// one : 2014-11-07 One.com A/S
+// one : One.com A/S
+// https://www.iana.org/domains/root/db/one.html
one
-// ong : 2014-03-06 Public Interest Registry
+// ong : Public Interest Registry
+// https://www.iana.org/domains/root/db/ong.html
ong
-// onl : 2013-09-16 iRegistry GmbH
+// onl : iRegistry GmbH
+// https://www.iana.org/domains/root/db/onl.html
onl
-// online : 2015-01-15 Radix FZC
+// online : Radix FZC DMCC
+// https://www.iana.org/domains/root/db/online.html
online
-// ooo : 2014-01-09 INFIBEAM AVENUES LIMITED
+// ooo : INFIBEAM AVENUES LIMITED
+// https://www.iana.org/domains/root/db/ooo.html
ooo
-// open : 2015-07-31 American Express Travel Related Services Company, Inc.
+// open : American Express Travel Related Services Company, Inc.
+// https://www.iana.org/domains/root/db/open.html
open
-// oracle : 2014-06-19 Oracle Corporation
+// oracle : Oracle Corporation
+// https://www.iana.org/domains/root/db/oracle.html
oracle
-// orange : 2015-03-12 Orange Brand Services Limited
+// orange : Orange Brand Services Limited
+// https://www.iana.org/domains/root/db/orange.html
orange
-// organic : 2014-03-27 Identity Digital Limited
+// organic : Identity Digital Limited
+// https://www.iana.org/domains/root/db/organic.html
organic
-// origins : 2015-10-01 The Estée Lauder Companies Inc.
+// origins : The Estée Lauder Companies Inc.
+// https://www.iana.org/domains/root/db/origins.html
origins
-// osaka : 2014-09-04 Osaka Registry Co., Ltd.
+// osaka : Osaka Registry Co., Ltd.
+// https://www.iana.org/domains/root/db/osaka.html
osaka
-// otsuka : 2013-10-11 Otsuka Holdings Co., Ltd.
+// otsuka : Otsuka Holdings Co., Ltd.
+// https://www.iana.org/domains/root/db/otsuka.html
otsuka
-// ott : 2015-06-04 Dish DBS Corporation
+// ott : Dish DBS Corporation
+// https://www.iana.org/domains/root/db/ott.html
ott
-// ovh : 2014-01-16 MédiaBC
+// ovh : MédiaBC
+// https://www.iana.org/domains/root/db/ovh.html
ovh
-// page : 2014-12-04 Charleston Road Registry Inc.
+// page : Charleston Road Registry Inc.
+// https://www.iana.org/domains/root/db/page.html
page
-// panasonic : 2015-07-30 Panasonic Corporation
+// panasonic : Panasonic Holdings Corporation
+// https://www.iana.org/domains/root/db/panasonic.html
panasonic
-// paris : 2014-01-30 City of Paris
+// paris : City of Paris
+// https://www.iana.org/domains/root/db/paris.html
paris
-// pars : 2014-09-04 Asia Green IT System Bilgisayar San. ve Tic. Ltd. Sti.
+// pars : Asia Green IT System Bilgisayar San. ve Tic. Ltd. Sti.
+// https://www.iana.org/domains/root/db/pars.html
pars
-// partners : 2013-12-05 Binky Moon, LLC
+// partners : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/partners.html
partners
-// parts : 2013-12-05 Binky Moon, LLC
+// parts : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/parts.html
parts
-// party : 2014-09-11 Blue Sky Registry Limited
+// party : Blue Sky Registry Limited
+// https://www.iana.org/domains/root/db/party.html
party
-// passagens : 2015-03-05 Travel Reservations SRL
-passagens
-
-// pay : 2015-08-27 Amazon Registry Services, Inc.
+// pay : Amazon Registry Services, Inc.
+// https://www.iana.org/domains/root/db/pay.html
pay
-// pccw : 2015-05-14 PCCW Enterprises Limited
+// pccw : PCCW Enterprises Limited
+// https://www.iana.org/domains/root/db/pccw.html
pccw
-// pet : 2015-05-07 Identity Digital Limited
+// pet : Identity Digital Limited
+// https://www.iana.org/domains/root/db/pet.html
pet
-// pfizer : 2015-09-11 Pfizer Inc.
+// pfizer : Pfizer Inc.
+// https://www.iana.org/domains/root/db/pfizer.html
pfizer
-// pharmacy : 2014-06-19 National Association of Boards of Pharmacy
+// pharmacy : National Association of Boards of Pharmacy
+// https://www.iana.org/domains/root/db/pharmacy.html
pharmacy
-// phd : 2016-07-28 Charleston Road Registry Inc.
+// phd : Charleston Road Registry Inc.
+// https://www.iana.org/domains/root/db/phd.html
phd
-// philips : 2014-11-07 Koninklijke Philips N.V.
+// philips : Koninklijke Philips N.V.
+// https://www.iana.org/domains/root/db/philips.html
philips
-// phone : 2016-06-02 Dish DBS Corporation
+// phone : Dish DBS Corporation
+// https://www.iana.org/domains/root/db/phone.html
phone
-// photo : 2013-11-14 Registry Services, LLC
+// photo : Registry Services, LLC
+// https://www.iana.org/domains/root/db/photo.html
photo
-// photography : 2013-09-20 Binky Moon, LLC
+// photography : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/photography.html
photography
-// photos : 2013-10-17 Binky Moon, LLC
+// photos : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/photos.html
photos
-// physio : 2014-05-01 PhysBiz Pty Ltd
+// physio : PhysBiz Pty Ltd
+// https://www.iana.org/domains/root/db/physio.html
physio
-// pics : 2013-11-14 XYZ.COM LLC
+// pics : XYZ.COM LLC
+// https://www.iana.org/domains/root/db/pics.html
pics
-// pictet : 2014-06-26 Pictet Europe S.A.
+// pictet : Pictet Europe S.A.
+// https://www.iana.org/domains/root/db/pictet.html
pictet
-// pictures : 2014-03-06 Binky Moon, LLC
+// pictures : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/pictures.html
pictures
-// pid : 2015-01-08 Top Level Spectrum, Inc.
+// pid : Top Level Spectrum, Inc.
+// https://www.iana.org/domains/root/db/pid.html
pid
-// pin : 2014-12-18 Amazon Registry Services, Inc.
+// pin : Amazon Registry Services, Inc.
+// https://www.iana.org/domains/root/db/pin.html
pin
-// ping : 2015-06-11 Ping Registry Provider, Inc.
+// ping : Ping Registry Provider, Inc.
+// https://www.iana.org/domains/root/db/ping.html
ping
-// pink : 2013-10-01 Identity Digital Limited
+// pink : Identity Digital Limited
+// https://www.iana.org/domains/root/db/pink.html
pink
-// pioneer : 2015-07-16 Pioneer Corporation
+// pioneer : Pioneer Corporation
+// https://www.iana.org/domains/root/db/pioneer.html
pioneer
-// pizza : 2014-06-26 Binky Moon, LLC
+// pizza : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/pizza.html
pizza
-// place : 2014-04-24 Binky Moon, LLC
+// place : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/place.html
place
-// play : 2015-03-05 Charleston Road Registry Inc.
+// play : Charleston Road Registry Inc.
+// https://www.iana.org/domains/root/db/play.html
play
-// playstation : 2015-07-02 Sony Interactive Entertainment Inc.
+// playstation : Sony Interactive Entertainment Inc.
+// https://www.iana.org/domains/root/db/playstation.html
playstation
-// plumbing : 2013-09-10 Binky Moon, LLC
+// plumbing : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/plumbing.html
plumbing
-// plus : 2015-02-05 Binky Moon, LLC
+// plus : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/plus.html
plus
-// pnc : 2015-07-02 PNC Domain Co., LLC
+// pnc : PNC Domain Co., LLC
+// https://www.iana.org/domains/root/db/pnc.html
pnc
-// pohl : 2014-06-23 Deutsche Vermögensberatung Aktiengesellschaft DVAG
+// pohl : Deutsche Vermögensberatung Aktiengesellschaft DVAG
+// https://www.iana.org/domains/root/db/pohl.html
pohl
-// poker : 2014-07-03 Identity Digital Limited
+// poker : Identity Digital Limited
+// https://www.iana.org/domains/root/db/poker.html
poker
-// politie : 2015-08-20 Politie Nederland
+// politie : Politie Nederland
+// https://www.iana.org/domains/root/db/politie.html
politie
-// porn : 2014-10-16 ICM Registry PN LLC
+// porn : ICM Registry PN LLC
+// https://www.iana.org/domains/root/db/porn.html
porn
-// pramerica : 2015-07-30 Prudential Financial, Inc.
+// pramerica : Prudential Financial, Inc.
+// https://www.iana.org/domains/root/db/pramerica.html
pramerica
-// praxi : 2013-12-05 Praxi S.p.A.
+// praxi : Praxi S.p.A.
+// https://www.iana.org/domains/root/db/praxi.html
praxi
-// press : 2014-04-03 Radix FZC
+// press : Radix FZC DMCC
+// https://www.iana.org/domains/root/db/press.html
press
-// prime : 2015-06-25 Amazon Registry Services, Inc.
+// prime : Amazon Registry Services, Inc.
+// https://www.iana.org/domains/root/db/prime.html
prime
-// prod : 2014-01-23 Charleston Road Registry Inc.
+// prod : Charleston Road Registry Inc.
+// https://www.iana.org/domains/root/db/prod.html
prod
-// productions : 2013-12-05 Binky Moon, LLC
+// productions : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/productions.html
productions
-// prof : 2014-07-24 Charleston Road Registry Inc.
+// prof : Charleston Road Registry Inc.
+// https://www.iana.org/domains/root/db/prof.html
prof
-// progressive : 2015-07-23 Progressive Casualty Insurance Company
+// progressive : Progressive Casualty Insurance Company
+// https://www.iana.org/domains/root/db/progressive.html
progressive
-// promo : 2014-12-18 Identity Digital Limited
+// promo : Identity Digital Limited
+// https://www.iana.org/domains/root/db/promo.html
promo
-// properties : 2013-12-05 Binky Moon, LLC
+// properties : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/properties.html
properties
-// property : 2014-05-22 Internet Naming Company LLC
+// property : Digital Property Infrastructure Limited
+// https://www.iana.org/domains/root/db/property.html
property
-// protection : 2015-04-23 XYZ.COM LLC
+// protection : XYZ.COM LLC
+// https://www.iana.org/domains/root/db/protection.html
protection
-// pru : 2015-07-30 Prudential Financial, Inc.
+// pru : Prudential Financial, Inc.
+// https://www.iana.org/domains/root/db/pru.html
pru
-// prudential : 2015-07-30 Prudential Financial, Inc.
+// prudential : Prudential Financial, Inc.
+// https://www.iana.org/domains/root/db/prudential.html
prudential
-// pub : 2013-12-12 Dog Beach, LLC
+// pub : Dog Beach, LLC
+// https://www.iana.org/domains/root/db/pub.html
pub
-// pwc : 2015-10-29 PricewaterhouseCoopers LLP
+// pwc : PricewaterhouseCoopers LLP
+// https://www.iana.org/domains/root/db/pwc.html
pwc
-// qpon : 2013-11-14 dotQPON LLC
+// qpon : dotQPON LLC
+// https://www.iana.org/domains/root/db/qpon.html
qpon
-// quebec : 2013-12-19 PointQuébec Inc
+// quebec : PointQuébec Inc
+// https://www.iana.org/domains/root/db/quebec.html
quebec
-// quest : 2015-03-26 XYZ.COM LLC
+// quest : XYZ.COM LLC
+// https://www.iana.org/domains/root/db/quest.html
quest
-// racing : 2014-12-04 Premier Registry Limited
+// racing : Premier Registry Limited
+// https://www.iana.org/domains/root/db/racing.html
racing
-// radio : 2016-07-21 European Broadcasting Union (EBU)
+// radio : European Broadcasting Union (EBU)
+// https://www.iana.org/domains/root/db/radio.html
radio
-// read : 2014-12-18 Amazon Registry Services, Inc.
+// read : Amazon Registry Services, Inc.
+// https://www.iana.org/domains/root/db/read.html
read
-// realestate : 2015-09-11 dotRealEstate LLC
+// realestate : dotRealEstate LLC
+// https://www.iana.org/domains/root/db/realestate.html
realestate
-// realtor : 2014-05-29 Real Estate Domains LLC
+// realtor : Real Estate Domains LLC
+// https://www.iana.org/domains/root/db/realtor.html
realtor
-// realty : 2015-03-19 Dog Beach, LLC
+// realty : Internet Naming Company LLC
+// https://www.iana.org/domains/root/db/realty.html
realty
-// recipes : 2013-10-17 Binky Moon, LLC
+// recipes : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/recipes.html
recipes
-// red : 2013-11-07 Identity Digital Limited
+// red : Identity Digital Limited
+// https://www.iana.org/domains/root/db/red.html
red
-// redstone : 2014-10-31 Redstone Haute Couture Co., Ltd.
+// redstone : Redstone Haute Couture Co., Ltd.
+// https://www.iana.org/domains/root/db/redstone.html
redstone
-// redumbrella : 2015-03-26 Travelers TLD, LLC
+// redumbrella : Travelers TLD, LLC
+// https://www.iana.org/domains/root/db/redumbrella.html
redumbrella
-// rehab : 2014-03-06 Dog Beach, LLC
+// rehab : Dog Beach, LLC
+// https://www.iana.org/domains/root/db/rehab.html
rehab
-// reise : 2014-03-13 Binky Moon, LLC
+// reise : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/reise.html
reise
-// reisen : 2014-03-06 Binky Moon, LLC
+// reisen : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/reisen.html
reisen
-// reit : 2014-09-04 National Association of Real Estate Investment Trusts, Inc.
+// reit : National Association of Real Estate Investment Trusts, Inc.
+// https://www.iana.org/domains/root/db/reit.html
reit
-// reliance : 2015-04-02 Reliance Industries Limited
+// reliance : Reliance Industries Limited
+// https://www.iana.org/domains/root/db/reliance.html
reliance
-// ren : 2013-12-12 ZDNS International Limited
+// ren : ZDNS International Limited
+// https://www.iana.org/domains/root/db/ren.html
ren
-// rent : 2014-12-04 XYZ.COM LLC
+// rent : XYZ.COM LLC
+// https://www.iana.org/domains/root/db/rent.html
rent
-// rentals : 2013-12-05 Binky Moon, LLC
+// rentals : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/rentals.html
rentals
-// repair : 2013-11-07 Binky Moon, LLC
+// repair : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/repair.html
repair
-// report : 2013-12-05 Binky Moon, LLC
+// report : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/report.html
report
-// republican : 2014-03-20 Dog Beach, LLC
+// republican : Dog Beach, LLC
+// https://www.iana.org/domains/root/db/republican.html
republican
-// rest : 2013-12-19 Punto 2012 Sociedad Anonima Promotora de Inversion de Capital Variable
+// rest : Punto 2012 Sociedad Anonima Promotora de Inversion de Capital Variable
+// https://www.iana.org/domains/root/db/rest.html
rest
-// restaurant : 2014-07-03 Binky Moon, LLC
+// restaurant : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/restaurant.html
restaurant
-// review : 2014-11-20 dot Review Limited
+// review : dot Review Limited
+// https://www.iana.org/domains/root/db/review.html
review
-// reviews : 2013-09-13 Dog Beach, LLC
+// reviews : Dog Beach, LLC
+// https://www.iana.org/domains/root/db/reviews.html
reviews
-// rexroth : 2015-06-18 Robert Bosch GMBH
+// rexroth : Robert Bosch GMBH
+// https://www.iana.org/domains/root/db/rexroth.html
rexroth
-// rich : 2013-11-21 iRegistry GmbH
+// rich : iRegistry GmbH
+// https://www.iana.org/domains/root/db/rich.html
rich
-// richardli : 2015-05-14 Pacific Century Asset Management (HK) Limited
+// richardli : Pacific Century Asset Management (HK) Limited
+// https://www.iana.org/domains/root/db/richardli.html
richardli
-// ricoh : 2014-11-20 Ricoh Company, Ltd.
+// ricoh : Ricoh Company, Ltd.
+// https://www.iana.org/domains/root/db/ricoh.html
ricoh
-// ril : 2015-04-02 Reliance Industries Limited
+// ril : Reliance Industries Limited
+// https://www.iana.org/domains/root/db/ril.html
ril
-// rio : 2014-02-27 Empresa Municipal de Informática SA - IPLANRIO
+// rio : Empresa Municipal de Informática SA - IPLANRIO
+// https://www.iana.org/domains/root/db/rio.html
rio
-// rip : 2014-07-10 Dog Beach, LLC
+// rip : Dog Beach, LLC
+// https://www.iana.org/domains/root/db/rip.html
rip
-// rocher : 2014-12-18 Ferrero Trading Lux S.A.
-rocher
-
-// rocks : 2013-11-14 Dog Beach, LLC
+// rocks : Dog Beach, LLC
+// https://www.iana.org/domains/root/db/rocks.html
rocks
-// rodeo : 2013-12-19 Registry Services, LLC
+// rodeo : Registry Services, LLC
+// https://www.iana.org/domains/root/db/rodeo.html
rodeo
-// rogers : 2015-08-06 Rogers Communications Canada Inc.
+// rogers : Rogers Communications Canada Inc.
+// https://www.iana.org/domains/root/db/rogers.html
rogers
-// room : 2014-12-18 Amazon Registry Services, Inc.
+// room : Amazon Registry Services, Inc.
+// https://www.iana.org/domains/root/db/room.html
room
-// rsvp : 2014-05-08 Charleston Road Registry Inc.
+// rsvp : Charleston Road Registry Inc.
+// https://www.iana.org/domains/root/db/rsvp.html
rsvp
-// rugby : 2016-12-15 World Rugby Strategic Developments Limited
+// rugby : World Rugby Strategic Developments Limited
+// https://www.iana.org/domains/root/db/rugby.html
rugby
-// ruhr : 2013-10-02 dotSaarland GmbH
+// ruhr : dotSaarland GmbH
+// https://www.iana.org/domains/root/db/ruhr.html
ruhr
-// run : 2015-03-19 Binky Moon, LLC
+// run : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/run.html
run
-// rwe : 2015-04-02 RWE AG
+// rwe : RWE AG
+// https://www.iana.org/domains/root/db/rwe.html
rwe
-// ryukyu : 2014-01-09 BRregistry, Inc.
+// ryukyu : BRregistry, Inc.
+// https://www.iana.org/domains/root/db/ryukyu.html
ryukyu
-// saarland : 2013-12-12 dotSaarland GmbH
+// saarland : dotSaarland GmbH
+// https://www.iana.org/domains/root/db/saarland.html
saarland
-// safe : 2014-12-18 Amazon Registry Services, Inc.
+// safe : Amazon Registry Services, Inc.
+// https://www.iana.org/domains/root/db/safe.html
safe
-// safety : 2015-01-08 Safety Registry Services, LLC.
+// safety : Safety Registry Services, LLC.
+// https://www.iana.org/domains/root/db/safety.html
safety
-// sakura : 2014-12-18 SAKURA Internet Inc.
+// sakura : SAKURA Internet Inc.
+// https://www.iana.org/domains/root/db/sakura.html
sakura
-// sale : 2014-10-16 Dog Beach, LLC
+// sale : Dog Beach, LLC
+// https://www.iana.org/domains/root/db/sale.html
sale
-// salon : 2014-12-11 Binky Moon, LLC
+// salon : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/salon.html
salon
-// samsclub : 2015-07-31 Wal-Mart Stores, Inc.
+// samsclub : Wal-Mart Stores, Inc.
+// https://www.iana.org/domains/root/db/samsclub.html
samsclub
-// samsung : 2014-04-03 SAMSUNG SDS CO., LTD
+// samsung : SAMSUNG SDS CO., LTD
+// https://www.iana.org/domains/root/db/samsung.html
samsung
-// sandvik : 2014-11-13 Sandvik AB
+// sandvik : Sandvik AB
+// https://www.iana.org/domains/root/db/sandvik.html
sandvik
-// sandvikcoromant : 2014-11-07 Sandvik AB
+// sandvikcoromant : Sandvik AB
+// https://www.iana.org/domains/root/db/sandvikcoromant.html
sandvikcoromant
-// sanofi : 2014-10-09 Sanofi
+// sanofi : Sanofi
+// https://www.iana.org/domains/root/db/sanofi.html
sanofi
-// sap : 2014-03-27 SAP AG
+// sap : SAP AG
+// https://www.iana.org/domains/root/db/sap.html
sap
-// sarl : 2014-07-03 Binky Moon, LLC
+// sarl : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/sarl.html
sarl
-// sas : 2015-04-02 Research IP LLC
+// sas : Research IP LLC
+// https://www.iana.org/domains/root/db/sas.html
sas
-// save : 2015-06-25 Amazon Registry Services, Inc.
+// save : Amazon Registry Services, Inc.
+// https://www.iana.org/domains/root/db/save.html
save
-// saxo : 2014-10-31 Saxo Bank A/S
+// saxo : Saxo Bank A/S
+// https://www.iana.org/domains/root/db/saxo.html
saxo
-// sbi : 2015-03-12 STATE BANK OF INDIA
+// sbi : STATE BANK OF INDIA
+// https://www.iana.org/domains/root/db/sbi.html
sbi
-// sbs : 2014-11-07 ShortDot SA
+// sbs : ShortDot SA
+// https://www.iana.org/domains/root/db/sbs.html
sbs
-// sca : 2014-03-13 SVENSKA CELLULOSA AKTIEBOLAGET SCA (publ)
+// sca : SVENSKA CELLULOSA AKTIEBOLAGET SCA (publ)
+// https://www.iana.org/domains/root/db/sca.html
sca
-// scb : 2014-02-20 The Siam Commercial Bank Public Company Limited ("SCB")
+// scb : The Siam Commercial Bank Public Company Limited ("SCB")
+// https://www.iana.org/domains/root/db/scb.html
scb
-// schaeffler : 2015-08-06 Schaeffler Technologies AG & Co. KG
+// schaeffler : Schaeffler Technologies AG & Co. KG
+// https://www.iana.org/domains/root/db/schaeffler.html
schaeffler
-// schmidt : 2014-04-03 SCHMIDT GROUPE S.A.S.
+// schmidt : SCHMIDT GROUPE S.A.S.
+// https://www.iana.org/domains/root/db/schmidt.html
schmidt
-// scholarships : 2014-04-24 Scholarships.com, LLC
+// scholarships : Scholarships.com, LLC
+// https://www.iana.org/domains/root/db/scholarships.html
scholarships
-// school : 2014-12-18 Binky Moon, LLC
+// school : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/school.html
school
-// schule : 2014-03-06 Binky Moon, LLC
+// schule : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/schule.html
schule
-// schwarz : 2014-09-18 Schwarz Domains und Services GmbH & Co. KG
+// schwarz : Schwarz Domains und Services GmbH & Co. KG
+// https://www.iana.org/domains/root/db/schwarz.html
schwarz
-// science : 2014-09-11 dot Science Limited
+// science : dot Science Limited
+// https://www.iana.org/domains/root/db/science.html
science
-// scot : 2014-01-23 Dot Scot Registry Limited
+// scot : Dot Scot Registry Limited
+// https://www.iana.org/domains/root/db/scot.html
scot
-// search : 2016-06-09 Charleston Road Registry Inc.
+// search : Charleston Road Registry Inc.
+// https://www.iana.org/domains/root/db/search.html
search
-// seat : 2014-05-22 SEAT, S.A. (Sociedad Unipersonal)
+// seat : SEAT, S.A. (Sociedad Unipersonal)
+// https://www.iana.org/domains/root/db/seat.html
seat
-// secure : 2015-08-27 Amazon Registry Services, Inc.
+// secure : Amazon Registry Services, Inc.
+// https://www.iana.org/domains/root/db/secure.html
secure
-// security : 2015-05-14 XYZ.COM LLC
+// security : XYZ.COM LLC
+// https://www.iana.org/domains/root/db/security.html
security
-// seek : 2014-12-04 Seek Limited
+// seek : Seek Limited
+// https://www.iana.org/domains/root/db/seek.html
seek
-// select : 2015-10-08 Registry Services, LLC
+// select : Registry Services, LLC
+// https://www.iana.org/domains/root/db/select.html
select
-// sener : 2014-10-24 Sener Ingeniería y Sistemas, S.A.
+// sener : Sener Ingeniería y Sistemas, S.A.
+// https://www.iana.org/domains/root/db/sener.html
sener
-// services : 2014-02-27 Binky Moon, LLC
+// services : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/services.html
services
-// seven : 2015-08-06 Seven West Media Ltd
+// seven : Seven West Media Ltd
+// https://www.iana.org/domains/root/db/seven.html
seven
-// sew : 2014-07-17 SEW-EURODRIVE GmbH & Co KG
+// sew : SEW-EURODRIVE GmbH & Co KG
+// https://www.iana.org/domains/root/db/sew.html
sew
-// sex : 2014-11-13 ICM Registry SX LLC
+// sex : ICM Registry SX LLC
+// https://www.iana.org/domains/root/db/sex.html
sex
-// sexy : 2013-09-11 Internet Naming Company LLC
+// sexy : Internet Naming Company LLC
+// https://www.iana.org/domains/root/db/sexy.html
sexy
-// sfr : 2015-08-13 Societe Francaise du Radiotelephone - SFR
+// sfr : Societe Francaise du Radiotelephone - SFR
+// https://www.iana.org/domains/root/db/sfr.html
sfr
-// shangrila : 2015-09-03 Shangri‐La International Hotel Management Limited
+// shangrila : Shangri‐La International Hotel Management Limited
+// https://www.iana.org/domains/root/db/shangrila.html
shangrila
-// sharp : 2014-05-01 Sharp Corporation
+// sharp : Sharp Corporation
+// https://www.iana.org/domains/root/db/sharp.html
sharp
-// shaw : 2015-04-23 Shaw Cablesystems G.P.
+// shaw : Shaw Cablesystems G.P.
+// https://www.iana.org/domains/root/db/shaw.html
shaw
-// shell : 2015-07-30 Shell Information Technology International Inc
+// shell : Shell Information Technology International Inc
+// https://www.iana.org/domains/root/db/shell.html
shell
-// shia : 2014-09-04 Asia Green IT System Bilgisayar San. ve Tic. Ltd. Sti.
+// shia : Asia Green IT System Bilgisayar San. ve Tic. Ltd. Sti.
+// https://www.iana.org/domains/root/db/shia.html
shia
-// shiksha : 2013-11-14 Identity Digital Limited
+// shiksha : Identity Digital Limited
+// https://www.iana.org/domains/root/db/shiksha.html
shiksha
-// shoes : 2013-10-02 Binky Moon, LLC
+// shoes : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/shoes.html
shoes
-// shop : 2016-04-08 GMO Registry, Inc.
+// shop : GMO Registry, Inc.
+// https://www.iana.org/domains/root/db/shop.html
shop
-// shopping : 2016-03-31 Binky Moon, LLC
+// shopping : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/shopping.html
shopping
-// shouji : 2015-01-08 Beijing Qihu Keji Co., Ltd.
+// shouji : Beijing Qihu Keji Co., Ltd.
+// https://www.iana.org/domains/root/db/shouji.html
shouji
-// show : 2015-03-05 Binky Moon, LLC
+// show : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/show.html
show
-// showtime : 2015-08-06 CBS Domains Inc.
-showtime
-
-// silk : 2015-06-25 Amazon Registry Services, Inc.
+// silk : Amazon Registry Services, Inc.
+// https://www.iana.org/domains/root/db/silk.html
silk
-// sina : 2015-03-12 Sina Corporation
+// sina : Sina Corporation
+// https://www.iana.org/domains/root/db/sina.html
sina
-// singles : 2013-08-27 Binky Moon, LLC
+// singles : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/singles.html
singles
-// site : 2015-01-15 Radix FZC
+// site : Radix FZC DMCC
+// https://www.iana.org/domains/root/db/site.html
site
-// ski : 2015-04-09 Identity Digital Limited
+// ski : Identity Digital Limited
+// https://www.iana.org/domains/root/db/ski.html
ski
-// skin : 2015-01-15 XYZ.COM LLC
+// skin : XYZ.COM LLC
+// https://www.iana.org/domains/root/db/skin.html
skin
-// sky : 2014-06-19 Sky International AG
+// sky : Sky International AG
+// https://www.iana.org/domains/root/db/sky.html
sky
-// skype : 2014-12-18 Microsoft Corporation
+// skype : Microsoft Corporation
+// https://www.iana.org/domains/root/db/skype.html
skype
-// sling : 2015-07-30 DISH Technologies L.L.C.
+// sling : DISH Technologies L.L.C.
+// https://www.iana.org/domains/root/db/sling.html
sling
-// smart : 2015-07-09 Smart Communications, Inc. (SMART)
+// smart : Smart Communications, Inc. (SMART)
+// https://www.iana.org/domains/root/db/smart.html
smart
-// smile : 2014-12-18 Amazon Registry Services, Inc.
+// smile : Amazon Registry Services, Inc.
+// https://www.iana.org/domains/root/db/smile.html
smile
-// sncf : 2015-02-19 Société Nationale SNCF
+// sncf : Société Nationale SNCF
+// https://www.iana.org/domains/root/db/sncf.html
sncf
-// soccer : 2015-03-26 Binky Moon, LLC
+// soccer : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/soccer.html
soccer
-// social : 2013-11-07 Dog Beach, LLC
+// social : Dog Beach, LLC
+// https://www.iana.org/domains/root/db/social.html
social
-// softbank : 2015-07-02 SoftBank Group Corp.
+// softbank : SoftBank Group Corp.
+// https://www.iana.org/domains/root/db/softbank.html
softbank
-// software : 2014-03-20 Dog Beach, LLC
+// software : Dog Beach, LLC
+// https://www.iana.org/domains/root/db/software.html
software
-// sohu : 2013-12-19 Sohu.com Limited
+// sohu : Sohu.com Limited
+// https://www.iana.org/domains/root/db/sohu.html
sohu
-// solar : 2013-11-07 Binky Moon, LLC
+// solar : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/solar.html
solar
-// solutions : 2013-11-07 Binky Moon, LLC
+// solutions : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/solutions.html
solutions
-// song : 2015-02-26 Amazon Registry Services, Inc.
+// song : Amazon Registry Services, Inc.
+// https://www.iana.org/domains/root/db/song.html
song
-// sony : 2015-01-08 Sony Corporation
+// sony : Sony Corporation
+// https://www.iana.org/domains/root/db/sony.html
sony
-// soy : 2014-01-23 Charleston Road Registry Inc.
+// soy : Charleston Road Registry Inc.
+// https://www.iana.org/domains/root/db/soy.html
soy
-// spa : 2019-09-19 Asia Spa and Wellness Promotion Council Limited
+// spa : Asia Spa and Wellness Promotion Council Limited
+// https://www.iana.org/domains/root/db/spa.html
spa
-// space : 2014-04-03 Radix FZC
+// space : Radix FZC DMCC
+// https://www.iana.org/domains/root/db/space.html
space
-// sport : 2017-11-16 Global Association of International Sports Federations (GAISF)
+// sport : SportAccord
+// https://www.iana.org/domains/root/db/sport.html
sport
-// spot : 2015-02-26 Amazon Registry Services, Inc.
+// spot : Amazon Registry Services, Inc.
+// https://www.iana.org/domains/root/db/spot.html
spot
-// srl : 2015-05-07 InterNetX, Corp
+// srl : InterNetX, Corp
+// https://www.iana.org/domains/root/db/srl.html
srl
-// stada : 2014-11-13 STADA Arzneimittel AG
+// stada : STADA Arzneimittel AG
+// https://www.iana.org/domains/root/db/stada.html
stada
-// staples : 2015-07-30 Staples, Inc.
+// staples : Staples, Inc.
+// https://www.iana.org/domains/root/db/staples.html
staples
-// star : 2015-01-08 Star India Private Limited
+// star : Star India Private Limited
+// https://www.iana.org/domains/root/db/star.html
star
-// statebank : 2015-03-12 STATE BANK OF INDIA
+// statebank : STATE BANK OF INDIA
+// https://www.iana.org/domains/root/db/statebank.html
statebank
-// statefarm : 2015-07-30 State Farm Mutual Automobile Insurance Company
+// statefarm : State Farm Mutual Automobile Insurance Company
+// https://www.iana.org/domains/root/db/statefarm.html
statefarm
-// stc : 2014-10-09 Saudi Telecom Company
+// stc : Saudi Telecom Company
+// https://www.iana.org/domains/root/db/stc.html
stc
-// stcgroup : 2014-10-09 Saudi Telecom Company
+// stcgroup : Saudi Telecom Company
+// https://www.iana.org/domains/root/db/stcgroup.html
stcgroup
-// stockholm : 2014-12-18 Stockholms kommun
+// stockholm : Stockholms kommun
+// https://www.iana.org/domains/root/db/stockholm.html
stockholm
-// storage : 2014-12-22 XYZ.COM LLC
+// storage : XYZ.COM LLC
+// https://www.iana.org/domains/root/db/storage.html
storage
-// store : 2015-04-09 Radix FZC
+// store : Radix FZC DMCC
+// https://www.iana.org/domains/root/db/store.html
store
-// stream : 2016-01-08 dot Stream Limited
+// stream : dot Stream Limited
+// https://www.iana.org/domains/root/db/stream.html
stream
-// studio : 2015-02-11 Dog Beach, LLC
+// studio : Dog Beach, LLC
+// https://www.iana.org/domains/root/db/studio.html
studio
-// study : 2014-12-11 Registry Services, LLC
+// study : Registry Services, LLC
+// https://www.iana.org/domains/root/db/study.html
study
-// style : 2014-12-04 Binky Moon, LLC
+// style : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/style.html
style
-// sucks : 2014-12-22 Vox Populi Registry Ltd.
+// sucks : Vox Populi Registry Ltd.
+// https://www.iana.org/domains/root/db/sucks.html
sucks
-// supplies : 2013-12-19 Binky Moon, LLC
+// supplies : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/supplies.html
supplies
-// supply : 2013-12-19 Binky Moon, LLC
+// supply : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/supply.html
supply
-// support : 2013-10-24 Binky Moon, LLC
+// support : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/support.html
support
-// surf : 2014-01-09 Registry Services, LLC
+// surf : Registry Services, LLC
+// https://www.iana.org/domains/root/db/surf.html
surf
-// surgery : 2014-03-20 Binky Moon, LLC
+// surgery : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/surgery.html
surgery
-// suzuki : 2014-02-20 SUZUKI MOTOR CORPORATION
+// suzuki : SUZUKI MOTOR CORPORATION
+// https://www.iana.org/domains/root/db/suzuki.html
suzuki
-// swatch : 2015-01-08 The Swatch Group Ltd
+// swatch : The Swatch Group Ltd
+// https://www.iana.org/domains/root/db/swatch.html
swatch
-// swiss : 2014-10-16 Swiss Confederation
+// swiss : Swiss Confederation
+// https://www.iana.org/domains/root/db/swiss.html
swiss
-// sydney : 2014-09-18 State of New South Wales, Department of Premier and Cabinet
+// sydney : State of New South Wales, Department of Premier and Cabinet
+// https://www.iana.org/domains/root/db/sydney.html
sydney
-// systems : 2013-11-07 Binky Moon, LLC
+// systems : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/systems.html
systems
-// tab : 2014-12-04 Tabcorp Holdings Limited
+// tab : Tabcorp Holdings Limited
+// https://www.iana.org/domains/root/db/tab.html
tab
-// taipei : 2014-07-10 Taipei City Government
+// taipei : Taipei City Government
+// https://www.iana.org/domains/root/db/taipei.html
taipei
-// talk : 2015-04-09 Amazon Registry Services, Inc.
+// talk : Amazon Registry Services, Inc.
+// https://www.iana.org/domains/root/db/talk.html
talk
-// taobao : 2015-01-15 Alibaba Group Holding Limited
+// taobao : Alibaba Group Holding Limited
+// https://www.iana.org/domains/root/db/taobao.html
taobao
-// target : 2015-07-31 Target Domain Holdings, LLC
+// target : Target Domain Holdings, LLC
+// https://www.iana.org/domains/root/db/target.html
target
-// tatamotors : 2015-03-12 Tata Motors Ltd
+// tatamotors : Tata Motors Ltd
+// https://www.iana.org/domains/root/db/tatamotors.html
tatamotors
-// tatar : 2014-04-24 Limited Liability Company "Coordination Center of Regional Domain of Tatarstan Republic"
+// tatar : Limited Liability Company "Coordination Center of Regional Domain of Tatarstan Republic"
+// https://www.iana.org/domains/root/db/tatar.html
tatar
-// tattoo : 2013-08-30 Top Level Design, LLC
+// tattoo : Registry Services, LLC
+// https://www.iana.org/domains/root/db/tattoo.html
tattoo
-// tax : 2014-03-20 Binky Moon, LLC
+// tax : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/tax.html
tax
-// taxi : 2015-03-19 Binky Moon, LLC
+// taxi : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/taxi.html
taxi
-// tci : 2014-09-12 Asia Green IT System Bilgisayar San. ve Tic. Ltd. Sti.
+// tci : Asia Green IT System Bilgisayar San. ve Tic. Ltd. Sti.
+// https://www.iana.org/domains/root/db/tci.html
tci
-// tdk : 2015-06-11 TDK Corporation
+// tdk : TDK Corporation
+// https://www.iana.org/domains/root/db/tdk.html
tdk
-// team : 2015-03-05 Binky Moon, LLC
+// team : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/team.html
team
-// tech : 2015-01-30 Radix FZC
+// tech : Radix FZC DMCC
+// https://www.iana.org/domains/root/db/tech.html
tech
-// technology : 2013-09-13 Binky Moon, LLC
+// technology : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/technology.html
technology
-// temasek : 2014-08-07 Temasek Holdings (Private) Limited
+// temasek : Temasek Holdings (Private) Limited
+// https://www.iana.org/domains/root/db/temasek.html
temasek
-// tennis : 2014-12-04 Binky Moon, LLC
+// tennis : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/tennis.html
tennis
-// teva : 2015-07-02 Teva Pharmaceutical Industries Limited
+// teva : Teva Pharmaceutical Industries Limited
+// https://www.iana.org/domains/root/db/teva.html
teva
-// thd : 2015-04-02 Home Depot Product Authority, LLC
+// thd : Home Depot Product Authority, LLC
+// https://www.iana.org/domains/root/db/thd.html
thd
-// theater : 2015-03-19 Binky Moon, LLC
+// theater : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/theater.html
theater
-// theatre : 2015-05-07 XYZ.COM LLC
+// theatre : XYZ.COM LLC
+// https://www.iana.org/domains/root/db/theatre.html
theatre
-// tiaa : 2015-07-23 Teachers Insurance and Annuity Association of America
+// tiaa : Teachers Insurance and Annuity Association of America
+// https://www.iana.org/domains/root/db/tiaa.html
tiaa
-// tickets : 2015-02-05 XYZ.COM LLC
+// tickets : XYZ.COM LLC
+// https://www.iana.org/domains/root/db/tickets.html
tickets
-// tienda : 2013-11-14 Binky Moon, LLC
+// tienda : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/tienda.html
tienda
-// tiffany : 2015-01-30 Tiffany and Company
-tiffany
-
-// tips : 2013-09-20 Binky Moon, LLC
+// tips : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/tips.html
tips
-// tires : 2014-11-07 Binky Moon, LLC
+// tires : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/tires.html
tires
-// tirol : 2014-04-24 punkt Tirol GmbH
+// tirol : punkt Tirol GmbH
+// https://www.iana.org/domains/root/db/tirol.html
tirol
-// tjmaxx : 2015-07-16 The TJX Companies, Inc.
+// tjmaxx : The TJX Companies, Inc.
+// https://www.iana.org/domains/root/db/tjmaxx.html
tjmaxx
-// tjx : 2015-07-16 The TJX Companies, Inc.
+// tjx : The TJX Companies, Inc.
+// https://www.iana.org/domains/root/db/tjx.html
tjx
-// tkmaxx : 2015-07-16 The TJX Companies, Inc.
+// tkmaxx : The TJX Companies, Inc.
+// https://www.iana.org/domains/root/db/tkmaxx.html
tkmaxx
-// tmall : 2015-01-15 Alibaba Group Holding Limited
+// tmall : Alibaba Group Holding Limited
+// https://www.iana.org/domains/root/db/tmall.html
tmall
-// today : 2013-09-20 Binky Moon, LLC
+// today : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/today.html
today
-// tokyo : 2013-11-13 GMO Registry, Inc.
+// tokyo : GMO Registry, Inc.
+// https://www.iana.org/domains/root/db/tokyo.html
tokyo
-// tools : 2013-11-21 Binky Moon, LLC
+// tools : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/tools.html
tools
-// top : 2014-03-20 .TOP Registry
+// top : .TOP Registry
+// https://www.iana.org/domains/root/db/top.html
top
-// toray : 2014-12-18 Toray Industries, Inc.
+// toray : Toray Industries, Inc.
+// https://www.iana.org/domains/root/db/toray.html
toray
-// toshiba : 2014-04-10 TOSHIBA Corporation
+// toshiba : TOSHIBA Corporation
+// https://www.iana.org/domains/root/db/toshiba.html
toshiba
-// total : 2015-08-06 TotalEnergies SE
+// total : TotalEnergies SE
+// https://www.iana.org/domains/root/db/total.html
total
-// tours : 2015-01-22 Binky Moon, LLC
+// tours : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/tours.html
tours
-// town : 2014-03-06 Binky Moon, LLC
+// town : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/town.html
town
-// toyota : 2015-04-23 TOYOTA MOTOR CORPORATION
+// toyota : TOYOTA MOTOR CORPORATION
+// https://www.iana.org/domains/root/db/toyota.html
toyota
-// toys : 2014-03-06 Binky Moon, LLC
+// toys : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/toys.html
toys
-// trade : 2014-01-23 Elite Registry Limited
+// trade : Elite Registry Limited
+// https://www.iana.org/domains/root/db/trade.html
trade
-// trading : 2014-12-11 Dog Beach, LLC
+// trading : Dog Beach, LLC
+// https://www.iana.org/domains/root/db/trading.html
trading
-// training : 2013-11-07 Binky Moon, LLC
+// training : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/training.html
training
-// travel : 2015-10-09 Dog Beach, LLC
+// travel : Dog Beach, LLC
+// https://www.iana.org/domains/root/db/travel.html
travel
-// travelchannel : 2015-07-02 Lifestyle Domain Holdings, Inc.
-travelchannel
-
-// travelers : 2015-03-26 Travelers TLD, LLC
+// travelers : Travelers TLD, LLC
+// https://www.iana.org/domains/root/db/travelers.html
travelers
-// travelersinsurance : 2015-03-26 Travelers TLD, LLC
+// travelersinsurance : Travelers TLD, LLC
+// https://www.iana.org/domains/root/db/travelersinsurance.html
travelersinsurance
-// trust : 2014-10-16 Internet Naming Company LLC
+// trust : Internet Naming Company LLC
+// https://www.iana.org/domains/root/db/trust.html
trust
-// trv : 2015-03-26 Travelers TLD, LLC
+// trv : Travelers TLD, LLC
+// https://www.iana.org/domains/root/db/trv.html
trv
-// tube : 2015-06-11 Latin American Telecom LLC
+// tube : Latin American Telecom LLC
+// https://www.iana.org/domains/root/db/tube.html
tube
-// tui : 2014-07-03 TUI AG
+// tui : TUI AG
+// https://www.iana.org/domains/root/db/tui.html
tui
-// tunes : 2015-02-26 Amazon Registry Services, Inc.
+// tunes : Amazon Registry Services, Inc.
+// https://www.iana.org/domains/root/db/tunes.html
tunes
-// tushu : 2014-12-18 Amazon Registry Services, Inc.
+// tushu : Amazon Registry Services, Inc.
+// https://www.iana.org/domains/root/db/tushu.html
tushu
-// tvs : 2015-02-19 T V SUNDRAM IYENGAR & SONS LIMITED
+// tvs : T V SUNDRAM IYENGAR & SONS LIMITED
+// https://www.iana.org/domains/root/db/tvs.html
tvs
-// ubank : 2015-08-20 National Australia Bank Limited
+// ubank : National Australia Bank Limited
+// https://www.iana.org/domains/root/db/ubank.html
ubank
-// ubs : 2014-12-11 UBS AG
+// ubs : UBS AG
+// https://www.iana.org/domains/root/db/ubs.html
ubs
-// unicom : 2015-10-15 China United Network Communications Corporation Limited
+// unicom : China United Network Communications Corporation Limited
+// https://www.iana.org/domains/root/db/unicom.html
unicom
-// university : 2014-03-06 Binky Moon, LLC
+// university : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/university.html
university
-// uno : 2013-09-11 Radix FZC
+// uno : Radix FZC DMCC
+// https://www.iana.org/domains/root/db/uno.html
uno
-// uol : 2014-05-01 UBN INTERNET LTDA.
+// uol : UBN INTERNET LTDA.
+// https://www.iana.org/domains/root/db/uol.html
uol
-// ups : 2015-06-25 UPS Market Driver, Inc.
+// ups : UPS Market Driver, Inc.
+// https://www.iana.org/domains/root/db/ups.html
ups
-// vacations : 2013-12-05 Binky Moon, LLC
+// vacations : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/vacations.html
vacations
-// vana : 2014-12-11 Lifestyle Domain Holdings, Inc.
+// vana : Internet Naming Company LLC
+// https://www.iana.org/domains/root/db/vana.html
vana
-// vanguard : 2015-09-03 The Vanguard Group, Inc.
+// vanguard : The Vanguard Group, Inc.
+// https://www.iana.org/domains/root/db/vanguard.html
vanguard
-// vegas : 2014-01-16 Dot Vegas, Inc.
+// vegas : Dot Vegas, Inc.
+// https://www.iana.org/domains/root/db/vegas.html
vegas
-// ventures : 2013-08-27 Binky Moon, LLC
+// ventures : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/ventures.html
ventures
-// verisign : 2015-08-13 VeriSign, Inc.
+// verisign : VeriSign, Inc.
+// https://www.iana.org/domains/root/db/verisign.html
verisign
-// versicherung : 2014-03-20 tldbox GmbH
+// versicherung : tldbox GmbH
+// https://www.iana.org/domains/root/db/versicherung.html
versicherung
-// vet : 2014-03-06 Dog Beach, LLC
+// vet : Dog Beach, LLC
+// https://www.iana.org/domains/root/db/vet.html
vet
-// viajes : 2013-10-17 Binky Moon, LLC
+// viajes : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/viajes.html
viajes
-// video : 2014-10-16 Dog Beach, LLC
+// video : Dog Beach, LLC
+// https://www.iana.org/domains/root/db/video.html
video
-// vig : 2015-05-14 VIENNA INSURANCE GROUP AG Wiener Versicherung Gruppe
+// vig : VIENNA INSURANCE GROUP AG Wiener Versicherung Gruppe
+// https://www.iana.org/domains/root/db/vig.html
vig
-// viking : 2015-04-02 Viking River Cruises (Bermuda) Ltd.
+// viking : Viking River Cruises (Bermuda) Ltd.
+// https://www.iana.org/domains/root/db/viking.html
viking
-// villas : 2013-12-05 Binky Moon, LLC
+// villas : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/villas.html
villas
-// vin : 2015-06-18 Binky Moon, LLC
+// vin : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/vin.html
vin
-// vip : 2015-01-22 Registry Services, LLC
+// vip : Registry Services, LLC
+// https://www.iana.org/domains/root/db/vip.html
vip
-// virgin : 2014-09-25 Virgin Enterprises Limited
+// virgin : Virgin Enterprises Limited
+// https://www.iana.org/domains/root/db/virgin.html
virgin
-// visa : 2015-07-30 Visa Worldwide Pte. Limited
+// visa : Visa Worldwide Pte. Limited
+// https://www.iana.org/domains/root/db/visa.html
visa
-// vision : 2013-12-05 Binky Moon, LLC
+// vision : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/vision.html
vision
-// viva : 2014-11-07 Saudi Telecom Company
+// viva : Saudi Telecom Company
+// https://www.iana.org/domains/root/db/viva.html
viva
-// vivo : 2015-07-31 Telefonica Brasil S.A.
+// vivo : Telefonica Brasil S.A.
+// https://www.iana.org/domains/root/db/vivo.html
vivo
-// vlaanderen : 2014-02-06 DNS.be vzw
+// vlaanderen : DNS.be vzw
+// https://www.iana.org/domains/root/db/vlaanderen.html
vlaanderen
-// vodka : 2013-12-19 Registry Services, LLC
+// vodka : Registry Services, LLC
+// https://www.iana.org/domains/root/db/vodka.html
vodka
-// volkswagen : 2015-05-14 Volkswagen Group of America Inc.
-volkswagen
-
-// volvo : 2015-11-12 Volvo Holding Sverige Aktiebolag
+// volvo : Volvo Holding Sverige Aktiebolag
+// https://www.iana.org/domains/root/db/volvo.html
volvo
-// vote : 2013-11-21 Monolith Registry LLC
+// vote : Monolith Registry LLC
+// https://www.iana.org/domains/root/db/vote.html
vote
-// voting : 2013-11-13 Valuetainment Corp.
+// voting : Valuetainment Corp.
+// https://www.iana.org/domains/root/db/voting.html
voting
-// voto : 2013-11-21 Monolith Registry LLC
+// voto : Monolith Registry LLC
+// https://www.iana.org/domains/root/db/voto.html
voto
-// voyage : 2013-08-27 Binky Moon, LLC
+// voyage : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/voyage.html
voyage
-// vuelos : 2015-03-05 Travel Reservations SRL
-vuelos
-
-// wales : 2014-05-08 Nominet UK
+// wales : Nominet UK
+// https://www.iana.org/domains/root/db/wales.html
wales
-// walmart : 2015-07-31 Wal-Mart Stores, Inc.
+// walmart : Wal-Mart Stores, Inc.
+// https://www.iana.org/domains/root/db/walmart.html
walmart
-// walter : 2014-11-13 Sandvik AB
+// walter : Sandvik AB
+// https://www.iana.org/domains/root/db/walter.html
walter
-// wang : 2013-10-24 Zodiac Wang Limited
+// wang : Zodiac Wang Limited
+// https://www.iana.org/domains/root/db/wang.html
wang
-// wanggou : 2014-12-18 Amazon Registry Services, Inc.
+// wanggou : Amazon Registry Services, Inc.
+// https://www.iana.org/domains/root/db/wanggou.html
wanggou
-// watch : 2013-11-14 Binky Moon, LLC
+// watch : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/watch.html
watch
-// watches : 2014-12-22 Identity Digital Limited
+// watches : Identity Digital Limited
+// https://www.iana.org/domains/root/db/watches.html
watches
-// weather : 2015-01-08 International Business Machines Corporation
+// weather : International Business Machines Corporation
+// https://www.iana.org/domains/root/db/weather.html
weather
-// weatherchannel : 2015-03-12 International Business Machines Corporation
+// weatherchannel : International Business Machines Corporation
+// https://www.iana.org/domains/root/db/weatherchannel.html
weatherchannel
-// webcam : 2014-01-23 dot Webcam Limited
+// webcam : dot Webcam Limited
+// https://www.iana.org/domains/root/db/webcam.html
webcam
-// weber : 2015-06-04 Saint-Gobain Weber SA
+// weber : Saint-Gobain Weber SA
+// https://www.iana.org/domains/root/db/weber.html
weber
-// website : 2014-04-03 Radix FZC
+// website : Radix FZC DMCC
+// https://www.iana.org/domains/root/db/website.html
website
-// wedding : 2014-04-24 Registry Services, LLC
+// wed
+// https://www.iana.org/domains/root/db/wed.html
+wed
+
+// wedding : Registry Services, LLC
+// https://www.iana.org/domains/root/db/wedding.html
wedding
-// weibo : 2015-03-05 Sina Corporation
+// weibo : Sina Corporation
+// https://www.iana.org/domains/root/db/weibo.html
weibo
-// weir : 2015-01-29 Weir Group IP Limited
+// weir : Weir Group IP Limited
+// https://www.iana.org/domains/root/db/weir.html
weir
-// whoswho : 2014-02-20 Who's Who Registry
+// whoswho : Who's Who Registry
+// https://www.iana.org/domains/root/db/whoswho.html
whoswho
-// wien : 2013-10-28 punkt.wien GmbH
+// wien : punkt.wien GmbH
+// https://www.iana.org/domains/root/db/wien.html
wien
-// wiki : 2013-11-07 Top Level Design, LLC
+// wiki : Registry Services, LLC
+// https://www.iana.org/domains/root/db/wiki.html
wiki
-// williamhill : 2014-03-13 William Hill Organization Limited
+// williamhill : William Hill Organization Limited
+// https://www.iana.org/domains/root/db/williamhill.html
williamhill
-// win : 2014-11-20 First Registry Limited
+// win : First Registry Limited
+// https://www.iana.org/domains/root/db/win.html
win
-// windows : 2014-12-18 Microsoft Corporation
+// windows : Microsoft Corporation
+// https://www.iana.org/domains/root/db/windows.html
windows
-// wine : 2015-06-18 Binky Moon, LLC
+// wine : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/wine.html
wine
-// winners : 2015-07-16 The TJX Companies, Inc.
+// winners : The TJX Companies, Inc.
+// https://www.iana.org/domains/root/db/winners.html
winners
-// wme : 2014-02-13 William Morris Endeavor Entertainment, LLC
+// wme : William Morris Endeavor Entertainment, LLC
+// https://www.iana.org/domains/root/db/wme.html
wme
-// wolterskluwer : 2015-08-06 Wolters Kluwer N.V.
+// wolterskluwer : Wolters Kluwer N.V.
+// https://www.iana.org/domains/root/db/wolterskluwer.html
wolterskluwer
-// woodside : 2015-07-09 Woodside Petroleum Limited
+// woodside : Woodside Petroleum Limited
+// https://www.iana.org/domains/root/db/woodside.html
woodside
-// work : 2013-12-19 Registry Services, LLC
+// work : Registry Services, LLC
+// https://www.iana.org/domains/root/db/work.html
work
-// works : 2013-11-14 Binky Moon, LLC
+// works : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/works.html
works
-// world : 2014-06-12 Binky Moon, LLC
+// world : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/world.html
world
-// wow : 2015-10-08 Amazon Registry Services, Inc.
+// wow : Amazon Registry Services, Inc.
+// https://www.iana.org/domains/root/db/wow.html
wow
-// wtc : 2013-12-19 World Trade Centers Association, Inc.
+// wtc : World Trade Centers Association, Inc.
+// https://www.iana.org/domains/root/db/wtc.html
wtc
-// wtf : 2014-03-06 Binky Moon, LLC
+// wtf : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/wtf.html
wtf
-// xbox : 2014-12-18 Microsoft Corporation
+// xbox : Microsoft Corporation
+// https://www.iana.org/domains/root/db/xbox.html
xbox
-// xerox : 2014-10-24 Xerox DNHC LLC
+// xerox : Xerox DNHC LLC
+// https://www.iana.org/domains/root/db/xerox.html
xerox
-// xfinity : 2015-07-09 Comcast IP Holdings I, LLC
+// xfinity : Comcast IP Holdings I, LLC
+// https://www.iana.org/domains/root/db/xfinity.html
xfinity
-// xihuan : 2015-01-08 Beijing Qihu Keji Co., Ltd.
+// xihuan : Beijing Qihu Keji Co., Ltd.
+// https://www.iana.org/domains/root/db/xihuan.html
xihuan
-// xin : 2014-12-11 Elegant Leader Limited
+// xin : Elegant Leader Limited
+// https://www.iana.org/domains/root/db/xin.html
xin
-// xn--11b4c3d : 2015-01-15 VeriSign Sarl
+// xn--11b4c3d : VeriSign Sarl
+// https://www.iana.org/domains/root/db/xn--11b4c3d.html
कॉम
-// xn--1ck2e1b : 2015-02-26 Amazon Registry Services, Inc.
+// xn--1ck2e1b : Amazon Registry Services, Inc.
+// https://www.iana.org/domains/root/db/xn--1ck2e1b.html
セール
-// xn--1qqw23a : 2014-01-09 Guangzhou YU Wei Information Technology Co., Ltd.
+// xn--1qqw23a : Guangzhou YU Wei Information Technology Co., Ltd.
+// https://www.iana.org/domains/root/db/xn--1qqw23a.html
佛山
-// xn--30rr7y : 2014-06-12 Excellent First Limited
+// xn--30rr7y : Excellent First Limited
+// https://www.iana.org/domains/root/db/xn--30rr7y.html
慈善
-// xn--3bst00m : 2013-09-13 Eagle Horizon Limited
+// xn--3bst00m : Eagle Horizon Limited
+// https://www.iana.org/domains/root/db/xn--3bst00m.html
集团
-// xn--3ds443g : 2013-09-08 TLD REGISTRY LIMITED OY
+// xn--3ds443g : TLD REGISTRY LIMITED OY
+// https://www.iana.org/domains/root/db/xn--3ds443g.html
在线
-// xn--3pxu8k : 2015-01-15 VeriSign Sarl
+// xn--3pxu8k : VeriSign Sarl
+// https://www.iana.org/domains/root/db/xn--3pxu8k.html
点看
-// xn--42c2d9a : 2015-01-15 VeriSign Sarl
+// xn--42c2d9a : VeriSign Sarl
+// https://www.iana.org/domains/root/db/xn--42c2d9a.html
คอม
-// xn--45q11c : 2013-11-21 Zodiac Gemini Ltd
+// xn--45q11c : Zodiac Gemini Ltd
+// https://www.iana.org/domains/root/db/xn--45q11c.html
八卦
-// xn--4gbrim : 2013-10-04 Helium TLDs Ltd
+// xn--4gbrim : Helium TLDs Ltd
+// https://www.iana.org/domains/root/db/xn--4gbrim.html
موقع
-// xn--55qw42g : 2013-11-08 China Organizational Name Administration Center
+// xn--55qw42g : China Organizational Name Administration Center
+// https://www.iana.org/domains/root/db/xn--55qw42g.html
公益
-// xn--55qx5d : 2013-11-14 China Internet Network Information Center (CNNIC)
+// xn--55qx5d : China Internet Network Information Center (CNNIC)
+// https://www.iana.org/domains/root/db/xn--55qx5d.html
公司
-// xn--5su34j936bgsg : 2015-09-03 Shangri‐La International Hotel Management Limited
+// xn--5su34j936bgsg : Shangri‐La International Hotel Management Limited
+// https://www.iana.org/domains/root/db/xn--5su34j936bgsg.html
香格里拉
-// xn--5tzm5g : 2014-12-22 Global Website TLD Asia Limited
+// xn--5tzm5g : Global Website TLD Asia Limited
+// https://www.iana.org/domains/root/db/xn--5tzm5g.html
网站
-// xn--6frz82g : 2013-09-23 Identity Digital Limited
+// xn--6frz82g : Identity Digital Limited
+// https://www.iana.org/domains/root/db/xn--6frz82g.html
移动
-// xn--6qq986b3xl : 2013-09-13 Tycoon Treasure Limited
+// xn--6qq986b3xl : Tycoon Treasure Limited
+// https://www.iana.org/domains/root/db/xn--6qq986b3xl.html
我爱你
-// xn--80adxhks : 2013-12-19 Foundation for Assistance for Internet Technologies and Infrastructure Development (FAITID)
+// xn--80adxhks : Foundation for Assistance for Internet Technologies and Infrastructure Development (FAITID)
+// https://www.iana.org/domains/root/db/xn--80adxhks.html
москва
-// xn--80aqecdr1a : 2015-10-21 Pontificium Consilium de Comunicationibus Socialibus (PCCS) (Pontifical Council for Social Communication)
+// xn--80aqecdr1a : Pontificium Consilium de Comunicationibus Socialibus (PCCS) (Pontifical Council for Social Communication)
+// https://www.iana.org/domains/root/db/xn--80aqecdr1a.html
католик
-// xn--80asehdb : 2013-07-14 CORE Association
+// xn--80asehdb : CORE Association
+// https://www.iana.org/domains/root/db/xn--80asehdb.html
онлайн
-// xn--80aswg : 2013-07-14 CORE Association
+// xn--80aswg : CORE Association
+// https://www.iana.org/domains/root/db/xn--80aswg.html
сайт
-// xn--8y0a063a : 2015-03-26 China United Network Communications Corporation Limited
+// xn--8y0a063a : China United Network Communications Corporation Limited
+// https://www.iana.org/domains/root/db/xn--8y0a063a.html
联通
-// xn--9dbq2a : 2015-01-15 VeriSign Sarl
+// xn--9dbq2a : VeriSign Sarl
+// https://www.iana.org/domains/root/db/xn--9dbq2a.html
קום
-// xn--9et52u : 2014-06-12 RISE VICTORY LIMITED
+// xn--9et52u : RISE VICTORY LIMITED
+// https://www.iana.org/domains/root/db/xn--9et52u.html
时尚
-// xn--9krt00a : 2015-03-12 Sina Corporation
+// xn--9krt00a : Sina Corporation
+// https://www.iana.org/domains/root/db/xn--9krt00a.html
微博
-// xn--b4w605ferd : 2014-08-07 Temasek Holdings (Private) Limited
+// xn--b4w605ferd : Temasek Holdings (Private) Limited
+// https://www.iana.org/domains/root/db/xn--b4w605ferd.html
淡马锡
-// xn--bck1b9a5dre4c : 2015-02-26 Amazon Registry Services, Inc.
+// xn--bck1b9a5dre4c : Amazon Registry Services, Inc.
+// https://www.iana.org/domains/root/db/xn--bck1b9a5dre4c.html
ファッション
-// xn--c1avg : 2013-11-14 Public Interest Registry
+// xn--c1avg : Public Interest Registry
+// https://www.iana.org/domains/root/db/xn--c1avg.html
орг
-// xn--c2br7g : 2015-01-15 VeriSign Sarl
+// xn--c2br7g : VeriSign Sarl
+// https://www.iana.org/domains/root/db/xn--c2br7g.html
नेट
-// xn--cck2b3b : 2015-02-26 Amazon Registry Services, Inc.
+// xn--cck2b3b : Amazon Registry Services, Inc.
+// https://www.iana.org/domains/root/db/xn--cck2b3b.html
ストア
-// xn--cckwcxetd : 2019-12-19 Amazon Registry Services, Inc.
+// xn--cckwcxetd : Amazon Registry Services, Inc.
+// https://www.iana.org/domains/root/db/xn--cckwcxetd.html
アマゾン
-// xn--cg4bki : 2013-09-27 SAMSUNG SDS CO., LTD
+// xn--cg4bki : SAMSUNG SDS CO., LTD
+// https://www.iana.org/domains/root/db/xn--cg4bki.html
삼성
-// xn--czr694b : 2014-01-16 Internet DotTrademark Organisation Limited
+// xn--czr694b : Internet DotTrademark Organisation Limited
+// https://www.iana.org/domains/root/db/xn--czr694b.html
商标
-// xn--czrs0t : 2013-12-19 Binky Moon, LLC
+// xn--czrs0t : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/xn--czrs0t.html
商店
-// xn--czru2d : 2013-11-21 Zodiac Aquarius Limited
+// xn--czru2d : Zodiac Aquarius Limited
+// https://www.iana.org/domains/root/db/xn--czru2d.html
商城
-// xn--d1acj3b : 2013-11-20 The Foundation for Network Initiatives “The Smart Internet”
+// xn--d1acj3b : The Foundation for Network Initiatives “The Smart Internet”
+// https://www.iana.org/domains/root/db/xn--d1acj3b.html
дети
-// xn--eckvdtc9d : 2014-12-18 Amazon Registry Services, Inc.
+// xn--eckvdtc9d : Amazon Registry Services, Inc.
+// https://www.iana.org/domains/root/db/xn--eckvdtc9d.html
ポイント
-// xn--efvy88h : 2014-08-22 Guangzhou YU Wei Information Technology Co., Ltd.
+// xn--efvy88h : Guangzhou YU Wei Information Technology Co., Ltd.
+// https://www.iana.org/domains/root/db/xn--efvy88h.html
新闻
-// xn--fct429k : 2015-04-09 Amazon Registry Services, Inc.
+// xn--fct429k : Amazon Registry Services, Inc.
+// https://www.iana.org/domains/root/db/xn--fct429k.html
家電
-// xn--fhbei : 2015-01-15 VeriSign Sarl
+// xn--fhbei : VeriSign Sarl
+// https://www.iana.org/domains/root/db/xn--fhbei.html
كوم
-// xn--fiq228c5hs : 2013-09-08 TLD REGISTRY LIMITED OY
+// xn--fiq228c5hs : TLD REGISTRY LIMITED OY
+// https://www.iana.org/domains/root/db/xn--fiq228c5hs.html
中文网
-// xn--fiq64b : 2013-10-14 CITIC Group Corporation
+// xn--fiq64b : CITIC Group Corporation
+// https://www.iana.org/domains/root/db/xn--fiq64b.html
中信
-// xn--fjq720a : 2014-05-22 Binky Moon, LLC
+// xn--fjq720a : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/xn--fjq720a.html
娱乐
-// xn--flw351e : 2014-07-31 Charleston Road Registry Inc.
+// xn--flw351e : Charleston Road Registry Inc.
+// https://www.iana.org/domains/root/db/xn--flw351e.html
谷歌
-// xn--fzys8d69uvgm : 2015-05-14 PCCW Enterprises Limited
+// xn--fzys8d69uvgm : PCCW Enterprises Limited
+// https://www.iana.org/domains/root/db/xn--fzys8d69uvgm.html
電訊盈科
-// xn--g2xx48c : 2015-01-30 Nawang Heli(Xiamen) Network Service Co., LTD.
+// xn--g2xx48c : Nawang Heli(Xiamen) Network Service Co., LTD.
+// https://www.iana.org/domains/root/db/xn--g2xx48c.html
购物
-// xn--gckr3f0f : 2015-02-26 Amazon Registry Services, Inc.
+// xn--gckr3f0f : Amazon Registry Services, Inc.
+// https://www.iana.org/domains/root/db/xn--gckr3f0f.html
クラウド
-// xn--gk3at1e : 2015-10-08 Amazon Registry Services, Inc.
+// xn--gk3at1e : Amazon Registry Services, Inc.
+// https://www.iana.org/domains/root/db/xn--gk3at1e.html
通販
-// xn--hxt814e : 2014-05-15 Zodiac Taurus Limited
+// xn--hxt814e : Zodiac Taurus Limited
+// https://www.iana.org/domains/root/db/xn--hxt814e.html
网店
-// xn--i1b6b1a6a2e : 2013-11-14 Public Interest Registry
+// xn--i1b6b1a6a2e : Public Interest Registry
+// https://www.iana.org/domains/root/db/xn--i1b6b1a6a2e.html
संगठन
-// xn--imr513n : 2014-12-11 Internet DotTrademark Organisation Limited
+// xn--imr513n : Internet DotTrademark Organisation Limited
+// https://www.iana.org/domains/root/db/xn--imr513n.html
餐厅
-// xn--io0a7i : 2013-11-14 China Internet Network Information Center (CNNIC)
+// xn--io0a7i : China Internet Network Information Center (CNNIC)
+// https://www.iana.org/domains/root/db/xn--io0a7i.html
网络
-// xn--j1aef : 2015-01-15 VeriSign Sarl
+// xn--j1aef : VeriSign Sarl
+// https://www.iana.org/domains/root/db/xn--j1aef.html
ком
-// xn--jlq480n2rg : 2019-12-19 Amazon Registry Services, Inc.
+// xn--jlq480n2rg : Amazon Registry Services, Inc.
+// https://www.iana.org/domains/root/db/xn--jlq480n2rg.html
亚马逊
-// xn--jvr189m : 2015-02-26 Amazon Registry Services, Inc.
+// xn--jvr189m : Amazon Registry Services, Inc.
+// https://www.iana.org/domains/root/db/xn--jvr189m.html
食品
-// xn--kcrx77d1x4a : 2014-11-07 Koninklijke Philips N.V.
+// xn--kcrx77d1x4a : Koninklijke Philips N.V.
+// https://www.iana.org/domains/root/db/xn--kcrx77d1x4a.html
飞利浦
-// xn--kput3i : 2014-02-13 Beijing RITT-Net Technology Development Co., Ltd
+// xn--kput3i : Beijing RITT-Net Technology Development Co., Ltd
+// https://www.iana.org/domains/root/db/xn--kput3i.html
手机
-// xn--mgba3a3ejt : 2014-11-20 Aramco Services Company
+// xn--mgba3a3ejt : Aramco Services Company
+// https://www.iana.org/domains/root/db/xn--mgba3a3ejt.html
ارامكو
-// xn--mgba7c0bbn0a : 2015-05-14 Crescent Holding GmbH
+// xn--mgba7c0bbn0a : Competrol (Luxembourg) Sarl
+// https://www.iana.org/domains/root/db/xn--mgba7c0bbn0a.html
العليان
-// xn--mgbaakc7dvf : 2015-09-03 Emirates Telecommunications Corporation (trading as Etisalat)
-اتصالات
-
-// xn--mgbab2bd : 2013-10-31 CORE Association
+// xn--mgbab2bd : CORE Association
+// https://www.iana.org/domains/root/db/xn--mgbab2bd.html
بازار
-// xn--mgbca7dzdo : 2015-07-30 Abu Dhabi Systems and Information Centre
+// xn--mgbca7dzdo : Abu Dhabi Systems and Information Centre
+// https://www.iana.org/domains/root/db/xn--mgbca7dzdo.html
ابوظبي
-// xn--mgbi4ecexp : 2015-10-21 Pontificium Consilium de Comunicationibus Socialibus (PCCS) (Pontifical Council for Social Communication)
+// xn--mgbi4ecexp : Pontificium Consilium de Comunicationibus Socialibus (PCCS) (Pontifical Council for Social Communication)
+// https://www.iana.org/domains/root/db/xn--mgbi4ecexp.html
كاثوليك
-// xn--mgbt3dhd : 2014-09-04 Asia Green IT System Bilgisayar San. ve Tic. Ltd. Sti.
+// xn--mgbt3dhd : Asia Green IT System Bilgisayar San. ve Tic. Ltd. Sti.
+// https://www.iana.org/domains/root/db/xn--mgbt3dhd.html
همراه
-// xn--mk1bu44c : 2015-01-15 VeriSign Sarl
+// xn--mk1bu44c : VeriSign Sarl
+// https://www.iana.org/domains/root/db/xn--mk1bu44c.html
닷컴
-// xn--mxtq1m : 2014-03-06 Net-Chinese Co., Ltd.
+// xn--mxtq1m : Net-Chinese Co., Ltd.
+// https://www.iana.org/domains/root/db/xn--mxtq1m.html
政府
-// xn--ngbc5azd : 2013-07-13 International Domain Registry Pty. Ltd.
+// xn--ngbc5azd : International Domain Registry Pty. Ltd.
+// https://www.iana.org/domains/root/db/xn--ngbc5azd.html
شبكة
-// xn--ngbe9e0a : 2014-12-04 Kuwait Finance House
+// xn--ngbe9e0a : Kuwait Finance House
+// https://www.iana.org/domains/root/db/xn--ngbe9e0a.html
بيتك
-// xn--ngbrx : 2015-11-12 League of Arab States
+// xn--ngbrx : League of Arab States
+// https://www.iana.org/domains/root/db/xn--ngbrx.html
عرب
-// xn--nqv7f : 2013-11-14 Public Interest Registry
+// xn--nqv7f : Public Interest Registry
+// https://www.iana.org/domains/root/db/xn--nqv7f.html
机构
-// xn--nqv7fs00ema : 2013-11-14 Public Interest Registry
+// xn--nqv7fs00ema : Public Interest Registry
+// https://www.iana.org/domains/root/db/xn--nqv7fs00ema.html
组织机构
-// xn--nyqy26a : 2014-11-07 Stable Tone Limited
+// xn--nyqy26a : Stable Tone Limited
+// https://www.iana.org/domains/root/db/xn--nyqy26a.html
健康
-// xn--otu796d : 2017-08-06 Jiang Yu Liang Cai Technology Company Limited
+// xn--otu796d : Jiang Yu Liang Cai Technology Company Limited
+// https://www.iana.org/domains/root/db/xn--otu796d.html
招聘
-// xn--p1acf : 2013-12-12 Rusnames Limited
+// xn--p1acf : Rusnames Limited
+// https://www.iana.org/domains/root/db/xn--p1acf.html
рус
-// xn--pssy2u : 2015-01-15 VeriSign Sarl
+// xn--pssy2u : VeriSign Sarl
+// https://www.iana.org/domains/root/db/xn--pssy2u.html
大拿
-// xn--q9jyb4c : 2013-09-17 Charleston Road Registry Inc.
+// xn--q9jyb4c : Charleston Road Registry Inc.
+// https://www.iana.org/domains/root/db/xn--q9jyb4c.html
みんな
-// xn--qcka1pmc : 2014-07-31 Charleston Road Registry Inc.
+// xn--qcka1pmc : Charleston Road Registry Inc.
+// https://www.iana.org/domains/root/db/xn--qcka1pmc.html
グーグル
-// xn--rhqv96g : 2013-09-11 Stable Tone Limited
+// xn--rhqv96g : Stable Tone Limited
+// https://www.iana.org/domains/root/db/xn--rhqv96g.html
世界
-// xn--rovu88b : 2015-02-26 Amazon Registry Services, Inc.
+// xn--rovu88b : Amazon Registry Services, Inc.
+// https://www.iana.org/domains/root/db/xn--rovu88b.html
書籍
-// xn--ses554g : 2014-01-16 KNET Co., Ltd.
+// xn--ses554g : KNET Co., Ltd.
+// https://www.iana.org/domains/root/db/xn--ses554g.html
网址
-// xn--t60b56a : 2015-01-15 VeriSign Sarl
+// xn--t60b56a : VeriSign Sarl
+// https://www.iana.org/domains/root/db/xn--t60b56a.html
닷넷
-// xn--tckwe : 2015-01-15 VeriSign Sarl
+// xn--tckwe : VeriSign Sarl
+// https://www.iana.org/domains/root/db/xn--tckwe.html
コム
-// xn--tiq49xqyj : 2015-10-21 Pontificium Consilium de Comunicationibus Socialibus (PCCS) (Pontifical Council for Social Communication)
+// xn--tiq49xqyj : Pontificium Consilium de Comunicationibus Socialibus (PCCS) (Pontifical Council for Social Communication)
+// https://www.iana.org/domains/root/db/xn--tiq49xqyj.html
天主教
-// xn--unup4y : 2013-07-14 Binky Moon, LLC
+// xn--unup4y : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/xn--unup4y.html
游戏
-// xn--vermgensberater-ctb : 2014-06-23 Deutsche Vermögensberatung Aktiengesellschaft DVAG
+// xn--vermgensberater-ctb : Deutsche Vermögensberatung Aktiengesellschaft DVAG
+// https://www.iana.org/domains/root/db/xn--vermgensberater-ctb.html
vermögensberater
-// xn--vermgensberatung-pwb : 2014-06-23 Deutsche Vermögensberatung Aktiengesellschaft DVAG
+// xn--vermgensberatung-pwb : Deutsche Vermögensberatung Aktiengesellschaft DVAG
+// https://www.iana.org/domains/root/db/xn--vermgensberatung-pwb.html
vermögensberatung
-// xn--vhquv : 2013-08-27 Binky Moon, LLC
+// xn--vhquv : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/xn--vhquv.html
企业
-// xn--vuq861b : 2014-10-16 Beijing Tele-info Network Technology Co., Ltd.
+// xn--vuq861b : Beijing Tele-info Technology Co., Ltd.
+// https://www.iana.org/domains/root/db/xn--vuq861b.html
信息
-// xn--w4r85el8fhu5dnra : 2015-04-30 Kerry Trading Co. Limited
+// xn--w4r85el8fhu5dnra : Kerry Trading Co. Limited
+// https://www.iana.org/domains/root/db/xn--w4r85el8fhu5dnra.html
嘉里大酒店
-// xn--w4rs40l : 2015-07-30 Kerry Trading Co. Limited
+// xn--w4rs40l : Kerry Trading Co. Limited
+// https://www.iana.org/domains/root/db/xn--w4rs40l.html
嘉里
-// xn--xhq521b : 2013-11-14 Guangzhou YU Wei Information Technology Co., Ltd.
+// xn--xhq521b : Guangzhou YU Wei Information Technology Co., Ltd.
+// https://www.iana.org/domains/root/db/xn--xhq521b.html
广东
-// xn--zfr164b : 2013-11-08 China Organizational Name Administration Center
+// xn--zfr164b : China Organizational Name Administration Center
+// https://www.iana.org/domains/root/db/xn--zfr164b.html
政务
-// xyz : 2013-12-05 XYZ.COM LLC
+// xyz : XYZ.COM LLC
+// https://www.iana.org/domains/root/db/xyz.html
xyz
-// yachts : 2014-01-09 XYZ.COM LLC
+// yachts : XYZ.COM LLC
+// https://www.iana.org/domains/root/db/yachts.html
yachts
-// yahoo : 2015-04-02 Oath Inc.
+// yahoo : Oath Inc.
+// https://www.iana.org/domains/root/db/yahoo.html
yahoo
-// yamaxun : 2014-12-18 Amazon Registry Services, Inc.
+// yamaxun : Amazon Registry Services, Inc.
+// https://www.iana.org/domains/root/db/yamaxun.html
yamaxun
-// yandex : 2014-04-10 Yandex Europe B.V.
+// yandex : Yandex Europe B.V.
+// https://www.iana.org/domains/root/db/yandex.html
yandex
-// yodobashi : 2014-11-20 YODOBASHI CAMERA CO.,LTD.
+// yodobashi : YODOBASHI CAMERA CO.,LTD.
+// https://www.iana.org/domains/root/db/yodobashi.html
yodobashi
-// yoga : 2014-05-29 Registry Services, LLC
+// yoga : Registry Services, LLC
+// https://www.iana.org/domains/root/db/yoga.html
yoga
-// yokohama : 2013-12-12 GMO Registry, Inc.
+// yokohama : GMO Registry, Inc.
+// https://www.iana.org/domains/root/db/yokohama.html
yokohama
-// you : 2015-04-09 Amazon Registry Services, Inc.
+// you : Amazon Registry Services, Inc.
+// https://www.iana.org/domains/root/db/you.html
you
-// youtube : 2014-05-01 Charleston Road Registry Inc.
+// youtube : Charleston Road Registry Inc.
+// https://www.iana.org/domains/root/db/youtube.html
youtube
-// yun : 2015-01-08 Beijing Qihu Keji Co., Ltd.
+// yun : Beijing Qihu Keji Co., Ltd.
+// https://www.iana.org/domains/root/db/yun.html
yun
-// zappos : 2015-06-25 Amazon Registry Services, Inc.
+// zappos : Amazon Registry Services, Inc.
+// https://www.iana.org/domains/root/db/zappos.html
zappos
-// zara : 2014-11-07 Industria de Diseño Textil, S.A. (INDITEX, S.A.)
+// zara : Industria de Diseño Textil, S.A. (INDITEX, S.A.)
+// https://www.iana.org/domains/root/db/zara.html
zara
-// zero : 2014-12-18 Amazon Registry Services, Inc.
+// zero : Amazon Registry Services, Inc.
+// https://www.iana.org/domains/root/db/zero.html
zero
-// zip : 2014-05-08 Charleston Road Registry Inc.
+// zip : Charleston Road Registry Inc.
+// https://www.iana.org/domains/root/db/zip.html
zip
-// zone : 2013-11-14 Binky Moon, LLC
+// zone : Binky Moon, LLC
+// https://www.iana.org/domains/root/db/zone.html
zone
-// zuerich : 2014-11-07 Kanton Zürich (Canton of Zurich)
+// zuerich : Kanton Zürich (Canton of Zurich)
+// https://www.iana.org/domains/root/db/zuerich.html
zuerich
@@ -10737,11 +11313,78 @@ myamaze.net
// Submitted by AWS Security <psl-maintainers@amazon.com>
// Subsections of Amazon/subsidiaries will appear until "concludes" tag
+// Amazon API Gateway
+// Submitted by AWS Security <psl-maintainers@amazon.com>
+// Reference: 4d863337-ff98-4501-a6f2-361eba8445d6
+execute-api.cn-north-1.amazonaws.com.cn
+execute-api.cn-northwest-1.amazonaws.com.cn
+execute-api.af-south-1.amazonaws.com
+execute-api.ap-east-1.amazonaws.com
+execute-api.ap-northeast-1.amazonaws.com
+execute-api.ap-northeast-2.amazonaws.com
+execute-api.ap-northeast-3.amazonaws.com
+execute-api.ap-south-1.amazonaws.com
+execute-api.ap-south-2.amazonaws.com
+execute-api.ap-southeast-1.amazonaws.com
+execute-api.ap-southeast-2.amazonaws.com
+execute-api.ap-southeast-3.amazonaws.com
+execute-api.ap-southeast-4.amazonaws.com
+execute-api.ca-central-1.amazonaws.com
+execute-api.eu-central-1.amazonaws.com
+execute-api.eu-central-2.amazonaws.com
+execute-api.eu-north-1.amazonaws.com
+execute-api.eu-south-1.amazonaws.com
+execute-api.eu-south-2.amazonaws.com
+execute-api.eu-west-1.amazonaws.com
+execute-api.eu-west-2.amazonaws.com
+execute-api.eu-west-3.amazonaws.com
+execute-api.il-central-1.amazonaws.com
+execute-api.me-central-1.amazonaws.com
+execute-api.me-south-1.amazonaws.com
+execute-api.sa-east-1.amazonaws.com
+execute-api.us-east-1.amazonaws.com
+execute-api.us-east-2.amazonaws.com
+execute-api.us-gov-east-1.amazonaws.com
+execute-api.us-gov-west-1.amazonaws.com
+execute-api.us-west-1.amazonaws.com
+execute-api.us-west-2.amazonaws.com
+
// Amazon CloudFront
// Submitted by Donavan Miller <donavanm@amazon.com>
// Reference: 54144616-fd49-4435-8535-19c6a601bdb3
cloudfront.net
+// Amazon Cognito
+// Submitted by AWS Security <psl-maintainers@amazon.com>
+// Reference: 7bee1013-f456-47df-bfe8-03c78d946d61
+auth.af-south-1.amazoncognito.com
+auth.ap-northeast-1.amazoncognito.com
+auth.ap-northeast-2.amazoncognito.com
+auth.ap-northeast-3.amazoncognito.com
+auth.ap-south-1.amazoncognito.com
+auth.ap-southeast-1.amazoncognito.com
+auth.ap-southeast-2.amazoncognito.com
+auth.ap-southeast-3.amazoncognito.com
+auth.ca-central-1.amazoncognito.com
+auth.eu-central-1.amazoncognito.com
+auth.eu-north-1.amazoncognito.com
+auth.eu-south-1.amazoncognito.com
+auth.eu-west-1.amazoncognito.com
+auth.eu-west-2.amazoncognito.com
+auth.eu-west-3.amazoncognito.com
+auth.il-central-1.amazoncognito.com
+auth.me-south-1.amazoncognito.com
+auth.sa-east-1.amazoncognito.com
+auth.us-east-1.amazoncognito.com
+auth-fips.us-east-1.amazoncognito.com
+auth.us-east-2.amazoncognito.com
+auth-fips.us-east-2.amazoncognito.com
+auth-fips.us-gov-west-1.amazoncognito.com
+auth.us-west-1.amazoncognito.com
+auth-fips.us-west-1.amazoncognito.com
+auth.us-west-2.amazoncognito.com
+auth-fips.us-west-2.amazoncognito.com
+
// Amazon EC2
// Submitted by Luke Wells <psl-maintainers@amazon.com>
// Reference: 4c38fa71-58ac-4768-99e5-689c1767e537
@@ -10750,47 +11393,307 @@ cloudfront.net
*.compute.amazonaws.com.cn
us-east-1.amazonaws.com
+// Amazon EMR
+// Submitted by AWS Security <psl-maintainers@amazon.com>
+// Reference: 597f3f8e-9283-4e48-8e32-7ee25a1ff6ab
+emrappui-prod.cn-north-1.amazonaws.com.cn
+emrnotebooks-prod.cn-north-1.amazonaws.com.cn
+emrstudio-prod.cn-north-1.amazonaws.com.cn
+emrappui-prod.cn-northwest-1.amazonaws.com.cn
+emrnotebooks-prod.cn-northwest-1.amazonaws.com.cn
+emrstudio-prod.cn-northwest-1.amazonaws.com.cn
+emrappui-prod.af-south-1.amazonaws.com
+emrnotebooks-prod.af-south-1.amazonaws.com
+emrstudio-prod.af-south-1.amazonaws.com
+emrappui-prod.ap-east-1.amazonaws.com
+emrnotebooks-prod.ap-east-1.amazonaws.com
+emrstudio-prod.ap-east-1.amazonaws.com
+emrappui-prod.ap-northeast-1.amazonaws.com
+emrnotebooks-prod.ap-northeast-1.amazonaws.com
+emrstudio-prod.ap-northeast-1.amazonaws.com
+emrappui-prod.ap-northeast-2.amazonaws.com
+emrnotebooks-prod.ap-northeast-2.amazonaws.com
+emrstudio-prod.ap-northeast-2.amazonaws.com
+emrappui-prod.ap-northeast-3.amazonaws.com
+emrnotebooks-prod.ap-northeast-3.amazonaws.com
+emrstudio-prod.ap-northeast-3.amazonaws.com
+emrappui-prod.ap-south-1.amazonaws.com
+emrnotebooks-prod.ap-south-1.amazonaws.com
+emrstudio-prod.ap-south-1.amazonaws.com
+emrappui-prod.ap-southeast-1.amazonaws.com
+emrnotebooks-prod.ap-southeast-1.amazonaws.com
+emrstudio-prod.ap-southeast-1.amazonaws.com
+emrappui-prod.ap-southeast-2.amazonaws.com
+emrnotebooks-prod.ap-southeast-2.amazonaws.com
+emrstudio-prod.ap-southeast-2.amazonaws.com
+emrappui-prod.ap-southeast-3.amazonaws.com
+emrnotebooks-prod.ap-southeast-3.amazonaws.com
+emrstudio-prod.ap-southeast-3.amazonaws.com
+emrappui-prod.ca-central-1.amazonaws.com
+emrnotebooks-prod.ca-central-1.amazonaws.com
+emrstudio-prod.ca-central-1.amazonaws.com
+emrappui-prod.eu-central-1.amazonaws.com
+emrnotebooks-prod.eu-central-1.amazonaws.com
+emrstudio-prod.eu-central-1.amazonaws.com
+emrappui-prod.eu-north-1.amazonaws.com
+emrnotebooks-prod.eu-north-1.amazonaws.com
+emrstudio-prod.eu-north-1.amazonaws.com
+emrappui-prod.eu-south-1.amazonaws.com
+emrnotebooks-prod.eu-south-1.amazonaws.com
+emrstudio-prod.eu-south-1.amazonaws.com
+emrappui-prod.eu-west-1.amazonaws.com
+emrnotebooks-prod.eu-west-1.amazonaws.com
+emrstudio-prod.eu-west-1.amazonaws.com
+emrappui-prod.eu-west-2.amazonaws.com
+emrnotebooks-prod.eu-west-2.amazonaws.com
+emrstudio-prod.eu-west-2.amazonaws.com
+emrappui-prod.eu-west-3.amazonaws.com
+emrnotebooks-prod.eu-west-3.amazonaws.com
+emrstudio-prod.eu-west-3.amazonaws.com
+emrappui-prod.me-central-1.amazonaws.com
+emrnotebooks-prod.me-central-1.amazonaws.com
+emrstudio-prod.me-central-1.amazonaws.com
+emrappui-prod.me-south-1.amazonaws.com
+emrnotebooks-prod.me-south-1.amazonaws.com
+emrstudio-prod.me-south-1.amazonaws.com
+emrappui-prod.sa-east-1.amazonaws.com
+emrnotebooks-prod.sa-east-1.amazonaws.com
+emrstudio-prod.sa-east-1.amazonaws.com
+emrappui-prod.us-east-1.amazonaws.com
+emrnotebooks-prod.us-east-1.amazonaws.com
+emrstudio-prod.us-east-1.amazonaws.com
+emrappui-prod.us-east-2.amazonaws.com
+emrnotebooks-prod.us-east-2.amazonaws.com
+emrstudio-prod.us-east-2.amazonaws.com
+emrappui-prod.us-gov-east-1.amazonaws.com
+emrnotebooks-prod.us-gov-east-1.amazonaws.com
+emrstudio-prod.us-gov-east-1.amazonaws.com
+emrappui-prod.us-gov-west-1.amazonaws.com
+emrnotebooks-prod.us-gov-west-1.amazonaws.com
+emrstudio-prod.us-gov-west-1.amazonaws.com
+emrappui-prod.us-west-1.amazonaws.com
+emrnotebooks-prod.us-west-1.amazonaws.com
+emrstudio-prod.us-west-1.amazonaws.com
+emrappui-prod.us-west-2.amazonaws.com
+emrnotebooks-prod.us-west-2.amazonaws.com
+emrstudio-prod.us-west-2.amazonaws.com
+
+// Amazon Managed Workflows for Apache Airflow
+// Submitted by AWS Security <psl-maintainers@amazon.com>
+// Reference: 4ab55e6f-90c0-4a8d-b6a0-52ca5dbb1c2e
+*.cn-north-1.airflow.amazonaws.com.cn
+*.cn-northwest-1.airflow.amazonaws.com.cn
+*.ap-northeast-1.airflow.amazonaws.com
+*.ap-northeast-2.airflow.amazonaws.com
+*.ap-south-1.airflow.amazonaws.com
+*.ap-southeast-1.airflow.amazonaws.com
+*.ap-southeast-2.airflow.amazonaws.com
+*.ca-central-1.airflow.amazonaws.com
+*.eu-central-1.airflow.amazonaws.com
+*.eu-north-1.airflow.amazonaws.com
+*.eu-west-1.airflow.amazonaws.com
+*.eu-west-2.airflow.amazonaws.com
+*.eu-west-3.airflow.amazonaws.com
+*.sa-east-1.airflow.amazonaws.com
+*.us-east-1.airflow.amazonaws.com
+*.us-east-2.airflow.amazonaws.com
+*.us-west-2.airflow.amazonaws.com
+
// Amazon S3
-// Submitted by Luke Wells <psl-maintainers@amazon.com>
-// Reference: d068bd97-f0a9-4838-a6d8-954b622ef4ae
+// Submitted by AWS Security <psl-maintainers@amazon.com>
+// Reference: 0e801048-08f2-4064-9cb8-e7373e0b57f4
+s3.dualstack.cn-north-1.amazonaws.com.cn
+s3-accesspoint.dualstack.cn-north-1.amazonaws.com.cn
+s3-website.dualstack.cn-north-1.amazonaws.com.cn
s3.cn-north-1.amazonaws.com.cn
+s3-accesspoint.cn-north-1.amazonaws.com.cn
+s3-deprecated.cn-north-1.amazonaws.com.cn
+s3-object-lambda.cn-north-1.amazonaws.com.cn
+s3-website.cn-north-1.amazonaws.com.cn
+s3.dualstack.cn-northwest-1.amazonaws.com.cn
+s3-accesspoint.dualstack.cn-northwest-1.amazonaws.com.cn
+s3.cn-northwest-1.amazonaws.com.cn
+s3-accesspoint.cn-northwest-1.amazonaws.com.cn
+s3-object-lambda.cn-northwest-1.amazonaws.com.cn
+s3-website.cn-northwest-1.amazonaws.com.cn
+s3.dualstack.af-south-1.amazonaws.com
+s3-accesspoint.dualstack.af-south-1.amazonaws.com
+s3-website.dualstack.af-south-1.amazonaws.com
+s3.af-south-1.amazonaws.com
+s3-accesspoint.af-south-1.amazonaws.com
+s3-object-lambda.af-south-1.amazonaws.com
+s3-website.af-south-1.amazonaws.com
+s3.dualstack.ap-east-1.amazonaws.com
+s3-accesspoint.dualstack.ap-east-1.amazonaws.com
+s3.ap-east-1.amazonaws.com
+s3-accesspoint.ap-east-1.amazonaws.com
+s3-object-lambda.ap-east-1.amazonaws.com
+s3-website.ap-east-1.amazonaws.com
s3.dualstack.ap-northeast-1.amazonaws.com
+s3-accesspoint.dualstack.ap-northeast-1.amazonaws.com
+s3-website.dualstack.ap-northeast-1.amazonaws.com
+s3.ap-northeast-1.amazonaws.com
+s3-accesspoint.ap-northeast-1.amazonaws.com
+s3-object-lambda.ap-northeast-1.amazonaws.com
+s3-website.ap-northeast-1.amazonaws.com
s3.dualstack.ap-northeast-2.amazonaws.com
+s3-accesspoint.dualstack.ap-northeast-2.amazonaws.com
+s3-website.dualstack.ap-northeast-2.amazonaws.com
s3.ap-northeast-2.amazonaws.com
+s3-accesspoint.ap-northeast-2.amazonaws.com
+s3-object-lambda.ap-northeast-2.amazonaws.com
s3-website.ap-northeast-2.amazonaws.com
+s3.dualstack.ap-northeast-3.amazonaws.com
+s3-accesspoint.dualstack.ap-northeast-3.amazonaws.com
+s3-website.dualstack.ap-northeast-3.amazonaws.com
+s3.ap-northeast-3.amazonaws.com
+s3-accesspoint.ap-northeast-3.amazonaws.com
+s3-object-lambda.ap-northeast-3.amazonaws.com
+s3-website.ap-northeast-3.amazonaws.com
s3.dualstack.ap-south-1.amazonaws.com
+s3-accesspoint.dualstack.ap-south-1.amazonaws.com
+s3-website.dualstack.ap-south-1.amazonaws.com
s3.ap-south-1.amazonaws.com
+s3-accesspoint.ap-south-1.amazonaws.com
+s3-object-lambda.ap-south-1.amazonaws.com
s3-website.ap-south-1.amazonaws.com
+s3.dualstack.ap-south-2.amazonaws.com
+s3-accesspoint.dualstack.ap-south-2.amazonaws.com
+s3.ap-south-2.amazonaws.com
+s3-accesspoint.ap-south-2.amazonaws.com
+s3-object-lambda.ap-south-2.amazonaws.com
+s3-website.ap-south-2.amazonaws.com
s3.dualstack.ap-southeast-1.amazonaws.com
+s3-accesspoint.dualstack.ap-southeast-1.amazonaws.com
+s3-website.dualstack.ap-southeast-1.amazonaws.com
+s3.ap-southeast-1.amazonaws.com
+s3-accesspoint.ap-southeast-1.amazonaws.com
+s3-object-lambda.ap-southeast-1.amazonaws.com
+s3-website.ap-southeast-1.amazonaws.com
s3.dualstack.ap-southeast-2.amazonaws.com
+s3-accesspoint.dualstack.ap-southeast-2.amazonaws.com
+s3-website.dualstack.ap-southeast-2.amazonaws.com
+s3.ap-southeast-2.amazonaws.com
+s3-accesspoint.ap-southeast-2.amazonaws.com
+s3-object-lambda.ap-southeast-2.amazonaws.com
+s3-website.ap-southeast-2.amazonaws.com
+s3.dualstack.ap-southeast-3.amazonaws.com
+s3-accesspoint.dualstack.ap-southeast-3.amazonaws.com
+s3.ap-southeast-3.amazonaws.com
+s3-accesspoint.ap-southeast-3.amazonaws.com
+s3-object-lambda.ap-southeast-3.amazonaws.com
+s3-website.ap-southeast-3.amazonaws.com
+s3.dualstack.ap-southeast-4.amazonaws.com
+s3-accesspoint.dualstack.ap-southeast-4.amazonaws.com
+s3.ap-southeast-4.amazonaws.com
+s3-accesspoint.ap-southeast-4.amazonaws.com
+s3-object-lambda.ap-southeast-4.amazonaws.com
+s3-website.ap-southeast-4.amazonaws.com
s3.dualstack.ca-central-1.amazonaws.com
+s3-accesspoint.dualstack.ca-central-1.amazonaws.com
+s3-accesspoint-fips.dualstack.ca-central-1.amazonaws.com
+s3-fips.dualstack.ca-central-1.amazonaws.com
+s3-website.dualstack.ca-central-1.amazonaws.com
s3.ca-central-1.amazonaws.com
+s3-accesspoint.ca-central-1.amazonaws.com
+s3-accesspoint-fips.ca-central-1.amazonaws.com
+s3-fips.ca-central-1.amazonaws.com
+s3-object-lambda.ca-central-1.amazonaws.com
s3-website.ca-central-1.amazonaws.com
s3.dualstack.eu-central-1.amazonaws.com
+s3-accesspoint.dualstack.eu-central-1.amazonaws.com
+s3-website.dualstack.eu-central-1.amazonaws.com
s3.eu-central-1.amazonaws.com
+s3-accesspoint.eu-central-1.amazonaws.com
+s3-object-lambda.eu-central-1.amazonaws.com
s3-website.eu-central-1.amazonaws.com
+s3.dualstack.eu-central-2.amazonaws.com
+s3-accesspoint.dualstack.eu-central-2.amazonaws.com
+s3.eu-central-2.amazonaws.com
+s3-accesspoint.eu-central-2.amazonaws.com
+s3-object-lambda.eu-central-2.amazonaws.com
+s3-website.eu-central-2.amazonaws.com
+s3.dualstack.eu-north-1.amazonaws.com
+s3-accesspoint.dualstack.eu-north-1.amazonaws.com
+s3.eu-north-1.amazonaws.com
+s3-accesspoint.eu-north-1.amazonaws.com
+s3-object-lambda.eu-north-1.amazonaws.com
+s3-website.eu-north-1.amazonaws.com
+s3.dualstack.eu-south-1.amazonaws.com
+s3-accesspoint.dualstack.eu-south-1.amazonaws.com
+s3-website.dualstack.eu-south-1.amazonaws.com
+s3.eu-south-1.amazonaws.com
+s3-accesspoint.eu-south-1.amazonaws.com
+s3-object-lambda.eu-south-1.amazonaws.com
+s3-website.eu-south-1.amazonaws.com
+s3.dualstack.eu-south-2.amazonaws.com
+s3-accesspoint.dualstack.eu-south-2.amazonaws.com
+s3.eu-south-2.amazonaws.com
+s3-accesspoint.eu-south-2.amazonaws.com
+s3-object-lambda.eu-south-2.amazonaws.com
+s3-website.eu-south-2.amazonaws.com
s3.dualstack.eu-west-1.amazonaws.com
+s3-accesspoint.dualstack.eu-west-1.amazonaws.com
+s3-website.dualstack.eu-west-1.amazonaws.com
+s3.eu-west-1.amazonaws.com
+s3-accesspoint.eu-west-1.amazonaws.com
+s3-deprecated.eu-west-1.amazonaws.com
+s3-object-lambda.eu-west-1.amazonaws.com
+s3-website.eu-west-1.amazonaws.com
s3.dualstack.eu-west-2.amazonaws.com
+s3-accesspoint.dualstack.eu-west-2.amazonaws.com
s3.eu-west-2.amazonaws.com
+s3-accesspoint.eu-west-2.amazonaws.com
+s3-object-lambda.eu-west-2.amazonaws.com
s3-website.eu-west-2.amazonaws.com
s3.dualstack.eu-west-3.amazonaws.com
+s3-accesspoint.dualstack.eu-west-3.amazonaws.com
+s3-website.dualstack.eu-west-3.amazonaws.com
s3.eu-west-3.amazonaws.com
+s3-accesspoint.eu-west-3.amazonaws.com
+s3-object-lambda.eu-west-3.amazonaws.com
s3-website.eu-west-3.amazonaws.com
+s3.dualstack.il-central-1.amazonaws.com
+s3-accesspoint.dualstack.il-central-1.amazonaws.com
+s3.il-central-1.amazonaws.com
+s3-accesspoint.il-central-1.amazonaws.com
+s3-object-lambda.il-central-1.amazonaws.com
+s3-website.il-central-1.amazonaws.com
+s3.dualstack.me-central-1.amazonaws.com
+s3-accesspoint.dualstack.me-central-1.amazonaws.com
+s3.me-central-1.amazonaws.com
+s3-accesspoint.me-central-1.amazonaws.com
+s3-object-lambda.me-central-1.amazonaws.com
+s3-website.me-central-1.amazonaws.com
+s3.dualstack.me-south-1.amazonaws.com
+s3-accesspoint.dualstack.me-south-1.amazonaws.com
+s3.me-south-1.amazonaws.com
+s3-accesspoint.me-south-1.amazonaws.com
+s3-object-lambda.me-south-1.amazonaws.com
+s3-website.me-south-1.amazonaws.com
s3.amazonaws.com
+s3-1.amazonaws.com
+s3-ap-east-1.amazonaws.com
s3-ap-northeast-1.amazonaws.com
s3-ap-northeast-2.amazonaws.com
+s3-ap-northeast-3.amazonaws.com
s3-ap-south-1.amazonaws.com
s3-ap-southeast-1.amazonaws.com
s3-ap-southeast-2.amazonaws.com
s3-ca-central-1.amazonaws.com
s3-eu-central-1.amazonaws.com
+s3-eu-north-1.amazonaws.com
s3-eu-west-1.amazonaws.com
s3-eu-west-2.amazonaws.com
s3-eu-west-3.amazonaws.com
s3-external-1.amazonaws.com
+s3-fips-us-gov-east-1.amazonaws.com
s3-fips-us-gov-west-1.amazonaws.com
+mrap.accesspoint.s3-global.amazonaws.com
+s3-me-south-1.amazonaws.com
s3-sa-east-1.amazonaws.com
s3-us-east-2.amazonaws.com
+s3-us-gov-east-1.amazonaws.com
s3-us-gov-west-1.amazonaws.com
s3-us-west-1.amazonaws.com
s3-us-west-2.amazonaws.com
@@ -10800,80 +11703,277 @@ s3-website-ap-southeast-2.amazonaws.com
s3-website-eu-west-1.amazonaws.com
s3-website-sa-east-1.amazonaws.com
s3-website-us-east-1.amazonaws.com
+s3-website-us-gov-west-1.amazonaws.com
s3-website-us-west-1.amazonaws.com
s3-website-us-west-2.amazonaws.com
s3.dualstack.sa-east-1.amazonaws.com
+s3-accesspoint.dualstack.sa-east-1.amazonaws.com
+s3-website.dualstack.sa-east-1.amazonaws.com
+s3.sa-east-1.amazonaws.com
+s3-accesspoint.sa-east-1.amazonaws.com
+s3-object-lambda.sa-east-1.amazonaws.com
+s3-website.sa-east-1.amazonaws.com
s3.dualstack.us-east-1.amazonaws.com
+s3-accesspoint.dualstack.us-east-1.amazonaws.com
+s3-accesspoint-fips.dualstack.us-east-1.amazonaws.com
+s3-fips.dualstack.us-east-1.amazonaws.com
+s3-website.dualstack.us-east-1.amazonaws.com
+s3.us-east-1.amazonaws.com
+s3-accesspoint.us-east-1.amazonaws.com
+s3-accesspoint-fips.us-east-1.amazonaws.com
+s3-deprecated.us-east-1.amazonaws.com
+s3-fips.us-east-1.amazonaws.com
+s3-object-lambda.us-east-1.amazonaws.com
+s3-website.us-east-1.amazonaws.com
s3.dualstack.us-east-2.amazonaws.com
+s3-accesspoint.dualstack.us-east-2.amazonaws.com
+s3-accesspoint-fips.dualstack.us-east-2.amazonaws.com
+s3-fips.dualstack.us-east-2.amazonaws.com
s3.us-east-2.amazonaws.com
+s3-accesspoint.us-east-2.amazonaws.com
+s3-accesspoint-fips.us-east-2.amazonaws.com
+s3-deprecated.us-east-2.amazonaws.com
+s3-fips.us-east-2.amazonaws.com
+s3-object-lambda.us-east-2.amazonaws.com
s3-website.us-east-2.amazonaws.com
+s3.dualstack.us-gov-east-1.amazonaws.com
+s3-accesspoint.dualstack.us-gov-east-1.amazonaws.com
+s3-accesspoint-fips.dualstack.us-gov-east-1.amazonaws.com
+s3-fips.dualstack.us-gov-east-1.amazonaws.com
+s3.us-gov-east-1.amazonaws.com
+s3-accesspoint.us-gov-east-1.amazonaws.com
+s3-accesspoint-fips.us-gov-east-1.amazonaws.com
+s3-fips.us-gov-east-1.amazonaws.com
+s3-object-lambda.us-gov-east-1.amazonaws.com
+s3-website.us-gov-east-1.amazonaws.com
+s3.dualstack.us-gov-west-1.amazonaws.com
+s3-accesspoint.dualstack.us-gov-west-1.amazonaws.com
+s3-accesspoint-fips.dualstack.us-gov-west-1.amazonaws.com
+s3-fips.dualstack.us-gov-west-1.amazonaws.com
+s3.us-gov-west-1.amazonaws.com
+s3-accesspoint.us-gov-west-1.amazonaws.com
+s3-accesspoint-fips.us-gov-west-1.amazonaws.com
+s3-fips.us-gov-west-1.amazonaws.com
+s3-object-lambda.us-gov-west-1.amazonaws.com
+s3-website.us-gov-west-1.amazonaws.com
+s3.dualstack.us-west-1.amazonaws.com
+s3-accesspoint.dualstack.us-west-1.amazonaws.com
+s3-accesspoint-fips.dualstack.us-west-1.amazonaws.com
+s3-fips.dualstack.us-west-1.amazonaws.com
+s3-website.dualstack.us-west-1.amazonaws.com
+s3.us-west-1.amazonaws.com
+s3-accesspoint.us-west-1.amazonaws.com
+s3-accesspoint-fips.us-west-1.amazonaws.com
+s3-fips.us-west-1.amazonaws.com
+s3-object-lambda.us-west-1.amazonaws.com
+s3-website.us-west-1.amazonaws.com
+s3.dualstack.us-west-2.amazonaws.com
+s3-accesspoint.dualstack.us-west-2.amazonaws.com
+s3-accesspoint-fips.dualstack.us-west-2.amazonaws.com
+s3-fips.dualstack.us-west-2.amazonaws.com
+s3-website.dualstack.us-west-2.amazonaws.com
+s3.us-west-2.amazonaws.com
+s3-accesspoint.us-west-2.amazonaws.com
+s3-accesspoint-fips.us-west-2.amazonaws.com
+s3-deprecated.us-west-2.amazonaws.com
+s3-fips.us-west-2.amazonaws.com
+s3-object-lambda.us-west-2.amazonaws.com
+s3-website.us-west-2.amazonaws.com
+
+// Amazon SageMaker Notebook Instances
+// Submitted by AWS Security <psl-maintainers@amazon.com>
+// Reference: fe8c9e94-5a22-486d-8750-991a3a9b13c6
+notebook.af-south-1.sagemaker.aws
+notebook.ap-east-1.sagemaker.aws
+notebook.ap-northeast-1.sagemaker.aws
+notebook.ap-northeast-2.sagemaker.aws
+notebook.ap-northeast-3.sagemaker.aws
+notebook.ap-south-1.sagemaker.aws
+notebook.ap-south-2.sagemaker.aws
+notebook.ap-southeast-1.sagemaker.aws
+notebook.ap-southeast-2.sagemaker.aws
+notebook.ap-southeast-3.sagemaker.aws
+notebook.ap-southeast-4.sagemaker.aws
+notebook.ca-central-1.sagemaker.aws
+notebook.eu-central-1.sagemaker.aws
+notebook.eu-central-2.sagemaker.aws
+notebook.eu-north-1.sagemaker.aws
+notebook.eu-south-1.sagemaker.aws
+notebook.eu-south-2.sagemaker.aws
+notebook.eu-west-1.sagemaker.aws
+notebook.eu-west-2.sagemaker.aws
+notebook.eu-west-3.sagemaker.aws
+notebook.il-central-1.sagemaker.aws
+notebook.me-central-1.sagemaker.aws
+notebook.me-south-1.sagemaker.aws
+notebook.sa-east-1.sagemaker.aws
+notebook.us-east-1.sagemaker.aws
+notebook-fips.us-east-1.sagemaker.aws
+notebook.us-east-2.sagemaker.aws
+notebook-fips.us-east-2.sagemaker.aws
+notebook.us-gov-east-1.sagemaker.aws
+notebook-fips.us-gov-east-1.sagemaker.aws
+notebook.us-gov-west-1.sagemaker.aws
+notebook-fips.us-gov-west-1.sagemaker.aws
+notebook.us-west-1.sagemaker.aws
+notebook.us-west-2.sagemaker.aws
+notebook-fips.us-west-2.sagemaker.aws
+notebook.cn-north-1.sagemaker.com.cn
+notebook.cn-northwest-1.sagemaker.com.cn
+
+// Amazon SageMaker Studio
+// Submitted by AWS Security <psl-maintainers@amazon.com>
+// Reference: 057ee397-6bf8-4f20-b807-d7bc145ac980
+studio.af-south-1.sagemaker.aws
+studio.ap-east-1.sagemaker.aws
+studio.ap-northeast-1.sagemaker.aws
+studio.ap-northeast-2.sagemaker.aws
+studio.ap-northeast-3.sagemaker.aws
+studio.ap-south-1.sagemaker.aws
+studio.ap-southeast-1.sagemaker.aws
+studio.ap-southeast-2.sagemaker.aws
+studio.ap-southeast-3.sagemaker.aws
+studio.ca-central-1.sagemaker.aws
+studio.eu-central-1.sagemaker.aws
+studio.eu-north-1.sagemaker.aws
+studio.eu-south-1.sagemaker.aws
+studio.eu-west-1.sagemaker.aws
+studio.eu-west-2.sagemaker.aws
+studio.eu-west-3.sagemaker.aws
+studio.il-central-1.sagemaker.aws
+studio.me-central-1.sagemaker.aws
+studio.me-south-1.sagemaker.aws
+studio.sa-east-1.sagemaker.aws
+studio.us-east-1.sagemaker.aws
+studio.us-east-2.sagemaker.aws
+studio.us-gov-east-1.sagemaker.aws
+studio-fips.us-gov-east-1.sagemaker.aws
+studio.us-gov-west-1.sagemaker.aws
+studio-fips.us-gov-west-1.sagemaker.aws
+studio.us-west-1.sagemaker.aws
+studio.us-west-2.sagemaker.aws
+studio.cn-north-1.sagemaker.com.cn
+studio.cn-northwest-1.sagemaker.com.cn
+
+// Analytics on AWS
+// Submitted by AWS Security <psl-maintainers@amazon.com>
+// Reference: 955f9f40-a495-4e73-ae85-67b77ac9cadd
+analytics-gateway.ap-northeast-1.amazonaws.com
+analytics-gateway.ap-northeast-2.amazonaws.com
+analytics-gateway.ap-south-1.amazonaws.com
+analytics-gateway.ap-southeast-1.amazonaws.com
+analytics-gateway.ap-southeast-2.amazonaws.com
+analytics-gateway.eu-central-1.amazonaws.com
+analytics-gateway.eu-west-1.amazonaws.com
+analytics-gateway.us-east-1.amazonaws.com
+analytics-gateway.us-east-2.amazonaws.com
+analytics-gateway.us-west-2.amazonaws.com
+
+// AWS Amplify
+// Submitted by AWS Security <psl-maintainers@amazon.com>
+// Reference: 5ecce854-c033-4fc4-a755-1a9916d9a9bb
+*.amplifyapp.com
+
+// AWS App Runner
+// Submitted by AWS Security <psl-maintainers@amazon.com>
+// Reference: 6828c008-ba5d-442f-ade5-48da4e7c2316
+*.awsapprunner.com
// AWS Cloud9
// Submitted by: AWS Security <psl-maintainers@amazon.com>
-// Reference: 2b6dfa9a-3a7f-4367-b2e7-0321e77c0d59
+// Reference: 05c44955-977c-4b57-938a-f2af92733f9f
+webview-assets.aws-cloud9.af-south-1.amazonaws.com
vfs.cloud9.af-south-1.amazonaws.com
webview-assets.cloud9.af-south-1.amazonaws.com
+webview-assets.aws-cloud9.ap-east-1.amazonaws.com
vfs.cloud9.ap-east-1.amazonaws.com
webview-assets.cloud9.ap-east-1.amazonaws.com
+webview-assets.aws-cloud9.ap-northeast-1.amazonaws.com
vfs.cloud9.ap-northeast-1.amazonaws.com
webview-assets.cloud9.ap-northeast-1.amazonaws.com
+webview-assets.aws-cloud9.ap-northeast-2.amazonaws.com
vfs.cloud9.ap-northeast-2.amazonaws.com
webview-assets.cloud9.ap-northeast-2.amazonaws.com
+webview-assets.aws-cloud9.ap-northeast-3.amazonaws.com
vfs.cloud9.ap-northeast-3.amazonaws.com
webview-assets.cloud9.ap-northeast-3.amazonaws.com
+webview-assets.aws-cloud9.ap-south-1.amazonaws.com
vfs.cloud9.ap-south-1.amazonaws.com
webview-assets.cloud9.ap-south-1.amazonaws.com
+webview-assets.aws-cloud9.ap-southeast-1.amazonaws.com
vfs.cloud9.ap-southeast-1.amazonaws.com
webview-assets.cloud9.ap-southeast-1.amazonaws.com
+webview-assets.aws-cloud9.ap-southeast-2.amazonaws.com
vfs.cloud9.ap-southeast-2.amazonaws.com
webview-assets.cloud9.ap-southeast-2.amazonaws.com
+webview-assets.aws-cloud9.ca-central-1.amazonaws.com
vfs.cloud9.ca-central-1.amazonaws.com
webview-assets.cloud9.ca-central-1.amazonaws.com
+webview-assets.aws-cloud9.eu-central-1.amazonaws.com
vfs.cloud9.eu-central-1.amazonaws.com
webview-assets.cloud9.eu-central-1.amazonaws.com
+webview-assets.aws-cloud9.eu-north-1.amazonaws.com
vfs.cloud9.eu-north-1.amazonaws.com
webview-assets.cloud9.eu-north-1.amazonaws.com
+webview-assets.aws-cloud9.eu-south-1.amazonaws.com
vfs.cloud9.eu-south-1.amazonaws.com
webview-assets.cloud9.eu-south-1.amazonaws.com
+webview-assets.aws-cloud9.eu-west-1.amazonaws.com
vfs.cloud9.eu-west-1.amazonaws.com
webview-assets.cloud9.eu-west-1.amazonaws.com
+webview-assets.aws-cloud9.eu-west-2.amazonaws.com
vfs.cloud9.eu-west-2.amazonaws.com
webview-assets.cloud9.eu-west-2.amazonaws.com
+webview-assets.aws-cloud9.eu-west-3.amazonaws.com
vfs.cloud9.eu-west-3.amazonaws.com
webview-assets.cloud9.eu-west-3.amazonaws.com
+webview-assets.aws-cloud9.me-south-1.amazonaws.com
vfs.cloud9.me-south-1.amazonaws.com
webview-assets.cloud9.me-south-1.amazonaws.com
+webview-assets.aws-cloud9.sa-east-1.amazonaws.com
vfs.cloud9.sa-east-1.amazonaws.com
webview-assets.cloud9.sa-east-1.amazonaws.com
+webview-assets.aws-cloud9.us-east-1.amazonaws.com
vfs.cloud9.us-east-1.amazonaws.com
webview-assets.cloud9.us-east-1.amazonaws.com
+webview-assets.aws-cloud9.us-east-2.amazonaws.com
vfs.cloud9.us-east-2.amazonaws.com
webview-assets.cloud9.us-east-2.amazonaws.com
+webview-assets.aws-cloud9.us-west-1.amazonaws.com
vfs.cloud9.us-west-1.amazonaws.com
webview-assets.cloud9.us-west-1.amazonaws.com
+webview-assets.aws-cloud9.us-west-2.amazonaws.com
vfs.cloud9.us-west-2.amazonaws.com
webview-assets.cloud9.us-west-2.amazonaws.com
// AWS Elastic Beanstalk
-// Submitted by Luke Wells <psl-maintainers@amazon.com>
-// Reference: aa202394-43a0-4857-b245-8db04549137e
+// Submitted by AWS Security <psl-maintainers@amazon.com>
+// Reference: bb5a965c-dec3-4967-aa22-e306ad064797
cn-north-1.eb.amazonaws.com.cn
cn-northwest-1.eb.amazonaws.com.cn
elasticbeanstalk.com
+af-south-1.elasticbeanstalk.com
+ap-east-1.elasticbeanstalk.com
ap-northeast-1.elasticbeanstalk.com
ap-northeast-2.elasticbeanstalk.com
ap-northeast-3.elasticbeanstalk.com
ap-south-1.elasticbeanstalk.com
ap-southeast-1.elasticbeanstalk.com
ap-southeast-2.elasticbeanstalk.com
+ap-southeast-3.elasticbeanstalk.com
ca-central-1.elasticbeanstalk.com
eu-central-1.elasticbeanstalk.com
+eu-north-1.elasticbeanstalk.com
+eu-south-1.elasticbeanstalk.com
eu-west-1.elasticbeanstalk.com
eu-west-2.elasticbeanstalk.com
eu-west-3.elasticbeanstalk.com
+il-central-1.elasticbeanstalk.com
+me-south-1.elasticbeanstalk.com
sa-east-1.elasticbeanstalk.com
us-east-1.elasticbeanstalk.com
us-east-2.elasticbeanstalk.com
+us-gov-east-1.elasticbeanstalk.com
us-gov-west-1.elasticbeanstalk.com
us-west-1.elasticbeanstalk.com
us-west-2.elasticbeanstalk.com
@@ -12089,7 +13189,7 @@ shw.io
// Submitted by Jonathan Rudenberg <jonathan@flynn.io>
flynnhosting.net
-// Forgerock : https://www.forgerock.com
+// Forgerock : https://www.forgerock.com
// Submitted by Roderick Parr <roderick.parr@forgerock.com>
forgeblocks.com
id.forgerock.io
@@ -12136,7 +13236,7 @@ freemyip.com
// Submitted by Daniel A. Maierhofer <vorstand@funkfeuer.at>
wien.funkfeuer.at
-// Futureweb OG : http://www.futureweb.at
+// Futureweb GmbH : https://www.futureweb.at
// Submitted by Andreas Schnederle-Wagner <schnederle@futureweb.at>
*.futurecms.at
*.ex.futurecms.at
@@ -12643,7 +13743,6 @@ iobb.net
// Submitted by Ihor Kolodyuk <ik@jelastic.com>
mel.cloudlets.com.au
cloud.interhostsolutions.be
-users.scale.virtualcloud.com.br
mycloud.by
alp1.ae.flow.ch
appengine.flow.ch
@@ -12667,9 +13766,7 @@ ch.trendhosting.cloud
de.trendhosting.cloud
jele.club
amscompute.com
-clicketcloud.com
dopaas.com
-hidora.com
paas.hosted-by-previder.com
rag-cloud.hosteur.com
rag-cloud-ch.hosteur.com
@@ -12984,6 +14081,10 @@ azurestaticapps.net
1.azurestaticapps.net
2.azurestaticapps.net
3.azurestaticapps.net
+4.azurestaticapps.net
+5.azurestaticapps.net
+6.azurestaticapps.net
+7.azurestaticapps.net
centralus.azurestaticapps.net
eastasia.azurestaticapps.net
eastus2.azurestaticapps.net
@@ -13064,6 +14165,9 @@ sa.ngrok.io
us.ngrok.io
ngrok.pizza
+// Nicolaus Copernicus University in Torun - MSK TORMAN (https://www.man.torun.pl)
+torun.pl
+
// Nimbus Hosting Ltd. : https://www.nimbushosting.co.uk/
// Submitted by Nicholas Ford <nick@nimbushosting.co.uk>
nh-serv.co.uk
@@ -13459,6 +14563,10 @@ qoto.io
// Submitted by Xavier De Cock <xdecock@gmail.com>
qualifioapp.com
+// Quality Unit: https://qualityunit.com
+// Submitted by Vasyl Tsalko <vtsalko@qualityunit.com>
+ladesk.com
+
// QuickBackend: https://www.quickbackend.com
// Submitted by Dani Biro <dani@pymet.com>
qbuser.com
@@ -13774,6 +14882,20 @@ bounty-full.com
alpha.bounty-full.com
beta.bounty-full.com
+// Smallregistry by Promopixel SARL: https://www.smallregistry.net
+// Former AFNIC's SLDs
+// Submitted by Jérôme Lipowicz <support@promopixel.com>
+aeroport.fr
+avocat.fr
+chambagri.fr
+chirurgiens-dentistes.fr
+experts-comptables.fr
+medecin.fr
+notaires.fr
+pharmacien.fr
+port.fr
+veterinaire.fr
+
// Small Technology Foundation : https://small-tech.org
// Submitted by Aral Balkan <aral@small-tech.org>
small-web.org
@@ -13867,6 +14989,10 @@ myspreadshop.co.uk
// Submitted by Jacob Lee <jacob@stdlib.com>
api.stdlib.com
+// Storipress : https://storipress.com
+// Submitted by Benno Liu <benno@storipress.com>
+storipress.app
+
// Storj Labs Inc. : https://storj.io/
// Submitted by Philip Hutchins <hostmaster@storj.io>
storj.farm
@@ -14234,6 +15360,8 @@ js.wpenginepowered.com
// Submitted by Shahar Talmi <shahar@wix.com>
wixsite.com
editorx.io
+wixstudio.io
+wix.run
// XenonCloud GbR: https://xenoncloud.net
// Submitted by Julian Uphoff <publicsuffixlist@xenoncloud.net>
diff --git a/etc/refcards/Makefile b/etc/refcards/Makefile
index 9bc7564395a..c80c55a60cf 100644
--- a/etc/refcards/Makefile
+++ b/etc/refcards/Makefile
@@ -1,6 +1,6 @@
### Makefile for Emacs refcards
-## Copyright (C) 1993-1994, 2001-2023 Free Software Foundation, Inc.
+## Copyright (C) 1993-1994, 2001-2024 Free Software Foundation, Inc.
## This file is part of GNU Emacs.
#
diff --git a/etc/refcards/README b/etc/refcards/README
index 7e3c7d65d6c..9521c9e0c2a 100644
--- a/etc/refcards/README
+++ b/etc/refcards/README
@@ -1,4 +1,4 @@
-Copyright (C) 2013-2023 Free Software Foundation, Inc.
+Copyright (C) 2013-2024 Free Software Foundation, Inc.
See the end of the file for license conditions.
@@ -77,7 +77,7 @@ it is reproduced here for convenience.
File: gnus-logo.eps, gnus-logo.pdf
Author: Luis Fernandes <elf@ee.ryerson.ca>
- Copyright (C) 2001-2022 Free Software Foundation, Inc.
+ Copyright (C) 2001-2024 Free Software Foundation, Inc.
License: GNU General Public License version 3 or later (see COPYING)
diff --git a/etc/refcards/calccard.tex b/etc/refcards/calccard.tex
index ce70b6271e5..1684240f9cf 100644
--- a/etc/refcards/calccard.tex
+++ b/etc/refcards/calccard.tex
@@ -20,7 +20,7 @@
% Typical command to format: tex calccard.tex
% Typical command to print (3 cols): dvips -t landscape calccard.dvi
-% Copyright (C) 1987, 1992, 2001--2023 Free Software Foundation, Inc.
+% Copyright (C) 1987, 1992, 2001--2024 Free Software Foundation, Inc.
% This document is free software: you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
diff --git a/etc/refcards/cs-dired-ref.tex b/etc/refcards/cs-dired-ref.tex
index 6f865ca26c7..028df7ee33b 100644
--- a/etc/refcards/cs-dired-ref.tex
+++ b/etc/refcards/cs-dired-ref.tex
@@ -1,6 +1,6 @@
% Reference Card for Dired -*- coding: utf-8 -*-
-% Copyright (C) 2000--2023 Free Software Foundation, Inc.
+% Copyright (C) 2000--2024 Free Software Foundation, Inc.
% Author: Evgeny Roubinchtein <eroubinc@u.washington.edu>
% Czech translation: Pavel Janík <Pavel@Janik.cz>, March 2001
diff --git a/etc/refcards/cs-refcard.tex b/etc/refcards/cs-refcard.tex
index a949b3d19d2..85383d0ac4b 100644
--- a/etc/refcards/cs-refcard.tex
+++ b/etc/refcards/cs-refcard.tex
@@ -1,6 +1,6 @@
% Reference Card for GNU Emacs -*- coding: utf-8 -*-
-% Copyright (C) 1987, 1993, 1996--1997, 2001--2023 Free Software
+% Copyright (C) 1987, 1993, 1996--1997, 2001--2024 Free Software
% Foundation, Inc.
% Author: Stephen Gildea <stepheng+emacs@gildea.com>
diff --git a/etc/refcards/cs-survival.tex b/etc/refcards/cs-survival.tex
index 59885e92654..bd6206152de 100644
--- a/etc/refcards/cs-survival.tex
+++ b/etc/refcards/cs-survival.tex
@@ -1,6 +1,6 @@
% Title: GNU Emacs Survival Card -*- coding: utf-8 -*-
-% Copyright (C) 2000--2023 Free Software Foundation, Inc.
+% Copyright (C) 2000--2024 Free Software Foundation, Inc.
% Author: Włodek Bzyl <matwb@univ.gda.pl>
% Czech translation: Pavel Janík <Pavel@Janik.cz>, March 2001
diff --git a/etc/refcards/de-refcard.tex b/etc/refcards/de-refcard.tex
index e0088bc6c7c..da11ac4aa8e 100644
--- a/etc/refcards/de-refcard.tex
+++ b/etc/refcards/de-refcard.tex
@@ -1,6 +1,6 @@
% Reference Card for GNU Emacs
-% Copyright (C) 1987, 1993, 1996, 2000--2023 Free Software Foundation,
+% Copyright (C) 1987, 1993, 1996, 2000--2024 Free Software Foundation,
% Inc.
% Author: Stephen Gildea <stepheng+emacs@gildea.com>
diff --git a/etc/refcards/dired-ref.tex b/etc/refcards/dired-ref.tex
index 3ebd422ed09..ffe1bbb50ff 100644
--- a/etc/refcards/dired-ref.tex
+++ b/etc/refcards/dired-ref.tex
@@ -1,6 +1,6 @@
% Reference Card for Dired
-% Copyright (C) 2000--2023 Free Software Foundation, Inc.
+% Copyright (C) 2000--2024 Free Software Foundation, Inc.
% Author: Evgeny Roubinchtein <eroubinc@u.washington.edu>
diff --git a/etc/refcards/emacsver.tex.in b/etc/refcards/emacsver.tex.in
index d1f15f18c85..31d1aa95eff 100644
--- a/etc/refcards/emacsver.tex.in
+++ b/etc/refcards/emacsver.tex.in
@@ -2,4 +2,4 @@
\def\versionemacs{@majorversion@} % major version of emacs
%% This one should not be automatically updated;
%% M-x set-copyright in admin.el handles it.
-\def\year{2023} % latest copyright year
+\def\year{2024} % latest copyright year
diff --git a/etc/refcards/fr-dired-ref.tex b/etc/refcards/fr-dired-ref.tex
index 9a0df984ad1..7f9d32901c7 100644
--- a/etc/refcards/fr-dired-ref.tex
+++ b/etc/refcards/fr-dired-ref.tex
@@ -1,6 +1,6 @@
% Reference Card for Dired -*- coding: utf-8 -*-
-% Copyright (C) 2000--2023 Free Software Foundation, Inc.
+% Copyright (C) 2000--2024 Free Software Foundation, Inc.
% Author: Evgeny Roubinchtein <eroubinc@u.washington.edu>
% French translation: Eric Jacoboni
diff --git a/etc/refcards/fr-refcard.tex b/etc/refcards/fr-refcard.tex
index b7b70721f90..cce866d634d 100644
--- a/etc/refcards/fr-refcard.tex
+++ b/etc/refcards/fr-refcard.tex
@@ -1,6 +1,6 @@
% Reference Card for GNU Emacs
-% Copyright (C) 1987, 1993, 1996--1997, 2001--2023 Free Software
+% Copyright (C) 1987, 1993, 1996--1997, 2001--2024 Free Software
% Foundation, Inc.
% Author: Stephen Gildea <stepheng+emacs@gildea.com>
diff --git a/etc/refcards/fr-survival.tex b/etc/refcards/fr-survival.tex
index abc49b61895..149268c20b0 100644
--- a/etc/refcards/fr-survival.tex
+++ b/etc/refcards/fr-survival.tex
@@ -1,7 +1,7 @@
%&tex
% Title: GNU Emacs Survival Card
-% Copyright (C) 2000--2023 Free Software Foundation, Inc.
+% Copyright (C) 2000--2024 Free Software Foundation, Inc.
% Author: Włodek Bzyl <matwb@univ.gda.pl>
% French translation: \'Eric Jacoboni <jaco@teaser.fr>, November 2001
diff --git a/etc/refcards/gnus-logo.eps b/etc/refcards/gnus-logo.eps
index 3bd785d6825..44a43ab65c9 100644
--- a/etc/refcards/gnus-logo.eps
+++ b/etc/refcards/gnus-logo.eps
@@ -1,5 +1,5 @@
%!PS-Adobe-2.0 EPSF-2.0
-% Copyright (C) 2000-2023 Free Software Foundation, Inc.
+% Copyright (C) 2000-2024 Free Software Foundation, Inc.
%
% Author: Luis Fernandes <elf@ee.ryerson.ca>
%
diff --git a/etc/refcards/gnus-refcard.tex b/etc/refcards/gnus-refcard.tex
index 1064af089a4..ee3fff2d3e3 100644
--- a/etc/refcards/gnus-refcard.tex
+++ b/etc/refcards/gnus-refcard.tex
@@ -120,7 +120,7 @@
%% Gnus logo by Luis Fernandes.
\newcommand{\Copyright}{%
\begin{center}
- Copyright \copyright\ 1995, 2000, 2002--2023 Free Software Foundation, Inc.\\*
+ Copyright \copyright\ 1995, 2000, 2002--2024 Free Software Foundation, Inc.\\*
\end{center}
Released under the terms of the GNU General Public License version 3 or later.
diff --git a/etc/refcards/orgcard.tex b/etc/refcards/orgcard.tex
index dd8cae5ce5e..705ab62d69d 100644
--- a/etc/refcards/orgcard.tex
+++ b/etc/refcards/orgcard.tex
@@ -1,5 +1,5 @@
% Reference Card for Org Mode
-\def\orgversionnumber{9.6.7}
+\def\orgversionnumber{9.6.15}
\def\versionyear{2023} % latest update
\input emacsver.tex
@@ -17,7 +17,7 @@
\pdflayout=(0l)
% Nothing else needs to be changed below this line.
-% Copyright (C) 1987, 1993, 1996--1997, 2001--2023 Free Software
+% Copyright (C) 1987, 1993, 1996--1997, 2001--2024 Free Software
% Foundation, Inc.
% This document is free software: you can redistribute it and/or modify
diff --git a/etc/refcards/pdflayout.sty b/etc/refcards/pdflayout.sty
index 284f4d74cc7..050dee2f9ca 100644
--- a/etc/refcards/pdflayout.sty
+++ b/etc/refcards/pdflayout.sty
@@ -1,4 +1,4 @@
-% Copyright (C) 2007-2023 Free Software Foundation, Inc.
+% Copyright (C) 2007-2024 Free Software Foundation, Inc.
% This file is part of GNU Emacs.
diff --git a/etc/refcards/pl-refcard.tex b/etc/refcards/pl-refcard.tex
index 1fbdeab1be9..dabef6d91c8 100644
--- a/etc/refcards/pl-refcard.tex
+++ b/etc/refcards/pl-refcard.tex
@@ -1,7 +1,7 @@
%&mex
% Reference Card for GNU Emacs
-% Copyright (C) 1999, 2001--2023 Free Software Foundation, Inc.
+% Copyright (C) 1999, 2001--2024 Free Software Foundation, Inc.
% Author: Stephen Gildea <stepheng+emacs@gildea.com>
% Polish translation: Włodek Bzyl <matwb@univ.gda.pl>
diff --git a/etc/refcards/pt-br-refcard.tex b/etc/refcards/pt-br-refcard.tex
index 20f7e16d230..47064e7365d 100644
--- a/etc/refcards/pt-br-refcard.tex
+++ b/etc/refcards/pt-br-refcard.tex
@@ -1,6 +1,6 @@
% Reference Card for GNU Emacs
-% Copyright (C) 1987, 1993, 1996--1997, 2002--2004, 2006--2023 Free
+% Copyright (C) 1987, 1993, 1996--1997, 2002--2004, 2006--2024 Free
% Software Foundation, Inc.
% Author: Stephen Gildea <stepheng+emacs@gildea.com>
diff --git a/etc/refcards/refcard.tex b/etc/refcards/refcard.tex
index ac802fdc4c3..8e8ee846291 100644
--- a/etc/refcards/refcard.tex
+++ b/etc/refcards/refcard.tex
@@ -1,6 +1,6 @@
% Reference Card for GNU Emacs
-% Copyright (C) 1987, 1993, 1996--1997, 2001--2023 Free Software
+% Copyright (C) 1987, 1993, 1996--1997, 2001--2024 Free Software
% Foundation, Inc.
% Author: Stephen Gildea <stepheng+emacs@gildea.com>
diff --git a/etc/refcards/ru-refcard.tex b/etc/refcards/ru-refcard.tex
index 815a2db2f6d..0fc4363ec05 100644
--- a/etc/refcards/ru-refcard.tex
+++ b/etc/refcards/ru-refcard.tex
@@ -1,4 +1,4 @@
-% Copyright (C) 1997, 2002--2023 Free Software Foundation, Inc.
+% Copyright (C) 1997, 2002--2024 Free Software Foundation, Inc.
% Author: Stephen Gildea <stepheng+emacs@gildea.com>
% Russian translation: Alex Ott <alexott@gmail.com>
@@ -40,8 +40,8 @@
\newlength{\ColThreeWidth}
\setlength{\ColThreeWidth}{25mm}
-\newcommand{\versionemacs}[0]{30} % version of Emacs this is for
-\newcommand{\cyear}[0]{2023} % copyright year
+\newcommand{\versionemacs}[0]{29} % version of Emacs this is for
+\newcommand{\cyear}[0]{2024} % copyright year
\newcommand\shortcopyrightnotice[0]{\vskip 1ex plus 2 fill
\centerline{\footnotesize \copyright\ \cyear\ Free Software Foundation, Inc.
diff --git a/etc/refcards/sk-dired-ref.tex b/etc/refcards/sk-dired-ref.tex
index b353bd74404..cc15f3edf3b 100644
--- a/etc/refcards/sk-dired-ref.tex
+++ b/etc/refcards/sk-dired-ref.tex
@@ -1,6 +1,6 @@
% Reference Card for Dired -*- coding: utf-8 -*-
-% Copyright (C) 2000--2023 Free Software Foundation, Inc.
+% Copyright (C) 2000--2024 Free Software Foundation, Inc.
% Author: Evgeny Roubinchtein <eroubinc@u.washington.edu>
% Czech translation: Pavel Janík <Pavel@Janik.cz>, March 2001
diff --git a/etc/refcards/sk-refcard.tex b/etc/refcards/sk-refcard.tex
index fe3d352c5b4..30dc61e9bc5 100644
--- a/etc/refcards/sk-refcard.tex
+++ b/etc/refcards/sk-refcard.tex
@@ -1,6 +1,6 @@
% Reference Card for GNU Emacs -*- coding: utf-8 -*-
-% Copyright (C) 1987, 1993, 1996--1997, 2001--2023 Free Software
+% Copyright (C) 1987, 1993, 1996--1997, 2001--2024 Free Software
% Foundation, Inc.
% Author: Stephen Gildea <stepheng+emacs@gildea.com>
diff --git a/etc/refcards/sk-survival.tex b/etc/refcards/sk-survival.tex
index f7a9ee20722..5adc16ef667 100644
--- a/etc/refcards/sk-survival.tex
+++ b/etc/refcards/sk-survival.tex
@@ -1,6 +1,6 @@
% Title: GNU Emacs Survival Card -*- coding: utf-8 -*-
-% Copyright (C) 2000--2023 Free Software Foundation, Inc.
+% Copyright (C) 2000--2024 Free Software Foundation, Inc.
% Author: Włodek Bzyl <matwb@univ.gda.pl>
% Czech translation: Pavel Janík <Pavel@Janik.cz>, March 2001
diff --git a/etc/refcards/survival.tex b/etc/refcards/survival.tex
index cfa1be8b915..9f071b2aac3 100644
--- a/etc/refcards/survival.tex
+++ b/etc/refcards/survival.tex
@@ -1,7 +1,7 @@
%&tex
% Title: GNU Emacs Survival Card
-% Copyright (C) 2000--2023 Free Software Foundation, Inc.
+% Copyright (C) 2000--2024 Free Software Foundation, Inc.
% Author: Włodek Bzyl <matwb@univ.gda.pl>
diff --git a/etc/refcards/vipcard.tex b/etc/refcards/vipcard.tex
index d780a8b1ae8..7e5e0bdcb74 100644
--- a/etc/refcards/vipcard.tex
+++ b/etc/refcards/vipcard.tex
@@ -1,6 +1,6 @@
% Quick Reference Card for VIP
-% Copyright (C) 1987, 2001--2023 Free Software Foundation, Inc.
+% Copyright (C) 1987, 2001--2024 Free Software Foundation, Inc.
% Author: Masahiko Sato <ms@sail.stanford.edu>, <masahiko@sato.riec.tohoku.junet>
diff --git a/etc/refcards/viperCard.tex b/etc/refcards/viperCard.tex
index 8376179be09..3675c024a98 100644
--- a/etc/refcards/viperCard.tex
+++ b/etc/refcards/viperCard.tex
@@ -1,6 +1,6 @@
% ViperCard -- The Reference Card for Viper under GNU Emacs
-% Copyright (C) 1995--1997, 2001--2023 Free Software Foundation, Inc.
+% Copyright (C) 1995--1997, 2001--2024 Free Software Foundation, Inc.
% Author: Michael Kifer <kifer@cs.stonybrook.edu> (Viper)
% Aamod Sane <sane@cs.uiuc.edu> (VIP 4.3)
diff --git a/etc/schema/locate.rnc b/etc/schema/locate.rnc
index 10addaeaa33..bb80aa186e3 100644
--- a/etc/schema/locate.rnc
+++ b/etc/schema/locate.rnc
@@ -1,4 +1,4 @@
-# Copyright (C) 2003-2004, 2007-2023 Free Software Foundation, Inc.
+# Copyright (C) 2003-2004, 2007-2024 Free Software Foundation, Inc.
# This file is part of GNU Emacs.
diff --git a/etc/schema/relaxng.rnc b/etc/schema/relaxng.rnc
index 7489dd58c40..451548ac260 100644
--- a/etc/schema/relaxng.rnc
+++ b/etc/schema/relaxng.rnc
@@ -1,6 +1,6 @@
# RELAX NG XML syntax expressed in RELAX NG Compact syntax.
-# Copyright (C) 2003-2004, 2007-2023 Free Software Foundation, Inc.
+# Copyright (C) 2003-2004, 2007-2024 Free Software Foundation, Inc.
# This file is part of GNU Emacs.
diff --git a/etc/schema/schemas.xml b/etc/schema/schemas.xml
index 8ac208790bf..f04bba849b4 100644
--- a/etc/schema/schemas.xml
+++ b/etc/schema/schemas.xml
@@ -1,5 +1,5 @@
<?xml version="1.0"?>
-<!-- Copyright (C) 2003-2004, 2007-2023 Free Software Foundation, Inc.
+<!-- Copyright (C) 2003-2004, 2007-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/etc/ses-example.ses b/etc/ses-example.ses
index 43793721d7c..ababd9f897f 100644
--- a/etc/ses-example.ses
+++ b/etc/ses-example.ses
@@ -205,7 +205,7 @@ Sales summary - Acme fundraising
;;; ses--symbolic-formulas: (("Eastern area") ("West-district") ("North&South") ("Other"))
;;; End:
-;;; Copyright (C) 2002-2023 Free Software Foundation, Inc.
+;;; Copyright (C) 2002-2024 Free Software Foundation, Inc.
;;; COPYING PERMISSIONS:
;;;
diff --git a/etc/srecode/c.srt b/etc/srecode/c.srt
index 398e9b559b3..73f3ae4a43e 100644
--- a/etc/srecode/c.srt
+++ b/etc/srecode/c.srt
@@ -1,6 +1,6 @@
;;; c.srt --- SRecode templates for c-mode
-;; Copyright (C) 2007-2010, 2012-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2010, 2012-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/etc/srecode/cpp.srt b/etc/srecode/cpp.srt
index ad8618b51be..b2ef5c2ef3c 100644
--- a/etc/srecode/cpp.srt
+++ b/etc/srecode/cpp.srt
@@ -1,6 +1,6 @@
;;; cpp.srt --- SRecode templates for c++-mode
-;; Copyright (C) 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/etc/srecode/default.srt b/etc/srecode/default.srt
index d07f7abf562..dd14334f69c 100644
--- a/etc/srecode/default.srt
+++ b/etc/srecode/default.srt
@@ -1,6 +1,6 @@
;;; default.srt --- SRecode templates for srecode-template-mode
-;; Copyright (C) 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/etc/srecode/doc-cpp.srt b/etc/srecode/doc-cpp.srt
index ea2370e089d..2c43b734ed8 100644
--- a/etc/srecode/doc-cpp.srt
+++ b/etc/srecode/doc-cpp.srt
@@ -1,6 +1,6 @@
;; doc-c.srt --- SRecode templates for "document" applications
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/etc/srecode/doc-default.srt b/etc/srecode/doc-default.srt
index cbaa599147d..54f78ac3966 100644
--- a/etc/srecode/doc-default.srt
+++ b/etc/srecode/doc-default.srt
@@ -1,6 +1,6 @@
;; doc-default.srt --- SRecode templates for "document" applications
-;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/etc/srecode/doc-java.srt b/etc/srecode/doc-java.srt
index a1015572507..cf720316dcf 100644
--- a/etc/srecode/doc-java.srt
+++ b/etc/srecode/doc-java.srt
@@ -1,6 +1,6 @@
;; doc-java.srt --- SRecode templates for "document" applications
-;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/etc/srecode/ede-autoconf.srt b/etc/srecode/ede-autoconf.srt
index 833cd6359ea..a31bcf387d1 100644
--- a/etc/srecode/ede-autoconf.srt
+++ b/etc/srecode/ede-autoconf.srt
@@ -1,6 +1,6 @@
;;; ede/templates/autoconf.srt --- Templates for autoconf used by EDE
-;; Copyright (C) 2010, 2012-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2010, 2012-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/etc/srecode/ede-make.srt b/etc/srecode/ede-make.srt
index 5f16dfc9baa..3d36f230e40 100644
--- a/etc/srecode/ede-make.srt
+++ b/etc/srecode/ede-make.srt
@@ -1,6 +1,6 @@
;; ede-make.srt --- SRecode templates for Makefiles used by EDE.
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/etc/srecode/el.srt b/etc/srecode/el.srt
index 44c7aff6d7e..f765ae41926 100644
--- a/etc/srecode/el.srt
+++ b/etc/srecode/el.srt
@@ -1,6 +1,6 @@
;;; el.srt --- SRecode templates for Emacs Lisp mode
-;; Copyright (C) 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/etc/srecode/getset-cpp.srt b/etc/srecode/getset-cpp.srt
index f000680ab40..b193e8361ed 100644
--- a/etc/srecode/getset-cpp.srt
+++ b/etc/srecode/getset-cpp.srt
@@ -1,6 +1,6 @@
;;; getset-cpp.srt --- SRecode templates for C++ class getter/setters.
-;; Copyright (C) 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/etc/srecode/java.srt b/etc/srecode/java.srt
index 23210b85dfa..70ff87893fd 100644
--- a/etc/srecode/java.srt
+++ b/etc/srecode/java.srt
@@ -1,6 +1,6 @@
;; java.srt
-;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/etc/srecode/make.srt b/etc/srecode/make.srt
index 8857de87b5a..1248f6e85a6 100644
--- a/etc/srecode/make.srt
+++ b/etc/srecode/make.srt
@@ -1,6 +1,6 @@
;; make.srt
-;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/etc/srecode/proj-test.srt b/etc/srecode/proj-test.srt
index b8469542119..d1ff081d980 100644
--- a/etc/srecode/proj-test.srt
+++ b/etc/srecode/proj-test.srt
@@ -1,6 +1,6 @@
;; proj-test.srt --- SRecode template for testing project scoping.
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/etc/srecode/template.srt b/etc/srecode/template.srt
index ded8ce3f705..ebc9f076495 100644
--- a/etc/srecode/template.srt
+++ b/etc/srecode/template.srt
@@ -1,6 +1,6 @@
;;; template.srt --- Templates for Semantic Recoders
-;; Copyright (C) 2005, 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2005, 2007-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/etc/srecode/test.srt b/etc/srecode/test.srt
index 127c4f47672..3fe877096e9 100644
--- a/etc/srecode/test.srt
+++ b/etc/srecode/test.srt
@@ -1,6 +1,6 @@
;; test.srt --- SRecode templates for testing
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/etc/srecode/texi.srt b/etc/srecode/texi.srt
index 4a0a20a2267..427a0df4c05 100644
--- a/etc/srecode/texi.srt
+++ b/etc/srecode/texi.srt
@@ -1,6 +1,6 @@
;; texi.srt --- SRecode templates for Texinfo
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/etc/srecode/wisent.srt b/etc/srecode/wisent.srt
index e42ca5c979c..a816495a23e 100644
--- a/etc/srecode/wisent.srt
+++ b/etc/srecode/wisent.srt
@@ -1,6 +1,6 @@
;; wisent.srt --- SRecode templates for Emacs/WISENT grammar files.
-;; Copyright (C) 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/etc/themes/adwaita-theme.el b/etc/themes/adwaita-theme.el
index 108a9165961..cea8f85c081 100644
--- a/etc/themes/adwaita-theme.el
+++ b/etc/themes/adwaita-theme.el
@@ -1,6 +1,6 @@
;;; adwaita-theme.el --- Tango-based custom theme for faces -*- lexical-binding:t -*-
-;; Copyright (C) 2010-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2010-2024 Free Software Foundation, Inc.
;; Author: William Stevenson <yhvh2000@gmail.com>
diff --git a/etc/themes/deeper-blue-theme.el b/etc/themes/deeper-blue-theme.el
index 20da432c75a..ab769281eb6 100644
--- a/etc/themes/deeper-blue-theme.el
+++ b/etc/themes/deeper-blue-theme.el
@@ -1,6 +1,6 @@
;;; deeper-blue-theme.el --- Custom theme for faces -*- lexical-binding:t -*-
-;; Copyright (C) 2011-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2011-2024 Free Software Foundation, Inc.
;; Author: Scott Frazer <frazer.scott@gmail.com>
diff --git a/etc/themes/dichromacy-theme.el b/etc/themes/dichromacy-theme.el
index c59fe8e0dfa..1e9802bd0ea 100644
--- a/etc/themes/dichromacy-theme.el
+++ b/etc/themes/dichromacy-theme.el
@@ -1,6 +1,6 @@
;;; dichromacy-theme.el --- color theme suitable for color-blind users -*- lexical-binding:t -*-
-;; Copyright (C) 2011-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2011-2024 Free Software Foundation, Inc.
;; Author: Chong Yidong <cyd@stupidchicken>
diff --git a/etc/themes/leuven-dark-theme.el b/etc/themes/leuven-dark-theme.el
index 33a15945e71..e5427f77909 100644
--- a/etc/themes/leuven-dark-theme.el
+++ b/etc/themes/leuven-dark-theme.el
@@ -1,6 +1,6 @@
;;; leuven-dark-theme.el --- Awesome Emacs color theme on dark background -*- lexical-binding: t; -*-
-;; Copyright (C) 2003-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003-2024 Free Software Foundation, Inc.
;; Author: Fabrice Niessen <(concat "fniessen" at-sign "pirilampo.org")>
;; Contributor: Thibault Polge <(concat "thibault" at-sign "thb.lt")>
diff --git a/etc/themes/leuven-theme.el b/etc/themes/leuven-theme.el
index f7d454381d7..2f20dc39859 100644
--- a/etc/themes/leuven-theme.el
+++ b/etc/themes/leuven-theme.el
@@ -1,6 +1,6 @@
;;; leuven-theme.el --- Awesome Emacs color theme on white background -*- lexical-binding:t -*-
-;; Copyright (C) 2003-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003-2024 Free Software Foundation, Inc.
;; Author: Fabrice Niessen <(concat "fniessen" at-sign "pirilampo.org")>
;; URL: https://github.com/fniessen/emacs-leuven-theme
diff --git a/etc/themes/light-blue-theme.el b/etc/themes/light-blue-theme.el
index f3850537617..ce98b53378e 100644
--- a/etc/themes/light-blue-theme.el
+++ b/etc/themes/light-blue-theme.el
@@ -1,6 +1,6 @@
;;; light-blue-theme.el --- Custom theme for faces -*- lexical-binding:t -*-
-;; Copyright (C) 2011-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2011-2024 Free Software Foundation, Inc.
;; Author: Drew Adams <drew.adams@oracle.com>
;; Maintainer: emacs-devel@gnu.org
diff --git a/etc/themes/manoj-dark-theme.el b/etc/themes/manoj-dark-theme.el
index 26627a29c70..81dac1902f0 100644
--- a/etc/themes/manoj-dark-theme.el
+++ b/etc/themes/manoj-dark-theme.el
@@ -1,6 +1,6 @@
;;; manoj-dark-theme.el --- A dark theme from Manoj -*- lexical-binding:t -*-
-;; Copyright (C) 2011-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2011-2024 Free Software Foundation, Inc.
;; Author: Manoj Srivastava <srivasta@ieee.org>
;; Keywords: lisp, faces
@@ -411,10 +411,10 @@ jarring angry fruit salad look to reduce eye fatigue."
'(cursor ((t (:background "orchid"))))
'(custom-button-face ((t (:background "lightgrey" :foreground "black"
- :box '(:line-width 2 :style released-button)))))
+ :box (:line-width 2 :style released-button)))))
'(custom-button-pressed-face ((t (:background "lightgrey"
:foreground "black"
- :box '(:line-width 2 :style pressed-button)))))
+ :box (:line-width 2 :style pressed-button)))))
'(custom-changed-face ((t (:foreground "wheat" :background "blue"))))
'(custom-comment-face ((t (:background "dim gray"))))
'(custom-comment-tag-face ((t (:foreground "gray80"))))
@@ -430,7 +430,7 @@ jarring angry fruit salad look to reduce eye fatigue."
'(custom-variable-button-face ((t (:bold t :underline t :weight bold
:background "lightgrey"
:foreground "black"
- :box '(:line-width 2 :style released-button)))))
+ :box (:line-width 2 :style released-button)))))
'(custom-variable-tag-face ((t (:bold t :foreground "light blue"
:weight bold :height 1.2))))
@@ -586,15 +586,16 @@ jarring angry fruit salad look to reduce eye fatigue."
'(match ((t (:background "RoyalBlue3"))))
'(minibuffer-prompt ((t (:foreground "cyan"))))
'(mode-line ((t (:background "grey75" :foreground "Blue"
- :box '(:line-width -1 :style released-button)
+ :box (:line-width -1 :style released-button)
:height 0.9))))
'(mode-line-buffer-id ((t (:background "grey65" :foreground "red"
:bold t :weight bold :height 0.9))))
'(mode-line-emphasis ((t (:bold t :weight bold))))
'(mode-line-highlight ((t (:box (:line-width 2 :color "grey40"
- :style released-button :height 0.9)))))
+ :style released-button)
+ :height 0.9))))
'(mode-line-inactive ((t (:background "grey30" :foreground "grey80"
- :box '(:line-width -1 :color "grey40")
+ :box (:line-width -1 :color "grey40")
:weight light :height 0.9))))
'(mouse ((t (:background "OrangeRed"))))
diff --git a/etc/themes/misterioso-theme.el b/etc/themes/misterioso-theme.el
index 685951ce1a7..75693b59016 100644
--- a/etc/themes/misterioso-theme.el
+++ b/etc/themes/misterioso-theme.el
@@ -1,6 +1,6 @@
;;; misterioso-theme.el --- Custom face theme for Emacs -*- lexical-binding:t -*-
-;; Copyright (C) 2011-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2011-2024 Free Software Foundation, Inc.
;; Author: Sebastian Hermida
diff --git a/etc/themes/modus-operandi-deuteranopia-theme.el b/etc/themes/modus-operandi-deuteranopia-theme.el
index 5817d8f674c..4d210b977eb 100644
--- a/etc/themes/modus-operandi-deuteranopia-theme.el
+++ b/etc/themes/modus-operandi-deuteranopia-theme.el
@@ -1,6 +1,6 @@
;;; modus-operandi-deuteranopia-theme.el --- Deuteranopia-optimized theme with a white background -*- lexical-binding:t -*-
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
;; Author: Protesilaos Stavrou <info@protesilaos.com>
;; Maintainer: Modus-Themes Development <~protesilaos/modus-themes@lists.sr.ht>
@@ -43,6 +43,7 @@
(require-theme 'modus-themes t))
(require 'modus-themes))
+;;;###theme-autoload
(deftheme modus-operandi-deuteranopia
"Deuteranopia-optimized theme with a white background.
This variant is optimized for users with red-green color
@@ -50,14 +51,17 @@ deficiency (deuteranopia). It conforms with the highest
legibility standard for color contrast between background and
foreground in any given piece of text, which corresponds to a
minimum contrast in relative luminance of 7:1 (WCAG AAA
-standard).")
+standard)."
+ :background-mode 'light
+ :kind 'color-scheme
+ :family 'modus)
(defconst modus-operandi-deuteranopia-palette
'(
;;; Basic values
(bg-main "#ffffff")
- (bg-dim "#f0f0f0")
+ (bg-dim "#f2f2f2")
(fg-main "#000000")
(fg-dim "#595959")
(fg-alt "#193668")
@@ -155,7 +159,7 @@ standard).")
;;; Special purpose
(bg-completion "#c0deff")
- (bg-hover "#97dfed")
+ (bg-hover "#b2e4dc")
(bg-hover-secondary "#f5d0a0")
(bg-hl-line "#dae5ec")
(bg-region "#bdbdbd")
@@ -198,7 +202,7 @@ standard).")
(bg-removed "#f4f099")
(bg-removed-faint "#f6f6b7")
- (bg-removed-refine "#f0e56f")
+ (bg-removed-refine "#ede06f")
(bg-removed-fringe "#c0b200")
(fg-removed "#553d00")
(fg-removed-intense "#7f6f00")
@@ -284,6 +288,7 @@ standard).")
(date-deadline yellow-warmer)
(date-event fg-alt)
(date-holiday yellow-warmer)
+ (date-holiday-other blue)
(date-now blue-faint)
(date-range fg-alt)
(date-scheduled yellow-cooler)
@@ -367,6 +372,48 @@ standard).")
(fg-space border)
(bg-space-err bg-yellow-intense)
+;;;; Terminal mappings
+
+ (bg-term-black "black")
+ (fg-term-black "black")
+ (bg-term-black-bright "gray35")
+ (fg-term-black-bright "gray35")
+
+ (bg-term-red red)
+ (fg-term-red red)
+ (bg-term-red-bright red-warmer)
+ (fg-term-red-bright red-warmer)
+
+ (bg-term-green green)
+ (fg-term-green green)
+ (bg-term-green-bright green-cooler)
+ (fg-term-green-bright green-cooler)
+
+ (bg-term-yellow yellow)
+ (fg-term-yellow yellow)
+ (bg-term-yellow-bright yellow-warmer)
+ (fg-term-yellow-bright yellow-warmer)
+
+ (bg-term-blue blue)
+ (fg-term-blue blue)
+ (bg-term-blue-bright blue-warmer)
+ (fg-term-blue-bright blue-warmer)
+
+ (bg-term-magenta magenta)
+ (fg-term-magenta magenta)
+ (bg-term-magenta-bright magenta-cooler)
+ (fg-term-magenta-bright magenta-cooler)
+
+ (bg-term-cyan cyan)
+ (fg-term-cyan cyan)
+ (bg-term-cyan-bright cyan-cooler)
+ (fg-term-cyan-bright cyan-cooler)
+
+ (bg-term-white "gray65")
+ (fg-term-white "gray65")
+ (bg-term-white-bright "white")
+ (fg-term-white-bright "white")
+
;;;; Heading mappings
(fg-heading-0 cyan-cooler)
@@ -436,7 +483,4 @@ represents."
(provide-theme 'modus-operandi-deuteranopia))
-;;;###theme-autoload
-(put 'modus-operandi-deuteranopia 'theme-properties '(:background-mode light :kind color-scheme :family modus))
-
;;; modus-operandi-deuteranopia-theme.el ends here
diff --git a/etc/themes/modus-operandi-theme.el b/etc/themes/modus-operandi-theme.el
index 9a69e3290b7..b41d5491c2e 100644
--- a/etc/themes/modus-operandi-theme.el
+++ b/etc/themes/modus-operandi-theme.el
@@ -1,6 +1,6 @@
;;; modus-operandi-theme.el --- Elegant, highly legible theme with a white background -*- lexical-binding:t -*-
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
;; Author: Protesilaos Stavrou <info@protesilaos.com>
;; Maintainer: Modus-Themes Development <~protesilaos/modus-themes@lists.sr.ht>
@@ -43,19 +43,23 @@
(require-theme 'modus-themes t))
(require 'modus-themes))
+;;;###theme-autoload
(deftheme modus-operandi
"Elegant, highly legible theme with a white background.
Conforms with the highest legibility standard for color contrast
between background and foreground in any given piece of text,
which corresponds to a minimum contrast in relative luminance of
-7:1 (WCAG AAA standard).")
+7:1 (WCAG AAA standard)."
+ :background-mode 'light
+ :kind 'color-scheme
+ :family 'modus)
(defconst modus-operandi-palette
'(
;;; Basic values
(bg-main "#ffffff")
- (bg-dim "#f0f0f0")
+ (bg-dim "#f2f2f2")
(fg-main "#000000")
(fg-dim "#595959")
(fg-alt "#193668")
@@ -153,7 +157,7 @@ which corresponds to a minimum contrast in relative luminance of
;;; Special purpose
(bg-completion "#c0deff")
- (bg-hover "#94d4ff")
+ (bg-hover "#b2e4dc")
(bg-hover-secondary "#f5d0a0")
(bg-hl-line "#dae5ec")
(bg-region "#bdbdbd")
@@ -282,6 +286,7 @@ which corresponds to a minimum contrast in relative luminance of
(date-deadline red)
(date-event fg-alt)
(date-holiday red-cooler)
+ (date-holiday-other blue)
(date-now fg-main)
(date-range fg-alt)
(date-scheduled yellow-warmer)
@@ -365,6 +370,48 @@ which corresponds to a minimum contrast in relative luminance of
(fg-space border)
(bg-space-err bg-red-intense)
+;;;; Terminal mappings
+
+ (bg-term-black "black")
+ (fg-term-black "black")
+ (bg-term-black-bright "gray35")
+ (fg-term-black-bright "gray35")
+
+ (bg-term-red red)
+ (fg-term-red red)
+ (bg-term-red-bright red-warmer)
+ (fg-term-red-bright red-warmer)
+
+ (bg-term-green green)
+ (fg-term-green green)
+ (bg-term-green-bright green-cooler)
+ (fg-term-green-bright green-cooler)
+
+ (bg-term-yellow yellow)
+ (fg-term-yellow yellow)
+ (bg-term-yellow-bright yellow-warmer)
+ (fg-term-yellow-bright yellow-warmer)
+
+ (bg-term-blue blue)
+ (fg-term-blue blue)
+ (bg-term-blue-bright blue-warmer)
+ (fg-term-blue-bright blue-warmer)
+
+ (bg-term-magenta magenta)
+ (fg-term-magenta magenta)
+ (bg-term-magenta-bright magenta-cooler)
+ (fg-term-magenta-bright magenta-cooler)
+
+ (bg-term-cyan cyan)
+ (fg-term-cyan cyan)
+ (bg-term-cyan-bright cyan-cooler)
+ (fg-term-cyan-bright cyan-cooler)
+
+ (bg-term-white "gray65")
+ (fg-term-white "gray65")
+ (bg-term-white-bright "white")
+ (fg-term-white-bright "white")
+
;;;; Heading mappings
(fg-heading-0 cyan-cooler)
@@ -434,7 +481,4 @@ represents."
(provide-theme 'modus-operandi))
-;;;###theme-autoload
-(put 'modus-operandi 'theme-properties '(:background-mode light :kind color-scheme :family modus))
-
;;; modus-operandi-theme.el ends here
diff --git a/etc/themes/modus-operandi-tinted-theme.el b/etc/themes/modus-operandi-tinted-theme.el
index 341a7d29e84..7e0ad3d7ea8 100644
--- a/etc/themes/modus-operandi-tinted-theme.el
+++ b/etc/themes/modus-operandi-tinted-theme.el
@@ -1,6 +1,6 @@
-;;; modus-operandi-tinted-theme.el --- Elegant, highly legible theme with a light ochre background -*- lexical-binding:t -*-
+;;; modus-operandi-tinted-theme.el --- Elegant, highly legible theme with a light ocher background -*- lexical-binding:t -*-
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
;; Author: Protesilaos Stavrou <info@protesilaos.com>
;; Maintainer: Modus-Themes Development <~protesilaos/modus-themes@lists.sr.ht>
@@ -42,19 +42,23 @@
(require-theme 'modus-themes t))
(require 'modus-themes))
+;;;###theme-autoload
(deftheme modus-operandi-tinted
- "Elegant, highly legible theme with a light ochre background.
+ "Elegant, highly legible theme with a light ocher background.
Conforms with the highest legibility standard for color contrast
between background and foreground in any given piece of text,
which corresponds to a minimum contrast in relative luminance of
-7:1 (WCAG AAA standard).")
+7:1 (WCAG AAA standard)."
+ :background-mode 'light
+ :kind 'color-scheme
+ :family 'modus)
(defconst modus-operandi-tinted-palette
'(
;;; Basic values
(bg-main "#fbf7f0")
- (bg-dim "#ede7db")
+ (bg-dim "#efe9dd")
(fg-main "#000000")
(fg-dim "#595959")
(fg-alt "#193668")
@@ -152,7 +156,7 @@ which corresponds to a minimum contrast in relative luminance of
;;; Special purpose
(bg-completion "#f0c1cf")
- (bg-hover "#94d4ff")
+ (bg-hover "#b2e4dc")
(bg-hover-secondary "#f5d0a0")
(bg-hl-line "#f1d5d0")
(bg-region "#c2bcb5")
@@ -281,6 +285,7 @@ which corresponds to a minimum contrast in relative luminance of
(date-deadline red)
(date-event fg-alt)
(date-holiday red-cooler)
+ (date-holiday-other blue)
(date-now fg-main)
(date-range fg-alt)
(date-scheduled yellow-warmer)
@@ -364,6 +369,48 @@ which corresponds to a minimum contrast in relative luminance of
(fg-space border)
(bg-space-err bg-red-intense)
+;;;; Terminal mappings
+
+ (bg-term-black "black")
+ (fg-term-black "black")
+ (bg-term-black-bright "gray35")
+ (fg-term-black-bright "gray35")
+
+ (bg-term-red red)
+ (fg-term-red red)
+ (bg-term-red-bright red-warmer)
+ (fg-term-red-bright red-warmer)
+
+ (bg-term-green green)
+ (fg-term-green green)
+ (bg-term-green-bright green-cooler)
+ (fg-term-green-bright green-cooler)
+
+ (bg-term-yellow yellow)
+ (fg-term-yellow yellow)
+ (bg-term-yellow-bright yellow-warmer)
+ (fg-term-yellow-bright yellow-warmer)
+
+ (bg-term-blue blue)
+ (fg-term-blue blue)
+ (bg-term-blue-bright blue-warmer)
+ (fg-term-blue-bright blue-warmer)
+
+ (bg-term-magenta magenta)
+ (fg-term-magenta magenta)
+ (bg-term-magenta-bright magenta-cooler)
+ (fg-term-magenta-bright magenta-cooler)
+
+ (bg-term-cyan cyan)
+ (fg-term-cyan cyan)
+ (bg-term-cyan-bright cyan-cooler)
+ (fg-term-cyan-bright cyan-cooler)
+
+ (bg-term-white "gray65")
+ (fg-term-white "gray65")
+ (bg-term-white-bright "white")
+ (fg-term-white-bright "white")
+
;;;; Heading mappings
(fg-heading-0 cyan-cooler)
@@ -433,7 +480,4 @@ represents."
(provide-theme 'modus-operandi-tinted))
-;;;###theme-autoload
-(put 'modus-operandi-tinted 'theme-properties '(:background-mode light :kind color-scheme :family modus))
-
;;; modus-operandi-tinted-theme.el ends here
diff --git a/etc/themes/modus-operandi-tritanopia-theme.el b/etc/themes/modus-operandi-tritanopia-theme.el
index 5d143fa7514..968a6526ca3 100644
--- a/etc/themes/modus-operandi-tritanopia-theme.el
+++ b/etc/themes/modus-operandi-tritanopia-theme.el
@@ -1,6 +1,6 @@
;;; modus-operandi-tritanopia-theme.el --- Tritanopia-optimized theme with a white background -*- lexical-binding:t -*-
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
;; Author: Protesilaos Stavrou <info@protesilaos.com>
;; Maintainer: Modus-Themes Development <~protesilaos/modus-themes@lists.sr.ht>
@@ -43,6 +43,7 @@
(require-theme 'modus-themes t))
(require 'modus-themes))
+;;;###theme-autoload
(deftheme modus-operandi-tritanopia
"Tritanopia-optimized theme with a white background.
This variant is optimized for users with blue-yellow color
@@ -50,14 +51,17 @@ deficiency (tritanopia). It conforms with the highest
legibility standard for color contrast between background and
foreground in any given piece of text, which corresponds to a
minimum contrast in relative luminance of 7:1 (WCAG AAA
-standard).")
+standard)."
+ :background-mode 'light
+ :kind 'color-scheme
+ :family 'modus)
(defconst modus-operandi-tritanopia-palette
'(
;;; Basic values
(bg-main "#ffffff")
- (bg-dim "#f0f0f0")
+ (bg-dim "#f2f2f2")
(fg-main "#000000")
(fg-dim "#595959")
(fg-alt "#193668")
@@ -161,9 +165,9 @@ standard).")
(bg-region "#bdbdbd")
(fg-region "#000000")
- (bg-char-0 "#ff8a5f")
- (bg-char-1 "#bf7aff")
- (bg-char-2 "#7fe0e0")
+ (bg-char-0 "#ff908f")
+ (bg-char-1 "#bfbfff")
+ (bg-char-2 "#5fcfdf")
(bg-mode-line-active "#afe0f2")
(fg-mode-line-active "#0f0f0f")
@@ -284,6 +288,7 @@ standard).")
(date-deadline red)
(date-event fg-alt)
(date-holiday red)
+ (date-holiday-other cyan)
(date-now fg-main)
(date-range fg-alt)
(date-scheduled magenta)
@@ -367,6 +372,48 @@ standard).")
(fg-space border)
(bg-space-err bg-red-intense)
+;;;; Terminal mappings
+
+ (bg-term-black "black")
+ (fg-term-black "black")
+ (bg-term-black-bright "gray35")
+ (fg-term-black-bright "gray35")
+
+ (bg-term-red red)
+ (fg-term-red red)
+ (bg-term-red-bright red-warmer)
+ (fg-term-red-bright red-warmer)
+
+ (bg-term-green green)
+ (fg-term-green green)
+ (bg-term-green-bright green-cooler)
+ (fg-term-green-bright green-cooler)
+
+ (bg-term-yellow yellow)
+ (fg-term-yellow yellow)
+ (bg-term-yellow-bright yellow-warmer)
+ (fg-term-yellow-bright yellow-warmer)
+
+ (bg-term-blue blue)
+ (fg-term-blue blue)
+ (bg-term-blue-bright blue-warmer)
+ (fg-term-blue-bright blue-warmer)
+
+ (bg-term-magenta magenta)
+ (fg-term-magenta magenta)
+ (bg-term-magenta-bright magenta-cooler)
+ (fg-term-magenta-bright magenta-cooler)
+
+ (bg-term-cyan cyan)
+ (fg-term-cyan cyan)
+ (bg-term-cyan-bright cyan-cooler)
+ (fg-term-cyan-bright cyan-cooler)
+
+ (bg-term-white "gray65")
+ (fg-term-white "gray65")
+ (bg-term-white-bright "white")
+ (fg-term-white-bright "white")
+
;;;; Heading mappings
(fg-heading-0 cyan-cooler)
@@ -436,7 +483,4 @@ represents."
(provide-theme 'modus-operandi-tritanopia))
-;;;###theme-autoload
-(put 'modus-operandi-tritanopia 'theme-properties '(:background-mode light :kind color-scheme :family modus))
-
;;; modus-operandi-tritanopia-theme.el ends here
diff --git a/etc/themes/modus-themes.el b/etc/themes/modus-themes.el
index 43c10043bc5..44f25182a30 100644
--- a/etc/themes/modus-themes.el
+++ b/etc/themes/modus-themes.el
@@ -1,12 +1,12 @@
;;; modus-themes.el --- Elegant, highly legible and customizable themes -*- lexical-binding:t -*-
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
;; Author: Protesilaos Stavrou <info@protesilaos.com>
;; Maintainer: Modus-Themes Development <~protesilaos/modus-themes@lists.sr.ht>
;; URL: https://git.sr.ht/~protesilaos/modus-themes
;; Mailing-List: https://lists.sr.ht/~protesilaos/modus-themes
-;; Version: 4.2.0
+;; Version: 4.3.0
;; Package-Requires: ((emacs "27.1"))
;; Keywords: faces, theme, accessibility
@@ -841,8 +841,6 @@ represents."
(defvar modus-themes-preset-overrides-faint
'((bg-completion bg-inactive)
- (bg-hover bg-cyan-subtle)
- (bg-hover-secondary bg-magenta-subtle)
(bg-hl-line bg-dim)
(bg-paren-match bg-cyan-subtle)
(bg-region bg-active)
@@ -997,9 +995,9 @@ Info node `(modus-themes) Option for palette overrides'.")
(prose-block red-faint)
(prose-done green-intense)
- (prose-metadata cyan-faint)
+ (prose-metadata magenta-faint)
(prose-metadata-value blue-cooler)
- (prose-table cyan)
+ (prose-table blue)
(prose-todo red-intense)
(fg-heading-0 blue-cooler)
@@ -1031,7 +1029,7 @@ Info node `(modus-themes) Option for palette overrides'.")
(overline-heading-6 yellow-cooler)
(overline-heading-7 red-cooler)
(overline-heading-8 magenta))
- "Preset for palette overrides with faint coloration.
+ "Preset for palette overrides with intense coloration.
This changes many parts of the theme to make them look more
colorful/intense. Many background colors are accented and
@@ -1111,7 +1109,7 @@ Info node `(modus-themes) Option for palette overrides'.")
(fnname magenta-cooler)
(keyword magenta-warmer)
(preprocessor red-cooler)
- (string olive)
+ (string green-warmer)
(type cyan-cooler)
(variable cyan)
(rx-construct blue-cooler)
@@ -1322,7 +1320,20 @@ symbol, which is safe when used as a face attribute's value."
(defun modus-themes--annotate-theme (theme)
"Return completion annotation for THEME."
- (format " -- %s" (car (split-string (get (intern theme) 'theme-documentation) "\\."))))
+ (when-let ((symbol (intern-soft theme))
+ (doc-string (get symbol 'theme-documentation)))
+ (format " -- %s" (car (split-string doc-string "\\.")))))
+
+(defun modus-themes--completion-table (category candidates)
+ "Pass appropriate metadata CATEGORY to completion CANDIDATES."
+ (lambda (string pred action)
+ (if (eq action 'metadata)
+ `(metadata (category . ,category))
+ (complete-with-action action candidates string pred))))
+
+(defun modus-themes--completion-table-candidates ()
+ "Render `modus-themes--list-known-themes' as completion with theme category."
+ (modus-themes--completion-table 'theme (modus-themes--list-known-themes)))
(defun modus-themes--select-prompt ()
"Minibuffer prompt to select a Modus theme."
@@ -1330,7 +1341,7 @@ symbol, which is safe when used as a face attribute's value."
(intern
(completing-read
"Select Modus theme: "
- (modus-themes--list-known-themes)
+ (modus-themes--completion-table-candidates)
nil t nil
'modus-themes--select-theme-history))))
@@ -1344,12 +1355,13 @@ Disable other themes per `modus-themes-disable-other-themes'."
(defun modus-themes--toggle-theme-p ()
"Return non-nil if `modus-themes-to-toggle' are valid."
- (mapc (lambda (theme)
- (if (or (memq theme modus-themes-items)
- (memq theme (modus-themes--list-known-themes)))
- theme
- (user-error "`%s' is not part of `modus-themes-items'" theme)))
- modus-themes-to-toggle))
+ (mapc
+ (lambda (theme)
+ (if (or (memq theme modus-themes-items)
+ (memq theme (modus-themes--list-known-themes)))
+ theme
+ (user-error "`%s' is not part of `modus-themes-items'" theme)))
+ modus-themes-to-toggle))
;;;###autoload
(defun modus-themes-toggle ()
@@ -1364,9 +1376,7 @@ Disable other themes per `modus-themes-disable-other-themes'."
(if-let* ((themes (modus-themes--toggle-theme-p))
(one (car themes))
(two (cadr themes)))
- (if (eq (car custom-enabled-themes) one)
- (modus-themes-load-theme two)
- (modus-themes-load-theme one))
+ (modus-themes-load-theme (if (eq (car custom-enabled-themes) one) two one))
(modus-themes-load-theme (modus-themes--select-prompt))))
(defun modus-themes--list-colors-render (buffer theme &optional mappings &rest _)
@@ -1424,7 +1434,8 @@ Helper function for `modus-themes-list-colors'."
(completion-extra-properties `(:annotation-function ,#'modus-themes--annotate-theme)))
(completing-read
(format "Use palette from theme [%s]: " def)
- (modus-themes--list-known-themes) nil t nil
+ (modus-themes--completion-table-candidates)
+ nil t nil
'modus-themes--list-colors-prompt-history def)))
(defun modus-themes-list-colors (theme &optional mappings)
@@ -1524,7 +1535,7 @@ color that is combined with FG-FOR-BG."
:foreground fg
:weight
;; If we have `bold' specifically, we inherit the face of
- ;; the same name. This allows the user to customise that
+ ;; the same name. This allows the user to customize that
;; face, such as to change its font family.
(if (and weight (not (eq weight 'bold)))
weight
@@ -1552,20 +1563,22 @@ Optional OL is the color of an overline."
(style (or key (alist-get t modus-themes-headings)))
(style-listp (listp style))
(properties style)
- (var (when (memq 'variable-pitch properties) 'variable-pitch))
+ (var (when (and style-listp (memq 'variable-pitch properties)) 'variable-pitch))
(weight (when style-listp (modus-themes--weight style))))
- (list :inherit
- (cond
- ;; `no-bold' is for backward compatibility because we cannot
- ;; deprecate a variable's value.
- ((or weight (memq 'no-bold properties))
- var)
- (var (append (list 'bold) (list var)))
- ('bold))
+ (list :inherit (cond
+ ((not style-listp) 'bold)
+ ;; `no-bold' is for backward compatibility because we cannot
+ ;; deprecate a variable's value.
+ ((or weight (memq 'no-bold properties))
+ var)
+ (var (append (list 'bold) (list var)))
+ (t 'bold))
:background (or bg 'unspecified)
:foreground fg
:overline (or ol 'unspecified)
- :height (modus-themes--property-lookup properties 'height #'floatp 'unspecified)
+ :height (if style-listp
+ (modus-themes--property-lookup properties 'height #'floatp 'unspecified)
+ 'unspecified)
:weight (or weight 'unspecified))))
(defun modus-themes--org-block (fg bg)
@@ -1747,6 +1760,8 @@ FG and BG are the main colors."
`(tool-bar ((,c :background ,bg-dim :foreground ,fg-main)))
`(vertical-border ((,c :foreground ,border)))
;;;;; basic and/or ungrouped styles
+ `(appt-notification ((,c :inherit error)))
+ `(blink-matching-paren-highlight-offscreen ((,c :background ,bg-paren-match)))
`(bold ((,c :weight bold)))
`(bold-italic ((,c :inherit (bold italic))))
`(underline ((,c :underline ,fg-dim)))
@@ -1824,9 +1839,9 @@ FG and BG are the main colors."
`(agda2-highlight-unsolved-meta-face ((,c :inherit modus-themes-lang-warning)))
;;;;; all-the-icons
`(all-the-icons-blue ((,c :foreground ,blue-cooler)))
- `(all-the-icons-blue-warmer ((,c :foreground ,blue-warmer)))
- `(all-the-icons-cyan ((,c :foreground ,cyan-intense)))
- `(all-the-icons-cyan-warmer ((,c :foreground ,cyan-warmer)))
+ `(all-the-icons-blue-alt ((,c :foreground ,blue-warmer)))
+ `(all-the-icons-cyan ((,c :foreground ,cyan)))
+ `(all-the-icons-cyan-alt ((,c :foreground ,cyan-warmer)))
`(all-the-icons-dblue ((,c :foreground ,blue-faint)))
`(all-the-icons-dcyan ((,c :foreground ,cyan-faint)))
`(all-the-icons-dgreen ((,c :foreground ,green-faint)))
@@ -1834,7 +1849,7 @@ FG and BG are the main colors."
`(all-the-icons-dorange ((,c :foreground ,red-faint)))
`(all-the-icons-dpink ((,c :foreground ,magenta-faint)))
`(all-the-icons-dpurple ((,c :foreground ,magenta-cooler)))
- `(all-the-icons-dred ((,c :foreground ,red-faint)))
+ `(all-the-icons-dred ((,c :foreground ,red)))
`(all-the-icons-dsilver ((,c :foreground ,cyan-faint)))
`(all-the-icons-dyellow ((,c :foreground ,yellow-faint)))
`(all-the-icons-green ((,c :foreground ,green)))
@@ -1845,12 +1860,18 @@ FG and BG are the main colors."
`(all-the-icons-lorange ((,c :foreground ,red-warmer)))
`(all-the-icons-lpink ((,c :foreground ,magenta)))
`(all-the-icons-lpurple ((,c :foreground ,magenta-faint)))
- `(all-the-icons-lred ((,c :foreground ,red)))
+ `(all-the-icons-lred ((,c :foreground ,red-faint)))
+ `(all-the-icons-lsilver ((,c :foreground "gray50")))
`(all-the-icons-lyellow ((,c :foreground ,yellow-warmer)))
- `(all-the-icons-maroon ((,c :foreground ,yellow-cooler)))
- `(all-the-icons-red ((,c :foreground ,red-intense)))
- `(all-the-icons-red-warmer ((,c :foreground ,red-cooler)))
- `(all-the-icons-yellow ((,c :foreground ,yellow-intense)))
+ `(all-the-icons-maroon ((,c :foreground ,magenta)))
+ `(all-the-icons-orange ((,c :foreground ,yellow-warmer)))
+ `(all-the-icons-pink ((,c :foreground ,magenta-warmer)))
+ `(all-the-icons-purple ((,c :foreground ,magenta-cooler)))
+ `(all-the-icons-purple-alt ((,c :foreground ,blue-warmer)))
+ `(all-the-icons-red ((,c :foreground ,red)))
+ `(all-the-icons-red-alt ((,c :foreground ,red-cooler)))
+ `(all-the-icons-silver ((,c :foreground "gray50")))
+ `(all-the-icons-yellow ((,c :foreground ,yellow)))
;;;;; all-the-icons-dired
`(all-the-icons-dired-dir-face ((,c :foreground ,cyan-faint)))
;;;;; all-the-icons-ibuffer
@@ -1865,23 +1886,23 @@ FG and BG are the main colors."
`(annotate-highlight-secondary ((,c :background ,bg-magenta-subtle :underline ,magenta-intense)))
;;;;; ansi-color
;; Those are in Emacs28.
- `(ansi-color-black ((,c :background "black" :foreground "black")))
- `(ansi-color-blue ((,c :background ,blue :foreground ,blue)))
+ `(ansi-color-black ((,c :background ,bg-term-black :foreground ,fg-term-black)))
+ `(ansi-color-blue ((,c :background ,bg-term-blue :foreground ,fg-term-blue)))
`(ansi-color-bold ((,c :inherit bold)))
- `(ansi-color-bright-black ((,c :background "gray35" :foreground "gray35")))
- `(ansi-color-bright-blue ((,c :background ,blue-warmer :foreground ,blue-warmer)))
- `(ansi-color-bright-cyan ((,c :background ,cyan-cooler :foreground ,cyan-cooler)))
- `(ansi-color-bright-green ((,c :background ,green-cooler :foreground ,green-cooler)))
- `(ansi-color-bright-magenta ((,c :background ,magenta-cooler :foreground ,magenta-cooler)))
- `(ansi-color-bright-red ((,c :background ,red-warmer :foreground ,red-warmer)))
- `(ansi-color-bright-white ((,c :background "white" :foreground "white")))
- `(ansi-color-bright-yellow ((,c :background ,yellow-warmer :foreground ,yellow-warmer)))
- `(ansi-color-cyan ((,c :background ,cyan :foreground ,cyan)))
- `(ansi-color-green ((,c :background ,green :foreground ,green)))
- `(ansi-color-magenta ((,c :background ,magenta :foreground ,magenta)))
- `(ansi-color-red ((,c :background ,red :foreground ,red)))
- `(ansi-color-white ((,c :background "gray65" :foreground "gray65")))
- `(ansi-color-yellow ((,c :background ,yellow :foreground ,yellow)))
+ `(ansi-color-bright-black ((,c :background ,bg-term-black-bright :foreground ,fg-term-black-bright)))
+ `(ansi-color-bright-blue ((,c :background ,bg-term-blue-bright :foreground ,fg-term-blue-bright)))
+ `(ansi-color-bright-cyan ((,c :background ,bg-term-cyan-bright :foreground ,fg-term-cyan-bright)))
+ `(ansi-color-bright-green ((,c :background ,bg-term-green-bright :foreground ,fg-term-green-bright)))
+ `(ansi-color-bright-magenta ((,c :background ,bg-term-magenta-bright :foreground ,fg-term-magenta-bright)))
+ `(ansi-color-bright-red ((,c :background ,bg-term-red-bright :foreground ,fg-term-red-bright)))
+ `(ansi-color-bright-white ((,c :background ,bg-term-white-bright :foreground ,fg-term-white-bright)))
+ `(ansi-color-bright-yellow ((,c :background ,bg-term-yellow-bright :foreground ,fg-term-yellow-bright)))
+ `(ansi-color-cyan ((,c :background ,bg-term-cyan :foreground ,fg-term-cyan)))
+ `(ansi-color-green ((,c :background ,bg-term-green :foreground ,fg-term-green)))
+ `(ansi-color-magenta ((,c :background ,bg-term-magenta :foreground ,fg-term-magenta)))
+ `(ansi-color-red ((,c :background ,bg-term-red :foreground ,fg-term-red)))
+ `(ansi-color-white ((,c :background ,bg-term-white :foreground ,fg-term-white)))
+ `(ansi-color-yellow ((,c :background ,bg-term-yellow :foreground ,fg-term-yellow)))
;;;;; anzu
`(anzu-match-1 ((,c :inherit modus-themes-subtle-cyan)))
`(anzu-match-2 ((,c :inherit modus-themes-search-current)))
@@ -1932,6 +1953,10 @@ FG and BG are the main colors."
`(binder-sidebar-marked ((,c :inherit modus-themes-mark-sel)))
`(binder-sidebar-missing ((,c :inherit modus-themes-mark-del)))
`(binder-sidebar-tags ((,c :foreground ,variable)))
+;;;;; breadcrumb
+ `(breadcrumb-face ((,c :foreground ,fg-alt)))
+ `(breadcrumb-imenu-leaf-face ((,c :inherit bold :foreground ,modeline-info))) ; same as `which-func'
+ `(breadcrumb-project-leaf-face ((,c :inherit bold)))
;;;;; bongo
`(bongo-album-title (( )))
`(bongo-artist ((,c :foreground ,accent-0)))
@@ -2009,7 +2034,7 @@ FG and BG are the main colors."
`(change-log-name ((,c :foreground ,name)))
`(log-edit-header ((,c :inherit bold)))
`(log-edit-headers-separator ((,c :height 1 :background ,border :extend t)))
- `(log-edit-summary ((,c :inherit bold :foreground ,blue)))
+ `(log-edit-summary ((,c :inherit success)))
`(log-edit-unknown-header ((,c :inherit shadow)))
`(log-view-commit-body (( )))
`(log-view-file ((,c :inherit bold)))
@@ -2084,6 +2109,8 @@ FG and BG are the main colors."
`(corfu-bar ((,c :background ,fg-dim)))
`(corfu-border ((,c :background ,bg-active)))
`(corfu-default ((,c :background ,bg-dim)))
+;;;;; corfu-candidate-overlay
+ `(corfu-candidate-overlay-face ((t :inherit shadow)))
;;;;; corfu-quick
`(corfu-quick1 ((,c :inherit bold :background ,bg-char-0)))
`(corfu-quick2 ((,c :inherit bold :background ,bg-char-1)))
@@ -2104,9 +2131,6 @@ FG and BG are the main colors."
`(crontab-month ((,c :foreground ,constant)))
`(crontab-week-day ((,c :foreground ,variable)))
`(crontab-predefined ((,c :foreground ,string)))
-;;;;; css-mode
- `(css-property ((,c :inherit font-lock-type-face)))
- `(css-selector ((,c :inherit font-lock-keyword-face)))
;;;;; csv-mode
`(csv-separator-face ((,c :foreground ,red-intense)))
;;;;; ctrlf
@@ -2413,6 +2437,11 @@ FG and BG are the main colors."
;;;;; ert
`(ert-test-result-expected ((,c :inherit modus-themes-prominent-note)))
`(ert-test-result-unexpected ((,c :inherit modus-themes-prominent-error)))
+;;;;; erts-mode
+ `(erts-mode-end-test ((,c :inherit error)))
+ `(erts-mode-specification-name ((,c :inherit bold)))
+ `(erts-mode-specification-value ((,c :foreground ,string)))
+ `(erts-mode-start-test ((,c :inherit success)))
;;;;; eshell
`(eshell-ls-archive ((,c :foreground ,accent-2)))
`(eshell-ls-backup ((,c :inherit shadow)))
@@ -2524,7 +2553,7 @@ FG and BG are the main colors."
`(git-commit-keyword ((,c :foreground ,keyword)))
`(git-commit-nonempty-second-line ((,c :inherit error)))
`(git-commit-overlong-summary ((,c :inherit warning)))
- `(git-commit-summary ((,c :inherit bold :foreground ,blue)))
+ `(git-commit-summary ((,c :inherit success)))
;;;;; git-gutter
`(git-gutter:added ((,c :background ,bg-added-fringe)))
`(git-gutter:deleted ((,c :background ,bg-removed-fringe)))
@@ -2799,6 +2828,8 @@ FG and BG are the main colors."
;;;;; ivy-posframe
`(ivy-posframe-border ((,c :background ,border)))
`(ivy-posframe-cursor ((,c :background ,fg-main :foreground ,bg-main)))
+;;;;; japanese-holidays
+ `(japanese-holiday-saturday ((,c :foreground ,date-holiday-other)))
;;;;; jira (org-jira)
`(jiralib-comment-face ((,c :background ,bg-inactive)))
`(jiralib-comment-header-face ((,c :inherit bold)))
@@ -3127,6 +3158,50 @@ FG and BG are the main colors."
`(mc/cursor-bar-face ((,c :height 1 :foreground ,fg-main :background ,bg-main)))
`(mc/cursor-face ((,c :inverse-video t)))
`(mc/region-face ((,c :inherit region)))
+;;;;; nerd-icons
+ `(nerd-icons-blue ((,c :foreground ,blue-cooler)))
+ `(nerd-icons-blue-alt ((,c :foreground ,blue-warmer)))
+ `(nerd-icons-cyan ((,c :foreground ,cyan)))
+ `(nerd-icons-cyan-alt ((,c :foreground ,cyan-warmer)))
+ `(nerd-icons-dblue ((,c :foreground ,blue-faint)))
+ `(nerd-icons-dcyan ((,c :foreground ,cyan-faint)))
+ `(nerd-icons-dgreen ((,c :foreground ,green-faint)))
+ `(nerd-icons-dmaroon ((,c :foreground ,magenta-faint)))
+ `(nerd-icons-dorange ((,c :foreground ,red-faint)))
+ `(nerd-icons-dpink ((,c :foreground ,magenta-faint)))
+ `(nerd-icons-dpurple ((,c :foreground ,magenta-cooler)))
+ `(nerd-icons-dred ((,c :foreground ,red)))
+ `(nerd-icons-dsilver ((,c :foreground ,cyan-faint)))
+ `(nerd-icons-dyellow ((,c :foreground ,yellow-faint)))
+ `(nerd-icons-green ((,c :foreground ,green)))
+ `(nerd-icons-lblue ((,c :foreground ,blue-cooler)))
+ `(nerd-icons-lcyan ((,c :foreground ,cyan)))
+ `(nerd-icons-lgreen ((,c :foreground ,green-warmer)))
+ `(nerd-icons-lmaroon ((,c :foreground ,magenta-warmer)))
+ `(nerd-icons-lorange ((,c :foreground ,red-warmer)))
+ `(nerd-icons-lpink ((,c :foreground ,magenta)))
+ `(nerd-icons-lpurple ((,c :foreground ,magenta-faint)))
+ `(nerd-icons-lred ((,c :foreground ,red-faint)))
+ `(nerd-icons-lsilver ((,c :foreground "gray50")))
+ `(nerd-icons-lyellow ((,c :foreground ,yellow-warmer)))
+ `(nerd-icons-maroon ((,c :foreground ,magenta)))
+ `(nerd-icons-orange ((,c :foreground ,yellow-warmer)))
+ `(nerd-icons-pink ((,c :foreground ,magenta-warmer)))
+ `(nerd-icons-purple ((,c :foreground ,magenta-cooler)))
+ `(nerd-icons-purple-alt ((,c :foreground ,blue-warmer)))
+ `(nerd-icons-red ((,c :foreground ,red)))
+ `(nerd-icons-red-alt ((,c :foreground ,red-cooler)))
+ `(nerd-icons-silver ((,c :foreground "gray50")))
+ `(nerd-icons-yellow ((,c :foreground ,yellow)))
+;;;;; nerd-icons-completion
+ `(nerd-icons-completion-dir-face ((,c :foreground ,cyan-faint)))
+;;;;; nerd-icons-dired
+ `(nerd-icons-dired-dir-face ((,c :foreground ,cyan-faint)))
+;;;;; nerd-icons-ibuffer
+ `(nerd-icons-ibuffer-dir-face ((,c :foreground ,cyan-faint)))
+ `(nerd-icons-ibuffer-file-face ((,c :foreground ,blue-faint)))
+ `(nerd-icons-ibuffer-mode-face ((,c :foreground ,cyan)))
+ `(nerd-icons-ibuffer-size-face ((,c :foreground ,cyan-cooler)))
;;;;; neotree
`(neo-banner-face ((,c :foreground ,accent-0)))
`(neo-button-face ((,c :inherit button)))
@@ -3247,7 +3322,7 @@ FG and BG are the main colors."
`(org-date ((,c :inherit modus-themes-fixed-pitch :foreground ,date-common)))
`(org-date-selected ((,c :foreground ,date-common :inverse-video t)))
`(org-document-info ((,c :foreground ,prose-metadata-value)))
- `(org-document-info-keyword ((,c :foreground ,prose-metadata)))
+ `(org-document-info-keyword ((,c :inherit modus-themes-fixed-pitch :foreground ,prose-metadata)))
`(org-document-title ((,c :inherit modus-themes-heading-0)))
`(org-done ((,c :foreground ,prose-done)))
`(org-drawer ((,c :inherit modus-themes-fixed-pitch :foreground ,prose-metadata)))
@@ -3707,16 +3782,19 @@ FG and BG are the main colors."
`(terraform--resource-name-face ((,c :foreground ,keyword)))
`(terraform--resource-type-face ((,c :foreground ,type)))
;;;;; term
+ ;; NOTE 2023-08-10: `term-color-black' and `term-color-white' use
+ ;; the "bright" semantic color mappings to make sure they are
+ ;; distinct from `term'.
`(term ((,c :background ,bg-main :foreground ,fg-main)))
`(term-bold ((,c :inherit bold)))
- `(term-color-black ((,c :background "gray35" :foreground "gray35")))
- `(term-color-blue ((,c :background ,blue :foreground ,blue)))
- `(term-color-cyan ((,c :background ,cyan :foreground ,cyan)))
- `(term-color-green ((,c :background ,green :foreground ,green)))
- `(term-color-magenta ((,c :background ,magenta :foreground ,magenta)))
- `(term-color-red ((,c :background ,red :foreground ,red)))
- `(term-color-white ((,c :background "gray65" :foreground "gray65")))
- `(term-color-yellow ((,c :background ,yellow :foreground ,yellow)))
+ `(term-color-black ((,c :background ,bg-term-black-bright :foreground ,fg-term-black-bright)))
+ `(term-color-blue ((,c :background ,bg-term-blue :foreground ,fg-term-blue)))
+ `(term-color-cyan ((,c :background ,bg-term-cyan :foreground ,fg-term-cyan)))
+ `(term-color-green ((,c :background ,bg-term-green :foreground ,fg-term-green)))
+ `(term-color-magenta ((,c :background ,bg-term-magenta :foreground ,fg-term-magenta)))
+ `(term-color-red ((,c :background ,bg-term-red :foreground ,fg-term-red)))
+ `(term-color-white ((,c :background ,bg-term-white-bright :foreground ,fg-term-white-bright)))
+ `(term-color-yellow ((,c :background ,bg-term-yellow :foreground ,fg-term-yellow)))
`(term-underline ((,c :underline t)))
;;;;; textsec
`(textsec-suspicious (( )))
@@ -3847,17 +3925,20 @@ FG and BG are the main colors."
`(vr/match-1 ((,c :inherit modus-themes-intense-yellow)))
`(vr/match-separator-face ((,c :inherit bold :background ,bg-active)))
;;;;; vterm
- `(vterm-color-black ((,c :background "gray35" :foreground "black")))
- `(vterm-color-blue ((,c :background ,blue-warmer :foreground ,blue)))
- `(vterm-color-cyan ((,c :background ,cyan-cooler :foreground ,cyan)))
+ ;; NOTE 2023-08-10: `vterm-color-black' and `vterm-color-white'
+ ;; use the "bright" semantic color mappings to make sure they are
+ ;; distinct from `vterm-color-default'.
+ `(vterm-color-black ((,c :background ,bg-term-black :foreground ,fg-term-black)))
+ `(vterm-color-blue ((,c :background ,bg-term-blue :foreground ,fg-term-blue)))
+ `(vterm-color-cyan ((,c :background ,bg-term-cyan :foreground ,fg-term-cyan)))
`(vterm-color-default ((,c :background ,bg-main :foreground ,fg-main)))
- `(vterm-color-green ((,c :background ,green-cooler :foreground ,green)))
+ `(vterm-color-green ((,c :background ,bg-term-green :foreground ,fg-term-green)))
`(vterm-color-inverse-video ((,c :background ,bg-main :inverse-video t)))
- `(vterm-color-magenta ((,c :background ,magenta-cooler :foreground ,magenta)))
- `(vterm-color-red ((,c :background ,red-warmer :foreground ,red)))
+ `(vterm-color-magenta ((,c :background ,bg-term-magenta :foreground ,fg-term-magenta)))
+ `(vterm-color-red ((,c :background ,bg-term-red :foreground ,fg-term-red)))
`(vterm-color-underline ((,c :underline t)))
- `(vterm-color-white ((,c :background "white" :foreground "gray65")))
- `(vterm-color-yellow ((,c :background ,yellow-warmer :foreground ,yellow)))
+ `(vterm-color-white ((,c :background ,bg-term-white :foreground ,fg-term-white)))
+ `(vterm-color-yellow ((,c :background ,bg-term-yellow :foreground ,fg-term-yellow)))
;;;;; vundo
`(vundo-default ((,c :inherit shadow)))
`(vundo-highlight ((,c :inherit (bold vundo-node) :foreground ,red)))
@@ -3941,7 +4022,7 @@ FG and BG are the main colors."
`(wgrep-file-face ((,c :foreground ,fg-alt)))
`(wgrep-reject-face ((,c :inherit error)))
;;;;; which-function-mode
- `(which-func ((,c :inherit bold :foreground ,modeline-info)))
+ `(which-func ((,c :inherit bold :foreground ,modeline-info))) ; same as `breadcrumb-imenu-leaf-face'
;;;;; which-key
`(which-key-command-description-face ((,c :foreground ,fg-main)))
`(which-key-group-description-face ((,c :foreground ,keyword)))
diff --git a/etc/themes/modus-vivendi-deuteranopia-theme.el b/etc/themes/modus-vivendi-deuteranopia-theme.el
index 60c3c62b38f..62715e20e51 100644
--- a/etc/themes/modus-vivendi-deuteranopia-theme.el
+++ b/etc/themes/modus-vivendi-deuteranopia-theme.el
@@ -1,6 +1,6 @@
;;; modus-vivendi-deuteranopia-theme.el --- Deuteranopia-optimized theme with a black background -*- lexical-binding:t -*-
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
;; Author: Protesilaos Stavrou <info@protesilaos.com>
;; Maintainer: Modus-Themes Development <~protesilaos/modus-themes@lists.sr.ht>
@@ -42,6 +42,7 @@
(require-theme 'modus-themes t))
(require 'modus-themes))
+;;;###theme-autoload
(deftheme modus-vivendi-deuteranopia
"Deuteranopia-optimized theme with a black background.
This variant is optimized for users with red-green color
@@ -49,7 +50,10 @@ deficiency (deuteranopia). It conforms with the highest
legibility standard for color contrast between background and
foreground in any given piece of text, which corresponds to a
minimum contrast in relative luminance of 7:1 (WCAG AAA
-standard).")
+standard)."
+ :background-mode 'dark
+ :kind 'color-scheme
+ :family 'modus)
(defconst modus-vivendi-deuteranopia-palette
'(
@@ -154,7 +158,7 @@ standard).")
;;; Special purpose
(bg-completion "#2f447f")
- (bg-hover "#004f70")
+ (bg-hover "#45605e")
(bg-hover-secondary "#654a39")
(bg-hl-line "#2f3849")
(bg-region "#5a5a5a")
@@ -197,7 +201,7 @@ standard).")
(bg-removed "#3d3d00")
(bg-removed-faint "#281f00")
- (bg-removed-refine "#515100")
+ (bg-removed-refine "#555500")
(bg-removed-fringe "#d0c03f")
(fg-removed "#d4d48f")
(fg-removed-intense "#d0b05f")
@@ -283,6 +287,7 @@ standard).")
(date-deadline yellow-warmer)
(date-event fg-alt)
(date-holiday yellow-warmer)
+ (date-holiday-other blue)
(date-now blue-faint)
(date-range fg-alt)
(date-scheduled yellow-cooler)
@@ -366,6 +371,48 @@ standard).")
(fg-space border)
(bg-space-err bg-yellow-intense)
+;;;; Terminal mappings
+
+ (bg-term-black "black")
+ (fg-term-black "black")
+ (bg-term-black-bright "gray35")
+ (fg-term-black-bright "gray35")
+
+ (bg-term-red red)
+ (fg-term-red red)
+ (bg-term-red-bright red-warmer)
+ (fg-term-red-bright red-warmer)
+
+ (bg-term-green green)
+ (fg-term-green green)
+ (bg-term-green-bright green-cooler)
+ (fg-term-green-bright green-cooler)
+
+ (bg-term-yellow yellow)
+ (fg-term-yellow yellow)
+ (bg-term-yellow-bright yellow-warmer)
+ (fg-term-yellow-bright yellow-warmer)
+
+ (bg-term-blue blue)
+ (fg-term-blue blue)
+ (bg-term-blue-bright blue-warmer)
+ (fg-term-blue-bright blue-warmer)
+
+ (bg-term-magenta magenta)
+ (fg-term-magenta magenta)
+ (bg-term-magenta-bright magenta-cooler)
+ (fg-term-magenta-bright magenta-cooler)
+
+ (bg-term-cyan cyan)
+ (fg-term-cyan cyan)
+ (bg-term-cyan-bright cyan-cooler)
+ (fg-term-cyan-bright cyan-cooler)
+
+ (bg-term-white "gray65")
+ (fg-term-white "gray65")
+ (bg-term-white-bright "white")
+ (fg-term-white-bright "white")
+
;;;; Heading mappings
(fg-heading-0 cyan-cooler)
@@ -435,7 +482,4 @@ represents."
(provide-theme 'modus-vivendi-deuteranopia))
-;;;###theme-autoload
-(put 'modus-vivendi-deuteranopia 'theme-properties '(:background-mode dark :kind color-scheme :family modus))
-
;;; modus-vivendi-deuteranopia-theme.el ends here
diff --git a/etc/themes/modus-vivendi-theme.el b/etc/themes/modus-vivendi-theme.el
index 70dd0f78675..238484206bb 100644
--- a/etc/themes/modus-vivendi-theme.el
+++ b/etc/themes/modus-vivendi-theme.el
@@ -1,6 +1,6 @@
;;; modus-vivendi-theme.el --- Elegant, highly legible theme with a black background -*- lexical-binding:t -*-
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
;; Author: Protesilaos Stavrou <info@protesilaos.com>
;; Maintainer: Modus-Themes Development <~protesilaos/modus-themes@lists.sr.ht>
@@ -42,12 +42,16 @@
(require-theme 'modus-themes t))
(require 'modus-themes))
+;;;###theme-autoload
(deftheme modus-vivendi
"Elegant, highly legible theme with a black background.
Conforms with the highest legibility standard for color contrast
between background and foreground in any given piece of text,
which corresponds to a minimum contrast in relative luminance of
-7:1 (WCAG AAA standard).")
+7:1 (WCAG AAA standard)."
+ :background-mode 'dark
+ :kind 'color-scheme
+ :family 'modus)
(defconst modus-vivendi-palette
'(
@@ -152,7 +156,7 @@ which corresponds to a minimum contrast in relative luminance of
;;; Special purpose
(bg-completion "#2f447f")
- (bg-hover "#004f70")
+ (bg-hover "#45605e")
(bg-hover-secondary "#654a39")
(bg-hl-line "#2f3849")
(bg-region "#5a5a5a")
@@ -281,6 +285,7 @@ which corresponds to a minimum contrast in relative luminance of
(date-deadline red)
(date-event fg-alt)
(date-holiday red-cooler)
+ (date-holiday-other blue)
(date-now fg-main)
(date-range fg-alt)
(date-scheduled yellow-warmer)
@@ -364,6 +369,48 @@ which corresponds to a minimum contrast in relative luminance of
(fg-space border)
(bg-space-err bg-red-intense)
+;;;; Terminal mappings
+
+ (bg-term-black "black")
+ (fg-term-black "black")
+ (bg-term-black-bright "gray35")
+ (fg-term-black-bright "gray35")
+
+ (bg-term-red red)
+ (fg-term-red red)
+ (bg-term-red-bright red-warmer)
+ (fg-term-red-bright red-warmer)
+
+ (bg-term-green green)
+ (fg-term-green green)
+ (bg-term-green-bright green-cooler)
+ (fg-term-green-bright green-cooler)
+
+ (bg-term-yellow yellow)
+ (fg-term-yellow yellow)
+ (bg-term-yellow-bright yellow-warmer)
+ (fg-term-yellow-bright yellow-warmer)
+
+ (bg-term-blue blue)
+ (fg-term-blue blue)
+ (bg-term-blue-bright blue-warmer)
+ (fg-term-blue-bright blue-warmer)
+
+ (bg-term-magenta magenta)
+ (fg-term-magenta magenta)
+ (bg-term-magenta-bright magenta-cooler)
+ (fg-term-magenta-bright magenta-cooler)
+
+ (bg-term-cyan cyan)
+ (fg-term-cyan cyan)
+ (bg-term-cyan-bright cyan-cooler)
+ (fg-term-cyan-bright cyan-cooler)
+
+ (bg-term-white "gray65")
+ (fg-term-white "gray65")
+ (bg-term-white-bright "white")
+ (fg-term-white-bright "white")
+
;;;; Heading mappings
(fg-heading-0 cyan-cooler)
@@ -434,7 +481,4 @@ represents."
(provide-theme 'modus-vivendi))
-;;;###theme-autoload
-(put 'modus-vivendi 'theme-properties '(:background-mode dark :kind color-scheme :family modus))
-
;;; modus-vivendi-theme.el ends here
diff --git a/etc/themes/modus-vivendi-tinted-theme.el b/etc/themes/modus-vivendi-tinted-theme.el
index b6443bdf6cc..025257ef01c 100644
--- a/etc/themes/modus-vivendi-tinted-theme.el
+++ b/etc/themes/modus-vivendi-tinted-theme.el
@@ -1,6 +1,6 @@
;;; modus-vivendi-tinted-theme.el --- Elegant, highly legible theme with a night sky background -*- lexical-binding:t -*-
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
;; Author: Protesilaos Stavrou <info@protesilaos.com>
;; Maintainer: Modus-Themes Development <~protesilaos/modus-themes@lists.sr.ht>
@@ -42,12 +42,16 @@
(require-theme 'modus-themes t))
(require 'modus-themes))
+;;;###theme-autoload
(deftheme modus-vivendi-tinted
"Elegant, highly legible theme with a night sky background.
Conforms with the highest legibility standard for color contrast
between background and foreground in any given piece of text,
which corresponds to a minimum contrast in relative luminance of
-7:1 (WCAG AAA standard).")
+7:1 (WCAG AAA standard)."
+ :background-mode 'dark
+ :kind 'color-scheme
+ :family 'modus)
(defconst modus-vivendi-tinted-palette
'(
@@ -146,7 +150,7 @@ which corresponds to a minimum contrast in relative luminance of
;;; Special purpose
(bg-completion "#483d8a")
- (bg-hover "#004f70")
+ (bg-hover "#45605e")
(bg-hover-secondary "#654a39")
(bg-hl-line "#303a6f")
(bg-region "#555a66")
@@ -281,6 +285,7 @@ which corresponds to a minimum contrast in relative luminance of
(date-deadline red)
(date-event fg-alt)
(date-holiday red-cooler)
+ (date-holiday-other blue)
(date-now fg-main)
(date-range fg-alt)
(date-scheduled yellow-warmer)
@@ -364,6 +369,48 @@ which corresponds to a minimum contrast in relative luminance of
(bg-space unspecified)
(fg-space border)
+;;;; Terminal mappings
+
+ (bg-term-black "black")
+ (fg-term-black "black")
+ (bg-term-black-bright "gray35")
+ (fg-term-black-bright "gray35")
+
+ (bg-term-red red)
+ (fg-term-red red)
+ (bg-term-red-bright red-warmer)
+ (fg-term-red-bright red-warmer)
+
+ (bg-term-green green)
+ (fg-term-green green)
+ (bg-term-green-bright green-cooler)
+ (fg-term-green-bright green-cooler)
+
+ (bg-term-yellow yellow)
+ (fg-term-yellow yellow)
+ (bg-term-yellow-bright yellow-warmer)
+ (fg-term-yellow-bright yellow-warmer)
+
+ (bg-term-blue blue)
+ (fg-term-blue blue)
+ (bg-term-blue-bright blue-warmer)
+ (fg-term-blue-bright blue-warmer)
+
+ (bg-term-magenta magenta)
+ (fg-term-magenta magenta)
+ (bg-term-magenta-bright magenta-cooler)
+ (fg-term-magenta-bright magenta-cooler)
+
+ (bg-term-cyan cyan)
+ (fg-term-cyan cyan)
+ (bg-term-cyan-bright cyan-cooler)
+ (fg-term-cyan-bright cyan-cooler)
+
+ (bg-term-white "gray65")
+ (fg-term-white "gray65")
+ (bg-term-white-bright "white")
+ (fg-term-white-bright "white")
+
;;;; Heading mappings
(fg-heading-0 cyan-cooler)
@@ -433,7 +480,4 @@ represents."
(provide-theme 'modus-vivendi-tinted))
-;;;###theme-autoload
-(put 'modus-vivendi-tinted 'theme-properties '(:background-mode dark :kind color-scheme :family modus))
-
;;; modus-vivendi-tinted-theme.el ends here
diff --git a/etc/themes/modus-vivendi-tritanopia-theme.el b/etc/themes/modus-vivendi-tritanopia-theme.el
index 0d09989e2a7..bfd6d63b844 100644
--- a/etc/themes/modus-vivendi-tritanopia-theme.el
+++ b/etc/themes/modus-vivendi-tritanopia-theme.el
@@ -1,11 +1,12 @@
;;; modus-vivendi-tritanopia-theme.el --- Tritanopia-optimized theme with a black background -*- lexical-binding:t -*-
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
;; Author: Protesilaos Stavrou <info@protesilaos.com>
;; Maintainer: Modus-Themes Development <~protesilaos/modus-themes@lists.sr.ht>
;; URL: https://git.sr.ht/~protesilaos/modus-themes
;; Mailing-List: https://lists.sr.ht/~protesilaos/modus-themes
+;; Keywords: faces, theme, accessibility
;; This file is part of GNU Emacs.
@@ -42,6 +43,7 @@
(require-theme 'modus-themes t))
(require 'modus-themes))
+;;;###theme-autoload
(deftheme modus-vivendi-tritanopia
"Tritanopia-optimized theme with a black background.
This variant is optimized for users with blue-yellow color
@@ -49,7 +51,10 @@ deficiency (tritanopia). It conforms with the highest
legibility standard for color contrast between background and
foreground in any given piece of text, which corresponds to a
minimum contrast in relative luminance of 7:1 (WCAG AAA
-standard).")
+standard)."
+ :background-mode 'dark
+ :kind 'color-scheme
+ :family 'modus)
(defconst modus-vivendi-tritanopia-palette
'(
@@ -161,8 +166,8 @@ standard).")
(fg-region "#ffffff")
(bg-char-0 "#922a00")
- (bg-char-1 "#4f3f7f")
- (bg-char-2 "#00709f")
+ (bg-char-1 "#00709f")
+ (bg-char-2 "#5f3faf")
(bg-mode-line-active "#003c52")
(fg-mode-line-active "#f0f0f0")
@@ -283,6 +288,7 @@ standard).")
(date-deadline red)
(date-event fg-alt)
(date-holiday red-intense)
+ (date-holiday-other cyan-warmer)
(date-now fg-main)
(date-range fg-alt)
(date-scheduled magenta)
@@ -366,6 +372,48 @@ standard).")
(fg-space border)
(bg-space-err bg-red-intense)
+;;;; Terminal mappings
+
+ (bg-term-black "black")
+ (fg-term-black "black")
+ (bg-term-black-bright "gray35")
+ (fg-term-black-bright "gray35")
+
+ (bg-term-red red)
+ (fg-term-red red)
+ (bg-term-red-bright red-warmer)
+ (fg-term-red-bright red-warmer)
+
+ (bg-term-green green)
+ (fg-term-green green)
+ (bg-term-green-bright green-cooler)
+ (fg-term-green-bright green-cooler)
+
+ (bg-term-yellow yellow)
+ (fg-term-yellow yellow)
+ (bg-term-yellow-bright yellow-warmer)
+ (fg-term-yellow-bright yellow-warmer)
+
+ (bg-term-blue blue)
+ (fg-term-blue blue)
+ (bg-term-blue-bright blue-warmer)
+ (fg-term-blue-bright blue-warmer)
+
+ (bg-term-magenta magenta)
+ (fg-term-magenta magenta)
+ (bg-term-magenta-bright magenta-cooler)
+ (fg-term-magenta-bright magenta-cooler)
+
+ (bg-term-cyan cyan)
+ (fg-term-cyan cyan)
+ (bg-term-cyan-bright cyan-cooler)
+ (fg-term-cyan-bright cyan-cooler)
+
+ (bg-term-white "gray65")
+ (fg-term-white "gray65")
+ (bg-term-white-bright "white")
+ (fg-term-white-bright "white")
+
;;;; Heading mappings
(fg-heading-0 cyan-cooler)
@@ -435,7 +483,4 @@ represents."
(provide-theme 'modus-vivendi-tritanopia))
-;;;###theme-autoload
-(put 'modus-vivendi-tritanopia 'theme-properties '(:background-mode dark :kind color-scheme :family modus))
-
;;; modus-vivendi-tritanopia-theme.el ends here
diff --git a/etc/themes/tango-dark-theme.el b/etc/themes/tango-dark-theme.el
index e79c14d734f..a744ec2fc32 100644
--- a/etc/themes/tango-dark-theme.el
+++ b/etc/themes/tango-dark-theme.el
@@ -1,6 +1,6 @@
;;; tango-dark-theme.el --- Tango-based custom theme for faces -*- lexical-binding:t -*-
-;; Copyright (C) 2010-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2010-2024 Free Software Foundation, Inc.
;; Authors: Chong Yidong <cyd@stupidchicken>
;; Jan Moringen <jan.moringen@uni-bielefeld.de>
diff --git a/etc/themes/tango-theme.el b/etc/themes/tango-theme.el
index 4fecb60bc6e..63f869d281f 100644
--- a/etc/themes/tango-theme.el
+++ b/etc/themes/tango-theme.el
@@ -1,6 +1,6 @@
;;; tango-theme.el --- Tango-based custom theme for faces -*- lexical-binding:t -*-
-;; Copyright (C) 2010-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2010-2024 Free Software Foundation, Inc.
;; Authors: Chong Yidong <cyd@stupidchicken>
;; Jan Moringen <jan.moringen@uni-bielefeld.de>
diff --git a/etc/themes/tsdh-dark-theme.el b/etc/themes/tsdh-dark-theme.el
index 2451ee9666d..213cd8edb70 100644
--- a/etc/themes/tsdh-dark-theme.el
+++ b/etc/themes/tsdh-dark-theme.el
@@ -1,6 +1,6 @@
;;; tsdh-dark-theme.el --- Tassilo's dark custom theme -*- lexical-binding:t -*-
-;; Copyright (C) 2011-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2011-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/etc/themes/tsdh-light-theme.el b/etc/themes/tsdh-light-theme.el
index 4d11f5cc32f..5314f3c1b82 100644
--- a/etc/themes/tsdh-light-theme.el
+++ b/etc/themes/tsdh-light-theme.el
@@ -1,6 +1,6 @@
;;; tsdh-light-theme.el --- Tassilo's light custom theme -*- lexical-binding:t -*-
-;; Copyright (C) 2011-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2011-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/etc/themes/wheatgrass-theme.el b/etc/themes/wheatgrass-theme.el
index 812fd623f1a..9e785596c10 100644
--- a/etc/themes/wheatgrass-theme.el
+++ b/etc/themes/wheatgrass-theme.el
@@ -1,6 +1,6 @@
;;; wheatgrass-theme.el --- custom theme for faces -*- lexical-binding:t -*-
-;; Copyright (C) 2010-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2010-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/etc/themes/whiteboard-theme.el b/etc/themes/whiteboard-theme.el
index b52996c24c0..2db11fcb4b8 100644
--- a/etc/themes/whiteboard-theme.el
+++ b/etc/themes/whiteboard-theme.el
@@ -1,6 +1,6 @@
;;; whiteboard-theme.el --- Custom theme for faces -*- lexical-binding:t -*-
-;; Copyright (C) 2011-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2011-2024 Free Software Foundation, Inc.
;; Author: Scott Frazer <frazer.scott@gmail.com>
diff --git a/etc/themes/wombat-theme.el b/etc/themes/wombat-theme.el
index 5b8b4d19907..3399d637811 100644
--- a/etc/themes/wombat-theme.el
+++ b/etc/themes/wombat-theme.el
@@ -1,6 +1,6 @@
;;; wombat-theme.el --- Custom face theme for Emacs -*- lexical-binding:t -*-
-;; Copyright (C) 2011-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2011-2024 Free Software Foundation, Inc.
;; Author: Kristoffer Grönlund <krig@koru.se>
diff --git a/etc/tutorials/TUTORIAL b/etc/tutorials/TUTORIAL
index 4e6d7b9b287..4718e0d9430 100644
--- a/etc/tutorials/TUTORIAL
+++ b/etc/tutorials/TUTORIAL
@@ -1131,7 +1131,7 @@ starting with the one written by Stuart Cracraft for the original Emacs.
This version of the tutorial is a part of GNU Emacs. It is copyrighted
and comes with permission to distribute copies on certain conditions:
- Copyright (C) 1985, 1996, 1998, 2001-2023 Free Software Foundation,
+ Copyright (C) 1985, 1996, 1998, 2001-2024 Free Software Foundation,
Inc.
This file is part of GNU Emacs.
diff --git a/etc/tutorials/TUTORIAL.bg b/etc/tutorials/TUTORIAL.bg
index 60c1e07272d..c5b8c6dd983 100644
--- a/etc/tutorials/TUTORIAL.bg
+++ b/etc/tutorials/TUTORIAL.bg
@@ -1162,7 +1162,7 @@ Dired ви позволява да гледате списъка от файло
This version of the tutorial, like GNU Emacs, is copyrighted, and
comes with permission to distribute copies on certain conditions:
- Copyright (C) 1985, 1996, 1998, 2001-2023 Free Software Foundation,
+ Copyright (C) 1985, 1996, 1998, 2001-2024 Free Software Foundation,
Inc.
This file is part of GNU Emacs.
diff --git a/etc/tutorials/TUTORIAL.cn b/etc/tutorials/TUTORIAL.cn
index e4c90102f53..02d9aadd318 100644
--- a/etc/tutorials/TUTORIAL.cn
+++ b/etc/tutorials/TUTORIAL.cn
@@ -1026,7 +1026,7 @@ starting with the one written by Stuart Cracraft for the original Emacs.
This version of the tutorial is a part of GNU Emacs. It is copyrighted
and comes with permission to distribute copies on certain conditions:
- Copyright (C) 1985, 1996, 1998, 2001-2023 Free Software Foundation,
+ Copyright (C) 1985, 1996, 1998, 2001-2024 Free Software Foundation,
Inc.
This file is part of GNU Emacs.
@@ -1055,7 +1055,7 @@ using, writing, and sharing free software!
本篇指南是 GNU Emacs 的一部分,并允许在下列条件的约束下发行其拷贝:
- Copyright (C) 1985, 1996, 1998, 2001-2023 Free Software Foundation,
+ Copyright (C) 1985, 1996, 1998, 2001-2024 Free Software Foundation,
Inc.
本文件为 GNU Emacs 的一部分。
diff --git a/etc/tutorials/TUTORIAL.cs b/etc/tutorials/TUTORIAL.cs
index be3b92f8ffd..b2a709e6415 100644
--- a/etc/tutorials/TUTORIAL.cs
+++ b/etc/tutorials/TUTORIAL.cs
@@ -1015,7 +1015,7 @@ tutoriálem napsaným Stuartem Cracraftem pro původní Emacs.
Tato verze tutoriálu je, podobně jako GNU Emacs, chráněna copyrightem a
je šířena se svolením distribuovat kopie za jistých podmínek:
-Copyright (C) 1985, 1996, 1998, 2001-2023 Free Software Foundation, Inc.
+Copyright (C) 1985, 1996, 1998, 2001-2024 Free Software Foundation, Inc.
Každému je zaručeno právo vytvářet a distribuovat přesné kopie tohoto
dokumentu tak, jak jej obdržel, na jakémkoliv médiu, s tím, že bude
diff --git a/etc/tutorials/TUTORIAL.de b/etc/tutorials/TUTORIAL.de
index 03716dd7de4..c5a60185a70 100644
--- a/etc/tutorials/TUTORIAL.de
+++ b/etc/tutorials/TUTORIAL.de
@@ -1488,7 +1488,7 @@ Beachten Sie bitte, dass im Zweifelsfalle das englische Original
dieser Urheberrechtsnotiz gültig ist (zu finden in der Datei
TUTORIAL).
- Copyright (C) 1985, 1996-1997, 2001-2023 Free Software Foundation,
+ Copyright (C) 1985, 1996-1997, 2001-2024 Free Software Foundation,
Inc.
Diese Datei ist ein Bestandteil von GNU Emacs.
diff --git a/etc/tutorials/TUTORIAL.el_GR b/etc/tutorials/TUTORIAL.el_GR
index 33b87cb99e9..577010dae8b 100644
--- a/etc/tutorials/TUTORIAL.el_GR
+++ b/etc/tutorials/TUTORIAL.el_GR
@@ -1239,7 +1239,7 @@ list-packages. Στη σχετική λίστα, μπορείς να εγκατ
πνευματικά δικαιώματα και δίνεται με την άδεια διανομής αντιγράφων υπό
κάποιους όρους.
- Πνευματικά Δικαιώματα (C) 1985, 1996, 1998, 2001-2023 Free Software
+ Πνευματικά Δικαιώματα (C) 1985, 1996, 1998, 2001-2024 Free Software
Foundation, Inc.
Αυτό το αρχείο είναι μέρος του GNU Emacs.
diff --git a/etc/tutorials/TUTORIAL.eo b/etc/tutorials/TUTORIAL.eo
index a92edf267fe..01423a04f50 100644
--- a/etc/tutorials/TUTORIAL.eo
+++ b/etc/tutorials/TUTORIAL.eo
@@ -1081,7 +1081,7 @@ la dosiero verkita de Stuart Cracraft por la originala Emakso.
kopirajton, kaj venas kun permeso por disdoni kopiojn se certaj
kondiĉoj estas observataj:
- Copyright (C) 1985, 1999, 2001-2002, 2005, 2007-2023 Free Software
+ Copyright (C) 1985, 1999, 2001-2002, 2005, 2007-2024 Free Software
Foundation, Inc.
Ĉi tiu dosiero estas parto de "GNU Emacs".
diff --git a/etc/tutorials/TUTORIAL.es b/etc/tutorials/TUTORIAL.es
index b0d176d27cc..86944bf341e 100644
--- a/etc/tutorials/TUTORIAL.es
+++ b/etc/tutorials/TUTORIAL.es
@@ -1204,7 +1204,7 @@ Por favor, en caso de duda, solo es válido el original en inglés de la
siguiente nota de derechos de reproducción (que puede encontrar en el
archivo TUTORIAL).
-Copyright (C) 1985, 1996, 1998, 2001-2023 Free Software Foundation, Inc.
+Copyright (C) 1985, 1996, 1998, 2001-2024 Free Software Foundation, Inc.
Se permite a cualquiera hacer o distribuir copias literales de este
documento como se recibe, en cualquier medio, siempre que la nota
diff --git a/etc/tutorials/TUTORIAL.fa b/etc/tutorials/TUTORIAL.fa
index 1333b47cae2..e2afcbe638d 100644
--- a/etc/tutorials/TUTORIAL.fa
+++ b/etc/tutorials/TUTORIAL.fa
@@ -1131,7 +1131,8 @@ Stuart Cracraft سر چشمه گرفت.
این نسخه از آموزش بخشی از GNU Emacs است. دارای حق چاپ است
و با مجوز برای توزیع کپی در شرایط خاص همراه است:
- Copyright (C) 1985, 1996, 1998, 2001-2022 Free Software Foundation, Inc.
+ Copyright (C) 1985, 1996, 1998, 2001-2022, 2024 Free Software
+ Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/etc/tutorials/TUTORIAL.fr b/etc/tutorials/TUTORIAL.fr
index 1e4260acf0a..55a00f43e86 100644
--- a/etc/tutorials/TUTORIAL.fr
+++ b/etc/tutorials/TUTORIAL.fr
@@ -1202,7 +1202,7 @@ Cette version du didacticiel, comme GNU Emacs, est placée sous
droit d'auteur, et vous pouvez en distribuer des copies sous certaines
conditions :
-Copyright (C) 1985, 1996, 2001-2023 Free Software Foundation, Inc.
+Copyright (C) 1985, 1996, 2001-2024 Free Software Foundation, Inc.
Chacun peut créer ou distribuer des copies de ce document tel qu'il
l'a reçu, sur n'importe quel support, pourvu que la note de
diff --git a/etc/tutorials/TUTORIAL.he b/etc/tutorials/TUTORIAL.he
index 4257f94edcf..0a4222a6fdc 100644
--- a/etc/tutorials/TUTORIAL.he
+++ b/etc/tutorials/TUTORIAL.he
@@ -1015,7 +1015,7 @@ find-file.
גירסה זו של השיעור הינה חלק מחבילת GNU Emacs. היא מוגנת בזכויות יוצרים
וניתנת להעתקה והפצת עותקים בתנאים מסויימים כדלקמן:
- Copyright (C) 2010-2023 Free Software Foundation, Inc.
+ Copyright (C) 2010-2024 Free Software Foundation, Inc.
‏GNU Emacs הינו תכנה חפשית; זכותכם להפיצו ו\או לשנותו בכפוף לתנאי
הרשיון GNU General Public License, כפי שהוא יוצא לאור ע״י Free
diff --git a/etc/tutorials/TUTORIAL.it b/etc/tutorials/TUTORIAL.it
index f97446d01c6..0baa54a40ad 100644
--- a/etc/tutorials/TUTORIAL.it
+++ b/etc/tutorials/TUTORIAL.it
@@ -1219,7 +1219,7 @@ distribuito con il permesso di farne copie a determinate condizioni:
indicativo, restando comunque inteso il fatto che è quella
originale a fare fede.
-Copyright (C) 2003-2023 Free Software Foundation, Inc.
+Copyright (C) 2003-2024 Free Software Foundation, Inc.
È permesso a chiunque copiare e distribuire attraverso ogni mezzo
copie fedeli di questo documento così come viene ricevuto, a
diff --git a/etc/tutorials/TUTORIAL.ja b/etc/tutorials/TUTORIAL.ja
index eb77faf0cf2..7f18e251a0c 100644
--- a/etc/tutorials/TUTORIAL.ja
+++ b/etc/tutorials/TUTORIAL.ja
@@ -1062,7 +1062,7 @@ starting with the one written by Stuart Cracraft for the original Emacs.
This version of the tutorial, like GNU Emacs, is copyrighted, and
comes with permission to distribute copies on certain conditions:
-Copyright (C) 1985, 1996, 1998, 2001-2023 Free Software Foundation, Inc.
+Copyright (C) 1985, 1996, 1998, 2001-2024 Free Software Foundation, Inc.
Permission is granted to anyone to make or distribute verbatim copies
of this document as received, in any medium, provided that the
diff --git a/etc/tutorials/TUTORIAL.ko b/etc/tutorials/TUTORIAL.ko
index 8252a91e179..a8c97e8db9c 100644
--- a/etc/tutorials/TUTORIAL.ko
+++ b/etc/tutorials/TUTORIAL.ko
@@ -981,7 +981,7 @@ C-x C-s와 (META쇠나 EDIT쇠 혹은 교체쇠가 있으면) <ESC>v와 같은
GNU 이맥스와 같이 이 지침서 판은 저작권이 있으며 특정한 조건을 만족할
때에 복사본을 배포할 수 있는 허가를 갖고 나온 것이다:
-Copyright (C) 1985, 1996, 2001-2023 Free Software Foundation, Inc.
+Copyright (C) 1985, 1996, 2001-2024 Free Software Foundation, Inc.
이 문서는 이 저작권 공고와 허용 공고가 그대로 유지되고, 배포자가
수취자에게 이 공고에 따라 허용되는 것처럼 또 재분배하는 것을
diff --git a/etc/tutorials/TUTORIAL.nl b/etc/tutorials/TUTORIAL.nl
index ce777e29e4f..73acaba73e4 100644
--- a/etc/tutorials/TUTORIAL.nl
+++ b/etc/tutorials/TUTORIAL.nl
@@ -1209,7 +1209,7 @@ Deze versie van de inleiding is onderdeel van GNU Emacs. Het valt
onder copyright. Je mag deze inleiding verspreiden onder bepaalde
voorwaarden:
- Copyright (C) 1985, 1996, 1998, 2001-2023 Free Software Foundation,
+ Copyright (C) 1985, 1996, 1998, 2001-2024 Free Software Foundation,
Inc.
Dit bestand is onderdeel van GNU Emacs.
@@ -1239,7 +1239,7 @@ Engels origineel van de copyrightmelding en condities:
This version of the tutorial is a part of GNU Emacs. It is copyrighted
and comes with permission to distribute copies on certain conditions:
- Copyright (C) 1985, 1996, 1998, 2001-2023 Free Software Foundation, Inc.
+ Copyright (C) 1985, 1996, 1998, 2001-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/etc/tutorials/TUTORIAL.pl b/etc/tutorials/TUTORIAL.pl
index 388e4cf692b..6f2565f6855 100644
--- a/etc/tutorials/TUTORIAL.pl
+++ b/etc/tutorials/TUTORIAL.pl
@@ -1209,7 +1209,7 @@ z pomocą Ryszarda Kubiaka i Janusza S. Bienia <jsbien@mail.uw.edu.pl>.
Ta wersja samouczka, podobnie jak GNU Emacs, jest chroniona prawem
autorskim, ale wolno ją kopiować pod następującymi warunkami:
-Copyright (C) 1985, 1994, 2001-2023 Free Software Foundation, Inc.
+Copyright (C) 1985, 1994, 2001-2024 Free Software Foundation, Inc.
Zezwala się na wykonywanie lub rozpowszechnianie
wiernych kopii tego dokumentu w otrzymanej formie, na dowolnym
diff --git a/etc/tutorials/TUTORIAL.pt_BR b/etc/tutorials/TUTORIAL.pt_BR
index a7d6dcb9204..1afc82748d4 100644
--- a/etc/tutorials/TUTORIAL.pt_BR
+++ b/etc/tutorials/TUTORIAL.pt_BR
@@ -1056,7 +1056,7 @@ Essa versão do tutorial foi originalmente traduzida por Marcelo Toledo
<marcelo@gnu.org> e como o GNU Emacs, tem um copyright, e vem
com uma permissão de distribuição de cópias nas seguintes condições:
-Copyright (C) 2004-2023 Free Software Foundation, Inc.
+Copyright (C) 2004-2024 Free Software Foundation, Inc.
Permissão é garantida a qualquer um para fazer ou distribuir cópias
integrais deste documento como recebido, em qualquer meio, deixando
diff --git a/etc/tutorials/TUTORIAL.ro b/etc/tutorials/TUTORIAL.ro
index ee3a1426239..849374ee706 100644
--- a/etc/tutorials/TUTORIAL.ro
+++ b/etc/tutorials/TUTORIAL.ro
@@ -4,7 +4,7 @@ Mulţumiri Aidei Hulubei <aida@chang.pub.ro> pentru corecturi şi sugestii.
Această versiune a fost produsă plecând de la versiunea în limba
engleză, care este
-Copyright (c) 1985, 2013-2023 Free Software Foundation, Inc.
+Copyright (c) 1985, 2013-2024 Free Software Foundation, Inc.
Citiţi acum versiunea românească a tutorialului de Emacs.
@@ -1082,7 +1082,7 @@ continuare noţita de copyright originală în limba engleză.
This version of the tutorial, like GNU Emacs, is copyrighted, and
comes with permission to distribute copies on certain conditions:
-Copyright (C) 1998, 2001-2022 Free Software Foundation, Inc.
+Copyright (C) 1998, 2001-2024 Free Software Foundation, Inc.
Permission is granted to anyone to make or distribute verbatim copies
of this document as received, in any medium, provided that the
diff --git a/etc/tutorials/TUTORIAL.ru b/etc/tutorials/TUTORIAL.ru
index 8018b36cc38..a5c76321acc 100644
--- a/etc/tutorials/TUTORIAL.ru
+++ b/etc/tutorials/TUTORIAL.ru
@@ -1105,7 +1105,7 @@ Dired позволяет вам отображать список файлов
(copyrighted) и приходит с ограничениями распространения копий со
следующими соглашениями:
-Copyright (C) 1985, 1996, 1998, 2001-2023 Free Software Foundation, Inc.
+Copyright (C) 1985, 1996, 1998, 2001-2024 Free Software Foundation, Inc.
Permission is granted to anyone to make or distribute verbatim copies
of this document as received, in any medium, provided that the
diff --git a/etc/tutorials/TUTORIAL.sk b/etc/tutorials/TUTORIAL.sk
index e5033a822dc..2186f1716de 100644
--- a/etc/tutorials/TUTORIAL.sk
+++ b/etc/tutorials/TUTORIAL.sk
@@ -1074,7 +1074,7 @@ tútorialom napísaným Stuartom Cracraftom pre pôvodný Emacs.
Táto verzia tútorialu je, podobne ako GNU Emacs, chránená copyrightom
a je šírená s povolením distribuovať kópie za istých podmienok:
-Copyright (C) 1985, 1996, 1998, 2001-2023 Free Software Foundation, Inc.
+Copyright (C) 1985, 1996, 1998, 2001-2024 Free Software Foundation, Inc.
Každému je zaručené právo vytvárať a distribuovať presné kópie tohto
dokumentu tak, ako ho dostal, na akomkoľvek médiu, s tým, že bude
diff --git a/etc/tutorials/TUTORIAL.sl b/etc/tutorials/TUTORIAL.sl
index ae594b99332..28dfdcb71fd 100644
--- a/etc/tutorials/TUTORIAL.sl
+++ b/etc/tutorials/TUTORIAL.sl
@@ -1119,7 +1119,7 @@ Emacs. V slovenščino ga je prevedel Primož Peterlin.
To besedilo, kot sam GNU Emacs, je avtorsko delo, in njegovo
razmnoževanje in razširjanje je dovoljeno pod naslednjimi pogoji:
-Copyright © 1985, 1996, 1998, 2001-2023 Free Software Foundation, Inc.
+Copyright © 1985, 1996, 1998, 2001-2024 Free Software Foundation, Inc.
Ta datoteka je del paketa GNU Emacs.
diff --git a/etc/tutorials/TUTORIAL.sv b/etc/tutorials/TUTORIAL.sv
index 9b38fa0c6fe..f13799ad369 100644
--- a/etc/tutorials/TUTORIAL.sv
+++ b/etc/tutorials/TUTORIAL.sv
@@ -1153,7 +1153,7 @@ Lidell översatte den till svenska.
This version of the tutorial, like GNU Emacs, is copyrighted, and
comes with permission to distribute copies on certain conditions:
-Copyright (C) 1985, 1996, 1998, 2001-2023 Free Software Foundation, Inc.
+Copyright (C) 1985, 1996, 1998, 2001-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/etc/tutorials/TUTORIAL.th b/etc/tutorials/TUTORIAL.th
index 9c2ee1e5b90..3913791b8b2 100644
--- a/etc/tutorials/TUTORIAL.th
+++ b/etc/tutorials/TUTORIAL.th
@@ -964,7 +964,7 @@ starting with the one written by Stuart Cracraft for the original Emacs.
This version of the tutorial, like GNU Emacs, is copyrighted, and
comes with permission to distribute copies on certain conditions:
-Copyright (C) 1985, 1996, 2001-2023 Free Software Foundation, Inc.
+Copyright (C) 1985, 1996, 2001-2024 Free Software Foundation, Inc.
Permission is granted to anyone to make or distribute verbatim copies
of this document as received, in any medium, provided that the
diff --git a/etc/tutorials/TUTORIAL.uk b/etc/tutorials/TUTORIAL.uk
index 6d4772cf0ad..c09ba7de7d6 100644
--- a/etc/tutorials/TUTORIAL.uk
+++ b/etc/tutorials/TUTORIAL.uk
@@ -1126,7 +1126,7 @@ list-packages. З'явиться екран, за допомогою якого
Ця версія посібника — складник GNU Emacs. Її захищено авторським
правом. Розповсюджувати копії дозволено за певних умов:
- Copyright (C) 1985, 1996, 1998, 2001-2023 Free Software Foundation,
+ Copyright (C) 1985, 1996, 1998, 2001-2024 Free Software Foundation,
Inc. (Фонд вільного програмного забезпечення, Inc.)
Цей файл — складник GNU Emacs.
diff --git a/etc/tutorials/TUTORIAL.zh b/etc/tutorials/TUTORIAL.zh
index f938ed693d8..15698cfb688 100644
--- a/etc/tutorials/TUTORIAL.zh
+++ b/etc/tutorials/TUTORIAL.zh
@@ -1049,7 +1049,7 @@ issue here>」。
這個版本的快速指南和 GNU Emacs 一樣都是版權化的,並且允許在某些條件下
散佈其拷貝:
-Copyright (C) 1985, 1996, 1998, 2001-2023 Free Software Foundation, Inc.
+Copyright (C) 1985, 1996, 1998, 2001-2024 Free Software Foundation, Inc.
Permission is granted to anyone to make or distribute verbatim copies
of this document as received, in any medium, provided that the
diff --git a/etc/w32-feature.el b/etc/w32-feature.el
index 97a7a5f729d..8d36e32e0fb 100644
--- a/etc/w32-feature.el
+++ b/etc/w32-feature.el
@@ -1,6 +1,6 @@
;;; w32-feature.el --- Check Availability of Emacs Features -*- lexical-binding: t -*-
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
;; Author: Phillip Lord <phillip.lord@russet.org.uk>
diff --git a/exec/Makefile.in b/exec/Makefile.in
index 00e59771337..068f59efc75 100644
--- a/exec/Makefile.in
+++ b/exec/Makefile.in
@@ -1,6 +1,6 @@
### @configure_input@
-# Copyright (C) 2023 Free Software Foundation, Inc.
+# Copyright (C) 2023-2024 Free Software Foundation, Inc.
# This file is part of GNU Emacs.
diff --git a/exec/config-mips.m4.in b/exec/config-mips.m4.in
index 72632765bd0..67a14e36b61 100644
--- a/exec/config-mips.m4.in
+++ b/exec/config-mips.m4.in
@@ -1,6 +1,6 @@
dnl Assembler templates for MIPS computers.
dnl
-dnl Copyright (C) 2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2023-2024 Free Software Foundation, Inc.
dnl
dnl This file is part of GNU Emacs.
dnl
diff --git a/exec/config.guess b/exec/config.guess
index c7f17e8fb97..62974adb3dd 100755
--- a/exec/config.guess
+++ b/exec/config.guess
@@ -1,10 +1,10 @@
#!/usr/bin/sh
# Attempt to guess a canonical system name.
-# Copyright 1992-2022 Free Software Foundation, Inc.
+# Copyright 1992-2024 Free Software Foundation, Inc.
# shellcheck disable=SC2006,SC2268 # see below for rationale
-timestamp='2022-05-25'
+timestamp='2023-06-23'
# This file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
@@ -47,7 +47,7 @@ me=`echo "$0" | sed -e 's,.*/,,'`
usage="\
Usage: $0 [OPTION]
-Output the configuration name of the system \`$me' is run on.
+Output the configuration name of the system '$me' is run on.
Options:
-h, --help print this help, then exit
@@ -60,13 +60,13 @@ version="\
GNU config.guess ($timestamp)
Originally written by Per Bothner.
-Copyright 1992-2022 Free Software Foundation, Inc.
+Copyright 1992-2023 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
help="
-Try \`$me --help' for more information."
+Try '$me --help' for more information."
# Parse command line
while test $# -gt 0 ; do
@@ -102,8 +102,8 @@ GUESS=
# temporary files to be created and, as you can see below, it is a
# headache to deal with in a portable fashion.
-# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still
-# use `HOST_CC' if defined, but it is deprecated.
+# Historically, 'CC_FOR_BUILD' used to be named 'HOST_CC'. We still
+# use 'HOST_CC' if defined, but it is deprecated.
# Portable tmp directory creation inspired by the Autoconf team.
@@ -459,7 +459,7 @@ case $UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION in
UNAME_RELEASE=`uname -v`
;;
esac
- # Japanese Language versions have a version number like `4.1.3-JL'.
+ # Japanese Language versions have a version number like '4.1.3-JL'.
SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/-/_/'`
GUESS=sparc-sun-sunos$SUN_REL
;;
@@ -966,6 +966,12 @@ EOF
GNU_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'`
GUESS=$UNAME_MACHINE-unknown-$GNU_SYS$GNU_REL-$LIBC
;;
+ x86_64:[Mm]anagarm:*:*|i?86:[Mm]anagarm:*:*)
+ GUESS="$UNAME_MACHINE-pc-managarm-mlibc"
+ ;;
+ *:[Mm]anagarm:*:*)
+ GUESS="$UNAME_MACHINE-unknown-managarm-mlibc"
+ ;;
*:Minix:*:*)
GUESS=$UNAME_MACHINE-unknown-minix
;;
@@ -1036,7 +1042,7 @@ EOF
k1om:Linux:*:*)
GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
;;
- loongarch32:Linux:*:* | loongarch64:Linux:*:* | loongarchx32:Linux:*:*)
+ loongarch32:Linux:*:* | loongarch64:Linux:*:*)
GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
;;
m32r*:Linux:*:*)
@@ -1191,7 +1197,7 @@ EOF
GUESS=$UNAME_MACHINE-pc-sysv4.2uw$UNAME_VERSION
;;
i*86:OS/2:*:*)
- # If we were able to find `uname', then EMX Unix compatibility
+ # If we were able to find 'uname', then EMX Unix compatibility
# is probably installed.
GUESS=$UNAME_MACHINE-pc-os2-emx
;;
@@ -1332,7 +1338,7 @@ EOF
GUESS=ns32k-sni-sysv
fi
;;
- PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
+ PENTIUM:*:4.0*:*) # Unisys 'ClearPath HMP IX 4000' SVR4/MP effort
# says <Richard.M.Bartel@ccMail.Census.GOV>
GUESS=i586-unisys-sysv4
;;
diff --git a/exec/config.sub b/exec/config.sub
index b41da55df45..7ab92879f13 100755
--- a/exec/config.sub
+++ b/exec/config.sub
@@ -1,10 +1,10 @@
#!/usr/bin/sh
# Configuration validation subroutine script.
-# Copyright 1992-2022 Free Software Foundation, Inc.
+# Copyright 1992-2024 Free Software Foundation, Inc.
# shellcheck disable=SC2006,SC2268 # see below for rationale
-timestamp='2022-01-03'
+timestamp='2023-06-23'
# This file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
@@ -76,13 +76,13 @@ Report bugs and patches to <config-patches@gnu.org>."
version="\
GNU config.sub ($timestamp)
-Copyright 1992-2022 Free Software Foundation, Inc.
+Copyright 1992-2023 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
help="
-Try \`$me --help' for more information."
+Try '$me --help' for more information."
# Parse command line
while test $# -gt 0 ; do
@@ -130,7 +130,7 @@ IFS=$saved_IFS
# Separate into logical components for further validation
case $1 in
*-*-*-*-*)
- echo Invalid configuration \`"$1"\': more than four components >&2
+ echo "Invalid configuration '$1': more than four components" >&2
exit 1
;;
*-*-*-*)
@@ -145,7 +145,7 @@ case $1 in
nto-qnx* | linux-* | uclinux-uclibc* \
| uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* \
| netbsd*-eabi* | kopensolaris*-gnu* | cloudabi*-eabi* \
- | storm-chaos* | os2-emx* | rtmk-nova*)
+ | storm-chaos* | os2-emx* | rtmk-nova* | managarm-*)
basic_machine=$field1
basic_os=$maybe_os
;;
@@ -943,7 +943,7 @@ $basic_machine
EOF
IFS=$saved_IFS
;;
- # We use `pc' rather than `unknown'
+ # We use 'pc' rather than 'unknown'
# because (1) that's what they normally are, and
# (2) the word "unknown" tends to confuse beginning users.
i*86 | x86_64)
@@ -1075,7 +1075,7 @@ case $cpu-$vendor in
pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
cpu=i586
;;
- pentiumpro-* | p6-* | 6x86-* | athlon-* | athalon_*-*)
+ pentiumpro-* | p6-* | 6x86-* | athlon-* | athlon_*-*)
cpu=i686
;;
pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)
@@ -1207,7 +1207,7 @@ case $cpu-$vendor in
| k1om \
| le32 | le64 \
| lm32 \
- | loongarch32 | loongarch64 | loongarchx32 \
+ | loongarch32 | loongarch64 \
| m32c | m32r | m32rle \
| m5200 | m68000 | m680[012346]0 | m68360 | m683?2 | m68k \
| m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x \
@@ -1285,7 +1285,7 @@ case $cpu-$vendor in
;;
*)
- echo Invalid configuration \`"$1"\': machine \`"$cpu-$vendor"\' not recognized 1>&2
+ echo "Invalid configuration '$1': machine '$cpu-$vendor' not recognized" 1>&2
exit 1
;;
esac
@@ -1341,6 +1341,10 @@ EOF
kernel=linux
os=`echo "$basic_os" | sed -e 's|linux|gnu|'`
;;
+ managarm*)
+ kernel=managarm
+ os=`echo "$basic_os" | sed -e 's|managarm|mlibc|'`
+ ;;
*)
kernel=
os=$basic_os
@@ -1754,7 +1758,7 @@ case $os in
| onefs* | tirtos* | phoenix* | fuchsia* | redox* | bme* \
| midnightbsd* | amdhsa* | unleashed* | emscripten* | wasi* \
| nsk* | powerunix* | genode* | zvmoe* | qnx* | emx* | zephyr* \
- | fiwix* )
+ | fiwix* | mlibc* )
;;
# This one is extra strict with allowed versions
sco3.2v2 | sco3.2v[4-9]* | sco5v6*)
@@ -1762,8 +1766,11 @@ case $os in
;;
none)
;;
+ kernel* )
+ # Restricted further below
+ ;;
*)
- echo Invalid configuration \`"$1"\': OS \`"$os"\' not recognized 1>&2
+ echo "Invalid configuration '$1': OS '$os' not recognized" 1>&2
exit 1
;;
esac
@@ -1772,14 +1779,24 @@ esac
# (given a valid OS), if there is a kernel.
case $kernel-$os in
linux-gnu* | linux-dietlibc* | linux-android* | linux-newlib* \
- | linux-musl* | linux-relibc* | linux-uclibc* )
+ | linux-musl* | linux-relibc* | linux-uclibc* | linux-mlibc* )
;;
uclinux-uclibc* )
;;
- -dietlibc* | -newlib* | -musl* | -relibc* | -uclibc* )
+ managarm-mlibc* | managarm-kernel* )
+ ;;
+ -dietlibc* | -newlib* | -musl* | -relibc* | -uclibc* | -mlibc* )
# These are just libc implementations, not actual OSes, and thus
# require a kernel.
- echo "Invalid configuration \`$1': libc \`$os' needs explicit kernel." 1>&2
+ echo "Invalid configuration '$1': libc '$os' needs explicit kernel." 1>&2
+ exit 1
+ ;;
+ -kernel* )
+ echo "Invalid configuration '$1': '$os' needs explicit kernel." 1>&2
+ exit 1
+ ;;
+ *-kernel* )
+ echo "Invalid configuration '$1': '$kernel' does not support '$os'." 1>&2
exit 1
;;
kfreebsd*-gnu* | kopensolaris*-gnu*)
@@ -1796,7 +1813,7 @@ case $kernel-$os in
# Blank kernel with real OS is always fine.
;;
*-*)
- echo "Invalid configuration \`$1': Kernel \`$kernel' not known to work with OS \`$os'." 1>&2
+ echo "Invalid configuration '$1': Kernel '$kernel' not known to work with OS '$os'." 1>&2
exit 1
;;
esac
diff --git a/exec/configure.ac b/exec/configure.ac
index 180c200d13d..9008c84f6a6 100644
--- a/exec/configure.ac
+++ b/exec/configure.ac
@@ -4,7 +4,7 @@ dnl autoconf
dnl in the directory containing this script.
dnl If you changed any AC_DEFINES, also run autoheader.
dnl
-dnl Copyright (C) 2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2023-2024 Free Software Foundation, Inc.
dnl
dnl This file is part of GNU Emacs.
dnl
@@ -25,7 +25,7 @@ AC_PREREQ([2.65])
AC_INIT([libexec], [30.0.50], [bug-gnu-emacs@gnu.org], [],
[https://www.gnu.org/software/emacs/])
-AH_TOP([/* Copyright (C) 2023 Free Software Foundation, Inc.
+AH_TOP([/* Copyright (C) 2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/exec/deps.mk b/exec/deps.mk
index 20fcd2dbc5a..2425503ab44 100644
--- a/exec/deps.mk
+++ b/exec/deps.mk
@@ -1,6 +1,6 @@
### deps.mk
-## Copyright (C) 2023 Free Software Foundation, Inc.
+## Copyright (C) 2023-2024 Free Software Foundation, Inc.
## This file is part of GNU Emacs.
diff --git a/exec/exec.c b/exec/exec.c
index dae05755675..254a983f25f 100644
--- a/exec/exec.c
+++ b/exec/exec.c
@@ -1,6 +1,6 @@
/* Program execution for Emacs.
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
@@ -309,10 +309,10 @@ write_load_command (program_header *header, bool use_alternate,
#else /* HAVE_GETPAGESIZE */
if (!pagesize)
pagesize = sysconf (_SC_PAGESIZE);
+#endif /* HAVE_GETPAGESIZE */
#define PAGE_MASK (~(pagesize - 1))
#define PAGE_SIZE (pagesize)
-#endif /* HAVE_GETPAGESIZE */
#endif /* PAGE_MASK */
start = header->p_vaddr & PAGE_MASK;
diff --git a/exec/exec.h b/exec/exec.h
index 8ee74d7ca8b..bed5edc9bab 100644
--- a/exec/exec.h
+++ b/exec/exec.h
@@ -1,6 +1,6 @@
/* Program execution for Emacs.
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/exec/exec1.c b/exec/exec1.c
index d77ca8adf54..aaff9a94c62 100644
--- a/exec/exec1.c
+++ b/exec/exec1.c
@@ -1,6 +1,6 @@
/* Program execution for Emacs.
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
@@ -53,7 +53,7 @@ main (int argc, char **argv)
tracing_execve (argv[2], argv + 2, environ);
- /* An error occured. Exit with failure. */
+ /* An error occurred. Exit with failure. */
exit (127);
}
else
diff --git a/exec/loader-aarch64.s b/exec/loader-aarch64.s
index da8ec1f4977..0fc9606c62a 100644
--- a/exec/loader-aarch64.s
+++ b/exec/loader-aarch64.s
@@ -1,4 +1,4 @@
-// Copyright (C) 2023 Free Software Foundation, Inc.
+// Copyright (C) 2023-2024 Free Software Foundation, Inc.
//
// This file is part of GNU Emacs.
//
diff --git a/exec/loader-armeabi.s b/exec/loader-armeabi.s
index 32b2a5268d6..5601088262c 100644
--- a/exec/loader-armeabi.s
+++ b/exec/loader-armeabi.s
@@ -1,4 +1,4 @@
-@ Copyright (C) 2023 Free Software Foundation, Inc.
+@ Copyright (C) 2023-2024 Free Software Foundation, Inc.
@
@ This file is part of GNU Emacs.
@
@@ -200,5 +200,5 @@ timespec:
.long 10
@ Local Variables:
-@ asm-comment-char: 64
+@ asm-comment-char: ?@
@ End:
diff --git a/exec/loader-mips64el.s b/exec/loader-mips64el.s
index f4a6f918497..0ff140f9f31 100644
--- a/exec/loader-mips64el.s
+++ b/exec/loader-mips64el.s
@@ -1,4 +1,4 @@
-# Copyright (C) 2023 Free Software Foundation, Inc.
+# Copyright (C) 2023-2024 Free Software Foundation, Inc.
#
# This file is part of GNU Emacs.
#
@@ -230,5 +230,5 @@ dnl syscall # syscall
.quad 10
# Local Variables:
-# asm-comment-char: 35
+# asm-comment-char: ?#
# End:
diff --git a/exec/loader-mipsel.s b/exec/loader-mipsel.s
index baba3f05a94..f1cdcfcf149 100644
--- a/exec/loader-mipsel.s
+++ b/exec/loader-mipsel.s
@@ -1,4 +1,4 @@
-# Copyright (C) 2023 Free Software Foundation, Inc.
+# Copyright (C) 2023-2024 Free Software Foundation, Inc.
#
# This file is part of GNU Emacs.
#
@@ -232,5 +232,5 @@ RESTORE() # restore sp
.long 10
# Local Variables:
-# asm-comment-char: 35
+# asm-comment-char: ?#
# End:
diff --git a/exec/loader-x86.s b/exec/loader-x86.s
index 6329e7f33b1..216bc88f976 100644
--- a/exec/loader-x86.s
+++ b/exec/loader-x86.s
@@ -1,7 +1,7 @@
define(`CC', `
dnl')
-CC Copyright (C) 2023 Free Software Foundation, Inc.
+CC Copyright (C) 2023-2024 Free Software Foundation, Inc.
CC
CC This file is part of GNU Emacs.
CC
diff --git a/exec/loader-x86_64.s b/exec/loader-x86_64.s
index acba609b202..2ef779e4504 100644
--- a/exec/loader-x86_64.s
+++ b/exec/loader-x86_64.s
@@ -1,7 +1,7 @@
define(`CC', `
dnl')
-CC Copyright (C) 2023 Free Software Foundation, Inc.
+CC Copyright (C) 2023-2024 Free Software Foundation, Inc.
CC
CC This file is part of GNU Emacs.
CC
diff --git a/exec/mipsel-user.h b/exec/mipsel-user.h
index 9c5a445c9aa..04f4a2a5089 100644
--- a/exec/mipsel-user.h
+++ b/exec/mipsel-user.h
@@ -1,6 +1,6 @@
/* Program execution for Emacs.
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/exec/mipsfpu.c b/exec/mipsfpu.c
index f5fa5720804..5fd81fb9237 100644
--- a/exec/mipsfpu.c
+++ b/exec/mipsfpu.c
@@ -1,6 +1,6 @@
/* Program execution for Emacs.
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/exec/mipsfpu.h b/exec/mipsfpu.h
index 2315db59e93..1669102942b 100644
--- a/exec/mipsfpu.h
+++ b/exec/mipsfpu.h
@@ -1,6 +1,6 @@
/* Program execution for Emacs.
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/exec/test.c b/exec/test.c
index fa2a848837c..7185c958b87 100644
--- a/exec/test.c
+++ b/exec/test.c
@@ -1,6 +1,6 @@
/* Program execution for Emacs.
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/exec/trace.c b/exec/trace.c
index 3b384792d0a..8e190c94f79 100644
--- a/exec/trace.c
+++ b/exec/trace.c
@@ -1,6 +1,6 @@
/* Program execution for Emacs.
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
@@ -1028,7 +1028,7 @@ process_system_call (struct exec_tracee *tracee)
break;
case 1:
- /* An error has occured; errno is set to the error. */
+ /* An error has occurred; errno is set to the error. */
goto report_syscall_error;
}
@@ -1039,16 +1039,22 @@ process_system_call (struct exec_tracee *tracee)
#endif /* READLINK_SYSCALL */
case READLINKAT_SYSCALL:
- /* Handle this readlinkat system call. */
- rc = handle_readlinkat (callno, &regs, tracee,
- &result);
+ /* This system call is already in progress if
+ TRACEE->waiting_for_syscall is true. */
- /* rc means the same as in `handle_exec'. */
+ if (!tracee->waiting_for_syscall)
+ {
+ /* Handle this readlinkat system call. */
+ rc = handle_readlinkat (callno, &regs, tracee,
+ &result);
+
+ /* rc means the same as in `handle_exec'. */
- if (rc == 1)
- goto report_syscall_error;
- else if (rc == 2)
- goto emulate_syscall;
+ if (rc == 1)
+ goto report_syscall_error;
+ else if (rc == 2)
+ goto emulate_syscall;
+ }
/* Fallthrough. */
diff --git a/java/AndroidManifest.xml.in b/java/AndroidManifest.xml.in
index 2cbcdbc3e5b..b18446bece0 100644
--- a/java/AndroidManifest.xml.in
+++ b/java/AndroidManifest.xml.in
@@ -1,6 +1,6 @@
<!-- @configure_input@
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
@@ -40,6 +40,8 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.SET_WALLPAPER" />
+ <uses-permission android:name="android.permission.READ_CALENDAR" />
+ <uses-permission android:name="android.permission.WRITE_CALENDAR" />
<!-- Despite the claim that WRITE_EXTERNAL_STORAGE also covers
reading from external storage, specifying READ_EXTERNAL_STORAGE
seems to still be necessary on some versions of Android.
@@ -71,8 +73,12 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. -->
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
+ <!-- Under Android 14 or later to run within the background. -->
+
+ <uses-permission android:name="android.permission.FOREGROUND_SERVICE_SPECIAL_USE"/>
+
<uses-sdk android:minSdkVersion="@ANDROID_MIN_SDK@"
- android:targetSdkVersion="33"/>
+ android:targetSdkVersion="34"/>
<application android:name="org.gnu.emacs.EmacsApplication"
android:label="Emacs"
@@ -88,7 +94,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. -->
android:launchMode="singleInstance"
android:windowSoftInputMode="adjustResize"
android:exported="true"
- android:configChanges="orientation|screenSize|screenLayout|keyboardHidden">
+ android:configChanges="orientation|screenSize|screenLayout|keyboardHidden|locale|fontScale">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.DEFAULT" />
@@ -107,80 +113,43 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. -->
<action android:name="android.intent.action.VIEW"/>
<action android:name="android.intent.action.EDIT"/>
<action android:name="android.intent.action.PICK"/>
+ <category android:name="android.intent.category.DEFAULT"/>
+ <!-- Don't offer to start Emacs for URLs that designate
+ resources other than files. -->
+ <data android:mimeType="*/*" android:scheme="file"/>
+ <data android:mimeType="*/*" android:scheme="content"/>
+ </intent-filter>
+
+ <!-- Facilitate opening org-protocol:// URLs as well, the same
+ way emacsclient.desktop does. -->
+
+ <intent-filter>
+ <action android:name="android.intent.action.VIEW"/>
+ <category android:name="android.intent.category.DEFAULT"/>
+ <category android:name="android.intent.category.BROWSABLE"/>
+ <data android:scheme="org-protocol"/>
+ </intent-filter>
+ <!-- And also mailto links. -->
+
+ <intent-filter>
+ <action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
+ <category android:name="android.intent.category.BROWSABLE"/>
+ <data android:scheme="mailto"/>
+ </intent-filter>
- <data android:mimeType="image/aces"/>
- <data android:mimeType="image/avci"/>
- <data android:mimeType="image/avcs"/>
- <data android:mimeType="image/avif"/>
- <data android:mimeType="image/bmp"/>
- <data android:mimeType="image/cgm"/>
- <data android:mimeType="image/dicom-rle"/>
- <data android:mimeType="image/dpx"/>
- <data android:mimeType="image/emf"/>
- <data android:mimeType="image/example"/>
- <data android:mimeType="image/fits"/>
- <data android:mimeType="image/g3fax"/>
- <data android:mimeType="image/heic"/>
- <data android:mimeType="image/heic-sequence"/>
- <data android:mimeType="image/heif"/>
- <data android:mimeType="image/heif-sequence"/>
- <data android:mimeType="image/hej2k"/>
- <data android:mimeType="image/hsj2"/>
- <data android:mimeType="image/jls"/>
- <data android:mimeType="image/jp2"/>
- <data android:mimeType="image/jph"/>
- <data android:mimeType="image/jphc"/>
- <data android:mimeType="image/jpm"/>
- <data android:mimeType="image/jpx"/>
- <data android:mimeType="image/jxr"/>
- <data android:mimeType="image/jxrA"/>
- <data android:mimeType="image/jxrS"/>
- <data android:mimeType="image/jxs"/>
- <data android:mimeType="image/jxsc"/>
- <data android:mimeType="image/jxsi"/>
- <data android:mimeType="image/jxss"/>
- <data android:mimeType="image/ktx"/>
- <data android:mimeType="image/ktx2"/>
- <data android:mimeType="image/naplps"/>
- <data android:mimeType="image/png"/>
- <data android:mimeType="image/prs.btif"/>
- <data android:mimeType="image/prs.pti"/>
- <data android:mimeType="image/pwg-raster"/>
- <data android:mimeType="image/svg+xml"/>
- <data android:mimeType="image/t38"/>
- <data android:mimeType="image/tiff"/>
- <data android:mimeType="image/tiff-fx"/>
- <data android:mimeType="image/xpm"/>
- <data android:mimeType="text/*"/>
- <data android:mimeType="application/*xml"/>
- <data android:mimeType="application/atom+xml"/>
- <data android:mimeType="application/dxf"/>
- <data android:mimeType="application/ecmascript"/>
- <data android:mimeType="application/javascript"/>
- <data android:mimeType="application/json"/>
- <data android:mimeType="application/*log*"/>
- <data android:mimeType="application/octet-stream"/>
- <data android:mimeType="application/soap+xm"/>
- <data android:mimeType="application/x-caramel"/>
- <data android:mimeType="application/x-klaunch"/>
- <data android:mimeType="application/x-latex"/>
- <data android:mimeType="application/x-sh"/>
- <data android:mimeType="application/x-tcl"/>
- <data android:mimeType="application/x-tex*"/>
- <data android:mimeType="application/x-troff*"/>
- <data android:mimeType="application/xhtml+xml"/>
- <data android:mimeType="application/xml*"/>
- <data android:mimeType="application/zip"/>
- <data android:mimeType="application/x-zip-compressed"/>
+ <intent-filter>
+ <action android:name="android.intent.action.SENDTO"/>
+ <data android:scheme="mailto"/>
+ <category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</activity>
<activity android:name="org.gnu.emacs.EmacsMultitaskActivity"
android:windowSoftInputMode="adjustResize"
android:exported="true"
- android:configChanges="orientation|screenSize|screenLayout|keyboardHidden"/>
+ android:configChanges="orientation|screenSize|screenLayout|keyboardHidden|locale|fontScale"/>
<activity android:autoRemoveFromRecents="true"
android:label="Emacs options"
@@ -225,6 +194,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. -->
android:directBootAware="false"
android:enabled="true"
android:exported="false"
+ android:foregroundServiceType="specialUse"
android:label="GNU Emacs service"/>
</application>
</manifest>
diff --git a/java/INSTALL b/java/INSTALL
index fb235af1346..175ff2826b2 100644
--- a/java/INSTALL
+++ b/java/INSTALL
@@ -1,5 +1,5 @@
Installation instructions for Android
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
See the end of the file for license conditions.
Please read the entirety of this file before attempting to build Emacs
@@ -39,7 +39,7 @@ script like so:
Replacing the paths in the command line above with:
- the path to the `android.jar' headers which come with the Android
- SDK. They must correspond to Android version 13 (API level 33).
+ SDK. They must correspond to Android version 14 (API level 34).
- the path to the C compiler in the Android NDK, for the kind of CPU
you are building Emacs to run on.
@@ -87,13 +87,13 @@ necessary for compiling Emacs.
It is imperative that Emacs is compiled using the headers for the
exact API level that it is written for. This is currently API level
-33, so the correct android.jar archive is located within a directory
-whose name begins with `android-33'. Minor revisions to the headers
+34, so the correct android.jar archive is located within a directory
+whose name begins with `android-34'. Minor revisions to the headers
are inconsequential towards the Emacs compilation process; if there is
-a directory named `android-33-extN' (where N represents a revision to
+a directory named `android-34-extN' (where N represents a revision to
the Android SDK), whether you provide `configure' with that
directory's android.jar or the android.jar contained within the
-directory named `android-33' is of no special importance.
+directory named `android-34' is of no special importance.
The ndk directory contains one subdirectory for each version of the
Android NDK installed. This directory in turn contains the C and C++
@@ -167,7 +167,7 @@ than a compressed package for a newer version of Android.
BUILDING C++ DEPENDENCIES
With a new version of the NDK, dependencies containing C++ code should
-build without any futher configuration. However, older versions
+build without any further configuration. However, older versions
require that you use the ``make_standalone_toolchain.py'' script in
the NDK distribution to create a ``standalone toolchain'', and use
that instead, in order for C++ headers to be found.
@@ -299,6 +299,8 @@ work, along with what has to be patched to make them work:
the following three dependencies.)
libpackagelistparser
https://android.googlesource.com/platform/system/core/+/refs/heads/nougat-mr1-dev/libpackagelistparser/
+ (You must add LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include before
+ its Android.mk includes $(BUILD_SHARED_LIBRARY))
libpcre - https://android.googlesource.com/platform/external/pcre
libcrypto - https://android.googlesource.com/platform/external/boringssl
(You must apply the patch at the end of this file when building for
@@ -307,7 +309,7 @@ work, along with what has to be patched to make them work:
Many of these dependencies have been migrated over to the
``Android.bp'' build system now used to build Android itself.
However, the old ``Android.mk'' Makefiles are still present in older
-branches, and can be easily adapte to newer versions.
+branches, and can be easily adapted to newer versions.
In addition, some Emacs dependencies provide `ndk-build' support
themselves:
@@ -404,14 +406,14 @@ libxml2 before it can be built for Emacs. In addition, you must also
revert the commit `edb5870767fed8712a9b77ef34097209b61ab2db'.
diff --git a/Android.mk b/Android.mk
-index 07c7b372..24f67e49 100644
+index 07c7b372..2494274f 100644
--- a/Android.mk
+++ b/Android.mk
@@ -80,6 +80,7 @@ LOCAL_SHARED_LIBRARIES := libicuuc
LOCAL_MODULE:= libxml2
LOCAL_CLANG := true
LOCAL_ADDITIONAL_DEPENDENCIES += $(LOCAL_PATH)/Android.mk
-+LOCAL_EXPORT_C_INCLUDES += $(LOCAL_PATH)
++LOCAL_EXPORT_C_INCLUDES += $(LOCAL_PATH)/include
include $(BUILD_SHARED_LIBRARY)
# For the host
diff --git a/java/Makefile.in b/java/Makefile.in
index 804d4669c7a..60bd2ea086b 100644
--- a/java/Makefile.in
+++ b/java/Makefile.in
@@ -1,6 +1,6 @@
### @configure_input@
-# Copyright (C) 2023 Free Software Foundation, Inc.
+# Copyright (C) 2023-2024 Free Software Foundation, Inc.
# This file is part of GNU Emacs.
@@ -227,6 +227,13 @@ install_temp: $(CROSS_BINS) $(CROSS_LIBS) $(RESOURCE_FILES)
cp -f $$file install_temp/lib/$(ANDROID_ABI); \
fi \
done
+# Next, produce a version of rcs2log befitting Android's naming
+# conventions and shell interpreter location.
+ $(AM_V_at) \
+ sed 's|/bin/sh|/system/bin/sh|' \
+ $(top_srcdir)/lib-src/rcs2log > \
+ install_temp/lib/$(ANDROID_ABI)/librcs2log.so
+ $(AM_V_at) chmod +x install_temp/lib/$(ANDROID_ABI)/librcs2log.so
ifneq ($(NDK_BUILD_SHARED),)
$(AM_V_SILENT) cp -f $(NDK_BUILD_SHARED) \
install_temp/lib/$(ANDROID_ABI)
diff --git a/java/README b/java/README
index e518e9fbb2f..a909cdd22ef 100644
--- a/java/README
+++ b/java/README
@@ -22,1027 +22,6 @@ Please keep the Java code indented with tabs and formatted according
to the rules for C code in the GNU coding standards. Always use
C-style comments.
-======================================================================
-
-OVERVIEW OF JAVA
-
-Emacs developers do not know Java, and there is no reason they should
-have to. Thus, the code in this directory is confined to what is
-strictly necessary to support Emacs, and only uses a subset of Java
-written in a way that is easily understandable to C programmers.
-
-Java is required because the entire Android runtime is based around
-Java, and there is no way to write an Android program which runs
-without Java.
-
-This text exists to prime other Emacs developers, already familar with
-C, on the basic architecture of the Android port, and to teach them
-how to read and write the Java code found in this directory.
-
-Java is an object oriented language with automatic memory management
-compiled down to bytecode, which is then subject to interpretation by
-a Java virtual machine.
-
-What that means, is that:
-
-struct emacs_window
-{
- int some_fields;
- int of_emacs_window;
-};
-
-static void
-do_something_with_emacs_window (struct emacs_window *a, int n)
-{
- a->some_fields = a->of_emacs_window + n;
-}
-
-would be written:
-
-public class EmacsWindow
-{
- public int someFields;
- public int ofEmacsWindow;
-
- public void
- doSomething (int n)
- {
- someFields = ofEmacsWindow + n;
- }
-}
-
-and instead of doing:
-
-do_something_with_emacs_window (my_window, 1);
-
-you say:
-
-myWindow.doSomething (1);
-
-In addition to functions associated with an object of a given class
-(such as EmacsWindow), Java also has two other kinds of functions.
-
-The first are so-called ``static'' functions (the static means
-something entirely different from what it does in C.)
-
-A static function, while still having to be defined within a class,
-can be called without any object. Instead of the object, you write
-the name of the Java class within which it is defined. For example,
-the following C code:
-
-int
-multiply_a_with_b_and_then_add_c (int a, int b, int c)
-{
- return a * b + c;
-}
-
-would be:
-
-public class EmacsSomething
-{
- public static int
- multiplyAWithBAndThenAddC (int a, int b, int c)
- {
- return a * b + c;
- }
-};
-
-Then, instead of calling:
-
-int foo;
-
-foo = multiply_a_with_b_then_add_c (1, 2, 3);
-
-you say:
-
-int foo;
-
-foo = EmacsSomething.multiplyAWithBAndThenAddC (1, 2, 3);
-
-In Java, ``static'' does not mean that the function is only used
-within its compilation unit! Instead, the ``private'' qualifier is
-used to mean more or less the same thing:
-
-static void
-this_procedure_is_only_used_within_this_file (void)
-{
- do_something ();
-}
-
-becomes
-
-public class EmacsSomething
-{
- private static void
- thisProcedureIsOnlyUsedWithinThisClass ()
- {
-
- }
-}
-
-the other kind are called ``constructors''. They are functions that
-must be called to allocate memory to hold a class:
-
-public class EmacsFoo
-{
- int bar;
-
- public
- EmacsFoo (int tokenA, int tokenB)
- {
- bar = tokenA + tokenB;
- }
-}
-
-now, the following statement:
-
-EmacsFoo foo;
-
-foo = new EmacsFoo (1, 2);
-
-becomes more or less equivalent to the following C code:
-
-struct emacs_foo
-{
- int bar;
-};
-
-struct emacs_foo *
-make_emacs_foo (int token_a, int token_b)
-{
- struct emacs_foo *foo;
-
- foo = xmalloc (sizeof *foo);
- foo->bar = token_a + token_b;
-
- return foo;
-}
-
-/* ... */
-
-struct emacs_foo *foo;
-
-foo = make_emacs_foo (1, 2);
-
-A class may have any number of constructors, or no constructors at
-all, in which case the compiler inserts an empty constructor.
-
-
-
-Sometimes, you will see Java code that looks like this:
-
- allFiles = filesDirectory.listFiles (new FileFilter () {
- @Override
- public boolean
- accept (File file)
- {
- return (!file.isDirectory ()
- && file.getName ().endsWith (".pdmp"));
- }
- });
-
-This is Java's version of GCC's nested function extension. The major
-difference is that the nested function may still be called even after
-it goes out of scope, and always retains a reference to the class and
-local variables around where it was called.
-
-Being an object-oriented language, Java also allows defining that a
-class ``extends'' another class. The following C code:
-
-struct a
-{
- long thirty_two;
-};
-
-struct b
-{
- struct a a;
- long long sixty_four;
-};
-
-extern void do_something (struct a *);
-
-void
-my_function (struct b *b)
-{
- do_something (&b->a);
-}
-
-is roughly equivalent to the following Java code, split into two
-files:
-
- A.java
-
-public class A
-{
- int thirtyTwo;
-
- public void
- doSomething ()
- {
- etcEtcEtc ();
- }
-};
-
- B.java
-
-public class B extends A
-{
- long sixty_four;
-
- public static void
- myFunction (B b)
- {
- b.doSomething ();
- }
-}
-
-the Java runtime has transformed the call to ``b.doSomething'' to
-``((A) b).doSomething''.
-
-However, Java also allows overriding this behavior, by specifying the
-@Override keyword:
-
-public class B extends A
-{
- long sixty_four;
-
- @Override
- public void
- doSomething ()
- {
- Something.doSomethingTwo ();
- super.doSomething ();
- }
-}
-
-now, any call to ``doSomething'' on a ``B'' created using ``new B ()''
-will end up calling ``Something.doSomethingTwo'', before calling back
-to ``A.doSomething''. This override also applies in reverse; that is
-to say, even if you write:
-
- ((A) b).doSomething ();
-
-B's version of doSomething will still be called, if ``b'' was created
-using ``new B ()''.
-
-This mechanism is used extensively throughout the Java language and
-Android windowing APIs.
-
-Elsewhere, you will encounter Java code that defines arrays:
-
-public class EmacsFrobinicator
-{
- public static void
- emacsFrobinicate (int something)
- {
- int[] primesFromSomething;
-
- primesFromSomething = new int[numberOfPrimes];
- /* ... */
- }
-}
-
-Java arrays are similar to C arrays in that they can not grow. But
-they are very much unlike C arrays in that they are always references
-(as opposed to decaying into pointers in only some situations), and
-contain information about their length.
-
-If another function named ``frobinicate1'' takes an array as an
-argument, then it need not take the length of the array.
-
-Instead, it may simply iterate over the array like so:
-
-int i, k;
-
-for (i = 0; i < array.length; ++i)
- {
- k = array[i];
-
- Whatever.doSomethingWithK (k);
- }
-
-The syntax used to define arrays is also slightly different. As
-arrays are always references, there is no way for you to tell the
-runtime to allocate an array of size N in a structure (class.)
-
-Instead, if you need an array of that size, you must declare a field
-with the type of the array, and allocate the array inside the class's
-constructor, like so:
-
-public class EmacsArrayContainer
-{
- public int[] myArray;
-
- public
- EmacsArrayContainer ()
- {
- myArray = new array[10];
- }
-}
-
-while in C, you could just have written:
-
-struct emacs_array_container
-{
- int my_array[10];
-};
-
-or, possibly even better,
-
-typedef int emacs_array_container[10];
-
-Alas, Java has no equivalent of `typedef'.
-
-Like in C, Java string literals are delimited by double quotes.
-Unlike C, however, strings are not NULL-terminated arrays of
-characters, but a distinct type named ``String''. They store their
-own length, characters in Java's 16-bit ``char'' type, and are capable
-of holding NULL bytes.
-
-Instead of writing:
-
-wchar_t character;
-extern char *s;
-size_t s;
-
- for (/* determine n, s in a loop. */)
- s += mbstowc (&character, s, n);
-
-or:
-
-const char *byte;
-
-for (byte = my_string; *byte; ++byte)
- /* do something with *byte. */;
-
-or perhaps even:
-
-size_t length, i;
-char foo;
-
-length = strlen (my_string);
-
-for (i = 0; i < length; ++i)
- foo = my_string[i];
-
-you write:
-
-char foo;
-int i;
-
-for (i = 0; i < myString.length (); ++i)
- foo = myString.charAt (0);
-
-Java also has stricter rules on what can be used as a truth value in a
-conditional. While in C, any non-zero value is true, Java requires
-that every truth value be of the boolean type ``boolean''.
-
-What this means is that instead of simply writing:
-
- if (foo || bar)
-
-where foo can either be 1 or 0, and bar can either be NULL or a
-pointer to something, you must explicitly write:
-
- if (foo != 0 || bar != null)
-
-in Java.
-
-JAVA NATIVE INTERFACE
-
-Java also provides an interface for C code to interface with Java.
-
-C functions exported from a shared library become static Java
-functions within a class, like so:
-
-public class EmacsNative
-{
- /* Obtain the fingerprint of this build of Emacs. The fingerprint
- can be used to determine the dump file name. */
- public static native String getFingerprint ();
-
- /* Set certain parameters before initializing Emacs.
-
- assetManager must be the asset manager associated with the
- context that is loading Emacs. It is saved and remains for the
- remainder the lifetime of the Emacs process.
-
- filesDir must be the package's data storage location for the
- current Android user.
-
- libDir must be the package's data storage location for native
- libraries. It is used as PATH.
-
- cacheDir must be the package's cache directory. It is used as
- the `temporary-file-directory'.
-
- pixelDensityX and pixelDensityY are the DPI values that will be
- used by Emacs.
-
- classPath must be the classpath of this app_process process, or
- NULL.
-
- emacsService must be the EmacsService singleton, or NULL. */
- public static native void setEmacsParams (AssetManager assetManager,
- String filesDir,
- String libDir,
- String cacheDir,
- float pixelDensityX,
- float pixelDensityY,
- String classPath,
- EmacsService emacsService);
-}
-
-Where the corresponding C functions are located in android.c, and
-loaded by the special invocation:
-
- static
- {
- System.loadLibrary ("emacs");
- };
-
-where ``static'' defines a section of code which will be run upon the
-object (containing class) being loaded. This is like:
-
- __attribute__((constructor))
-
-on systems where shared object constructors are supported.
-
-See http://docs.oracle.com/en/java/javase/19/docs/specs/jni/intro.html
-for more details.
-
-
-
-OVERVIEW OF ANDROID
-
-When the Android system starts an application, it does not actually
-call the application's ``main'' function. It may not even start the
-application's process if one is already running.
-
-Instead, Android is organized around components. When the user opens
-the ``Emacs'' icon, the Android system looks up and starts the
-component associated with the ``Emacs'' icon. In this case, the
-component is called an activity, and is declared in
-the AndroidManifest.xml in this directory:
-
- <activity android:name="org.gnu.emacs.EmacsActivity"
- android:launchMode="singleTop"
- android:windowSoftInputMode="adjustResize"
- android:exported="true"
- android:configChanges="orientation|screenSize|screenLayout|keyboardHidden">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.DEFAULT" />
- <category android:name="android.intent.category.LAUNCHER" />
- </intent-filter>
- </activity>
-
-This tells Android to start the activity defined in ``EmacsActivity''
-(defined in org/gnu/emacs/EmacsActivity.java), a class extending the
-Android class ``Activity''.
-
-To do so, the Android system creates an instance of ``EmacsActivity''
-and the window system window associated with it, and eventually calls:
-
- Activity activity;
-
- activity.onCreate (...);
-
-But which ``onCreate'' is really called?
-It is actually the ``onCreate'' defined in EmacsActivity.java, as
-it overrides the ``onCreate'' defined in Android's own Activity class:
-
- @Override
- public void
- onCreate (Bundle savedInstanceState)
- {
- FrameLayout.LayoutParams params;
- Intent intent;
-
-Then, this is what happens step-by-step within the ``onCreate''
-function:
-
- /* See if Emacs should be started with -Q. */
- intent = getIntent ();
- EmacsService.needDashQ
- = intent.getBooleanExtra ("org.gnu.emacs.START_DASH_Q",
- false);
-
-Here, Emacs obtains the intent (a request to start a component) which
-was used to start Emacs, and sets a special flag if it contains a
-request for Emacs to start with the ``-Q'' command-line argument.
-
- /* Set the theme to one without a title bar. */
-
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH)
- setTheme (android.R.style.Theme_DeviceDefault_NoActionBar);
- else
- setTheme (android.R.style.Theme_NoTitleBar);
-
-Next, Emacs sets an appropriate theme for the activity's associated
-window decorations.
-
- params = new FrameLayout.LayoutParams (LayoutParams.MATCH_PARENT,
- LayoutParams.MATCH_PARENT);
-
- /* Make the frame layout. */
- layout = new FrameLayout (this);
- layout.setLayoutParams (params);
-
- /* Set it as the content view. */
- setContentView (layout);
-
-Then, Emacs creates a ``FrameLayout'', a widget that holds a single
-other widget, and makes it the activity's ``content view''.
-
-The activity itself is a ``FrameLayout'', so the ``layout parameters''
-here apply to the FrameLayout itself, and not its children.
-
- /* Maybe start the Emacs service if necessary. */
- EmacsService.startEmacsService (this);
-
-And after that, Emacs calls the static function ``startEmacsService'',
-defined in the class ``EmacsService''. This starts the Emacs service
-component if necessary.
-
- /* Add this activity to the list of available activities. */
- EmacsWindowAttachmentManager.MANAGER.registerWindowConsumer (this);
-
- super.onCreate (savedInstanceState);
-
-Finally, Emacs registers that this activity is now ready to receive
-top-level frames (windows) created from Lisp.
-
-Activities come and go, but Emacs has to stay running in the mean
-time. Thus, Emacs also defines a ``service'', which is a long-running
-component that the Android system allows to run in the background.
-
-Let us go back and review the definition of ``startEmacsService'':
-
- public static void
- startEmacsService (Context context)
- {
- if (EmacsService.SERVICE == null)
- {
- if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O)
- /* Start the Emacs service now. */
- context.startService (new Intent (context,
- EmacsService.class));
- else
- /* Display the permanant notification and start Emacs as a
- foreground service. */
- context.startForegroundService (new Intent (context,
- EmacsService.class));
- }
- }
-
-If ``EmacsService.SERVICE'' does not yet exist, what this does is to
-tell the ``context'' (the equivalent of an Xlib Display *) to start a
-service defined by the class ``EmacsService''. Eventually, this
-results in ``EmacsService.onCreate'' being called:
-
- @Override
- public void
- onCreate ()
- {
- AssetManager manager;
- Context app_context;
- String filesDir, libDir, cacheDir, classPath;
- double pixelDensityX;
- double pixelDensityY;
-
-Here is what this function does, step-by-step:
-
- SERVICE = this;
-
-First, it sets the special static variable ``SERVICE'' to ``this'',
-which is a pointer to the ``EmacsService' object that was created.
-
- handler = new Handler (Looper.getMainLooper ());
-
-Next, it creates a ``Handler'' object for the ``main looper''.
-This is a helper structure which allows executing code on the Android
-user interface thread.
-
- manager = getAssets ();
- app_context = getApplicationContext ();
- metrics = getResources ().getDisplayMetrics ();
- pixelDensityX = metrics.xdpi;
- pixelDensityY = metrics.ydpi;
-
-Finally, it obtains:
-
- - the asset manager, which is used to retrieve assets packaged
- into the Emacs application package.
-
- - the application context, used to obtain application specific
- information.
-
- - the display metrics, and from them, the X and Y densities in dots
- per inch.
-
-Then, inside a ``try'' block:
-
- try
- {
- /* Configure Emacs with the asset manager and other necessary
- parameters. */
- filesDir = app_context.getFilesDir ().getCanonicalPath ();
- libDir = getLibraryDirectory ();
- cacheDir = app_context.getCacheDir ().getCanonicalPath ();
-
-It obtains the names of the Emacs home, shared library, and temporary
-file directories.
-
- /* Now provide this application's apk file, so a recursive
- invocation of app_process (through android-emacs) can
- find EmacsNoninteractive. */
- classPath = getApkFile ();
-
-The name of the Emacs application package.
-
- Log.d (TAG, "Initializing Emacs, where filesDir = " + filesDir
- + ", libDir = " + libDir + ", and classPath = " + classPath);
-
-Prints a debug message to the Android system log with this
-information.
-
- EmacsNative.setEmacsParams (manager, filesDir, libDir,
- cacheDir, (float) pixelDensityX,
- (float) pixelDensityY,
- classPath, this);
-
-And calls the native function ``setEmacsParams'' (defined in
-android.c) to configure Emacs with this information.
-
- /* Start the thread that runs Emacs. */
- thread = new EmacsThread (this, needDashQ);
- thread.start ();
-
-Then, it allocates an ``EmacsThread'' object, and starts that thread.
-Inside that thread is where Emacs's C code runs.
-
- }
- catch (IOException exception)
- {
- EmacsNative.emacsAbort ();
- return;
-
-And here is the purpose of the ``try'' block. Functions related to
-file names in Java will signal errors of various types upon failure.
-
-This ``catch'' block means that the Java virtual machine will abort
-execution of the contents of the ``try'' block as soon as an error of
-type ``IOException'' is encountered, and begin executing the contents
-of the ``catch'' block.
-
-Any failure of that type here is a crash, and
-``EmacsNative.emacsAbort'' is called to quickly abort the process to
-get a useful backtrace.
- }
- }
-
-Now, let us look at the definition of the class ``EmacsThread'', found
-in org/gnu/emacs/EmacsThread.java:
-
-public class EmacsThread extends Thread
-{
- /* Whether or not Emacs should be started -Q. */
- private boolean startDashQ;
-
- public
- EmacsThread (EmacsService service, boolean startDashQ)
- {
- super ("Emacs main thread");
- this.startDashQ = startDashQ;
- }
-
- @Override
- public void
- run ()
- {
- String args[];
-
- if (!startDashQ)
- args = new String[] { "libandroid-emacs.so", };
- else
- args = new String[] { "libandroid-emacs.so", "-Q", };
-
- /* Run the native code now. */
- EmacsNative.initEmacs (args, EmacsApplication.dumpFileName);
- }
-};
-
-The class itself defines a single field, ``startDashQ'', a constructor
-with an unused argument of the type ``EmacsService'' (which is useful
-while debugging) and a flag ``startDashQ'', and a single function
-``run'', overriding the same function in the class ``Thread''.
-
-When ``thread.start'' is called, the Java virtual machine creates a
-new thread, and then calls the function ``run'' within that thread.
-
-This function then computes a suitable argument vector, and calls
-``EmacsNative.initEmacs'' (defined in android.c), which then calls a
-modified version of the regular Emacs ``main'' function.
-
-At that point, Emacs initialization proceeds as usual:
-Vinitial_window_system is set, loadup.el calls `normal-top-level',
-which calls `command-line', and finally
-`window-system-initialization', which initializes the `android'
-terminal interface as usual.
-
-What happens here is the same as on other platforms. Now, here is
-what happens when the initial frame is created: Fx_create_frame calls
-`android_create_frame_window' to create a top level window:
-
-static void
-android_create_frame_window (struct frame *f)
-{
- struct android_set_window_attributes attributes;
- enum android_window_value_mask attribute_mask;
-
- attributes.background_pixel = FRAME_BACKGROUND_PIXEL (f);
- attribute_mask = ANDROID_CW_BACK_PIXEL;
-
- block_input ();
- FRAME_ANDROID_WINDOW (f)
- = android_create_window (FRAME_DISPLAY_INFO (f)->root_window,
- f->left_pos,
- f->top_pos,
- FRAME_PIXEL_WIDTH (f),
- FRAME_PIXEL_HEIGHT (f),
- attribute_mask, &attributes);
- unblock_input ();
-}
-
-This calls the function `android_create_window' with some arguments
-whose meanings are identical to the arguments to `XCreateWindow'.
-
-Here is the definition of `android_create_window', in android.c:
-
-android_window
-android_create_window (android_window parent, int x, int y,
- int width, int height,
- enum android_window_value_mask value_mask,
- struct android_set_window_attributes *attrs)
-{
- static jclass class;
- static jmethodID constructor;
- jobject object, parent_object, old;
- android_window window;
- android_handle prev_max_handle;
- bool override_redirect;
-
-What does it do? First, some context:
-
-At any time, there can be at most 65535 Java objects referred to by
-the rest of Emacs through the Java native interface. Each such object
-is assigned a ``handle'' (similar to an XID on X) and given a unique
-type. The function `android_resolve_handle' returns the JNI `jobject'
-associated with a given handle.
-
- parent_object = android_resolve_handle (parent, ANDROID_HANDLE_WINDOW);
-
-Here, it is being used to look up the `jobject' associated with the
-`parent' handle.
-
- prev_max_handle = max_handle;
- window = android_alloc_id ();
-
-Next, `max_handle' is saved, and a new handle is allocated for
-`window'.
-
- if (!window)
- error ("Out of window handles!");
-
-An error is signalled if Emacs runs out of available handles.
-
- if (!class)
- {
- class = (*android_java_env)->FindClass (android_java_env,
- "org/gnu/emacs/EmacsWindow");
- assert (class != NULL);
-
-Then, if this initialization has not yet been completed, Emacs
-proceeds to find the Java class named ``EmacsWindow''.
-
- constructor
- = (*android_java_env)->GetMethodID (android_java_env, class, "<init>",
- "(SLorg/gnu/emacs/EmacsWindow;"
- "IIIIZ)V");
- assert (constructor != NULL);
-
-And it tries to look up the constructor, which should take seven
-arguments:
-
- S - a short. (the handle ID)
- Lorg/gnu/Emacs/EmacsWindow; - an instance of the EmacsWindow
- class. (the parent)
- IIII - four ints. (the window geometry.)
- Z - a boolean. (whether or not the
- window is override-redirect; see
- XChangeWindowAttributes.)
-
- old = class;
- class = (*android_java_env)->NewGlobalRef (android_java_env, class);
- (*android_java_env)->ExceptionClear (android_java_env);
- ANDROID_DELETE_LOCAL_REF (old);
-
-Next, it saves a global reference to the class and deletes the local
-reference. Global references will never be deallocated by the Java
-virtual machine as long as they still exist.
-
- if (!class)
- memory_full (0);
- }
-
- /* N.B. that ANDROID_CW_OVERRIDE_REDIRECT can only be set at window
- creation time. */
- override_redirect = ((value_mask
- & ANDROID_CW_OVERRIDE_REDIRECT)
- && attrs->override_redirect);
-
- object = (*android_java_env)->NewObject (android_java_env, class,
- constructor, (jshort) window,
- parent_object, (jint) x, (jint) y,
- (jint) width, (jint) height,
- (jboolean) override_redirect);
-
-Then, it creates an instance of the ``EmacsWindow'' class with the
-appropriate arguments and previously determined constructor.
-
- if (!object)
- {
- (*android_java_env)->ExceptionClear (android_java_env);
-
- max_handle = prev_max_handle;
- memory_full (0);
-
-If creating the object fails, Emacs clears the ``pending exception''
-and signals that it is out of memory.
- }
-
- android_handles[window].type = ANDROID_HANDLE_WINDOW;
- android_handles[window].handle
- = (*android_java_env)->NewGlobalRef (android_java_env,
- object);
- (*android_java_env)->ExceptionClear (android_java_env);
- ANDROID_DELETE_LOCAL_REF (object);
-
-Otherwise, it associates a new global reference to the object with the
-handle, and deletes the local reference returned from the JNI
-NewObject function.
-
- if (!android_handles[window].handle)
- memory_full (0);
-
-If allocating the global reference fails, Emacs signals that it is out
-of memory.
-
- android_change_window_attributes (window, value_mask, attrs);
- return window;
-
-Otherwise, it applies the specified window attributes and returns the
-handle of the new window.
-}
-
-
-
-DRAWABLES, CURSORS AND HANDLES
-
-Each widget created by Emacs corresponds to a single ``window'', which
-has its own backing store. This arrangement is quite similar to X.
-
-C code does not directly refer to the EmacsView widgets that implement
-the UI logic behind windows. Instead, its handles refer to
-EmacsWindow structures, which contain the state necessary to interact
-with the widgets in an orderly and synchronized manner.
-
-Like X, both pixmaps and windows are drawable resources, and the same
-graphics operations can be applied to both. Thus, a separate
-EmacsPixmap structure is used to wrap around Android Bitmap resources,
-and the Java-level graphics operation functions are capable of
-operating on them both.
-
-Finally, graphics contexts are maintained on both the C and Java
-levels; the C state recorded in `struct android_gc' is kept in sync
-with the Java state in the GContext handle's corresponding EmacsGC
-structure, and cursors are used through handles that refer to
-EmacsCursor structures that hold system PointerIcons.
-
-In all cases, the interfaces provided are identical to X.
-
-
-
-EVENT LOOP
-
-In a typical Android application, the event loop is managed by the
-operating system, and callbacks (implemented through overriding
-separate functions in widgets) are run by the event loop wherever
-necessary. The thread which runs the event loop is also the only
-thread capable of creating and manipulating widgets and activities,
-and is referred to as the ``UI thread''.
-
-These callbacks are used by Emacs to write representations of X-like
-events to a separate event queue, which are then read from Emacs's own
-event loop running in a separate thread. This is accomplished through
-replacing `select' by a function which waits for the event queue to be
-occupied, in addition to any file descriptors that `select' would
-normally wait for.
-
-Conversely, Emacs's event loop sometimes needs to send events to the
-UI thread. These events are implemented as tiny fragments of code,
-which are run as they are received by the main thread.
-
-A typical example is `displayToast', which is implemented in
-EmacsService.java:
-
- public void
- displayToast (final String string)
- {
- runOnUiThread (new Runnable () {
- @Override
- public void
- run ()
- {
- Toast toast;
-
- toast = Toast.makeText (getApplicationContext (),
- string, Toast.LENGTH_SHORT);
- toast.show ();
- }
- });
- }
-
-Here, the variable `string' is used by a nested function. This nested
-function contains a copy of that variable, and is run on the main
-thread using the function `runOnUiThread', in order to display a short
-status message on the display.
-
-When Emacs needs to wait for the nested function to finish, it uses a
-mechanism implemented in `syncRunnable'. This mechanism first calls a
-deadlock avoidance mechanism, then runs a nested function on the UI
-thread, which is expected to signal itself as a condition variable
-upon completion. It is typically used to allocate resources that can
-only be allocated from the UI thread, or to obtain non-thread-safe
-information. The following function is an example; it returns a new
-EmacsView widget corresponding to the provided window:
-
- public EmacsView
- getEmacsView (final EmacsWindow window, final int visibility,
- final boolean isFocusedByDefault)
- {
- Runnable runnable;
- final EmacsHolder<EmacsView> view;
-
- view = new EmacsHolder<EmacsView> ();
-
- runnable = new Runnable () {
- public void
- run ()
- {
- synchronized (this)
- {
- view.thing = new EmacsView (window);
- view.thing.setVisibility (visibility);
-
- /* The following function is only present on Android 26
- or later. */
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
- view.thing.setFocusedByDefault (isFocusedByDefault);
-
- notify ();
- }
- }
- };
-
- syncRunnable (runnable);
- return view.thing;
- }
-
-As no value can be directly returned from the nested function, a
-separate container object is used to hold the result after the
-function finishes execution. Note the type name inside the angle
-brackets: this type is substituted into the class definition as it is
-used; a definition such as:
-
-public class Foo<T>
-{
- T bar;
-};
-
-can not be used alone:
-
- Foo holder; /* Error! */
-
-but must have a type specified:
-
- Foo<Object> holder;
-
-in which case the effective definition is:
-
-public class Foo
-{
- Object bar;
-};
+Refer to the file `admin/notes/java' in the toplevel directory of the
+Emacs distribution or repository for specifics regarding writing Java
+code for Emacs and the organization of the Android port.
diff --git a/java/debug.sh b/java/debug.sh
index d6e439bec90..8fc03d014cf 100755
--- a/java/debug.sh
+++ b/java/debug.sh
@@ -1,7 +1,7 @@
#!/bin/bash
### Run Emacs under GDB or JDB on Android.
-## Copyright (C) 2023 Free Software Foundation, Inc.
+## Copyright (C) 2023-2024 Free Software Foundation, Inc.
## This file is part of GNU Emacs.
diff --git a/java/org/gnu/emacs/EmacsActivity.java b/java/org/gnu/emacs/EmacsActivity.java
index 4ddf51fbb20..3237f650240 100644
--- a/java/org/gnu/emacs/EmacsActivity.java
+++ b/java/org/gnu/emacs/EmacsActivity.java
@@ -1,6 +1,6 @@
/* Communication module for Android terminals. -*- c-file-style: "GNU" -*-
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
@@ -89,8 +89,11 @@ public class EmacsActivity extends Activity
if (window.view.isFocused ())
focusedWindow = window;
- for (EmacsWindow child : window.children)
- invalidateFocus1 (child);
+ synchronized (window.children)
+ {
+ for (EmacsWindow child : window.children)
+ invalidateFocus1 (child);
+ }
}
public static void
@@ -149,8 +152,6 @@ public class EmacsActivity extends Activity
public final void
attachWindow (EmacsWindow child)
{
- Log.d (TAG, "attachWindow: " + child);
-
if (window != null)
throw new IllegalStateException ("trying to attach window when one"
+ " already exists");
@@ -257,7 +258,6 @@ public class EmacsActivity extends Activity
/* The activity will die shortly hereafter. If there is a window
attached, close it now. */
- Log.d (TAG, "onDestroy " + this);
isMultitask = this instanceof EmacsMultitaskActivity;
manager.removeWindowConsumer (this, isMultitask || isFinishing ());
focusedActivities.remove (this);
@@ -274,9 +274,6 @@ public class EmacsActivity extends Activity
public final void
onWindowFocusChanged (boolean isFocused)
{
- Log.d (TAG, ("onWindowFocusChanged: "
- + (isFocused ? "YES" : "NO")));
-
if (isFocused && !focusedActivities.contains (this))
{
focusedActivities.add (this);
@@ -323,8 +320,6 @@ public class EmacsActivity extends Activity
{
int serial;
- Log.d (TAG, "onContextMenuClosed: " + menu);
-
/* See the comment inside onMenuItemClick. */
if (((EmacsContextMenu.wasSubmenuSelected == -2)
diff --git a/java/org/gnu/emacs/EmacsApplication.java b/java/org/gnu/emacs/EmacsApplication.java
index 8afa5bcedb4..b5f8e688b65 100644
--- a/java/org/gnu/emacs/EmacsApplication.java
+++ b/java/org/gnu/emacs/EmacsApplication.java
@@ -1,6 +1,6 @@
/* Communication module for Android terminals. -*- c-file-style: "GNU" -*-
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
@@ -25,19 +25,61 @@ import java.io.FileFilter;
import android.content.Context;
import android.app.Application;
+
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager.ApplicationInfoFlags;
+import android.content.pm.PackageManager;
+
+import android.os.Build;
+
import android.util.Log;
public final class EmacsApplication extends Application
{
private static final String TAG = "EmacsApplication";
- /* The name of the dump file to use. */
+ /* The name of the dump file to use, or NULL if this Emacs binary
+ has yet to be dumped. */
public static String dumpFileName;
+ /* The name of the APK file housing Emacs, or NULL if it could not
+ be ascertained. */
+ public static String apkFileName;
+
+ @SuppressWarnings ("deprecation")
+ private String
+ getApkFile ()
+ {
+ PackageManager manager;
+ ApplicationInfo info;
+
+ manager = getPackageManager ();
+
+ try
+ {
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU)
+ info = manager.getApplicationInfo ("org.gnu.emacs", 0);
+ else
+ info = manager.getApplicationInfo ("org.gnu.emacs",
+ ApplicationInfoFlags.of (0));
+
+ /* Return an empty string upon failure. */
+
+ if (info.sourceDir != null)
+ return info.sourceDir;
+
+ return null;
+ }
+ catch (Exception e)
+ {
+ return null;
+ }
+ }
+
public static void
findDumpFile (Context context)
{
- File filesDirectory;
+ File filesDirectory, apk;
File[] allFiles;
String wantedDumpFile;
int i;
@@ -67,7 +109,29 @@ public final class EmacsApplication extends Application
for (i = 0; i < allFiles.length; ++i)
{
if (allFiles[i].getName ().equals (wantedDumpFile))
- dumpFileName = allFiles[i].getAbsolutePath ();
+ {
+ /* Compare the last modified time of the dumpfile with
+ that of apkFileName, the time at which Emacs was
+ installed. Delete it if the dump file was created
+ before Emacs was installed, even if the C signature
+ (representing libemacs.so) remains identical. */
+
+ if (apkFileName != null)
+ {
+ apk = new File (apkFileName);
+
+ if (apk.lastModified ()
+ > allFiles[i].lastModified ())
+ {
+ allFiles[i].delete ();
+
+ /* Don't set the dump file name in this case. */
+ continue;
+ }
+ }
+
+ dumpFileName = allFiles[i].getAbsolutePath ();
+ }
else
/* Delete this outdated dump file. */
allFiles[i].delete ();
@@ -83,6 +147,9 @@ public final class EmacsApplication extends Application
will be restored for the Emacs thread in `initEmacs'. */
EmacsNative.setupSystemThread ();
+ /* Establish the name of the APK. */
+ apkFileName = getApkFile ();
+
/* Locate a suitable dump file. */
findDumpFile (this);
diff --git a/java/org/gnu/emacs/EmacsClipboard.java b/java/org/gnu/emacs/EmacsClipboard.java
index 5cd48af6e3a..9db436ca1e2 100644
--- a/java/org/gnu/emacs/EmacsClipboard.java
+++ b/java/org/gnu/emacs/EmacsClipboard.java
@@ -1,6 +1,6 @@
/* Communication module for Android terminals. -*- c-file-style: "GNU" -*-
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/java/org/gnu/emacs/EmacsContextMenu.java b/java/org/gnu/emacs/EmacsContextMenu.java
index 46eddeeda3d..17e6033377d 100644
--- a/java/org/gnu/emacs/EmacsContextMenu.java
+++ b/java/org/gnu/emacs/EmacsContextMenu.java
@@ -1,6 +1,6 @@
/* Communication module for Android terminals. -*- c-file-style: "GNU" -*-
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
@@ -22,6 +22,9 @@ package org.gnu.emacs;
import java.util.List;
import java.util.ArrayList;
+import java.util.concurrent.Callable;
+import java.util.concurrent.FutureTask;
+
import android.content.Context;
import android.content.Intent;
@@ -36,7 +39,7 @@ import android.view.SubMenu;
import android.util.Log;
/* Context menu implementation. This object is built from JNI and
- describes a menu hiearchy. Then, `inflate' can turn it into an
+ describes a menu hierarchy. Then, `inflate' can turn it into an
Android menu, which can be turned into a popup (or other kind of)
menu. */
@@ -72,8 +75,6 @@ public final class EmacsContextMenu
public boolean
onMenuItemClick (MenuItem item)
{
- Log.d (TAG, "onMenuItemClick: " + itemName + " (" + itemID + ")");
-
if (subMenu != null)
{
/* Android 6.0 and earlier don't support nested submenus
@@ -81,8 +82,6 @@ public final class EmacsContextMenu
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N)
{
- Log.d (TAG, "onMenuItemClick: displaying submenu " + subMenu);
-
/* Still set wasSubmenuSelected -- if not set, the
dismissal of this context menu will result in a
context menu event being sent. */
@@ -348,28 +347,26 @@ public final class EmacsContextMenu
display (final EmacsWindow window, final int xPosition,
final int yPosition, final int serial)
{
- Runnable runnable;
- final EmacsHolder<Boolean> rc;
+ FutureTask<Boolean> task;
+
+ /* Android will permanently cease to display any popup menus at
+ all if the list of menu items is empty. Prevent this by
+ promptly returning if there are no menu items. */
- rc = new EmacsHolder<Boolean> ();
- rc.thing = false;
+ if (menuItems.isEmpty ())
+ return false;
- runnable = new Runnable () {
+ task = new FutureTask<Boolean> (new Callable<Boolean> () {
@Override
- public void
- run ()
+ public Boolean
+ call ()
{
- synchronized (this)
- {
- lastMenuEventSerial = serial;
- rc.thing = display1 (window, xPosition, yPosition);
- notify ();
- }
+ lastMenuEventSerial = serial;
+ return display1 (window, xPosition, yPosition);
}
- };
+ });
- EmacsService.syncRunnable (runnable);
- return rc.thing;
+ return EmacsService.<Boolean>syncRunnable (task);
}
/* Dismiss this context menu. WINDOW is the window where the
diff --git a/java/org/gnu/emacs/EmacsCursor.java b/java/org/gnu/emacs/EmacsCursor.java
index c14c6f2a11b..1049c03d7da 100644
--- a/java/org/gnu/emacs/EmacsCursor.java
+++ b/java/org/gnu/emacs/EmacsCursor.java
@@ -1,6 +1,6 @@
/* Communication module for Android terminals. -*- c-file-style: "GNU" -*-
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/java/org/gnu/emacs/EmacsDesktopNotification.java b/java/org/gnu/emacs/EmacsDesktopNotification.java
index 121d8f481a2..fb35e3fea1f 100644
--- a/java/org/gnu/emacs/EmacsDesktopNotification.java
+++ b/java/org/gnu/emacs/EmacsDesktopNotification.java
@@ -1,6 +1,6 @@
/* Communication module for Android terminals. -*- c-file-style: "GNU" -*-
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
@@ -96,6 +96,7 @@ public final class EmacsDesktopNotification
RemoteViews contentView;
Intent intent;
PendingIntent pending;
+ int priority;
tem = context.getSystemService (Context.NOTIFICATION_SERVICE);
manager = (NotificationManager) tem;
@@ -116,11 +117,37 @@ public final class EmacsDesktopNotification
.build ());
}
else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
- notification = (new Notification.Builder (context)
- .setContentTitle (title)
- .setContentText (content)
- .setSmallIcon (icon)
- .build ());
+ {
+ /* Android 7.1 and earlier don't segregate notifications into
+ distinct categories, but permit an importance to be
+ assigned to each individual notification. */
+
+ switch (importance)
+ {
+ case 2: /* IMPORTANCE_LOW */
+ default:
+ priority = Notification.PRIORITY_LOW;
+ break;
+
+ case 3: /* IMPORTANCE_DEFAULT */
+ priority = Notification.PRIORITY_DEFAULT;
+ break;
+
+ case 4: /* IMPORTANCE_HIGH */
+ priority = Notification.PRIORITY_HIGH;
+ break;
+ }
+
+ notification = (new Notification.Builder (context)
+ .setContentTitle (title)
+ .setContentText (content)
+ .setSmallIcon (icon)
+ .setPriority (priority)
+ .build ());
+
+ if (Build.VERSION.SDK_INT > Build.VERSION_CODES.JELLY_BEAN)
+ notification.priority = priority;
+ }
else
{
notification = new Notification ();
diff --git a/java/org/gnu/emacs/EmacsDialog.java b/java/org/gnu/emacs/EmacsDialog.java
index 2291207fbcc..0d5b650f7d0 100644
--- a/java/org/gnu/emacs/EmacsDialog.java
+++ b/java/org/gnu/emacs/EmacsDialog.java
@@ -1,6 +1,6 @@
/* Communication module for Android terminals. -*- c-file-style: "GNU" -*-
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
@@ -22,6 +22,9 @@ package org.gnu.emacs;
import java.util.List;
import java.util.ArrayList;
+import java.util.concurrent.Callable;
+import java.util.concurrent.FutureTask;
+
import android.app.AlertDialog;
import android.content.Context;
@@ -41,6 +44,7 @@ import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.FrameLayout;
+import android.view.ContextThemeWrapper;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
@@ -88,8 +92,6 @@ public final class EmacsDialog implements DialogInterface.OnDismissListener
public void
onClick (View view)
{
- Log.d (TAG, "onClicked " + this);
-
wasButtonClicked = true;
EmacsNative.sendContextMenu ((short) 0, id, menuEventSerial);
dismissDialog.dismiss ();
@@ -99,8 +101,6 @@ public final class EmacsDialog implements DialogInterface.OnDismissListener
public void
onClick (DialogInterface dialog, int which)
{
- Log.d (TAG, "onClicked " + this);
-
wasButtonClicked = true;
EmacsNative.sendContextMenu ((short) 0, id, menuEventSerial);
}
@@ -162,6 +162,13 @@ public final class EmacsDialog implements DialogInterface.OnDismissListener
TypedArray attributes;
Window window;
+ /* Wrap the context within a style wrapper. Any dialog properties
+ tied to EmacsStyle (such as those applied by the system ``dark
+ theme'') will thus affect the dialog irrespective of whether
+ CONTEXT is an activity or the service. */
+
+ context = new ContextThemeWrapper (context, R.style.EmacsStyle);
+
size = buttons.size ();
styleId = -1;
@@ -300,10 +307,6 @@ public final class EmacsDialog implements DialogInterface.OnDismissListener
work, then any focused EmacsOpenActivity, and finally the
last EmacsActivity to be focused. */
- Log.d (TAG, "display1: no focused activities...");
- Log.d (TAG, ("display1: EmacsOpenActivity.currentActivity: "
- + EmacsOpenActivity.currentActivity));
-
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M
|| Settings.canDrawOverlays (EmacsService.SERVICE))
context = EmacsService.SERVICE;
@@ -321,8 +324,6 @@ public final class EmacsDialog implements DialogInterface.OnDismissListener
consistently. */
context = EmacsActivity.focusedActivities.get (0);
- Log.d (TAG, "display1: using context " + context);
-
dialog = dismissDialog = toAlertDialog (context);
try
@@ -390,26 +391,18 @@ public final class EmacsDialog implements DialogInterface.OnDismissListener
public boolean
display ()
{
- Runnable runnable;
- final EmacsHolder<Boolean> rc;
+ FutureTask<Boolean> task;
- rc = new EmacsHolder<Boolean> ();
- rc.thing = false;
- runnable = new Runnable () {
+ task = new FutureTask<Boolean> (new Callable<Boolean> () {
@Override
- public void
- run ()
+ public Boolean
+ call ()
{
- synchronized (this)
- {
- rc.thing = display1 ();
- notify ();
- }
+ return display1 ();
}
- };
+ });
- EmacsService.syncRunnable (runnable);
- return rc.thing;
+ return EmacsService.<Boolean>syncRunnable (task);
}
@@ -418,8 +411,6 @@ public final class EmacsDialog implements DialogInterface.OnDismissListener
public void
onDismiss (DialogInterface dialog)
{
- Log.d (TAG, "onDismiss: " + this);
-
if (wasButtonClicked)
return;
diff --git a/java/org/gnu/emacs/EmacsDialogButtonLayout.java b/java/org/gnu/emacs/EmacsDialogButtonLayout.java
index fd8d63d81d3..da57d1c4404 100644
--- a/java/org/gnu/emacs/EmacsDialogButtonLayout.java
+++ b/java/org/gnu/emacs/EmacsDialogButtonLayout.java
@@ -1,6 +1,6 @@
/* Communication module for Android terminals. -*- c-file-style: "GNU" -*-
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/java/org/gnu/emacs/EmacsDirectoryEntry.java b/java/org/gnu/emacs/EmacsDirectoryEntry.java
index 75c52e48002..4a7526dddc6 100644
--- a/java/org/gnu/emacs/EmacsDirectoryEntry.java
+++ b/java/org/gnu/emacs/EmacsDirectoryEntry.java
@@ -1,6 +1,6 @@
/* Communication module for Android terminals. -*- c-file-style: "GNU" -*-
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/java/org/gnu/emacs/EmacsDocumentsProvider.java b/java/org/gnu/emacs/EmacsDocumentsProvider.java
index 96dc2bc6e14..7c5de9e0e14 100644
--- a/java/org/gnu/emacs/EmacsDocumentsProvider.java
+++ b/java/org/gnu/emacs/EmacsDocumentsProvider.java
@@ -1,6 +1,6 @@
/* Communication module for Android terminals. -*- c-file-style: "GNU" -*-
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/java/org/gnu/emacs/EmacsDrawLine.java b/java/org/gnu/emacs/EmacsDrawLine.java
index d367ccff9c4..61b7d54d63c 100644
--- a/java/org/gnu/emacs/EmacsDrawLine.java
+++ b/java/org/gnu/emacs/EmacsDrawLine.java
@@ -1,6 +1,6 @@
/* Communication module for Android terminals. -*- c-file-style: "GNU" -*-
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
@@ -29,7 +29,6 @@ public final class EmacsDrawLine
perform (EmacsDrawable drawable, EmacsGC gc,
int x, int y, int x2, int y2)
{
- Rect rect;
Canvas canvas;
Paint paint;
int x0, x1, y0, y1;
@@ -48,7 +47,6 @@ public final class EmacsDrawLine
/* And the clip rectangle. */
paint = gc.gcPaint;
- rect = new Rect (x0, y0, x1, y1);
canvas = drawable.lockCanvas (gc);
if (canvas == null)
@@ -74,6 +72,6 @@ public final class EmacsDrawLine
/* DrawLine with clip mask not implemented; it is not used by
Emacs. */
- drawable.damageRect (rect);
+ drawable.damageRect (x0, y0, x1, y1);
}
}
diff --git a/java/org/gnu/emacs/EmacsDrawPoint.java b/java/org/gnu/emacs/EmacsDrawPoint.java
index 6a1cb744d60..859c590b1d0 100644
--- a/java/org/gnu/emacs/EmacsDrawPoint.java
+++ b/java/org/gnu/emacs/EmacsDrawPoint.java
@@ -1,6 +1,6 @@
/* Communication module for Android terminals. -*- c-file-style: "GNU" -*-
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/java/org/gnu/emacs/EmacsDrawRectangle.java b/java/org/gnu/emacs/EmacsDrawRectangle.java
index e1261b4a2d2..a8f68c6530a 100644
--- a/java/org/gnu/emacs/EmacsDrawRectangle.java
+++ b/java/org/gnu/emacs/EmacsDrawRectangle.java
@@ -1,6 +1,6 @@
/* Communication module for Android terminals. -*- c-file-style: "GNU" -*-
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
@@ -114,7 +114,6 @@ public final class EmacsDrawRectangle
maskBitmap.recycle ();
}
- drawable.damageRect (new Rect (x, y, x + width + 1,
- y + height + 1));
+ drawable.damageRect (x, y, x + width + 1, y + height + 1);
}
}
diff --git a/java/org/gnu/emacs/EmacsDrawable.java b/java/org/gnu/emacs/EmacsDrawable.java
index f2f8885e976..a75a8f7017d 100644
--- a/java/org/gnu/emacs/EmacsDrawable.java
+++ b/java/org/gnu/emacs/EmacsDrawable.java
@@ -1,6 +1,6 @@
/* Communication module for Android terminals. -*- c-file-style: "GNU" -*-
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
@@ -27,6 +27,7 @@ public interface EmacsDrawable
{
public Canvas lockCanvas (EmacsGC gc);
public void damageRect (Rect damageRect);
+ public void damageRect (int left, int top, int right, int bottom);
public Bitmap getBitmap ();
public boolean isDestroyed ();
};
diff --git a/java/org/gnu/emacs/EmacsFillPolygon.java b/java/org/gnu/emacs/EmacsFillPolygon.java
index 4ae3882cab4..6bc8333984a 100644
--- a/java/org/gnu/emacs/EmacsFillPolygon.java
+++ b/java/org/gnu/emacs/EmacsFillPolygon.java
@@ -1,6 +1,6 @@
/* Communication module for Android terminals. -*- c-file-style: "GNU" -*-
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/java/org/gnu/emacs/EmacsFillRectangle.java b/java/org/gnu/emacs/EmacsFillRectangle.java
index 461fd3c639c..ca87c06c014 100644
--- a/java/org/gnu/emacs/EmacsFillRectangle.java
+++ b/java/org/gnu/emacs/EmacsFillRectangle.java
@@ -1,6 +1,6 @@
/* Communication module for Android terminals. -*- c-file-style: "GNU" -*-
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/java/org/gnu/emacs/EmacsFontDriver.java b/java/org/gnu/emacs/EmacsFontDriver.java
index ff52899a897..09d0377bd5e 100644
--- a/java/org/gnu/emacs/EmacsFontDriver.java
+++ b/java/org/gnu/emacs/EmacsFontDriver.java
@@ -1,6 +1,6 @@
/* Font backend for Android terminals. -*- c-file-style: "GNU" -*-
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
@@ -63,6 +63,11 @@ public abstract class EmacsFontDriver
public static final int MONO = 100;
public static final int CHARCELL = 110;
+ /* Special glyph codes. */
+ public static final int FONT_INVALID_CODE = 0xFFFFFFFF;
+
+
+
public static class FontSpec
{
/* The fields below mean the same as they do in enum
@@ -148,15 +153,17 @@ public abstract class EmacsFontDriver
}
};
+
+
/* These mean the same as they do in struct font_driver. */
public abstract FontEntity[] list (FontSpec fontSpec);
public abstract FontEntity match (FontSpec fontSpec);
public abstract String[] listFamilies ();
public abstract FontObject openFont (FontEntity fontEntity, int pixelSize);
- public abstract int hasChar (FontSpec font, char charCode);
+ public abstract int hasChar (FontSpec font, int charCode);
public abstract void textExtents (FontObject font, int code[],
FontMetrics fontMetrics);
- public abstract int encodeChar (FontObject fontObject, char charCode);
+ public abstract int encodeChar (FontObject fontObject, int charCode);
public abstract int draw (FontObject fontObject, EmacsGC gc,
EmacsDrawable drawable, int[] chars,
int x, int y, int backgroundWidth,
diff --git a/java/org/gnu/emacs/EmacsGC.java b/java/org/gnu/emacs/EmacsGC.java
index a7467cb9bd0..e45f0666fe2 100644
--- a/java/org/gnu/emacs/EmacsGC.java
+++ b/java/org/gnu/emacs/EmacsGC.java
@@ -1,6 +1,6 @@
/* Communication module for Android terminals. -*- c-file-style: "GNU" -*-
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/java/org/gnu/emacs/EmacsHandleObject.java b/java/org/gnu/emacs/EmacsHandleObject.java
index 5b889895337..8534f08519c 100644
--- a/java/org/gnu/emacs/EmacsHandleObject.java
+++ b/java/org/gnu/emacs/EmacsHandleObject.java
@@ -1,6 +1,6 @@
/* Communication module for Android terminals. -*- c-file-style: "GNU" -*-
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/java/org/gnu/emacs/EmacsHolder.java b/java/org/gnu/emacs/EmacsHolder.java
index 6cd48ba57ce..6d093d27e06 100644
--- a/java/org/gnu/emacs/EmacsHolder.java
+++ b/java/org/gnu/emacs/EmacsHolder.java
@@ -1,6 +1,6 @@
/* Communication module for Android terminals. -*- c-file-style: "GNU" -*-
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/java/org/gnu/emacs/EmacsInputConnection.java b/java/org/gnu/emacs/EmacsInputConnection.java
index c3764a7b29f..054eca66cf3 100644
--- a/java/org/gnu/emacs/EmacsInputConnection.java
+++ b/java/org/gnu/emacs/EmacsInputConnection.java
@@ -1,6 +1,6 @@
/* Communication module for Android terminals. -*- c-file-style: "GNU" -*-
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
@@ -60,7 +60,7 @@ public final class EmacsInputConnection implements InputConnection
This helps with on screen keyboard programs found in some vendor
versions of Android, which rely on immediate updates to the point
- position after text is commited in order to place the cursor
+ position after text is committed in order to place the cursor
within that text. */
private static boolean syncAfterCommit;
@@ -628,6 +628,21 @@ public final class EmacsInputConnection implements InputConnection
batchEditCount = 0;
}
+ @Override
+ public boolean
+ replaceText (int start, int end, CharSequence text,
+ int newCursorPosition, TextAttribute attributes)
+ {
+ if (EmacsService.DEBUG_IC)
+ Log.d (TAG, ("replaceText: " + text + ":: " + start + ","
+ + end + "," + newCursorPosition));
+
+ EmacsNative.replaceText (windowHandle, start, end,
+ text.toString (), newCursorPosition,
+ attributes);
+ return true;
+ }
+
public void
diff --git a/java/org/gnu/emacs/EmacsLauncherPreferencesActivity.java b/java/org/gnu/emacs/EmacsLauncherPreferencesActivity.java
index 1e1e5d97631..21a43b261a0 100644
--- a/java/org/gnu/emacs/EmacsLauncherPreferencesActivity.java
+++ b/java/org/gnu/emacs/EmacsLauncherPreferencesActivity.java
@@ -1,6 +1,6 @@
/* Communication module for Android terminals. -*- c-file-style: "GNU" -*-
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/java/org/gnu/emacs/EmacsMultitaskActivity.java b/java/org/gnu/emacs/EmacsMultitaskActivity.java
index b1c48f03fba..7229e34496e 100644
--- a/java/org/gnu/emacs/EmacsMultitaskActivity.java
+++ b/java/org/gnu/emacs/EmacsMultitaskActivity.java
@@ -1,6 +1,6 @@
/* Communication module for Android terminals. -*- c-file-style: "GNU" -*-
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/java/org/gnu/emacs/EmacsNative.java b/java/org/gnu/emacs/EmacsNative.java
index fae0ba98f86..cd0e70923d1 100644
--- a/java/org/gnu/emacs/EmacsNative.java
+++ b/java/org/gnu/emacs/EmacsNative.java
@@ -1,6 +1,6 @@
/* Communication module for Android terminals. -*- c-file-style: "GNU" -*-
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
@@ -26,6 +26,7 @@ import android.graphics.Bitmap;
import android.view.inputmethod.ExtractedText;
import android.view.inputmethod.ExtractedTextRequest;
import android.view.inputmethod.SurroundingText;
+import android.view.inputmethod.TextAttribute;
import android.view.inputmethod.TextSnapshot;
public final class EmacsNative
@@ -38,6 +39,9 @@ public final class EmacsNative
/* Like `dup' in C. */
public static native int dup (int fd);
+ /* Like `close' in C. */
+ public static native int close (int fd);
+
/* Obtain the fingerprint of this build of Emacs. The fingerprint
can be used to determine the dump file name. */
public static native String getFingerprint ();
@@ -88,6 +92,13 @@ public final class EmacsNative
loadup.el itself. */
public static native void initEmacs (String argv[], String dumpFile);
+ /* Call shut_down_emacs to auto-save and unlock files in the main
+ thread, then return. */
+ public static native void shutDownEmacs ();
+
+ /* Garbage collect and clear each frame's image cache. */
+ public static native void onLowMemory ();
+
/* Abort and generate a native core dump. */
public static native void emacsAbort ();
@@ -174,6 +185,17 @@ public final class EmacsNative
public static native long sendExpose (short window, int x, int y,
int width, int height);
+ /* Send an ANDROID_DND_DRAG event. */
+ public static native long sendDndDrag (short window, int x, int y);
+
+ /* Send an ANDROID_DND_URI event. */
+ public static native long sendDndUri (short window, int x, int y,
+ String text);
+
+ /* Send an ANDROID_DND_TEXT event. */
+ public static native long sendDndText (short window, int x, int y,
+ String text);
+
/* Return the file name associated with the specified file
descriptor, or NULL if there is none. */
public static native byte[] getProcName (int fd);
@@ -196,6 +218,10 @@ public final class EmacsNative
KEYCODE_VOLUME_MUTE should be forwarded to Emacs. */
public static native boolean shouldForwardMultimediaButtons ();
+ /* Return whether KEYCODE_SPACE combined with META_CTRL_MASK should
+ be prevented from reaching the system input method. */
+ public static native boolean shouldForwardCtrlSpace ();
+
/* Initialize the current thread, by blocking signals that do not
interest it. */
public static native void setupSystemThread ();
@@ -215,6 +241,9 @@ public final class EmacsNative
int leftLength,
int rightLength);
public static native void finishComposingText (short window);
+ public static native void replaceText (short window, int start, int end,
+ String text, int newCursorPosition,
+ TextAttribute attributes);
public static native String getSelectedText (short window, int flags);
public static native String getTextAfterCursor (short window, int length,
int flags);
diff --git a/java/org/gnu/emacs/EmacsNoninteractive.java b/java/org/gnu/emacs/EmacsNoninteractive.java
index 1c7513e1cc9..ba23399cb3e 100644
--- a/java/org/gnu/emacs/EmacsNoninteractive.java
+++ b/java/org/gnu/emacs/EmacsNoninteractive.java
@@ -1,6 +1,6 @@
/* Communication module for Android terminals. -*- c-file-style: "GNU" -*-
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/java/org/gnu/emacs/EmacsOpenActivity.java b/java/org/gnu/emacs/EmacsOpenActivity.java
index 3832cd2faab..9ae1bf353dd 100644
--- a/java/org/gnu/emacs/EmacsOpenActivity.java
+++ b/java/org/gnu/emacs/EmacsOpenActivity.java
@@ -1,6 +1,6 @@
/* Communication module for Android terminals. -*- c-file-style: "GNU" -*-
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
@@ -55,6 +55,7 @@ import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.ParcelFileDescriptor;
+import android.os.Parcelable;
import android.util.Log;
@@ -67,6 +68,8 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
+import java.util.List;
+
public final class EmacsOpenActivity extends Activity
implements DialogInterface.OnClickListener,
DialogInterface.OnCancelListener
@@ -213,12 +216,13 @@ public final class EmacsOpenActivity extends Activity
dialog.show ();
}
- /* Check that the specified FILE is readable. If Android 4.4 or
- later is being used, return URI formatted into a `/content/' file
- name.
+ /* Check that the specified FILE is non-NULL and readable.
If it is not, then copy the file in FD to a location in the
- system cache directory and return the name of that file. */
+ system cache directory and return the name of that file.
+
+ Alternatively, return URI formatted into a `/content/' file name
+ if the system runs Android 4.4 or later. */
private String
checkReadableOrCopy (String file, ParcelFileDescriptor fd,
@@ -232,24 +236,34 @@ public final class EmacsOpenActivity extends Activity
int read;
String content;
- Log.d (TAG, "checkReadableOrCopy: " + file);
-
- inFile = new File (file);
+ if (file != null)
+ {
+ inFile = new File (file);
- if (inFile.canRead ())
- return file;
+ if (inFile.canRead ())
+ return file;
- Log.d (TAG, "checkReadableOrCopy: NO");
+ content = inFile.getName ();
+ }
+ else
+ /* content is the name of this content file if the next branch
+ is not taken. */
+ content = uri.getLastPathSegment ();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)
{
content = EmacsService.buildContentName (uri);
- Log.d (TAG, "checkReadableOrCopy: " + content);
return content;
}
+ /* The file is unnamed if content is NULL. Generate a unique
+ name with the current time as a reference. */
+
+ if (content == null)
+ content = "content." + System.currentTimeMillis () / 1000;
+
/* inFile is now the file being written to. */
- inFile = new File (getCacheDir (), inFile.getName ());
+ inFile = new File (getCacheDir (), content);
buffer = new byte[4098];
/* Initialize both streams to NULL. */
@@ -331,8 +345,14 @@ public final class EmacsOpenActivity extends Activity
});
}
+ /* Start `emacsclient' with the provided list of ARGUMENTS, after
+ ARGUMENTS[0] is replaced with the name of the emacsclient binary.
+
+ Create a new thread to await its completion, subsequently
+ reporting any errors that arise to the user. */
+
public void
- startEmacsClient (String fileName)
+ startEmacsClient (String[] arguments)
{
String libDir;
ProcessBuilder builder;
@@ -341,23 +361,10 @@ public final class EmacsOpenActivity extends Activity
File file;
Intent intent;
- /* If the Emacs service is not running, then start Emacs and make
- it open this file. */
-
- if (EmacsService.SERVICE == null)
- {
- fileToOpen = fileName;
- intent = new Intent (EmacsOpenActivity.this,
- EmacsActivity.class);
- finish ();
- startActivity (intent);
- return;
- }
-
libDir = EmacsService.getLibraryDirectory (this);
- builder = new ProcessBuilder (libDir + "/libemacsclient.so",
- fileName, "--reuse-frame",
- "--timeout=10", "--no-wait");
+ arguments[0] = libDir + "/libemacsclient.so";
+
+ builder = new ProcessBuilder (arguments);
/* Redirection is unfortunately not possible in Android 7 and
earlier. */
@@ -392,6 +399,7 @@ public final class EmacsOpenActivity extends Activity
Finally, display any error message, transfer the focus to an
Emacs frame, and finish the activity. */
+ @SuppressWarnings ("deprecation") /* getParcelableExtra */
@Override
public void
onCreate (Bundle savedInstanceState)
@@ -402,7 +410,13 @@ public final class EmacsOpenActivity extends Activity
ContentResolver resolver;
ParcelFileDescriptor fd;
byte[] names;
- String errorBlurb;
+ String errorBlurb, scheme;
+ String subjectString, textString, attachmentString;
+ CharSequence tem;
+ String tem1;
+ String[] emails;
+ StringBuilder builder;
+ List<Parcelable> list;
super.onCreate (savedInstanceState);
@@ -420,7 +434,9 @@ public final class EmacsOpenActivity extends Activity
if (action.equals ("android.intent.action.VIEW")
|| action.equals ("android.intent.action.EDIT")
- || action.equals ("android.intent.action.PICK"))
+ || action.equals ("android.intent.action.PICK")
+ || action.equals ("android.intent.action.SEND")
+ || action.equals ("android.intent.action.SENDTO"))
{
/* Obtain the URI of the action. */
uri = intent.getData ();
@@ -431,15 +447,162 @@ public final class EmacsOpenActivity extends Activity
return;
}
+ scheme = uri.getScheme ();
+
+ /* It is possible for scheme to be NULL, under Android 2.3 at
+ least. */
+
+ if (scheme == null)
+ return;
+
+ /* If URL is a mailto URI, call `message-mailto' much the same
+ way emacsclient-mail.desktop does. */
+
+ if (scheme.equals ("mailto"))
+ {
+ /* Escape the special characters $ and " before enclosing
+ the string within the `message-mailto' wrapper. */
+ fileName = uri.toString ();
+
+ /* If fileName is merely mailto: (absent either an email
+ address or content), then the program launching Emacs
+ conceivably provided such an URI to exclude non-email
+ programs from the Share dialog. Intents created thus
+ might hold the recipient email as a string array, which
+ is non-standard behavior. */
+
+ if (fileName.equals ("mailto:") || fileName.equals ("mailto://"))
+ {
+ emails = intent.getStringArrayExtra (Intent.EXTRA_EMAIL);
+
+ if (emails[0] != null && emails.length > 0)
+ fileName = "mailto:" + emails[0];
+ }
+
+ /* Subsequently, escape fileName such that it is rendered
+ safe to append to the command line. */
+
+ fileName = (fileName
+ .replace ("\\", "\\\\")
+ .replace ("\"", "\\\"")
+ .replace ("$", "\\$"));
+
+ fileName = "(message-mailto \"" + fileName + "\" ";
+
+ /* Parse the intent itself to ascertain if any
+ non-standard subject, body, or something else of the
+ like is set. Such fields, non-standard as they are,
+ yield to fields provided within the URL itself; refer
+ to message-mailto. */
+
+ textString = attachmentString = subjectString = "()";
+
+ tem = intent.getCharSequenceExtra (Intent.EXTRA_SUBJECT);
+
+ if (tem != null)
+ subjectString = ("\"" + (tem.toString ()
+ .replace ("\\", "\\\\")
+ .replace ("\"", "\\\"")
+ .replace ("$", "\\$"))
+ + "\" ");
+
+ tem = intent.getCharSequenceExtra (Intent.EXTRA_TEXT);
+
+ if (tem != null)
+ textString = ("\"" + (tem.toString ()
+ .replace ("\\", "\\\\")
+ .replace ("\"", "\\\"")
+ .replace ("$", "\\$"))
+ + "\" ");
+
+ /* Producing a list of attachments is prey to two
+ mannerisms of the system: in the first instance, these
+ attachments are content URIs which don't allude to
+ their content types; and in the second instance, they
+ are either a list of such URIs or one individual URI,
+ subject to the type of the intent itself. */
+
+ if (Intent.ACTION_SEND.equals (action))
+ {
+ /* The attachment in this case is a single content
+ URI. */
+
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU)
+ uri = intent.getParcelableExtra (Intent.EXTRA_STREAM,
+ Uri.class);
+ else
+ uri = intent.getParcelableExtra (Intent.EXTRA_STREAM);
+
+ if ((scheme = uri.getScheme ()) != null
+ && scheme.equals ("content"))
+ {
+ tem1 = EmacsService.buildContentName (uri);
+ attachmentString = ("'(\"" + (tem1.replace ("\\", "\\\\")
+ .replace ("\"", "\\\"")
+ .replace ("$", "\\$"))
+ + "\")");
+ }
+ }
+ else
+ {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU)
+ list
+ = intent.getParcelableArrayListExtra (Intent.EXTRA_STREAM,
+ Parcelable.class);
+ else
+ list
+ = intent.getParcelableArrayListExtra (Intent.EXTRA_STREAM);
+
+ if (list != null)
+ {
+ builder = new StringBuilder ("'(");
+
+ for (Parcelable parcelable : list)
+ {
+ if (!(parcelable instanceof Uri))
+ continue;
+
+ uri = (Uri) parcelable;
+
+ if (uri != null
+ && (scheme = uri.getScheme ()) != null
+ && scheme.equals ("content"))
+ {
+ tem1 = EmacsService.buildContentName (uri);
+ builder.append ("\"");
+ builder.append (tem1.replace ("\\", "\\\\")
+ .replace ("\"", "\\\"")
+ .replace ("$", "\\$"));
+ builder.append ("\"");
+ }
+ }
+
+ builder.append (")");
+ attachmentString = builder.toString ();
+ }
+ }
+
+ fileName += subjectString;
+ fileName += textString;
+ fileName += attachmentString;
+ fileName += ")";
+
+ /* Execute emacsclient in order to execute this code. */
+ currentActivity = this;
+ startEmacsClient (new String[] { "--timeout=10", "--no-wait",
+ "--eval", fileName, });
+ return;
+ }
+
/* Now, try to get the file name. */
- if (uri.getScheme ().equals ("file"))
+ if (scheme.equals ("file"))
fileName = uri.getPath ();
else
{
fileName = null;
- if (uri.getScheme ().equals ("content"))
+ if (scheme.equals ("content"))
{
/* This is one of the annoying Android ``content''
URIs. Most of the time, there is actually an
@@ -469,6 +632,14 @@ public final class EmacsOpenActivity extends Activity
{
/* Do nothing. */
}
+ catch (SecurityException exception)
+ {
+ /* This means Emacs lacks the rights to open this
+ file. Display the error message and exit. */
+ displayFailureDialog ("Error opening file",
+ exception.toString ());
+ return;
+ }
if (fd != null)
{
@@ -482,6 +653,10 @@ public final class EmacsOpenActivity extends Activity
}
}
}
+ else if (scheme.equals ("org-protocol"))
+ /* URL is an org-protocol:// link, which is meant to be
+ directly relayed to emacsclient. */
+ fileName = uri.toString ();
if (fileName == null)
{
@@ -493,11 +668,25 @@ public final class EmacsOpenActivity extends Activity
}
}
+ /* If the Emacs service is not running, then start Emacs and make
+ it open this file. */
+
+ if (EmacsService.SERVICE == null)
+ {
+ fileToOpen = fileName;
+ intent = new Intent (EmacsOpenActivity.this,
+ EmacsActivity.class);
+ finish ();
+ startActivity (intent);
+ return;
+ }
+
/* And start emacsclient. Set `currentActivity' to this now.
Presumably, it will shortly become capable of displaying
dialogs. */
currentActivity = this;
- startEmacsClient (fileName);
+ startEmacsClient (new String[] { "--timeout=10", "--no-wait",
+ "--reuse-frame", fileName, });
}
else
finish ();
@@ -509,8 +698,6 @@ public final class EmacsOpenActivity extends Activity
public void
onDestroy ()
{
- Log.d (TAG, "onDestroy: " + this);
-
/* Clear `currentActivity' if it refers to the activity being
destroyed. */
@@ -524,9 +711,6 @@ public final class EmacsOpenActivity extends Activity
public void
onWindowFocusChanged (boolean isFocused)
{
- Log.d (TAG, "onWindowFocusChanged: " + this + ", is now focused: "
- + isFocused);
-
if (isFocused)
currentActivity = this;
else if (currentActivity == this)
@@ -539,8 +723,6 @@ public final class EmacsOpenActivity extends Activity
public void
onPause ()
{
- Log.d (TAG, "onPause: " + this);
-
/* XXX: clear currentActivity here as well; I don't know whether
or not onWindowFocusChanged is always called prior to this. */
diff --git a/java/org/gnu/emacs/EmacsPixmap.java b/java/org/gnu/emacs/EmacsPixmap.java
index eb011bc5e65..c621e2de3c5 100644
--- a/java/org/gnu/emacs/EmacsPixmap.java
+++ b/java/org/gnu/emacs/EmacsPixmap.java
@@ -1,6 +1,6 @@
/* Communication module for Android terminals. -*- c-file-style: "GNU" -*-
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
@@ -34,7 +34,7 @@ public final class EmacsPixmap extends EmacsHandleObject
{
/* The depth of the bitmap. This is not actually used, just defined
in order to be consistent with X. */
- public int depth, width, height;
+ public final int depth, width, height;
/* The bitmap itself. */
public Bitmap bitmap;
@@ -44,42 +44,13 @@ public final class EmacsPixmap extends EmacsHandleObject
/* Whether or not GC should be explicitly triggered upon
release. */
- private boolean needCollect;
+ private final boolean needCollect;
/* ID used to determine whether or not the GC clip rects
changed. */
private long gcClipRectID;
public
- EmacsPixmap (short handle, int colors[], int width,
- int height, int depth)
- {
- super (handle);
-
- if (depth != 1 && depth != 24)
- throw new IllegalArgumentException ("Invalid depth specified"
- + " for pixmap: " + depth);
-
- switch (depth)
- {
- case 1:
- bitmap = Bitmap.createBitmap (colors, width, height,
- Bitmap.Config.ALPHA_8);
- break;
-
- case 24:
- bitmap = Bitmap.createBitmap (colors, width, height,
- Bitmap.Config.ARGB_8888);
- bitmap.setHasAlpha (false);
- break;
- }
-
- this.width = width;
- this.height = height;
- this.depth = depth;
- }
-
- public
EmacsPixmap (short handle, int width, int height, int depth)
{
super (handle);
@@ -172,6 +143,13 @@ public final class EmacsPixmap extends EmacsHandleObject
}
@Override
+ public void
+ damageRect (int left, int top, int right, int bottom)
+ {
+
+ }
+
+ @Override
public Bitmap
getBitmap ()
{
diff --git a/java/org/gnu/emacs/EmacsPreferencesActivity.java b/java/org/gnu/emacs/EmacsPreferencesActivity.java
index 7e67cc3679b..330adbea223 100644
--- a/java/org/gnu/emacs/EmacsPreferencesActivity.java
+++ b/java/org/gnu/emacs/EmacsPreferencesActivity.java
@@ -1,6 +1,6 @@
/* Communication module for Android terminals. -*- c-file-style: "GNU" -*-
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/java/org/gnu/emacs/EmacsSafThread.java b/java/org/gnu/emacs/EmacsSafThread.java
index 1b62662b4fc..14c3f222833 100644
--- a/java/org/gnu/emacs/EmacsSafThread.java
+++ b/java/org/gnu/emacs/EmacsSafThread.java
@@ -1,6 +1,6 @@
/* Communication module for Android terminals. -*- c-file-style: "GNU" -*-
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
@@ -504,7 +504,7 @@ public final class EmacsSafThread extends HandlerThread
cacheDirectoryFromCursor (CacheToplevel toplevel, String documentId,
Cursor cursor)
{
- CacheEntry entry, constitutent;
+ CacheEntry entry, constituent;
int nameColumn, idColumn, typeColumn;
String id, name, type;
DocIdEntry idEntry;
@@ -561,8 +561,8 @@ public final class EmacsSafThread extends HandlerThread
/* Otherwise, create a new cache entry comprised of its
type. */
- constitutent = new CacheEntry ();
- constitutent.type = type;
+ constituent = new CacheEntry ();
+ constituent.type = type;
toplevel.idCache.put (documentId, entry);
}
catch (Exception e)
@@ -767,7 +767,7 @@ public final class EmacsSafThread extends HandlerThread
private abstract class SafIntFunction
{
- /* The ``throws Throwable'' here is a Java idiosyncracy that tells
+ /* The ``throws Throwable'' here is a Java idiosyncrasy that tells
the compiler to allow arbitrary error objects to be signaled
from within this function.
@@ -782,7 +782,7 @@ public final class EmacsSafThread extends HandlerThread
private abstract class SafObjectFunction
{
- /* The ``throws Throwable'' here is a Java idiosyncracy that tells
+ /* The ``throws Throwable'' here is a Java idiosyncrasy that tells
the compiler to allow arbitrary error objects to be signaled
from within this function.
@@ -1216,7 +1216,7 @@ public final class EmacsSafThread extends HandlerThread
});
}
- /* The bulk of `statDocument'. SIGNAL should be a cancelation
+ /* The bulk of `statDocument'. SIGNAL should be a cancellation
signal. */
private long[]
@@ -1430,9 +1430,6 @@ public final class EmacsSafThread extends HandlerThread
/* If so, don't check for FLAG_SUPPORTS_WRITE.
Check for FLAG_DIR_SUPPORTS_CREATE instead. */
- if (!writable)
- return 0;
-
index = cursor.getColumnIndex (Document.COLUMN_FLAGS);
if (index < 0)
return -3;
diff --git a/java/org/gnu/emacs/EmacsSdk11Clipboard.java b/java/org/gnu/emacs/EmacsSdk11Clipboard.java
index b34753922b8..850bb6c8deb 100644
--- a/java/org/gnu/emacs/EmacsSdk11Clipboard.java
+++ b/java/org/gnu/emacs/EmacsSdk11Clipboard.java
@@ -1,6 +1,6 @@
/* Communication module for Android terminals. -*- c-file-style: "GNU" -*-
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
@@ -209,7 +209,7 @@ public final class EmacsSdk11Clipboard extends EmacsClipboard
Value is normally an array of three longs: the file descriptor,
the start offset of the data, and its length; length may be
- AssetFileDescriptor.UNKOWN_LENGTH, meaning that the data extends
+ AssetFileDescriptor.UNKNOWN_LENGTH, meaning that the data extends
from that offset to the end of the file.
Do not use this function to open text targets; use `getClipboard'
@@ -245,6 +245,8 @@ public final class EmacsSdk11Clipboard extends EmacsClipboard
if (data == null || data.getItemCount () < 1)
return null;
+ fd = -1;
+
try
{
uri = data.getItemAt (0).getUri ();
@@ -267,12 +269,34 @@ public final class EmacsSdk11Clipboard extends EmacsClipboard
/* Close the original offset. */
assetFd.close ();
}
+ catch (SecurityException e)
+ {
+ /* Guarantee a file descriptor duplicated or detached is
+ ultimately closed if an error arises. */
+
+ if (fd != -1)
+ EmacsNative.close (fd);
+
+ return null;
+ }
catch (FileNotFoundException e)
{
+ /* Guarantee a file descriptor duplicated or detached is
+ ultimately closed if an error arises. */
+
+ if (fd != -1)
+ EmacsNative.close (fd);
+
return null;
}
catch (IOException e)
{
+ /* Guarantee a file descriptor duplicated or detached is
+ ultimately closed if an error arises. */
+
+ if (fd != -1)
+ EmacsNative.close (fd);
+
return null;
}
diff --git a/java/org/gnu/emacs/EmacsSdk23FontDriver.java b/java/org/gnu/emacs/EmacsSdk23FontDriver.java
index aaba8dbd166..91153feaa11 100644
--- a/java/org/gnu/emacs/EmacsSdk23FontDriver.java
+++ b/java/org/gnu/emacs/EmacsSdk23FontDriver.java
@@ -1,6 +1,6 @@
/* Font backend for Android terminals. -*- c-file-style: "GNU" -*-
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
@@ -96,7 +96,7 @@ public final class EmacsSdk23FontDriver extends EmacsSdk7FontDriver
@Override
public int
- hasChar (FontSpec font, char charCode)
+ hasChar (FontSpec font, int charCode)
{
Sdk7FontObject fontObject;
Paint paint;
@@ -109,6 +109,12 @@ public final class EmacsSdk23FontDriver extends EmacsSdk7FontDriver
else
paint = ((Sdk7FontEntity) font).typeface.typefacePaint;
- return paint.hasGlyph (String.valueOf (charCode)) ? 1 : 0;
+ /* If the character falls within the confines of the BMP, return
+ 1. */
+ if (charCode < 65536)
+ return paint.hasGlyph (String.valueOf ((char) charCode)) ? 1 : 0;
+
+ /* Otherwise return 0. */
+ return 0;
}
};
diff --git a/java/org/gnu/emacs/EmacsSdk7FontDriver.java b/java/org/gnu/emacs/EmacsSdk7FontDriver.java
index 97969585d16..49d9514c104 100644
--- a/java/org/gnu/emacs/EmacsSdk7FontDriver.java
+++ b/java/org/gnu/emacs/EmacsSdk7FontDriver.java
@@ -1,6 +1,6 @@
/* Font backend for Android terminals. -*- c-file-style: "GNU" -*-
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
@@ -31,6 +31,19 @@ import android.graphics.Canvas;
import android.util.Log;
+
+
+/* EmacsSdk7FontDriver implements a fallback font driver under
+ Android. This font driver is enabled when the SFNT font driver (in
+ sfntfont-android.c) proves incapable of locating any fonts, which
+ has hitherto not been observed in practice.
+
+ This font driver does not supply each font installed on the system,
+ in lieu of which it provides a list of fonts for each conceivable
+ style and sub-type of the system's own Typefaces, which arises from
+ Android's absence of suitable APIs for loading individual font
+ files. */
+
public class EmacsSdk7FontDriver extends EmacsFontDriver
{
private static final String TOFU_STRING = "\uDB3F\uDFFD";
@@ -46,106 +59,26 @@ public class EmacsSdk7FontDriver extends EmacsFontDriver
public int slant, width, weight, spacing;
public
- Sdk7Typeface (String fileName, Typeface typeface)
+ Sdk7Typeface (String familyName, Typeface typeface)
{
String style, testString;
int index, measured, i;
float[] widths;
+ /* Initialize the font style fields and create a paint object
+ linked with that typeface. */
+
slant = NORMAL;
weight = REGULAR;
width = UNSPECIFIED;
spacing = PROPORTIONAL;
this.typeface = typeface;
+ this.familyName = familyName;
typefacePaint = new Paint ();
typefacePaint.setAntiAlias (true);
typefacePaint.setTypeface (typeface);
-
- /* For the calls to measureText below. */
- typefacePaint.setTextSize (10.0f);
-
- /* Parse the file name into some useful data. First, strip off
- the extension. */
- fileName = fileName.split ("\\.", 2)[0];
-
- /* Next, split the file name by dashes. Everything before the
- last dash is part of the family name. */
- index = fileName.lastIndexOf ("-");
-
- if (index > 0)
- {
- style = fileName.substring (index + 1, fileName.length ());
- familyName = fileName.substring (0, index);
-
- /* Look for something describing the weight. */
- if (style.contains ("Thin"))
- weight = THIN;
- else if (style.contains ("UltraLight"))
- weight = ULTRA_LIGHT;
- else if (style.contains ("SemiLight"))
- weight = SEMI_LIGHT;
- else if (style.contains ("Light"))
- weight = LIGHT;
- else if (style.contains ("Medium"))
- weight = MEDIUM;
- else if (style.contains ("SemiBold"))
- weight = SEMI_BOLD;
- else if (style.contains ("ExtraBold"))
- weight = EXTRA_BOLD;
- else if (style.contains ("Bold"))
- weight = BOLD;
- else if (style.contains ("Black"))
- weight = BLACK;
- else if (style.contains ("UltraHeavy"))
- weight = ULTRA_HEAVY;
-
- /* And the slant. */
- if (style.contains ("ReverseOblique"))
- slant = OBLIQUE;
- else if (style.contains ("ReverseItalic"))
- slant = REVERSE_ITALIC;
- else if (style.contains ("Italic"))
- slant = ITALIC;
- else if (style.contains ("Oblique"))
- slant = OBLIQUE;
-
- /* Finally, the width. */
- if (style.contains ("UltraCondensed"))
- width = ULTRA_CONDENSED;
- else if (style.contains ("ExtraCondensed"))
- width = EXTRA_CONDENSED;
- else if (style.contains ("SemiCondensed"))
- width = SEMI_CONDENSED;
- else if (style.contains ("Condensed"))
- width = CONDENSED;
- else if (style.contains ("SemiExpanded"))
- width = SEMI_EXPANDED;
- else if (style.contains ("ExtraExpanded"))
- width = EXTRA_EXPANDED;
- else if (style.contains ("UltraExpanded"))
- width = ULTRA_EXPANDED;
- else if (style.contains ("Expanded"))
- width = EXPANDED;
-
- /* Guess the spacing information. */
- testString = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
- widths = new float[testString.length ()];
-
- measured = typefacePaint.getTextWidths (testString,
- 0, testString.length (),
- widths);
- spacing = MONO;
- for (i = 0; i < measured; ++i)
- {
- if (i != 0 && widths[i - 1] != widths[i])
- /* This isn't a monospace font. */
- spacing = PROPORTIONAL;
- }
- }
- else
- familyName = fileName;
}
@Override
@@ -166,6 +99,7 @@ public class EmacsSdk7FontDriver extends EmacsFontDriver
/* The typeface. */
public Sdk7Typeface typeface;
+ @SuppressWarnings ("deprecation")
public
Sdk7FontEntity (Sdk7Typeface typeface)
{
@@ -187,6 +121,7 @@ public class EmacsSdk7FontDriver extends EmacsFontDriver
/* The typeface. */
public Sdk7Typeface typeface;
+ @SuppressWarnings ("deprecation")
public
Sdk7FontObject (Sdk7Typeface typeface, int pixelSize)
{
@@ -244,43 +179,42 @@ public class EmacsSdk7FontDriver extends EmacsFontDriver
EmacsSdk7FontDriver ()
{
int i;
- File systemFontsDirectory, fontFile;
Typeface typeface;
- systemFontsDirectory = new File ("/system/fonts");
-
- fontFamilyList = systemFontsDirectory.list ();
-
- /* If that returned null, replace it with an empty array. */
- fontFamilyList = new String[0];
-
- typefaceList = new Sdk7Typeface[fontFamilyList.length + 3];
+ typefaceList = new Sdk7Typeface[5];
- /* It would be nice to avoid opening each and every font upon
- startup. But that doesn't seem to be possible on
- Android. */
+ /* Initialize the default monospace and Sans Serif typefaces.
+ Initialize the same typeface with various distinct styles. */
+ fallbackTypeface = new Sdk7Typeface ("Sans Serif",
+ Typeface.DEFAULT);
+ typefaceList[1] = fallbackTypeface;
- for (i = 0; i < fontFamilyList.length; ++i)
- {
- fontFile = new File (systemFontsDirectory,
- fontFamilyList[i]);
- typeface = Typeface.createFromFile (fontFile);
- typefaceList[i] = new Sdk7Typeface (fontFile.getName (),
- typeface);
- }
+ fallbackTypeface = new Sdk7Typeface ("Sans Serif",
+ Typeface.create (Typeface.DEFAULT,
+ Typeface.BOLD));
+ fallbackTypeface.weight = BOLD;
+ typefaceList[2] = fallbackTypeface;
- /* Initialize the default monospace and serif typefaces. */
- fallbackTypeface = new Sdk7Typeface ("monospace",
- Typeface.MONOSPACE);
- typefaceList[fontFamilyList.length] = fallbackTypeface;
+ fallbackTypeface = new Sdk7Typeface ("Sans Serif",
+ Typeface.create (Typeface.DEFAULT,
+ Typeface.ITALIC));
+ fallbackTypeface.slant = ITALIC;
+ typefaceList[3] = fallbackTypeface;
+
+ fallbackTypeface
+ = new Sdk7Typeface ("Sans Serif",
+ Typeface.create (Typeface.DEFAULT,
+ Typeface.BOLD_ITALIC));
+ fallbackTypeface.weight = BOLD;
+ fallbackTypeface.slant = ITALIC;
+ typefaceList[4] = fallbackTypeface;
fallbackTypeface = new Sdk7Typeface ("Monospace",
Typeface.MONOSPACE);
- typefaceList[fontFamilyList.length + 1] = fallbackTypeface;
+ fallbackTypeface.spacing = MONO;
+ typefaceList[0] = fallbackTypeface;
- fallbackTypeface = new Sdk7Typeface ("Sans Serif",
- Typeface.DEFAULT);
- typefaceList[fontFamilyList.length + 2] = fallbackTypeface;
+ fontFamilyList = new String[] { "Monospace", "Sans Serif", };
}
private boolean
@@ -359,13 +293,18 @@ public class EmacsSdk7FontDriver extends EmacsFontDriver
@Override
public int
- hasChar (FontSpec font, char charCode)
+ hasChar (FontSpec font, int charCode)
{
float missingGlyphWidth, width;
Rect rect1, rect2;
Paint paint;
Sdk7FontObject fontObject;
+ /* Ignore characters outside the BMP. */
+
+ if (charCode > 65535)
+ return 0;
+
if (font instanceof Sdk7FontObject)
{
fontObject = (Sdk7FontObject) font;
@@ -376,7 +315,7 @@ public class EmacsSdk7FontDriver extends EmacsFontDriver
paint.setTextSize (10);
- if (Character.isWhitespace (charCode))
+ if (Character.isWhitespace ((char) charCode))
return 1;
missingGlyphWidth = paint.measureText (TOFU_STRING);
@@ -393,7 +332,7 @@ public class EmacsSdk7FontDriver extends EmacsFontDriver
paint.getTextBounds (TOFU_STRING, 0, TOFU_STRING.length (),
rect1);
- paint.getTextBounds ("" + charCode, 0, 1, rect2);
+ paint.getTextBounds ("" + (char) charCode, 0, 1, rect2);
return rect1.equals (rect2) ? 0 : 1;
}
@@ -478,8 +417,11 @@ public class EmacsSdk7FontDriver extends EmacsFontDriver
@Override
public int
- encodeChar (FontObject fontObject, char charCode)
+ encodeChar (FontObject fontObject, int charCode)
{
+ if (charCode > 65535)
+ return FONT_INVALID_CODE;
+
return charCode;
}
@@ -491,16 +433,12 @@ public class EmacsSdk7FontDriver extends EmacsFontDriver
{
Rect backgroundRect, bounds;
Sdk7FontObject sdk7FontObject;
- char[] charsArray;
int i;
Canvas canvas;
Paint paint;
+ char[] array;
sdk7FontObject = (Sdk7FontObject) fontObject;
- charsArray = new char[chars.length];
-
- for (i = 0; i < chars.length; ++i)
- charsArray[i] = (char) chars[i];
backgroundRect = new Rect ();
backgroundRect.top = y - sdk7FontObject.ascent;
@@ -526,13 +464,33 @@ public class EmacsSdk7FontDriver extends EmacsFontDriver
paint.setTextSize (sdk7FontObject.pixelSize);
paint.setTypeface (sdk7FontObject.typeface.typeface);
paint.setAntiAlias (true);
- canvas.drawText (charsArray, 0, chars.length, x, y, paint);
+
+ /* Android applies kerning to non-monospaced fonts by default,
+ which brings the dimensions of strings drawn via `drawText' out
+ of agreement with measurements previously provided to redisplay
+ by textExtents. To avert such disaster, draw each character
+ individually, advancing the origin point by hand. */
bounds = new Rect ();
- paint.getTextBounds (charsArray, 0, chars.length, bounds);
- bounds.offset (x, y);
- bounds.union (backgroundRect);
- drawable.damageRect (bounds);
+ array = new char[1];
+
+ for (i = 0; i < chars.length; ++i)
+ {
+ /* Retrieve the text bounds for this character so as to
+ compute the damage rectangle. */
+ array[0] = (char) chars[i];
+ paint.getTextBounds (array, 0, 1, bounds);
+ bounds.offset (x, y);
+ backgroundRect.union (bounds);
+
+ /* Draw this character. */
+ canvas.drawText (array, 0, 1, x, y, paint);
+
+ /* Advance the origin point by that much. */
+ x += paint.measureText ("" + array[0]);
+ }
+
+ drawable.damageRect (backgroundRect);
paint.setAntiAlias (false);
return 1;
}
diff --git a/java/org/gnu/emacs/EmacsSdk8Clipboard.java b/java/org/gnu/emacs/EmacsSdk8Clipboard.java
index 9622641810f..418f55c12c1 100644
--- a/java/org/gnu/emacs/EmacsSdk8Clipboard.java
+++ b/java/org/gnu/emacs/EmacsSdk8Clipboard.java
@@ -1,6 +1,6 @@
/* Communication module for Android terminals. -*- c-file-style: "GNU" -*-
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/java/org/gnu/emacs/EmacsService.java b/java/org/gnu/emacs/EmacsService.java
index 404796cd08c..5cb1ceca0aa 100644
--- a/java/org/gnu/emacs/EmacsService.java
+++ b/java/org/gnu/emacs/EmacsService.java
@@ -1,6 +1,6 @@
/* Communication module for Android terminals. -*- c-file-style: "GNU" -*-
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
@@ -27,6 +27,10 @@ import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.FutureTask;
+
import java.util.concurrent.atomic.AtomicInteger;
import android.database.Cursor;
@@ -53,8 +57,6 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.content.UriPermission;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager.ApplicationInfoFlags;
import android.content.pm.PackageManager;
import android.content.res.AssetManager;
@@ -65,6 +67,7 @@ import android.net.Uri;
import android.os.BatteryManager;
import android.os.Build;
+import android.os.Environment;
import android.os.Looper;
import android.os.IBinder;
import android.os.Handler;
@@ -75,6 +78,7 @@ import android.os.VibrationEffect;
import android.provider.DocumentsContract;
import android.provider.DocumentsContract.Document;
+import android.provider.Settings;
import android.util.Log;
import android.util.DisplayMetrics;
@@ -193,34 +197,19 @@ public final class EmacsService extends Service
return null;
}
+ /* Return the display density, adjusted in accord with the user's
+ text scaling preferences. */
+
@SuppressWarnings ("deprecation")
- private String
- getApkFile ()
+ private static float
+ getScaledDensity (DisplayMetrics metrics)
{
- PackageManager manager;
- ApplicationInfo info;
-
- manager = getPackageManager ();
-
- try
- {
- if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU)
- info = manager.getApplicationInfo ("org.gnu.emacs", 0);
- else
- info = manager.getApplicationInfo ("org.gnu.emacs",
- ApplicationInfoFlags.of (0));
-
- /* Return an empty string upon failure. */
-
- if (info.sourceDir != null)
- return info.sourceDir;
-
- return "";
- }
- catch (Exception e)
- {
- return "";
- }
+ /* The scaled density has been made obsolete by the introduction
+ of non-linear text scaling in Android 34, where there is no
+ longer a fixed relation between point and pixel sizes, but
+ remains useful, considering that Emacs does not support
+ non-linear text scaling. */
+ return metrics.scaledDensity;
}
@Override
@@ -242,7 +231,7 @@ public final class EmacsService extends Service
metrics = getResources ().getDisplayMetrics ();
pixelDensityX = metrics.xdpi;
pixelDensityY = metrics.ydpi;
- tempScaledDensity = ((metrics.scaledDensity
+ tempScaledDensity = ((getScaledDensity (metrics)
/ metrics.density)
* pixelDensityX);
resolver = getContentResolver ();
@@ -273,7 +262,7 @@ public final class EmacsService extends Service
/* Now provide this application's apk file, so a recursive
invocation of app_process (through android-emacs) can
find EmacsNoninteractive. */
- classPath = getApkFile ();
+ classPath = EmacsApplication.apkFileName;
Log.d (TAG, "Initializing Emacs, where filesDir = " + filesDir
+ ", libDir = " + libDir + ", and classPath = " + classPath
@@ -306,6 +295,30 @@ public final class EmacsService extends Service
}
}
+ /* The native functions the subsequent two functions call do nothing
+ in the infrequent case the Emacs thread is awaiting a response
+ for the main thread. Caveat emptor! */
+
+ @Override
+ public void
+ onDestroy ()
+ {
+ /* This function is called immediately before the system kills
+ Emacs. In this respect, it is rather akin to a SIGDANGER
+ signal, so force an auto-save accordingly. */
+
+ EmacsNative.shutDownEmacs ();
+ super.onDestroy ();
+ }
+
+ @Override
+ public void
+ onLowMemory ()
+ {
+ EmacsNative.onLowMemory ();
+ super.onLowMemory ();
+ }
+
/* Functions from here on must only be called from the Emacs
@@ -322,52 +335,45 @@ public final class EmacsService extends Service
final boolean isFocusedByDefault)
{
Runnable runnable;
- final EmacsHolder<EmacsView> view;
-
- view = new EmacsHolder<EmacsView> ();
+ FutureTask<EmacsView> task;
- runnable = new Runnable () {
+ task = new FutureTask<EmacsView> (new Callable<EmacsView> () {
@Override
- public void
- run ()
+ public EmacsView
+ call ()
{
- synchronized (this)
- {
- view.thing = new EmacsView (window);
- view.thing.setVisibility (visibility);
+ EmacsView view;
- /* The following function is only present on Android 26
- or later. */
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
- view.thing.setFocusedByDefault (isFocusedByDefault);
+ view = new EmacsView (window);
+ view.setVisibility (visibility);
- notify ();
- }
+ /* The following function is only present on Android 26
+ or later. */
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
+ view.setFocusedByDefault (isFocusedByDefault);
+
+ return view;
}
- };
+ });
- syncRunnable (runnable);
- return view.thing;
+ return EmacsService.<EmacsView>syncRunnable (task);
}
public void
getLocationOnScreen (final EmacsView view, final int[] coordinates)
{
- Runnable runnable;
+ FutureTask<Void> task;
- runnable = new Runnable () {
- public void
- run ()
+ task = new FutureTask<Void> (new Callable<Void> () {
+ public Void
+ call ()
{
- synchronized (this)
- {
- view.getLocationOnScreen (coordinates);
- notify ();
- }
+ view.getLocationOnScreen (coordinates);
+ return null;
}
- };
+ });
- syncRunnable (runnable);
+ EmacsService.<Void>syncRunnable (task);
}
@@ -448,12 +454,13 @@ public final class EmacsService extends Service
@SuppressWarnings ("deprecation")
public void
- ringBell ()
+ ringBell (int duration)
{
Vibrator vibrator;
VibrationEffect effect;
VibratorManager vibratorManager;
Object tem;
+ int amplitude;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S)
{
@@ -467,13 +474,13 @@ public final class EmacsService extends Service
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
{
+ amplitude = VibrationEffect.DEFAULT_AMPLITUDE;
effect
- = VibrationEffect.createOneShot (50,
- VibrationEffect.DEFAULT_AMPLITUDE);
+ = VibrationEffect.createOneShot (duration, amplitude);
vibrator.vibrate (effect);
}
else
- vibrator.vibrate (50);
+ vibrator.vibrate (duration);
}
public short[]
@@ -489,15 +496,18 @@ public final class EmacsService extends Service
else
windowList = window.children;
- array = new short[windowList.size () + 1];
- i = 1;
+ synchronized (windowList)
+ {
+ array = new short[windowList.size () + 1];
+ i = 1;
- array[0] = (window == null
- ? 0 : (window.parent != null
- ? window.parent.handle : 0));
+ array[0] = (window == null
+ ? 0 : (window.parent != null
+ ? window.parent.handle : 0));
- for (EmacsWindow treeWindow : windowList)
- array[i++] = treeWindow.handle;
+ for (EmacsWindow treeWindow : windowList)
+ array[i++] = treeWindow.handle;
+ }
return array;
}
@@ -599,7 +609,7 @@ public final class EmacsService extends Service
context.startService (new Intent (context,
EmacsService.class));
else
- /* Display the permanant notification and start Emacs as a
+ /* Display the permanent notification and start Emacs as a
foreground service. */
context.startForegroundService (new Intent (context,
EmacsService.class));
@@ -643,13 +653,18 @@ public final class EmacsService extends Service
uri.getPath ());
}
- Log.d (TAG, ("browseUri: browsing " + url
- + " --> " + uri.getPath ()
- + " --> " + uri));
-
intent = new Intent (Intent.ACTION_VIEW, uri);
+
+ /* Set several flags on the Intent prompting the system to
+ permit the recipient to read and edit the URI
+ indefinitely. */
+
intent.setFlags (Intent.FLAG_ACTIVITY_NEW_TASK
- | Intent.FLAG_GRANT_READ_URI_PERMISSION);
+ | Intent.FLAG_GRANT_READ_URI_PERMISSION
+ | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
+
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)
+ intent.addFlags (Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION);
}
else
{
@@ -661,7 +676,7 @@ public final class EmacsService extends Service
/* Display a list of programs able to send this URL. */
intent = Intent.createChooser (intent, "Send");
- /* Apparently flags need to be set after a choser is
+ /* Apparently flags need to be set after a chooser is
created. */
intent.addFlags (Intent.FLAG_ACTIVITY_NEW_TASK);
}
@@ -684,28 +699,17 @@ public final class EmacsService extends Service
public ClipboardManager
getClipboardManager ()
{
- final EmacsHolder<ClipboardManager> manager;
- Runnable runnable;
+ FutureTask<Object> task;
- manager = new EmacsHolder<ClipboardManager> ();
-
- runnable = new Runnable () {
- public void
- run ()
+ task = new FutureTask<Object> (new Callable<Object> () {
+ public Object
+ call ()
{
- Object tem;
-
- synchronized (this)
- {
- tem = getSystemService (Context.CLIPBOARD_SERVICE);
- manager.thing = (ClipboardManager) tem;
- notify ();
- }
+ return getSystemService (Context.CLIPBOARD_SERVICE);
}
- };
+ });
- syncRunnable (runnable);
- return manager.thing;
+ return (ClipboardManager) EmacsService.<Object>syncRunnable (task);
}
public void
@@ -720,33 +724,37 @@ public final class EmacsService extends Service
System.exit (0);
}
- /* Wait synchronously for the specified RUNNABLE to complete in the
- UI thread. Must be called from the Emacs thread. */
+ /* Wait synchronously for the specified TASK to complete in the UI
+ thread, then return its result. Must be called from the Emacs
+ thread. */
- public static void
- syncRunnable (Runnable runnable)
+ public static <V> V
+ syncRunnable (FutureTask<V> task)
{
+ V object;
+
EmacsNative.beginSynchronous ();
+ SERVICE.runOnUiThread (task);
- synchronized (runnable)
+ try
{
- SERVICE.runOnUiThread (runnable);
-
- while (true)
- {
- try
- {
- runnable.wait ();
- break;
- }
- catch (InterruptedException e)
- {
- continue;
- }
- }
+ object = task.get ();
+ }
+ catch (ExecutionException exception)
+ {
+ /* Wrap this exception in a RuntimeException and signal it to
+ the caller. */
+ throw new RuntimeException (exception.getCause ());
+ }
+ catch (InterruptedException exception)
+ {
+ EmacsNative.emacsAbort ();
+ object = null;
}
EmacsNative.endSynchronous ();
+
+ return object;
}
@@ -884,8 +892,6 @@ public final class EmacsService extends Service
0);
info = builder.build ();
-
-
if (DEBUG_IC)
Log.d (TAG, ("updateCursorAnchorInfo: " + x + " " + y
+ " " + yBaseline + "-" + yBottom));
@@ -899,6 +905,48 @@ public final class EmacsService extends Service
/* Content provider functions. */
+ /* Return a ContentResolver capable of accessing as many files as
+ possible, namely the content resolver of the last selected
+ activity if available: only they posses the rights to access drag
+ and drop files. */
+
+ public ContentResolver
+ getUsefulContentResolver ()
+ {
+ EmacsActivity activity;
+
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N)
+ /* Since the system predates drag and drop, return this resolver
+ to avoid any unforeseen difficulties. */
+ return resolver;
+
+ activity = EmacsActivity.lastFocusedActivity;
+ if (activity == null)
+ return resolver;
+
+ return activity.getContentResolver ();
+ }
+
+ /* Return a context whose ContentResolver is granted access to most
+ files, as in `getUsefulContentResolver'. */
+
+ public Context
+ getContentResolverContext ()
+ {
+ EmacsActivity activity;
+
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N)
+ /* Since the system predates drag and drop, return this resolver
+ to avoid any unforeseen difficulties. */
+ return this;
+
+ activity = EmacsActivity.lastFocusedActivity;
+ if (activity == null)
+ return this;
+
+ return activity;
+ }
+
/* Open a content URI described by the bytes BYTES, a non-terminated
string; make it writable if WRITABLE, and readable if READABLE.
Truncate the file if TRUNCATE.
@@ -912,6 +960,9 @@ public final class EmacsService extends Service
String name, mode;
ParcelFileDescriptor fd;
int i;
+ ContentResolver resolver;
+
+ resolver = getUsefulContentResolver ();
/* Figure out the file access mode. */
@@ -956,6 +1007,7 @@ public final class EmacsService extends Service
}
catch (Exception exception)
{
+ exception.printStackTrace ();
return -1;
}
}
@@ -972,6 +1024,11 @@ public final class EmacsService extends Service
ParcelFileDescriptor fd;
Uri uri;
int rc, flags;
+ Context context;
+ ContentResolver resolver;
+ ParcelFileDescriptor descriptor;
+
+ context = getContentResolverContext ();
uri = Uri.parse (name);
flags = 0;
@@ -982,8 +1039,42 @@ public final class EmacsService extends Service
if (writable)
flags |= Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
- rc = checkCallingUriPermission (uri, flags);
- return rc == PackageManager.PERMISSION_GRANTED;
+ rc = context.checkCallingUriPermission (uri, flags);
+
+ if (rc == PackageManager.PERMISSION_GRANTED)
+ return true;
+
+ /* In the event checkCallingUriPermission fails and only read
+ permissions are being verified, attempt to query the URI. This
+ enables ascertaining whether drag and drop URIs can be
+ accessed, something otherwise not provided for. */
+
+ descriptor = null;
+
+ try
+ {
+ resolver = context.getContentResolver ();
+ descriptor = resolver.openFileDescriptor (uri, "r");
+ return true;
+ }
+ catch (Exception exception)
+ {
+ /* Ignored. */
+ }
+ finally
+ {
+ try
+ {
+ if (descriptor != null)
+ descriptor.close ();
+ }
+ catch (IOException exception)
+ {
+ /* Ignored. */
+ }
+ }
+
+ return false;
}
/* Build a content file name for URI.
@@ -1137,8 +1228,10 @@ public final class EmacsService extends Service
if (DEBUG_IC)
Log.d (TAG, "updateExtractedText: @" + token + ", " + text);
+ icBeginSynchronous ();
window.view.imManager.updateExtractedText (window.view,
token, text);
+ icEndSynchronous ();
}
@@ -1180,71 +1273,61 @@ public final class EmacsService extends Service
public int
requestDirectoryAccess ()
{
- Runnable runnable;
- final EmacsHolder<Integer> rc;
+ FutureTask<Integer> task;
/* Return 1 if Android is too old to support this feature. */
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP)
return 1;
- rc = new EmacsHolder<Integer> ();
- rc.thing = Integer.valueOf (1);
-
- runnable = new Runnable () {
+ task = new FutureTask<Integer> (new Callable<Integer> () {
@Override
- public void
- run ()
+ public Integer
+ call ()
{
EmacsActivity activity;
Intent intent;
- int id;
+ int id, rc;
- synchronized (this)
+ /* Try to obtain an activity that will receive the response
+ from the file chooser dialog. */
+
+ if (EmacsActivity.focusedActivities.isEmpty ())
{
- /* Try to obtain an activity that will receive the
- response from the file chooser dialog. */
+ /* If focusedActivities is empty then this dialog may
+ have been displayed immediately after another popup
+ dialog was dismissed. Try the EmacsActivity to be
+ focused. */
- if (EmacsActivity.focusedActivities.isEmpty ())
- {
- /* If focusedActivities is empty then this dialog
- may have been displayed immediately after another
- popup dialog was dismissed. Try the
- EmacsActivity to be focused. */
-
- activity = EmacsActivity.lastFocusedActivity;
-
- if (activity == null)
- {
- /* Still no luck. Return failure. */
- notify ();
- return;
- }
- }
- else
- activity = EmacsActivity.focusedActivities.get (0);
+ activity = EmacsActivity.lastFocusedActivity;
- /* Now create the intent. */
- intent = new Intent (Intent.ACTION_OPEN_DOCUMENT_TREE);
+ if (activity == null)
+ /* Still no luck. Return failure. */
+ return 1;
+ }
+ else
+ activity = EmacsActivity.focusedActivities.get (0);
- try
- {
- id = EmacsActivity.ACCEPT_DOCUMENT_TREE;
- activity.startActivityForResult (intent, id, null);
- rc.thing = Integer.valueOf (0);
- }
- catch (Exception e)
- {
- e.printStackTrace ();
- }
+ /* Now create the intent. */
+ intent = new Intent (Intent.ACTION_OPEN_DOCUMENT_TREE);
+ rc = 1;
- notify ();
+ try
+ {
+ id = EmacsActivity.ACCEPT_DOCUMENT_TREE;
+ activity.startActivityForResult (intent, id, null);
+ rc = 0;
}
+ catch (Exception e)
+ {
+ e.printStackTrace ();
+ }
+
+ return rc;
}
- };
+ });
- syncRunnable (runnable);
- return rc.thing;
+ return EmacsService.<Integer>syncRunnable (task);
}
/* Return an array of each tree provided by the document PROVIDER
@@ -1310,7 +1393,7 @@ public final class EmacsService extends Service
of OperationCanceledException, SecurityException,
FileNotFoundException, or UnsupportedOperationException. */
- private int
+ public int
documentIdFromName (String tree_uri, String name, String[] id_return)
{
/* Start the thread used to run SAF requests if it isn't already
@@ -1808,4 +1891,124 @@ public final class EmacsService extends Service
return false;
}
+
+
+
+ /* Functions for detecting and requesting storage permissions. */
+
+ public boolean
+ externalStorageAvailable ()
+ {
+ final String readPermission;
+
+ readPermission = "android.permission.READ_EXTERNAL_STORAGE";
+
+ return (Build.VERSION.SDK_INT < Build.VERSION_CODES.R
+ ? (checkSelfPermission (readPermission)
+ == PackageManager.PERMISSION_GRANTED)
+ : Environment.isExternalStorageManager ());
+ }
+
+ private void
+ requestStorageAccess23 ()
+ {
+ Runnable runnable;
+
+ runnable = new Runnable () {
+ @Override
+ public void
+ run ()
+ {
+ EmacsActivity activity;
+ String permission, permission1;
+
+ permission = "android.permission.READ_EXTERNAL_STORAGE";
+ permission1 = "android.permission.WRITE_EXTERNAL_STORAGE";
+
+ /* Find an activity that is entitled to display a permission
+ request dialog. */
+
+ if (EmacsActivity.focusedActivities.isEmpty ())
+ {
+ /* If focusedActivities is empty then this dialog may
+ have been displayed immediately after another popup
+ dialog was dismissed. Try the EmacsActivity to be
+ focused. */
+
+ activity = EmacsActivity.lastFocusedActivity;
+
+ if (activity == null)
+ {
+ /* Still no luck. Return failure. */
+ return;
+ }
+ }
+ else
+ activity = EmacsActivity.focusedActivities.get (0);
+
+ /* Now request these permissions. */
+ activity.requestPermissions (new String[] { permission,
+ permission1, },
+ 0);
+ }
+ };
+
+ runOnUiThread (runnable);
+ }
+
+ private void
+ requestStorageAccess30 ()
+ {
+ Runnable runnable;
+ final Intent intent;
+
+ intent
+ = new Intent (Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION,
+ Uri.parse ("package:org.gnu.emacs"));
+
+ runnable = new Runnable () {
+ @Override
+ public void
+ run ()
+ {
+ EmacsActivity activity;
+
+ /* Find an activity that is entitled to display a permission
+ request dialog. */
+
+ if (EmacsActivity.focusedActivities.isEmpty ())
+ {
+ /* If focusedActivities is empty then this dialog may
+ have been displayed immediately after another popup
+ dialog was dismissed. Try the EmacsActivity to be
+ focused. */
+
+ activity = EmacsActivity.lastFocusedActivity;
+
+ if (activity == null)
+ {
+ /* Still no luck. Return failure. */
+ return;
+ }
+ }
+ else
+ activity = EmacsActivity.focusedActivities.get (0);
+
+ /* Now request these permissions. */
+
+ activity.startActivity (intent);
+ }
+ };
+
+ runOnUiThread (runnable);
+ }
+
+ public void
+ requestStorageAccess ()
+ {
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R)
+ requestStorageAccess23 ();
+ else
+ requestStorageAccess30 ();
+ }
};
diff --git a/java/org/gnu/emacs/EmacsSurfaceView.java b/java/org/gnu/emacs/EmacsSurfaceView.java
index c47696b35c0..e5601041538 100644
--- a/java/org/gnu/emacs/EmacsSurfaceView.java
+++ b/java/org/gnu/emacs/EmacsSurfaceView.java
@@ -1,6 +1,6 @@
/* Communication module for Android terminals. -*- c-file-style: "GNU" -*-
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/java/org/gnu/emacs/EmacsThread.java b/java/org/gnu/emacs/EmacsThread.java
index 5307015b46f..4adcb98b2f7 100644
--- a/java/org/gnu/emacs/EmacsThread.java
+++ b/java/org/gnu/emacs/EmacsThread.java
@@ -1,6 +1,6 @@
/* Communication module for Android terminals. -*- c-file-style: "GNU" -*-
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/java/org/gnu/emacs/EmacsView.java b/java/org/gnu/emacs/EmacsView.java
index 12d8ff4da56..136d8abc713 100644
--- a/java/org/gnu/emacs/EmacsView.java
+++ b/java/org/gnu/emacs/EmacsView.java
@@ -1,6 +1,6 @@
/* Communication module for Android terminals. -*- c-file-style: "GNU" -*-
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
@@ -24,11 +24,13 @@ import android.content.Context;
import android.text.InputType;
import android.view.ContextMenu;
+import android.view.DragEvent;
import android.view.View;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
+import android.view.WindowInsets;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputConnection;
@@ -302,6 +304,26 @@ public final class EmacsView extends ViewGroup
super.setMeasuredDimension (width, height);
}
+ /* Return whether this view's window is focused. This is made
+ necessary by Android 11's unreliable dispatch of
+ onWindowFocusChanged prior to gesture navigation away from a
+ frame. */
+
+ public boolean
+ checkWindowFocus ()
+ {
+ EmacsActivity activity;
+ Object consumer;
+
+ consumer = window.getAttachedConsumer ();
+
+ if (!(consumer instanceof EmacsActivity))
+ return false;
+
+ activity = (EmacsActivity) consumer;
+ return activity.hasWindowFocus ();
+ }
+
/* Note that the monitor lock for the window must never be held from
within the lock for the view, because the window also locks the
other way around. */
@@ -315,6 +337,7 @@ public final class EmacsView extends ViewGroup
View child;
Rect windowRect;
boolean needExpose;
+ WindowInsets rootWindowInsets;
count = getChildCount ();
needExpose = false;
@@ -330,11 +353,17 @@ public final class EmacsView extends ViewGroup
measuredHeight = bottom - top;
}
+ /* If oldMeasuredHeight or oldMeasuredWidth are wrong, set changed
+ to true as well. */
+
+ if (right - left != oldMeasuredWidth
+ || bottom - top != oldMeasuredHeight)
+ changed = true;
+
/* Dirty the back buffer if the layout change resulted in the view
being resized. */
- if (changed && (right - left != oldMeasuredWidth
- || bottom - top != oldMeasuredHeight))
+ if (changed)
{
explicitlyDirtyBitmap ();
@@ -343,14 +372,37 @@ public final class EmacsView extends ViewGroup
if (right - left > oldMeasuredWidth
|| bottom - top > oldMeasuredHeight)
needExpose = true;
+
+ /* This might return NULL if this view is not attached. */
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R)
+ {
+ /* If a toplevel view is focused and isCurrentlyTextEditor
+ is enabled when the IME is hidden, clear
+ isCurrentlyTextEditor so it isn't shown again if the
+ user dismisses Emacs before returning. */
+ rootWindowInsets = getRootWindowInsets ();
+
+ if (isCurrentlyTextEditor
+ && rootWindowInsets != null
+ && isAttachedToWindow
+ && !rootWindowInsets.isVisible (WindowInsets.Type.ime ())
+ /* N.B. that the keyboard is dismissed during gesture
+ navigation under Android 30, but the system is
+ quite temperamental regarding whether the window is
+ focused at that point. Ideally
+ isCurrentlyTextEditor shouldn't be reset in that
+ case, but detecting that situation appears to be
+ impossible. Sigh. */
+ && (window == EmacsActivity.focusedWindow
+ && hasWindowFocus ()))
+ isCurrentlyTextEditor = false;
+ }
}
for (i = 0; i < count; ++i)
{
child = getChildAt (i);
- Log.d (TAG, "onLayout: " + child);
-
if (child == surfaceView)
child.layout (0, 0, right - left, bottom - top);
else if (child.getVisibility () != GONE)
@@ -386,6 +438,16 @@ public final class EmacsView extends ViewGroup
damageRegion.union (damageRect);
}
+ /* This function enables damage to be recorded without consing a new
+ Rect object. */
+
+ public void
+ damageRect (int left, int top, int right, int bottom)
+ {
+ EmacsService.checkEmacsThread ();
+ damageRegion.op (left, top, right, bottom, Region.Op.UNION);
+ }
+
/* This method is called from both the UI thread and the Emacs
thread. */
@@ -421,6 +483,26 @@ public final class EmacsView extends ViewGroup
@Override
public boolean
+ onKeyPreIme (int keyCode, KeyEvent event)
+ {
+ /* Several Android systems intercept key events representing
+ C-SPC. Avert this by detecting C-SPC events here and relaying
+ them directly to onKeyDown.
+
+ Make this optional though, since some input methods also
+ leverage C-SPC as a shortcut for switching languages. */
+
+ if ((keyCode == KeyEvent.KEYCODE_SPACE
+ && (window.eventModifiers (event)
+ & KeyEvent.META_CTRL_MASK) != 0)
+ && !EmacsNative.shouldForwardCtrlSpace ())
+ return onKeyDown (keyCode, event);
+
+ return super.onKeyPreIme (keyCode, event);
+ }
+
+ @Override
+ public boolean
onKeyDown (int keyCode, KeyEvent event)
{
if ((keyCode == KeyEvent.KEYCODE_VOLUME_UP
@@ -485,6 +567,21 @@ public final class EmacsView extends ViewGroup
return window.onTouchEvent (motion);
}
+ @Override
+ public boolean
+ onDragEvent (DragEvent drag)
+ {
+ /* Inter-program drag and drop isn't supported under Android 23
+ and earlier. */
+
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N)
+ return false;
+
+ return window.onDragEvent (drag);
+ }
+
+
+
private void
moveChildToBack (View child)
{
@@ -498,12 +595,12 @@ public final class EmacsView extends ViewGroup
/* The view at 0 is the surface view. */
attachViewToParent (child, 1,
- child.getLayoutParams());
+ child.getLayoutParams ());
}
}
- /* The following two functions must not be called if the view has no
- parent, or is parented to an activity. */
+ /* The following four functions must not be called if the view has
+ no parent, or is parented to an activity. */
public void
raise ()
@@ -512,8 +609,6 @@ public final class EmacsView extends ViewGroup
parent = (EmacsView) getParent ();
- Log.d (TAG, "raise: parent " + parent);
-
if (parent.indexOfChild (this)
== parent.getChildCount () - 1)
return;
@@ -528,14 +623,46 @@ public final class EmacsView extends ViewGroup
parent = (EmacsView) getParent ();
- Log.d (TAG, "lower: parent " + parent);
-
if (parent.indexOfChild (this) == 1)
return;
parent.moveChildToBack (this);
}
+ public void
+ moveAbove (EmacsView view)
+ {
+ EmacsView parent;
+ int index;
+
+ parent = (EmacsView) getParent ();
+
+ if (parent != view.getParent ())
+ throw new IllegalStateException ("Moving view above non-sibling");
+
+ index = parent.indexOfChild (this);
+ parent.detachViewFromParent (index);
+ index = parent.indexOfChild (view);
+ parent.attachViewToParent (this, index + 1, getLayoutParams ());
+ }
+
+ public void
+ moveBelow (EmacsView view)
+ {
+ EmacsView parent;
+ int index;
+
+ parent = (EmacsView) getParent ();
+
+ if (parent != view.getParent ())
+ throw new IllegalStateException ("Moving view above non-sibling");
+
+ index = parent.indexOfChild (this);
+ parent.detachViewFromParent (index);
+ index = parent.indexOfChild (view);
+ parent.attachViewToParent (this, index, getLayoutParams ());
+ }
+
@Override
protected void
onCreateContextMenu (ContextMenu menu)
@@ -553,12 +680,16 @@ public final class EmacsView extends ViewGroup
if (popupActive && !force)
return false;
+ /* Android will permanently cease to display any popup menus at
+ all if the list of menu items is empty. Prevent this by
+ promptly returning if there are no menu items. */
+
+ if (menu.menuItems.isEmpty ())
+ return false;
+
contextMenu = menu;
popupActive = true;
- Log.d (TAG, "popupMenu: " + menu + " @" + xPosition
- + ", " + yPosition + " " + force);
-
/* Use showContextMenu (float, float) on N to get actual popup
behavior. */
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
@@ -694,14 +825,8 @@ public final class EmacsView extends ViewGroup
selection = EmacsService.viewGetSelection (window.handle);
- if (selection != null)
- Log.d (TAG, "onCreateInputConnection: current selection is: "
- + selection[0] + ", by " + selection[1]);
- else
+ if (selection == null)
{
- Log.d (TAG, "onCreateInputConnection: current selection could"
- + " not be retrieved.");
-
/* If the selection could not be obtained, return 0 by 0.
However, ask for the selection position to be updated as
soon as possible. */
@@ -774,4 +899,33 @@ public final class EmacsView extends ViewGroup
window.notifyContentRectPosition (locations[0],
locations[1]);
}
+
+ @Override
+ public WindowInsets
+ onApplyWindowInsets (WindowInsets insets)
+ {
+ WindowInsets rootWindowInsets;
+
+ /* This function is called when window insets change, which
+ encompasses input method visibility changes under Android 30
+ and later. If a toplevel view is focused and
+ isCurrentlyTextEditor is enabled when the IME is hidden, clear
+ isCurrentlyTextEditor so it isn't shown again if the user
+ dismisses Emacs before returning. */
+
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R)
+ return super.onApplyWindowInsets (insets);
+
+ /* This might return NULL if this view is not attached. */
+ rootWindowInsets = getRootWindowInsets ();
+
+ if (isCurrentlyTextEditor
+ && rootWindowInsets != null
+ && isAttachedToWindow
+ && !rootWindowInsets.isVisible (WindowInsets.Type.ime ())
+ && window == EmacsActivity.focusedWindow)
+ isCurrentlyTextEditor = false;
+
+ return super.onApplyWindowInsets (insets);
+ }
};
diff --git a/java/org/gnu/emacs/EmacsWindow.java b/java/org/gnu/emacs/EmacsWindow.java
index aff5046b22e..207bd22c538 100644
--- a/java/org/gnu/emacs/EmacsWindow.java
+++ b/java/org/gnu/emacs/EmacsWindow.java
@@ -1,6 +1,6 @@
/* Communication module for Android terminals. -*- c-file-style: "GNU" -*-
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
@@ -22,10 +22,13 @@ package org.gnu.emacs;
import java.lang.IllegalStateException;
import java.util.ArrayList;
import java.util.List;
+import java.util.ListIterator;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
+import android.content.ClipData;
+import android.content.ClipDescription;
import android.content.Context;
import android.graphics.Rect;
@@ -33,12 +36,15 @@ import android.graphics.Canvas;
import android.graphics.Bitmap;
import android.graphics.PixelFormat;
-import android.view.View;
-import android.view.ViewManager;
+import android.net.Uri;
+
+import android.view.DragEvent;
import android.view.Gravity;
+import android.view.InputDevice;
import android.view.KeyEvent;
import android.view.MotionEvent;
-import android.view.InputDevice;
+import android.view.View;
+import android.view.ViewManager;
import android.view.WindowManager;
import android.util.Log;
@@ -93,7 +99,9 @@ public final class EmacsWindow extends EmacsHandleObject
public EmacsWindow parent;
/* List of all children in stacking order. This must be kept
- consistent with their Z order! */
+ consistent with their Z order!
+
+ Synchronize access to this list with itself. */
public ArrayList<EmacsWindow> children;
/* Map between pointer identifiers and last known position. Used to
@@ -144,6 +152,10 @@ public final class EmacsWindow extends EmacsHandleObject
/* The position of this window relative to the root window. */
public int xPosition, yPosition;
+ /* The position of the last drag and drop event received; both
+ values are -1 if no drag and drop operation is under way. */
+ private int dndXPosition, dndYPosition;
+
public
EmacsWindow (short handle, final EmacsWindow parent, int x, int y,
int width, int height, boolean overrideRedirect)
@@ -165,7 +177,11 @@ public final class EmacsWindow extends EmacsHandleObject
if (parent != null)
{
- parent.children.add (this);
+ synchronized (parent.children)
+ {
+ parent.children.add (this);
+ }
+
EmacsService.SERVICE.runOnUiThread (new Runnable () {
@Override
public void
@@ -190,6 +206,9 @@ public final class EmacsWindow extends EmacsHandleObject
return size () > 10;
}
};
+
+ dndXPosition = -1;
+ dndYPosition = -1;
}
public void
@@ -214,7 +233,12 @@ public final class EmacsWindow extends EmacsHandleObject
destroyHandle () throws IllegalStateException
{
if (parent != null)
- parent.children.remove (this);
+ {
+ synchronized (parent.children)
+ {
+ parent.children.remove (this);
+ }
+ }
EmacsActivity.invalidateFocus ();
@@ -404,7 +428,7 @@ public final class EmacsWindow extends EmacsHandleObject
manager = EmacsWindowAttachmentManager.MANAGER;
/* If parent is the root window, notice that there are new
- children available for interested activites to pick
+ children available for interested activities to pick
up. */
manager.registerWindow (EmacsWindow.this);
@@ -514,7 +538,17 @@ public final class EmacsWindow extends EmacsHandleObject
public void
damageRect (Rect damageRect)
{
- view.damageRect (damageRect);
+ view.damageRect (damageRect.left,
+ damageRect.top,
+ damageRect.right,
+ damageRect.bottom);
+ }
+
+ @Override
+ public void
+ damageRect (int left, int top, int right, int bottom)
+ {
+ view.damageRect (left, top, right, bottom);
}
public void
@@ -576,7 +610,7 @@ public final class EmacsWindow extends EmacsHandleObject
input EVENT. Replace bits corresponding to Left or Right keys
with their corresponding general modifier bits. */
- private int
+ public static int
eventModifiers (KeyEvent event)
{
int state;
@@ -610,19 +644,44 @@ public final class EmacsWindow extends EmacsHandleObject
public void
onKeyDown (int keyCode, KeyEvent event)
{
- int state, state_1;
+ int state, state_1, num_lock_flag;
long serial;
String characters;
+ if (keyCode == KeyEvent.KEYCODE_BACK)
+ {
+ /* New Android systems display Back navigation buttons on a
+ row of virtual buttons at the bottom of the screen. These
+ buttons function much as physical buttons do, in that key
+ down events are produced when a finger taps them, even if
+ the finger is not ultimately released after the OS's
+ gesture navigation is activated.
+
+ Deliver onKeyDown events in onKeyUp instead, so as not to
+ navigate backwards during gesture navigation. */
+
+ return;
+ }
+
state = eventModifiers (event);
+ /* Num Lock and Scroll Lock aren't supported by systems older than
+ Android 3.0. */
+
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
+ num_lock_flag = (KeyEvent.META_NUM_LOCK_ON
+ | KeyEvent.META_SCROLL_LOCK_ON);
+ else
+ num_lock_flag = 0;
+
/* Ignore meta-state understood by Emacs for now, or key presses
such as Ctrl+C and Meta+C will not be recognized as an ASCII
key press event. */
state_1
= state & ~(KeyEvent.META_ALT_MASK | KeyEvent.META_CTRL_MASK
- | KeyEvent.META_SYM_ON | KeyEvent.META_META_MASK);
+ | KeyEvent.META_SYM_ON | KeyEvent.META_META_MASK
+ | num_lock_flag);
synchronized (eventStrings)
{
@@ -643,25 +702,45 @@ public final class EmacsWindow extends EmacsHandleObject
public void
onKeyUp (int keyCode, KeyEvent event)
{
- int state, state_1;
+ int state, state_1, unicode_char, num_lock_flag;
long time;
/* Compute the event's modifier mask. */
state = eventModifiers (event);
+ /* Num Lock and Scroll Lock aren't supported by systems older than
+ Android 3.0. */
+
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
+ num_lock_flag = (KeyEvent.META_NUM_LOCK_ON
+ | KeyEvent.META_SCROLL_LOCK_ON);
+ else
+ num_lock_flag = 0;
+
/* Ignore meta-state understood by Emacs for now, or key presses
such as Ctrl+C and Meta+C will not be recognized as an ASCII
key press event. */
state_1
= state & ~(KeyEvent.META_ALT_MASK | KeyEvent.META_CTRL_MASK
- | KeyEvent.META_SYM_ON | KeyEvent.META_META_MASK);
+ | KeyEvent.META_SYM_ON | KeyEvent.META_META_MASK
+ | num_lock_flag);
- EmacsNative.sendKeyRelease (this.handle,
- event.getEventTime (),
- state, keyCode,
- getEventUnicodeChar (event,
- state_1));
+ unicode_char = getEventUnicodeChar (event, state_1);
+
+ if (keyCode == KeyEvent.KEYCODE_BACK)
+ {
+ /* If the key press's been canceled, return immediately. */
+
+ if ((event.getFlags () & KeyEvent.FLAG_CANCELED) != 0)
+ return;
+
+ EmacsNative.sendKeyPress (this.handle, event.getEventTime (),
+ state, keyCode, unicode_char);
+ }
+
+ EmacsNative.sendKeyRelease (this.handle, event.getEventTime (),
+ state, keyCode, unicode_char);
if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN)
{
@@ -884,8 +963,8 @@ public final class EmacsWindow extends EmacsHandleObject
it in the map. */
pointerIndex = event.getActionIndex ();
pointerID = event.getPointerId (pointerIndex);
- coordinate = new Coordinate ((int) event.getX (0),
- (int) event.getY (0),
+ coordinate = new Coordinate ((int) event.getX (pointerIndex),
+ (int) event.getY (pointerIndex),
buttonForEvent (event),
pointerID);
pointerMap.put (pointerID, coordinate);
@@ -1153,10 +1232,20 @@ public final class EmacsWindow extends EmacsHandleObject
/* Reparent this window to the other window. */
if (parent != null)
- parent.children.remove (this);
+ {
+ synchronized (parent.children)
+ {
+ parent.children.remove (this);
+ }
+ }
if (otherWindow != null)
- otherWindow.children.add (this);
+ {
+ synchronized (otherWindow.children)
+ {
+ otherWindow.children.add (this);
+ }
+ }
parent = otherWindow;
@@ -1229,9 +1318,12 @@ public final class EmacsWindow extends EmacsHandleObject
if (parent == null)
return;
- /* Remove and add this view again. */
- parent.children.remove (this);
- parent.children.add (this);
+ synchronized (parent.children)
+ {
+ /* Remove and add this view again. */
+ parent.children.remove (this);
+ parent.children.add (this);
+ }
/* Request a relayout. */
EmacsService.SERVICE.runOnUiThread (new Runnable () {
@@ -1251,9 +1343,12 @@ public final class EmacsWindow extends EmacsHandleObject
if (parent == null)
return;
- /* Remove and add this view again. */
- parent.children.remove (this);
- parent.children.add (this);
+ synchronized (parent.children)
+ {
+ /* Remove and add this view again. */
+ parent.children.remove (this);
+ parent.children.add (this);
+ }
/* Request a relayout. */
EmacsService.SERVICE.runOnUiThread (new Runnable () {
@@ -1266,6 +1361,86 @@ public final class EmacsWindow extends EmacsHandleObject
});
}
+ public synchronized void
+ reconfigure (final EmacsWindow window, final int stackMode)
+ {
+ ListIterator<EmacsWindow> iterator;
+ EmacsWindow object;
+
+ /* This does nothing here. */
+ if (parent == null)
+ return;
+
+ /* If window is NULL, call lower or upper subject to
+ stackMode. */
+
+ if (window == null)
+ {
+ if (stackMode == 1) /* ANDROID_BELOW */
+ lower ();
+ else
+ raise ();
+
+ return;
+ }
+
+ /* Otherwise, if window.parent is distinct from this, return. */
+ if (window.parent != this.parent)
+ return;
+
+ /* Synchronize with the parent's child list. Iterate over each
+ item until WINDOW is encountered, before moving this window to
+ the location prescribed by STACKMODE. */
+
+ synchronized (parent.children)
+ {
+ /* Remove this window from parent.children, for it will be
+ reinserted before or after WINDOW. */
+ parent.children.remove (this);
+
+ /* Create an iterator. */
+ iterator = parent.children.listIterator ();
+
+ while (iterator.hasNext ())
+ {
+ object = iterator.next ();
+
+ if (object == window)
+ {
+ /* Now place this before or after the cursor of the
+ iterator. */
+
+ if (stackMode == 0) /* ANDROID_ABOVE */
+ iterator.add (this);
+ else
+ {
+ iterator.previous ();
+ iterator.add (this);
+ }
+
+ /* Effect the same adjustment upon the view
+ hierarchy. */
+
+ EmacsService.SERVICE.runOnUiThread (new Runnable () {
+ @Override
+ public void
+ run ()
+ {
+ if (stackMode == 0)
+ view.moveAbove (window.view);
+ else
+ view.moveBelow (window.view);
+ }
+ });
+ }
+ }
+
+ /* parent.children does not list WINDOW, which should never
+ transpire. */
+ EmacsNative.emacsAbort ();
+ }
+ }
+
public synchronized int[]
getWindowGeometry ()
{
@@ -1442,4 +1617,171 @@ public final class EmacsWindow extends EmacsHandleObject
rect.width (), rect.height ());
}
}
+
+
+
+ /* Drag and drop.
+
+ Android 7.0 and later permit multiple windows to be juxtaposed
+ on-screen, consequently enabling items selected from one window
+ to be dragged onto another. Data is transferred across program
+ boundaries using ClipData items, much the same way clipboard data
+ is transferred.
+
+ When an item is dropped, Emacs must ascertain whether the clip
+ data represents plain text, a content URI incorporating a file,
+ or some other data. This is implemented by examining the clip
+ data's ``description'', which enumerates each of the MIME data
+ types the clip data is capable of providing data in.
+
+ If the clip data represents plain text, then that text is copied
+ into a string and conveyed to Lisp code. Otherwise, Emacs must
+ solicit rights to access the URI from the system, absent which it
+ is accounted plain text and reinterpreted as such, to cue the
+ user that something has gone awry.
+
+ Moreover, events are regularly sent as the item being dragged
+ travels across the frame, even if it might not be dropped. This
+ facilitates cursor motion and scrolling in response, as provided
+ by the options dnd-indicate-insertion-point and
+ dnd-scroll-margin. */
+
+ /* Register the drag and drop event EVENT. */
+
+ public boolean
+ onDragEvent (DragEvent event)
+ {
+ ClipData data;
+ ClipDescription description;
+ int i, j, x, y, itemCount;
+ String type;
+ Uri uri;
+ EmacsActivity activity;
+ StringBuilder builder;
+
+ x = (int) event.getX ();
+ y = (int) event.getY ();
+
+ switch (event.getAction ())
+ {
+ case DragEvent.ACTION_DRAG_STARTED:
+ /* Return true to continue the drag and drop operation. */
+ return true;
+
+ case DragEvent.ACTION_DRAG_LOCATION:
+ /* Send this drag motion event to Emacs. Skip this when the
+ integer position hasn't changed, for Android sends events
+ even if the movement from the previous position of the drag
+ is less than 1 pixel on either axis. */
+
+ if (x != dndXPosition || y != dndYPosition)
+ {
+ EmacsNative.sendDndDrag (handle, x, y);
+ dndXPosition = x;
+ dndYPosition = y;
+ }
+
+ return true;
+
+ case DragEvent.ACTION_DROP:
+ /* Reset this view's record of the previous drag and drop
+ event's position. */
+ dndXPosition = -1;
+ dndYPosition = -1;
+
+ /* Judge whether this is plain text, or if it's a file URI for
+ which permissions must be requested. */
+
+ data = event.getClipData ();
+ description = data.getDescription ();
+ itemCount = data.getItemCount ();
+
+ /* If there are insufficient items within the clip data,
+ return false. */
+
+ if (itemCount < 1)
+ return false;
+
+ /* Search for plain text data within the clipboard. */
+
+ for (i = 0; i < description.getMimeTypeCount (); ++i)
+ {
+ type = description.getMimeType (i);
+
+ if (type.equals (ClipDescription.MIMETYPE_TEXT_PLAIN)
+ || type.equals (ClipDescription.MIMETYPE_TEXT_HTML))
+ {
+ /* The data being dropped is plain text; encode it
+ suitably and send it to the main thread. */
+ type = (data.getItemAt (0).coerceToText (EmacsService.SERVICE)
+ .toString ());
+ EmacsNative.sendDndText (handle, x, y, type);
+ return true;
+ }
+ else if (type.equals (ClipDescription.MIMETYPE_TEXT_URILIST))
+ {
+ /* The data being dropped is a list of URIs; encode it
+ suitably and send it to the main thread. */
+ type = (data.getItemAt (0).coerceToText (EmacsService.SERVICE)
+ .toString ());
+ EmacsNative.sendDndUri (handle, x, y, type);
+ return true;
+ }
+ }
+
+ /* There's no plain text data within this clipboard item, so
+ each item within should be treated as a content URI
+ designating a file. */
+
+ /* Collect the URIs into a string with each suffixed
+ by newlines, much as in a text/uri-list. */
+ builder = new StringBuilder ();
+
+ for (i = 0; i < itemCount; ++i)
+ {
+ /* If the item dropped is a URI, send it to the
+ main thread. */
+
+ uri = data.getItemAt (i).getUri ();
+
+ /* Attempt to acquire permissions for this URI;
+ failing which, insert it as text instead. */
+
+ if (uri != null
+ && uri.getScheme () != null
+ && uri.getScheme ().equals ("content")
+ && (activity = EmacsActivity.lastFocusedActivity) != null)
+ {
+ if ((activity.requestDragAndDropPermissions (event) == null))
+ uri = null;
+ }
+
+ if (uri != null)
+ builder.append (uri.toString ()).append ("\n");
+ else
+ {
+ /* Treat each URI that Emacs cannot secure
+ permissions for as plain text. */
+ type = (data.getItemAt (i)
+ .coerceToText (EmacsService.SERVICE)
+ .toString ());
+ EmacsNative.sendDndText (handle, x, y, type);
+ }
+ }
+
+ /* Now send each URI to Emacs. */
+
+ if (builder.length () > 0)
+ EmacsNative.sendDndUri (handle, x, y, builder.toString ());
+ return true;
+
+ default:
+ /* Reset this view's record of the previous drag and drop
+ event's position. */
+ dndXPosition = -1;
+ dndYPosition = -1;
+ }
+
+ return true;
+ }
};
diff --git a/java/org/gnu/emacs/EmacsWindowAttachmentManager.java b/java/org/gnu/emacs/EmacsWindowAttachmentManager.java
index bc96de7fe1a..18bdb6dbf60 100644
--- a/java/org/gnu/emacs/EmacsWindowAttachmentManager.java
+++ b/java/org/gnu/emacs/EmacsWindowAttachmentManager.java
@@ -1,6 +1,6 @@
/* Communication module for Android terminals. -*- c-file-style: "GNU" -*-
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
@@ -87,21 +87,17 @@ public final class EmacsWindowAttachmentManager
public void
registerWindowConsumer (WindowConsumer consumer)
{
- Log.d (TAG, "registerWindowConsumer " + consumer);
-
consumers.add (consumer);
for (EmacsWindow window : windows)
{
if (window.getAttachedConsumer () == null)
{
- Log.d (TAG, "registerWindowConsumer: attaching " + window);
consumer.attachWindow (window);
return;
}
}
- Log.d (TAG, "registerWindowConsumer: sendWindowAction 0, 0");
EmacsNative.sendWindowAction ((short) 0, 0);
}
@@ -111,21 +107,16 @@ public final class EmacsWindowAttachmentManager
Intent intent;
ActivityOptions options;
- Log.d (TAG, "registerWindow (maybe): " + window);
-
if (windows.contains (window))
/* The window is already registered. */
return;
- Log.d (TAG, "registerWindow: " + window);
-
windows.add (window);
for (WindowConsumer consumer : consumers)
{
if (consumer.getAttachedWindow () == null)
{
- Log.d (TAG, "registerWindow: attaching " + consumer);
consumer.attachWindow (window);
return;
}
@@ -147,8 +138,6 @@ public final class EmacsWindowAttachmentManager
EmacsService.SERVICE.startActivity (intent,
options.toBundle ());
}
-
- Log.d (TAG, "registerWindow: startActivity");
}
public void
@@ -156,19 +145,14 @@ public final class EmacsWindowAttachmentManager
{
EmacsWindow window;
- Log.d (TAG, "removeWindowConsumer " + consumer);
-
window = consumer.getAttachedWindow ();
if (window != null)
{
- Log.d (TAG, "removeWindowConsumer: detaching " + window);
-
consumer.detachWindow ();
window.onActivityDetached (isFinishing);
}
- Log.d (TAG, "removeWindowConsumer: removing " + consumer);
consumers.remove (consumer);
}
@@ -177,14 +161,10 @@ public final class EmacsWindowAttachmentManager
{
WindowConsumer consumer;
- Log.d (TAG, "detachWindow " + window);
-
if (window.getAttachedConsumer () != null)
{
consumer = window.getAttachedConsumer ();
- Log.d (TAG, "detachWindow: removing" + consumer);
-
consumers.remove (consumer);
consumer.destroy ();
}
@@ -197,8 +177,6 @@ public final class EmacsWindowAttachmentManager
{
EmacsWindow window;
- Log.d (TAG, "noticeIconified " + consumer);
-
/* If a window is attached, send the appropriate iconification
events. */
window = consumer.getAttachedWindow ();
@@ -212,8 +190,6 @@ public final class EmacsWindowAttachmentManager
{
EmacsWindow window;
- Log.d (TAG, "noticeDeiconified " + consumer);
-
/* If a window is attached, send the appropriate iconification
events. */
window = consumer.getAttachedWindow ();
diff --git a/java/res/drawable/emacs_background.xml b/java/res/drawable/emacs_background.xml
index c29e0635f7d..448ca48d1cb 100644
--- a/java/res/drawable/emacs_background.xml
+++ b/java/res/drawable/emacs_background.xml
@@ -1,6 +1,6 @@
<!-- Adaptive icon for Emacs.
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/java/res/drawable/emacs_foreground.xml b/java/res/drawable/emacs_foreground.xml
index 68a4631f17b..d4d71f8e29a 100644
--- a/java/res/drawable/emacs_foreground.xml
+++ b/java/res/drawable/emacs_foreground.xml
@@ -1,6 +1,6 @@
<!-- Adaptive icon for Emacs.
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/java/res/layout/sdk8_notifications_view.xml b/java/res/layout/sdk8_notifications_view.xml
index 0572f350cff..a6a441b098f 100644
--- a/java/res/layout/sdk8_notifications_view.xml
+++ b/java/res/layout/sdk8_notifications_view.xml
@@ -1,6 +1,6 @@
<!-- Notification content widget tree for GNU Emacs on Android 2.3.
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/java/res/mipmap-v26/emacs_icon.xml b/java/res/mipmap-v26/emacs_icon.xml
index 9f070e3f3d2..f0a8df92846 100644
--- a/java/res/mipmap-v26/emacs_icon.xml
+++ b/java/res/mipmap-v26/emacs_icon.xml
@@ -1,6 +1,6 @@
<!-- Adaptive icon for Emacs.
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/java/res/values-v11/style.xml b/java/res/values-v11/style.xml
index b114758bf0d..f55dd378e39 100644
--- a/java/res/values-v11/style.xml
+++ b/java/res/values-v11/style.xml
@@ -1,6 +1,6 @@
<!-- Style resources for GNU Emacs on Android.
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/java/res/values-v14/style.xml b/java/res/values-v14/style.xml
index 2cb54dc301b..aa19067d4ec 100644
--- a/java/res/values-v14/style.xml
+++ b/java/res/values-v14/style.xml
@@ -1,6 +1,6 @@
<!-- Style resources for GNU Emacs on Android.
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/java/res/values-v19/bool.xml b/java/res/values-v19/bool.xml
index a4e3a87ae71..fa0f8b5c486 100644
--- a/java/res/values-v19/bool.xml
+++ b/java/res/values-v19/bool.xml
@@ -1,6 +1,6 @@
<!-- Boolean resources for GNU Emacs on Android 4.4 or later.
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/java/res/values-v24/bool.xml b/java/res/values-v24/bool.xml
index 37f07992995..aeab90a0da0 100644
--- a/java/res/values-v24/bool.xml
+++ b/java/res/values-v24/bool.xml
@@ -1,6 +1,6 @@
<!-- Boolean resources for GNU Emacs on Android.
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/java/res/values-v29/style.xml b/java/res/values-v29/style.xml
index ec7b8d14554..4de416c645e 100644
--- a/java/res/values-v29/style.xml
+++ b/java/res/values-v29/style.xml
@@ -1,6 +1,6 @@
<!-- Style resources for GNU Emacs on Android.
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/java/res/values/bool.xml b/java/res/values/bool.xml
index 2b253824e29..f7a7528bead 100644
--- a/java/res/values/bool.xml
+++ b/java/res/values/bool.xml
@@ -1,6 +1,6 @@
<!-- Boolean resources for GNU Emacs on Android.
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/java/res/values/strings.xml b/java/res/values/strings.xml
index 0bf1ef0ac9b..f858b44fe4b 100644
--- a/java/res/values/strings.xml
+++ b/java/res/values/strings.xml
@@ -1,6 +1,6 @@
<!-- String resources used by GNU Emacs on Android.
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/java/res/values/style.xml b/java/res/values/style.xml
index 498e844fda0..64f2f68aea9 100644
--- a/java/res/values/style.xml
+++ b/java/res/values/style.xml
@@ -1,6 +1,6 @@
<!-- Style resources for GNU Emacs on Android.
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/java/res/xml/preferences.xml b/java/res/xml/preferences.xml
index d52d28816e5..8ff93910446 100644
--- a/java/res/xml/preferences.xml
+++ b/java/res/xml/preferences.xml
@@ -1,6 +1,6 @@
<!-- Descriptions for the preferences screen for GNU Emacs on Android.
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/leim/ChangeLog.1 b/leim/ChangeLog.1
index ac17527d66f..23c7a9ce7ce 100644
--- a/leim/ChangeLog.1
+++ b/leim/ChangeLog.1
@@ -2578,7 +2578,7 @@
;; coding: utf-8
;; End:
- Copyright (C) 1997-1999, 2001-2023 Free Software Foundation, Inc.
+ Copyright (C) 1997-1999, 2001-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/leim/Makefile.in b/leim/Makefile.in
index 4c6c3179283..f7a23178919 100644
--- a/leim/Makefile.in
+++ b/leim/Makefile.in
@@ -1,6 +1,6 @@
### @configure_input@
-# Copyright (C) 1997-2023 Free Software Foundation, Inc.
+# Copyright (C) 1997-2024 Free Software Foundation, Inc.
# Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
# 2006, 2007, 2008, 2009, 2010, 2011
# National Institute of Advanced Industrial Science and Technology (AIST)
@@ -26,6 +26,7 @@ SHELL = @SHELL@
# Here are the things that we expect ../configure to edit.
srcdir=@srcdir@
top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
# Where the generated files go.
leimdir = ${srcdir}/../lisp/leim
@@ -134,9 +135,15 @@ ${leimdir}/leim-list.el: ${srcdir}/leim-ext.el ${TIT_MISC}
${leimdir}/ja-dic/ja-dic.el: | $(leimdir)/ja-dic
+# This is used to support regeneration of ja-dic when the SMALL_JA_DIC
+# option is flipped by the configure-time option.
+small-ja-dic-option: ../config.status
+ $(AM_V_GEN)echo "Small ja-dic option: $(SMALL_JA_DIC)" > $@.$$$$ && \
+ ${top_srcdir}/build-aux/move-if-change $@.$$$$ $@
+
.PHONY: generate-ja-dic
generate-ja-dic: ${leimdir}/ja-dic/ja-dic.el
-${leimdir}/ja-dic/ja-dic.el: $(srcdir)/SKK-DIC/SKK-JISYO.L
+${leimdir}/ja-dic/ja-dic.el: $(srcdir)/SKK-DIC/SKK-JISYO.L small-ja-dic-option
$(AM_V_GEN)$(RUN_EMACS) -batch -l ja-dic-cnv \
-f batch-skkdic-convert -dir "$(leimdir)/ja-dic" $(JA_DIC_NO_REDUCTION_OPTION) "$<"
diff --git a/leim/README b/leim/README
index 89219f27db2..054b1710dbd 100644
--- a/leim/README
+++ b/leim/README
@@ -1,4 +1,4 @@
-Copyright (C) 2001-2023 Free Software Foundation, Inc.
+Copyright (C) 2001-2024 Free Software Foundation, Inc.
See the end of the file for license conditions.
diff --git a/leim/leim-ext.el b/leim/leim-ext.el
index d145296e3c8..e710da1004a 100644
--- a/leim/leim-ext.el
+++ b/leim/leim-ext.el
@@ -1,6 +1,6 @@
;;; leim-ext.el --- extra leim configuration -*- lexical-binding: t; -*-
-;; Copyright (C) 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2004-2024 Free Software Foundation, Inc.
;; Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
;; National Institute of Advanced Industrial Science and Technology (AIST)
;; Registration Number H13PRO009
diff --git a/lib-src/ChangeLog.1 b/lib-src/ChangeLog.1
index 136e8917d50..5acb93fb76f 100644
--- a/lib-src/ChangeLog.1
+++ b/lib-src/ChangeLog.1
@@ -1853,7 +1853,7 @@
* emacsclient.c (main): Remove unused variables.
(start_daemon_and_retry_set_socket): Use EXIT_FAILURE.
-2010-09-25 Ulrich Mueller <ulm@gentoo.org>
+2010-09-25 Ulrich Müller <ulm@gentoo.org>
* etags.c (compressors, print_language_names): Support xz compression.
@@ -2498,7 +2498,7 @@
* makefile.w32-in ($(BLD)/sorted-doc.$(O)): Remove spurious backslash.
Reported by Guillaume Conjat <gconjat.ext@orange-ftgroup.com>.
-2008-10-29 Ulrich Mueller <ulm@gentoo.org>
+2008-10-29 Ulrich Müller <ulm@gentoo.org>
* emacsclient.c (set_local_socket): Use TMPDIR (default /tmp)
instead of hardcoded /tmp.
@@ -2539,7 +2539,7 @@
* Makefile.in (CFLAGS): Drop -universal under NS_IMPL_COCOA.
(.m.o): Dispense with GNUstep-specific flags.
-2008-08-05 Ulrich Mueller <ulm@gentoo.org>
+2008-08-05 Ulrich Müller <ulm@gentoo.org>
* pop.c (socket_connection): Add conditionals for
HAVE_KRB5_ERROR_TEXT and HAVE_KRB5_ERROR_E_TEXT to support
@@ -3003,7 +3003,7 @@
* Makefile.in (etags, ctags): Define EMACS_NAME as "GNU Emacs".
-2007-02-20 Ulrich Mueller <ulm@kph.uni-mainz.de> (tiny change)
+2007-02-20 Ulrich Müller <ulm@kph.uni-mainz.de> (tiny change)
* Makefile.in (EMACS, EMACSOPT): New variables.
(blessmail): Use `--no-site-file' when compiling.
@@ -8609,7 +8609,7 @@
;; coding: utf-8
;; End:
- Copyright (C) 1988-1999, 2001-2023 Free Software Foundation, Inc.
+ Copyright (C) 1988-1999, 2001-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/lib-src/Makefile.in b/lib-src/Makefile.in
index 8a5ce019ca2..7c059640862 100644
--- a/lib-src/Makefile.in
+++ b/lib-src/Makefile.in
@@ -1,6 +1,6 @@
### @configure_input@
-# Copyright (C) 1985, 1987-1988, 1993-1994, 2001-2023 Free Software
+# Copyright (C) 1985, 1987-1988, 1993-1994, 2001-2024 Free Software
# Foundation, Inc.
# This file is part of GNU Emacs.
diff --git a/lib-src/asset-directory-tool.c b/lib-src/asset-directory-tool.c
index 99c954a3922..31735586193 100644
--- a/lib-src/asset-directory-tool.c
+++ b/lib-src/asset-directory-tool.c
@@ -1,6 +1,6 @@
/* Android asset directory tool.
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/lib-src/be_resources.cc b/lib-src/be_resources.cc
index f77601d3414..e91ee315803 100644
--- a/lib-src/be_resources.cc
+++ b/lib-src/be_resources.cc
@@ -1,5 +1,5 @@
/* Haiku window system support
- Copyright (C) 2021-2023 Free Software Foundation, Inc.
+ Copyright (C) 2021-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/lib-src/ebrowse.c b/lib-src/ebrowse.c
index 4b71f7447e0..821c29272a4 100644
--- a/lib-src/ebrowse.c
+++ b/lib-src/ebrowse.c
@@ -1,6 +1,6 @@
/* ebrowse.c --- parsing files for the ebrowse C++ browser
-Copyright (C) 1992-2023 Free Software Foundation, Inc.
+Copyright (C) 1992-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/lib-src/emacsclient.c b/lib-src/emacsclient.c
index a72fced1bf2..ea34d5f7b93 100644
--- a/lib-src/emacsclient.c
+++ b/lib-src/emacsclient.c
@@ -1,6 +1,6 @@
/* Client process that communicates with GNU Emacs acting as server.
-Copyright (C) 1986-2023 Free Software Foundation, Inc.
+Copyright (C) 1986-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
@@ -618,6 +618,7 @@ decode_options (int argc, char **argv)
display in DISPLAY (if any). */
if (create_frame && !tty && !display)
{
+#ifndef HAVE_ANDROID
/* Set these here so we use a default_display only when the user
didn't give us an explicit display. */
#if defined (NS_IMPL_COCOA)
@@ -626,16 +627,22 @@ decode_options (int argc, char **argv)
alt_display = "w32";
#elif defined (HAVE_HAIKU)
alt_display = "be";
-#elif defined (HAVE_ANDROID)
- alt_display = "android";
-#endif
+#endif /* NS_IMPL_COCOA */
#ifdef HAVE_PGTK
display = egetenv ("WAYLAND_DISPLAY");
alt_display = egetenv ("DISPLAY");
-#else
+#else /* !HAVE_PGTK */
display = egetenv ("DISPLAY");
-#endif
+#endif /* HAVE_PGTK */
+#else /* HAVE_ANDROID */
+ /* Disregard the DISPLAY environment variable under Android.
+ Several terminal emulator programs furnish their own X
+ servers and set DISPLAY, but an Android build is incapable of
+ displaying X frames. */
+ alt_display = NULL;
+ display = "android";
+#endif /* !HAVE_ANDROID */
}
if (!display)
diff --git a/lib-src/etags.c b/lib-src/etags.c
index 147ecbd7c1b..506366141e6 100644
--- a/lib-src/etags.c
+++ b/lib-src/etags.c
@@ -28,7 +28,7 @@ OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-Copyright (C) 1984, 1987-1989, 1993-1995, 1998-2023 Free Software
+Copyright (C) 1984, 1987-1989, 1993-1995, 1998-2024 Free Software
Foundation, Inc.
This file is not considered part of GNU Emacs.
diff --git a/lib-src/hexl.c b/lib-src/hexl.c
index ff2466a0a57..4b67633e743 100644
--- a/lib-src/hexl.c
+++ b/lib-src/hexl.c
@@ -1,5 +1,5 @@
/* Convert files for Emacs Hexl mode.
- Copyright (C) 1989, 2001-2023 Free Software Foundation, Inc.
+ Copyright (C) 1989, 2001-2024 Free Software Foundation, Inc.
Author: Keith Gabryelski (according to authors.el)
diff --git a/lib-src/make-docfile.c b/lib-src/make-docfile.c
index 1087562dc0b..ac4f320f9a5 100644
--- a/lib-src/make-docfile.c
+++ b/lib-src/make-docfile.c
@@ -1,6 +1,6 @@
/* Generate doc-string file for GNU Emacs from source files.
-Copyright (C) 1985-1986, 1992-1994, 1997, 1999-2023 Free Software
+Copyright (C) 1985-1986, 1992-1994, 1997, 1999-2024 Free Software
Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/lib-src/make-fingerprint.c b/lib-src/make-fingerprint.c
index 7931616096b..dcd2ccc6f54 100644
--- a/lib-src/make-fingerprint.c
+++ b/lib-src/make-fingerprint.c
@@ -1,6 +1,6 @@
/* Hash inputs and generate C file with the digest.
-Copyright (C) 1985-1986, 1992-1994, 1997, 1999-2016, 2018-2023 Free
+Copyright (C) 1985-1986, 1992-1994, 1997, 1999-2016, 2018-2024 Free
Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/lib-src/movemail.c b/lib-src/movemail.c
index 6a772e9043e..407f95e4541 100644
--- a/lib-src/movemail.c
+++ b/lib-src/movemail.c
@@ -1,7 +1,7 @@
/* movemail foo bar -- move file foo to file bar,
locking file foo the way /bin/mail respects.
-Copyright (C) 1986, 1992-1994, 1996, 1999, 2001-2023 Free Software
+Copyright (C) 1986, 1992-1994, 1996, 1999, 2001-2024 Free Software
Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/lib-src/ntlib.c b/lib-src/ntlib.c
index 252bc576c94..55f247f8b5d 100644
--- a/lib-src/ntlib.c
+++ b/lib-src/ntlib.c
@@ -1,6 +1,6 @@
/* Utility and Unix shadow routines for GNU Emacs support programs on NT.
-Copyright (C) 1994, 2001-2023 Free Software Foundation, Inc.
+Copyright (C) 1994, 2001-2024 Free Software Foundation, Inc.
Author: Geoff Voelker (voelker@cs.washington.edu)
Created: 10-8-94
diff --git a/lib-src/ntlib.h b/lib-src/ntlib.h
index f47fb5745de..c0756fde571 100644
--- a/lib-src/ntlib.h
+++ b/lib-src/ntlib.h
@@ -1,5 +1,5 @@
/* Utility and Unix shadow routines for GNU Emacs support programs on NT.
- Copyright (C) 1994, 2002-2023 Free Software Foundation, Inc.
+ Copyright (C) 1994, 2002-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/lib-src/pop.c b/lib-src/pop.c
index c58103a7e65..e2a4f1d8d3b 100644
--- a/lib-src/pop.c
+++ b/lib-src/pop.c
@@ -1,6 +1,6 @@
/* pop.c: client routines for talking to a POP3-protocol post-office server
-Copyright (C) 1991, 1993, 1996-1997, 1999, 2001-2023 Free Software
+Copyright (C) 1991, 1993, 1996-1997, 1999, 2001-2024 Free Software
Foundation, Inc.
Author: Jonathan Kamens <jik@security.ov.com>
diff --git a/lib-src/pop.h b/lib-src/pop.h
index 2f48272edb2..3e7d8c47ee1 100644
--- a/lib-src/pop.h
+++ b/lib-src/pop.h
@@ -1,5 +1,5 @@
/* pop.h: Header file for the "pop.c" client POP3 protocol.
- Copyright (C) 1991, 1993, 2001-2023 Free Software Foundation, Inc.
+ Copyright (C) 1991, 1993, 2001-2024 Free Software Foundation, Inc.
Author: Jonathan Kamens <jik@security.ov.com>
diff --git a/lib-src/rcs2log b/lib-src/rcs2log
index 65fb1c9598f..61301e7246d 100755
--- a/lib-src/rcs2log
+++ b/lib-src/rcs2log
@@ -2,7 +2,7 @@
# RCS to ChangeLog generator
-# Copyright (C) 1992-1998, 2001-2023 Free Software Foundation, Inc.
+# Copyright (C) 1992-1998, 2001-2024 Free Software Foundation, Inc.
# Author: Paul Eggert <eggert@cs.ucla.edu>
@@ -20,7 +20,7 @@
# along with this program. If not, see <https://www.gnu.org/licenses/>.
-Copyright='Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright='Copyright (C) 2024 Free Software Foundation, Inc.
This program comes with NO WARRANTY, to the extent permitted by law.
You may redistribute copies of this program
under the terms of the GNU General Public License.
diff --git a/lib-src/seccomp-filter.c b/lib-src/seccomp-filter.c
index e83c2142e51..8846e6aedae 100644
--- a/lib-src/seccomp-filter.c
+++ b/lib-src/seccomp-filter.c
@@ -1,6 +1,6 @@
/* Generate a Secure Computing filter definition file.
-Copyright (C) 2020-2023 Free Software Foundation, Inc.
+Copyright (C) 2020-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/lib-src/update-game-score.c b/lib-src/update-game-score.c
index 4592e14d1d6..4139073bcd7 100644
--- a/lib-src/update-game-score.c
+++ b/lib-src/update-game-score.c
@@ -1,6 +1,6 @@
/* update-game-score.c --- Update a score file
-Copyright (C) 2002-2023 Free Software Foundation, Inc.
+Copyright (C) 2002-2024 Free Software Foundation, Inc.
Author: Colin Walters <walters@debian.org>
diff --git a/lib/Makefile.in b/lib/Makefile.in
index 6752f68c50e..6706d73ace0 100644
--- a/lib/Makefile.in
+++ b/lib/Makefile.in
@@ -1,6 +1,6 @@
### @configure_input@
-# Copyright 2017-2023 Free Software Foundation, Inc.
+# Copyright 2017-2024 Free Software Foundation, Inc.
# This file is part of GNU Emacs.
diff --git a/lib/_Noreturn.h b/lib/_Noreturn.h
index 6ecea98b54a..7326bd47733 100644
--- a/lib/_Noreturn.h
+++ b/lib/_Noreturn.h
@@ -1,5 +1,5 @@
/* A C macro for declaring that a function does not return.
- Copyright (C) 2011-2023 Free Software Foundation, Inc.
+ Copyright (C) 2011-2024 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published
diff --git a/lib/acl-errno-valid.c b/lib/acl-errno-valid.c
index a4fd575e3f3..ee9407232db 100644
--- a/lib/acl-errno-valid.c
+++ b/lib/acl-errno-valid.c
@@ -1,6 +1,6 @@
/* Test whether ACLs are well supported on this system.
- Copyright 2013-2023 Free Software Foundation, Inc.
+ Copyright 2013-2024 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/lib/acl-internal.c b/lib/acl-internal.c
index fbe9b2c9a06..68aead8de65 100644
--- a/lib/acl-internal.c
+++ b/lib/acl-internal.c
@@ -1,6 +1,6 @@
/* Test whether a file has a nontrivial ACL. -*- coding: utf-8 -*-
- Copyright (C) 2002-2003, 2005-2023 Free Software Foundation, Inc.
+ Copyright (C) 2002-2003, 2005-2024 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/lib/acl-internal.h b/lib/acl-internal.h
index 496e41d7b21..4de891d3f22 100644
--- a/lib/acl-internal.h
+++ b/lib/acl-internal.h
@@ -1,6 +1,6 @@
/* Internal implementation of access control lists. -*- coding: utf-8 -*-
- Copyright (C) 2002-2003, 2005-2023 Free Software Foundation, Inc.
+ Copyright (C) 2002-2003, 2005-2024 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/lib/acl.h b/lib/acl.h
index 0d021200556..a3aeb8fc86a 100644
--- a/lib/acl.h
+++ b/lib/acl.h
@@ -1,6 +1,6 @@
/* acl.c - access control lists
- Copyright (C) 2002, 2008-2023 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2008-2024 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/lib/acl_entries.c b/lib/acl_entries.c
index a59ace3f404..81338323f5c 100644
--- a/lib/acl_entries.c
+++ b/lib/acl_entries.c
@@ -1,6 +1,6 @@
/* Return the number of entries in an ACL.
- Copyright (C) 2002-2003, 2005-2023 Free Software Foundation, Inc.
+ Copyright (C) 2002-2003, 2005-2024 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/lib/af_alg.h b/lib/af_alg.h
index e8ffb3f7a09..ed933e1208d 100644
--- a/lib/af_alg.h
+++ b/lib/af_alg.h
@@ -1,5 +1,5 @@
/* af_alg.h - Compute message digests from file streams and buffers.
- Copyright (C) 2018-2023 Free Software Foundation, Inc.
+ Copyright (C) 2018-2024 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
diff --git a/lib/alloca.in.h b/lib/alloca.in.h
index a1bb3d758dc..49c86125b69 100644
--- a/lib/alloca.in.h
+++ b/lib/alloca.in.h
@@ -1,7 +1,7 @@
/* Memory allocation on the stack.
- Copyright (C) 1995, 1999, 2001-2004, 2006-2023 Free Software Foundation,
- Inc.
+ Copyright (C) 1995, 1999, 2001-2004, 2006-2024 Free Software
+ Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
diff --git a/lib/allocator.c b/lib/allocator.c
index 922be1fce8d..79fffbed14b 100644
--- a/lib/allocator.c
+++ b/lib/allocator.c
@@ -1,6 +1,6 @@
/* Memory allocators such as malloc+free.
- Copyright (C) 2011-2023 Free Software Foundation, Inc.
+ Copyright (C) 2011-2024 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
diff --git a/lib/allocator.h b/lib/allocator.h
index 0c830d01cda..bb30a3440c2 100644
--- a/lib/allocator.h
+++ b/lib/allocator.h
@@ -1,6 +1,6 @@
/* Memory allocators such as malloc+free.
- Copyright (C) 2011-2023 Free Software Foundation, Inc.
+ Copyright (C) 2011-2024 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
diff --git a/lib/arg-nonnull.h b/lib/arg-nonnull.h
index 9498ae1f7da..46c711ca1a1 100644
--- a/lib/arg-nonnull.h
+++ b/lib/arg-nonnull.h
@@ -1,5 +1,5 @@
/* A C macro for declaring that specific arguments must not be NULL.
- Copyright (C) 2009-2023 Free Software Foundation, Inc.
+ Copyright (C) 2009-2024 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published
diff --git a/lib/assert.in.h b/lib/assert.in.h
index b0ab99c776e..6e4995e1455 100644
--- a/lib/assert.in.h
+++ b/lib/assert.in.h
@@ -1,5 +1,5 @@
/* Substitute for and wrapper around <assert.h>
- Copyright (C) 2011-2023 Free Software Foundation, Inc.
+ Copyright (C) 2011-2024 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
diff --git a/lib/at-func.c b/lib/at-func.c
index 13e3fb32056..56b313f4749 100644
--- a/lib/at-func.c
+++ b/lib/at-func.c
@@ -1,5 +1,5 @@
/* Define at-style functions like fstatat, unlinkat, fchownat, etc.
- Copyright (C) 2006, 2009-2023 Free Software Foundation, Inc.
+ Copyright (C) 2006, 2009-2024 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/lib/attribute.h b/lib/attribute.h
index 9464fde0f30..9504c625e59 100644
--- a/lib/attribute.h
+++ b/lib/attribute.h
@@ -1,6 +1,6 @@
/* ATTRIBUTE_* macros for using attributes in GCC and similar compilers
- Copyright 2020-2023 Free Software Foundation, Inc.
+ Copyright 2020-2024 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
diff --git a/lib/binary-io.c b/lib/binary-io.c
index 28a9e6ed69c..40f01d67ee1 100644
--- a/lib/binary-io.c
+++ b/lib/binary-io.c
@@ -1,5 +1,5 @@
/* Binary mode I/O.
- Copyright 2017-2023 Free Software Foundation, Inc.
+ Copyright 2017-2024 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
diff --git a/lib/binary-io.h b/lib/binary-io.h
index 855d6f819f0..33e3de1d1de 100644
--- a/lib/binary-io.h
+++ b/lib/binary-io.h
@@ -1,5 +1,6 @@
/* Binary mode I/O.
- Copyright (C) 2001, 2003, 2005, 2008-2023 Free Software Foundation, Inc.
+ Copyright (C) 2001, 2003, 2005, 2008-2024 Free Software Foundation,
+ Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
diff --git a/lib/boot-time-aux.h b/lib/boot-time-aux.h
index e59a0fd03c7..a7babf6dc64 100644
--- a/lib/boot-time-aux.h
+++ b/lib/boot-time-aux.h
@@ -1,5 +1,5 @@
/* Auxiliary functions for determining the time when the machine last booted.
- Copyright (C) 2023 Free Software Foundation, Inc.
+ Copyright (C) 2023-2024 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published
diff --git a/lib/boot-time.c b/lib/boot-time.c
index fe5b5b88c8e..f560914962b 100644
--- a/lib/boot-time.c
+++ b/lib/boot-time.c
@@ -1,5 +1,5 @@
/* Determine the time when the machine last booted.
- Copyright (C) 2023 Free Software Foundation, Inc.
+ Copyright (C) 2023-2024 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published
diff --git a/lib/boot-time.h b/lib/boot-time.h
index 401e854adbb..99684323ec6 100644
--- a/lib/boot-time.h
+++ b/lib/boot-time.h
@@ -1,5 +1,5 @@
/* Determine the time when the machine last booted.
- Copyright (C) 2023 Free Software Foundation, Inc.
+ Copyright (C) 2023-2024 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published
diff --git a/lib/byteswap.in.h b/lib/byteswap.in.h
index e61be27e917..8e49efad05a 100644
--- a/lib/byteswap.in.h
+++ b/lib/byteswap.in.h
@@ -1,5 +1,5 @@
/* byteswap.h - Byte swapping
- Copyright (C) 2005, 2007, 2009-2023 Free Software Foundation, Inc.
+ Copyright (C) 2005, 2007, 2009-2024 Free Software Foundation, Inc.
Written by Oskar Liljeblad <oskar@osk.mine.nu>, 2005.
This file is free software: you can redistribute it and/or modify
diff --git a/lib/c++defs.h b/lib/c++defs.h
index 458c014de5c..eb66967b09b 100644
--- a/lib/c++defs.h
+++ b/lib/c++defs.h
@@ -1,5 +1,5 @@
/* C++ compatible function declaration macros.
- Copyright (C) 2010-2023 Free Software Foundation, Inc.
+ Copyright (C) 2010-2024 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published
diff --git a/lib/c-ctype.c b/lib/c-ctype.c
index a4343f445f0..d3f1b12d5a9 100644
--- a/lib/c-ctype.c
+++ b/lib/c-ctype.c
@@ -1,6 +1,6 @@
/* Character handling in C locale.
- Copyright (C) 2003-2023 Free Software Foundation, Inc.
+ Copyright (C) 2003-2024 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
diff --git a/lib/c-ctype.h b/lib/c-ctype.h
index cb0f4f3ba1f..016fe7c3b11 100644
--- a/lib/c-ctype.h
+++ b/lib/c-ctype.h
@@ -5,7 +5,8 @@
<ctype.h> functions' behaviour depends on the current locale set via
setlocale.
- Copyright (C) 2000-2003, 2006, 2008-2023 Free Software Foundation, Inc.
+ Copyright (C) 2000-2003, 2006, 2008-2024 Free Software Foundation,
+ Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
diff --git a/lib/c-strcase.h b/lib/c-strcase.h
index 5dfa96c41f4..b75e8dd1cb3 100644
--- a/lib/c-strcase.h
+++ b/lib/c-strcase.h
@@ -1,5 +1,5 @@
/* Case-insensitive string comparison functions in C locale.
- Copyright (C) 1995-1996, 2001, 2003, 2005, 2009-2023 Free Software
+ Copyright (C) 1995-1996, 2001, 2003, 2005, 2009-2024 Free Software
Foundation, Inc.
This file is free software: you can redistribute it and/or modify
diff --git a/lib/c-strcasecmp.c b/lib/c-strcasecmp.c
index 8a958dc4fd9..a4bad4f2e2f 100644
--- a/lib/c-strcasecmp.c
+++ b/lib/c-strcasecmp.c
@@ -1,5 +1,6 @@
/* c-strcasecmp.c -- case insensitive string comparator in C locale
- Copyright (C) 1998-1999, 2005-2006, 2009-2023 Free Software Foundation, Inc.
+ Copyright (C) 1998-1999, 2005-2006, 2009-2024 Free Software
+ Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
diff --git a/lib/c-strncasecmp.c b/lib/c-strncasecmp.c
index 4ca8c5f4001..693601586be 100644
--- a/lib/c-strncasecmp.c
+++ b/lib/c-strncasecmp.c
@@ -1,5 +1,6 @@
/* c-strncasecmp.c -- case insensitive string comparator in C locale
- Copyright (C) 1998-1999, 2005-2006, 2009-2023 Free Software Foundation, Inc.
+ Copyright (C) 1998-1999, 2005-2006, 2009-2024 Free Software
+ Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
diff --git a/lib/canonicalize-lgpl.c b/lib/canonicalize-lgpl.c
index e701297d84b..efd79ceebb8 100644
--- a/lib/canonicalize-lgpl.c
+++ b/lib/canonicalize-lgpl.c
@@ -1,5 +1,5 @@
/* Return the canonical absolute name of a given file.
- Copyright (C) 1996-2023 Free Software Foundation, Inc.
+ Copyright (C) 1996-2024 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/lib/careadlinkat.c b/lib/careadlinkat.c
index 49c92dcc196..9d77aa7067a 100644
--- a/lib/careadlinkat.c
+++ b/lib/careadlinkat.c
@@ -1,7 +1,7 @@
/* Read symbolic links into a buffer without size limitation, relative to fd.
- Copyright (C) 2001, 2003-2004, 2007, 2009-2023 Free Software Foundation,
- Inc.
+ Copyright (C) 2001, 2003-2004, 2007, 2009-2024 Free Software
+ Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
diff --git a/lib/careadlinkat.h b/lib/careadlinkat.h
index 562cf013b75..473e6531e67 100644
--- a/lib/careadlinkat.h
+++ b/lib/careadlinkat.h
@@ -1,6 +1,6 @@
/* Read symbolic links into a buffer without size limitation, relative to fd.
- Copyright (C) 2011-2023 Free Software Foundation, Inc.
+ Copyright (C) 2011-2024 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
diff --git a/lib/cdefs.h b/lib/cdefs.h
index 412f036ce35..87ddce319dc 100644
--- a/lib/cdefs.h
+++ b/lib/cdefs.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 1992-2023 Free Software Foundation, Inc.
+/* Copyright (C) 1992-2024 Free Software Foundation, Inc.
Copyright The GNU Toolchain Authors.
This file is part of the GNU C Library.
diff --git a/lib/cloexec.c b/lib/cloexec.c
index e4cecbd2e8a..b4279752880 100644
--- a/lib/cloexec.c
+++ b/lib/cloexec.c
@@ -1,6 +1,7 @@
/* cloexec.c - set or clear the close-on-exec descriptor flag
- Copyright (C) 1991, 2004-2006, 2009-2023 Free Software Foundation, Inc.
+ Copyright (C) 1991, 2004-2006, 2009-2024 Free Software Foundation,
+ Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
diff --git a/lib/cloexec.h b/lib/cloexec.h
index 057fd668c9b..f52e5f2ec0f 100644
--- a/lib/cloexec.h
+++ b/lib/cloexec.h
@@ -1,6 +1,6 @@
/* cloexec.c - set or clear the close-on-exec descriptor flag
- Copyright (C) 2004, 2009-2023 Free Software Foundation, Inc.
+ Copyright (C) 2004, 2009-2024 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
diff --git a/lib/close-stream.c b/lib/close-stream.c
index ab686bac2ae..ae53f93aabe 100644
--- a/lib/close-stream.c
+++ b/lib/close-stream.c
@@ -1,6 +1,7 @@
/* Close a stream, with nicer error checking than fclose's.
- Copyright (C) 1998-2002, 2004, 2006-2023 Free Software Foundation, Inc.
+ Copyright (C) 1998-2002, 2004, 2006-2024 Free Software Foundation,
+ Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/lib/close-stream.h b/lib/close-stream.h
index 3b52cc66c3d..8a1b3c7ac2c 100644
--- a/lib/close-stream.h
+++ b/lib/close-stream.h
@@ -1,6 +1,6 @@
/* Close a stream, with nicer error checking than fclose's.
- Copyright (C) 2006-2023 Free Software Foundation, Inc.
+ Copyright (C) 2006-2024 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published
diff --git a/lib/copy-file-range.c b/lib/copy-file-range.c
index 747a5a8ad1d..e7e3a441c6b 100644
--- a/lib/copy-file-range.c
+++ b/lib/copy-file-range.c
@@ -1,5 +1,5 @@
/* Stub for copy_file_range
- Copyright 2019-2023 Free Software Foundation, Inc.
+ Copyright 2019-2024 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
diff --git a/lib/count-leading-zeros.c b/lib/count-leading-zeros.c
index 949f156eab1..2bbfd674849 100644
--- a/lib/count-leading-zeros.c
+++ b/lib/count-leading-zeros.c
@@ -1,6 +1,6 @@
/* Count the number of leading 0 bits in a word.
- Copyright (C) 2012-2023 Free Software Foundation, Inc.
+ Copyright (C) 2012-2024 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
diff --git a/lib/count-leading-zeros.h b/lib/count-leading-zeros.h
index 9fe2a03ee09..545749d6d27 100644
--- a/lib/count-leading-zeros.h
+++ b/lib/count-leading-zeros.h
@@ -1,5 +1,5 @@
/* count-leading-zeros.h -- counts the number of leading 0 bits in a word.
- Copyright (C) 2012-2023 Free Software Foundation, Inc.
+ Copyright (C) 2012-2024 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
diff --git a/lib/count-one-bits.c b/lib/count-one-bits.c
index 8a348f2e5a0..54b87088028 100644
--- a/lib/count-one-bits.c
+++ b/lib/count-one-bits.c
@@ -1,6 +1,6 @@
/* Count the number of 1-bits in a word.
- Copyright (C) 2012-2023 Free Software Foundation, Inc.
+ Copyright (C) 2012-2024 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
diff --git a/lib/count-one-bits.h b/lib/count-one-bits.h
index 2821a1fb75e..8d67f8718a4 100644
--- a/lib/count-one-bits.h
+++ b/lib/count-one-bits.h
@@ -1,5 +1,5 @@
/* count-one-bits.h -- counts the number of 1-bits in a word.
- Copyright (C) 2007-2023 Free Software Foundation, Inc.
+ Copyright (C) 2007-2024 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
diff --git a/lib/count-trailing-zeros.c b/lib/count-trailing-zeros.c
index f6fddab4232..e13f77788da 100644
--- a/lib/count-trailing-zeros.c
+++ b/lib/count-trailing-zeros.c
@@ -1,6 +1,6 @@
/* Count the number of trailing 0 bits in a word.
- Copyright 2013-2023 Free Software Foundation, Inc.
+ Copyright 2013-2024 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
diff --git a/lib/count-trailing-zeros.h b/lib/count-trailing-zeros.h
index 9b33df76f6d..ed1e0131147 100644
--- a/lib/count-trailing-zeros.h
+++ b/lib/count-trailing-zeros.h
@@ -1,5 +1,5 @@
/* count-trailing-zeros.h -- counts the number of trailing 0 bits in a word.
- Copyright 2013-2023 Free Software Foundation, Inc.
+ Copyright 2013-2024 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
diff --git a/lib/diffseq.h b/lib/diffseq.h
index 3f85ab2ec41..7f8fa0bc6d3 100644
--- a/lib/diffseq.h
+++ b/lib/diffseq.h
@@ -1,7 +1,7 @@
/* Analyze differences between two vectors.
- Copyright (C) 1988-1989, 1992-1995, 2001-2004, 2006-2023 Free Software
- Foundation, Inc.
+ Copyright (C) 1988-1989, 1992-1995, 2001-2004, 2006-2024 Free
+ Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/lib/dirent-private.h b/lib/dirent-private.h
index 012b6837198..335fbc351a5 100644
--- a/lib/dirent-private.h
+++ b/lib/dirent-private.h
@@ -1,5 +1,5 @@
/* Private details of the DIR type.
- Copyright (C) 2011-2023 Free Software Foundation, Inc.
+ Copyright (C) 2011-2024 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
diff --git a/lib/dirent.in.h b/lib/dirent.in.h
index d409a031ec8..425550ab3ab 100644
--- a/lib/dirent.in.h
+++ b/lib/dirent.in.h
@@ -1,5 +1,5 @@
/* A GNU-like <dirent.h>.
- Copyright (C) 2006-2023 Free Software Foundation, Inc.
+ Copyright (C) 2006-2024 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
diff --git a/lib/dirfd.c b/lib/dirfd.c
index 75b2163c353..70600f2a75a 100644
--- a/lib/dirfd.c
+++ b/lib/dirfd.c
@@ -1,6 +1,6 @@
/* dirfd.c -- return the file descriptor associated with an open DIR*
- Copyright (C) 2001, 2006, 2008-2023 Free Software Foundation, Inc.
+ Copyright (C) 2001, 2006, 2008-2024 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
diff --git a/lib/dtoastr.c b/lib/dtoastr.c
index 66b50995c79..09ddc3c6688 100644
--- a/lib/dtoastr.c
+++ b/lib/dtoastr.c
@@ -1,6 +1,6 @@
/* Convert 'double' to accurate string.
- Copyright (C) 2010-2023 Free Software Foundation, Inc.
+ Copyright (C) 2010-2024 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published
diff --git a/lib/dtotimespec.c b/lib/dtotimespec.c
index 28a44b69171..0557961cf97 100644
--- a/lib/dtotimespec.c
+++ b/lib/dtotimespec.c
@@ -1,6 +1,6 @@
/* Convert double to timespec.
- Copyright (C) 2011-2023 Free Software Foundation, Inc.
+ Copyright (C) 2011-2024 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/lib/dup2.c b/lib/dup2.c
index 7d197ca3123..7e1960e48d3 100644
--- a/lib/dup2.c
+++ b/lib/dup2.c
@@ -1,6 +1,7 @@
/* Duplicate an open file descriptor to a specified file descriptor.
- Copyright (C) 1999, 2004-2007, 2009-2023 Free Software Foundation, Inc.
+ Copyright (C) 1999, 2004-2007, 2009-2024 Free Software Foundation,
+ Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
diff --git a/lib/dynarray.h b/lib/dynarray.h
index 9155910934f..8940e81b25d 100644
--- a/lib/dynarray.h
+++ b/lib/dynarray.h
@@ -1,5 +1,5 @@
/* Type-safe arrays which grow dynamically.
- Copyright 2021-2023 Free Software Foundation, Inc.
+ Copyright 2021-2024 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
diff --git a/lib/eloop-threshold.h b/lib/eloop-threshold.h
index d9b154e4868..84d19b458b8 100644
--- a/lib/eloop-threshold.h
+++ b/lib/eloop-threshold.h
@@ -1,5 +1,5 @@
/* Threshold at which to diagnose ELOOP. Generic version.
- Copyright (C) 2012-2023 Free Software Foundation, Inc.
+ Copyright (C) 2012-2024 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/lib/errno.in.h b/lib/errno.in.h
index 3dda9c260e6..aa658e62708 100644
--- a/lib/errno.in.h
+++ b/lib/errno.in.h
@@ -1,6 +1,6 @@
/* A POSIX-like <errno.h>.
- Copyright (C) 2008-2023 Free Software Foundation, Inc.
+ Copyright (C) 2008-2024 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
diff --git a/lib/euidaccess.c b/lib/euidaccess.c
index c2ecbeff52a..ad392dba19c 100644
--- a/lib/euidaccess.c
+++ b/lib/euidaccess.c
@@ -1,6 +1,6 @@
/* euidaccess -- check if effective user id can access file
- Copyright (C) 1990-1991, 1995, 1998, 2000, 2003-2006, 2008-2023 Free
+ Copyright (C) 1990-1991, 1995, 1998, 2000, 2003-2006, 2008-2024 Free
Software Foundation, Inc.
This file is part of the GNU C Library.
diff --git a/lib/execinfo.c b/lib/execinfo.c
index 2048d00f5fb..ea30f4140b2 100644
--- a/lib/execinfo.c
+++ b/lib/execinfo.c
@@ -1,6 +1,6 @@
/* Information about executables.
- Copyright (C) 2012-2023 Free Software Foundation, Inc.
+ Copyright (C) 2012-2024 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
diff --git a/lib/execinfo.in.h b/lib/execinfo.in.h
index 56b04d1d862..0ffb2c386e7 100644
--- a/lib/execinfo.in.h
+++ b/lib/execinfo.in.h
@@ -1,6 +1,6 @@
/* Information about executables.
- Copyright (C) 2012-2023 Free Software Foundation, Inc.
+ Copyright (C) 2012-2024 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
diff --git a/lib/explicit_bzero.c b/lib/explicit_bzero.c
index c33cab9e6d5..91c31c52dd3 100644
--- a/lib/explicit_bzero.c
+++ b/lib/explicit_bzero.c
@@ -1,5 +1,5 @@
/* Erasure of sensitive data, generic implementation.
- Copyright (C) 2016-2023 Free Software Foundation, Inc.
+ Copyright (C) 2016-2024 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/lib/faccessat.c b/lib/faccessat.c
index ac8977cfd65..f82eca2dbe3 100644
--- a/lib/faccessat.c
+++ b/lib/faccessat.c
@@ -1,5 +1,5 @@
/* Check the access rights of a file relative to an open directory.
- Copyright (C) 2009-2023 Free Software Foundation, Inc.
+ Copyright (C) 2009-2024 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/lib/fchmodat.c b/lib/fchmodat.c
index a7b70a2af2c..00f6cf62448 100644
--- a/lib/fchmodat.c
+++ b/lib/fchmodat.c
@@ -1,5 +1,5 @@
/* Change the protections of file relative to an open directory.
- Copyright (C) 2006, 2009-2023 Free Software Foundation, Inc.
+ Copyright (C) 2006, 2009-2024 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/lib/fcntl.c b/lib/fcntl.c
index e220800845b..7cd3a0f976d 100644
--- a/lib/fcntl.c
+++ b/lib/fcntl.c
@@ -1,6 +1,6 @@
/* Provide file descriptor control.
- Copyright (C) 2009-2023 Free Software Foundation, Inc.
+ Copyright (C) 2009-2024 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
diff --git a/lib/fcntl.in.h b/lib/fcntl.in.h
index d0bb85f30b5..eea3b9542a5 100644
--- a/lib/fcntl.in.h
+++ b/lib/fcntl.in.h
@@ -1,6 +1,6 @@
/* Like <fcntl.h>, but with non-working flags defined to 0.
- Copyright (C) 2006-2023 Free Software Foundation, Inc.
+ Copyright (C) 2006-2024 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
diff --git a/lib/fdopendir.c b/lib/fdopendir.c
index 0f43d6ff349..e49abec4f62 100644
--- a/lib/fdopendir.c
+++ b/lib/fdopendir.c
@@ -1,5 +1,5 @@
/* provide a replacement fdopendir function
- Copyright (C) 2004-2023 Free Software Foundation, Inc.
+ Copyright (C) 2004-2024 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/lib/file-has-acl.c b/lib/file-has-acl.c
index 3eeaf9c57d1..898fb030d1d 100644
--- a/lib/file-has-acl.c
+++ b/lib/file-has-acl.c
@@ -1,6 +1,6 @@
/* Test whether a file has a nontrivial ACL. -*- coding: utf-8 -*-
- Copyright (C) 2002-2003, 2005-2023 Free Software Foundation, Inc.
+ Copyright (C) 2002-2003, 2005-2024 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/lib/filemode.c b/lib/filemode.c
index 318d287f27d..9be6aad1878 100644
--- a/lib/filemode.c
+++ b/lib/filemode.c
@@ -1,6 +1,6 @@
/* filemode.c -- make a string describing file modes
- Copyright (C) 1985, 1990, 1993, 1998-2000, 2004, 2006, 2009-2023 Free
+ Copyright (C) 1985, 1990, 1993, 1998-2000, 2004, 2006, 2009-2024 Free
Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
diff --git a/lib/filemode.h b/lib/filemode.h
index 3e1d9903eac..bb601c11d3f 100644
--- a/lib/filemode.h
+++ b/lib/filemode.h
@@ -1,7 +1,7 @@
/* Make a string describing file modes.
- Copyright (C) 1998-1999, 2003, 2006, 2009-2023 Free Software Foundation,
- Inc.
+ Copyright (C) 1998-1999, 2003, 2006, 2009-2024 Free Software
+ Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/lib/filename.h b/lib/filename.h
index a2400a9dfe3..4f0f0fbc3c6 100644
--- a/lib/filename.h
+++ b/lib/filename.h
@@ -1,5 +1,5 @@
/* Basic filename support macros.
- Copyright (C) 2001-2023 Free Software Foundation, Inc.
+ Copyright (C) 2001-2024 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/lib/filevercmp.c b/lib/filevercmp.c
index 78e1faff536..88745b5f1d4 100644
--- a/lib/filevercmp.c
+++ b/lib/filevercmp.c
@@ -2,7 +2,7 @@
Copyright (C) 1995 Ian Jackson <iwj10@cus.cam.ac.uk>
Copyright (C) 2001 Anthony Towns <aj@azure.humbug.org.au>
- Copyright (C) 2008-2023 Free Software Foundation, Inc.
+ Copyright (C) 2008-2024 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
diff --git a/lib/filevercmp.h b/lib/filevercmp.h
index 9e052bdd08c..8c549fcda00 100644
--- a/lib/filevercmp.h
+++ b/lib/filevercmp.h
@@ -2,7 +2,7 @@
Copyright (C) 1995 Ian Jackson <iwj10@cus.cam.ac.uk>
Copyright (C) 2001 Anthony Towns <aj@azure.humbug.org.au>
- Copyright (C) 2008-2023 Free Software Foundation, Inc.
+ Copyright (C) 2008-2024 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
diff --git a/lib/fingerprint.c b/lib/fingerprint.c
index d83de2245e8..52d4b25e599 100644
--- a/lib/fingerprint.c
+++ b/lib/fingerprint.c
@@ -1,6 +1,6 @@
/* Placeholder fingerprint for Emacs
-Copyright 2019-2023 Free Software Foundation, Inc.
+Copyright 2019-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/lib/fingerprint.h b/lib/fingerprint.h
index 0bb099ceeee..74a6a4b281d 100644
--- a/lib/fingerprint.h
+++ b/lib/fingerprint.h
@@ -1,6 +1,6 @@
/* Header file for the Emacs build fingerprint.
-Copyright (C) 2016, 2018-2023 Free Software Foundation, Inc.
+Copyright (C) 2016, 2018-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/lib/flexmember.h b/lib/flexmember.h
index 8df44195392..6ef66a32d32 100644
--- a/lib/flexmember.h
+++ b/lib/flexmember.h
@@ -1,6 +1,6 @@
/* Sizes of structs with flexible array members.
- Copyright 2016-2023 Free Software Foundation, Inc.
+ Copyright 2016-2024 Free Software Foundation, Inc.
This file is part of the GNU C Library.
diff --git a/lib/fpending.c b/lib/fpending.c
index e57155e586e..8d90bdee51b 100644
--- a/lib/fpending.c
+++ b/lib/fpending.c
@@ -1,6 +1,6 @@
/* fpending.c -- return the number of pending output bytes on a stream
- Copyright (C) 2000, 2004, 2006-2007, 2009-2023 Free Software Foundation,
- Inc.
+ Copyright (C) 2000, 2004, 2006-2007, 2009-2024 Free Software
+ Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/lib/fpending.h b/lib/fpending.h
index 1604ca0b7af..15122915254 100644
--- a/lib/fpending.h
+++ b/lib/fpending.h
@@ -1,7 +1,7 @@
/* Declare __fpending.
- Copyright (C) 2000, 2003, 2005-2006, 2009-2023 Free Software Foundation,
- Inc.
+ Copyright (C) 2000, 2003, 2005-2006, 2009-2024 Free Software
+ Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/lib/free.c b/lib/free.c
index 372a6b0fecf..2f0c40ba89d 100644
--- a/lib/free.c
+++ b/lib/free.c
@@ -1,6 +1,6 @@
/* Make free() preserve errno.
- Copyright (C) 2003, 2006, 2009-2023 Free Software Foundation, Inc.
+ Copyright (C) 2003, 2006, 2009-2024 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
diff --git a/lib/fstatat.c b/lib/fstatat.c
index 372965ef5f6..470ef336cff 100644
--- a/lib/fstatat.c
+++ b/lib/fstatat.c
@@ -1,6 +1,6 @@
/* Work around an fstatat bug on Solaris 9.
- Copyright (C) 2006, 2009-2023 Free Software Foundation, Inc.
+ Copyright (C) 2006, 2009-2024 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/lib/fsusage.c b/lib/fsusage.c
index f6f4b1c35fd..d99a02f01f3 100644
--- a/lib/fsusage.c
+++ b/lib/fsusage.c
@@ -1,7 +1,7 @@
/* fsusage.c -- return space usage of mounted file systems
- Copyright (C) 1991-1992, 1996, 1998-1999, 2002-2006, 2009-2023 Free Software
- Foundation, Inc.
+ Copyright (C) 1991-1992, 1996, 1998-1999, 2002-2006, 2009-2024 Free
+ Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
diff --git a/lib/fsusage.h b/lib/fsusage.h
index 9630b04e001..d7ae5f63a36 100644
--- a/lib/fsusage.h
+++ b/lib/fsusage.h
@@ -1,6 +1,6 @@
/* fsusage.h -- declarations for file system space usage info
- Copyright (C) 1991-1992, 1997, 2003-2006, 2009-2023 Free Software
+ Copyright (C) 1991-1992, 1997, 2003-2006, 2009-2024 Free Software
Foundation, Inc.
This file is free software: you can redistribute it and/or modify
diff --git a/lib/fsync.c b/lib/fsync.c
index 51314662872..10a70023a15 100644
--- a/lib/fsync.c
+++ b/lib/fsync.c
@@ -7,7 +7,7 @@
Written by Richard W.M. Jones <rjones.at.redhat.com>
- Copyright (C) 2008-2023 Free Software Foundation, Inc.
+ Copyright (C) 2008-2024 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
diff --git a/lib/ftoastr.c b/lib/ftoastr.c
index 8740a4d86c8..4ecde06cea9 100644
--- a/lib/ftoastr.c
+++ b/lib/ftoastr.c
@@ -1,6 +1,6 @@
/* floating point to accurate string
- Copyright (C) 2010-2023 Free Software Foundation, Inc.
+ Copyright (C) 2010-2024 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/lib/ftoastr.h b/lib/ftoastr.h
index 1ce1b7a4bc6..ed43c961a04 100644
--- a/lib/ftoastr.h
+++ b/lib/ftoastr.h
@@ -1,6 +1,6 @@
/* floating point to accurate string
- Copyright (C) 2010-2023 Free Software Foundation, Inc.
+ Copyright (C) 2010-2024 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/lib/futimens.c b/lib/futimens.c
index 5bb30493c7e..defae933ade 100644
--- a/lib/futimens.c
+++ b/lib/futimens.c
@@ -1,5 +1,5 @@
/* Set the access and modification time of an open fd.
- Copyright (C) 2009-2023 Free Software Foundation, Inc.
+ Copyright (C) 2009-2024 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
diff --git a/lib/get-permissions.c b/lib/get-permissions.c
index 545ad23195b..36848d3d080 100644
--- a/lib/get-permissions.c
+++ b/lib/get-permissions.c
@@ -1,6 +1,6 @@
/* Get permissions of a file. -*- coding: utf-8 -*-
- Copyright (C) 2002-2003, 2005-2023 Free Software Foundation, Inc.
+ Copyright (C) 2002-2003, 2005-2024 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/lib/getdelim.c b/lib/getdelim.c
index e414df648f6..58063b156e7 100644
--- a/lib/getdelim.c
+++ b/lib/getdelim.c
@@ -1,5 +1,5 @@
/* getdelim.c --- Implementation of replacement getdelim function.
- Copyright (C) 1994, 1996-1998, 2001, 2003, 2005-2023 Free Software
+ Copyright (C) 1994, 1996-1998, 2001, 2003, 2005-2024 Free Software
Foundation, Inc.
This file is free software: you can redistribute it and/or modify
diff --git a/lib/getdtablesize.c b/lib/getdtablesize.c
index ac2d1753a6b..762c100b38a 100644
--- a/lib/getdtablesize.c
+++ b/lib/getdtablesize.c
@@ -1,5 +1,5 @@
/* getdtablesize() function: Return maximum possible file descriptor value + 1.
- Copyright (C) 2008-2023 Free Software Foundation, Inc.
+ Copyright (C) 2008-2024 Free Software Foundation, Inc.
Written by Bruno Haible <bruno@clisp.org>, 2008.
This file is free software: you can redistribute it and/or modify
diff --git a/lib/getgroups.c b/lib/getgroups.c
index 93829d3b15e..346954adaad 100644
--- a/lib/getgroups.c
+++ b/lib/getgroups.c
@@ -1,6 +1,7 @@
/* provide consistent interface to getgroups for systems that don't allow N==0
- Copyright (C) 1996, 1999, 2003, 2006-2023 Free Software Foundation, Inc.
+ Copyright (C) 1996, 1999, 2003, 2006-2024 Free Software Foundation,
+ Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
diff --git a/lib/getline.c b/lib/getline.c
index 85f16ab8bac..2d03b64689e 100644
--- a/lib/getline.c
+++ b/lib/getline.c
@@ -1,5 +1,5 @@
/* getline.c --- Implementation of replacement getline function.
- Copyright (C) 2005-2007, 2009-2023 Free Software Foundation, Inc.
+ Copyright (C) 2005-2007, 2009-2024 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
diff --git a/lib/getloadavg.c b/lib/getloadavg.c
index 59b53e79980..7f0a236c870 100644
--- a/lib/getloadavg.c
+++ b/lib/getloadavg.c
@@ -1,7 +1,7 @@
/* Get the system load averages.
- Copyright (C) 1985-1989, 1991-1995, 1997, 1999-2000, 2003-2023 Free Software
- Foundation, Inc.
+ Copyright (C) 1985-1989, 1991-1995, 1997, 1999-2000, 2003-2024 Free
+ Software Foundation, Inc.
NOTE: The canonical source of this file is maintained with gnulib.
Bugs can be reported to bug-gnulib@gnu.org.
diff --git a/lib/getopt-cdefs.in.h b/lib/getopt-cdefs.in.h
index e76c78cb212..7a791392de5 100644
--- a/lib/getopt-cdefs.in.h
+++ b/lib/getopt-cdefs.in.h
@@ -1,5 +1,5 @@
/* getopt-on-non-glibc compatibility macros.
- Copyright (C) 1989-2023 Free Software Foundation, Inc.
+ Copyright (C) 1989-2024 Free Software Foundation, Inc.
This file is part of gnulib.
Unlike most of the getopt implementation, it is NOT shared
with the GNU C Library.
diff --git a/lib/getopt-core.h b/lib/getopt-core.h
index c5dd49363f0..12d09a25c0d 100644
--- a/lib/getopt-core.h
+++ b/lib/getopt-core.h
@@ -1,5 +1,5 @@
/* Declarations for getopt (basic, portable features only).
- Copyright (C) 1989-2023 Free Software Foundation, Inc.
+ Copyright (C) 1989-2024 Free Software Foundation, Inc.
This file is part of the GNU C Library and is also part of gnulib.
Patches to this file should be submitted to both projects.
diff --git a/lib/getopt-ext.h b/lib/getopt-ext.h
index d37c29328b2..e4b499d4e82 100644
--- a/lib/getopt-ext.h
+++ b/lib/getopt-ext.h
@@ -1,5 +1,5 @@
/* Declarations for getopt (GNU extensions).
- Copyright (C) 1989-2023 Free Software Foundation, Inc.
+ Copyright (C) 1989-2024 Free Software Foundation, Inc.
This file is part of the GNU C Library and is also part of gnulib.
Patches to this file should be submitted to both projects.
diff --git a/lib/getopt-pfx-core.h b/lib/getopt-pfx-core.h
index 095e3930feb..78b7816aa42 100644
--- a/lib/getopt-pfx-core.h
+++ b/lib/getopt-pfx-core.h
@@ -1,5 +1,5 @@
/* getopt (basic, portable features) gnulib wrapper header.
- Copyright (C) 1989-2023 Free Software Foundation, Inc.
+ Copyright (C) 1989-2024 Free Software Foundation, Inc.
This file is part of gnulib.
Unlike most of the getopt implementation, it is NOT shared
with the GNU C Library.
diff --git a/lib/getopt-pfx-ext.h b/lib/getopt-pfx-ext.h
index 8578d72530a..f001c11e057 100644
--- a/lib/getopt-pfx-ext.h
+++ b/lib/getopt-pfx-ext.h
@@ -1,5 +1,5 @@
/* getopt (GNU extensions) gnulib wrapper header.
- Copyright (C) 1989-2023 Free Software Foundation, Inc.
+ Copyright (C) 1989-2024 Free Software Foundation, Inc.
This file is part of gnulib.
Unlike most of the getopt implementation, it is NOT shared
with the GNU C Library.
diff --git a/lib/getopt.c b/lib/getopt.c
index 1e2441c4afe..e2951f74601 100644
--- a/lib/getopt.c
+++ b/lib/getopt.c
@@ -1,5 +1,5 @@
/* Getopt for GNU.
- Copyright (C) 1987-2023 Free Software Foundation, Inc.
+ Copyright (C) 1987-2024 Free Software Foundation, Inc.
This file is part of the GNU C Library and is also part of gnulib.
Patches to this file should be submitted to both projects.
diff --git a/lib/getopt.in.h b/lib/getopt.in.h
index 0867d365f47..c2411a754fa 100644
--- a/lib/getopt.in.h
+++ b/lib/getopt.in.h
@@ -1,5 +1,5 @@
/* Declarations for getopt.
- Copyright (C) 1989-2023 Free Software Foundation, Inc.
+ Copyright (C) 1989-2024 Free Software Foundation, Inc.
This file is part of gnulib.
Unlike most of the getopt implementation, it is NOT shared
with the GNU C Library, which supplies a different version of
diff --git a/lib/getopt1.c b/lib/getopt1.c
index 49323aa8ed1..0c8e29b5b91 100644
--- a/lib/getopt1.c
+++ b/lib/getopt1.c
@@ -1,5 +1,5 @@
/* getopt_long and getopt_long_only entry points for GNU getopt.
- Copyright (C) 1987-2023 Free Software Foundation, Inc.
+ Copyright (C) 1987-2024 Free Software Foundation, Inc.
This file is part of the GNU C Library and is also part of gnulib.
Patches to this file should be submitted to both projects.
diff --git a/lib/getopt_int.h b/lib/getopt_int.h
index 4d9e24beebc..c00c0b69404 100644
--- a/lib/getopt_int.h
+++ b/lib/getopt_int.h
@@ -1,5 +1,5 @@
/* Internal declarations for getopt.
- Copyright (C) 1989-2023 Free Software Foundation, Inc.
+ Copyright (C) 1989-2024 Free Software Foundation, Inc.
This file is part of the GNU C Library and is also part of gnulib.
Patches to this file should be submitted to both projects.
diff --git a/lib/getrandom.c b/lib/getrandom.c
index 19bb3429baf..44283cf1816 100644
--- a/lib/getrandom.c
+++ b/lib/getrandom.c
@@ -1,6 +1,6 @@
/* Obtain a series of random bytes.
- Copyright 2020-2023 Free Software Foundation, Inc.
+ Copyright 2020-2024 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
diff --git a/lib/gettext.h b/lib/gettext.h
index d0462c47e17..970032306e5 100644
--- a/lib/gettext.h
+++ b/lib/gettext.h
@@ -1,6 +1,6 @@
/* Convenience header for conditional use of GNU <libintl.h>.
- Copyright (C) 1995-1998, 2000-2002, 2004-2006, 2009-2023 Free Software
- Foundation, Inc.
+ Copyright (C) 1995-1998, 2000-2002, 2004-2006, 2009-2024 Free
+ Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
diff --git a/lib/gettime.c b/lib/gettime.c
index ec40ff903e1..1f6d960713b 100644
--- a/lib/gettime.c
+++ b/lib/gettime.c
@@ -1,6 +1,7 @@
/* gettime -- get the system clock
- Copyright (C) 2002, 2004-2007, 2009-2023 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2004-2007, 2009-2024 Free Software Foundation,
+ Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
diff --git a/lib/gettimeofday.c b/lib/gettimeofday.c
index c71629cbc57..ddef1425a4d 100644
--- a/lib/gettimeofday.c
+++ b/lib/gettimeofday.c
@@ -1,6 +1,7 @@
/* Provide gettimeofday for systems that don't have it or for which it's broken.
- Copyright (C) 2001-2003, 2005-2007, 2009-2023 Free Software Foundation, Inc.
+ Copyright (C) 2001-2003, 2005-2007, 2009-2024 Free Software
+ Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
diff --git a/lib/gnulib.mk.in b/lib/gnulib.mk.in
index 3b33f39f73b..add29f83883 100644
--- a/lib/gnulib.mk.in
+++ b/lib/gnulib.mk.in
@@ -1,5 +1,5 @@
## DO NOT EDIT! GENERATED AUTOMATICALLY!
-# Copyright (C) 2002-2023 Free Software Foundation, Inc.
+# Copyright (C) 2002-2024 Free Software Foundation, Inc.
#
# This file is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
diff --git a/lib/group-member.c b/lib/group-member.c
index 96a09f94a8f..300d58bdbaa 100644
--- a/lib/group-member.c
+++ b/lib/group-member.c
@@ -1,7 +1,7 @@
/* group-member.c -- determine whether group id is in calling user's group list
- Copyright (C) 1994, 1997-1998, 2003, 2005-2006, 2009-2023 Free Software
- Foundation, Inc.
+ Copyright (C) 1994, 1997-1998, 2003, 2005-2006, 2009-2024 Free
+ Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
diff --git a/lib/idx.h b/lib/idx.h
index 23020b7ec0c..f9ce0acd57d 100644
--- a/lib/idx.h
+++ b/lib/idx.h
@@ -1,5 +1,5 @@
/* A type for indices and sizes.
- Copyright (C) 2020-2023 Free Software Foundation, Inc.
+ Copyright (C) 2020-2024 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/lib/ieee754.in.h b/lib/ieee754.in.h
index 8de4c32be5e..805048ca9fc 100644
--- a/lib/ieee754.in.h
+++ b/lib/ieee754.in.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 1992-2023 Free Software Foundation, Inc.
+/* Copyright (C) 1992-2024 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/lib/ignore-value.h b/lib/ignore-value.h
index f0b569af4a7..de4a240cef4 100644
--- a/lib/ignore-value.h
+++ b/lib/ignore-value.h
@@ -1,6 +1,6 @@
/* ignore a function return without a compiler warning. -*- coding: utf-8 -*-
- Copyright (C) 2008-2023 Free Software Foundation, Inc.
+ Copyright (C) 2008-2024 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
diff --git a/lib/intprops-internal.h b/lib/intprops-internal.h
index 0467a9ca8f2..dcbf537786a 100644
--- a/lib/intprops-internal.h
+++ b/lib/intprops-internal.h
@@ -1,6 +1,6 @@
/* intprops-internal.h -- properties of integer types not visible to users
- Copyright (C) 2001-2023 Free Software Foundation, Inc.
+ Copyright (C) 2001-2024 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published
diff --git a/lib/intprops.h b/lib/intprops.h
index 44b5e60fb9a..43734f3440a 100644
--- a/lib/intprops.h
+++ b/lib/intprops.h
@@ -1,6 +1,6 @@
/* intprops.h -- properties of integer types
- Copyright (C) 2001-2023 Free Software Foundation, Inc.
+ Copyright (C) 2001-2024 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published
diff --git a/lib/inttypes.in.h b/lib/inttypes.in.h
index 22643876ab3..b9ab8a4b424 100644
--- a/lib/inttypes.in.h
+++ b/lib/inttypes.in.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2006-2023 Free Software Foundation, Inc.
+/* Copyright (C) 2006-2024 Free Software Foundation, Inc.
Written by Paul Eggert, Bruno Haible, Derek Price.
This file is part of gnulib.
diff --git a/lib/lchmod.c b/lib/lchmod.c
index b2d1b8bfde1..8056f0b197d 100644
--- a/lib/lchmod.c
+++ b/lib/lchmod.c
@@ -1,6 +1,6 @@
/* Implement lchmod on platforms where it does not work correctly.
- Copyright 2020-2023 Free Software Foundation, Inc.
+ Copyright 2020-2024 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/lib/libc-config.h b/lib/libc-config.h
index 5f5ad010377..70114608fb1 100644
--- a/lib/libc-config.h
+++ b/lib/libc-config.h
@@ -1,6 +1,6 @@
/* System definitions for code taken from the GNU C Library
- Copyright 2017-2023 Free Software Foundation, Inc.
+ Copyright 2017-2024 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
diff --git a/lib/limits.in.h b/lib/limits.in.h
index e2e173eb2de..236fc58e525 100644
--- a/lib/limits.in.h
+++ b/lib/limits.in.h
@@ -1,6 +1,6 @@
/* A GNU-like <limits.h>.
- Copyright 2016-2023 Free Software Foundation, Inc.
+ Copyright 2016-2024 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
diff --git a/lib/lstat.c b/lib/lstat.c
index 00a4ce2ab87..7c09957e20d 100644
--- a/lib/lstat.c
+++ b/lib/lstat.c
@@ -1,6 +1,6 @@
/* Work around a bug of lstat on some systems
- Copyright (C) 1997-2006, 2008-2023 Free Software Foundation, Inc.
+ Copyright (C) 1997-2006, 2008-2024 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
diff --git a/lib/malloc.c b/lib/malloc.c
index 3ade35cb63f..7b954ae1129 100644
--- a/lib/malloc.c
+++ b/lib/malloc.c
@@ -1,6 +1,7 @@
/* malloc() function that is glibc compatible.
- Copyright (C) 1997-1998, 2006-2007, 2009-2023 Free Software Foundation, Inc.
+ Copyright (C) 1997-1998, 2006-2007, 2009-2024 Free Software
+ Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
diff --git a/lib/malloc/dynarray-skeleton.c b/lib/malloc/dynarray-skeleton.c
index 580c278b7c5..a95241abd2d 100644
--- a/lib/malloc/dynarray-skeleton.c
+++ b/lib/malloc/dynarray-skeleton.c
@@ -1,5 +1,5 @@
/* Type-safe arrays which grow dynamically.
- Copyright (C) 2017-2023 Free Software Foundation, Inc.
+ Copyright (C) 2017-2024 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/lib/malloc/dynarray.h b/lib/malloc/dynarray.h
index a9a3b0859c1..3163e2782b4 100644
--- a/lib/malloc/dynarray.h
+++ b/lib/malloc/dynarray.h
@@ -1,5 +1,5 @@
/* Type-safe arrays which grow dynamically. Shared definitions.
- Copyright (C) 2017-2023 Free Software Foundation, Inc.
+ Copyright (C) 2017-2024 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/lib/malloc/dynarray_at_failure.c b/lib/malloc/dynarray_at_failure.c
index ebc9310982c..95e34e7aacd 100644
--- a/lib/malloc/dynarray_at_failure.c
+++ b/lib/malloc/dynarray_at_failure.c
@@ -1,5 +1,5 @@
/* Report an dynamic array index out of bounds condition.
- Copyright (C) 2017-2023 Free Software Foundation, Inc.
+ Copyright (C) 2017-2024 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/lib/malloc/dynarray_emplace_enlarge.c b/lib/malloc/dynarray_emplace_enlarge.c
index 65aabb1e4a5..7bdba1597e0 100644
--- a/lib/malloc/dynarray_emplace_enlarge.c
+++ b/lib/malloc/dynarray_emplace_enlarge.c
@@ -1,5 +1,5 @@
/* Increase the size of a dynamic array in preparation of an emplace operation.
- Copyright (C) 2017-2023 Free Software Foundation, Inc.
+ Copyright (C) 2017-2024 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/lib/malloc/dynarray_finalize.c b/lib/malloc/dynarray_finalize.c
index 673595a5fad..52764f73287 100644
--- a/lib/malloc/dynarray_finalize.c
+++ b/lib/malloc/dynarray_finalize.c
@@ -1,5 +1,5 @@
/* Copy the dynamically-allocated area to an explicitly-sized heap allocation.
- Copyright (C) 2017-2023 Free Software Foundation, Inc.
+ Copyright (C) 2017-2024 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/lib/malloc/dynarray_resize.c b/lib/malloc/dynarray_resize.c
index 014f98c330e..7323f8eeb0c 100644
--- a/lib/malloc/dynarray_resize.c
+++ b/lib/malloc/dynarray_resize.c
@@ -1,5 +1,5 @@
/* Increase the size of a dynamic array.
- Copyright (C) 2017-2023 Free Software Foundation, Inc.
+ Copyright (C) 2017-2024 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/lib/malloc/dynarray_resize_clear.c b/lib/malloc/dynarray_resize_clear.c
index bb23c522a14..aa17f740e57 100644
--- a/lib/malloc/dynarray_resize_clear.c
+++ b/lib/malloc/dynarray_resize_clear.c
@@ -1,5 +1,5 @@
/* Increase the size of a dynamic array and clear the new part.
- Copyright (C) 2017-2023 Free Software Foundation, Inc.
+ Copyright (C) 2017-2024 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/lib/malloc/scratch_buffer.h b/lib/malloc/scratch_buffer.h
index 33fd2b29cd5..b94f872757e 100644
--- a/lib/malloc/scratch_buffer.h
+++ b/lib/malloc/scratch_buffer.h
@@ -1,5 +1,5 @@
/* Variable-sized buffer with on-stack default allocation.
- Copyright (C) 2015-2023 Free Software Foundation, Inc.
+ Copyright (C) 2015-2024 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/lib/malloc/scratch_buffer_dupfree.c b/lib/malloc/scratch_buffer_dupfree.c
index 2f60fbb54e8..8a8506e1e1d 100644
--- a/lib/malloc/scratch_buffer_dupfree.c
+++ b/lib/malloc/scratch_buffer_dupfree.c
@@ -1,5 +1,5 @@
/* Variable-sized buffer with on-stack default allocation.
- Copyright (C) 2020-2023 Free Software Foundation, Inc.
+ Copyright (C) 2020-2024 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/lib/malloc/scratch_buffer_grow.c b/lib/malloc/scratch_buffer_grow.c
index a5e8f2f7230..c08275797d6 100644
--- a/lib/malloc/scratch_buffer_grow.c
+++ b/lib/malloc/scratch_buffer_grow.c
@@ -1,5 +1,5 @@
/* Variable-sized buffer with on-stack default allocation.
- Copyright (C) 2015-2023 Free Software Foundation, Inc.
+ Copyright (C) 2015-2024 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/lib/malloc/scratch_buffer_grow_preserve.c b/lib/malloc/scratch_buffer_grow_preserve.c
index c0b5d87b7e4..6891db86aaf 100644
--- a/lib/malloc/scratch_buffer_grow_preserve.c
+++ b/lib/malloc/scratch_buffer_grow_preserve.c
@@ -1,5 +1,5 @@
/* Variable-sized buffer with on-stack default allocation.
- Copyright (C) 2015-2023 Free Software Foundation, Inc.
+ Copyright (C) 2015-2024 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/lib/malloc/scratch_buffer_set_array_size.c b/lib/malloc/scratch_buffer_set_array_size.c
index 24c39350ade..0582bef7ce1 100644
--- a/lib/malloc/scratch_buffer_set_array_size.c
+++ b/lib/malloc/scratch_buffer_set_array_size.c
@@ -1,5 +1,5 @@
/* Variable-sized buffer with on-stack default allocation.
- Copyright (C) 2015-2023 Free Software Foundation, Inc.
+ Copyright (C) 2015-2024 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/lib/md5-stream.c b/lib/md5-stream.c
index ba76792cbbe..ca82b067e42 100644
--- a/lib/md5-stream.c
+++ b/lib/md5-stream.c
@@ -1,7 +1,7 @@
/* Functions to compute MD5 message digest of files or memory blocks.
according to the definition of MD5 in RFC 1321 from April 1992.
- Copyright (C) 1995-1997, 1999-2001, 2005-2006, 2008-2023 Free Software
- Foundation, Inc.
+ Copyright (C) 1995-1997, 1999-2001, 2005-2006, 2008-2024 Free
+ Software Foundation, Inc.
This file is part of the GNU C Library.
This file is free software: you can redistribute it and/or modify
diff --git a/lib/md5.c b/lib/md5.c
index 4a6accf28ff..1818216a4b9 100644
--- a/lib/md5.c
+++ b/lib/md5.c
@@ -1,7 +1,7 @@
/* Functions to compute MD5 message digest of files or memory blocks.
according to the definition of MD5 in RFC 1321 from April 1992.
- Copyright (C) 1995-1997, 1999-2001, 2005-2006, 2008-2023 Free Software
- Foundation, Inc.
+ Copyright (C) 1995-1997, 1999-2001, 2005-2006, 2008-2024 Free
+ Software Foundation, Inc.
This file is part of the GNU C Library.
This file is free software: you can redistribute it and/or modify
diff --git a/lib/md5.h b/lib/md5.h
index 92dc6038988..99f56ef0eec 100644
--- a/lib/md5.h
+++ b/lib/md5.h
@@ -1,7 +1,7 @@
/* Declaration of functions and data types used for MD5 sum computing
library functions.
- Copyright (C) 1995-1997, 1999-2001, 2004-2006, 2008-2023 Free Software
- Foundation, Inc.
+ Copyright (C) 1995-1997, 1999-2001, 2004-2006, 2008-2024 Free
+ Software Foundation, Inc.
This file is part of the GNU C Library.
This file is free software: you can redistribute it and/or modify
diff --git a/lib/memmem.c b/lib/memmem.c
index c0b48c1b25d..6fbc36e6654 100644
--- a/lib/memmem.c
+++ b/lib/memmem.c
@@ -1,5 +1,5 @@
-/* Copyright (C) 1991-1994, 1996-1998, 2000, 2004, 2007-2023 Free Software
- Foundation, Inc.
+/* Copyright (C) 1991-1994, 1996-1998, 2000, 2004, 2007-2024 Free
+ Software Foundation, Inc.
This file is part of the GNU C Library.
This file is free software: you can redistribute it and/or modify
diff --git a/lib/mempcpy.c b/lib/mempcpy.c
index 24a3135988f..638867782d6 100644
--- a/lib/mempcpy.c
+++ b/lib/mempcpy.c
@@ -1,5 +1,5 @@
/* Copy memory area and return pointer after last written byte.
- Copyright (C) 2003, 2007, 2009-2023 Free Software Foundation, Inc.
+ Copyright (C) 2003, 2007, 2009-2024 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
diff --git a/lib/memrchr.c b/lib/memrchr.c
index c5b1fe8b2e3..025869b6022 100644
--- a/lib/memrchr.c
+++ b/lib/memrchr.c
@@ -1,7 +1,7 @@
/* memrchr -- find the last occurrence of a byte in a memory block
- Copyright (C) 1991, 1993, 1996-1997, 1999-2000, 2003-2023 Free Software
- Foundation, Inc.
+ Copyright (C) 1991, 1993, 1996-1997, 1999-2000, 2003-2024 Free
+ Software Foundation, Inc.
Based on strlen implementation by Torbjorn Granlund (tege@sics.se),
with help from Dan Sahlin (dan@sics.se) and
diff --git a/lib/memset_explicit.c b/lib/memset_explicit.c
index 6d21a5e8797..cf6cc647847 100644
--- a/lib/memset_explicit.c
+++ b/lib/memset_explicit.c
@@ -1,5 +1,5 @@
/* Erase sensitive data from memory.
- Copyright 2022-2023 Free Software Foundation, Inc.
+ Copyright 2022-2024 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
diff --git a/lib/mini-gmp-gnulib.c b/lib/mini-gmp-gnulib.c
index b15ce0ff754..6e02d3cefb6 100644
--- a/lib/mini-gmp-gnulib.c
+++ b/lib/mini-gmp-gnulib.c
@@ -1,6 +1,6 @@
/* Tailor mini-gmp.c for Gnulib-using applications.
- Copyright 2018-2023 Free Software Foundation, Inc.
+ Copyright 2018-2024 Free Software Foundation, Inc.
This file is free software.
It is dual-licensed under "the GNU LGPLv3+ or the GNU GPLv2+".
diff --git a/lib/minmax.h b/lib/minmax.h
index 0ac40198e24..f3df58b0d70 100644
--- a/lib/minmax.h
+++ b/lib/minmax.h
@@ -1,5 +1,5 @@
/* MIN, MAX macros.
- Copyright (C) 1995, 1998, 2001, 2003, 2005, 2009-2023 Free Software
+ Copyright (C) 1995, 1998, 2001, 2003, 2005, 2009-2024 Free Software
Foundation, Inc.
This file is free software: you can redistribute it and/or modify
diff --git a/lib/mkostemp.c b/lib/mkostemp.c
index 5cd5b3ac583..d826627fe58 100644
--- a/lib/mkostemp.c
+++ b/lib/mkostemp.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1998-1999, 2001, 2005-2007, 2009-2023 Free Software
+/* Copyright (C) 1998-1999, 2001, 2005-2007, 2009-2024 Free Software
Foundation, Inc.
This file is derived from the one in the GNU C Library.
diff --git a/lib/mktime-internal.h b/lib/mktime-internal.h
index 709c36bdf56..0693aaf1402 100644
--- a/lib/mktime-internal.h
+++ b/lib/mktime-internal.h
@@ -1,5 +1,5 @@
/* Internals of mktime and related functions
- Copyright 2016-2023 Free Software Foundation, Inc.
+ Copyright 2016-2024 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Paul Eggert <eggert@cs.ucla.edu>.
diff --git a/lib/mktime.c b/lib/mktime.c
index 8e80bcdbd16..c704f415740 100644
--- a/lib/mktime.c
+++ b/lib/mktime.c
@@ -1,5 +1,5 @@
/* Convert a 'struct tm' to a time_t value.
- Copyright (C) 1993-2023 Free Software Foundation, Inc.
+ Copyright (C) 1993-2024 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Paul Eggert <eggert@twinsun.com>.
diff --git a/lib/nanosleep.c b/lib/nanosleep.c
index 10974df461e..c998515ebaa 100644
--- a/lib/nanosleep.c
+++ b/lib/nanosleep.c
@@ -1,6 +1,7 @@
/* Provide a replacement for the POSIX nanosleep function.
- Copyright (C) 1999-2000, 2002, 2004-2023 Free Software Foundation, Inc.
+ Copyright (C) 1999-2000, 2002, 2004-2024 Free Software Foundation,
+ Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
diff --git a/lib/nproc.c b/lib/nproc.c
index e3de1873a96..92a07e82890 100644
--- a/lib/nproc.c
+++ b/lib/nproc.c
@@ -1,6 +1,6 @@
/* Detect the number of processors.
- Copyright (C) 2009-2023 Free Software Foundation, Inc.
+ Copyright (C) 2009-2024 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
diff --git a/lib/nproc.h b/lib/nproc.h
index 7b8b16d37cd..7054df5f7a3 100644
--- a/lib/nproc.h
+++ b/lib/nproc.h
@@ -1,6 +1,6 @@
/* Detect the number of processors.
- Copyright (C) 2009-2023 Free Software Foundation, Inc.
+ Copyright (C) 2009-2024 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
diff --git a/lib/nstrftime.c b/lib/nstrftime.c
index c4bef575fcd..69e4164dc0c 100644
--- a/lib/nstrftime.c
+++ b/lib/nstrftime.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991-2023 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2024 Free Software Foundation, Inc.
This file is part of the GNU C Library.
This file is free software: you can redistribute it and/or modify
diff --git a/lib/open.c b/lib/open.c
index 7ec8fdc35dc..adcac458a78 100644
--- a/lib/open.c
+++ b/lib/open.c
@@ -1,5 +1,5 @@
/* Open a descriptor to a file.
- Copyright (C) 2007-2023 Free Software Foundation, Inc.
+ Copyright (C) 2007-2024 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
diff --git a/lib/openat-priv.h b/lib/openat-priv.h
index 1d31c4e83cb..7fd4beb5a73 100644
--- a/lib/openat-priv.h
+++ b/lib/openat-priv.h
@@ -1,6 +1,6 @@
/* Internals for openat-like functions.
- Copyright (C) 2005-2006, 2009-2023 Free Software Foundation, Inc.
+ Copyright (C) 2005-2006, 2009-2024 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/lib/openat-proc.c b/lib/openat-proc.c
index 88f70be4f59..7ccb734f424 100644
--- a/lib/openat-proc.c
+++ b/lib/openat-proc.c
@@ -1,6 +1,6 @@
/* Create /proc/self/fd-related names for subfiles of open directories.
- Copyright (C) 2006, 2009-2023 Free Software Foundation, Inc.
+ Copyright (C) 2006, 2009-2024 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/lib/openat.h b/lib/openat.h
index 97f066d10f8..dc34092bb3f 100644
--- a/lib/openat.h
+++ b/lib/openat.h
@@ -1,5 +1,5 @@
/* provide a replacement openat function
- Copyright (C) 2004-2006, 2008-2023 Free Software Foundation, Inc.
+ Copyright (C) 2004-2006, 2008-2024 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/lib/pathmax.h b/lib/pathmax.h
index 6930283b82a..d6512c6f570 100644
--- a/lib/pathmax.h
+++ b/lib/pathmax.h
@@ -1,5 +1,5 @@
/* Define PATH_MAX somehow. Requires sys/types.h.
- Copyright (C) 1992, 1999, 2001, 2003, 2005, 2009-2023 Free Software
+ Copyright (C) 1992, 1999, 2001, 2003, 2005, 2009-2024 Free Software
Foundation, Inc.
This file is free software: you can redistribute it and/or modify
diff --git a/lib/pipe2.c b/lib/pipe2.c
index 8f06575a1dd..7b476df3457 100644
--- a/lib/pipe2.c
+++ b/lib/pipe2.c
@@ -1,5 +1,5 @@
/* Create a pipe, with specific opening flags.
- Copyright (C) 2009-2023 Free Software Foundation, Inc.
+ Copyright (C) 2009-2024 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
diff --git a/lib/pselect.c b/lib/pselect.c
index 1b8c19130c2..54732e5cce3 100644
--- a/lib/pselect.c
+++ b/lib/pselect.c
@@ -1,6 +1,6 @@
/* pselect - synchronous I/O multiplexing
- Copyright 2011-2023 Free Software Foundation, Inc.
+ Copyright 2011-2024 Free Software Foundation, Inc.
This file is part of gnulib.
diff --git a/lib/pthread_sigmask.c b/lib/pthread_sigmask.c
index 128107582a7..3b6e6e454ed 100644
--- a/lib/pthread_sigmask.c
+++ b/lib/pthread_sigmask.c
@@ -1,5 +1,5 @@
/* POSIX compatible signal blocking for threads.
- Copyright (C) 2011-2023 Free Software Foundation, Inc.
+ Copyright (C) 2011-2024 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
diff --git a/lib/qcopy-acl.c b/lib/qcopy-acl.c
index 0f4159b7fd9..dfc39cead05 100644
--- a/lib/qcopy-acl.c
+++ b/lib/qcopy-acl.c
@@ -1,6 +1,6 @@
/* Copy access control list from one file to another. -*- coding: utf-8 -*-
- Copyright (C) 2002-2003, 2005-2023 Free Software Foundation, Inc.
+ Copyright (C) 2002-2003, 2005-2024 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/lib/rawmemchr.c b/lib/rawmemchr.c
index 45c6cd35276..37639287f01 100644
--- a/lib/rawmemchr.c
+++ b/lib/rawmemchr.c
@@ -1,5 +1,5 @@
/* Searching in a string.
- Copyright (C) 2008-2023 Free Software Foundation, Inc.
+ Copyright (C) 2008-2024 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
diff --git a/lib/rawmemchr.valgrind b/lib/rawmemchr.valgrind
index f3e4cb0f655..bb201f73093 100644
--- a/lib/rawmemchr.valgrind
+++ b/lib/rawmemchr.valgrind
@@ -1,6 +1,6 @@
# Suppress a valgrind message about use of uninitialized memory in rawmemchr().
-# Copyright (C) 2008-2023 Free Software Foundation, Inc.
+# Copyright (C) 2008-2024 Free Software Foundation, Inc.
#
# This file is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as
diff --git a/lib/readlink.c b/lib/readlink.c
index 14bbb7f10ca..a5369fa977b 100644
--- a/lib/readlink.c
+++ b/lib/readlink.c
@@ -1,5 +1,5 @@
/* Read the contents of a symbolic link.
- Copyright (C) 2003-2007, 2009-2023 Free Software Foundation, Inc.
+ Copyright (C) 2003-2007, 2009-2024 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
diff --git a/lib/readlinkat.c b/lib/readlinkat.c
index 7738ba8bfd5..faf85401ae6 100644
--- a/lib/readlinkat.c
+++ b/lib/readlinkat.c
@@ -1,5 +1,5 @@
/* Read a symlink relative to an open directory.
- Copyright (C) 2009-2023 Free Software Foundation, Inc.
+ Copyright (C) 2009-2024 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/lib/readutmp.h b/lib/readutmp.h
index fa30fa9a004..b62eb3beaa1 100644
--- a/lib/readutmp.h
+++ b/lib/readutmp.h
@@ -1,6 +1,6 @@
/* Declarations for GNU's read utmp module.
- Copyright (C) 1992-2007, 2009-2023 Free Software Foundation, Inc.
+ Copyright (C) 1992-2007, 2009-2024 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/lib/realloc.c b/lib/realloc.c
index 1063eb09874..0573139625e 100644
--- a/lib/realloc.c
+++ b/lib/realloc.c
@@ -1,6 +1,6 @@
/* realloc() function that is glibc compatible.
- Copyright (C) 1997, 2003-2004, 2006-2007, 2009-2023 Free Software
+ Copyright (C) 1997, 2003-2004, 2006-2007, 2009-2024 Free Software
Foundation, Inc.
This file is free software: you can redistribute it and/or modify
diff --git a/lib/regcomp.c b/lib/regcomp.c
index 1f6a131107b..696cf813f3c 100644
--- a/lib/regcomp.c
+++ b/lib/regcomp.c
@@ -1,5 +1,5 @@
/* Extended regular expression matching and search library.
- Copyright (C) 2002-2023 Free Software Foundation, Inc.
+ Copyright (C) 2002-2024 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Isamu Hasegawa <isamu@yamato.ibm.com>.
diff --git a/lib/regex.c b/lib/regex.c
index 3beb0deb987..08031cecc04 100644
--- a/lib/regex.c
+++ b/lib/regex.c
@@ -1,5 +1,5 @@
/* Extended regular expression matching and search library.
- Copyright (C) 2002-2023 Free Software Foundation, Inc.
+ Copyright (C) 2002-2024 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Isamu Hasegawa <isamu@yamato.ibm.com>.
diff --git a/lib/regex.h b/lib/regex.h
index 9ef0252ffff..ccf40cebc0e 100644
--- a/lib/regex.h
+++ b/lib/regex.h
@@ -1,6 +1,6 @@
/* Definitions for data structures and routines for the regular
expression library.
- Copyright (C) 1985, 1989-2023 Free Software Foundation, Inc.
+ Copyright (C) 1985, 1989-2024 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/lib/regex_internal.c b/lib/regex_internal.c
index 998a19b7241..8cd096ebcfb 100644
--- a/lib/regex_internal.c
+++ b/lib/regex_internal.c
@@ -1,5 +1,5 @@
/* Extended regular expression matching and search library.
- Copyright (C) 2002-2023 Free Software Foundation, Inc.
+ Copyright (C) 2002-2024 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Isamu Hasegawa <isamu@yamato.ibm.com>.
diff --git a/lib/regex_internal.h b/lib/regex_internal.h
index 7e35a112ec2..6165cb17c70 100644
--- a/lib/regex_internal.h
+++ b/lib/regex_internal.h
@@ -1,5 +1,5 @@
/* Extended regular expression matching and search library.
- Copyright (C) 2002-2023 Free Software Foundation, Inc.
+ Copyright (C) 2002-2024 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Isamu Hasegawa <isamu@yamato.ibm.com>.
diff --git a/lib/regexec.c b/lib/regexec.c
index f05f38ae0e0..9f065dfa020 100644
--- a/lib/regexec.c
+++ b/lib/regexec.c
@@ -1,5 +1,5 @@
/* Extended regular expression matching and search library.
- Copyright (C) 2002-2023 Free Software Foundation, Inc.
+ Copyright (C) 2002-2024 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Isamu Hasegawa <isamu@yamato.ibm.com>.
diff --git a/lib/root-uid.h b/lib/root-uid.h
index 1905575e47b..ba50bfd4e6a 100644
--- a/lib/root-uid.h
+++ b/lib/root-uid.h
@@ -1,6 +1,6 @@
/* The user ID that always has appropriate privileges in the POSIX sense.
- Copyright 2012-2023 Free Software Foundation, Inc.
+ Copyright 2012-2024 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
diff --git a/lib/save-cwd.c b/lib/save-cwd.c
index 7c517d1c819..77835b55db6 100644
--- a/lib/save-cwd.c
+++ b/lib/save-cwd.c
@@ -1,6 +1,6 @@
/* save-cwd.c -- Save and restore current working directory.
- Copyright (C) 1995, 1997-1998, 2003-2006, 2009-2023 Free Software
+ Copyright (C) 1995, 1997-1998, 2003-2006, 2009-2024 Free Software
Foundation, Inc.
This program is free software: you can redistribute it and/or modify
diff --git a/lib/save-cwd.h b/lib/save-cwd.h
index d089b0e2145..79900ee0b08 100644
--- a/lib/save-cwd.h
+++ b/lib/save-cwd.h
@@ -1,7 +1,7 @@
/* Save and restore current working directory.
- Copyright (C) 1995, 1997-1998, 2003, 2009-2023 Free Software Foundation,
- Inc.
+ Copyright (C) 1995, 1997-1998, 2003, 2009-2024 Free Software
+ Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/lib/scratch_buffer.h b/lib/scratch_buffer.h
index 4cf60d232b7..4f28203a469 100644
--- a/lib/scratch_buffer.h
+++ b/lib/scratch_buffer.h
@@ -1,5 +1,5 @@
/* Variable-sized buffer with on-stack default allocation.
- Copyright (C) 2017-2023 Free Software Foundation, Inc.
+ Copyright (C) 2017-2024 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
diff --git a/lib/set-permissions.c b/lib/set-permissions.c
index 1d6732cc78f..a3d4cc839e5 100644
--- a/lib/set-permissions.c
+++ b/lib/set-permissions.c
@@ -1,6 +1,6 @@
/* Set permissions of a file. -*- coding: utf-8 -*-
- Copyright (C) 2002-2003, 2005-2023 Free Software Foundation, Inc.
+ Copyright (C) 2002-2003, 2005-2024 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/lib/sha1.c b/lib/sha1.c
index 80f0b7a3314..454d68e266d 100644
--- a/lib/sha1.c
+++ b/lib/sha1.c
@@ -1,7 +1,8 @@
/* sha1.c - Functions to compute SHA1 message digest of files or
memory blocks according to the NIST specification FIPS-180-1.
- Copyright (C) 2000-2001, 2003-2006, 2008-2023 Free Software Foundation, Inc.
+ Copyright (C) 2000-2001, 2003-2006, 2008-2024 Free Software
+ Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
diff --git a/lib/sha1.h b/lib/sha1.h
index 854213a9211..15bfa043e3b 100644
--- a/lib/sha1.h
+++ b/lib/sha1.h
@@ -1,6 +1,6 @@
/* Declarations of functions and data types used for SHA1 sum
library functions.
- Copyright (C) 2000-2001, 2003, 2005-2006, 2008-2023 Free Software
+ Copyright (C) 2000-2001, 2003, 2005-2006, 2008-2024 Free Software
Foundation, Inc.
This file is free software: you can redistribute it and/or modify
diff --git a/lib/sha256.c b/lib/sha256.c
index e5fea02bc2e..fe7c5446daf 100644
--- a/lib/sha256.c
+++ b/lib/sha256.c
@@ -1,7 +1,7 @@
/* sha256.c - Functions to compute SHA256 and SHA224 message digest of files or
memory blocks according to the NIST specification FIPS-180-2.
- Copyright (C) 2005-2006, 2008-2023 Free Software Foundation, Inc.
+ Copyright (C) 2005-2006, 2008-2024 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
diff --git a/lib/sha256.h b/lib/sha256.h
index 938b1067062..daf5edd2dd9 100644
--- a/lib/sha256.h
+++ b/lib/sha256.h
@@ -1,6 +1,6 @@
/* Declarations of functions and data types used for SHA256 and SHA224 sum
library functions.
- Copyright (C) 2005-2006, 2008-2023 Free Software Foundation, Inc.
+ Copyright (C) 2005-2006, 2008-2024 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
diff --git a/lib/sha512.c b/lib/sha512.c
index 8ca7fa319f5..9eb036fb327 100644
--- a/lib/sha512.c
+++ b/lib/sha512.c
@@ -1,7 +1,7 @@
/* sha512.c - Functions to compute SHA512 and SHA384 message digest of files or
memory blocks according to the NIST specification FIPS-180-2.
- Copyright (C) 2005-2006, 2008-2023 Free Software Foundation, Inc.
+ Copyright (C) 2005-2006, 2008-2024 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
diff --git a/lib/sha512.h b/lib/sha512.h
index f3465bc8a68..35fa3b52849 100644
--- a/lib/sha512.h
+++ b/lib/sha512.h
@@ -1,6 +1,6 @@
/* Declarations of functions and data types used for SHA512 and SHA384 sum
library functions.
- Copyright (C) 2005-2006, 2008-2023 Free Software Foundation, Inc.
+ Copyright (C) 2005-2006, 2008-2024 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
diff --git a/lib/sig2str.c b/lib/sig2str.c
index c5219caaaed..ac20be041a4 100644
--- a/lib/sig2str.c
+++ b/lib/sig2str.c
@@ -1,6 +1,7 @@
/* sig2str.c -- convert between signal names and numbers
- Copyright (C) 2002, 2004, 2006, 2009-2023 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2004, 2006, 2009-2024 Free Software Foundation,
+ Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/lib/sig2str.h b/lib/sig2str.h
index 1e5253658e7..391da4b1d1c 100644
--- a/lib/sig2str.h
+++ b/lib/sig2str.h
@@ -1,6 +1,6 @@
/* sig2str.h -- convert between signal names and numbers
- Copyright (C) 2002, 2005, 2009-2023 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2005, 2009-2024 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/lib/sigdescr_np.c b/lib/sigdescr_np.c
index fc8a4ad47a2..fb5401522f4 100644
--- a/lib/sigdescr_np.c
+++ b/lib/sigdescr_np.c
@@ -1,5 +1,5 @@
/* English descriptions of signals.
- Copyright (C) 2020-2023 Free Software Foundation, Inc.
+ Copyright (C) 2020-2024 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
diff --git a/lib/signal.in.h b/lib/signal.in.h
index 418d59c582d..107226e3dcf 100644
--- a/lib/signal.in.h
+++ b/lib/signal.in.h
@@ -1,6 +1,6 @@
/* A GNU-like <signal.h>.
- Copyright (C) 2006-2023 Free Software Foundation, Inc.
+ Copyright (C) 2006-2024 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
diff --git a/lib/stat-time.c b/lib/stat-time.c
index bc282232ab3..1ab01f532cd 100644
--- a/lib/stat-time.c
+++ b/lib/stat-time.c
@@ -1,6 +1,6 @@
/* stat-related time functions.
- Copyright (C) 2012-2023 Free Software Foundation, Inc.
+ Copyright (C) 2012-2024 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
diff --git a/lib/stat-time.h b/lib/stat-time.h
index 75eb27e549d..c43d578e144 100644
--- a/lib/stat-time.h
+++ b/lib/stat-time.h
@@ -1,6 +1,6 @@
/* stat-related time functions.
- Copyright (C) 2005, 2007, 2009-2023 Free Software Foundation, Inc.
+ Copyright (C) 2005, 2007, 2009-2024 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
diff --git a/lib/stdalign.in.h b/lib/stdalign.in.h
index b616c100fdc..ff9e5ec6d67 100644
--- a/lib/stdalign.in.h
+++ b/lib/stdalign.in.h
@@ -1,6 +1,6 @@
/* A substitute for ISO C11 <stdalign.h>.
- Copyright 2011-2023 Free Software Foundation, Inc.
+ Copyright 2011-2024 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
diff --git a/lib/stdckdint.in.h b/lib/stdckdint.in.h
index 71bab5f0c9e..91848806d8d 100644
--- a/lib/stdckdint.in.h
+++ b/lib/stdckdint.in.h
@@ -1,6 +1,6 @@
/* stdckdint.h -- checked integer arithmetic
- Copyright 2022-2023 Free Software Foundation, Inc.
+ Copyright 2022-2024 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published
diff --git a/lib/stddef.in.h b/lib/stddef.in.h
index 431e819b8bf..0f1d73ea49d 100644
--- a/lib/stddef.in.h
+++ b/lib/stddef.in.h
@@ -1,6 +1,6 @@
/* A substitute for POSIX 2008 <stddef.h>, for platforms that have issues.
- Copyright (C) 2009-2023 Free Software Foundation, Inc.
+ Copyright (C) 2009-2024 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
diff --git a/lib/stdint.in.h b/lib/stdint.in.h
index 5ddc644b8ee..446f29ecb57 100644
--- a/lib/stdint.in.h
+++ b/lib/stdint.in.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2002, 2004-2023 Free Software Foundation, Inc.
+/* Copyright (C) 2001-2002, 2004-2024 Free Software Foundation, Inc.
Written by Paul Eggert, Bruno Haible, Sam Steingold, Peter Burwood.
This file is part of gnulib.
diff --git a/lib/stdio-impl.h b/lib/stdio-impl.h
index 46608bed198..63ebf7c64b7 100644
--- a/lib/stdio-impl.h
+++ b/lib/stdio-impl.h
@@ -1,5 +1,5 @@
/* Implementation details of FILE streams.
- Copyright (C) 2007-2008, 2010-2023 Free Software Foundation, Inc.
+ Copyright (C) 2007-2008, 2010-2024 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
diff --git a/lib/stdio.in.h b/lib/stdio.in.h
index 6be12c0525d..7fcb4c7b008 100644
--- a/lib/stdio.in.h
+++ b/lib/stdio.in.h
@@ -1,6 +1,6 @@
/* A GNU-like <stdio.h>.
- Copyright (C) 2004, 2007-2023 Free Software Foundation, Inc.
+ Copyright (C) 2004, 2007-2024 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
diff --git a/lib/stdlib.in.h b/lib/stdlib.in.h
index 1479a2b2871..ffa86eef0dc 100644
--- a/lib/stdlib.in.h
+++ b/lib/stdlib.in.h
@@ -1,6 +1,7 @@
/* A GNU-like <stdlib.h>.
- Copyright (C) 1995, 2001-2004, 2006-2023 Free Software Foundation, Inc.
+ Copyright (C) 1995, 2001-2004, 2006-2024 Free Software Foundation,
+ Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
diff --git a/lib/stpcpy.c b/lib/stpcpy.c
index 73c1eb786ff..d4510054bf5 100644
--- a/lib/stpcpy.c
+++ b/lib/stpcpy.c
@@ -1,5 +1,5 @@
/* stpcpy.c -- copy a string and return pointer to end of new string
- Copyright (C) 1992, 1995, 1997-1998, 2006, 2009-2023 Free Software
+ Copyright (C) 1992, 1995, 1997-1998, 2006, 2009-2024 Free Software
Foundation, Inc.
NOTE: The canonical source of this file is maintained with the GNU C Library.
diff --git a/lib/str-two-way.h b/lib/str-two-way.h
index dfe702241c0..cf85e26817c 100644
--- a/lib/str-two-way.h
+++ b/lib/str-two-way.h
@@ -1,5 +1,5 @@
/* Byte-wise substring search, using the Two-Way algorithm.
- Copyright (C) 2008-2023 Free Software Foundation, Inc.
+ Copyright (C) 2008-2024 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Written by Eric Blake <ebb9@byu.net>, 2008.
diff --git a/lib/strftime.h b/lib/strftime.h
index 88c1f73928f..d6efdb848a3 100644
--- a/lib/strftime.h
+++ b/lib/strftime.h
@@ -1,6 +1,6 @@
/* declarations for strftime.c
- Copyright (C) 2002, 2004, 2008-2023 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2004, 2008-2024 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
diff --git a/lib/string.in.h b/lib/string.in.h
index 912d0f7a306..70239c33bea 100644
--- a/lib/string.in.h
+++ b/lib/string.in.h
@@ -1,6 +1,6 @@
/* A GNU-like <string.h>.
- Copyright (C) 1995-1996, 2001-2023 Free Software Foundation, Inc.
+ Copyright (C) 1995-1996, 2001-2024 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
diff --git a/lib/strnlen.c b/lib/strnlen.c
index 09c010eac42..80857ec22b0 100644
--- a/lib/strnlen.c
+++ b/lib/strnlen.c
@@ -1,5 +1,5 @@
/* Find the length of STRING, but scan at most MAXLEN characters.
- Copyright (C) 2005-2007, 2009-2023 Free Software Foundation, Inc.
+ 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
diff --git a/lib/strtoimax.c b/lib/strtoimax.c
index f7977e28e64..be6cd1fb7dd 100644
--- a/lib/strtoimax.c
+++ b/lib/strtoimax.c
@@ -1,7 +1,7 @@
/* Convert string representation of a number into an intmax_t value.
- Copyright (C) 1999, 2001-2004, 2006, 2009-2023 Free Software Foundation,
- Inc.
+ Copyright (C) 1999, 2001-2004, 2006, 2009-2024 Free Software
+ Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
diff --git a/lib/strtol.c b/lib/strtol.c
index b93483dca49..b0e7c358800 100644
--- a/lib/strtol.c
+++ b/lib/strtol.c
@@ -1,7 +1,7 @@
/* Convert string representation of a number into an integer value.
- Copyright (C) 1991-1992, 1994-1999, 2003, 2005-2007, 2009-2023 Free Software
- Foundation, Inc.
+ Copyright (C) 1991-1992, 1994-1999, 2003, 2005-2007, 2009-2024 Free
+ Software Foundation, Inc.
NOTE: The canonical source of this file is maintained with the GNU C
Library. Bugs can be reported to bug-glibc@gnu.org.
diff --git a/lib/strtoll.c b/lib/strtoll.c
index 9fdfa19b220..840a03b11e8 100644
--- a/lib/strtoll.c
+++ b/lib/strtoll.c
@@ -1,6 +1,6 @@
/* Function to parse a 'long long int' from text.
- Copyright (C) 1995-1997, 1999, 2001, 2009-2023 Free Software Foundation,
- Inc.
+ Copyright (C) 1995-1997, 1999, 2001, 2009-2024 Free Software
+ Foundation, Inc.
This file is part of the GNU C Library.
This file is free software: you can redistribute it and/or modify
diff --git a/lib/symlink.c b/lib/symlink.c
index b5009ae8355..6ba83666e17 100644
--- a/lib/symlink.c
+++ b/lib/symlink.c
@@ -1,5 +1,5 @@
/* Stub for symlink().
- Copyright (C) 2009-2023 Free Software Foundation, Inc.
+ Copyright (C) 2009-2024 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
diff --git a/lib/sys_random.in.h b/lib/sys_random.in.h
index b240033bcbf..22f67b17635 100644
--- a/lib/sys_random.in.h
+++ b/lib/sys_random.in.h
@@ -1,5 +1,5 @@
/* Substitute for <sys/random.h>.
- Copyright (C) 2020-2023 Free Software Foundation, Inc.
+ Copyright (C) 2020-2024 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
diff --git a/lib/sys_select.in.h b/lib/sys_select.in.h
index 3abfc48af09..de29c77949a 100644
--- a/lib/sys_select.in.h
+++ b/lib/sys_select.in.h
@@ -1,5 +1,5 @@
/* Substitute for <sys/select.h>.
- Copyright (C) 2007-2023 Free Software Foundation, Inc.
+ Copyright (C) 2007-2024 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
diff --git a/lib/sys_stat.in.h b/lib/sys_stat.in.h
index ad4da17fa46..7593fee54a8 100644
--- a/lib/sys_stat.in.h
+++ b/lib/sys_stat.in.h
@@ -1,5 +1,5 @@
/* Provide a more complete sys/stat.h header file.
- Copyright (C) 2005-2023 Free Software Foundation, Inc.
+ Copyright (C) 2005-2024 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
diff --git a/lib/sys_time.in.h b/lib/sys_time.in.h
index 59cce1440da..4a301c48ba1 100644
--- a/lib/sys_time.in.h
+++ b/lib/sys_time.in.h
@@ -1,6 +1,6 @@
/* Provide a more complete sys/time.h.
- Copyright (C) 2007-2023 Free Software Foundation, Inc.
+ Copyright (C) 2007-2024 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
diff --git a/lib/sys_types.in.h b/lib/sys_types.in.h
index ea77e140be9..0a0ccc3c379 100644
--- a/lib/sys_types.in.h
+++ b/lib/sys_types.in.h
@@ -1,6 +1,6 @@
/* Provide a more complete sys/types.h.
- Copyright (C) 2011-2023 Free Software Foundation, Inc.
+ Copyright (C) 2011-2024 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
diff --git a/lib/tempname.c b/lib/tempname.c
index bf362db6e17..fec5f7b29d6 100644
--- a/lib/tempname.c
+++ b/lib/tempname.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991-2023 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2024 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/lib/tempname.h b/lib/tempname.h
index 36a51381548..7cbdac95dea 100644
--- a/lib/tempname.h
+++ b/lib/tempname.h
@@ -1,6 +1,6 @@
/* Create a temporary file or directory.
- Copyright (C) 2006, 2009-2023 Free Software Foundation, Inc.
+ Copyright (C) 2006, 2009-2024 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
diff --git a/lib/time-internal.h b/lib/time-internal.h
index 51423c94ca9..816684a1172 100644
--- a/lib/time-internal.h
+++ b/lib/time-internal.h
@@ -1,6 +1,6 @@
/* Time internal interface
- Copyright 2015-2023 Free Software Foundation, Inc.
+ Copyright 2015-2024 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
diff --git a/lib/time.in.h b/lib/time.in.h
index 06824da9d3d..58e103af07c 100644
--- a/lib/time.in.h
+++ b/lib/time.in.h
@@ -1,6 +1,6 @@
/* A more-standard <time.h>.
- Copyright (C) 2007-2023 Free Software Foundation, Inc.
+ Copyright (C) 2007-2024 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
diff --git a/lib/time_r.c b/lib/time_r.c
index 97be4fd0544..4201e73f743 100644
--- a/lib/time_r.c
+++ b/lib/time_r.c
@@ -1,6 +1,7 @@
/* Reentrant time functions like localtime_r.
- Copyright (C) 2003, 2006-2007, 2010-2023 Free Software Foundation, Inc.
+ Copyright (C) 2003, 2006-2007, 2010-2024 Free Software Foundation,
+ Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
diff --git a/lib/time_rz.c b/lib/time_rz.c
index da0d57b8b1a..468d7539ce1 100644
--- a/lib/time_rz.c
+++ b/lib/time_rz.c
@@ -1,6 +1,6 @@
/* Time zone functions such as tzalloc and localtime_rz
- Copyright 2015-2023 Free Software Foundation, Inc.
+ Copyright 2015-2024 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
diff --git a/lib/timegm.c b/lib/timegm.c
index b47025a0545..e5cf30c0198 100644
--- a/lib/timegm.c
+++ b/lib/timegm.c
@@ -1,6 +1,6 @@
/* Convert UTC calendar time to simple time. Like mktime but assumes UTC.
- Copyright (C) 1994-2023 Free Software Foundation, Inc.
+ Copyright (C) 1994-2024 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/lib/timespec-add.c b/lib/timespec-add.c
index 38c4dfc24c2..e10c19842cd 100644
--- a/lib/timespec-add.c
+++ b/lib/timespec-add.c
@@ -1,6 +1,6 @@
/* Add two struct timespec values.
- Copyright (C) 2011-2023 Free Software Foundation, Inc.
+ Copyright (C) 2011-2024 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/lib/timespec-sub.c b/lib/timespec-sub.c
index f8052400410..315cc638369 100644
--- a/lib/timespec-sub.c
+++ b/lib/timespec-sub.c
@@ -1,6 +1,6 @@
/* Subtract two struct timespec values.
- Copyright (C) 2011-2023 Free Software Foundation, Inc.
+ Copyright (C) 2011-2024 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/lib/timespec.c b/lib/timespec.c
index 5f7ffbdd45f..8cee9870c71 100644
--- a/lib/timespec.c
+++ b/lib/timespec.c
@@ -1,6 +1,6 @@
/* Inline functions for <timespec.h>.
- Copyright (C) 2012-2023 Free Software Foundation, Inc.
+ Copyright (C) 2012-2024 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
diff --git a/lib/timespec.h b/lib/timespec.h
index e94da75defe..69ce348569d 100644
--- a/lib/timespec.h
+++ b/lib/timespec.h
@@ -1,6 +1,6 @@
/* timespec -- System time interface
- Copyright (C) 2000, 2002, 2004-2005, 2007, 2009-2023 Free Software
+ Copyright (C) 2000, 2002, 2004-2005, 2007, 2009-2024 Free Software
Foundation, Inc.
This file is free software: you can redistribute it and/or modify
diff --git a/lib/u64.c b/lib/u64.c
index ca088b45463..f788470b8f4 100644
--- a/lib/u64.c
+++ b/lib/u64.c
@@ -1,6 +1,6 @@
/* uint64_t-like operations that work even on hosts lacking uint64_t
- Copyright (C) 2012-2023 Free Software Foundation, Inc.
+ Copyright (C) 2012-2024 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
diff --git a/lib/u64.h b/lib/u64.h
index 8a99335b6aa..63339cca0fc 100644
--- a/lib/u64.h
+++ b/lib/u64.h
@@ -1,6 +1,6 @@
/* uint64_t-like operations that work even on hosts lacking uint64_t
- Copyright (C) 2006, 2009-2023 Free Software Foundation, Inc.
+ Copyright (C) 2006, 2009-2024 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
diff --git a/lib/unistd.c b/lib/unistd.c
index be7a8255033..50b75ff44b7 100644
--- a/lib/unistd.c
+++ b/lib/unistd.c
@@ -1,6 +1,6 @@
/* Inline functions for <unistd.h>.
- Copyright (C) 2012-2023 Free Software Foundation, Inc.
+ Copyright (C) 2012-2024 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
diff --git a/lib/unistd.in.h b/lib/unistd.in.h
index 2ae040a76b3..661cec2770f 100644
--- a/lib/unistd.in.h
+++ b/lib/unistd.in.h
@@ -1,5 +1,5 @@
/* Substitute for and wrapper around <unistd.h>.
- Copyright (C) 2003-2023 Free Software Foundation, Inc.
+ Copyright (C) 2003-2024 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
diff --git a/lib/unlocked-io.h b/lib/unlocked-io.h
index 4830df4a747..b27c3fdcd6f 100644
--- a/lib/unlocked-io.h
+++ b/lib/unlocked-io.h
@@ -1,6 +1,6 @@
/* Prefer faster, non-thread-safe stdio functions if available.
- Copyright (C) 2001-2004, 2009-2023 Free Software Foundation, Inc.
+ Copyright (C) 2001-2004, 2009-2024 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/lib/utimens.c b/lib/utimens.c
index faa197e6cb5..dca9a01252a 100644
--- a/lib/utimens.c
+++ b/lib/utimens.c
@@ -1,6 +1,6 @@
/* Set file access and modification times.
- Copyright (C) 2003-2023 Free Software Foundation, Inc.
+ Copyright (C) 2003-2024 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
diff --git a/lib/utimens.h b/lib/utimens.h
index 4a21792a7e4..7c740afd36d 100644
--- a/lib/utimens.h
+++ b/lib/utimens.h
@@ -1,6 +1,6 @@
/* Set file access and modification times.
- Copyright 2012-2023 Free Software Foundation, Inc.
+ Copyright 2012-2024 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
diff --git a/lib/utimensat.c b/lib/utimensat.c
index 5cff11cd0a9..1321264269e 100644
--- a/lib/utimensat.c
+++ b/lib/utimensat.c
@@ -1,5 +1,5 @@
/* Set the access and modification time of a file relative to directory fd.
- Copyright (C) 2009-2023 Free Software Foundation, Inc.
+ Copyright (C) 2009-2024 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/lib/verify.h b/lib/verify.h
index e4af91517e6..a80f22c694a 100644
--- a/lib/verify.h
+++ b/lib/verify.h
@@ -1,6 +1,6 @@
/* Compile-time assert-like macros.
- Copyright (C) 2005-2006, 2009-2023 Free Software Foundation, Inc.
+ Copyright (C) 2005-2006, 2009-2024 Free Software Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
diff --git a/lib/vla.h b/lib/vla.h
index 55f112a060a..a999d127822 100644
--- a/lib/vla.h
+++ b/lib/vla.h
@@ -1,6 +1,6 @@
/* vla.h - variable length arrays
- Copyright 2014-2023 Free Software Foundation, Inc.
+ Copyright 2014-2024 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/lib/warn-on-use.h b/lib/warn-on-use.h
index 30756034aff..8f4d40dcbeb 100644
--- a/lib/warn-on-use.h
+++ b/lib/warn-on-use.h
@@ -1,5 +1,5 @@
/* A C macro for emitting warnings if a function is used.
- Copyright (C) 2010-2023 Free Software Foundation, Inc.
+ Copyright (C) 2010-2024 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published
diff --git a/lib/xalloc-oversized.h b/lib/xalloc-oversized.h
index 5dbdfb5506a..2be82cd275d 100644
--- a/lib/xalloc-oversized.h
+++ b/lib/xalloc-oversized.h
@@ -1,6 +1,7 @@
/* xalloc-oversized.h -- memory allocation size checking
- Copyright (C) 1990-2000, 2003-2004, 2006-2023 Free Software Foundation, Inc.
+ Copyright (C) 1990-2000, 2003-2004, 2006-2024 Free Software
+ Foundation, Inc.
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
diff --git a/lisp/ChangeLog.1 b/lisp/ChangeLog.1
index 9dfff744e28..49296aaf3a7 100644
--- a/lisp/ChangeLog.1
+++ b/lisp/ChangeLog.1
@@ -3244,7 +3244,7 @@
Set current buffer variables from defaults
in case user's init file has changed them.
- Copyright (C) 1985-1986, 2001-2023 Free Software Foundation, Inc.
+ Copyright (C) 1985-1986, 2001-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/lisp/ChangeLog.10 b/lisp/ChangeLog.10
index fb88141e136..9bc34ea94e7 100644
--- a/lisp/ChangeLog.10
+++ b/lisp/ChangeLog.10
@@ -23541,7 +23541,7 @@ See ChangeLog.9 for earlier changes.
;; coding: utf-8
;; End:
- Copyright (C) 2001-2023 Free Software Foundation, Inc.
+ Copyright (C) 2001-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/lisp/ChangeLog.11 b/lisp/ChangeLog.11
index cbdf3ec57e0..65a55cd7dfb 100644
--- a/lisp/ChangeLog.11
+++ b/lisp/ChangeLog.11
@@ -14322,7 +14322,7 @@ See ChangeLog.10 for earlier changes.
;; coding: utf-8
;; End:
- Copyright (C) 2003-2011, 2013-2023 Free Software Foundation, Inc.
+ Copyright (C) 2003-2011, 2013-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/lisp/ChangeLog.12 b/lisp/ChangeLog.12
index 6c11bdeaa49..e042d023292 100644
--- a/lisp/ChangeLog.12
+++ b/lisp/ChangeLog.12
@@ -6789,8 +6789,8 @@
2006-09-04 Daiki Ueno <ueno@unixuser.org>
* pgg-gpg.el (pgg-gpg-process-region): Revert two patches from Satyaki
- Das. http://article.gmane.org/gmane.emacs.gnus.general/49947
- http://article.gmane.org/gmane.emacs.gnus.general/50457
+ Das. http://article.gmane.org/gmane.emacs.gnus.general/49947 [dead link]
+ http://article.gmane.org/gmane.emacs.gnus.general/50457 [dead link]
2006-09-03 Chong Yidong <cyd@stupidchicken.com>
@@ -10678,7 +10678,7 @@
for root variables.
* progmodes/gdb-ui.el (gdb-pc-address): Rename from gdb-frame-address.
- (gdb-frame-address): Re-use to identify frame for watch expression.
+ (gdb-frame-address): Reuse to identify frame for watch expression.
(gdb-var-list, gdb-var-create-handler): Add frame address for root
variables.
(gdb-init-1, gdb-source, gdb-post-prompt)
@@ -32867,7 +32867,7 @@
(reftex-index-switch-index-tag): Add `redo' to arguments of
`reftex-display-index'.
(reftex-index-make-phrase-regexp): Fix bug with case-sensitive
- indexing. Fix bug with matching is there is a quote before or
+ indexing. Fix bug with matching if there is a quote before or
after the word.
* textmodes/reftex-cite.el (reftex-all-used-citation-keys):
@@ -33335,7 +33335,7 @@ See ChangeLog.11 for earlier changes.
;; add-log-time-zone-rule: t
;; End:
- Copyright (C) 2005-2023 Free Software Foundation, Inc.
+ Copyright (C) 2005-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/lisp/ChangeLog.13 b/lisp/ChangeLog.13
index 49ff87f464c..414cd1d25f8 100644
--- a/lisp/ChangeLog.13
+++ b/lisp/ChangeLog.13
@@ -7753,7 +7753,7 @@
* textmodes/remember.el (remember-buffer):
Use define-obsolete-function-alias rather than defalias.
-2007-11-03 Ulrich Mueller <ulm@gentoo.org> (tiny change)
+2007-11-03 Ulrich Müller <ulm@gentoo.org> (tiny change)
* simple.el (bad-packages-alist): Anchor semantic regexp.
@@ -12516,7 +12516,7 @@
* net/tramp-ftp.el (top): Autoload `tramp-set-connection-property'.
(tramp-ftp-file-name-handler): Set "started" property.
-2007-08-24 Ulrich Mueller <ulm@gentoo.org> (tiny change)
+2007-08-24 Ulrich Müller <ulm@gentoo.org> (tiny change)
* files.el (backup-buffer-copy): Don't wrap delete in
condition-case, only try to delete if file exists.
@@ -12592,7 +12592,7 @@
* textmodes/org.el (org-agenda-skip): Allow a form for
`org-agenda-skip-function'.
- (org-agenda-redo): Re-use local settings.
+ (org-agenda-redo): Reuse local settings.
(org-agenda): Store local settings.
(org-agenda-deadline-faces): New option.
(org-agenda-deadline-face): New function.
@@ -16697,7 +16697,7 @@ See ChangeLog.12 for earlier changes.
;; coding: utf-8
;; End:
- Copyright (C) 2007-2023 Free Software Foundation, Inc.
+ Copyright (C) 2007-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/lisp/ChangeLog.14 b/lisp/ChangeLog.14
index 129621791c0..3d6df493041 100644
--- a/lisp/ChangeLog.14
+++ b/lisp/ChangeLog.14
@@ -39,7 +39,7 @@
* language/korean.el (korean-cp949): New coding system. Set cp949
as an alias to it.
-2009-06-18 Ulrich Mueller <ulm@gentoo.org>
+2009-06-18 Ulrich Müller <ulm@gentoo.org>
* pgg-gpg.el (pgg-gpg-lookup-key-owner): Handle colon listings
format used by GnuPG 2.0.11.
@@ -459,7 +459,7 @@
* subr.el (assoc-default): Doc fix.
-2009-04-29 Ulrich Mueller <ulm@gentoo.org>
+2009-04-29 Ulrich Müller <ulm@gentoo.org>
* files.el (hack-local-variables-prop-line)
(hack-local-variables, dir-locals-read-from-file):
@@ -3281,7 +3281,7 @@
(ispell-find-aspell-dictionaries): Better error message. Use correct
dictionary alist for default. Better fallback default dictionary.
-2009-01-16 Ulrich Mueller <ulm@kph.uni-mainz.de>
+2009-01-16 Ulrich Müller <ulm@kph.uni-mainz.de>
* international/quail.el (quail-insert-kbd-layout):
Delete superfluous handling of 8-bit code. (Bug#1418)
@@ -3736,7 +3736,7 @@
* simple.el (visual-line-mode-map): Remove M-[ and M-] bindings.
-2009-01-04 Ulrich Mueller <ulm@kph.uni-mainz.de>
+2009-01-04 Ulrich Müller <ulm@kph.uni-mainz.de>
* progmodes/sh-script.el (sh-ancestor-alist): Doc fix.
@@ -4380,7 +4380,7 @@
2008-12-10 Juanma Barranquero <lekktu@gmail.com>
* net/tramp.el (top): Don't fail if there is no current message.
- [Ulrich Mueller sent a patch, which I saw too late.] (Bug#1514)
+ [Ulrich Müller sent a patch, which I saw too late.] (Bug#1514)
2008-12-10 Kenichi Handa <handa@m17n.org>
@@ -5317,7 +5317,7 @@
(math-standard-units): Fix typo in constant's description.
(math-additional-units): Fix typo in docstring.
-2008-11-19 Ulrich Mueller <ulm@kph.uni-mainz.de>
+2008-11-19 Ulrich Müller <ulm@kph.uni-mainz.de>
* calc/calc-units.el (math-standard-units): Add eps0,
permittivity of vacuum.
@@ -6087,7 +6087,7 @@
* progmodes/gud.el (gud-tooltip-mode): Use `tooltip-functions'.
-2008-10-29 Ulrich Mueller <ulm@gentoo.org>
+2008-10-29 Ulrich Müller <ulm@gentoo.org>
* server.el (server-socket-dir): Use TMPDIR (default /tmp) instead
of hardcoded /tmp.
@@ -6284,7 +6284,7 @@
* pcmpl-rpm.el (pcomplete/rpm): Make "rpm -qp" use file completion.
-2008-10-23 Ulrich Mueller <ulm@kph.uni-mainz.de>
+2008-10-23 Ulrich Müller <ulm@kph.uni-mainz.de>
* international/mule-cmds.el (describe-language-environment):
Indent sample text.
@@ -7198,7 +7198,7 @@
* play/fortune.el (fortune-program-options): Change to a list.
(fortune-in-buffer): Use apply.
-2008-09-20 Ulrich Mueller <ulm@kph.uni-mainz.de>
+2008-09-20 Ulrich Müller <ulm@kph.uni-mainz.de>
* emacs-lisp/authors.el: Change encoding of file to utf-8.
(authors-coding-system): Likewise.
@@ -15985,7 +15985,7 @@
(imap-message-copyuid-1): Use it.
(imap-message-appenduid-1): Likewise. Based on patch by Nathan
J. Williams in
- <http://permalink.gmane.org/gmane.emacs.gnus.general/65855>.
+ <http://permalink.gmane.org/gmane.emacs.gnus.general/65855>. [dead link]
2008-04-02 Alan Mackenzie <acm@muc.de>
@@ -16505,7 +16505,7 @@
(diary-list-entries-2): Simplify finding start of date.
(diary-show-all-entries, make-diary-entry): Respect non-nil values of
pop-up-frames.
- (diary-mark-entries-1): Re-use offset in abbreviated-year case.
+ (diary-mark-entries-1): Reuse offset in abbreviated-year case.
(mark-sexp-diary-entries): Remove superfluous call to diary-pull-attrs.
2008-03-27 Dan Nicolaescu <dann@ics.uci.edu>
@@ -17072,14 +17072,14 @@
* calendar/cal-bahai.el (calendar-bahai-leap-year-p)
(calendar-bahai-leap-base, calendar-bahai-from-absolute): Doc fixes.
(calendar-absolute-from-bahai): Fix the leap-year case.
- (calendar-bahai-from-absolute): Re-use the Gregorian month.
+ (calendar-bahai-from-absolute): Reuse the Gregorian month.
(calendar-bahai-date-string, calendar-bahai-print-date):
Handle pre-Bahai dates.
* calendar/cal-china.el (chinese-calendar-celestial-stem)
(chinese-calendar-terrestrial-branch): Make defcustoms.
- * calendar/cal-menu.el (calendar-mouse-holidays): Re-use the title.
+ * calendar/cal-menu.el (calendar-mouse-holidays): Reuse the title.
(calendar-mouse-view-diary-entries): Use or.
(calendar-mouse-chinese-date): Remove unused command.
(cal-menu-load-hook): Mark as obsolete.
@@ -20547,7 +20547,7 @@ See ChangeLog.13 for earlier changes.
;; coding: utf-8
;; End:
- Copyright (C) 2008-2023 Free Software Foundation, Inc.
+ Copyright (C) 2008-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/lisp/ChangeLog.15 b/lisp/ChangeLog.15
index 6bd61211d47..a441dc46ad3 100644
--- a/lisp/ChangeLog.15
+++ b/lisp/ChangeLog.15
@@ -3931,7 +3931,7 @@
* emacs-lisp/autoload.el (autoload-find-destination): The function
coding-system-eol-type may return non-numeric values. (Bug#7414)
-2010-11-18 Ulrich Mueller <ulm@gentoo.org>
+2010-11-18 Ulrich Müller <ulm@gentoo.org>
* server.el (server-force-stop): Ensure the server is stopped (Bug#7409).
@@ -6386,7 +6386,7 @@
* eshell/esh-util.el, eshell/esh-var.el:
Remove leading `*' from docs of faces and defcustoms.
-2010-09-25 Ulrich Mueller <ulm@gentoo.org>
+2010-09-25 Ulrich Müller <ulm@gentoo.org>
* eshell/em-ls.el (eshell-ls-archive-regexp):
* eshell/esh-util.el (eshell-tar-regexp):
@@ -7702,7 +7702,7 @@
* finder.el: Load finder-inf using `require'.
(finder-list-matches): Sorting by status is now the default.
- (finder-compile-keywords): Simpify printing.
+ (finder-compile-keywords): Simplify printing.
2010-08-30 Stefan Monnier <monnier@iro.umontreal.ca>
@@ -14019,7 +14019,7 @@
* font-lock.el (font-lock-refresh-defaults): New function, which
can be used to let font-lock react to external changes in
variables like font-lock-defaults and keywords.
- See http://thread.gmane.org/gmane.emacs.devel/118777/focus=118802
+ See http://thread.gmane.org/gmane.emacs.devel/118777/focus=118802 [dead link]
2009-12-28 Dan Nicolaescu <dann@ics.uci.edu>
@@ -14485,7 +14485,7 @@
color queries. Recompute faces after getting the background
color.
-2009-12-07 Ulrich Mueller <ulm@gentoo.org>
+2009-12-07 Ulrich Müller <ulm@gentoo.org>
* emacs-lisp/bytecomp.el (byte-compile-insert-header): Put the version
number comment back on its own line, for easier parsing.
@@ -17532,7 +17532,7 @@
(flyspell-word-search-backward): Remove nil argument in calls to
flyspell-get-word, since it is not needed now.
-2009-10-17 Ulrich Mueller <ulm@gentoo.org>
+2009-10-17 Ulrich Müller <ulm@gentoo.org>
* play/doctor.el (doctor-adverbp): Exclude some nouns. (Bug#4565)
@@ -22802,7 +22802,7 @@ See ChangeLog.14 for earlier changes.
;; coding: utf-8
;; End:
- Copyright (C) 2009-2023 Free Software Foundation, Inc.
+ Copyright (C) 2009-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/lisp/ChangeLog.16 b/lisp/ChangeLog.16
index f7dcda87466..fa956ac8784 100644
--- a/lisp/ChangeLog.16
+++ b/lisp/ChangeLog.16
@@ -1770,7 +1770,7 @@
(jit-lock--debug-fontifying): New var.
(jit-lock--debug-fontify): New function.
* subr.el (condition-case-unless-debug): Don't prevent catching the
- error, just let the debbugger run.
+ error, just let the debugger run.
* emacs-lisp/timer.el (timer-event-handler): Don't prevent debugging
timer code and don't drop errors silently.
@@ -2573,7 +2573,7 @@
* progmodes/grep.el (rgrep): Escape command line. Sometimes, it
is too long for Tramp. See discussion in
- <http://thread.gmane.org/gmane.emacs.tramp/8233/focus=8244>.
+ <http://thread.gmane.org/gmane.emacs.tramp/8233/focus=8244>. [dead link]
* progmodes/compile.el (compilation-start): Remove line escape
template.
@@ -4784,7 +4784,7 @@
Convert to defcustom.
(gdb-get-source-file): Don't bind pop-up-windows.
- * progmodes/gud.el (gud-display-line): Don't specially re-use
+ * progmodes/gud.el (gud-display-line): Don't specially reuse
other frames for the gdb-mi case (Bug#12648).
2012-10-18 Stefan Monnier <monnier@iro.umontreal.ca>
@@ -15382,7 +15382,7 @@
* calendar/calendar.el (calendar-mode):
Locally set scroll-margin to 0. (Bug#10379)
-2012-01-06 Ulrich Mueller <ulm@gentoo.org>
+2012-01-06 Ulrich Müller <ulm@gentoo.org>
* play/doctor.el (doctor-death): Escape "," characters. (Bug#10370)
@@ -17133,7 +17133,7 @@
(mouse-drag-vertical-line): Call mouse-drag-line.
* window.el (window-at-side-p, windows-at-side): New functions.
-2011-10-21 Ulrich Mueller <ulm@gentoo.org>
+2011-10-21 Ulrich Müller <ulm@gentoo.org>
* tar-mode.el (tar-grind-file-mode):
Fix handling of setuid/setgid, handle sticky bit. (Bug#9817)
@@ -25222,7 +25222,7 @@ See ChangeLog.15 for earlier changes.
;; coding: utf-8
;; End:
- Copyright (C) 2011-2023 Free Software Foundation, Inc.
+ Copyright (C) 2011-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/lisp/ChangeLog.17 b/lisp/ChangeLog.17
index 3377da7c54d..0e69fd5e461 100644
--- a/lisp/ChangeLog.17
+++ b/lisp/ChangeLog.17
@@ -4339,7 +4339,7 @@
(verilog-beg-of-statement-1, verilog-at-constraint-p):
Fix hanging with many curly-bracket pairs, bug663.
(verilog-do-indent): Fix electric tab deleting form-feeds.
- Note caused by indent-line-to deleting tabls pre 24.5.
+ Note caused by indent-line-to deleting tables pre 24.5.
(verilog-auto-output, verilog-auto-input, verilog-auto-inout)
(verilog-auto-inout-module, verilog-auto-inout-in): Doc fixes.
(verilog-read-always-signals, verilog-auto-sense-sigs)
@@ -24676,7 +24676,7 @@
* frame.el (display-monitor-attributes-list): Add NS case.
(ns-display-monitor-attributes-list): Declare.
-2013-05-09 Ulrich Mueller <ulm@gentoo.org>
+2013-05-09 Ulrich Müller <ulm@gentoo.org>
* descr-text.el (describe-char): Fix %d/%x typo. (Bug#14360)
@@ -26294,7 +26294,7 @@ See ChangeLog.16 for earlier changes.
;; coding: utf-8
;; End:
- Copyright (C) 2011-2023 Free Software Foundation, Inc.
+ Copyright (C) 2011-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/lisp/ChangeLog.2 b/lisp/ChangeLog.2
index 039f9abd13d..4e8813668ab 100644
--- a/lisp/ChangeLog.2
+++ b/lisp/ChangeLog.2
@@ -3992,7 +3992,7 @@
See ChangeLog.1 for earlier changes.
- Copyright (C) 1986-1988, 2001-2023 Free Software Foundation, Inc.
+ Copyright (C) 1986-1988, 2001-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/lisp/ChangeLog.3 b/lisp/ChangeLog.3
index 29585129a8a..843492958dd 100644
--- a/lisp/ChangeLog.3
+++ b/lisp/ChangeLog.3
@@ -12433,7 +12433,7 @@ See ChangeLog.2 for earlier changes.
;; coding: utf-8
;; End:
- Copyright (C) 1989, 1993, 2001-2023 Free Software Foundation, Inc.
+ Copyright (C) 1989, 1993, 2001-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/lisp/ChangeLog.4 b/lisp/ChangeLog.4
index f0dd1295dd7..3d8421a1c7e 100644
--- a/lisp/ChangeLog.4
+++ b/lisp/ChangeLog.4
@@ -1055,7 +1055,7 @@
(gud-irixdbx-marker-filter): New function.
(dbx): Insert case for Irix.
-1994-04-27 Ulrich Mueller (ulm@vsnhd1.cern.ch)
+1994-04-27 Ulrich Müller (ulm@vsnhd1.cern.ch)
* case-table.el (describe-buffer-case-table): Don't use
text-char-description.
@@ -4189,7 +4189,7 @@
* paths.el (rmail-spool-directory): Use dgux, not dgux-unix.
* lpr.el (lpr-command): Use dgux, not dgux-unix.
-1993-12-14 Ulrich Mueller (ulm@vsnhd1.cern.ch)
+1993-12-14 Ulrich Müller (ulm@vsnhd1.cern.ch)
* gud.el (gud-format-command): Use gud-last-last-frame if
gud-last-frame is nil.
@@ -4200,7 +4200,7 @@
* info.el (Info-insert-dir): For generated menu items, add ::.
-1993-12-13 Ulrich Mueller (ulm@vsnhd1.cern.ch)
+1993-12-13 Ulrich Müller (ulm@vsnhd1.cern.ch)
* gud.el (gud-mipsdbx-massage-args, gud-mipsdbx-marker-filter):
New functions for dbx support on Mips under Ultrix.
@@ -8935,7 +8935,7 @@ See ChangeLog.3 for earlier changes.
;; coding: utf-8
;; End:
- Copyright (C) 1993-1994, 2001-2023 Free Software Foundation, Inc.
+ Copyright (C) 1993-1994, 2001-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/lisp/ChangeLog.5 b/lisp/ChangeLog.5
index 96bda7650e2..1cbd1f923d0 100644
--- a/lisp/ChangeLog.5
+++ b/lisp/ChangeLog.5
@@ -5463,7 +5463,7 @@
(makefile-font-lock-keywords): Use makefile-tab-face.
(makefile-font-lock-keywords): Use defvar, not defconst.
-1994-10-28 Ulrich Mueller <ulm@vsnhd1.cern.ch>
+1994-10-28 Ulrich Müller <ulm@vsnhd1.cern.ch>
* iso-acc.el (iso-accents-mode): Variable renamed from
iso-accents-minor-mode.
@@ -9268,7 +9268,7 @@ See ChangeLog.4 for earlier changes.
;; coding: utf-8
;; End:
- Copyright (C) 1994-1995, 2001-2023 Free Software Foundation, Inc.
+ Copyright (C) 1994-1995, 2001-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/lisp/ChangeLog.6 b/lisp/ChangeLog.6
index 0fc8ffcf591..84253b2d079 100644
--- a/lisp/ChangeLog.6
+++ b/lisp/ChangeLog.6
@@ -7197,7 +7197,7 @@
* faces.el (x-font-regexp): Add \\(\\) for substring extraction.
-1995-07-27 Ulrich Mueller <ulm@vsnhd1.cern.ch>
+1995-07-27 Ulrich Müller <ulm@vsnhd1.cern.ch>
* fortran.el (fortran-break-line): Fixed a bug that sometimes
deleted first character in statement field of continuation line.
@@ -8021,7 +8021,7 @@ See ChangeLog.5 for earlier changes.
;; coding: utf-8
;; End:
- Copyright (C) 1995-1996, 2001-2023 Free Software Foundation, Inc.
+ Copyright (C) 1995-1996, 2001-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/lisp/ChangeLog.7 b/lisp/ChangeLog.7
index 17464042b76..efd01a86166 100644
--- a/lisp/ChangeLog.7
+++ b/lisp/ChangeLog.7
@@ -5232,7 +5232,7 @@
1998-03-29 Ralph Schleicher <rs@purple.UL.BaWue.DE>
- * battery.el (battery-linux-proc-apm): Re-use the temporary
+ * battery.el (battery-linux-proc-apm): Reuse the temporary
buffer.
* battery.el (battery-insert-file-contents): Disable code
@@ -23111,7 +23111,7 @@ See ChangeLog.6 for earlier changes.
;; coding: utf-8
;; End:
- Copyright (C) 1997-1998, 2001-2023 Free Software Foundation,
+ Copyright (C) 1997-1998, 2001-2024 Free Software Foundation,
Inc.
This file is part of GNU Emacs.
diff --git a/lisp/ChangeLog.8 b/lisp/ChangeLog.8
index 9c5096e56c5..b557c62b9ac 100644
--- a/lisp/ChangeLog.8
+++ b/lisp/ChangeLog.8
@@ -9993,7 +9993,7 @@ See ChangeLog.7 for earlier changes.
;; add-log-time-zone-rule: t
;; End:
- Copyright (C) 1999, 2001-2023 Free Software Foundation, Inc.
+ Copyright (C) 1999, 2001-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/lisp/ChangeLog.9 b/lisp/ChangeLog.9
index 063b9ea4991..ca962d92987 100644
--- a/lisp/ChangeLog.9
+++ b/lisp/ChangeLog.9
@@ -20685,7 +20685,7 @@ See ChangeLog.8 for earlier changes.
;; coding: utf-8
;; End:
- Copyright (C) 2000-2011, 2013-2023 Free Software Foundation, Inc.
+ Copyright (C) 2000-2011, 2013-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/lisp/Makefile.in b/lisp/Makefile.in
index c4dd1e7a1f3..95cb6a97213 100644
--- a/lisp/Makefile.in
+++ b/lisp/Makefile.in
@@ -1,6 +1,6 @@
### @configure_input@
-# Copyright (C) 2000-2023 Free Software Foundation, Inc.
+# Copyright (C) 2000-2024 Free Software Foundation, Inc.
# This file is part of GNU Emacs.
@@ -95,6 +95,8 @@ COMPILE_FIRST = \
ifeq ($(HAVE_NATIVE_COMP),yes)
COMPILE_FIRST += $(lisp)/emacs-lisp/comp.elc
COMPILE_FIRST += $(lisp)/emacs-lisp/comp-cstr.elc
+COMPILE_FIRST += $(lisp)/emacs-lisp/comp-common.elc
+COMPILE_FIRST += $(lisp)/emacs-lisp/comp-run.elc
endif
COMPILE_FIRST += $(lisp)/emacs-lisp/loaddefs-gen.elc
COMPILE_FIRST += $(lisp)/emacs-lisp/radix-tree.elc
diff --git a/lisp/abbrev.el b/lisp/abbrev.el
index 1a665efb0a5..4e26136e8f8 100644
--- a/lisp/abbrev.el
+++ b/lisp/abbrev.el
@@ -1,6 +1,6 @@
;;; abbrev.el --- abbrev mode commands for Emacs -*- lexical-binding: t -*-
-;; Copyright (C) 1985-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1985-2024 Free Software Foundation, Inc.
;; Maintainer: emacs-devel@gnu.org
;; Keywords: abbrev convenience
@@ -122,6 +122,9 @@ Otherwise display all the abbrevs."
found))
(defun prepare-abbrev-list-buffer (&optional local)
+ "Return buffer listing abbreviations and expansions for each abbrev table.
+
+If LOCAL is non-nil, include in the buffer only the local abbrevs."
(let ((local-table local-abbrev-table))
(with-current-buffer (get-buffer-create "*Abbrevs*")
(erase-buffer)
@@ -333,6 +336,20 @@ Don't use this function in a Lisp program; use `define-abbrev' instead."
(add-abbrev global-abbrev-table "Global" arg))
(defun add-abbrev (table type arg)
+ "Define abbrev in TABLE, whose expansion is ARG words before point.
+Read the abbreviation from the minibuffer, with prompt TYPE.
+
+ARG of zero means the entire region is the expansion.
+
+A negative ARG means to undefine the specified abbrev.
+
+TYPE is an arbitrary string used to prompt user for the kind of
+abbrev, such as \"Global\", \"Mode\". (This has no influence on the
+choice of the actual TABLE).
+
+See `inverse-add-abbrev' for the opposite task.
+
+Don't use this function in a Lisp program; use `define-abbrev' instead."
(let ((exp
(cond
((or (and (null arg) (use-region-p))
@@ -353,7 +370,7 @@ Don't use this function in a Lisp program; use `define-abbrev' instead."
(if (or (null exp)
(not (abbrev-expansion name table))
(y-or-n-p (format "%s expands into \"%s\"; redefine? "
- name (abbrev-expansion name table))))
+ name (abbrev-expansion name table))))
(define-abbrev table (downcase name) exp))))
(defun inverse-add-mode-abbrev (n)
@@ -393,6 +410,19 @@ to define an abbrev by specifying the abbreviation in the minibuffer."
(inverse-add-abbrev global-abbrev-table "Global" n))
(defun inverse-add-abbrev (table type arg)
+ "Define the word before point as an abbrev in TABLE.
+Read the expansion from the minibuffer, using prompt TYPE, define
+the abbrev, and then expand the abbreviation in the current
+buffer.
+
+ARG means use the ARG-th word before point as the abbreviation.
+Negative ARG means use the ARG-th word after point.
+
+TYPE is an arbitrary string used to prompt user for the kind of
+abbrev, such as \"Global\", \"Mode\". (This has no influence on the
+choice of the actual TABLE).
+
+See also `add-abbrev', which performs the opposite task."
(let (name exp start end)
(save-excursion
(forward-word (1+ (- arg)))
@@ -1102,6 +1132,8 @@ Presumes that `standard-output' points to `current-buffer'."
(insert ")\n"))
(defun abbrev--describe (sym)
+ "Describe abbrev SYM.
+Print on `standard-output' the abbrev, count of use, expansion."
(when (symbol-value sym)
(prin1 (symbol-name sym))
(if (null (abbrev-get sym :system))
@@ -1243,11 +1275,12 @@ which see."
(setq font-lock-multiline nil))
(defun abbrev--possibly-save (query &optional arg)
+ "Hook function for use by `save-some-buffer-functions'.
+
+Maybe save abbrevs, and record whether we either saved them or asked to."
;; Query mode.
(if (eq query 'query)
(and save-abbrevs abbrevs-changed)
- ;; Maybe save abbrevs, and record whether we either saved them or
- ;; asked to.
(and save-abbrevs
abbrevs-changed
(prog1
diff --git a/lisp/align.el b/lisp/align.el
index bc8ccbd599c..fa95f24fa02 100644
--- a/lisp/align.el
+++ b/lisp/align.el
@@ -1,6 +1,6 @@
;;; align.el --- align text to a specific column, by regexp -*- lexical-binding:t -*-
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
;; Author: John Wiegley <johnw@gnu.org>
;; Maintainer: emacs-devel@gnu.org
@@ -555,8 +555,7 @@ The possible settings for `align-region-separate' are:
(repeat . t)
(run-if . ,(lambda ()
(and (not (eq '- current-prefix-arg))
- (not (apply #'provided-mode-derived-p
- major-mode align-tex-modes))))))
+ (not (derived-mode-p align-tex-modes))))))
;; With a negative prefix argument, lists of dollar figures will
;; be aligned.
@@ -577,7 +576,18 @@ The possible settings for `align-region-separate' are:
"="
(group (zero-or-more (syntax whitespace)))))
(group . (1 2))
- (modes . '(conf-toml-mode toml-ts-mode))))
+ (modes . '(conf-toml-mode toml-ts-mode lua-mode lua-ts-mode)))
+
+ (double-dash-comment
+ (regexp . ,(rx (group (zero-or-more (syntax whitespace)))
+ "--"
+ (zero-or-more nonl)))
+ (modes . '(lua-mode lua-ts-mode))
+ (column . comment-column)
+ (valid . ,(lambda ()
+ (save-excursion
+ (goto-char (match-beginning 1))
+ (not (bolp)))))))
"A list describing all of the available alignment rules.
The format is:
@@ -1270,6 +1280,14 @@ Otherwise, create a new marker at position POS, with type TYPE."
(move-marker ,marker-var ,pos)
(setq ,marker-var (copy-marker ,pos ,type))))
+(defun align--rule-should-run (rule)
+ "Given an `align-rules-list' entry RULE, return t if it should run.
+This is decided by the `modes' and `run-if' keys in the alist
+RULE. Their meaning is documented in `align-rules-list' (which see)."
+ (let-alist rule
+ (not (or (and .modes (not (derived-mode-p (eval .modes))))
+ (and .run-if (not (funcall .run-if)))))))
+
(defun align-region (beg end separate rules exclude-rules
&optional func)
"Align a region based on a given set of alignment rules.
@@ -1307,23 +1325,20 @@ This feature (of passing a FUNC) is used internally to locate the
position of exclusion areas, but could also be used for any other
purpose where you might want to know where the regions that the
aligner would have dealt with are."
- (let ((end-mark (and end (copy-marker end t)))
- (real-beg beg)
- (report (and (not func) align-large-region beg end
- (>= (- end beg) align-large-region)))
- (rule-index 1)
- (rule-count (length rules))
- markers)
+ (let* ((end-mark (and end (copy-marker end t)))
+ (real-beg beg)
+ (report (and (not func) align-large-region beg end
+ (>= (- end beg) align-large-region)))
+ (rules (seq-filter #'align--rule-should-run rules))
+ (rule-index 1)
+ (rule-count (length rules))
+ markers)
(if (and align-indent-before-aligning real-beg end-mark)
(indent-region real-beg end-mark nil))
(while rules
- (let* ((rule (car rules))
- (run-if (assq 'run-if rule))
- (modes (assq 'modes rule)))
- ;; unless the `run-if' form tells us not to, look for the
- ;; rule..
- (unless (or (and modes (not (apply #'derived-mode-p (eval (cdr modes)))))
- (and run-if (not (funcall (cdr run-if)))))
+ (let ((rule (car rules)))
+ (progn
+ ;; Search for a match for the rule.
(let* ((case-fold-search case-fold-search)
(case-fold (assq 'case-fold rule))
(regexp (cdr (assq 'regexp rule)))
@@ -1332,12 +1347,18 @@ aligner would have dealt with are."
(thissep (if rulesep (cdr rulesep) separate))
same (eol 0)
search-start
- groups ;; group-c
- spacing spacing-c
- tab-stop tab-stop-c
- repeat repeat-c
- valid valid-c
- first
+ (groups (ensure-list (or (cdr (assq 'group rule)) 1)))
+ (spacing (cdr (assq 'spacing rule)))
+ (tab-stop (let ((rule-ts (assq 'tab-stop rule)))
+ (cond (rule-ts
+ (cdr rule-ts))
+ ((symbolp align-to-tab-stop)
+ (symbol-value align-to-tab-stop))
+ (t
+ align-to-tab-stop))))
+ (repeat (cdr (assq 'repeat rule)))
+ (valid (assq 'valid rule))
+ (first (car groups))
regions index
last-point
save-match-data
@@ -1454,45 +1475,12 @@ aligner would have dealt with are."
(if (and (bolp) (> (point) search-start))
(forward-char -1))
- ;; lookup the `group' attribute the first time
- ;; that we need it
- (unless nil ;; group-c
- (setq groups (or (cdr (assq 'group rule)) 1))
- (unless (listp groups)
- (setq groups (list groups)))
- (setq first (car groups)))
-
- (unless spacing-c
- (setq spacing (cdr (assq 'spacing rule))
- spacing-c t))
-
- (unless tab-stop-c
- (setq tab-stop
- (let ((rule-ts (assq 'tab-stop rule)))
- (cond (rule-ts
- (cdr rule-ts))
- ((symbolp align-to-tab-stop)
- (symbol-value align-to-tab-stop))
- (t
- align-to-tab-stop)))
- tab-stop-c t))
-
;; test whether we have found a match on the same
;; line as a previous match
(when (> (point) eol)
(setq same nil)
(align--set-marker eol (line-end-position)))
- ;; lookup the `repeat' attribute the first time
- (or repeat-c
- (setq repeat (cdr (assq 'repeat rule))
- repeat-c t))
-
- ;; lookup the `valid' attribute the first time
- (or valid-c
- (setq valid (assq 'valid rule)
- valid-c t))
-
;; remember the beginning position of this rule
;; match, and save the match-data, since either
;; the `valid' form, or the code that searches for
@@ -1594,7 +1582,7 @@ aligner would have dealt with are."
(if (= (point) search-start)
(forward-char)))))
- ;; when they are no more matches for this rule,
+ ;; when there are no more matches for this rule,
;; align whatever was left over
(if regions
(align-regions regions align-props rule func))))))))
diff --git a/lisp/allout-widgets.el b/lisp/allout-widgets.el
index be9cf06c523..7f5831d4124 100644
--- a/lisp/allout-widgets.el
+++ b/lisp/allout-widgets.el
@@ -1,6 +1,6 @@
;;; allout-widgets.el --- Visually highlight allout outline structure. -*- lexical-binding: t; -*-
-;; Copyright (C) 2005-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2005-2024 Free Software Foundation, Inc.
;; Author: Ken Manheimer <ken dot manheimer at gmail...>
;; Version: 1.0
diff --git a/lisp/allout.el b/lisp/allout.el
index d3203800168..95b73c54934 100644
--- a/lisp/allout.el
+++ b/lisp/allout.el
@@ -1,11 +1,11 @@
;;; allout.el --- extensive outline mode for use alone and with other modes -*- lexical-binding: t; -*-
-;; Copyright (C) 1992-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1992-2024 Free Software Foundation, Inc.
;; Author: Ken Manheimer <ken dot manheimer at gmail...>
;; Created: Dec 1991 -- first release to usenet
;; Version: 2.3
-;; Keywords: outlines, wp, languages, PGP, GnuPG
+;; Keywords: outlines, text, languages, PGP, GnuPG
;; Website: https://myriadicity.net/software-and-systems/craft/emacs-allout
;; This file is part of GNU Emacs.
diff --git a/lisp/ansi-color.el b/lisp/ansi-color.el
index 0461ced6956..1d053f718f8 100644
--- a/lisp/ansi-color.el
+++ b/lisp/ansi-color.el
@@ -1,6 +1,6 @@
;;; ansi-color.el --- translate ANSI escape sequences into faces -*- lexical-binding: t -*-
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
;; Author: Alex Schroeder <alex@gnu.org>
;; Version: 3.4.2
diff --git a/lisp/ansi-osc.el b/lisp/ansi-osc.el
index 886291a2c78..7e686193f69 100644
--- a/lisp/ansi-osc.el
+++ b/lisp/ansi-osc.el
@@ -1,6 +1,6 @@
;;; ansi-osc.el --- Support for OSC escape sequences -*- lexical-binding: t; -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;; Author: Augusto Stoffel <arstoffel@gmail.com>
;; Matthias Meulien <orontee@gmail.com>
diff --git a/lisp/apropos.el b/lisp/apropos.el
index 0e286f3069d..6c6cd0b593d 100644
--- a/lisp/apropos.el
+++ b/lisp/apropos.el
@@ -1,6 +1,6 @@
;;; apropos.el --- apropos commands for users and programmers -*- lexical-binding: t -*-
-;; Copyright (C) 1989-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1989-2024 Free Software Foundation, Inc.
;; Author: Joe Wells <jbw@bigbird.bu.edu>
;; Daniel Pfeiffer <occitan@esperanto.org> (rewrite)
diff --git a/lisp/arc-mode.el b/lisp/arc-mode.el
index 81d3dfc3432..9a8dd6679e3 100644
--- a/lisp/arc-mode.el
+++ b/lisp/arc-mode.el
@@ -1,6 +1,6 @@
;;; arc-mode.el --- simple editing of archives -*- lexical-binding: t; -*-
-;; Copyright (C) 1995, 1997-1998, 2001-2023 Free Software Foundation,
+;; Copyright (C) 1995, 1997-1998, 2001-2024 Free Software Foundation,
;; Inc.
;; Author: Morten Welinder <terra@gnu.org>
@@ -231,13 +231,27 @@ Archive and member name will be added."
:group 'archive)
(defcustom archive-zip-extract
- (cond ((executable-find "unzip") '("unzip" "-qq" "-c"))
+ (cond ((executable-find "unzip")
+ (if (and (eq system-type 'android)
+ ;; Mind that the unzip provided by Android
+ ;; does not understand -qq or -c, their
+ ;; functions being assumed by -q and -p
+ ;; respectively. Furthermore, the user
+ ;; might install an unzip executable
+ ;; distinct from the system-provided unzip,
+ ;; and such situations must be detected as
+ ;; well.
+ (member (executable-find "unzip")
+ '("/bin/unzip"
+ "/system/bin/unzip")))
+ '("unzip" "-q" "-p")
+ '("unzip" "-qq" "-c")))
(archive-7z-program `(,archive-7z-program "x" "-so"))
((executable-find "pkunzip") '("pkunzip" "-e" "-o-"))
(t '("unzip" "-qq" "-c")))
"Program and its options to run in order to extract a zip file member.
-Extraction should happen to standard output. Archive and member name will
-be added."
+Extraction should happen to standard output. Archive and member
+name will be added."
:type '(list (string :tag "Program")
(repeat :tag "Options"
:inline t
@@ -2094,16 +2108,14 @@ This doesn't recover lost files, it just undoes changes in the buffer itself."
(t
(archive-extract-by-stdout
archive
- ;; unzip expands wildcards in NAME, so we need to quote it. But
- ;; not on DOS/Windows, since that fails extraction on those
- ;; systems (unless w32-quote-process-args is nil), and file names
- ;; with wildcards in zip archives don't work there anyway.
- ;; FIXME: Does pkunzip need similar treatment?
- (if (and (or (not (memq system-type '(windows-nt ms-dos)))
- (and (boundp 'w32-quote-process-args)
- (null w32-quote-process-args)))
- (equal (car archive-zip-extract) "unzip"))
- (shell-quote-argument name)
+ ;; unzip expands wildcard characters in NAME, so we need to quote
+ ;; wildcard characters in a special way: replace each such
+ ;; character C with a single-character alternative [C]. We
+ ;; cannot use 'shell-quote-argument' here because that doesn't
+ ;; protect wildcard characters from being expanded by unzip
+ ;; itself.
+ (if (equal (car archive-zip-extract) "unzip")
+ (replace-regexp-in-string "[[?*]" "[\\&]" name)
name)
archive-zip-extract))))
diff --git a/lisp/array.el b/lisp/array.el
index b2f961d187b..99e67be2d90 100644
--- a/lisp/array.el
+++ b/lisp/array.el
@@ -1,6 +1,6 @@
;;; array.el --- array editing commands for GNU Emacs -*- lexical-binding: t; -*-
-;; Copyright (C) 1987, 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1987, 2000-2024 Free Software Foundation, Inc.
;; Author: David M. Brown
;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/auth-source-pass.el b/lisp/auth-source-pass.el
index dbcc9d05753..03fd1f35811 100644
--- a/lisp/auth-source-pass.el
+++ b/lisp/auth-source-pass.el
@@ -1,6 +1,6 @@
;;; auth-source-pass.el --- Integrate auth-source with password-store -*- lexical-binding: t -*-
-;; Copyright (C) 2015, 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2015, 2017-2024 Free Software Foundation, Inc.
;; Author: Damien Cassou <damien@cassou.me>,
;; Nicolas Petton <nicolas@petton.fr>
@@ -122,9 +122,9 @@ HOSTS can be a string or a list of strings."
(defun auth-source-pass--build-result-many (hosts ports users require max)
"Return multiple `auth-source-pass--build-result' values."
- (unless (listp hosts) (setq hosts (list hosts)))
- (unless (listp users) (setq users (list users)))
- (unless (listp ports) (setq ports (list ports)))
+ (setq hosts (ensure-list hosts))
+ (setq users (ensure-list users))
+ (setq ports (ensure-list ports))
(let* ((auth-source-pass--match-regexp (auth-source-pass--match-regexp
auth-source-pass-port-separator))
(rv (auth-source-pass--find-match-many hosts users ports
diff --git a/lisp/auth-source.el b/lisp/auth-source.el
index 66de763f671..369cf4dca2e 100644
--- a/lisp/auth-source.el
+++ b/lisp/auth-source.el
@@ -1,6 +1,6 @@
;;; auth-source.el --- authentication sources for Gnus and Emacs -*- lexical-binding: t -*-
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
;; Author: Ted Zlatanov <tzz@lifelogs.com>
;; Keywords: news
@@ -387,7 +387,6 @@ soon as a function returns non-nil.")
(cond
((equal extension "plist")
(auth-source-backend
- source
:source source
:type 'plstore
:search-function #'auth-source-plstore-search
@@ -395,13 +394,11 @@ soon as a function returns non-nil.")
:data (plstore-open source)))
((member-ignore-case extension '("json"))
(auth-source-backend
- source
:source source
:type 'json
:search-function #'auth-source-json-search))
(t
(auth-source-backend
- source
:source source
:type 'netrc
:search-function #'auth-source-netrc-search
@@ -449,7 +446,6 @@ soon as a function returns non-nil.")
(setq source (symbol-name source)))
(auth-source-backend
- (format "Mac OS Keychain (%s)" source)
:source source
:type keychain-type
:search-function #'auth-source-macos-keychain-search
@@ -490,7 +486,6 @@ soon as a function returns non-nil.")
(if (featurep 'secrets)
(auth-source-backend
- (format "Secrets API (%s)" source)
:source source
:type 'secrets
:search-function #'auth-source-secrets-search
@@ -498,7 +493,6 @@ soon as a function returns non-nil.")
(auth-source-do-warn
"auth-source-backend-parse: no Secrets API, ignoring spec: %S" entry)
(auth-source-backend
- (format "Ignored Secrets API (%s)" source)
:source ""
:type 'ignore))))))
@@ -899,8 +893,7 @@ Remove trailing \": \"."
(defun auth-source-ensure-strings (values)
(if (eq values t)
values
- (unless (listp values)
- (setq values (list values)))
+ (setq values (ensure-list values))
(mapcar (lambda (value)
(if (numberp value)
(format "%s" value)
diff --git a/lisp/autoinsert.el b/lisp/autoinsert.el
index 3d95ce60ae3..f2631422c62 100644
--- a/lisp/autoinsert.el
+++ b/lisp/autoinsert.el
@@ -1,6 +1,6 @@
;;; autoinsert.el --- automatic mode-dependent insertion of text into new files -*- lexical-binding: t -*-
-;; Copyright (C) 1985-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1985-2024 Free Software Foundation, Inc.
;; Author: Charlie Martin <crm@cs.duke.edu>
;; Adapted-By: Daniel Pfeiffer <occitan@esperanto.org>
diff --git a/lisp/autorevert.el b/lisp/autorevert.el
index 23b7ca0a1d4..a23d536879d 100644
--- a/lisp/autorevert.el
+++ b/lisp/autorevert.el
@@ -1,6 +1,6 @@
;;; autorevert.el --- revert buffers when files on disk change -*- lexical-binding:t -*-
-;; Copyright (C) 1997-1999, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997-1999, 2001-2024 Free Software Foundation, Inc.
;; Author: Anders Lindgren
;; Keywords: convenience
diff --git a/lisp/avoid.el b/lisp/avoid.el
index eea6e88bd9b..c9b10ce3975 100644
--- a/lisp/avoid.el
+++ b/lisp/avoid.el
@@ -1,6 +1,6 @@
;;; avoid.el --- make mouse pointer stay out of the way of editing -*- lexical-binding: t -*-
-;; Copyright (C) 1993-1994, 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1993-1994, 2000-2024 Free Software Foundation, Inc.
;; Author: Boris Goldowsky <boris@gnu.org>
;; Keywords: mouse
diff --git a/lisp/battery.el b/lisp/battery.el
index c55fcbbee8c..4aae3e0ef54 100644
--- a/lisp/battery.el
+++ b/lisp/battery.el
@@ -1,6 +1,6 @@
;;; battery.el --- display battery status information -*- lexical-binding:t -*-
-;; Copyright (C) 1997-1998, 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997-1998, 2000-2024 Free Software Foundation, Inc.
;; Author: Ralph Schleicher <rs@ralph-schleicher.de>
;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/use-package/bind-key.el b/lisp/bind-key.el
index c45b9e546f7..94a39f795cd 100644
--- a/lisp/use-package/bind-key.el
+++ b/lisp/bind-key.el
@@ -1,6 +1,6 @@
;;; bind-key.el --- A simple way to manage personal keybindings -*- lexical-binding: t; -*-
-;; Copyright (c) 2012-2023 Free Software Foundation, Inc.
+;; Copyright (c) 2012-2024 Free Software Foundation, Inc.
;; Author: John Wiegley <johnw@newartisans.com>
;; Maintainer: John Wiegley <johnw@newartisans.com>
@@ -10,6 +10,9 @@
;; Keywords: keys keybinding config dotemacs extensions
;; URL: https://github.com/jwiegley/use-package
+;; This is a GNU ELPA :core package. Avoid functionality that is not
+;; compatible with the version of Emacs recorded above.
+
;; This file is part of GNU Emacs.
;; GNU Emacs is free software: you can redistribute it and/or modify
diff --git a/lisp/bindings.el b/lisp/bindings.el
index 68aa0a78099..4690897fed4 100644
--- a/lisp/bindings.el
+++ b/lisp/bindings.el
@@ -1,6 +1,6 @@
;;; bindings.el --- define standard key bindings and some variables -*- lexical-binding: t; -*-
-;; Copyright (C) 1985-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1985-2024 Free Software Foundation, Inc.
;; Maintainer: emacs-devel@gnu.org
;; Keywords: internal
@@ -298,6 +298,35 @@ Value is used for `mode-line-frame-identification', which see."
;;;###autoload
(put 'mode-line-frame-identification 'risky-local-variable t)
+(defvar mode-line-window-dedicated-keymap
+ (let ((map (make-sparse-keymap)))
+ (define-key map [mode-line mouse-1] #'toggle-window-dedicated)
+ (purecopy map)) "\
+Keymap for what is displayed by `mode-line-window-dedicated'.")
+
+(defun mode-line-window-control ()
+ "Compute mode line construct for window dedicated state.
+Value is used for `mode-line-window-dedicated', which see."
+ (cond
+ ((eq (window-dedicated-p) t)
+ (propertize
+ "D"
+ 'help-echo "Window strongly dedicated to its buffer\nmouse-1: Toggle"
+ 'local-map mode-line-window-dedicated-keymap
+ 'mouse-face 'mode-line-highlight))
+ ((window-dedicated-p)
+ (propertize
+ "d"
+ 'help-echo "Window dedicated to its buffer\nmouse-1: Toggle"
+ 'local-map mode-line-window-dedicated-keymap
+ 'mouse-face 'mode-line-highlight))
+ (t "")))
+
+(defvar mode-line-window-dedicated '(:eval (mode-line-window-control))
+ "Mode line construct to describe the current window.")
+;;;###autoload
+(put 'mode-line-window-dedicated 'risky-local-variable t)
+
(defvar-local mode-line-process nil
"Mode line construct for displaying info on process status.
Normally nil in most modes, since there is no process to display.")
@@ -676,12 +705,14 @@ By default, this shows the information specified by `global-mode-string'.")
'mode-line-mule-info
'mode-line-client
'mode-line-modified
- 'mode-line-remote)
- 'display '(min-width (5.0)))
+ 'mode-line-remote
+ 'mode-line-window-dedicated)
+ 'display '(min-width (6.0)))
'mode-line-frame-identification
'mode-line-buffer-identification
" "
'mode-line-position
+ '(project-mode-line project-mode-line-format)
'(vc-mode vc-mode)
" "
'mode-line-modes
@@ -794,7 +825,7 @@ meaningful if it refers to a lexically bound variable."
"Describe minor mode for EVENT on minor modes area of the mode line."
(interactive "@e")
(let ((indicator (car (nth 4 (car (cdr event))))))
- (describe-minor-mode-from-indicator indicator)))
+ (describe-minor-mode-from-indicator indicator event)))
(defvar mode-line-defining-kbd-macro (propertize " Def" 'face 'font-lock-warning-face)
"String displayed in the mode line in keyboard macro recording mode.")
@@ -1011,6 +1042,14 @@ or backward in the buffer. This is in contrast with \\[forward-word]
and \\[backward-word], which see.
Value is normally t.
+
+The word boundaries are normally determined by the buffer's syntax
+table and character script (according to `char-script-table'), but
+`find-word-boundary-function-table', such as set up by `subword-mode',
+can change that. If a Lisp program needs to move by words determined
+strictly by the syntax table, it should use `forward-word-strictly'
+instead. See Info node `(elisp) Word Motion' for details.
+
If an edge of the buffer or a field boundary is reached, point is left there
and the function returns nil. Field boundaries are not noticed
if `inhibit-field-text-motion' is non-nil."
@@ -1027,6 +1066,14 @@ or forward in the buffer. This is in contrast with \\[backward-word]
and \\[forward-word], which see.
Value is normally t.
+
+The word boundaries are normally determined by the buffer's syntax
+table and character script (according to `char-script-table'), but
+`find-word-boundary-function-table', such as set up by `subword-mode',
+can change that. If a Lisp program needs to move by words determined
+strictly by the syntax table, it should use `forward-word-strictly'
+instead. See Info node `(elisp) Word Motion' for details.
+
If an edge of the buffer or a field boundary is reached, point is left there
and the function returns nil. Field boundaries are not noticed
if `inhibit-field-text-motion' is non-nil."
diff --git a/lisp/bookmark.el b/lisp/bookmark.el
index 10ff2f5ebbf..893fdffb7ce 100644
--- a/lisp/bookmark.el
+++ b/lisp/bookmark.el
@@ -1,6 +1,6 @@
;;; bookmark.el --- set bookmarks, maybe annotate them, jump to them later -*- lexical-binding: t -*-
-;; Copyright (C) 1993-1997, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1993-1997, 2001-2024 Free Software Foundation, Inc.
;; Author: Karl Fogel <kfogel@red-bean.com>
;; Created: July, 1993
@@ -511,6 +511,8 @@ BM is a bookmark as returned from function `bookmark-get-bookmark'.
See user option `bookmark-fringe-mark'."
(let ((filename (cdr (assq 'filename bm)))
(pos (cdr (assq 'position bm)))
+ ;; Don't expand file names for non-existing remote connections.
+ (non-essential t)
overlays found temp)
(when (and pos filename)
(setq filename (expand-file-name filename))
diff --git a/lisp/bs.el b/lisp/bs.el
index 70868591196..9db93ea0423 100644
--- a/lisp/bs.el
+++ b/lisp/bs.el
@@ -1,6 +1,6 @@
;;; bs.el --- menu for selecting and displaying buffers -*- lexical-binding: t -*-
-;; Copyright (C) 1998-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-2024 Free Software Foundation, Inc.
;; Author: Olaf Sylvester <Olaf.Sylvester@netsurf.de>
;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/buff-menu.el b/lisp/buff-menu.el
index 29c981c1364..82afea3d053 100644
--- a/lisp/buff-menu.el
+++ b/lisp/buff-menu.el
@@ -1,6 +1,6 @@
;;; buff-menu.el --- Interface for viewing and manipulating buffers -*- lexical-binding: t -*-
-;; Copyright (C) 1985-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1985-2024 Free Software Foundation, Inc.
;; Maintainer: emacs-devel@gnu.org
;; Keywords: convenience
diff --git a/lisp/button.el b/lisp/button.el
index b01595943fc..c0584729172 100644
--- a/lisp/button.el
+++ b/lisp/button.el
@@ -1,6 +1,6 @@
;;; button.el --- clickable buttons -*- lexical-binding: t -*-
;;
-;; Copyright (C) 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2024 Free Software Foundation, Inc.
;;
;; Author: Miles Bader <miles@gnu.org>
;; Keywords: extensions, hypermedia
@@ -492,10 +492,10 @@ pushing a button, use the `button-describe' command."
(if str-button
;; mode-line, header-line, or display string event.
(button-activate str t)
- (if (eq (car pos) 'touchscreen-down)
+ (if (eq (car-safe pos) 'touchscreen-down)
;; If touch-screen-track tap returns nil, then the
- ;; tap was cancelled.
- (when (touch-screen-track-tap pos)
+ ;; tap was canceled.
+ (when (touch-screen-track-tap pos nil nil t)
(push-button (posn-point posn) t))
(push-button (posn-point posn) t))))))
;; POS is just normal position
diff --git a/lisp/calc/calc-aent.el b/lisp/calc/calc-aent.el
index 66ede3295ae..08e8d9fcd6f 100644
--- a/lisp/calc/calc-aent.el
+++ b/lisp/calc/calc-aent.el
@@ -1,6 +1,6 @@
;;; calc-aent.el --- algebraic entry functions for Calc -*- lexical-binding:t -*-
-;; Copyright (C) 1990-1993, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1990-1993, 2001-2024 Free Software Foundation, Inc.
;; Author: Dave Gillespie <daveg@synaptics.com>
@@ -547,22 +547,41 @@ The value t means abort and give an error message.")
"₀₁₂₃₄₅₆₇₈₉₊₋₍₎" ; 0123456789+-()
"A string consisting of the subscripts allowed by Calc.")
+(defvar math--read-preprocess-re-cache nil
+ "Cached regexp and tag: (REGEXP REPLACEMENTS SUPERSCRIPTS SUBSCRIPTS)")
+
;;;###autoload
(defun math-read-preprocess-string (str)
"Replace some substrings of STR by Calc equivalents."
- (setq str
- (replace-regexp-in-string (concat "[" math-read-superscripts "]+")
- "^(\\&)" str))
- (setq str
- (replace-regexp-in-string (concat "[" math-read-subscripts "]+")
- "_(\\&)" str))
- (let ((rep-list math-read-replacement-list))
- (while rep-list
- (setq str
- (replace-regexp-in-string (nth 0 (car rep-list))
- (nth 1 (car rep-list)) str))
- (setq rep-list (cdr rep-list))))
- str)
+ (unless (and (eq (nth 1 math--read-preprocess-re-cache)
+ math-read-replacement-list)
+ (eq (nth 2 math--read-preprocess-re-cache)
+ math-read-superscripts)
+ (eq (nth 3 math--read-preprocess-re-cache)
+ math-read-subscripts))
+ ;; Cache invalid, recompute.
+ (setq math--read-preprocess-re-cache
+ (list (rx-to-string
+ `(or (or (+ (in ,math-read-superscripts))
+ (group (+ (in ,math-read-subscripts))))
+ (group (or ,@(mapcar #'car math-read-replacement-list))))
+ t)
+ math-read-replacement-list
+ math-read-superscripts
+ math-read-subscripts)))
+ (replace-regexp-in-string
+ (nth 0 math--read-preprocess-re-cache)
+ (lambda (s)
+ (if (match-beginning 2)
+ (cadr (assoc s math-read-replacement-list)) ; not super/subscript
+ (concat (if (match-beginning 1) "_" "^")
+ "("
+ (mapconcat (lambda (c)
+ (cadr (assoc (char-to-string c)
+ math-read-replacement-list)))
+ s)
+ ")")))
+ str t))
;; The next few variables are local to math-read-exprs (and math-read-expr
;; in calc-ext.el), but are set in functions they call.
diff --git a/lisp/calc/calc-alg.el b/lisp/calc/calc-alg.el
index 95f7a34a4ae..81340b43221 100644
--- a/lisp/calc/calc-alg.el
+++ b/lisp/calc/calc-alg.el
@@ -1,6 +1,6 @@
;;; calc-alg.el --- algebraic functions for Calc -*- lexical-binding:t -*-
-;; Copyright (C) 1990-1993, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1990-1993, 2001-2024 Free Software Foundation, Inc.
;; Author: David Gillespie <daveg@synaptics.com>
diff --git a/lisp/calc/calc-arith.el b/lisp/calc/calc-arith.el
index 54f0a5649a3..7ab642dd2c3 100644
--- a/lisp/calc/calc-arith.el
+++ b/lisp/calc/calc-arith.el
@@ -1,6 +1,6 @@
;;; calc-arith.el --- arithmetic functions for Calc -*- lexical-binding:t -*-
-;; Copyright (C) 1990-1993, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1990-1993, 2001-2024 Free Software Foundation, Inc.
;; Author: David Gillespie <daveg@synaptics.com>
diff --git a/lisp/calc/calc-bin.el b/lisp/calc/calc-bin.el
index 16ebe7552f4..790528e428d 100644
--- a/lisp/calc/calc-bin.el
+++ b/lisp/calc/calc-bin.el
@@ -1,6 +1,6 @@
;;; calc-bin.el --- binary functions for Calc -*- lexical-binding:t -*-
-;; Copyright (C) 1990-1993, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1990-1993, 2001-2024 Free Software Foundation, Inc.
;; Author: David Gillespie <daveg@synaptics.com>
diff --git a/lisp/calc/calc-comb.el b/lisp/calc/calc-comb.el
index a1ebd68f571..8e8a0aee9c2 100644
--- a/lisp/calc/calc-comb.el
+++ b/lisp/calc/calc-comb.el
@@ -1,6 +1,6 @@
;;; calc-comb.el --- combinatoric functions for Calc -*- lexical-binding:t -*-
-;; Copyright (C) 1990-1993, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1990-1993, 2001-2024 Free Software Foundation, Inc.
;; Author: David Gillespie <daveg@synaptics.com>
diff --git a/lisp/calc/calc-cplx.el b/lisp/calc/calc-cplx.el
index 63e450d86bb..d5fe7a779f1 100644
--- a/lisp/calc/calc-cplx.el
+++ b/lisp/calc/calc-cplx.el
@@ -1,6 +1,6 @@
;;; calc-cplx.el --- Complex number functions for Calc -*- lexical-binding:t -*-
-;; Copyright (C) 1990-1993, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1990-1993, 2001-2024 Free Software Foundation, Inc.
;; Author: David Gillespie <daveg@synaptics.com>
diff --git a/lisp/calc/calc-embed.el b/lisp/calc/calc-embed.el
index 284d68adeeb..dad3f6a0ce1 100644
--- a/lisp/calc/calc-embed.el
+++ b/lisp/calc/calc-embed.el
@@ -1,6 +1,6 @@
;;; calc-embed.el --- embed Calc in a buffer -*- lexical-binding:t -*-
-;; Copyright (C) 1990-1993, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1990-1993, 2001-2024 Free Software Foundation, Inc.
;; Author: David Gillespie <daveg@synaptics.com>
diff --git a/lisp/calc/calc-ext.el b/lisp/calc/calc-ext.el
index 52c0fa4f69f..191149892a8 100644
--- a/lisp/calc/calc-ext.el
+++ b/lisp/calc/calc-ext.el
@@ -1,6 +1,6 @@
;;; calc-ext.el --- various extension functions for Calc -*- lexical-binding:t -*-
-;; Copyright (C) 1990-1993, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1990-1993, 2001-2024 Free Software Foundation, Inc.
;; Author: David Gillespie <daveg@synaptics.com>
diff --git a/lisp/calc/calc-fin.el b/lisp/calc/calc-fin.el
index 30da613f988..b14e95703ce 100644
--- a/lisp/calc/calc-fin.el
+++ b/lisp/calc/calc-fin.el
@@ -1,6 +1,6 @@
;;; calc-fin.el --- financial functions for Calc -*- lexical-binding:t -*-
-;; Copyright (C) 1990-1993, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1990-1993, 2001-2024 Free Software Foundation, Inc.
;; Author: David Gillespie <daveg@synaptics.com>
diff --git a/lisp/calc/calc-forms.el b/lisp/calc/calc-forms.el
index a75842ad172..c5d050444e3 100644
--- a/lisp/calc/calc-forms.el
+++ b/lisp/calc/calc-forms.el
@@ -1,6 +1,6 @@
;;; calc-forms.el --- data format conversion functions for Calc -*- lexical-binding:t -*-
-;; Copyright (C) 1990-1993, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1990-1993, 2001-2024 Free Software Foundation, Inc.
;; Author: David Gillespie <daveg@synaptics.com>
diff --git a/lisp/calc/calc-frac.el b/lisp/calc/calc-frac.el
index b57c1d6c760..d067ccc82fe 100644
--- a/lisp/calc/calc-frac.el
+++ b/lisp/calc/calc-frac.el
@@ -1,6 +1,6 @@
;;; calc-frac.el --- fraction functions for Calc -*- lexical-binding:t -*-
-;; Copyright (C) 1990-1993, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1990-1993, 2001-2024 Free Software Foundation, Inc.
;; Author: David Gillespie <daveg@synaptics.com>
diff --git a/lisp/calc/calc-funcs.el b/lisp/calc/calc-funcs.el
index cb9f7887ddc..62ac27c6dbd 100644
--- a/lisp/calc/calc-funcs.el
+++ b/lisp/calc/calc-funcs.el
@@ -1,6 +1,6 @@
;;; calc-funcs.el --- well-known functions for Calc -*- lexical-binding:t -*-
-;; Copyright (C) 1990-1993, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1990-1993, 2001-2024 Free Software Foundation, Inc.
;; Author: David Gillespie <daveg@synaptics.com>
diff --git a/lisp/calc/calc-graph.el b/lisp/calc/calc-graph.el
index 1b9d25daf3b..fb817b1bc3d 100644
--- a/lisp/calc/calc-graph.el
+++ b/lisp/calc/calc-graph.el
@@ -1,6 +1,6 @@
;;; calc-graph.el --- graph output functions for Calc -*- lexical-binding:t -*-
-;; Copyright (C) 1990-1993, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1990-1993, 2001-2024 Free Software Foundation, Inc.
;; Author: David Gillespie <daveg@synaptics.com>
diff --git a/lisp/calc/calc-help.el b/lisp/calc/calc-help.el
index 6b3e5cd64b1..6ba49137b73 100644
--- a/lisp/calc/calc-help.el
+++ b/lisp/calc/calc-help.el
@@ -1,6 +1,6 @@
;;; calc-help.el --- help display functions for Calc -*- lexical-binding:t -*-
-;; Copyright (C) 1990-1993, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1990-1993, 2001-2024 Free Software Foundation, Inc.
;; Author: David Gillespie <daveg@synaptics.com>
diff --git a/lisp/calc/calc-incom.el b/lisp/calc/calc-incom.el
index 16cb991dfa6..d94c8a99593 100644
--- a/lisp/calc/calc-incom.el
+++ b/lisp/calc/calc-incom.el
@@ -1,6 +1,6 @@
;;; calc-incom.el --- complex data type input functions for Calc -*- lexical-binding:t -*-
-;; Copyright (C) 1990-1993, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1990-1993, 2001-2024 Free Software Foundation, Inc.
;; Author: David Gillespie <daveg@synaptics.com>
diff --git a/lisp/calc/calc-keypd.el b/lisp/calc/calc-keypd.el
index 060099b8892..1e079bba37f 100644
--- a/lisp/calc/calc-keypd.el
+++ b/lisp/calc/calc-keypd.el
@@ -1,6 +1,6 @@
;;; calc-keypd.el --- mouse-capable keypad input for Calc -*- lexical-binding:t -*-
-;; Copyright (C) 1990-1993, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1990-1993, 2001-2024 Free Software Foundation, Inc.
;; Author: David Gillespie <daveg@synaptics.com>
diff --git a/lisp/calc/calc-lang.el b/lisp/calc/calc-lang.el
index f2d8aaa20a7..94133efdca9 100644
--- a/lisp/calc/calc-lang.el
+++ b/lisp/calc/calc-lang.el
@@ -1,6 +1,6 @@
;;; calc-lang.el --- calc language functions -*- lexical-binding:t -*-
-;; Copyright (C) 1990-1993, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1990-1993, 2001-2024 Free Software Foundation, Inc.
;; Author: David Gillespie <daveg@synaptics.com>
diff --git a/lisp/calc/calc-macs.el b/lisp/calc/calc-macs.el
index 9421f74a8ed..ffb876dd45f 100644
--- a/lisp/calc/calc-macs.el
+++ b/lisp/calc/calc-macs.el
@@ -1,6 +1,6 @@
;;; calc-macs.el --- important macros for Calc -*- lexical-binding:t -*-
-;; Copyright (C) 1990-1993, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1990-1993, 2001-2024 Free Software Foundation, Inc.
;; Author: David Gillespie <daveg@synaptics.com>
diff --git a/lisp/calc/calc-map.el b/lisp/calc/calc-map.el
index 7496537494b..f8dad435c75 100644
--- a/lisp/calc/calc-map.el
+++ b/lisp/calc/calc-map.el
@@ -1,6 +1,6 @@
;;; calc-map.el --- higher-order functions for Calc -*- lexical-binding:t -*-
-;; Copyright (C) 1990-1993, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1990-1993, 2001-2024 Free Software Foundation, Inc.
;; Author: David Gillespie <daveg@synaptics.com>
diff --git a/lisp/calc/calc-math.el b/lisp/calc/calc-math.el
index 7b4c14efad0..64820149eff 100644
--- a/lisp/calc/calc-math.el
+++ b/lisp/calc/calc-math.el
@@ -1,6 +1,6 @@
;;; calc-math.el --- mathematical functions for Calc -*- lexical-binding:t -*-
-;; Copyright (C) 1990-1993, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1990-1993, 2001-2024 Free Software Foundation, Inc.
;; Author: David Gillespie <daveg@synaptics.com>
diff --git a/lisp/calc/calc-menu.el b/lisp/calc/calc-menu.el
index bc6bb761f26..2329803d76e 100644
--- a/lisp/calc/calc-menu.el
+++ b/lisp/calc/calc-menu.el
@@ -1,6 +1,6 @@
;;; calc-menu.el --- a menu for Calc -*- lexical-binding:t -*-
-;; Copyright (C) 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/lisp/calc/calc-misc.el b/lisp/calc/calc-misc.el
index 4b1aab837af..8c692ac006c 100644
--- a/lisp/calc/calc-misc.el
+++ b/lisp/calc/calc-misc.el
@@ -1,6 +1,6 @@
;;; calc-misc.el --- miscellaneous functions for Calc -*- lexical-binding:t -*-
-;; Copyright (C) 1990-1993, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1990-1993, 2001-2024 Free Software Foundation, Inc.
;; Author: David Gillespie <daveg@synaptics.com>
diff --git a/lisp/calc/calc-mode.el b/lisp/calc/calc-mode.el
index 71a0171e7de..32ce4123e98 100644
--- a/lisp/calc/calc-mode.el
+++ b/lisp/calc/calc-mode.el
@@ -1,6 +1,6 @@
;;; calc-mode.el --- calculator modes for Calc -*- lexical-binding:t -*-
-;; Copyright (C) 1990-1993, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1990-1993, 2001-2024 Free Software Foundation, Inc.
;; Author: David Gillespie <daveg@synaptics.com>
diff --git a/lisp/calc/calc-mtx.el b/lisp/calc/calc-mtx.el
index 0a5f2a2c208..3ce2f9dff2b 100644
--- a/lisp/calc/calc-mtx.el
+++ b/lisp/calc/calc-mtx.el
@@ -1,6 +1,6 @@
;;; calc-mtx.el --- matrix functions for Calc -*- lexical-binding:t -*-
-;; Copyright (C) 1990-1993, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1990-1993, 2001-2024 Free Software Foundation, Inc.
;; Author: David Gillespie <daveg@synaptics.com>
diff --git a/lisp/calc/calc-nlfit.el b/lisp/calc/calc-nlfit.el
index 72b906ff69b..6dd3f3e7f63 100644
--- a/lisp/calc/calc-nlfit.el
+++ b/lisp/calc/calc-nlfit.el
@@ -1,6 +1,6 @@
;;; calc-nlfit.el --- nonlinear curve fitting for Calc -*- lexical-binding:t -*-
-;; Copyright (C) 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/lisp/calc/calc-poly.el b/lisp/calc/calc-poly.el
index c32b5be5849..c5a7ee66cc8 100644
--- a/lisp/calc/calc-poly.el
+++ b/lisp/calc/calc-poly.el
@@ -1,6 +1,6 @@
;;; calc-poly.el --- polynomial functions for Calc -*- lexical-binding:t -*-
-;; Copyright (C) 1990-1993, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1990-1993, 2001-2024 Free Software Foundation, Inc.
;; Author: David Gillespie <daveg@synaptics.com>
diff --git a/lisp/calc/calc-prog.el b/lisp/calc/calc-prog.el
index 8502b5196d2..03210995eb3 100644
--- a/lisp/calc/calc-prog.el
+++ b/lisp/calc/calc-prog.el
@@ -1,6 +1,6 @@
;;; calc-prog.el --- user programmability functions for Calc -*- lexical-binding:t -*-
-;; Copyright (C) 1990-1993, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1990-1993, 2001-2024 Free Software Foundation, Inc.
;; Author: David Gillespie <daveg@synaptics.com>
diff --git a/lisp/calc/calc-rewr.el b/lisp/calc/calc-rewr.el
index b7b3b7b16d4..cc70ded17c2 100644
--- a/lisp/calc/calc-rewr.el
+++ b/lisp/calc/calc-rewr.el
@@ -1,6 +1,6 @@
;;; calc-rewr.el --- rewriting functions for Calc -*- lexical-binding:t -*-
-;; Copyright (C) 1990-1993, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1990-1993, 2001-2024 Free Software Foundation, Inc.
;; Author: David Gillespie <daveg@synaptics.com>
diff --git a/lisp/calc/calc-rules.el b/lisp/calc/calc-rules.el
index 2d012d7ff63..da34c03ad05 100644
--- a/lisp/calc/calc-rules.el
+++ b/lisp/calc/calc-rules.el
@@ -1,6 +1,6 @@
;;; calc-rules.el --- rules for simplifying algebraic expressions in Calc -*- lexical-binding:t -*-
-;; Copyright (C) 1990-1993, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1990-1993, 2001-2024 Free Software Foundation, Inc.
;; Author: David Gillespie <daveg@synaptics.com>
diff --git a/lisp/calc/calc-sel.el b/lisp/calc/calc-sel.el
index 8d020d02aa7..1a14cd418c3 100644
--- a/lisp/calc/calc-sel.el
+++ b/lisp/calc/calc-sel.el
@@ -1,6 +1,6 @@
;;; calc-sel.el --- data selection functions for Calc -*- lexical-binding:t -*-
-;; Copyright (C) 1990-1993, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1990-1993, 2001-2024 Free Software Foundation, Inc.
;; Author: David Gillespie <daveg@synaptics.com>
diff --git a/lisp/calc/calc-stat.el b/lisp/calc/calc-stat.el
index bc5d575f257..e4f101acf19 100644
--- a/lisp/calc/calc-stat.el
+++ b/lisp/calc/calc-stat.el
@@ -1,6 +1,6 @@
;;; calc-stat.el --- statistical functions for Calc -*- lexical-binding:t -*-
-;; Copyright (C) 1990-1993, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1990-1993, 2001-2024 Free Software Foundation, Inc.
;; Author: David Gillespie <daveg@synaptics.com>
diff --git a/lisp/calc/calc-store.el b/lisp/calc/calc-store.el
index 97d1a76d0dc..df584760606 100644
--- a/lisp/calc/calc-store.el
+++ b/lisp/calc/calc-store.el
@@ -1,6 +1,6 @@
;;; calc-store.el --- value storage functions for Calc -*- lexical-binding:t -*-
-;; Copyright (C) 1990-1993, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1990-1993, 2001-2024 Free Software Foundation, Inc.
;; Author: David Gillespie <daveg@synaptics.com>
diff --git a/lisp/calc/calc-stuff.el b/lisp/calc/calc-stuff.el
index 595fef85224..8ecb208138c 100644
--- a/lisp/calc/calc-stuff.el
+++ b/lisp/calc/calc-stuff.el
@@ -1,6 +1,6 @@
;;; calc-stuff.el --- miscellaneous functions for Calc -*- lexical-binding:t -*-
-;; Copyright (C) 1990-1993, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1990-1993, 2001-2024 Free Software Foundation, Inc.
;; Author: David Gillespie <daveg@synaptics.com>
diff --git a/lisp/calc/calc-trail.el b/lisp/calc/calc-trail.el
index 945de4ae493..6678bc6bfc1 100644
--- a/lisp/calc/calc-trail.el
+++ b/lisp/calc/calc-trail.el
@@ -1,6 +1,6 @@
;;; calc-trail.el --- functions for manipulating the Calc "trail" -*- lexical-binding:t -*-
-;; Copyright (C) 1990-1993, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1990-1993, 2001-2024 Free Software Foundation, Inc.
;; Author: David Gillespie <daveg@synaptics.com>
diff --git a/lisp/calc/calc-undo.el b/lisp/calc/calc-undo.el
index cb6254f4ab6..65db157759b 100644
--- a/lisp/calc/calc-undo.el
+++ b/lisp/calc/calc-undo.el
@@ -1,6 +1,6 @@
;;; calc-undo.el --- undo functions for Calc -*- lexical-binding:t -*-
-;; Copyright (C) 1990-1993, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1990-1993, 2001-2024 Free Software Foundation, Inc.
;; Author: David Gillespie <daveg@synaptics.com>
diff --git a/lisp/calc/calc-units.el b/lisp/calc/calc-units.el
index 988fef2fcd2..fba2b9c50fb 100644
--- a/lisp/calc/calc-units.el
+++ b/lisp/calc/calc-units.el
@@ -1,6 +1,6 @@
;;; calc-units.el --- unit conversion functions for Calc -*- lexical-binding:t -*-
-;; Copyright (C) 1990-1993, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1990-1993, 2001-2024 Free Software Foundation, Inc.
;; Author: David Gillespie <daveg@synaptics.com>
@@ -32,7 +32,7 @@
;;; Units operations.
-;;; Units table last updated 9-Jan-91 by Ulrich Mueller (ulm@vsnhd1.cern.ch)
+;;; Units table last updated 9-Jan-91 by Ulrich Müller (ulm@vsnhd1.cern.ch)
;;; with some additions by Przemek Klosowski (przemek@rrdstrad.nist.gov)
;;; Updated April 2002 by Jochen Küpper
@@ -43,11 +43,12 @@
;;; Measures, by François Cardarelli)
;;; All conversions are exact unless otherwise noted.
-;; CODATA values updated February 2016, using 2014 adjustment
-;; https://arxiv.org/pdf/1507.07956.pdf
-
;; Updated November 2018 for the redefinition of the SI
-;; https://www.bipm.org/utils/en/pdf/CGPM/Draft-Resolution-A-EN.pdf
+;; https://www.bipm.org/en/committees/cg/cgpm/26-2018/resolution-1
+
+;; CODATA values last updated November 2023, using 2018 adjustment:
+;; E. Tiesinga, P. J. Mohr, D. B. Newell, and B. N. Taylor,
+;; Rev. Mod. Phys. 93, 025010 (2021)
(defvar math-standard-units
'( ;; Length
@@ -57,12 +58,13 @@
( ft "12 in" "Foot")
( yd "3 ft" "Yard" )
( mi "5280 ft" "Mile" )
- ( au "149597870691. m" "Astronomical Unit" nil
- "149597870691 m (*)")
- ;; (approx) NASA JPL (https://neo.jpl.nasa.gov/glossary/au.html)
+ ( au "149597870700 m" "Astronomical Unit")
+ ;; "149 597 870 700 m exactly"
+ ;; http://www.iau.org/static/resolutions/IAU2012_English.pdf
( lyr "c yr" "Light Year" )
- ( pc "3.0856775854*10^16 m" "Parsec (**)" nil
- "3.0856775854 10^16 m (*)") ;; (approx) ESUWM
+ ( pc "(648000/pi) au" "Parsec (**)")
+ ;; "The parsec is defined as exactly (648 000/π) au"
+ ;; http://www.iau.org/static/resolutions/IAU2015_English.pdf
( nmi "1852 m" "Nautical Mile" )
( fath "6 ft" "Fathom" )
( fur "660 ft" "Furlong")
@@ -121,7 +123,6 @@
( mph "mi/hr" "*Miles per hour" )
( kph "km/hr" "Kilometers per hour" )
( knot "nmi/hr" "Knot" )
- ( c "299792458 m/s" "Speed of light" ) ;; SI definition
;; Acceleration
( ga "980665*10^(-5) m/s^2" "*\"g\" acceleration" nil
@@ -142,8 +143,8 @@
"31.10347680 g") ;; ESUWM, 1/12 exact value for lbt
( ct "(2/10) g" "Carat" nil
"0.2 g") ;; ESUWM
- ( u "1.660539040*10^(-27) kg" "Unified atomic mass" nil
- "1.660539040 10^-27 kg (*)");;(approx) CODATA
+ ( u "1.66053906660*10^(-27) kg" "Unified atomic mass" nil
+ "1.66053906660 10^-27 kg (*)") ;; (approx) CODATA
;; Force
( N "m kg/s^2" "*Newton" )
@@ -181,9 +182,9 @@
( hpm "75 m kgf/s" "Metric Horsepower") ;;ESUWM
;; Temperature
- ( K nil "*Degree Kelvin" K )
- ( dK "K" "Degree Kelvin" K )
- ( degK "K" "Degree Kelvin" K )
+ ( K nil "*Kelvin" K )
+ ;; FIXME: Add °C and °F, but it requires that we sort out input etc for
+ ;; the ° sign.
( dC "K" "Degree Celsius" C )
( degC "K" "Degree Celsius" C )
( dF "(5/9) K" "Degree Fahrenheit" F )
@@ -209,9 +210,6 @@
( A nil "*Ampere" )
( C "A s" "Coulomb" )
( Fdy "ech Nav" "Faraday" )
- ( e "ech" "Elementary charge" )
- ( ech "1.602176634*10^(-19) C" "Elementary charge" nil
- "1.602176634 10^-19 C") ;; SI definition
( V "W/A" "Volt" )
( ohm "V/A" "Ohm" )
( Ω "ohm" "Ohm" )
@@ -258,57 +256,81 @@
;; Solid angle
( sr nil "*Steradian" )
+ ;; Constants defining the International System of Units (SI)
+ ( c "299792458 m/s" "*Speed of light" )
+ ( h "6.62607015*10^(-34) J s" "Planck constant" nil
+ "6.62607015 10^-34 J s")
+ ( ech "1.602176634*10^(-19) C" "Elementary charge" nil
+ "1.602176634 10^-19 C")
+ ( e "ech" "Elementary charge" nil
+ "1.602176634 10^-19 C")
+ ( k "1.380649*10^(-23) J/K" "Boltzmann constant" nil
+ "1.380649 10^-23 J/K")
+ ( Nav "6.02214076*10^(23) / mol" "Avogadro constant" nil
+ "6.02214076 10^23 / mol")
+
;; Other physical quantities
;; Unless otherwise mentioned, the values are from CODATA,
;; and are approximate.
- ( h "6.62607015*10^(-34) J s" "*Planck's constant" nil
- "6.62607015 10^-34 J s") ;; SI definition
- ( hbar "h / (2 pi)" "Planck's constant" ) ;; Exact
+ ( hbar "h / (2 pi)" "*Reduced Planck constant" )
;; After the 2018 SI redefinition, eps0 and mu0 are measured quantities,
;; and mu0 no longer has the previous exact value of 4 pi 10^(-7) H/m.
( eps0 "ech^2 / (2 alpha h c)" "Permittivity of vacuum" )
( ε0 "eps0" "Permittivity of vacuum" )
- ( mu0 "1 / (eps0 c^2)" "Permeability of vacuum") ;; Exact
- ( μ0 "mu0" "Permeability of vacuum") ;; Exact
- ( G "6.67408*10^(-11) m^3/(kg s^2)" "Gravitational constant" nil
- "6.67408 10^-11 m^3/(kg s^2) (*)")
- ( Nav "6.02214076*10^(23) / mol" "Avogadro's constant" nil
- "6.02214076 10^23 / mol") ;; SI definition
- ( me "9.10938356*10^(-31) kg" "Electron rest mass" nil
- "9.10938356 10^-31 kg (*)")
- ( mp "1.672621898*10^(-27) kg" "Proton rest mass" nil
- "1.672621898 10^-27 kg (*)")
- ( mn "1.674927471*10^(-27) kg" "Neutron rest mass" nil
- "1.674927471 10^-27 kg (*)")
- ( mmu "1.883531594*10^(-28) kg" "Muon rest mass" nil
- "1.883531594 10^-28 kg (*)")
+ ( mu0 "1 / (eps0 c^2)" "Permeability of vacuum")
+ ( μ0 "mu0" "Permeability of vacuum")
+ ( G "6.67430*10^(-11) m^3/(kg s^2)" "Gravitational constant" nil
+ "6.67430 10^-11 m^3/(kg s^2) (*)")
+ ( me "9.1093837015*10^(-31) kg" "Electron rest mass" nil
+ "9.1093837015 10^-31 kg (*)")
+ ( mp "1.67262192369*10^(-27) kg" "Proton rest mass" nil
+ "1.67262192369 10^-27 kg (*)")
+ ( mn "1.67492749804*10^(-27) kg" "Neutron rest mass" nil
+ "1.67492749804 10^-27 kg (*)")
+ ( mmu "1.883531627*10^(-28) kg" "Muon rest mass" nil
+ "1.883531627 10^-28 kg (*)")
( mμ "mmu" "Muon rest mass" nil
- "1.883531594 10^-28 kg (*)")
- ( Ryd "10973731.568508 /m" "Rydberg's constant" nil
- "10973731.568508 /m (*)")
- ( k "1.380649*10^(-23) J/K" "Boltzmann's constant" nil
- "1.380649 10^-23 J/K") ;; SI definition
+ "1.883531627 10^-28 kg (*)")
+ ( Ryd "10973731.568160 /m" "Rydberg constant" nil
+ "10973731.568160 /m (*)")
( sigma "2 pi^5 k^4 / (15 h^3 c^2)" "Stefan-Boltzmann constant")
( σ "sigma" "Stefan-Boltzmann constant")
- ( alpha "7.2973525664*10^(-3)" "Fine structure constant" nil
- "7.2973525664 10^-3 (*)")
- ( α "alpha" "Fine structure constant" nil
- "7.2973525664 10^-3 (*)")
- ( muB "927.4009994*10^(-26) J/T" "Bohr magneton" nil
- "927.4009994 10^-26 J/T (*)")
- ( muN "5.050783699*10^(-27) J/T" "Nuclear magneton" nil
- "5.050783699 10^-27 J/T (*)")
- ( mue "-928.4764620*10^(-26) J/T" "Electron magnetic moment" nil
- "-928.4764620 10^-26 J/T (*)")
- ( mup "1.4106067873*10^(-26) J/T" "Proton magnetic moment" nil
- "1.4106067873 10^-26 J/T (*)")
- ( R0 "Nav k" "Molar gas constant") ;; Exact
- ( V0 "22.710947*10^(-3) m^3/mol" "Standard volume of ideal gas" nil
- "22.710947 10^-3 m^3/mol (*)")
+ ( alpha "7.2973525693*10^(-3)" "Fine structure constant" nil
+ "7.2973525693 10^-3 (*)")
+ ( α "alpha" "Fine structure constant" nil
+ "7.2973525693 10^-3 (*)")
+ ( muB "9.2740100783*10^(-24) J/T" "Bohr magneton" nil
+ "9.2740100783 10^-24 J/T (*)")
+ ( muN "5.0507837461*10^(-27) J/T" "Nuclear magneton" nil
+ "5.0507837461 10^-27 J/T (*)")
+ ( mue "-9.2847647043*10^(-24) J/T" "Electron magnetic moment" nil
+ "-9.2847647043 10^-24 J/T (*)")
+ ( mup "1.41060679736*10^(-26) J/T" "Proton magnetic moment" nil
+ "1.41060679736 10^-26 J/T (*)")
+ ( R0 "Nav k" "Molar gas constant" )
+ ( V0 "R0 273.15 K / 10^5 Pa" "Standard volume of ideal gas" )
+ ;; IUPAC 1982 standard temperature and pressure
+
;; Logarithmic units
( Np nil "*Neper")
- ( dB "(ln(10)/20) Np" "decibel")))
-
+ ( dB "(ln(10)/20) Np" "decibel"))
+ "List of predefined units for Calc.
+
+Each element is (NAME DEF DESC TEMP-UNIT HUMAN-DEF), where:
+
+NAME is the unit symbol.
+DEF is a string defining the unit as a Calc expression; nil if base unit.
+DESC is a string describing the unit (to a human reader).
+ A leading asterisk indicates that the unit is first in its group.
+TEMP-UNIT is `K', `C' or `F' for temperature units and is used to identify
+ the unit when doing absolute temperature conversion
+ (`calc-convert-temperature'). For other units, nil.
+HUMAN-DEF is a string defining the unit (to a human reader).
+ If absent or nil, DEF is used.
+
+(*) in HUMAN-DEF means that the definition is approximate, otherwise exact.
+(**) in DESC means that the unit name is different in TeX and LaTeX
+ display modes.")
(defvar math-additional-units nil
"Additional units table for user-defined units.
diff --git a/lisp/calc/calc-vec.el b/lisp/calc/calc-vec.el
index 90239d58808..39ac6fa0347 100644
--- a/lisp/calc/calc-vec.el
+++ b/lisp/calc/calc-vec.el
@@ -1,6 +1,6 @@
;;; calc-vec.el --- vector functions for Calc -*- lexical-binding:t -*-
-;; Copyright (C) 1990-1993, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1990-1993, 2001-2024 Free Software Foundation, Inc.
;; Author: David Gillespie <daveg@synaptics.com>
diff --git a/lisp/calc/calc-yank.el b/lisp/calc/calc-yank.el
index a2a91dc8fb8..0f9e8f09019 100644
--- a/lisp/calc/calc-yank.el
+++ b/lisp/calc/calc-yank.el
@@ -1,6 +1,6 @@
;;; calc-yank.el --- kill-ring functionality for Calc -*- lexical-binding:t -*-
-;; Copyright (C) 1990-1993, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1990-1993, 2001-2024 Free Software Foundation, Inc.
;; Author: David Gillespie <daveg@synaptics.com>
diff --git a/lisp/calc/calc.el b/lisp/calc/calc.el
index 652cb8c1a88..e6448625cee 100644
--- a/lisp/calc/calc.el
+++ b/lisp/calc/calc.el
@@ -1,6 +1,6 @@
;;; calc.el --- the GNU Emacs calculator -*- lexical-binding:t -*-
-;; Copyright (C) 1990-1993, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1990-1993, 2001-2024 Free Software Foundation, Inc.
;; Author: David Gillespie <daveg@synaptics.com>
;; Keywords: convenience, extensions
@@ -906,6 +906,8 @@ Used by `calc-user-invocation'.")
(defvar calc-embedded-mode-hook nil
"Hook run when starting embedded mode.")
+(defvar calc-eval-error)
+
;; The following modes use specially-formatted data.
(put 'calc-mode 'mode-class 'special)
@@ -1283,6 +1285,8 @@ the trail buffer."
(setq calc-trail-buffer nil)
t))))
+(defvar touch-screen-display-keyboard)
+
(defun calc-mode ()
"Calculator major mode.
@@ -2489,7 +2493,7 @@ the United States."
(defun calcDigit-backspace ()
(interactive)
(cond ((eq last-command 'calcDigit-start)
- (erase-buffer))
+ (delete-minibuffer-contents))
(t (with-suppressed-warnings ((interactive-only backward-delete-char))
(backward-delete-char 1))))
(if (= (calc-minibuffer-size) 0)
diff --git a/lisp/calc/calcalg2.el b/lisp/calc/calcalg2.el
index e60c4539608..5e9ae8a3e5a 100644
--- a/lisp/calc/calcalg2.el
+++ b/lisp/calc/calcalg2.el
@@ -1,6 +1,6 @@
;;; calcalg2.el --- more algebraic functions for Calc -*- lexical-binding:t -*-
-;; Copyright (C) 1990-1993, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1990-1993, 2001-2024 Free Software Foundation, Inc.
;; Author: David Gillespie <daveg@synaptics.com>
diff --git a/lisp/calc/calcalg3.el b/lisp/calc/calcalg3.el
index af0daa55309..26952b8b10c 100644
--- a/lisp/calc/calcalg3.el
+++ b/lisp/calc/calcalg3.el
@@ -1,6 +1,6 @@
;;; calcalg3.el --- more algebraic functions for Calc -*- lexical-binding:t -*-
-;; Copyright (C) 1990-1993, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1990-1993, 2001-2024 Free Software Foundation, Inc.
;; Author: David Gillespie <daveg@synaptics.com>
diff --git a/lisp/calc/calccomp.el b/lisp/calc/calccomp.el
index c42e62853ed..9d9e9383c32 100644
--- a/lisp/calc/calccomp.el
+++ b/lisp/calc/calccomp.el
@@ -1,6 +1,6 @@
;;; calccomp.el --- composition functions for Calc -*- lexical-binding:t -*-
-;; Copyright (C) 1990-1993, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1990-1993, 2001-2024 Free Software Foundation, Inc.
;; Author: David Gillespie <daveg@synaptics.com>
diff --git a/lisp/calc/calcsel2.el b/lisp/calc/calcsel2.el
index 8935511db6e..bf62b7e1447 100644
--- a/lisp/calc/calcsel2.el
+++ b/lisp/calc/calcsel2.el
@@ -1,6 +1,6 @@
;;; calcsel2.el --- selection functions for Calc -*- lexical-binding:t -*-
-;; Copyright (C) 1990-1993, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1990-1993, 2001-2024 Free Software Foundation, Inc.
;; Author: David Gillespie <daveg@synaptics.com>
diff --git a/lisp/calculator.el b/lisp/calculator.el
index 00afa2457fe..ef1e6d8dbc3 100644
--- a/lisp/calculator.el
+++ b/lisp/calculator.el
@@ -1,6 +1,6 @@
;;; calculator.el --- a calculator for Emacs -*- lexical-binding: t -*-
-;; Copyright (C) 1998, 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998, 2000-2024 Free Software Foundation, Inc.
;; Author: Eli Barzilay <eli@barzilay.org>
;; Keywords: tools, convenience
diff --git a/lisp/calendar/appt.el b/lisp/calendar/appt.el
index 11beee94e64..7572e706283 100644
--- a/lisp/calendar/appt.el
+++ b/lisp/calendar/appt.el
@@ -1,6 +1,6 @@
;;; appt.el --- appointment notification functions -*- lexical-binding:t -*-
-;; Copyright (C) 1989-1990, 1994, 1998, 2001-2023 Free Software
+;; Copyright (C) 1989-1990, 1994, 1998, 2001-2024 Free Software
;; Foundation, Inc.
;; Author: Neil Mager <neilm@juliet.ll.mit.edu>
@@ -165,6 +165,12 @@ Only relevant if reminders are being displayed in a window."
:type 'function
:group 'appt)
+(defface appt-notification
+ '((t :inherit mode-line-emphasis))
+ "Face for appointment notification on the modeline.
+Shown when `appt-display-mode-line' is non-nil."
+ :group 'mode-line-faces
+ :version "30.1")
;;; Internal variables below this point.
@@ -406,7 +412,7 @@ displayed in a window:
(appt-mode-line (mapcar #'number-to-string
min-list)
t)
- 'face 'mode-line-emphasis)
+ 'face 'appt-notification)
" ")))
;; Reset count to 0 in case we display another appt on the next cycle.
(setq appt-display-count (if (equal '(0) min-list) 0
@@ -453,8 +459,7 @@ separate appointment."
;; It repeatedly reminds you of the date?
;; It would make more sense if it was eg the time of the appointment.
;; Let's allow it to be a list or not independent of the other elements.
- (or (listp new-time)
- (setq new-time (list new-time)))
+ (setq new-time (ensure-list new-time))
;; FIXME Link to diary entry?
(calendar-set-mode-line
(format " %s. %s" (appt-mode-line min-to-app)
diff --git a/lisp/calendar/cal-bahai.el b/lisp/calendar/cal-bahai.el
index 202c38916a9..0934f926d53 100644
--- a/lisp/calendar/cal-bahai.el
+++ b/lisp/calendar/cal-bahai.el
@@ -1,6 +1,6 @@
;;; cal-bahai.el --- calendar functions for the Bahá’í calendar. -*- lexical-binding: t; -*-
-;; Copyright (C) 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2024 Free Software Foundation, Inc.
;; Author: John Wiegley <johnw@gnu.org>
;; Keywords: calendar
diff --git a/lisp/calendar/cal-china.el b/lisp/calendar/cal-china.el
index b31d056941c..8145b99182e 100644
--- a/lisp/calendar/cal-china.el
+++ b/lisp/calendar/cal-china.el
@@ -1,6 +1,6 @@
;;; cal-china.el --- calendar functions for the Chinese calendar -*- lexical-binding: t; -*-
-;; Copyright (C) 1995, 1997, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1995, 1997, 2001-2024 Free Software Foundation, Inc.
;; Author: Edward M. Reingold <reingold@cs.uiuc.edu>
;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/calendar/cal-coptic.el b/lisp/calendar/cal-coptic.el
index 123b1f11f55..1700d1c262b 100644
--- a/lisp/calendar/cal-coptic.el
+++ b/lisp/calendar/cal-coptic.el
@@ -1,6 +1,6 @@
;;; cal-coptic.el --- calendar functions for the Coptic/Ethiopic calendars -*- lexical-binding: t; -*-
-;; Copyright (C) 1995, 1997, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1995, 1997, 2001-2024 Free Software Foundation, Inc.
;; Author: Edward M. Reingold <reingold@cs.uiuc.edu>
;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/calendar/cal-dst.el b/lisp/calendar/cal-dst.el
index a96fb0adf7c..b54738c464f 100644
--- a/lisp/calendar/cal-dst.el
+++ b/lisp/calendar/cal-dst.el
@@ -1,6 +1,6 @@
;;; cal-dst.el --- calendar functions for daylight saving rules -*- lexical-binding:t -*-
-;; Copyright (C) 1993-1996, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1993-1996, 2001-2024 Free Software Foundation, Inc.
;; Author: Paul Eggert <eggert@cs.ucla.edu>
;; Edward M. Reingold <reingold@cs.uiuc.edu>
diff --git a/lisp/calendar/cal-french.el b/lisp/calendar/cal-french.el
index cc523c28f49..fcc0d44c7c8 100644
--- a/lisp/calendar/cal-french.el
+++ b/lisp/calendar/cal-french.el
@@ -1,6 +1,6 @@
;;; cal-french.el --- calendar functions for the French Revolutionary calendar -*- lexical-binding: t; -*-
-;; Copyright (C) 1988-1989, 1992, 1994-1995, 1997, 2001-2023 Free
+;; Copyright (C) 1988-1989, 1992, 1994-1995, 1997, 2001-2024 Free
;; Software Foundation, Inc.
;; Author: Edward M. Reingold <reingold@cs.uiuc.edu>
diff --git a/lisp/calendar/cal-hebrew.el b/lisp/calendar/cal-hebrew.el
index b6c60185029..fea8e957e46 100644
--- a/lisp/calendar/cal-hebrew.el
+++ b/lisp/calendar/cal-hebrew.el
@@ -1,6 +1,6 @@
;;; cal-hebrew.el --- calendar functions for the Hebrew calendar -*- lexical-binding: t; -*-
-;; Copyright (C) 1995, 1997, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1995, 1997, 2001-2024 Free Software Foundation, Inc.
;; Author: Nachum Dershowitz <nachum@cs.uiuc.edu>
;; Edward M. Reingold <reingold@cs.uiuc.edu>
diff --git a/lisp/calendar/cal-html.el b/lisp/calendar/cal-html.el
index c85c476a109..919b3d5918f 100644
--- a/lisp/calendar/cal-html.el
+++ b/lisp/calendar/cal-html.el
@@ -1,6 +1,6 @@
;;; cal-html.el --- functions for printing HTML calendars -*- lexical-binding: t; -*-
-;; Copyright (C) 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2024 Free Software Foundation, Inc.
;; Author: Anna M. Bigatti <bigatti@dima.unige.it>
;; Keywords: calendar
diff --git a/lisp/calendar/cal-islam.el b/lisp/calendar/cal-islam.el
index 172e54edca6..9fb3fd631bd 100644
--- a/lisp/calendar/cal-islam.el
+++ b/lisp/calendar/cal-islam.el
@@ -1,6 +1,6 @@
;;; cal-islam.el --- calendar functions for the Islamic calendar -*- lexical-binding: t; -*-
-;; Copyright (C) 1995, 1997, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1995, 1997, 2001-2024 Free Software Foundation, Inc.
;; Author: Edward M. Reingold <reingold@cs.uiuc.edu>
;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/calendar/cal-iso.el b/lisp/calendar/cal-iso.el
index a4a3e585745..37b3f1d93cc 100644
--- a/lisp/calendar/cal-iso.el
+++ b/lisp/calendar/cal-iso.el
@@ -1,6 +1,6 @@
;;; cal-iso.el --- calendar functions for the ISO calendar -*- lexical-binding: t; -*-
-;; Copyright (C) 1995, 1997, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1995, 1997, 2001-2024 Free Software Foundation, Inc.
;; Author: Edward M. Reingold <reingold@cs.uiuc.edu>
;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/calendar/cal-julian.el b/lisp/calendar/cal-julian.el
index f45150455b0..1ae4049890e 100644
--- a/lisp/calendar/cal-julian.el
+++ b/lisp/calendar/cal-julian.el
@@ -1,6 +1,6 @@
;;; cal-julian.el --- calendar functions for the Julian calendar -*- lexical-binding:t -*-
-;; Copyright (C) 1995, 1997, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1995, 1997, 2001-2024 Free Software Foundation, Inc.
;; Author: Edward M. Reingold <reingold@cs.uiuc.edu>
;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/calendar/cal-mayan.el b/lisp/calendar/cal-mayan.el
index 8ec867454ff..e62e9d10ccf 100644
--- a/lisp/calendar/cal-mayan.el
+++ b/lisp/calendar/cal-mayan.el
@@ -1,6 +1,6 @@
;;; cal-mayan.el --- calendar functions for the Mayan calendars -*- lexical-binding: t; -*-
-;; Copyright (C) 1992-1993, 1995, 1997, 2001-2023 Free Software
+;; Copyright (C) 1992-1993, 1995, 1997, 2001-2024 Free Software
;; Foundation, Inc.
;; Author: Stewart M. Clamen <clamen@cs.cmu.edu>
diff --git a/lisp/calendar/cal-menu.el b/lisp/calendar/cal-menu.el
index edf5534581c..b63c931f7c6 100644
--- a/lisp/calendar/cal-menu.el
+++ b/lisp/calendar/cal-menu.el
@@ -1,6 +1,6 @@
;;; cal-menu.el --- calendar functions for menu bar and popup menu support -*- lexical-binding: t; -*-
-;; Copyright (C) 1994-1995, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1994-1995, 2001-2024 Free Software Foundation, Inc.
;; Author: Edward M. Reingold <reingold@cs.uiuc.edu>
;; Lara Rios <lrios@coewl.cen.uiuc.edu>
diff --git a/lisp/calendar/cal-move.el b/lisp/calendar/cal-move.el
index b494659a8ee..4a486d1cde7 100644
--- a/lisp/calendar/cal-move.el
+++ b/lisp/calendar/cal-move.el
@@ -1,6 +1,6 @@
;;; cal-move.el --- calendar functions for movement in the calendar -*- lexical-binding: t; -*-
-;; Copyright (C) 1995, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1995, 2001-2024 Free Software Foundation, Inc.
;; Author: Edward M. Reingold <reingold@cs.uiuc.edu>
;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/calendar/cal-persia.el b/lisp/calendar/cal-persia.el
index 822f2153c50..d01881f0a13 100644
--- a/lisp/calendar/cal-persia.el
+++ b/lisp/calendar/cal-persia.el
@@ -1,6 +1,6 @@
;;; cal-persia.el --- calendar functions for the Persian calendar -*- lexical-binding: t; -*-
-;; Copyright (C) 1996-1997, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-1997, 2001-2024 Free Software Foundation, Inc.
;; Author: Edward M. Reingold <reingold@cs.uiuc.edu>
;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/calendar/cal-tex.el b/lisp/calendar/cal-tex.el
index 8399d77b4c4..ea396329e4c 100644
--- a/lisp/calendar/cal-tex.el
+++ b/lisp/calendar/cal-tex.el
@@ -1,6 +1,6 @@
;;; cal-tex.el --- calendar functions for printing calendars with LaTeX -*- lexical-binding: t; -*-
-;; Copyright (C) 1995, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1995, 2001-2024 Free Software Foundation, Inc.
;; Author: Steve Fisk <fisk@bowdoin.edu>
;; Edward M. Reingold <reingold@cs.uiuc.edu>
diff --git a/lisp/calendar/cal-x.el b/lisp/calendar/cal-x.el
index 58eea324e82..1e1e2613d80 100644
--- a/lisp/calendar/cal-x.el
+++ b/lisp/calendar/cal-x.el
@@ -1,6 +1,6 @@
;;; cal-x.el --- calendar windows in dedicated frames -*- lexical-binding: t; -*-
-;; Copyright (C) 1994-1995, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1994-1995, 2001-2024 Free Software Foundation, Inc.
;; Author: Michael Kifer <kifer@cs.stonybrook.edu>
;; Edward M. Reingold <reingold@cs.uiuc.edu>
diff --git a/lisp/calendar/calendar.el b/lisp/calendar/calendar.el
index 02167d84b3e..a25684f7b5d 100644
--- a/lisp/calendar/calendar.el
+++ b/lisp/calendar/calendar.el
@@ -1,6 +1,6 @@
;;; calendar.el --- calendar functions -*- lexical-binding:t -*-
-;; Copyright (C) 1988-1995, 1997, 2000-2023 Free Software Foundation,
+;; Copyright (C) 1988-1995, 1997, 2000-2024 Free Software Foundation,
;; Inc.
;; Author: Edward M. Reingold <reingold@cs.uiuc.edu>
diff --git a/lisp/calendar/diary-lib.el b/lisp/calendar/diary-lib.el
index 946cf0e7236..63bbae4d8ed 100644
--- a/lisp/calendar/diary-lib.el
+++ b/lisp/calendar/diary-lib.el
@@ -1,6 +1,6 @@
;;; diary-lib.el --- diary functions -*- lexical-binding:t -*-
-;; Copyright (C) 1989-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1989-2024 Free Software Foundation, Inc.
;; Author: Edward M. Reingold <reingold@cs.uiuc.edu>
;; Maintainer: emacs-devel@gnu.org
@@ -167,8 +167,8 @@ form of ((MONTH DAY YEAR) STRING), where string is the diary
entry for the given date. This can be used, for example, to
produce a different buffer for display (perhaps combined with
holidays), or hard copy output."
- :type '(choice (const diary-fancy-display :tag "Fancy display")
- (const diary-simple-display :tag "Basic display")
+ :type '(choice (const :tag "Fancy display" diary-fancy-display)
+ (const :tag "Basic display" diary-simple-display)
(const :tag "No display" ignore)
(function :tag "User-specified function"))
:initialize 'custom-initialize-default
diff --git a/lisp/calendar/holidays.el b/lisp/calendar/holidays.el
index a65beca0e5b..c7499938c6a 100644
--- a/lisp/calendar/holidays.el
+++ b/lisp/calendar/holidays.el
@@ -1,6 +1,6 @@
;;; holidays.el --- holiday functions for the calendar package -*- lexical-binding:t -*-
-;; Copyright (C) 1989-1990, 1992-1994, 1997, 2001-2023 Free Software
+;; Copyright (C) 1989-1990, 1992-1994, 1997, 2001-2024 Free Software
;; Foundation, Inc.
;; Author: Edward M. Reingold <reingold@cs.uiuc.edu>
diff --git a/lisp/calendar/icalendar.el b/lisp/calendar/icalendar.el
index e51251d6d9f..d7e62e1baf3 100644
--- a/lisp/calendar/icalendar.el
+++ b/lisp/calendar/icalendar.el
@@ -1,8 +1,9 @@
;;; icalendar.el --- iCalendar implementation -*- lexical-binding: t -*-
-;; Copyright (C) 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2024 Free Software Foundation, Inc.
;; Author: Ulf Jasper <ulf.jasper@web.de>
+;; Maintainer: emacs-devel@gnu.org
;; Created: August 2002
;; Keywords: calendar
;; Human-Keywords: calendar, diary, iCalendar, vCalendar
@@ -276,9 +277,9 @@ other sexp entries are enumerated in any case."
:value 10)
(set :tag "Alarm type"
(list :tag "Audio"
- (const audio :tag "Audio"))
+ (const :tag "Audio" audio))
(list :tag "Display"
- (const display :tag "Display"))
+ (const :tag "Display" display))
(list :tag "Email"
(const email)
(repeat :tag "Attendees"
diff --git a/lisp/calendar/iso8601.el b/lisp/calendar/iso8601.el
index d7d064d9c2a..a32b52564c9 100644
--- a/lisp/calendar/iso8601.el
+++ b/lisp/calendar/iso8601.el
@@ -1,6 +1,6 @@
;;; iso8601.el --- parse ISO 8601 date/time strings -*- lexical-binding:t -*-
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
;; Keywords: dates
diff --git a/lisp/calendar/lunar.el b/lisp/calendar/lunar.el
index a9c3597a3f9..87c47304c24 100644
--- a/lisp/calendar/lunar.el
+++ b/lisp/calendar/lunar.el
@@ -1,6 +1,6 @@
;;; lunar.el --- calendar functions for phases of the moon -*- lexical-binding:t -*-
-;; Copyright (C) 1992-1993, 1995, 1997, 2001-2023 Free Software
+;; Copyright (C) 1992-1993, 1995, 1997, 2001-2024 Free Software
;; Foundation, Inc.
;; Author: Edward M. Reingold <reingold@cs.uiuc.edu>
diff --git a/lisp/calendar/parse-time.el b/lisp/calendar/parse-time.el
index a62361121fc..c34329a4002 100644
--- a/lisp/calendar/parse-time.el
+++ b/lisp/calendar/parse-time.el
@@ -1,6 +1,6 @@
;;; parse-time.el --- parsing time strings -*- lexical-binding: t -*-
-;; Copyright (C) 1996, 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996, 2000-2024 Free Software Foundation, Inc.
;; Author: Erik Naggum <erik@naggum.no>
;; Keywords: util
diff --git a/lisp/calendar/solar.el b/lisp/calendar/solar.el
index d82215a6d35..ecb3a47be71 100644
--- a/lisp/calendar/solar.el
+++ b/lisp/calendar/solar.el
@@ -1,6 +1,6 @@
;;; solar.el --- calendar functions for solar events -*- lexical-binding:t -*-
-;; Copyright (C) 1992-1993, 1995, 1997, 2001-2023 Free Software
+;; Copyright (C) 1992-1993, 1995, 1997, 2001-2024 Free Software
;; Foundation, Inc.
;; Author: Edward M. Reingold <reingold@cs.uiuc.edu>
diff --git a/lisp/calendar/time-date.el b/lisp/calendar/time-date.el
index 9cbe8e0f53c..e96e2e7e2db 100644
--- a/lisp/calendar/time-date.el
+++ b/lisp/calendar/time-date.el
@@ -1,6 +1,6 @@
;;; time-date.el --- Date and time handling functions -*- lexical-binding: t -*-
-;; Copyright (C) 1998-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-2024 Free Software Foundation, Inc.
;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
;; Masanobu Umeda <umerin@mse.kyutech.ac.jp>
@@ -181,7 +181,10 @@ If DATE lacks timezone information, GMT is assumed."
;;;###autoload
(defun days-to-time (days)
- "Convert DAYS into a time value."
+ "Convert Emacs-epoch DAYS into a time value.
+Note that this does not use the same epoch as `time-to-days'; you
+must subtract (time-to-days 0) first to convert, and may get nil
+if the result is before the start."
;; FIXME: We should likely just pass `t' to `time-convert'.
;; All uses I could find in Emacs, GNU ELPA, and NonGNU ELPA can handle
;; any valid time representation as return value.
@@ -243,7 +246,7 @@ DATE1 and DATE2 should be date-time strings."
;;;###autoload
(defun time-to-days (time)
- "The absolute date corresponding to TIME, a time value.
+ "The absolute pseudo-Gregorian date for TIME, a time value.
The absolute date is the number of days elapsed since the imaginary
Gregorian date Sunday, December 31, 1 BC."
(let* ((tim (decode-time time))
@@ -405,6 +408,7 @@ right of \"%x\", trailing zero units are not output."
"Formatting used by the function `seconds-to-string'.")
;;;###autoload
(defun seconds-to-string (delay)
+ ;; FIXME: There's a similar (tho fancier) function in mastodon.el!
"Convert the time interval in seconds to a short string."
(cond ((> 0 delay) (concat "-" (seconds-to-string (- delay))))
((= 0 delay) "0s")
diff --git a/lisp/calendar/timeclock.el b/lisp/calendar/timeclock.el
index 0cd03c15881..cc5d19522bd 100644
--- a/lisp/calendar/timeclock.el
+++ b/lisp/calendar/timeclock.el
@@ -1,6 +1,6 @@
;;; timeclock.el --- mode for keeping track of how much you work -*- lexical-binding:t -*-
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
;; Author: John Wiegley <johnw@gnu.org>
;; Created: 25 Mar 1999
@@ -100,19 +100,21 @@ into account any discrepancy of time under-worked or over-worked on
previous days. This only affects the timeclock mode line display."
:type 'boolean)
-(defcustom timeclock-get-project-function 'timeclock-ask-for-project
+(defcustom timeclock-get-project-function #'timeclock-ask-for-project
"The function used to determine the name of the current project.
When clocking in, and no project is specified, this function will be
called to determine what is the current project to be worked on.
If this variable is nil, no questions will be asked."
- :type 'function)
+ :type '(choice (const :tag "Don't ask" nil)
+ function))
-(defcustom timeclock-get-reason-function 'timeclock-ask-for-reason
+(defcustom timeclock-get-reason-function #'timeclock-ask-for-reason
"A function used to determine the reason for clocking out.
When clocking out, and no reason is specified, this function will be
called to determine what is the reason.
If this variable is nil, no questions will be asked."
- :type 'function)
+ :type '(choice (const :tag "Don't ask" nil)
+ function))
(defcustom timeclock-get-workday-function nil
"A function used to determine the length of today's workday.
diff --git a/lisp/calendar/todo-mode.el b/lisp/calendar/todo-mode.el
index ffb7b7168dd..7989fff9466 100644
--- a/lisp/calendar/todo-mode.el
+++ b/lisp/calendar/todo-mode.el
@@ -1,6 +1,6 @@
;;; todo-mode.el --- facilities for making and maintaining todo lists -*- lexical-binding:t -*-
-;; Copyright (C) 1997, 1999, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997, 1999, 2001-2024 Free Software Foundation, Inc.
;; Author: Oliver Seidel <privat@os10000.net>
;; Stephen Berman <stephen.berman@gmx.net>
@@ -139,8 +139,8 @@ automatically recalculated when the window width changes. If the
string consists of more (or less) than one character, it will be
the value of `todo-done-separator'."
:type 'string
- :initialize 'custom-initialize-default
- :set 'todo-reset-done-separator-string
+ :initialize #'custom-initialize-default
+ :set #'todo-reset-done-separator-string
:group 'todo-display)
(defun todo-done-separator ()
@@ -170,8 +170,8 @@ have its intended effect. The second string is inserted after
the diary date."
:type '(list string string)
:group 'todo-edit
- :initialize 'custom-initialize-default
- :set 'todo-reset-nondiary-marker)
+ :initialize #'custom-initialize-default
+ :set #'todo-reset-nondiary-marker)
(defconst todo-nondiary-start (nth 0 todo-nondiary-marker)
"String inserted before item date to block diary inclusion.")
@@ -189,20 +189,53 @@ The final element is \"*\", indicating an unspecified month.")
"Array of abbreviated month names, in order.
The final element is \"*\", indicating an unspecified month.")
+(defconst todo--date-pattern-groups
+ (pcase calendar-date-style
+ ('american '((monthname . "6") (month . "7") (day . "8") (year . "9")))
+ ('european '((day . "6") (monthname . "7") (month . "8") (year . "9")))
+ ('iso '((year . "6") (monthname . "7") (month . "8") (day . "9"))))
+ "Alist for grouping date components in `todo-date-pattern'.")
+
(defconst todo-date-pattern
- (let ((dayname (diary-name-pattern calendar-day-name-array nil t)))
- (concat "\\(?4:\\(?5:" dayname "\\)\\|"
- (calendar-dlet
- ((dayname)
- (monthname (format "\\(?6:%s\\)" (diary-name-pattern
- todo-month-name-array
- todo-month-abbrev-array)))
- (month "\\(?7:[0-9]+\\|\\*\\)")
- (day "\\(?8:[0-9]+\\|\\*\\)")
- (year "-?\\(?9:[0-9]+\\|\\*\\)"))
- (mapconcat #'eval calendar-date-display-form ""))
- "\\)"))
- "Regular expression matching a todo item date header.")
+ (let* ((dayname (diary-name-pattern calendar-day-name-array nil t))
+ (d (concat "\\(?" (alist-get 'day todo--date-pattern-groups)
+ ":[0-9]+\\|\\*\\)"))
+ (mn (format (concat "\\(?" (alist-get 'monthname
+ todo--date-pattern-groups)
+ ":%s\\)")
+ (diary-name-pattern todo-month-name-array
+ todo-month-abbrev-array)))
+ (m (concat "\\(?" (alist-get 'month todo--date-pattern-groups)
+ ":[0-9]+\\|\\*\\)"))
+ (y (concat "\\(?" (alist-get 'year todo--date-pattern-groups)
+ ":[0-9]+\\|\\*\\)"))
+ (dd "1111111")
+ (mm "2222222")
+ (yy "3333333")
+ (s (concat "\\(?4:\\(?5:" dayname "\\)\\|"
+ (calendar-dlet
+ ((dayname)
+ (monthname mn)
+ (year yy)
+ (month mm)
+ (day dd))
+ (mapconcat #'eval calendar-date-display-form))
+ "\\)")))
+ ;; The default value of calendar-iso-date-display-form calls
+ ;; `string-to-number' on the values of `month' and `day', so we
+ ;; gave them placeholder values above and now replace these with
+ ;; the necessary regexps with appropriately numbered groups, because
+ ;; `todo-edit-item--header' uses these groups.
+ (when (string-match dd s nil t)
+ (setq s (string-replace dd d s)))
+ (when (string-match mm s nil t)
+ (setq s (string-replace mm m s)))
+ (when (string-match yy s nil t)
+ (setq s (string-replace yy y s)))
+ s)
+ "Regular expression matching a todo item date header.
+The value of `calendar-date-display-form' determines the form of
+the date header.")
;; By itself this matches anything, because of the `?'; however, it's only
;; used in the context of `todo-date-pattern' (but Emacs Lisp lacks
@@ -215,8 +248,8 @@ The final element is \"*\", indicating an unspecified month.")
(defcustom todo-done-string "DONE "
"Identifying string appended to the front of done todo items."
:type 'string
- :initialize 'custom-initialize-default
- :set 'todo-reset-done-string
+ :initialize #'custom-initialize-default
+ :set #'todo-reset-done-string
:group 'todo-edit)
(defconst todo-done-string-start
@@ -242,16 +275,16 @@ The final element is \"*\", indicating an unspecified month.")
(format-message
"Invalid value: must be distinct from `todo-item-mark'"))
widget)))
- :initialize 'custom-initialize-default
- :set 'todo-reset-prefix
+ :initialize #'custom-initialize-default
+ :set #'todo-reset-prefix
:group 'todo-display)
(defcustom todo-number-prefix t
"Non-nil to prefix items with consecutively increasing integers.
These reflect the priorities of the items in each category."
:type 'boolean
- :initialize 'custom-initialize-default
- :set 'todo-reset-prefix
+ :initialize #'custom-initialize-default
+ :set #'todo-reset-prefix
:group 'todo-display)
(defun todo-mode-line-control (cat)
@@ -273,8 +306,8 @@ todo category. The resulting control becomes the local value of
(defcustom todo-highlight-item nil
"Non-nil means highlight items at point."
:type 'boolean
- :initialize 'custom-initialize-default
- :set 'todo-reset-highlight-item
+ :initialize #'custom-initialize-default
+ :set #'todo-reset-highlight-item
:group 'todo-display)
(defcustom todo-wrap-lines t
@@ -572,8 +605,8 @@ This lacks the extension and directory components."
"Non-nil to make `todo-show' visit the current todo file.
Otherwise, `todo-show' always visits `todo-default-todo-file'."
:type 'boolean
- :initialize 'custom-initialize-default
- :set 'todo-set-show-current-file
+ :initialize #'custom-initialize-default
+ :set #'todo-set-show-current-file
:group 'todo)
(defcustom todo-show-first 'first
@@ -1206,7 +1239,7 @@ visiting the deleted files."
(let ((sexp (read (buffer-substring-no-properties
(line-beginning-position)
(line-end-position))))
- (buffer-read-only nil)
+ (inhibit-read-only t)
(print-length nil)
(print-level nil))
(mapc (lambda (x) (aset (cdr x) 3 0)) sexp)
@@ -1304,7 +1337,7 @@ return the new category number."
(widen)
(goto-char (point-max))
(save-excursion ; Save point for todo-category-select.
- (let ((buffer-read-only nil))
+ (let ((inhibit-read-only t))
(insert todo-category-beg cat "\n\n" todo-category-done "\n")))
(todo-update-categories-sexp)
;; If invoked by user, display the newly added category, if
@@ -1334,7 +1367,7 @@ category there as well."
(list archive)))))
(dolist (buf buffers)
(with-current-buffer (find-file-noselect buf)
- (let (buffer-read-only)
+ (let ((inhibit-read-only t))
(setq todo-categories (todo-set-categories))
(save-excursion
(save-restriction
@@ -1382,7 +1415,7 @@ todo or done items."
"\"" (and arg " and all its entries")
"? "))))
(widen)
- (let ((buffer-read-only)
+ (let ((inhibit-read-only t)
(beg (re-search-backward
(concat "^" (regexp-quote (concat todo-category-beg cat))
"\n")
@@ -1486,7 +1519,7 @@ the archive of the file moved to, creating it if it does not exist."
nfile-short)
(format "the category \"%s\";\n" cat)
"enter a new category name: "))
- (buffer-read-only nil)
+ (inhibit-read-only t)
(print-length nil)
(print-level nil))
(widen)
@@ -1528,7 +1561,7 @@ the archive of the file moved to, creating it if it does not exist."
;; Delete the category from the old file, and if that was the
;; last category, delete the file. Also handle archive file
;; if necessary.
- (let ((buffer-read-only nil))
+ (let ((inhibit-read-only t))
(widen)
(remove-overlays beg end)
(delete-region beg end)
@@ -1581,7 +1614,7 @@ archive file and the source category is deleted."
here)
(with-current-buffer (get-buffer (find-file-noselect tfile))
(widen)
- (let* ((buffer-read-only nil)
+ (let* ((inhibit-read-only t)
(cbeg (progn
(re-search-backward
(concat "^" (regexp-quote todo-category-beg)) nil t)
@@ -1609,7 +1642,7 @@ archive file and the source category is deleted."
(unless (derived-mode-p 'todo-mode) (todo-mode))
(widen)
(goto-char (point-min))
- (let ((buffer-read-only nil))
+ (let ((inhibit-read-only t))
;; Merge any todo items.
(unless (zerop (length todo))
(re-search-forward
@@ -1647,7 +1680,7 @@ archive file and the source category is deleted."
(with-current-buffer (get-buffer (find-file-noselect tarchive))
(widen)
(goto-char (point-min))
- (let* ((buffer-read-only nil)
+ (let* ((inhibit-read-only t)
(cbeg (progn
(when (re-search-forward
(concat "^" (regexp-quote
@@ -1762,8 +1795,8 @@ only when no items are marked."
(defcustom todo-comment-string "COMMENT"
"String inserted before optional comment appended to done item."
:type 'string
- :initialize 'custom-initialize-default
- :set 'todo-reset-comment-string
+ :initialize #'custom-initialize-default
+ :set #'todo-reset-comment-string
:group 'todo-edit)
(defcustom todo-undo-item-omit-comment 'ask
@@ -1967,7 +2000,7 @@ their associated keys and their effects."
(setq todo-current-todo-file file)
(unless todo-global-current-todo-file
(setq todo-global-current-todo-file todo-current-todo-file))
- (let ((buffer-read-only nil)
+ (let ((inhibit-read-only t)
done-only item-added)
(unless copy
(setq new-item
@@ -2044,7 +2077,7 @@ their associated keys and their effects."
(todo-date-from-calendar
(let (calendar-view-diary-initially-flag)
(calendar)) ; *Calendar* is now current buffer.
- (define-key calendar-mode-map [remap newline] 'exit-recursive-edit)
+ (define-key calendar-mode-map [remap newline] #'exit-recursive-edit)
;; If user exits Calendar before choosing a date, clean up properly.
(define-key calendar-mode-map
[remap calendar-exit] (lambda ()
@@ -2079,7 +2112,7 @@ prompt for a todo file and then for a category in it."
(calendar-exit)
(todo-insert-item--basic arg nil todo-date-from-calendar))
-(define-key calendar-mode-map "it" 'todo-insert-item-from-calendar)
+(define-key calendar-mode-map "it" #'todo-insert-item-from-calendar)
(defun todo-delete-item ()
"Delete at least one item in this category.
@@ -2100,7 +2133,7 @@ the item at point."
(save-excursion (todo-item-end))))
(overlay-put ov 'face 'todo-search)
(todo-y-or-n-p "Permanently delete this item? "))))
- buffer-read-only)
+ (inhibit-read-only t))
(when answer
(and marked (goto-char (point-min)))
(catch 'done
@@ -2197,9 +2230,9 @@ the item at point."
end t)
(if comment-delete
(when (todo-y-or-n-p "Delete comment? ")
- (let ((buffer-read-only nil))
+ (let ((inhibit-read-only t))
(delete-region (match-beginning 0) (match-end 0))))
- (let ((buffer-read-only nil))
+ (let ((inhibit-read-only t))
(replace-match (save-match-data
(prog1 (let ((buffer-read-only t))
(read-string
@@ -2216,7 +2249,7 @@ the item at point."
nil nil nil 1)))
(if comment-delete
(user-error "There is no comment to delete")
- (let ((buffer-read-only nil))
+ (let ((inhibit-read-only t))
(insert " [" todo-comment-string ": "
(prog1 (let ((buffer-read-only t))
(read-string prompt))
@@ -2261,7 +2294,7 @@ the item at point."
(todo-category-number ocat)
(todo-category-select)
(goto-char opoint))
- (let ((buffer-read-only nil))
+ (let ((inhibit-read-only t))
(todo-remove-item)
(todo-insert-with-overlays new))
(move-to-column item-beg)))))))))
@@ -2350,10 +2383,18 @@ made in the number or names of categories."
(line-end-position) t)
(let* ((otime (match-string-no-properties 2))
(odayname (match-string-no-properties 5))
- (omonthname (match-string-no-properties 6))
- (omonth (match-string-no-properties 7))
- (oday (match-string-no-properties 8))
- (oyear (match-string-no-properties 9))
+ (mngroup (string-to-number
+ (alist-get 'monthname todo--date-pattern-groups)))
+ (omonthname (match-string-no-properties mngroup))
+ (mgroup (string-to-number
+ (alist-get 'month todo--date-pattern-groups)))
+ (omonth (match-string-no-properties mgroup))
+ (dgroup (string-to-number
+ (alist-get 'day todo--date-pattern-groups)))
+ (oday (match-string-no-properties dgroup))
+ (ygroup (string-to-number
+ (alist-get 'year todo--date-pattern-groups)))
+ (oyear (match-string-no-properties ygroup))
(tmn-array todo-month-name-array)
(mlist (append tmn-array nil))
(tma-array todo-month-abbrev-array)
@@ -2399,11 +2440,23 @@ made in the number or names of categories."
((eq what 'month)
(setf day oday
year oyear
- (if (memq 'month calendar-date-display-form)
+ ;; With default ISO style, 'month is in a
+ ;; sublist of c-d-d-f, so we flatten it.
+ (if (memq 'month (flatten-tree
+ calendar-date-display-form))
month
monthname)
(cond ((not current-prefix-arg)
- (todo-read-date 'month))
+ (let ((nmonth (todo-read-date 'month)))
+ ;; If old month is given as a number,
+ ;; have to convert new month name to
+ ;; the corresponding number.
+ (when omonth
+ (setq nmonth
+ (number-to-string
+ (1+ (seq-position tma-array
+ nmonth)))))
+ nmonth))
((or (string= omonth "*") (= mm 13))
(user-error "Cannot increment *"))
(t
@@ -2493,8 +2546,8 @@ made in the number or names of categories."
(month month)
(day day)
(dayname nil)) ;; dayname
- (mapconcat #'eval calendar-date-display-form "")))))
- (let ((buffer-read-only nil))
+ (mapconcat #'eval calendar-date-display-form)))))
+ (let ((inhibit-read-only t))
(when ndate (replace-match ndate nil nil nil 1))
;; Add new time string to the header, if it was supplied.
(when ntime
@@ -2513,7 +2566,7 @@ made in the number or names of categories."
(defun todo-edit-item--diary-inclusion (&optional nonmarking)
"Function providing diary marking facilities of `todo-edit-item'."
- (let ((buffer-read-only)
+ (let ((inhibit-read-only t)
(marked (assoc (todo-current-category) todo-categories-with-marks)))
(when marked (todo--user-error-if-marked-done-item))
(catch 'stop
@@ -2563,7 +2616,7 @@ items."
(goto-char (point-min))
(let ((todo-count (todo-get-count 'todo))
(diary-count (todo-get-count 'diary))
- (buffer-read-only))
+ (inhibit-read-only t))
(catch 'stop
(while (not (eobp))
(if (todo-done-item-p) ; We've gone too far.
@@ -2599,7 +2652,7 @@ items in this category."
(interactive "P")
(save-excursion
(goto-char (point-min))
- (let (buffer-read-only)
+ (let ((inhibit-read-only t))
(catch 'stop
(while (not (eobp))
(if (todo-done-item-p) ; We've gone too far.
@@ -2754,7 +2807,7 @@ meaning to raise or lower the item's priority by one."
(when match
(user-error (concat "Cannot reprioritize items from the same "
"category in this mode, only in Todo mode")))))
- (let ((buffer-read-only nil))
+ (let ((inhibit-read-only t))
;; Interactively or with non-nil ARG, relocate the item within its
;; category.
(when (or arg (called-interactively-p 'any))
@@ -2877,7 +2930,7 @@ section in the category moved to."
(setq here (point))
(while todo-items
(todo-forward-item)
- (let ((buffer-read-only nil))
+ (let ((inhibit-read-only t))
(todo-insert-with-overlays (pop todo-items)))))
;; Move done items en bloc to top of done items section.
(when done-items
@@ -2892,7 +2945,7 @@ section in the category moved to."
(forward-line)
(unless here (setq here (point)))
(while done-items
- (let ((buffer-read-only nil))
+ (let ((inhibit-read-only t))
(todo-insert-with-overlays (pop done-items)))
(todo-item-end)
(forward-line)))
@@ -2933,13 +2986,13 @@ section in the category moved to."
(goto-char beg)
(while (< (point) end)
(if (todo-marked-item-p)
- (let ((buffer-read-only nil))
+ (let ((inhibit-read-only t))
(todo-remove-item))
(todo-forward-item)))
(setq todo-categories-with-marks
(assq-delete-all cat1 todo-categories-with-marks)))
(if ov (delete-overlay ov))
- (let ((buffer-read-only nil))
+ (let ((inhibit-read-only t))
(todo-remove-item)))))
(when todo (todo-update-count 'todo (- todo) cat1))
(when diary (todo-update-count 'diary (- diary) cat1))
@@ -2999,7 +3052,7 @@ visible."
(show-done (save-excursion
(goto-char (point-min))
(re-search-forward todo-done-string-start nil t)))
- (buffer-read-only nil)
+ (inhibit-read-only t)
header item done-items
(opoint (point)))
;; Don't add empty comment to done item.
@@ -3131,7 +3184,7 @@ comments without asking."
(when ov (delete-overlay ov))
(if (not undone)
(goto-char opoint)
- (let ((buffer-read-only nil))
+ (let ((inhibit-read-only t))
(if marked
(progn
(setq item nil)
@@ -3269,13 +3322,14 @@ this category does not exist in the archive, it is created."
(with-current-buffer archive
(unless (derived-mode-p 'todo-archive-mode) (todo-archive-mode))
(let ((headers-hidden todo--item-headers-hidden)
- buffer-read-only)
+ (inhibit-read-only t))
(if headers-hidden (todo-toggle-item-header))
(widen)
(goto-char (point-min))
(if (and (re-search-forward
(concat "^" (regexp-quote
- (concat todo-category-beg cat)) "$")
+ (concat todo-category-beg cat))
+ "$")
nil t)
(re-search-forward (regexp-quote todo-category-done)
nil t))
@@ -3299,7 +3353,7 @@ this category does not exist in the archive, it is created."
(todo-archive-mode))
(if headers-hidden (todo-toggle-item-header))))
(with-current-buffer tbuf
- (let ((buffer-read-only nil))
+ (let ((inhibit-read-only t))
(cond
(all
(save-excursion
@@ -3367,7 +3421,7 @@ the only category in the archive, the archive file is deleted."
(item (concat (todo-item-string) "\n"))
(marked-count 0)
marked-items
- buffer-read-only)
+ (inhibit-read-only t))
(when marked
(save-excursion
(goto-char (point-min))
@@ -3379,7 +3433,7 @@ the only category in the archive, the archive file is deleted."
;; Restore items to top of category's done section and update counts.
(with-current-buffer tbuf
(let ((headers-hidden todo--item-headers-hidden)
- buffer-read-only newcat)
+ (inhibit-read-only t) newcat)
(if headers-hidden (todo-toggle-item-header))
(widen)
(goto-char (point-min))
@@ -3602,7 +3656,7 @@ decreasing or increasing its number."
;; Category's name and items counts list.
(catcons (nth (1- curnum) todo-categories))
(todo-categories (nconc head (list catcons) tail))
- (buffer-read-only nil)
+ (inhibit-read-only t)
newcats)
(when lower (setq todo-categories (nreverse todo-categories)))
(setq todo-categories (delete-dups todo-categories))
@@ -3823,8 +3877,7 @@ which is the value of the user option
(cons todo-categories-diary-label 'diary)
(cons todo-categories-done-label 'done)
(cons todo-categories-archived-label
- 'archived)))
- "")
+ 'archived))))
" ") ; Make highlighting on last column look better.
'face (if (and todo-skip-archived-categories
(zerop (todo-get-count 'todo cat))
@@ -3870,7 +3923,7 @@ which is the value of the user option
(kill-all-local-variables)
(todo-categories-mode)
(let ((archive (member todo-current-todo-file todo-archives))
- buffer-read-only)
+ (inhibit-read-only t))
(erase-buffer)
(insert (format (concat "Category counts for todo "
(if archive "archive" "file")
@@ -3909,7 +3962,7 @@ which is the value of the user option
(forward-line -2)
(goto-char (next-single-char-property-change
(point) 'face nil (line-end-position))))))
- (buffer-read-only))
+ (inhibit-read-only t))
(forward-line 2)
(delete-region (point) (point-max))
;; Fill in the table with buttonized lines, each showing a category and
@@ -3932,8 +3985,7 @@ which is the value of the user option
(list (cons todo-categories-todo-label 0)
(cons todo-categories-diary-label 1)
(cons todo-categories-done-label 2)
- (cons todo-categories-archived-label 3)))
- ""))
+ (cons todo-categories-archived-label 3)))))
;; Put cursor on Category button initially.
(if pt (goto-char pt))
(setq buffer-read-only t)))
@@ -4482,7 +4534,7 @@ the values of FILTER and FILE-LIST."
(widen)))
(setq bufstr (buffer-string))
(with-current-buffer buf
- (let (buffer-read-only)
+ (let ((inhibit-read-only t))
(insert bufstr)))))))
(set-window-buffer (selected-window) (set-buffer buf))
(todo-prefix-overlays)
@@ -4758,7 +4810,7 @@ Helper function for `todo-convert-legacy-files'."
(time (match-string 4))
dayname)
(replace-match "")
- (insert (mapconcat #'eval calendar-date-display-form "")
+ (insert (mapconcat #'eval calendar-date-display-form)
(when time (concat " " time)))))
(defun todo-convert-legacy-files ()
@@ -5112,7 +5164,7 @@ With nil or omitted CATEGORY, default to the current category."
(defun todo-update-categories-sexp ()
"Update the `todo-categories' sexp at the top of the file."
- (let ((buffer-read-only nil)
+ (let ((inhibit-read-only t)
(print-length nil)
(print-level nil))
(save-excursion
@@ -5279,7 +5331,12 @@ changes you have made in the order of the categories.
;; Point is on done items separator.
(save-excursion (beginning-of-line) (looking-at todo-category-done))
;; Buffer is widened.
- (looking-at (regexp-quote todo-category-beg)))
+ (looking-at (regexp-quote todo-category-beg))
+ ;; Moving an item to a todo file (with `C-u m') that had
+ ;; not yet been read into a buffer puts point at the
+ ;; beginning of the file, from where it is impossible to
+ ;; reach todo-item-start by the loop below (bug#66994).
+ (= (point) 1))
(goto-char (line-beginning-position))
(while (not (looking-at todo-item-start))
(forward-line -1))
@@ -5844,7 +5901,7 @@ Also return t if answer is \"Y\", but unlike `y-or-n-p', allow
SPC to affirm the question only if option `todo-y-with-space' is
non-nil."
(unless todo-y-with-space
- (define-key query-replace-map " " 'ignore))
+ (define-key query-replace-map " " #'ignore))
(prog1
(y-or-n-p prompt)
(define-key query-replace-map " " 'act)))
@@ -6180,7 +6237,7 @@ number of the last the day of the month."
(if (memq 'month calendar-date-display-form)
month
monthname)))
- (mapconcat #'eval calendar-date-display-form ""))))
+ (mapconcat #'eval calendar-date-display-form))))
(defun todo-read-dayname ()
"Choose name of a day of the week with completion and return it."
@@ -6277,7 +6334,7 @@ the empty string (i.e., no time string)."
(dolist (f files)
(let ((buf (find-buffer-visiting f)))
(with-current-buffer (find-file-noselect f)
- (let (buffer-read-only)
+ (let ((inhibit-read-only t))
(widen)
(goto-char (point-min))
(while (not (eobp))
@@ -6293,7 +6350,7 @@ the empty string (i.e., no time string)."
(replace-match (nth 1 value) t t nil 2))
(forward-line)))
(if buf
- (when (derived-mode-p 'todo-mode 'todo-archive-mode)
+ (when (derived-mode-p '(todo-mode todo-archive-mode))
(todo-category-select))
(save-buffer)
(kill-buffer)))))))))
@@ -6307,7 +6364,7 @@ the empty string (i.e., no time string)."
(when (not (equal value oldvalue))
(dolist (f files)
(with-current-buffer (find-file-noselect f)
- (let (buffer-read-only)
+ (let ((inhibit-read-only t))
(setq todo-done-separator (todo-done-separator))
(when (= 1 (length value))
(todo-reset-done-separator sep)))
@@ -6326,7 +6383,7 @@ the empty string (i.e., no time string)."
(dolist (f files)
(let ((buf (find-buffer-visiting f)))
(with-current-buffer (find-file-noselect f)
- (let (buffer-read-only)
+ (let ((inhibit-read-only t))
(widen)
(goto-char (point-min))
(while (not (eobp))
@@ -6337,7 +6394,7 @@ the empty string (i.e., no time string)."
(replace-match value t t nil 1)
(forward-line)))
(if buf
- (when (derived-mode-p 'todo-mode 'todo-archive-mode)
+ (when (derived-mode-p '(todo-mode todo-archive-mode))
(todo-category-select))
(save-buffer)
(kill-buffer)))))))))
@@ -6352,7 +6409,7 @@ the empty string (i.e., no time string)."
(dolist (f files)
(let ((buf (find-buffer-visiting f)))
(with-current-buffer (find-file-noselect f)
- (let (buffer-read-only)
+ (let ((inhibit-read-only t))
(widen)
(goto-char (point-min))
(while (not (eobp))
@@ -6363,7 +6420,7 @@ the empty string (i.e., no time string)."
(replace-match value t t nil 1)
(forward-line)))
(if buf
- (when (derived-mode-p 'todo-mode 'todo-archive-mode)
+ (when (derived-mode-p '(todo-mode todo-archive-mode))
(todo-category-select))
(save-buffer)
(kill-buffer)))))))))
@@ -6587,32 +6644,32 @@ Filtered Items mode following todo (not done) items."
(define-key map (nth 0 kb) (nth 1 kb)))
(dolist (kb todo-key-bindings-t+a)
(define-key map (nth 0 kb) (nth 1 kb)))
- (define-key map "a" 'todo-jump-to-archive-category)
- (define-key map "u" 'todo-unarchive-items)
+ (define-key map "a" #'todo-jump-to-archive-category)
+ (define-key map "u" #'todo-unarchive-items)
map)
"Todo Archive mode keymap.")
(defvar todo-edit-mode-map
(let ((map (make-sparse-keymap)))
- (define-key map "\C-x\C-q" 'todo-edit-quit)
+ (define-key map "\C-x\C-q" #'todo-edit-quit)
map)
"Todo Edit mode keymap.")
(defvar todo-categories-mode-map
(let ((map (make-sparse-keymap)))
- (define-key map "c" 'todo-sort-categories-alphabetically-or-numerically)
- (define-key map "t" 'todo-sort-categories-by-todo)
- (define-key map "y" 'todo-sort-categories-by-diary)
- (define-key map "d" 'todo-sort-categories-by-done)
- (define-key map "a" 'todo-sort-categories-by-archived)
- (define-key map "#" 'todo-set-category-number)
- (define-key map "l" 'todo-lower-category)
- (define-key map "r" 'todo-raise-category)
- (define-key map "n" 'todo-next-button)
- (define-key map "p" 'todo-previous-button)
- (define-key map [tab] 'todo-next-button)
- (define-key map [backtab] 'todo-previous-button)
- (define-key map "q" 'todo-quit)
+ (define-key map "c" #'todo-sort-categories-alphabetically-or-numerically)
+ (define-key map "t" #'todo-sort-categories-by-todo)
+ (define-key map "y" #'todo-sort-categories-by-diary)
+ (define-key map "d" #'todo-sort-categories-by-done)
+ (define-key map "a" #'todo-sort-categories-by-archived)
+ (define-key map "#" #'todo-set-category-number)
+ (define-key map "l" #'todo-lower-category)
+ (define-key map "r" #'todo-raise-category)
+ (define-key map "n" #'todo-next-button)
+ (define-key map "p" #'todo-previous-button)
+ (define-key map [tab] #'todo-next-button)
+ (define-key map [backtab] #'todo-previous-button)
+ (define-key map "q" #'todo-quit)
map)
"Todo Categories mode keymap.")
@@ -6622,8 +6679,8 @@ Filtered Items mode following todo (not done) items."
(define-key map (nth 0 kb) (nth 1 kb)))
(dolist (kb todo-key-bindings-t+f)
(define-key map (nth 0 kb) (nth 1 kb)))
- (define-key map "g" 'todo-go-to-source-item)
- (define-key map [remap newline] 'todo-go-to-source-item)
+ (define-key map "g" #'todo-go-to-source-item)
+ (define-key map [remap newline] #'todo-go-to-source-item)
map)
"Todo Filtered Items mode keymap.")
@@ -6779,13 +6836,9 @@ Added to `window-configuration-change-hook' in Todo mode."
;; (add-hook 'find-file-hook #'todo-display-as-todo-file nil t)
)
-(put 'todo-mode 'mode-class 'special)
-
;;;###autoload
(define-derived-mode todo-mode special-mode "Todo"
- "Major mode for displaying, navigating and editing todo lists.
-
-\\{todo-mode-map}"
+ "Major mode for displaying, navigating and editing todo lists."
(if (called-interactively-p 'any)
(message "%s"
(substitute-command-keys
@@ -6807,15 +6860,11 @@ Added to `window-configuration-change-hook' in Todo mode."
#'todo-reset-and-enable-done-separator nil t)
(add-hook 'kill-buffer-hook #'todo-reset-global-current-todo-file nil t)))
-(put 'todo-archive-mode 'mode-class 'special)
-
;; If todo-mode is parent, all todo-mode key bindings appear to be
;; available in todo-archive-mode (e.g. shown by C-h m).
;;;###autoload
(define-derived-mode todo-archive-mode special-mode "Todo-Arch"
- "Major mode for archived todo categories.
-
-\\{todo-archive-mode-map}"
+ "Major mode for archived todo categories."
(todo-modes-set-1)
(todo-modes-set-2)
(todo-modes-set-3)
@@ -6823,9 +6872,7 @@ Added to `window-configuration-change-hook' in Todo mode."
(setq-local todo-show-done-only t))
(define-derived-mode todo-edit-mode text-mode "Todo-Ed"
- "Major mode for editing multiline todo items.
-
-\\{todo-edit-mode-map}"
+ "Major mode for editing multiline todo items."
(todo-modes-set-1)
(setq-local indent-line-function #'todo-indent)
(if (> (buffer-size) (- (point-max) (point-min)))
@@ -6838,12 +6885,8 @@ Added to `window-configuration-change-hook' in Todo mode."
(setq-local todo-categories (todo-set-categories)))
(setq buffer-read-only nil))
-(put 'todo-categories-mode 'mode-class 'special)
-
(define-derived-mode todo-categories-mode special-mode "Todo-Cats"
- "Major mode for displaying and editing todo categories.
-
-\\{todo-categories-mode-map}"
+ "Major mode for displaying and editing todo categories."
(setq-local todo-current-todo-file todo-global-current-todo-file)
(setq-local todo-categories
;; Can't use find-buffer-visiting when
@@ -6854,13 +6897,9 @@ Added to `window-configuration-change-hook' in Todo mode."
todo-current-todo-file 'nowarn)
todo-categories)))
-(put 'todo-filtered-items-mode 'mode-class 'special)
-
;;;###autoload
(define-derived-mode todo-filtered-items-mode special-mode "Todo-Fltr"
- "Mode for displaying and reprioritizing top priority Todo.
-
-\\{todo-filtered-items-mode-map}"
+ "Mode for displaying and reprioritizing top priority Todo."
(todo-modes-set-1)
(todo-modes-set-2))
diff --git a/lisp/case-table.el b/lisp/case-table.el
index f5cfbae2c9c..b7c1719743e 100644
--- a/lisp/case-table.el
+++ b/lisp/case-table.el
@@ -1,6 +1,6 @@
;;; case-table.el --- code to extend the character set and support case tables -*- lexical-binding: t -*-
-;; Copyright (C) 1988, 1994, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1988, 1994, 2001-2024 Free Software Foundation, Inc.
;; Author: Howard Gayle
;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/cdl.el b/lisp/cdl.el
index 57504f4dae0..38a1bea9c31 100644
--- a/lisp/cdl.el
+++ b/lisp/cdl.el
@@ -1,6 +1,6 @@
;;; cdl.el --- Common Data Language (CDL) utility functions for GNU Emacs -*- lexical-binding: t -*-
-;; Copyright (C) 1993, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1993, 2001-2024 Free Software Foundation, Inc.
;; Author: Ata Etemadi <ATAE@spva.physics.imperial.ac.uk>
;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/cedet/ChangeLog.1 b/lisp/cedet/ChangeLog.1
index 5242c73062b..3f72bda75af 100644
--- a/lisp/cedet/ChangeLog.1
+++ b/lisp/cedet/ChangeLog.1
@@ -1515,7 +1515,7 @@
* semantic/complete.el (semantic-complete-post-command-hook):
Exit completion when user has deleted all characters from the prefix.
(semantic-displayor-focus-request): Return to previous window when
- focussing tags.
+ focusing tags.
* semantic/db-el.el (semanticdb-normalize-one-tag): Make obsolete.
(semanticdb-elisp-sym->tag): Use help-function-arglist instead.
@@ -3459,7 +3459,7 @@
;; coding: utf-8
;; End:
- Copyright (C) 2009-2023 Free Software Foundation, Inc.
+ Copyright (C) 2009-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/lisp/cedet/cedet-cscope.el b/lisp/cedet/cedet-cscope.el
index da86847a8f2..02e79db64ef 100644
--- a/lisp/cedet/cedet-cscope.el
+++ b/lisp/cedet/cedet-cscope.el
@@ -1,6 +1,6 @@
;;; cedet-cscope.el --- CScope support for CEDET -*- lexical-binding: t; -*-
-;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
;; Package: cedet
diff --git a/lisp/cedet/cedet-files.el b/lisp/cedet/cedet-files.el
index 1c82b7165a9..236ee5df0e9 100644
--- a/lisp/cedet/cedet-files.el
+++ b/lisp/cedet/cedet-files.el
@@ -1,6 +1,6 @@
;;; cedet-files.el --- Common routines dealing with file names. -*- lexical-binding: t; -*-
-;; Copyright (C) 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
;; Package: cedet
diff --git a/lisp/cedet/cedet-global.el b/lisp/cedet/cedet-global.el
index a175f16d6b8..3294a88d2c1 100644
--- a/lisp/cedet/cedet-global.el
+++ b/lisp/cedet/cedet-global.el
@@ -1,6 +1,6 @@
;;; cedet-global.el --- GNU Global support for CEDET. -*- lexical-binding: t; -*-
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
;; Package: cedet
@@ -152,7 +152,14 @@ return nil."
nil)
(with-current-buffer b
(goto-char (point-min))
- (re-search-forward "(?GNU GLOBAL)? \\([0-9.]+\\)" nil t)
+ (re-search-forward
+ (rx (or
+ ;; global (Global) 6.6.10
+ "global (Global)"
+ (seq (opt "(") "GNU GLOBAL" (opt ")")))
+ " "
+ (group (one-or-more (any "0-9."))))
+ nil t)
(setq rev (match-string 1))
(if (version< rev cedet-global-min-version)
(if noerror
diff --git a/lisp/cedet/cedet-idutils.el b/lisp/cedet/cedet-idutils.el
index e82ffd0990c..41b4d64238f 100644
--- a/lisp/cedet/cedet-idutils.el
+++ b/lisp/cedet/cedet-idutils.el
@@ -1,6 +1,6 @@
;;; cedet-idutils.el --- ID Utils support for CEDET. -*- lexical-binding: t; -*-
-;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
;; Old-Version: 0.2
diff --git a/lisp/cedet/cedet.el b/lisp/cedet/cedet.el
index 337a5be1cd8..28208e39285 100644
--- a/lisp/cedet/cedet.el
+++ b/lisp/cedet/cedet.el
@@ -1,6 +1,6 @@
;;; cedet.el --- Setup CEDET environment -*- lexical-binding: t; -*-
-;; Copyright (C) 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2024 Free Software Foundation, Inc.
;; Author: David Ponce <david@dponce.com>
;; Maintainer: Eric M. Ludlam <zappo@gnu.org>
diff --git a/lisp/cedet/data-debug.el b/lisp/cedet/data-debug.el
index 837d75ea158..83ff451fa99 100644
--- a/lisp/cedet/data-debug.el
+++ b/lisp/cedet/data-debug.el
@@ -1,6 +1,6 @@
;;; data-debug.el --- Data structure debugger -*- lexical-binding: t; -*-
-;; Copyright (C) 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
;; Old-Version: 0.2
diff --git a/lisp/cedet/ede.el b/lisp/cedet/ede.el
index 272633f5cac..b5993f9faac 100644
--- a/lisp/cedet/ede.el
+++ b/lisp/cedet/ede.el
@@ -1,6 +1,6 @@
;;; ede.el --- Emacs Development Environment gloss -*- lexical-binding: t; -*-
-;; Copyright (C) 1998-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
;; Keywords: project, make
diff --git a/lisp/cedet/ede/auto.el b/lisp/cedet/ede/auto.el
index 901fe958560..d923809b2e2 100644
--- a/lisp/cedet/ede/auto.el
+++ b/lisp/cedet/ede/auto.el
@@ -1,6 +1,6 @@
;;; ede/auto.el --- Autoload features for EDE -*- lexical-binding: t; -*-
-;; Copyright (C) 2010-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2010-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/lisp/cedet/ede/autoconf-edit.el b/lisp/cedet/ede/autoconf-edit.el
index 6663dd03576..d1cfdeb44d8 100644
--- a/lisp/cedet/ede/autoconf-edit.el
+++ b/lisp/cedet/ede/autoconf-edit.el
@@ -1,6 +1,6 @@
;;; ede/autoconf-edit.el --- Keymap for autoconf -*- lexical-binding: t; -*-
-;; Copyright (C) 1998-2000, 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-2000, 2009-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
;; Keywords: project
diff --git a/lisp/cedet/ede/base.el b/lisp/cedet/ede/base.el
index 305bf599151..91dd0a4749b 100644
--- a/lisp/cedet/ede/base.el
+++ b/lisp/cedet/ede/base.el
@@ -1,6 +1,6 @@
;;; ede/base.el --- Baseclasses for EDE -*- lexical-binding: t; -*-
-;; Copyright (C) 2010-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2010-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
@@ -312,7 +312,8 @@ All specific project types must derive from this project."
"File containing the list of projects EDE has viewed.
If set to nil, then the cache is not saved."
:group 'ede
- :type 'file)
+ :type '(choice (const :tag "Don't save the cache" nil)
+ file))
(defvar ede-project-cache-files nil
"List of project files EDE has seen before.")
diff --git a/lisp/cedet/ede/config.el b/lisp/cedet/ede/config.el
index 39a65d6e393..a27b336dc93 100644
--- a/lisp/cedet/ede/config.el
+++ b/lisp/cedet/ede/config.el
@@ -1,6 +1,6 @@
;;; ede/config.el --- Configuration Handler baseclass -*- lexical-binding: t; -*-
-;; Copyright (C) 2014-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2014-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/lisp/cedet/ede/cpp-root.el b/lisp/cedet/ede/cpp-root.el
index d30f45f8619..795d5189567 100644
--- a/lisp/cedet/ede/cpp-root.el
+++ b/lisp/cedet/ede/cpp-root.el
@@ -1,6 +1,6 @@
;;; ede/cpp-root.el --- A simple way to wrap a C++ project with a single root -*- lexical-binding: t; -*-
-;; Copyright (C) 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/lisp/cedet/ede/custom.el b/lisp/cedet/ede/custom.el
index 81edaa01ad4..959437d1c5d 100644
--- a/lisp/cedet/ede/custom.el
+++ b/lisp/cedet/ede/custom.el
@@ -1,6 +1,6 @@
;;; ede/custom.el --- customization of EDE projects. -*- lexical-binding: t; -*-
-;; Copyright (C) 2010-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2010-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/lisp/cedet/ede/detect.el b/lisp/cedet/ede/detect.el
index 445b540e826..0da5dc71be3 100644
--- a/lisp/cedet/ede/detect.el
+++ b/lisp/cedet/ede/detect.el
@@ -1,6 +1,6 @@
;;; ede/detect.el --- EDE project detection and file associations -*- lexical-binding: t; -*-
-;; Copyright (C) 2014-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2014-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/lisp/cedet/ede/dired.el b/lisp/cedet/ede/dired.el
index 850b1b2b5e2..fbfd9111dc0 100644
--- a/lisp/cedet/ede/dired.el
+++ b/lisp/cedet/ede/dired.el
@@ -1,6 +1,6 @@
;;; ede/dired.el --- EDE extensions to dired. -*- lexical-binding: t -*-
-;; Copyright (C) 1998-2000, 2003, 2009-2023 Free Software Foundation,
+;; Copyright (C) 1998-2000, 2003, 2009-2024 Free Software Foundation,
;; Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/lisp/cedet/ede/emacs.el b/lisp/cedet/ede/emacs.el
index 4ae16f6226e..e2d228e7e83 100644
--- a/lisp/cedet/ede/emacs.el
+++ b/lisp/cedet/ede/emacs.el
@@ -1,6 +1,6 @@
;;; ede/emacs.el --- Special project for Emacs -*- lexical-binding: t -*-
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/lisp/cedet/ede/files.el b/lisp/cedet/ede/files.el
index 28dc788c736..4dbe498877e 100644
--- a/lisp/cedet/ede/files.el
+++ b/lisp/cedet/ede/files.el
@@ -1,6 +1,6 @@
;;; ede/files.el --- Associate projects with files and directories. -*- lexical-binding: t; -*-
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/lisp/cedet/ede/generic.el b/lisp/cedet/ede/generic.el
index c3e6d5ef520..c3e8b9eb761 100644
--- a/lisp/cedet/ede/generic.el
+++ b/lisp/cedet/ede/generic.el
@@ -1,6 +1,6 @@
;;; ede/generic.el --- Base Support for generic build systems -*- lexical-binding: t; -*-
-;; Copyright (C) 2010-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2010-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/lisp/cedet/ede/linux.el b/lisp/cedet/ede/linux.el
index 0208475a8c7..234059dc26f 100644
--- a/lisp/cedet/ede/linux.el
+++ b/lisp/cedet/ede/linux.el
@@ -1,6 +1,6 @@
;;; ede/linux.el --- Special project for Linux -*- lexical-binding: t; -*-
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/lisp/cedet/ede/locate.el b/lisp/cedet/ede/locate.el
index c356979839d..56782ff4d36 100644
--- a/lisp/cedet/ede/locate.el
+++ b/lisp/cedet/ede/locate.el
@@ -1,6 +1,6 @@
;;; ede/locate.el --- Locate support -*- lexical-binding: t; -*-
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/lisp/cedet/ede/make.el b/lisp/cedet/ede/make.el
index 5d4bc9f556e..49b84f66e2c 100644
--- a/lisp/cedet/ede/make.el
+++ b/lisp/cedet/ede/make.el
@@ -1,6 +1,6 @@
;;; ede/make.el --- General information about "make" -*- lexical-binding: t -*-
-;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/lisp/cedet/ede/makefile-edit.el b/lisp/cedet/ede/makefile-edit.el
index 9a35c74d841..461274876a0 100644
--- a/lisp/cedet/ede/makefile-edit.el
+++ b/lisp/cedet/ede/makefile-edit.el
@@ -1,6 +1,6 @@
;;; makefile-edit.el --- Makefile editing/scanning commands. -*- lexical-binding: t; -*-
-;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/lisp/cedet/ede/pconf.el b/lisp/cedet/ede/pconf.el
index 610d0a1dcb6..57dc4263af5 100644
--- a/lisp/cedet/ede/pconf.el
+++ b/lisp/cedet/ede/pconf.el
@@ -1,6 +1,6 @@
;;; ede/pconf.el --- configure.ac maintenance for EDE -*- lexical-binding: t; -*-
-;; Copyright (C) 1998-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
;; Keywords: project
diff --git a/lisp/cedet/ede/pmake.el b/lisp/cedet/ede/pmake.el
index 954683a22bb..e6d989946db 100644
--- a/lisp/cedet/ede/pmake.el
+++ b/lisp/cedet/ede/pmake.el
@@ -1,6 +1,6 @@
;;; ede-pmake.el --- EDE Generic Project Makefile code generator -*- lexical-binding: t; -*-
-;; Copyright (C) 1998-2005, 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-2005, 2007-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
;; Keywords: project, make
diff --git a/lisp/cedet/ede/proj-archive.el b/lisp/cedet/ede/proj-archive.el
index 9f84497351c..7f8ccc11158 100644
--- a/lisp/cedet/ede/proj-archive.el
+++ b/lisp/cedet/ede/proj-archive.el
@@ -1,6 +1,6 @@
;;; ede/proj-archive.el --- EDE Generic Project archive support -*- lexical-binding: t -*-
-;; Copyright (C) 1998-2001, 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-2001, 2009-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
;; Keywords: project, make
diff --git a/lisp/cedet/ede/proj-aux.el b/lisp/cedet/ede/proj-aux.el
index 50fcb8ac201..6a8c81a9ce2 100644
--- a/lisp/cedet/ede/proj-aux.el
+++ b/lisp/cedet/ede/proj-aux.el
@@ -1,6 +1,6 @@
;;; ede/proj-aux.el --- EDE Generic Project auxiliary file support -*- lexical-binding: t -*-
-;; Copyright (C) 1998-2000, 2007, 2009-2023 Free Software Foundation,
+;; Copyright (C) 1998-2000, 2007, 2009-2024 Free Software Foundation,
;; Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/lisp/cedet/ede/proj-comp.el b/lisp/cedet/ede/proj-comp.el
index a31313bfe3d..1b2024d64c7 100644
--- a/lisp/cedet/ede/proj-comp.el
+++ b/lisp/cedet/ede/proj-comp.el
@@ -1,6 +1,6 @@
;;; ede/proj-comp.el --- EDE Generic Project compiler/rule driver -*- lexical-binding: t; -*-
-;; Copyright (C) 1999-2001, 2004-2005, 2007, 2009-2023 Free Software
+;; Copyright (C) 1999-2001, 2004-2005, 2007, 2009-2024 Free Software
;; Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/lisp/cedet/ede/proj-elisp.el b/lisp/cedet/ede/proj-elisp.el
index 1aa637c94fe..951c7173653 100644
--- a/lisp/cedet/ede/proj-elisp.el
+++ b/lisp/cedet/ede/proj-elisp.el
@@ -1,6 +1,6 @@
;;; ede-proj-elisp.el --- EDE Generic Project Emacs Lisp support -*- lexical-binding: t; -*-
-;; Copyright (C) 1998-2005, 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-2005, 2007-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
;; Keywords: project, make
diff --git a/lisp/cedet/ede/proj-info.el b/lisp/cedet/ede/proj-info.el
index 07fe5031ecf..1a9c2070116 100644
--- a/lisp/cedet/ede/proj-info.el
+++ b/lisp/cedet/ede/proj-info.el
@@ -1,6 +1,6 @@
;;; ede-proj-info.el --- EDE Generic Project texinfo support -*- lexical-binding: t; -*-
-;; Copyright (C) 1998-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
;; Keywords: project, make
diff --git a/lisp/cedet/ede/proj-misc.el b/lisp/cedet/ede/proj-misc.el
index 3433443f5d8..961b1e26b22 100644
--- a/lisp/cedet/ede/proj-misc.el
+++ b/lisp/cedet/ede/proj-misc.el
@@ -1,6 +1,6 @@
;;; ede-proj-misc.el --- EDE Generic Project Emacs Lisp support -*- lexical-binding: t -*-
-;; Copyright (C) 1998-2001, 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-2001, 2008-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
;; Keywords: project, make
diff --git a/lisp/cedet/ede/proj-obj.el b/lisp/cedet/ede/proj-obj.el
index 50eedf62eca..2a529c56e25 100644
--- a/lisp/cedet/ede/proj-obj.el
+++ b/lisp/cedet/ede/proj-obj.el
@@ -1,6 +1,6 @@
;;; ede/proj-obj.el --- EDE Generic Project Object code generation support -*- lexical-binding: t; -*-
-;; Copyright (C) 1998-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
;; Keywords: project, make
diff --git a/lisp/cedet/ede/proj-prog.el b/lisp/cedet/ede/proj-prog.el
index ce782eb4d0b..e5439f345d9 100644
--- a/lisp/cedet/ede/proj-prog.el
+++ b/lisp/cedet/ede/proj-prog.el
@@ -1,6 +1,6 @@
;;; ede-proj-prog.el --- EDE Generic Project program support -*- lexical-binding: t; -*-
-;; Copyright (C) 1998-2001, 2005, 2008-2023 Free Software Foundation,
+;; Copyright (C) 1998-2001, 2005, 2008-2024 Free Software Foundation,
;; Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/lisp/cedet/ede/proj-scheme.el b/lisp/cedet/ede/proj-scheme.el
index aa2b8c7fd86..a7482bd2bf2 100644
--- a/lisp/cedet/ede/proj-scheme.el
+++ b/lisp/cedet/ede/proj-scheme.el
@@ -1,6 +1,6 @@
;;; ede/proj-scheme.el --- EDE Generic Project scheme (guile) support -*- lexical-binding: t -*-
-;; Copyright (C) 1998-2000, 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-2000, 2009-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
;; Keywords: project, make, scheme
diff --git a/lisp/cedet/ede/proj-shared.el b/lisp/cedet/ede/proj-shared.el
index 34c9dbb5cf4..5e063251c5d 100644
--- a/lisp/cedet/ede/proj-shared.el
+++ b/lisp/cedet/ede/proj-shared.el
@@ -1,6 +1,6 @@
;;; ede-proj-shared.el --- EDE Generic Project shared library support -*- lexical-binding: t; -*-
-;; Copyright (C) 1998-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
;; Keywords: project, make
diff --git a/lisp/cedet/ede/proj.el b/lisp/cedet/ede/proj.el
index 3d680b3cb8c..9137d7eb59f 100644
--- a/lisp/cedet/ede/proj.el
+++ b/lisp/cedet/ede/proj.el
@@ -1,6 +1,6 @@
;;; ede/proj.el --- EDE Generic Project file driver -*- lexical-binding: t; -*-
-;; Copyright (C) 1998-2003, 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-2003, 2007-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
;; Keywords: project, make
diff --git a/lisp/cedet/ede/project-am.el b/lisp/cedet/ede/project-am.el
index 0f28afa7416..8810683d05d 100644
--- a/lisp/cedet/ede/project-am.el
+++ b/lisp/cedet/ede/project-am.el
@@ -1,6 +1,6 @@
;;; project-am.el --- A project management scheme based on automake files. -*- lexical-binding: t; -*-
-;; Copyright (C) 1998-2000, 2003, 2005, 2007-2023 Free Software
+;; Copyright (C) 1998-2000, 2003, 2005, 2007-2024 Free Software
;; Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/lisp/cedet/ede/shell.el b/lisp/cedet/ede/shell.el
index 4d58797e30b..8b47ba46670 100644
--- a/lisp/cedet/ede/shell.el
+++ b/lisp/cedet/ede/shell.el
@@ -1,6 +1,6 @@
;;; ede/shell.el --- A shell controlled by EDE. -*- lexical-binding: t; -*-
;;
-;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
;;
;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/lisp/cedet/ede/simple.el b/lisp/cedet/ede/simple.el
index 071e8d79eb5..6b62986f942 100644
--- a/lisp/cedet/ede/simple.el
+++ b/lisp/cedet/ede/simple.el
@@ -1,6 +1,6 @@
;;; ede/simple.el --- Overlay an EDE structure on an existing project -*- lexical-binding: t; -*-
-;; Copyright (C) 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/lisp/cedet/ede/source.el b/lisp/cedet/ede/source.el
index 8c699e8976f..fbe21c16a4f 100644
--- a/lisp/cedet/ede/source.el
+++ b/lisp/cedet/ede/source.el
@@ -1,6 +1,6 @@
;; ede/source.el --- EDE source code object -*- lexical-binding: t; -*-
-;; Copyright (C) 2000, 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2000, 2008-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
;; Keywords: project, make
diff --git a/lisp/cedet/ede/speedbar.el b/lisp/cedet/ede/speedbar.el
index aa3c95fec0c..65fb26d41d0 100644
--- a/lisp/cedet/ede/speedbar.el
+++ b/lisp/cedet/ede/speedbar.el
@@ -1,6 +1,6 @@
;;; ede/speedbar.el --- Speedbar viewing of EDE projects -*- lexical-binding: t; -*-
-;; Copyright (C) 1998-2001, 2003, 2005, 2007-2023 Free Software
+;; Copyright (C) 1998-2001, 2003, 2005, 2007-2024 Free Software
;; Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/lisp/cedet/ede/srecode.el b/lisp/cedet/ede/srecode.el
index b2f5e4779c8..0d305abf8e0 100644
--- a/lisp/cedet/ede/srecode.el
+++ b/lisp/cedet/ede/srecode.el
@@ -1,6 +1,6 @@
;;; ede/srecode.el --- EDE utilities on top of SRecoder -*- lexical-binding: t -*-
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/lisp/cedet/ede/system.el b/lisp/cedet/ede/system.el
index dbd48308769..a912856ec4f 100644
--- a/lisp/cedet/ede/system.el
+++ b/lisp/cedet/ede/system.el
@@ -1,6 +1,6 @@
;;; ede-system.el --- EDE working with the system (VC, FTP, ETC) -*- lexical-binding: t -*-
-;; Copyright (C) 2001-2003, 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2003, 2009-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
;; Keywords: project, make, vc
diff --git a/lisp/cedet/ede/util.el b/lisp/cedet/ede/util.el
index 739a2e34e86..8e346f5b9e3 100644
--- a/lisp/cedet/ede/util.el
+++ b/lisp/cedet/ede/util.el
@@ -1,6 +1,6 @@
;;; ede/util.el --- EDE utilities -*- lexical-binding: t; -*-
-;; Copyright (C) 2000, 2005, 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2000, 2005, 2009-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
;; Keywords: project, make
diff --git a/lisp/cedet/mode-local.el b/lisp/cedet/mode-local.el
index e1746e1a541..28f14232704 100644
--- a/lisp/cedet/mode-local.el
+++ b/lisp/cedet/mode-local.el
@@ -1,6 +1,6 @@
;;; mode-local.el --- Support for mode local facilities -*- lexical-binding:t -*-
;;
-;; Copyright (C) 2004-2005, 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2004-2005, 2007-2024 Free Software Foundation, Inc.
;;
;; Author: David Ponce <david@dponce.com>
;; Created: 27 Apr 2004
@@ -68,36 +68,23 @@ walk through. It defaults to `buffer-list'."
(when (or (not predicate) (funcall predicate))
(funcall function))))))
-(defsubst get-mode-local-parent (mode)
+(defun get-mode-local-parent (mode)
"Return the mode parent of the major mode MODE.
Return nil if MODE has no parent."
+ (declare (obsolete derived-mode-all-parents "30.1"))
(or (get mode 'mode-local-parent)
(get mode 'derived-mode-parent)))
-;; FIXME doc (and function name) seems wrong.
-;; Return a list of MODE and all its parent modes, if any.
-;; Lists parent modes first.
-(defun mode-local-equivalent-mode-p (mode)
- "Is the major-mode in the current buffer equivalent to a mode in MODES."
- (let ((modes nil))
- (while mode
- (setq modes (cons mode modes)
- mode (get-mode-local-parent mode)))
- modes))
+(define-obsolete-function-alias 'mode-local-equivalent-mode-p
+ #'derived-mode-all-parents "30.1")
(defun mode-local-map-mode-buffers (function modes)
"Run FUNCTION on every file buffer with major mode in MODES.
MODES can be a symbol or a list of symbols.
FUNCTION does not have arguments."
- (or (listp modes) (setq modes (list modes)))
+ (setq modes (ensure-list modes))
(mode-local-map-file-buffers
- function (lambda ()
- (let ((mm (mode-local-equivalent-mode-p major-mode))
- (ans nil))
- (while (and (not ans) mm)
- (setq ans (memq (car mm) modes)
- mm (cdr mm)) )
- ans))))
+ function (lambda () (apply #'derived-mode-p modes))))
;;; Hook machinery
;;
@@ -145,7 +132,8 @@ after changing the major mode."
"Set parent of major mode MODE to PARENT mode.
To work properly, this function should be called after PARENT mode
local variables have been defined."
- (put mode 'mode-local-parent parent)
+ (declare (obsolete derived-mode-add-parents "30.1"))
+ (derived-mode-add-parents mode (list parent))
;; Refresh mode bindings to get mode local variables inherited from
;; PARENT. To work properly, the following should be called after
;; PARENT mode local variables have been defined.
@@ -159,13 +147,8 @@ definition."
(declare (obsolete define-derived-mode "27.1") (indent 2))
`(mode-local--set-parent ',mode ',parent))
-(defun mode-local-use-bindings-p (this-mode desired-mode)
- "Return non-nil if THIS-MODE can use bindings of DESIRED-MODE."
- (let ((ans nil))
- (while (and (not ans) this-mode)
- (setq ans (eq this-mode desired-mode))
- (setq this-mode (get-mode-local-parent this-mode)))
- ans))
+(define-obsolete-function-alias 'mode-local-use-bindings-p
+ #'provided-mode-derived-p "30.1")
;;; Core bindings API
@@ -270,11 +253,13 @@ its parents."
(setq mode major-mode
bind (and mode-local-symbol-table
(intern-soft name mode-local-symbol-table))))
- (while (and mode (not bind))
- (or (and (get mode 'mode-local-symbol-table)
- (setq bind (intern-soft
- name (get mode 'mode-local-symbol-table))))
- (setq mode (get-mode-local-parent mode))))
+ (let ((parents (derived-mode-all-parents mode)))
+ (while (and parents (not bind))
+ (or (and (get (car parents) 'mode-local-symbol-table)
+ (setq bind (intern-soft
+ name (get (car parents)
+ 'mode-local-symbol-table))))
+ (setq parents (cdr parents)))))
bind))
(defsubst mode-local-symbol-value (symbol &optional mode property)
@@ -311,16 +296,12 @@ Elements are (SYMBOL . PREVIOUS-VALUE), describing one variable."
(mode-local-on-major-mode-change)
;; Do the normal thing.
- (let (modes table old-locals)
+ (let (table old-locals)
(unless mode
(setq-local mode-local--init-mode major-mode)
(setq mode major-mode))
- ;; Get MODE's parents & MODE in the right order.
- (while mode
- (setq modes (cons mode modes)
- mode (get-mode-local-parent mode)))
;; Activate mode bindings following parent modes order.
- (dolist (mode modes)
+ (dolist (mode (derived-mode-all-parents mode))
(when (setq table (get mode 'mode-local-symbol-table))
(mapatoms
(lambda (var)
@@ -345,14 +326,13 @@ If MODE is not specified it defaults to current `major-mode'."
(kill-local-variable 'mode-local--init-mode)
(setq mode major-mode))
(let (table)
- (while mode
+ (dolist (mode (derived-mode-all-parents mode))
(when (setq table (get mode 'mode-local-symbol-table))
(mapatoms
(lambda (var)
(when (get var 'mode-variable-flag)
(kill-local-variable (intern (symbol-name var)))))
- table))
- (setq mode (get-mode-local-parent mode)))))
+ table)))))
(defmacro with-mode-local-symbol (mode &rest body)
"With the local bindings of MODE symbol, evaluate BODY.
@@ -866,12 +846,11 @@ META-NAME is a cons (OVERLOADABLE-SYMBOL . MAJOR-MODE)."
(when table
(princ "\n- Buffer local\n")
(mode-local-print-bindings table))
- (while mode
+ (dolist (mode (derived-mode-all-parents mode))
(setq table (get mode 'mode-local-symbol-table))
(when table
(princ (format-message "\n- From `%s'\n" mode))
- (mode-local-print-bindings table))
- (setq mode (get-mode-local-parent mode)))))
+ (mode-local-print-bindings table)))))
(defun mode-local-describe-bindings-1 (buffer-or-mode &optional interactive-p)
"Display mode local bindings active in BUFFER-OR-MODE.
diff --git a/lisp/cedet/pulse.el b/lisp/cedet/pulse.el
index 37b41fbe8c3..d9f6a40865a 100644
--- a/lisp/cedet/pulse.el
+++ b/lisp/cedet/pulse.el
@@ -1,6 +1,6 @@
;;; pulse.el --- Pulsing Overlays -*- lexical-binding: t; -*-
-;; Copyright (C) 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
;; Version: 1.0
@@ -71,7 +71,9 @@ Any other value means to do the default pulsing behavior.
If `pulse-flag' is non-nil, but `pulse-available-p' is nil, then
this flag is ignored."
:group 'pulse
- :type 'boolean)
+ :type '(choice (const :tag "Highlight with unchanging color" nil)
+ (const :tag "No highlight" never)
+ (other :tag "Pulse" t)))
(defface pulse-highlight-start-face
'((((class color) (background dark))
diff --git a/lisp/cedet/semantic.el b/lisp/cedet/semantic.el
index 0c15a2a453e..3c3ae2ac160 100644
--- a/lisp/cedet/semantic.el
+++ b/lisp/cedet/semantic.el
@@ -1,6 +1,6 @@
;;; semantic.el --- Semantic buffer evaluator. -*- lexical-binding: t; -*-
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
;; Keywords: syntax tools
diff --git a/lisp/cedet/semantic/analyze.el b/lisp/cedet/semantic/analyze.el
index 405b1b136e3..d536b26f7ac 100644
--- a/lisp/cedet/semantic/analyze.el
+++ b/lisp/cedet/semantic/analyze.el
@@ -1,6 +1,6 @@
;;; semantic/analyze.el --- Analyze semantic tags against local context -*- lexical-binding: t; -*-
-;; Copyright (C) 2000-2005, 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2000-2005, 2007-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/lisp/cedet/semantic/analyze/complete.el b/lisp/cedet/semantic/analyze/complete.el
index 8c8ae6a271d..b42fe5e9f5d 100644
--- a/lisp/cedet/semantic/analyze/complete.el
+++ b/lisp/cedet/semantic/analyze/complete.el
@@ -1,6 +1,6 @@
;;; semantic/analyze/complete.el --- Smart Completions -*- lexical-binding: t; -*-
-;; Copyright (C) 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/lisp/cedet/semantic/analyze/debug.el b/lisp/cedet/semantic/analyze/debug.el
index 6f195c24337..ad3786b5b59 100644
--- a/lisp/cedet/semantic/analyze/debug.el
+++ b/lisp/cedet/semantic/analyze/debug.el
@@ -1,6 +1,6 @@
;;; semantic/analyze/debug.el --- Debug the analyzer -*- lexical-binding: t; -*-
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/lisp/cedet/semantic/analyze/fcn.el b/lisp/cedet/semantic/analyze/fcn.el
index d2c4e1aecb4..4404616007b 100644
--- a/lisp/cedet/semantic/analyze/fcn.el
+++ b/lisp/cedet/semantic/analyze/fcn.el
@@ -1,6 +1,6 @@
;;; semantic/analyze/fcn.el --- Analyzer support functions. -*- lexical-binding: t; -*-
-;; Copyright (C) 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/lisp/cedet/semantic/analyze/refs.el b/lisp/cedet/semantic/analyze/refs.el
index c3acec6a37b..977eabc9f5a 100644
--- a/lisp/cedet/semantic/analyze/refs.el
+++ b/lisp/cedet/semantic/analyze/refs.el
@@ -1,6 +1,6 @@
;;; semantic/analyze/refs.el --- Analysis of the references between tags. -*- lexical-binding: t; -*-
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/lisp/cedet/semantic/bovine.el b/lisp/cedet/semantic/bovine.el
index 1fe4bbf76f5..79435913dd6 100644
--- a/lisp/cedet/semantic/bovine.el
+++ b/lisp/cedet/semantic/bovine.el
@@ -1,6 +1,6 @@
;;; semantic/bovine.el --- LL Parser/Analyzer core -*- lexical-binding: t; -*-
-;; Copyright (C) 1999-2004, 2006-2007, 2009-2023 Free Software
+;; Copyright (C) 1999-2004, 2006-2007, 2009-2024 Free Software
;; Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/lisp/cedet/semantic/bovine/c.el b/lisp/cedet/semantic/bovine/c.el
index 4e6f6568501..cf5ce1761a8 100644
--- a/lisp/cedet/semantic/bovine/c.el
+++ b/lisp/cedet/semantic/bovine/c.el
@@ -1,6 +1,6 @@
;;; semantic/bovine/c.el --- Semantic details for C -*- lexical-binding: t; -*-
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/lisp/cedet/semantic/bovine/debug.el b/lisp/cedet/semantic/bovine/debug.el
index f583dbbc691..a13f4ad7c93 100644
--- a/lisp/cedet/semantic/bovine/debug.el
+++ b/lisp/cedet/semantic/bovine/debug.el
@@ -1,6 +1,6 @@
;;; semantic/bovine/debug.el --- Debugger support for bovinator -*- lexical-binding: t; -*-
-;; Copyright (C) 2003, 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003, 2009-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/lisp/cedet/semantic/bovine/el.el b/lisp/cedet/semantic/bovine/el.el
index 294616f70d9..ef3e5d53af9 100644
--- a/lisp/cedet/semantic/bovine/el.el
+++ b/lisp/cedet/semantic/bovine/el.el
@@ -1,6 +1,6 @@
;;; semantic/bovine/el.el --- Semantic details for Emacs Lisp -*- lexical-binding: t; -*-
-;; Copyright (C) 1999-2005, 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2005, 2007-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/lisp/cedet/semantic/bovine/gcc.el b/lisp/cedet/semantic/bovine/gcc.el
index 4c687fa43be..47700959a2b 100644
--- a/lisp/cedet/semantic/bovine/gcc.el
+++ b/lisp/cedet/semantic/bovine/gcc.el
@@ -1,6 +1,6 @@
;;; semantic/bovine/gcc.el --- gcc querying special code for the C parser -*- lexical-binding: t -*-
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/lisp/cedet/semantic/bovine/grammar.el b/lisp/cedet/semantic/bovine/grammar.el
index 1b9b65eaaf9..4a9324492c8 100644
--- a/lisp/cedet/semantic/bovine/grammar.el
+++ b/lisp/cedet/semantic/bovine/grammar.el
@@ -1,6 +1,6 @@
;;; semantic/bovine/grammar.el --- Bovine's input grammar mode -*- lexical-binding: t; -*-
;;
-;; Copyright (C) 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2024 Free Software Foundation, Inc.
;;
;; Author: David Ponce <david@dponce.com>
;; Created: 26 Aug 2002
diff --git a/lisp/cedet/semantic/bovine/make.el b/lisp/cedet/semantic/bovine/make.el
index 2171136ae9d..a95f7da27cf 100644
--- a/lisp/cedet/semantic/bovine/make.el
+++ b/lisp/cedet/semantic/bovine/make.el
@@ -1,6 +1,6 @@
;;; semantic/bovine/make.el --- Makefile parsing rules. -*- lexical-binding: t; -*-
-;; Copyright (C) 2000-2004, 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2000-2004, 2008-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/lisp/cedet/semantic/bovine/scm.el b/lisp/cedet/semantic/bovine/scm.el
index c0852eca8dd..6d19acf0282 100644
--- a/lisp/cedet/semantic/bovine/scm.el
+++ b/lisp/cedet/semantic/bovine/scm.el
@@ -1,6 +1,6 @@
;;; semantic/bovine/scm.el --- Semantic details for Scheme (guile) -*- lexical-binding: t; -*-
-;; Copyright (C) 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/lisp/cedet/semantic/chart.el b/lisp/cedet/semantic/chart.el
index 880d86fac49..a87ae19ee0c 100644
--- a/lisp/cedet/semantic/chart.el
+++ b/lisp/cedet/semantic/chart.el
@@ -1,6 +1,6 @@
;;; semantic/chart.el --- Utilities for use with semantic tag tables -*- lexical-binding: t; -*-
-;; Copyright (C) 1999-2001, 2003, 2005, 2008-2023 Free Software
+;; Copyright (C) 1999-2001, 2003, 2005, 2008-2024 Free Software
;; Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/lisp/cedet/semantic/complete.el b/lisp/cedet/semantic/complete.el
index 84040b572bc..7adf9abfdcb 100644
--- a/lisp/cedet/semantic/complete.el
+++ b/lisp/cedet/semantic/complete.el
@@ -1,6 +1,6 @@
;;; semantic/complete.el --- Routines for performing tag completion -*- lexical-binding: t; -*-
-;; Copyright (C) 2003-2005, 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003-2005, 2007-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
;; Keywords: syntax
@@ -1046,7 +1046,7 @@ Output must be in semanticdb Find result format."
(and last-prefix (string-prefix-p last-prefix prefix t)))
;; We have the same prefix, or last-prefix is a
;; substring of the of new prefix, in which case we are
- ;; refining our symbol so just re-use cache.
+ ;; refining our symbol so just reuse cache.
(oref obj last-all-completions))
((and last-prefix
(> (length prefix) 1)
diff --git a/lisp/cedet/semantic/ctxt.el b/lisp/cedet/semantic/ctxt.el
index 84e6c6ebecb..3b7af17a96d 100644
--- a/lisp/cedet/semantic/ctxt.el
+++ b/lisp/cedet/semantic/ctxt.el
@@ -1,6 +1,6 @@
;;; semantic/ctxt.el --- Context calculations for Semantic tools -*- lexical-binding: t; -*-
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
;; Keywords: syntax
diff --git a/lisp/cedet/semantic/db-debug.el b/lisp/cedet/semantic/db-debug.el
index c2ab5f0483c..817c8f07263 100644
--- a/lisp/cedet/semantic/db-debug.el
+++ b/lisp/cedet/semantic/db-debug.el
@@ -1,6 +1,6 @@
;;; semantic/db-debug.el --- Extra level debugging routines for Semantic -*- lexical-binding: t; -*-
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/lisp/cedet/semantic/db-ebrowse.el b/lisp/cedet/semantic/db-ebrowse.el
index 3e54b9e76cf..3b387477850 100644
--- a/lisp/cedet/semantic/db-ebrowse.el
+++ b/lisp/cedet/semantic/db-ebrowse.el
@@ -1,6 +1,6 @@
;;; semantic/db-ebrowse.el --- Semanticdb backend using ebrowse. -*- lexical-binding: t; -*-
-;; Copyright (C) 2005-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2005-2024 Free Software Foundation, Inc.
;; Authors: Eric M. Ludlam <zappo@gnu.org>
;; Joakim Verona
diff --git a/lisp/cedet/semantic/db-el.el b/lisp/cedet/semantic/db-el.el
index b97a8264a95..6357953a746 100644
--- a/lisp/cedet/semantic/db-el.el
+++ b/lisp/cedet/semantic/db-el.el
@@ -1,6 +1,6 @@
;;; semantic/db-el.el --- Semantic database extensions for Emacs Lisp -*- lexical-binding: t; -*-
-;; Copyright (C) 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
;; Keywords: tags
diff --git a/lisp/cedet/semantic/db-file.el b/lisp/cedet/semantic/db-file.el
index 11c3cb7c55f..393072501f3 100644
--- a/lisp/cedet/semantic/db-file.el
+++ b/lisp/cedet/semantic/db-file.el
@@ -1,6 +1,6 @@
;;; semantic/db-file.el --- Save a semanticdb to a cache file. -*- lexical-binding: t; -*-
-;; Copyright (C) 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2000-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
;; Keywords: tags
diff --git a/lisp/cedet/semantic/db-find.el b/lisp/cedet/semantic/db-find.el
index 675ff72cfd3..6d42c3125c0 100644
--- a/lisp/cedet/semantic/db-find.el
+++ b/lisp/cedet/semantic/db-find.el
@@ -1,6 +1,6 @@
;;; semantic/db-find.el --- Searching through semantic databases. -*- lexical-binding: t; -*-
-;; Copyright (C) 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2000-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
;; Keywords: tags
diff --git a/lisp/cedet/semantic/db-global.el b/lisp/cedet/semantic/db-global.el
index b8dfc3c245f..7e5dee60fbe 100644
--- a/lisp/cedet/semantic/db-global.el
+++ b/lisp/cedet/semantic/db-global.el
@@ -1,6 +1,6 @@
;;; semantic/db-global.el --- Semantic database extensions for GLOBAL -*- lexical-binding: t; -*-
-;; Copyright (C) 2002-2006, 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2006, 2008-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
;; Keywords: tags
diff --git a/lisp/cedet/semantic/db-javascript.el b/lisp/cedet/semantic/db-javascript.el
index b1c33e25018..9baa4e82b8f 100644
--- a/lisp/cedet/semantic/db-javascript.el
+++ b/lisp/cedet/semantic/db-javascript.el
@@ -1,6 +1,6 @@
;;; semantic/db-javascript.el --- Semantic database extensions for javascript -*- lexical-binding: t; -*-
-;; Copyright (C) 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2024 Free Software Foundation, Inc.
;; Author: Joakim Verona
diff --git a/lisp/cedet/semantic/db-mode.el b/lisp/cedet/semantic/db-mode.el
index 4e40424acb4..45a524fe849 100644
--- a/lisp/cedet/semantic/db-mode.el
+++ b/lisp/cedet/semantic/db-mode.el
@@ -1,6 +1,6 @@
;;; semantic/db-mode.el --- Semanticdb Minor Mode -*- lexical-binding: t; -*-
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/lisp/cedet/semantic/db-ref.el b/lisp/cedet/semantic/db-ref.el
index 2ed7d8d8937..964ecaec258 100644
--- a/lisp/cedet/semantic/db-ref.el
+++ b/lisp/cedet/semantic/db-ref.el
@@ -1,6 +1,6 @@
;;; semantic/db-ref.el --- Handle cross-db file references -*- lexical-binding: t; -*-
-;; Copyright (C) 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/lisp/cedet/semantic/db-typecache.el b/lisp/cedet/semantic/db-typecache.el
index 1864e567c9a..7ca4c70abc9 100644
--- a/lisp/cedet/semantic/db-typecache.el
+++ b/lisp/cedet/semantic/db-typecache.el
@@ -1,6 +1,6 @@
;;; semantic/db-typecache.el --- Manage Datatypes -*- lexical-binding: t; -*-
-;; Copyright (C) 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/lisp/cedet/semantic/db.el b/lisp/cedet/semantic/db.el
index 7c7ee749249..e4fbf28a64e 100644
--- a/lisp/cedet/semantic/db.el
+++ b/lisp/cedet/semantic/db.el
@@ -1,6 +1,6 @@
;;; semantic/db.el --- Semantic tag database manager -*- lexical-binding:t -*-
-;; Copyright (C) 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2000-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
;; Keywords: tags
@@ -393,9 +393,7 @@ If a database for DIRECTORY has already been created, return it.
If DIRECTORY doesn't exist, create a new one."
(let ((db (semanticdb-directory-loaded-p directory)))
(unless db
- (setq db (semanticdb-project-database
- (file-name-nondirectory directory)
- :tables nil))
+ (setq db (semanticdb-project-database :tables nil))
;; Set this up here. We can't put it in the constructor because it
;; would be saved, and we want DB files to be portable.
(setf (slot-value db 'reference-directory) (file-truename directory)))
@@ -799,7 +797,7 @@ local variable."
(null (oref table major-mode))
;; nil means the same as major-mode
(and (not semantic-equivalent-major-modes)
- (mode-local-use-bindings-p major-mode (oref table major-mode)))
+ (provided-mode-derived-p major-mode (oref table major-mode)))
(and semantic-equivalent-major-modes
(member (oref table major-mode) semantic-equivalent-major-modes))
)
diff --git a/lisp/cedet/semantic/debug.el b/lisp/cedet/semantic/debug.el
index 11e44538d31..7e3c0de9410 100644
--- a/lisp/cedet/semantic/debug.el
+++ b/lisp/cedet/semantic/debug.el
@@ -1,6 +1,6 @@
;;; semantic/debug.el --- Language Debugger framework -*- lexical-binding: t; -*-
-;; Copyright (C) 2003-2005, 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003-2005, 2008-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/lisp/cedet/semantic/decorate.el b/lisp/cedet/semantic/decorate.el
index 27cfea6a65c..8c07155be37 100644
--- a/lisp/cedet/semantic/decorate.el
+++ b/lisp/cedet/semantic/decorate.el
@@ -1,6 +1,6 @@
;;; semantic/decorate.el --- Utilities for decorating/highlighting tokens. -*- lexical-binding: t; -*-
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
;; Keywords: syntax
diff --git a/lisp/cedet/semantic/decorate/include.el b/lisp/cedet/semantic/decorate/include.el
index 96bf8cec3b2..c4629b68bca 100644
--- a/lisp/cedet/semantic/decorate/include.el
+++ b/lisp/cedet/semantic/decorate/include.el
@@ -1,6 +1,6 @@
;;; semantic/decorate/include.el --- Decoration modes for include statements -*- lexical-binding: t; -*-
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/lisp/cedet/semantic/decorate/mode.el b/lisp/cedet/semantic/decorate/mode.el
index 5adcf636cef..c0d8d791a39 100644
--- a/lisp/cedet/semantic/decorate/mode.el
+++ b/lisp/cedet/semantic/decorate/mode.el
@@ -1,6 +1,6 @@
;;; semantic/decorate/mode.el --- Minor mode for decorating tags -*- lexical-binding: t; -*-
-;; Copyright (C) 2000-2005, 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2000-2005, 2007-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
;; Keywords: syntax
diff --git a/lisp/cedet/semantic/dep.el b/lisp/cedet/semantic/dep.el
index bd01581feb1..0d0e4f08120 100644
--- a/lisp/cedet/semantic/dep.el
+++ b/lisp/cedet/semantic/dep.el
@@ -1,6 +1,6 @@
;;; semantic/dep.el --- Methods for tracking dependencies (include files) -*- lexical-binding: t; -*-
-;; Copyright (C) 2006-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2006-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
;; Keywords: syntax
diff --git a/lisp/cedet/semantic/doc.el b/lisp/cedet/semantic/doc.el
index 09b66e5cfac..80229fe5081 100644
--- a/lisp/cedet/semantic/doc.el
+++ b/lisp/cedet/semantic/doc.el
@@ -1,6 +1,6 @@
;;; semantic/doc.el --- Routines for documentation strings -*- lexical-binding: t; -*-
-;; Copyright (C) 1999-2003, 2005, 2008-2023 Free Software Foundation,
+;; Copyright (C) 1999-2003, 2005, 2008-2024 Free Software Foundation,
;; Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/lisp/cedet/semantic/ede-grammar.el b/lisp/cedet/semantic/ede-grammar.el
index 42ffe50ca63..49a6ee94c84 100644
--- a/lisp/cedet/semantic/ede-grammar.el
+++ b/lisp/cedet/semantic/ede-grammar.el
@@ -1,6 +1,6 @@
;;; semantic/ede-grammar.el --- EDE support for Semantic Grammar Files -*- lexical-binding: t; -*-
-;; Copyright (C) 2003-2004, 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003-2004, 2007-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
;; Keywords: project, make
diff --git a/lisp/cedet/semantic/edit.el b/lisp/cedet/semantic/edit.el
index 4eeb7745370..9dfb96f1fa1 100644
--- a/lisp/cedet/semantic/edit.el
+++ b/lisp/cedet/semantic/edit.el
@@ -1,6 +1,6 @@
;;; semantic/edit.el --- Edit Management for Semantic -*- lexical-binding: t; -*-
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/lisp/cedet/semantic/find.el b/lisp/cedet/semantic/find.el
index 9094fcf0739..14fbcbc00f8 100644
--- a/lisp/cedet/semantic/find.el
+++ b/lisp/cedet/semantic/find.el
@@ -1,6 +1,6 @@
;;; semantic/find.el --- Search routines for Semantic -*- lexical-binding: t; -*-
-;; Copyright (C) 1999-2005, 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2005, 2008-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
;; Keywords: syntax
diff --git a/lisp/cedet/semantic/format.el b/lisp/cedet/semantic/format.el
index c808da3b093..1e4c4d92d81 100644
--- a/lisp/cedet/semantic/format.el
+++ b/lisp/cedet/semantic/format.el
@@ -1,6 +1,6 @@
;;; semantic/format.el --- Routines for formatting tags -*- lexical-binding: t; -*-
-;; Copyright (C) 1999-2005, 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2005, 2007-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
;; Keywords: syntax
diff --git a/lisp/cedet/semantic/fw.el b/lisp/cedet/semantic/fw.el
index 30704760c1d..1a7af803a6b 100644
--- a/lisp/cedet/semantic/fw.el
+++ b/lisp/cedet/semantic/fw.el
@@ -1,6 +1,6 @@
;;; semantic/fw.el --- Framework for Semantic -*- lexical-binding: t; -*-
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
@@ -434,9 +434,8 @@ FILE, NOWARN, RAWFILE, and WILDCARDS are passed into `find-file-noselect'."
;; ))
;; "Highlighted Semantic keywords.")
-;; (when (fboundp 'font-lock-add-keywords)
-;; (font-lock-add-keywords 'emacs-lisp-mode
-;; semantic-fw-font-lock-keywords))
+;; (font-lock-add-keywords 'emacs-lisp-mode
+;; semantic-fw-font-lock-keywords)
(provide 'semantic/fw)
diff --git a/lisp/cedet/semantic/grammar.el b/lisp/cedet/semantic/grammar.el
index 2dccd87a710..54dc7807ef6 100644
--- a/lisp/cedet/semantic/grammar.el
+++ b/lisp/cedet/semantic/grammar.el
@@ -1,6 +1,6 @@
;;; semantic/grammar.el --- Major mode framework for Semantic grammars -*- lexical-binding: t; -*-
-;; Copyright (C) 2002-2005, 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2005, 2007-2024 Free Software Foundation, Inc.
;; Author: David Ponce <david@dponce.com>
@@ -644,7 +644,7 @@ The symbols in the list are local variables in
(cond
(x (cdr x))
((symbolp S) (symbol-value S))))))
- template ""))
+ template))
(defun semantic-grammar-header ()
"Return text of a generated standard header."
@@ -1156,18 +1156,13 @@ END is the limit of the search."
("^\\(\\(\\sw\\|\\s_\\)+\\)[ \n\r\t]*:"
1 font-lock-function-name-face)
(semantic--grammar-macros-matcher
- 1 ,(if (boundp 'font-lock-builtin-face)
- 'font-lock-builtin-face
- 'font-lock-preprocessor-face))
+ 1 font-lock-builtin-face)
("\\$\\(\\sw\\|\\s_\\)*"
0 font-lock-variable-name-face)
("<\\(\\(\\sw\\|\\s_\\)+\\)>"
1 font-lock-type-face)
(,semantic-grammar-lex-c-char-re
- 0 ,(if (boundp 'font-lock-constant-face)
- 'font-lock-constant-face
- 'font-lock-string-face)
- t)
+ 0 font-lock-constant-face t)
;; Must highlight :keyword here, because ':' is a punctuation in
;; grammar mode!
("[\r\n\t ]+:\\sw+\\>"
diff --git a/lisp/cedet/semantic/grm-wy-boot.el b/lisp/cedet/semantic/grm-wy-boot.el
index 159ac64fc30..7658a26d106 100644
--- a/lisp/cedet/semantic/grm-wy-boot.el
+++ b/lisp/cedet/semantic/grm-wy-boot.el
@@ -1,6 +1,6 @@
;;; semantic/grammar-wy.el --- Generated parser support file -*- lexical-binding:t -*-
-;; Copyright (C) 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/lisp/cedet/semantic/html.el b/lisp/cedet/semantic/html.el
index 7c1181de0d7..120b2108709 100644
--- a/lisp/cedet/semantic/html.el
+++ b/lisp/cedet/semantic/html.el
@@ -1,6 +1,6 @@
;;; semantic/html.el --- Semantic details for html files -*- lexical-binding: t; -*-
-;; Copyright (C) 2004-2005, 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2004-2005, 2007-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/lisp/cedet/semantic/ia-sb.el b/lisp/cedet/semantic/ia-sb.el
index 47a4ce322ca..76f32345cf7 100644
--- a/lisp/cedet/semantic/ia-sb.el
+++ b/lisp/cedet/semantic/ia-sb.el
@@ -1,6 +1,6 @@
;;; semantic/ia-sb.el --- Speedbar analysis display interactor -*- lexical-binding: t; -*-
-;; Copyright (C) 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
;; Keywords: syntax
diff --git a/lisp/cedet/semantic/ia.el b/lisp/cedet/semantic/ia.el
index 890c6dac51a..7fec56afaa3 100644
--- a/lisp/cedet/semantic/ia.el
+++ b/lisp/cedet/semantic/ia.el
@@ -1,6 +1,6 @@
;;; semantic/ia.el --- Interactive Analysis functions -*- lexical-binding: t; -*-
-;; Copyright (C) 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2000-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
;; Keywords: syntax
diff --git a/lisp/cedet/semantic/idle.el b/lisp/cedet/semantic/idle.el
index 58f162e67f7..2313e1c0703 100644
--- a/lisp/cedet/semantic/idle.el
+++ b/lisp/cedet/semantic/idle.el
@@ -1,6 +1,6 @@
;;; idle.el --- Schedule parsing tasks in idle time -*- lexical-binding: t; -*-
-;; Copyright (C) 2003-2006, 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003-2006, 2008-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
;; Keywords: syntax
diff --git a/lisp/cedet/semantic/imenu.el b/lisp/cedet/semantic/imenu.el
index a28f050f3a0..e13eec209ed 100644
--- a/lisp/cedet/semantic/imenu.el
+++ b/lisp/cedet/semantic/imenu.el
@@ -1,6 +1,6 @@
;;; semantic/imenu.el --- Use Semantic as an imenu tag generator -*- lexical-binding: t; -*-
-;; Copyright (C) 2000-2005, 2007-2008, 2010-2023 Free Software
+;; Copyright (C) 2000-2005, 2007-2008, 2010-2024 Free Software
;; Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
@@ -32,6 +32,8 @@
;; (setq imenu-create-index-function 'semantic-create-imenu-index)
;; ))
+;;; Code:
+
(require 'semantic)
(require 'semantic/format)
(require 'semantic/db)
@@ -134,7 +136,6 @@ Tags of those classes will be given submenu with children.
By default, a `type' has interesting children. In Texinfo, however, a
`section' has interesting children.")
-;;; Code:
(defun semantic-imenu-tag-overlay (tag)
"Return the overlay belonging to tag.
If TAG doesn't have an overlay, and instead as a vector of positions,
@@ -469,9 +470,8 @@ Clears all imenu menus that may be depending on the database."
;; buffer, there is a much more efficient way of doing this.
;; Advise `which-function' so that we optionally use semantic tags
;; instead, and get better stuff.
-(require 'advice)
-(defvar semantic-which-function 'semantic-default-which-function
+(defvar semantic-which-function #'semantic-default-which-function
"Function to convert semantic tags into `which-function' text.")
(defcustom semantic-which-function-use-color nil
diff --git a/lisp/cedet/semantic/java.el b/lisp/cedet/semantic/java.el
index e65dcdb2db3..7e6a252e423 100644
--- a/lisp/cedet/semantic/java.el
+++ b/lisp/cedet/semantic/java.el
@@ -1,6 +1,6 @@
;;; semantic/java.el --- Semantic functions for Java -*- lexical-binding: t; -*-
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
;; Author: David Ponce <david@dponce.com>
diff --git a/lisp/cedet/semantic/lex-spp.el b/lisp/cedet/semantic/lex-spp.el
index 6a16845ecf2..a4be5bf67e2 100644
--- a/lisp/cedet/semantic/lex-spp.el
+++ b/lisp/cedet/semantic/lex-spp.el
@@ -1,6 +1,6 @@
;;; semantic/lex-spp.el --- Semantic Lexical Pre-processor -*- lexical-binding: t; -*-
-;; Copyright (C) 2006-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2006-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
@@ -434,8 +434,7 @@ continue processing recursively."
(symbolp (car (car val))))
(mapconcat (lambda (subtok)
(semantic-lex-spp-one-token-to-txt subtok))
- val
- ""))
+ val))
;; If val is nil, that's probably wrong.
;; Found a system header case where this was true.
((null val) "")
@@ -699,8 +698,7 @@ be merged recursively."
(message "Invalid merge macro encountered; \
will return empty string instead.")
"")))
- txt
- ""))
+ txt))
(defun semantic-lex-spp-find-closing-macro ()
"Find next macro which closes a scope through a close-paren.
diff --git a/lisp/cedet/semantic/lex.el b/lisp/cedet/semantic/lex.el
index 5fd1fd45400..b32cb96bed9 100644
--- a/lisp/cedet/semantic/lex.el
+++ b/lisp/cedet/semantic/lex.el
@@ -1,6 +1,6 @@
;;; semantic/lex.el --- Lexical Analyzer builder -*- lexical-binding:t -*-
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/lisp/cedet/semantic/mru-bookmark.el b/lisp/cedet/semantic/mru-bookmark.el
index b8d28eb7b08..4b4b5bd7235 100644
--- a/lisp/cedet/semantic/mru-bookmark.el
+++ b/lisp/cedet/semantic/mru-bookmark.el
@@ -1,6 +1,6 @@
;;; semantic/mru-bookmark.el --- Automatic bookmark tracking -*- lexical-binding: t; -*-
-;; Copyright (C) 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/lisp/cedet/semantic/sb.el b/lisp/cedet/semantic/sb.el
index 17cf00cd3c4..aa472ef681e 100644
--- a/lisp/cedet/semantic/sb.el
+++ b/lisp/cedet/semantic/sb.el
@@ -1,6 +1,6 @@
;;; semantic/sb.el --- Semantic tag display for speedbar -*- lexical-binding: t; -*-
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
;; Keywords: syntax
diff --git a/lisp/cedet/semantic/scope.el b/lisp/cedet/semantic/scope.el
index 956e901d538..a6eeb7b98a8 100644
--- a/lisp/cedet/semantic/scope.el
+++ b/lisp/cedet/semantic/scope.el
@@ -1,6 +1,6 @@
;;; semantic/scope.el --- Analyzer Scope Calculations -*- lexical-binding: t; -*-
-;; Copyright (C) 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/lisp/cedet/semantic/senator.el b/lisp/cedet/semantic/senator.el
index ca4334eaff5..aec251a0dc6 100644
--- a/lisp/cedet/semantic/senator.el
+++ b/lisp/cedet/semantic/senator.el
@@ -1,6 +1,6 @@
;;; semantic/senator.el --- SEmantic NAvigaTOR -*- lexical-binding: t; -*-
-;; Copyright (C) 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2000-2024 Free Software Foundation, Inc.
;; Author: David Ponce <david@dponce.com>
;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/cedet/semantic/sort.el b/lisp/cedet/semantic/sort.el
index aebd50a649b..5e2dca03f64 100644
--- a/lisp/cedet/semantic/sort.el
+++ b/lisp/cedet/semantic/sort.el
@@ -1,6 +1,6 @@
;;; semantic/sort.el --- Utilities for sorting and re-arranging tag tables. -*- lexical-binding: t; -*-
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
;; Keywords: syntax
diff --git a/lisp/cedet/semantic/symref.el b/lisp/cedet/semantic/symref.el
index 1ebd7ea154b..5c487a7f44d 100644
--- a/lisp/cedet/semantic/symref.el
+++ b/lisp/cedet/semantic/symref.el
@@ -1,6 +1,6 @@
;;; semantic/symref.el --- Symbol Reference API -*- lexical-binding: t; -*-
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/lisp/cedet/semantic/symref/cscope.el b/lisp/cedet/semantic/symref/cscope.el
index 2d2e3e134aa..afe7829302c 100644
--- a/lisp/cedet/semantic/symref/cscope.el
+++ b/lisp/cedet/semantic/symref/cscope.el
@@ -1,6 +1,6 @@
;;; semantic/symref/cscope.el --- Semantic-symref support via cscope -*- lexical-binding: t; -*-
-;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/lisp/cedet/semantic/symref/filter.el b/lisp/cedet/semantic/symref/filter.el
index efc4cb06b83..300f165282a 100644
--- a/lisp/cedet/semantic/symref/filter.el
+++ b/lisp/cedet/semantic/symref/filter.el
@@ -1,6 +1,6 @@
;;; semantic/symref/filter.el --- Filter symbol reference hits for accuracy -*- lexical-binding: t; -*-
-;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/lisp/cedet/semantic/symref/global.el b/lisp/cedet/semantic/symref/global.el
index d13222855af..bfedbd3b366 100644
--- a/lisp/cedet/semantic/symref/global.el
+++ b/lisp/cedet/semantic/symref/global.el
@@ -1,6 +1,6 @@
;;; semantic/symref/global.el --- Use GNU Global for symbol references -*- lexical-binding: t; -*-
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/lisp/cedet/semantic/symref/grep.el b/lisp/cedet/semantic/symref/grep.el
index cebeac3adca..83e3bc36073 100644
--- a/lisp/cedet/semantic/symref/grep.el
+++ b/lisp/cedet/semantic/symref/grep.el
@@ -1,6 +1,6 @@
;;; semantic/symref/grep.el --- Symref implementation using find/grep -*- lexical-binding: t; -*-
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/lisp/cedet/semantic/symref/idutils.el b/lisp/cedet/semantic/symref/idutils.el
index 3052070da75..7af5146bbbb 100644
--- a/lisp/cedet/semantic/symref/idutils.el
+++ b/lisp/cedet/semantic/symref/idutils.el
@@ -1,6 +1,6 @@
;;; semantic/symref/idutils.el --- Symref implementation for idutils -*- lexical-binding: t; -*-
-;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/lisp/cedet/semantic/symref/list.el b/lisp/cedet/semantic/symref/list.el
index 4b4c968cf81..5239a8a33be 100644
--- a/lisp/cedet/semantic/symref/list.el
+++ b/lisp/cedet/semantic/symref/list.el
@@ -1,6 +1,6 @@
;;; semantic/symref/list.el --- Symref Output List UI -*- lexical-binding: t; -*-
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/lisp/cedet/semantic/tag-file.el b/lisp/cedet/semantic/tag-file.el
index ee32adeb574..ed2db82f9a0 100644
--- a/lisp/cedet/semantic/tag-file.el
+++ b/lisp/cedet/semantic/tag-file.el
@@ -1,6 +1,6 @@
;;; semantic/tag-file.el --- Routines that find files based on tags. -*- lexical-binding: t; -*-
-;; Copyright (C) 1999-2005, 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2005, 2007-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
;; Keywords: syntax
diff --git a/lisp/cedet/semantic/tag-ls.el b/lisp/cedet/semantic/tag-ls.el
index fb01e0365ac..1854acd59a5 100644
--- a/lisp/cedet/semantic/tag-ls.el
+++ b/lisp/cedet/semantic/tag-ls.el
@@ -1,6 +1,6 @@
;;; semantic/tag-ls.el --- Language Specific override functions for tags -*- lexical-binding: t; -*-
-;; Copyright (C) 1999-2004, 2006-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2004, 2006-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/lisp/cedet/semantic/tag-write.el b/lisp/cedet/semantic/tag-write.el
index d32a85d6a00..cee1c53b8b2 100644
--- a/lisp/cedet/semantic/tag-write.el
+++ b/lisp/cedet/semantic/tag-write.el
@@ -1,6 +1,6 @@
;;; semantic/tag-write.el --- Write tags to a text stream -*- lexical-binding: t; -*-
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/lisp/cedet/semantic/tag.el b/lisp/cedet/semantic/tag.el
index 4c1694ddd6b..18a0b4caee2 100644
--- a/lisp/cedet/semantic/tag.el
+++ b/lisp/cedet/semantic/tag.el
@@ -1,6 +1,6 @@
;;; semantic/tag.el --- Tag creation and access -*- lexical-binding: t; -*-
-;; Copyright (C) 1999-2005, 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2005, 2007-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/lisp/cedet/semantic/texi.el b/lisp/cedet/semantic/texi.el
index 45e03cb9102..6374d995d0a 100644
--- a/lisp/cedet/semantic/texi.el
+++ b/lisp/cedet/semantic/texi.el
@@ -1,6 +1,6 @@
;;; semantic/texi.el --- Semantic details for Texinfo files -*- lexical-binding: t; -*-
-;; Copyright (C) 2001-2005, 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2005, 2007-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/lisp/cedet/semantic/util-modes.el b/lisp/cedet/semantic/util-modes.el
index 92b9f84ebb3..c785c3d8ee2 100644
--- a/lisp/cedet/semantic/util-modes.el
+++ b/lisp/cedet/semantic/util-modes.el
@@ -1,6 +1,6 @@
;;; semantic/util-modes.el --- Semantic minor modes -*- lexical-binding: t; -*-
-;; Copyright (C) 2000-2005, 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2000-2005, 2007-2024 Free Software Foundation, Inc.
;; Authors: Eric M. Ludlam <zappo@gnu.org>
;; David Ponce <david@dponce.com>
diff --git a/lisp/cedet/semantic/util.el b/lisp/cedet/semantic/util.el
index 2cd3184d006..f3c33c16ebc 100644
--- a/lisp/cedet/semantic/util.el
+++ b/lisp/cedet/semantic/util.el
@@ -1,6 +1,6 @@
;;; semantic/util.el --- Utilities for use with semantic tag tables -*- lexical-binding: t; -*-
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
;; Keywords: syntax
diff --git a/lisp/cedet/semantic/wisent.el b/lisp/cedet/semantic/wisent.el
index d135adf4d3b..15b222aca85 100644
--- a/lisp/cedet/semantic/wisent.el
+++ b/lisp/cedet/semantic/wisent.el
@@ -1,6 +1,6 @@
;;; semantic/wisent.el --- Wisent - Semantic gateway -*- lexical-binding: t; -*-
-;; Copyright (C) 2001-2007, 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2007, 2009-2024 Free Software Foundation, Inc.
;; Author: David Ponce <david@dponce.com>
;; Created: 30 Aug 2001
diff --git a/lisp/cedet/semantic/wisent/comp.el b/lisp/cedet/semantic/wisent/comp.el
index d13b2cf326d..debf9fc97b2 100644
--- a/lisp/cedet/semantic/wisent/comp.el
+++ b/lisp/cedet/semantic/wisent/comp.el
@@ -1,6 +1,6 @@
;;; semantic/wisent/comp.el --- GNU Bison for Emacs - Grammar compiler -*- lexical-binding: t; -*-
-;; Copyright (C) 1984, 1986, 1989, 1992, 1995, 2000-2007, 2009-2023 Free
+;; Copyright (C) 1984, 1986, 1989, 1992, 1995, 2000-2007, 2009-2024 Free
;; Software Foundation, Inc.
;; Author: David Ponce <david@dponce.com>
diff --git a/lisp/cedet/semantic/wisent/grammar.el b/lisp/cedet/semantic/wisent/grammar.el
index b121b05befe..7911dc04564 100644
--- a/lisp/cedet/semantic/wisent/grammar.el
+++ b/lisp/cedet/semantic/wisent/grammar.el
@@ -1,6 +1,6 @@
;;; semantic/wisent/grammar.el --- Wisent's input grammar mode -*- lexical-binding: t; -*-
-;; Copyright (C) 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2024 Free Software Foundation, Inc.
;;
;; Author: David Ponce <david@dponce.com>
;; Created: 26 Aug 2002
diff --git a/lisp/cedet/semantic/wisent/java-tags.el b/lisp/cedet/semantic/wisent/java-tags.el
index 3bac18a257c..ed62d2c3a9c 100644
--- a/lisp/cedet/semantic/wisent/java-tags.el
+++ b/lisp/cedet/semantic/wisent/java-tags.el
@@ -1,6 +1,6 @@
;;; semantic/wisent/java-tags.el --- Java LALR parser for Emacs -*- lexical-binding: t; -*-
-;; Copyright (C) 2001-2006, 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2006, 2009-2024 Free Software Foundation, Inc.
;; Author: David Ponce <david@dponce.com>
;; Created: 15 Dec 2001
diff --git a/lisp/cedet/semantic/wisent/javascript.el b/lisp/cedet/semantic/wisent/javascript.el
index 1750d53d46d..7a1a8637aae 100644
--- a/lisp/cedet/semantic/wisent/javascript.el
+++ b/lisp/cedet/semantic/wisent/javascript.el
@@ -1,6 +1,6 @@
;;; semantic/wisent/javascript.el --- javascript parser support -*- lexical-binding: t; -*-
-;; Copyright (C) 2005, 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2005, 2009-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
;; Keywords: syntax
diff --git a/lisp/cedet/semantic/wisent/python.el b/lisp/cedet/semantic/wisent/python.el
index c6a8a35d8df..73f08beaa28 100644
--- a/lisp/cedet/semantic/wisent/python.el
+++ b/lisp/cedet/semantic/wisent/python.el
@@ -1,6 +1,6 @@
;;; wisent-python.el --- Semantic support for Python -*- lexical-binding: t; -*-
-;; Copyright (C) 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2024 Free Software Foundation, Inc.
;; Author: Richard Kim <emacs18@gmail.com>
;; Created: June 2002
@@ -262,18 +262,19 @@ the indentation of the current line."
;; Loop lexer to handle tokens in current line.
t)
;; Indentation decreased
- ((progn
- ;; Pop items from indentation stack
- (while (< curr-indent last-indent)
- (pop wisent-python-indent-stack)
- (setq semantic-lex-current-depth (1- semantic-lex-current-depth)
- last-indent (car wisent-python-indent-stack))
- (semantic-lex-push-token
- (semantic-lex-token 'DEDENT last-pos (point))))
- (= last-pos (point)))
- ;; If pos did not change, then we must return nil so that
- ;; other lexical analyzers can be run.
- nil))))
+ (t
+ ;; Pop items from indentation stack
+ (while (< curr-indent last-indent)
+ (pop wisent-python-indent-stack)
+ (setq semantic-lex-current-depth (1- semantic-lex-current-depth)
+ last-indent (car wisent-python-indent-stack))
+ (semantic-lex-push-token
+ (semantic-lex-token 'DEDENT last-pos (point))))
+ ;; (if (= last-pos (point))
+ ;; ;; If pos did not change, then we must return nil so that
+ ;; ;; other lexical analyzers can be run.
+ ;; nil)
+ ))))
;; All the work was done in the above analyzer matching condition.
)
diff --git a/lisp/cedet/semantic/wisent/wisent.el b/lisp/cedet/semantic/wisent/wisent.el
index c2bb429ef76..a6c5ba7c087 100644
--- a/lisp/cedet/semantic/wisent/wisent.el
+++ b/lisp/cedet/semantic/wisent/wisent.el
@@ -1,6 +1,6 @@
;;; semantic/wisent/wisent.el --- GNU Bison for Emacs - Runtime -*- lexical-binding: t; -*-
-;; Copyright (C) 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2024 Free Software Foundation, Inc.
;; Author: David Ponce <david@dponce.com>
;; Created: 30 January 2002
diff --git a/lisp/cedet/srecode.el b/lisp/cedet/srecode.el
index 7f606a6eb56..1dc7f98f7eb 100644
--- a/lisp/cedet/srecode.el
+++ b/lisp/cedet/srecode.el
@@ -1,6 +1,6 @@
;;; srecode.el --- Semantic buffer evaluator. -*- lexical-binding: t -*-
-;; Copyright (C) 2005-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2005-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
;; Keywords: codegeneration
diff --git a/lisp/cedet/srecode/args.el b/lisp/cedet/srecode/args.el
index 78b217d6b7e..f4f79a98ffd 100644
--- a/lisp/cedet/srecode/args.el
+++ b/lisp/cedet/srecode/args.el
@@ -1,6 +1,6 @@
;;; srecode/args.el --- Provide some simple template arguments -*- lexical-binding: t; -*-
-;; Copyright (C) 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/lisp/cedet/srecode/compile.el b/lisp/cedet/srecode/compile.el
index 77d3fee9df7..b960873506d 100644
--- a/lisp/cedet/srecode/compile.el
+++ b/lisp/cedet/srecode/compile.el
@@ -1,6 +1,6 @@
;;; srecode/compile --- Compilation of srecode template files. -*- lexical-binding: t; -*-
-;; Copyright (C) 2005, 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2005, 2007-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
;; Keywords: codegeneration
diff --git a/lisp/cedet/srecode/cpp.el b/lisp/cedet/srecode/cpp.el
index 0be8db03bbc..9b3f0b85dcb 100644
--- a/lisp/cedet/srecode/cpp.el
+++ b/lisp/cedet/srecode/cpp.el
@@ -1,6 +1,6 @@
;;; srecode/cpp.el --- C++ specific handlers for Semantic Recoder -*- lexical-binding: t; -*-
-;; Copyright (C) 2007, 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2007, 2009-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
;; Jan Moringen <scymtym@users.sourceforge.net>
diff --git a/lisp/cedet/srecode/ctxt.el b/lisp/cedet/srecode/ctxt.el
index ebcab20303f..bad9836bb43 100644
--- a/lisp/cedet/srecode/ctxt.el
+++ b/lisp/cedet/srecode/ctxt.el
@@ -1,6 +1,6 @@
;;; srecode/ctxt.el --- Derive a context from the source buffer. -*- lexical-binding: t; -*-
-;; Copyright (C) 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/lisp/cedet/srecode/dictionary.el b/lisp/cedet/srecode/dictionary.el
index 25d595bf3c3..03d25466cfc 100644
--- a/lisp/cedet/srecode/dictionary.el
+++ b/lisp/cedet/srecode/dictionary.el
@@ -1,6 +1,6 @@
;;; srecode/dictionary.el --- Dictionary code for the semantic recoder. -*- lexical-binding: t; -*-
-;; Copyright (C) 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/lisp/cedet/srecode/document.el b/lisp/cedet/srecode/document.el
index 40bb7f9e480..f4d192da38c 100644
--- a/lisp/cedet/srecode/document.el
+++ b/lisp/cedet/srecode/document.el
@@ -1,6 +1,6 @@
;;; srecode/document.el --- Documentation (comment) generation -*- lexical-binding: t; -*-
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/lisp/cedet/srecode/el.el b/lisp/cedet/srecode/el.el
index bf034691103..ee88a056793 100644
--- a/lisp/cedet/srecode/el.el
+++ b/lisp/cedet/srecode/el.el
@@ -1,6 +1,6 @@
;;; srecode/el.el --- Emacs Lisp specific arguments -*- lexical-binding: t; -*-
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/lisp/cedet/srecode/expandproto.el b/lisp/cedet/srecode/expandproto.el
index d5c22c0d71a..37b3fe3d78c 100644
--- a/lisp/cedet/srecode/expandproto.el
+++ b/lisp/cedet/srecode/expandproto.el
@@ -1,6 +1,6 @@
;;; srecode/expandproto.el --- Expanding prototypes. -*- lexical-binding: t; -*-
-;; Copyright (C) 2007, 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2007, 2009-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/lisp/cedet/srecode/extract.el b/lisp/cedet/srecode/extract.el
index 4eb7632b721..27a96431062 100644
--- a/lisp/cedet/srecode/extract.el
+++ b/lisp/cedet/srecode/extract.el
@@ -1,6 +1,6 @@
;;; srecode/extract.el --- Extract content from previously inserted macro. -*- lexical-binding: t; -*-
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
@@ -33,7 +33,7 @@
;; or deep template calls can be extracted.
;;
;; This code was specifically written for srecode-document, which
-;; wants to extract user written text, and re-use it in a reformatted
+;; wants to extract user written text, and reuse it in a reformatted
;; comment.
(require 'srecode)
diff --git a/lisp/cedet/srecode/fields.el b/lisp/cedet/srecode/fields.el
index 804b9937f6d..72ee2e91511 100644
--- a/lisp/cedet/srecode/fields.el
+++ b/lisp/cedet/srecode/fields.el
@@ -1,6 +1,6 @@
;;; srecode/fields.el --- Handling type-in fields in a buffer. -*- lexical-binding: t; -*-
;;
-;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
;;
;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/lisp/cedet/srecode/filters.el b/lisp/cedet/srecode/filters.el
index 1bb81b4a951..2b7fee06687 100644
--- a/lisp/cedet/srecode/filters.el
+++ b/lisp/cedet/srecode/filters.el
@@ -1,6 +1,6 @@
;;; srecode/filters.el --- Filters for use in template variables. -*- lexical-binding: t; -*-
-;; Copyright (C) 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/lisp/cedet/srecode/find.el b/lisp/cedet/srecode/find.el
index cfd64edfc98..41030aa6944 100644
--- a/lisp/cedet/srecode/find.el
+++ b/lisp/cedet/srecode/find.el
@@ -1,6 +1,6 @@
;;;; srecode/find.el --- Tools for finding templates in the database. -*- lexical-binding: t; -*-
-;; Copyright (C) 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
@@ -34,12 +34,12 @@
(defun srecode-table (&optional mode)
"Return the currently active Semantic Recoder table for this buffer.
Optional argument MODE specifies the mode table to use."
- (let* ((modeq (or mode major-mode))
- (table (srecode-get-mode-table modeq)))
+ (let ((modes (derived-mode-all-parents (or mode major-mode)))
+ (table nil))
;; If there isn't one, keep searching backwards for a table.
- (while (and (not table) (setq modeq (get-mode-local-parent modeq)))
- (setq table (srecode-get-mode-table modeq)))
+ (while (and modes (not (setq table (srecode-get-mode-table (car modes)))))
+ (setq modes (cdr modes)))
;; Last ditch effort.
(when (not table)
@@ -57,35 +57,23 @@ Templates are found in the SRecode Template Map.
See `srecode-get-maps' for more.
APPNAME is the name of an application. In this case,
all template files for that application will be loaded."
- (let ((files
- (apply #'append
- (mapcar
- (if appname
+ (dolist (mmode (cons 'default (reverse (derived-mode-all-parents mmode))))
+ (let ((files
+ (apply #'append
+ (mapcar
+ (if appname
+ (lambda (map)
+ (srecode-map-entries-for-app-and-mode map appname mmode))
(lambda (map)
- (srecode-map-entries-for-app-and-mode map appname mmode))
- (lambda (map)
- (srecode-map-entries-for-mode map mmode)))
- (srecode-get-maps))))
- )
- ;; Don't recurse if we are already the 'default state.
- (when (not (eq mmode 'default))
- ;; Are we a derived mode? If so, get the parent mode's
- ;; templates loaded too.
- (if (get-mode-local-parent mmode)
- (srecode-load-tables-for-mode (get-mode-local-parent mmode)
- appname)
- ;; No parent mode, all templates depend on the defaults being
- ;; loaded in, so get that in instead.
- (srecode-load-tables-for-mode 'default appname)))
+ (srecode-map-entries-for-mode map mmode)))
+ (srecode-get-maps)))))
- ;; Load in templates for our major mode.
- (dolist (f files)
- (let ((mt (srecode-get-mode-table mmode))
- )
- (when (or (not mt) (not (srecode-mode-table-find mt (car f))))
- (srecode-compile-file (car f)))
- ))
- ))
+ ;; Load in templates for our major mode.
+ (when files
+ (let ((mt (srecode-get-mode-table mmode)))
+ (dolist (f files)
+ (when (not (and mt (srecode-mode-table-find mt (car f))))
+ (srecode-compile-file (car f)))))))))
;;; PROJECT
;;
@@ -227,12 +215,12 @@ Optional argument MODE is the major mode to look for.
Optional argument HASH is the hash table to fill in.
Optional argument PREDICATE can be used to filter the returned
templates."
- (let* ((mhash (or hash (make-hash-table :test 'equal)))
- (mmode (or mode major-mode))
- (parent-mode (get-mode-local-parent mmode)))
- ;; Get the parent hash table filled into our current hash.
- (unless (eq mode 'default)
- (srecode-all-template-hash (or parent-mode 'default) mhash))
+ (let* ((mhash (or hash (make-hash-table :test 'equal))))
+ (dolist (mmode (cons 'default
+ ;; Get the parent hash table filled into our
+ ;; current hash.
+ (reverse (derived-mode-all-parents
+ (or mode major-mode)))))
;; Load up the hash table for our current mode.
(let* ((mt (srecode-get-mode-table mmode))
@@ -246,7 +234,7 @@ templates."
(funcall predicate temp))
(puthash key temp mhash)))
(oref tab namehash))))
- mhash)))
+ mhash))))
(defun srecode-calculate-default-template-string (hash)
"Calculate the name of the template to use as a DEFAULT.
diff --git a/lisp/cedet/srecode/getset.el b/lisp/cedet/srecode/getset.el
index 9ef85cbf5aa..046cba330af 100644
--- a/lisp/cedet/srecode/getset.el
+++ b/lisp/cedet/srecode/getset.el
@@ -1,6 +1,6 @@
;;; srecode/getset.el --- Package for inserting new get/set methods. -*- lexical-binding: t; -*-
-;; Copyright (C) 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/lisp/cedet/srecode/insert.el b/lisp/cedet/srecode/insert.el
index 04f5ef55e05..b08b3583cd4 100644
--- a/lisp/cedet/srecode/insert.el
+++ b/lisp/cedet/srecode/insert.el
@@ -1,6 +1,6 @@
;;; srecode/insert.el --- Insert srecode templates to an output stream -*- lexical-binding:t -*-
-;; Copyright (C) 2005, 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2005, 2007-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/lisp/cedet/srecode/java.el b/lisp/cedet/srecode/java.el
index 8d43111dd4d..66abd736de4 100644
--- a/lisp/cedet/srecode/java.el
+++ b/lisp/cedet/srecode/java.el
@@ -1,6 +1,6 @@
;;; srecode/java.el --- Srecode Java support -*- lexical-binding: t; -*-
-;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/lisp/cedet/srecode/map.el b/lisp/cedet/srecode/map.el
index 125459d6eeb..30f4c755e17 100644
--- a/lisp/cedet/srecode/map.el
+++ b/lisp/cedet/srecode/map.el
@@ -1,6 +1,6 @@
;;; srecode/map.el --- Manage a template file map -*- lexical-binding: t; -*-
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
@@ -49,7 +49,8 @@
"The save location for SRecode's map file.
If the save file is nil, then the MAP is not saved between sessions."
:group 'srecode
- :type 'file)
+ :type '(choice (const :tag "Don't save" nil)
+ file))
(defclass srecode-map (eieio-persistent)
((fileheaderline :initform ";; SRECODE TEMPLATE MAP")
@@ -75,7 +76,7 @@ Each app keys to an alist of files and modes (as above.)")
"Return the entries in MAP for major MODE."
(let ((ans nil))
(dolist (f (oref map files))
- (when (mode-local-use-bindings-p mode (cdr f))
+ (when (provided-mode-derived-p mode (cdr f))
(setq ans (cons f ans))))
ans))
diff --git a/lisp/cedet/srecode/mode.el b/lisp/cedet/srecode/mode.el
index d45f9a4bcd6..1774a52c0ab 100644
--- a/lisp/cedet/srecode/mode.el
+++ b/lisp/cedet/srecode/mode.el
@@ -1,6 +1,6 @@
;;; srecode/mode.el --- Minor mode for managing and using SRecode templates -*- lexical-binding: t; -*-
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/lisp/cedet/srecode/semantic.el b/lisp/cedet/srecode/semantic.el
index 68fedf6fc2c..90a25d543d5 100644
--- a/lisp/cedet/srecode/semantic.el
+++ b/lisp/cedet/srecode/semantic.el
@@ -1,6 +1,6 @@
;;; srecode/semantic.el --- Semantic specific extensions to SRecode -*- lexical-binding:t -*-
-;; Copyright (C) 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/lisp/cedet/srecode/srt-mode.el b/lisp/cedet/srecode/srt-mode.el
index 6bd416c5690..fbe88bd1fab 100644
--- a/lisp/cedet/srecode/srt-mode.el
+++ b/lisp/cedet/srecode/srt-mode.el
@@ -1,6 +1,6 @@
;;; srecode/srt-mode.el --- Major mode for writing screcode macros -*- lexical-binding: t; -*-
-;; Copyright (C) 2005, 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2005, 2007-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -420,7 +420,7 @@ Moves to the end of one named section."
(when (string= (car (car subdicts)) name)
(setq res (cdr (car subdicts))))
(setq subdicts (cdr subdicts)))
- ;; Pre-pend our global vars.
+ ;; Prepend our global vars.
(append global res))
;; If we aren't in a subsection, just do the global variables
global
diff --git a/lisp/cedet/srecode/srt.el b/lisp/cedet/srecode/srt.el
index bd2f62f8fd6..556dff82f97 100644
--- a/lisp/cedet/srecode/srt.el
+++ b/lisp/cedet/srecode/srt.el
@@ -1,6 +1,6 @@
;;; srecode/srt.el --- argument handlers for SRT files -*- lexical-binding: t; -*-
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/lisp/cedet/srecode/table.el b/lisp/cedet/srecode/table.el
index de151049f7f..8ac26c9bf01 100644
--- a/lisp/cedet/srecode/table.el
+++ b/lisp/cedet/srecode/table.el
@@ -1,6 +1,6 @@
;;; srecode/table.el --- Tables of Semantic Recoders -*- lexical-binding: t; -*-
-;; Copyright (C) 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
@@ -137,41 +137,36 @@ Tracks all the template-tables for a specific major mode.")
"Get the SRecoder mode table for the major mode MODE.
This will find the mode table specific to MODE, and then
calculate all inherited templates from parent modes."
- (let ((table nil)
- (tmptable nil))
- (while mode
- (setq tmptable (eieio-instance-tracker-find
- mode 'major-mode 'srecode-mode-table-list)
- mode (get-mode-local-parent mode))
- (when tmptable
- (if (not table)
- (progn
- ;; If this is the first, update tables to have
- ;; all the mode specific tables in it.
- (setq table tmptable)
- (oset table tables (oref table modetables)))
- ;; If there already is a table, then reset the tables
- ;; slot to include all the tables belonging to this new child node.
- (oset table tables (append (oref table modetables)
- (oref tmptable modetables)))))
- )
+ (let ((table nil))
+ (dolist (mode (derived-mode-all-parents mode))
+ (let ((tmptable (eieio-instance-tracker-find
+ mode 'major-mode 'srecode-mode-table-list)))
+ (when tmptable
+ (if (not table)
+ (progn
+ ;; If this is the first, update tables to have
+ ;; all the mode specific tables in it.
+ (setq table tmptable)
+ (oset table tables (oref table modetables)))
+ ;; If there already is a table, then reset the tables
+ ;; slot to include all the tables belonging to this new child node.
+ (oset table tables (append (oref table modetables)
+ (oref tmptable modetables)))))
+ ))
table))
(defun srecode-make-mode-table (mode)
"Get the SRecoder mode table for the major mode MODE."
(let ((old (eieio-instance-tracker-find
mode 'major-mode 'srecode-mode-table-list)))
- (if old
- old
- (let* ((ms (if (stringp mode) mode (symbol-name mode)))
- (new (srecode-mode-table ms
- :major-mode mode
- :modetables nil
- :tables nil)))
- ;; Save this new mode table in that mode's variable.
- (eval `(setq-mode-local ,mode srecode-table ,new) t)
+ (or old
+ (let* ((new (srecode-mode-table :major-mode mode
+ :modetables nil
+ :tables nil)))
+ ;; Save this new mode table in that mode's variable.
+ (eval `(setq-mode-local ,mode srecode-table ,new) t)
- new))))
+ new))))
(cl-defmethod srecode-mode-table-find ((mt srecode-mode-table) file)
"Look in the mode table MT for a template table from FILE.
diff --git a/lisp/cedet/srecode/template.el b/lisp/cedet/srecode/template.el
index 4048e13e602..2417f1f7ef6 100644
--- a/lisp/cedet/srecode/template.el
+++ b/lisp/cedet/srecode/template.el
@@ -1,6 +1,6 @@
;;; srecode/template.el --- SRecoder template language parser support. -*- lexical-binding: t; -*-
-;; Copyright (C) 2005, 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2005, 2007-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/lisp/cedet/srecode/texi.el b/lisp/cedet/srecode/texi.el
index 65af027fe19..dd54347faef 100644
--- a/lisp/cedet/srecode/texi.el
+++ b/lisp/cedet/srecode/texi.el
@@ -1,6 +1,6 @@
;;; srecode/texi.el --- Srecode texinfo support. -*- lexical-binding: t; -*-
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/lisp/char-fold.el b/lisp/char-fold.el
index 6da2dae8471..a620d4d8dc3 100644
--- a/lisp/char-fold.el
+++ b/lisp/char-fold.el
@@ -1,6 +1,6 @@
;;; char-fold.el --- match unicode to similar ASCII -*- lexical-binding: t; -*-
-;; Copyright (C) 2015-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2024 Free Software Foundation, Inc.
;; Maintainer: emacs-devel@gnu.org
;; Keywords: matching
diff --git a/lisp/chistory.el b/lisp/chistory.el
index e53499d9e05..2a2d55f66ae 100644
--- a/lisp/chistory.el
+++ b/lisp/chistory.el
@@ -1,6 +1,6 @@
;;; chistory.el --- list command history -*- lexical-binding: t -*-
-;; Copyright (C) 1985, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1985, 2001-2024 Free Software Foundation, Inc.
;; Author: K. Shane Hartman
;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/cmuscheme.el b/lisp/cmuscheme.el
index b3b8ae87ee3..c84a1809322 100644
--- a/lisp/cmuscheme.el
+++ b/lisp/cmuscheme.el
@@ -1,6 +1,6 @@
;;; cmuscheme.el --- Scheme process in a buffer. Adapted from tea.el -*- lexical-binding: t -*-
-;; Copyright (C) 1988-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1988-2024 Free Software Foundation, Inc.
;; Author: Olin Shivers <olin.shivers@cs.cmu.edu>
;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/color.el b/lisp/color.el
index f68cf5e6b17..078c12fbf47 100644
--- a/lisp/color.el
+++ b/lisp/color.el
@@ -1,6 +1,6 @@
;;; color.el --- Color manipulation library -*- lexical-binding:t -*-
-;; Copyright (C) 2010-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2010-2024 Free Software Foundation, Inc.
;; Authors: Julien Danjou <julien@danjou.info>
;; Drew Adams <drew.adams@oracle.com>
diff --git a/lisp/comint.el b/lisp/comint.el
index 777795bcb46..0a9cdb44bef 100644
--- a/lisp/comint.el
+++ b/lisp/comint.el
@@ -1,6 +1,6 @@
;;; comint.el --- general command interpreter in a window stuff -*- lexical-binding: t -*-
-;; Copyright (C) 1988, 1990, 1992-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1988, 1990, 1992-2024 Free Software Foundation, Inc.
;; Author: Olin Shivers <shivers@cs.cmu.edu>
;; Simon Marshall <simon@gnu.org>
@@ -260,6 +260,7 @@ to set this in a mode hook, rather than customize the default value."
(defcustom comint-pager nil
"If non-nil, the program to use for pagination of program output.
+If nil, use the default pager.
Some programs produce large amounts of output, and have provision for
pagination of their output through a filter program, commonly known as
@@ -2809,7 +2810,7 @@ If N is negative, find the previous or Nth previous match."
If `comint-use-prompt-regexp' is nil, then this means the beginning of
the Nth next `input' field, otherwise, it means the Nth occurrence of
text matching `comint-prompt-regexp'."
- (interactive "p")
+ (interactive "^p")
(if comint-use-prompt-regexp
;; Use comint-prompt-regexp
(let ((paragraph-start comint-prompt-regexp))
@@ -2846,7 +2847,7 @@ text matching `comint-prompt-regexp'."
If `comint-use-prompt-regexp' is nil, then this means the beginning of
the Nth previous `input' field, otherwise, it means the Nth occurrence of
text matching `comint-prompt-regexp'."
- (interactive "p")
+ (interactive "^p")
(comint-next-prompt (- n)))
;; State used by `comint-insert-previous-argument' when cycling.
@@ -2857,7 +2858,7 @@ text matching `comint-prompt-regexp'."
"If non-nil, `comint-insert-previous-argument' counts args from the end.
If this variable is nil, the default, `comint-insert-previous-argument'
counts the arguments from the beginning; if non-nil, it counts from
-the end instead. This allows to emulate the behavior of `ESC-NUM ESC-.'
+the end instead. This emulates the behavior of `ESC-NUM ESC-.'
in both Bash and zsh: in Bash, `number' counts from the
beginning (variable is nil), while in zsh, it counts from the end."
:type 'boolean
diff --git a/lisp/completion-preview.el b/lisp/completion-preview.el
new file mode 100644
index 00000000000..baadb4714b1
--- /dev/null
+++ b/lisp/completion-preview.el
@@ -0,0 +1,417 @@
+;;; completion-preview.el --- Preview completion with inline overlay -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2023-2024 Free Software Foundation, Inc.
+
+;; Author: Eshel Yaron <me@eshelyaron.com>
+;; Maintainer: Eshel Yaron <me@eshelyaron.com>
+;; Keywords: abbrev convenience
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; This library provides the Completion Preview mode. This minor mode
+;; displays a completion suggestion for the symbol at point in an
+;; overlay after point. Check out the customization group
+;; `completion-preview' for user options that you may want to tweak.
+;;
+;; To enable Completion Preview mode, use `completion-preview-mode'.
+;; To accept the completion suggestion, press TAB. If you want to
+;; ignore a completion suggestion, just go on editing or moving around
+;; the buffer. Completion Preview mode continues to update the
+;; suggestion as you type according to the text around point.
+;;
+;; The commands `completion-preview-next-candidate' and
+;; `completion-preview-prev-candidate' allow you to cycle the
+;; completion candidate that the preview suggests. These commands
+;; don't have a default keybinding, but you can bind them, for
+;; example, to M-n and M-p in `completion-preview-active-mode-map' to
+;; have them handy whenever the preview is visible.
+;;
+;; 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)
+;; symbol at point. The user option `completion-preview-commands'
+;; says which commands should trigger the completion preview. The
+;; user option `completion-preview-minimum-symbol-length' specifies a
+;; minimum number of consecutive characters with word or symbol syntax
+;; that should appear around point for Emacs to suggest a completion.
+;; By default, this option is set to 3, so Emacs suggests a completion
+;; if you type "foo", but typing just "fo" doesn't show the preview.
+
+;;; Code:
+
+(defgroup completion-preview nil
+ "In-buffer completion preview."
+ :group 'completion)
+
+(defcustom completion-preview-exact-match-only nil
+ "Whether to show completion preview only when there is an exact match.
+
+If this option is non-nil, Completion Preview mode only shows the
+preview when there is exactly one completion candidate that
+matches the symbol at point. Otherwise, if this option is nil,
+when there are multiple matching candidates the preview shows the
+first candidate, and you can cycle between the candidates with
+\\[completion-preview-next-candidate] and
+\\[completion-preview-prev-candidate]."
+ :type 'boolean
+ :version "30.1")
+
+(defcustom completion-preview-commands '(self-insert-command
+ insert-char
+ delete-backward-char
+ backward-delete-char-untabify
+ analyze-text-conversion)
+ "List of commands that should trigger completion preview."
+ :type '(repeat (function :tag "Command" :value self-insert-command))
+ :version "30.1")
+
+(defcustom completion-preview-minimum-symbol-length 3
+ "Minimum length of the symbol at point for showing completion preview."
+ :type 'natnum
+ :version "30.1")
+
+(defcustom completion-preview-message-format
+ "Completion suggestion %i out of %n"
+ "Message to show after cycling the completion preview suggestion.
+
+If the value is a string, `completion-preview-next-candidate' and
+`completion-preview-prev-candidate' display this string in the
+echo area, after substituting \"%i\" with the 1-based index of
+the completion suggestion that the preview is showing, and \"%n\"
+with the total number of available completion suggestions for the
+text around point.
+
+If this option is nil, these commands do not display any message."
+ :type '(choice (string :tag "Message format")
+ (const :tag "No message" nil))
+ :version "30.1")
+
+(defvar completion-preview-sort-function #'minibuffer--sort-by-length-alpha
+ "Sort function to use for choosing a completion candidate to preview.")
+
+(defface completion-preview
+ '((t :inherit shadow))
+ "Face for completion preview overlay."
+ :version "30.1")
+
+(defface completion-preview-exact
+ '((((supports :underline t))
+ :underline t :inherit completion-preview)
+ (((supports :weight bold))
+ :weight bold :inherit completion-preview)
+ (t :background "gray"))
+ "Face for exact completion preview overlay."
+ :version "30.1")
+
+(defface completion-preview-highlight
+ '((t :inherit highlight))
+ "Face for highlighting the completion preview when the mouse is over it."
+ :version "30.1")
+
+(defvar-keymap completion-preview-active-mode-map
+ :doc "Keymap for Completion Preview Active mode."
+ "C-i" #'completion-preview-insert
+ ;; "M-n" #'completion-preview-next-candidate
+ ;; "M-p" #'completion-preview-prev-candidate
+ )
+
+(defvar mouse-wheel-up-event)
+(defvar mouse-wheel-up-alternate-event)
+(defvar mouse-wheel-down-event)
+(defvar mouse-wheel-down-alternate-event)
+(defvar-keymap completion-preview--mouse-map
+ :doc "Keymap for mouse clicks on the completion preview."
+ "<down-mouse-1>" #'completion-preview-insert
+ "C-<down-mouse-1>" #'completion-at-point
+ "<down-mouse-2>" #'completion-at-point
+ (format "<%s>" mouse-wheel-up-event) #'completion-preview-prev-candidate
+ (format "<%s>" mouse-wheel-up-alternate-event) #'completion-preview-prev-candidate
+ (format "<%s>" mouse-wheel-down-event) #'completion-preview-next-candidate
+ (format "<%s>" mouse-wheel-down-alternate-event) #'completion-preview-next-candidate)
+
+(defvar-local completion-preview--overlay nil)
+
+(defvar completion-preview--internal-commands
+ '(completion-preview-next-candidate
+ completion-preview-prev-candidate
+ ;; Don't dismiss or update the preview when the user scrolls.
+ mwheel-scroll)
+ "List of commands that manipulate the completion preview.
+
+Completion Preview mode avoids updating the preview after these commands.")
+
+(defsubst completion-preview--internal-command-p ()
+ "Return non-nil if `this-command' manipulates the completion preview."
+ (memq this-command completion-preview--internal-commands))
+
+(defsubst completion-preview-require-certain-commands ()
+ "Check if `this-command' is one of `completion-preview-commands'."
+ (or (completion-preview--internal-command-p)
+ (memq this-command completion-preview-commands)))
+
+(defun completion-preview-require-minimum-symbol-length ()
+ "Check if the length of symbol at point is at least above a certain threshold.
+`completion-preview-minimum-symbol-length' determines that threshold."
+ (let ((bounds (bounds-of-thing-at-point 'symbol)))
+ (and bounds (<= completion-preview-minimum-symbol-length
+ (- (cdr bounds) (car bounds))))))
+
+(defun completion-preview-hide ()
+ "Hide the completion preview."
+ (when completion-preview--overlay
+ (delete-overlay completion-preview--overlay)
+ (setq completion-preview--overlay nil)))
+
+(defun completion-preview--make-overlay (pos string)
+ "Make preview overlay showing STRING at POS, or move existing preview there."
+ (if completion-preview--overlay
+ (move-overlay completion-preview--overlay pos pos)
+ (setq completion-preview--overlay (make-overlay pos pos))
+ (overlay-put completion-preview--overlay 'window (selected-window)))
+ (let ((previous (overlay-get completion-preview--overlay 'after-string)))
+ (unless (and previous (string= previous string)
+ (eq (get-text-property 0 'face previous)
+ (get-text-property 0 'face string)))
+ (add-text-properties 0 1 '(cursor 1) string)
+ (overlay-put completion-preview--overlay 'after-string string))
+ completion-preview--overlay))
+
+(defsubst completion-preview--get (prop)
+ "Return property PROP of the completion preview overlay."
+ (overlay-get completion-preview--overlay prop))
+
+(defun completion-preview--window-selection-change (window)
+ "Hide completion preview in WINDOW after switching to another window.
+Completion Preview mode adds this function to
+`window-selection-change-functions', which see."
+ (unless (or (eq window (selected-window))
+ (eq window (minibuffer-selected-window)))
+ (with-current-buffer (window-buffer window)
+ (completion-preview-active-mode -1))))
+
+(define-minor-mode completion-preview-active-mode
+ "Mode for when the completion preview is shown."
+ :interactive nil
+ (if completion-preview-active-mode
+ (add-hook 'window-selection-change-functions
+ #'completion-preview--window-selection-change nil t)
+ (remove-hook 'window-selection-change-functions
+ #'completion-preview--window-selection-change t)
+ (completion-preview-hide)))
+
+(defun completion-preview--try-table (table beg end props)
+ "Check TABLE for a completion matching the text between BEG and END.
+
+PROPS is a property list with additional information about TABLE.
+See `completion-at-point-functions' for more details.
+
+If TABLE contains a matching completion, return a list
+\(PREVIEW BEG END ALL BASE EXIT-FN) where PREVIEW is the text to
+show in the completion preview, ALL is the list of all matching
+completion candidates, BASE is a common prefix that TABLE elided
+from the start of each candidate, and EXIT-FN is either a
+function to call after inserting PREVIEW or nil. If TABLE does
+not contain matching completions, or if there are multiple
+matching completions and `completion-preview-exact-match-only' is
+non-nil, return nil instead."
+ (let* ((pred (plist-get props :predicate))
+ (exit-fn (plist-get props :exit-function))
+ (string (buffer-substring beg end))
+ (md (completion-metadata string table pred))
+ (sort-fn (or (completion-metadata-get md 'cycle-sort-function)
+ (completion-metadata-get md 'display-sort-function)
+ completion-preview-sort-function))
+ (all (let ((completion-lazy-hilit t))
+ (completion-all-completions string table pred
+ (- (point) beg) md)))
+ (last (last all))
+ (base (or (cdr last) 0))
+ (prefix (substring string base)))
+ (when last
+ (setcdr last nil)
+ (when-let ((sorted (funcall sort-fn
+ (delete prefix (all-completions prefix all)))))
+ (unless (and (cdr sorted) completion-preview-exact-match-only)
+ (list (propertize (substring (car sorted) (length prefix))
+ 'face (if (cdr sorted)
+ 'completion-preview
+ 'completion-preview-exact)
+ 'mouse-face 'completion-preview-highlight
+ 'keymap completion-preview--mouse-map)
+ (+ beg base) end sorted
+ (substring string 0 base) exit-fn))))))
+
+(defun completion-preview--capf-wrapper (capf)
+ "Translate return value of CAPF to properties for completion preview overlay."
+ (let ((res (ignore-errors (funcall capf))))
+ (and (consp res)
+ (not (functionp res))
+ (seq-let (beg end table &rest plist) res
+ (or (completion-preview--try-table table beg end plist)
+ (unless (eq 'no (plist-get plist :exclusive))
+ ;; Return non-nil to exclude other capfs.
+ '(nil)))))))
+
+(defun completion-preview--update ()
+ "Update completion preview."
+ (seq-let (preview beg end all base exit-fn)
+ (run-hook-wrapped
+ 'completion-at-point-functions
+ #'completion-preview--capf-wrapper)
+ (when preview
+ (let ((ov (completion-preview--make-overlay end preview)))
+ (overlay-put ov 'completion-preview-beg beg)
+ (overlay-put ov 'completion-preview-end end)
+ (overlay-put ov 'completion-preview-index 0)
+ (overlay-put ov 'completion-preview-cands all)
+ (overlay-put ov 'completion-preview-base base)
+ (overlay-put ov 'completion-preview-exit-fn exit-fn)
+ (completion-preview-active-mode)))))
+
+(defun completion-preview--show ()
+ "Show a new completion preview.
+
+Call `completion-at-point-functions' in order to obtain and
+display a completion candidate for the text around point.
+
+If the preview is already shown, first check whether the
+suggested candidate remains a valid completion for the text at
+point. If so, update the preview according the new text at
+point, otherwise hide it."
+ (when completion-preview-active-mode
+ ;; We were already showing a preview before this command, so we
+ ;; check if the text before point is still a prefix of the
+ ;; candidate that the preview suggested, and if so we first update
+ ;; existing preview according to the changes made by this command,
+ ;; and only then try to get a new candidate. This ensures that we
+ ;; never display a stale preview and that the preview doesn't
+ ;; flicker, even with slow completion backends.
+ (let* ((beg (completion-preview--get 'completion-preview-beg))
+ (cands (completion-preview--get 'completion-preview-cands))
+ (index (completion-preview--get 'completion-preview-index))
+ (cand (nth index cands))
+ (len (length cand))
+ (end (+ beg len))
+ (cur (point))
+ (face (get-text-property 0 'face (completion-preview--get 'after-string))))
+ (if (and (< beg cur end) (string-prefix-p (buffer-substring beg cur) cand))
+ ;; The previous preview is still applicable, update it.
+ (overlay-put (completion-preview--make-overlay
+ cur (propertize (substring cand (- cur beg))
+ 'face face
+ 'mouse-face 'completion-preview-highlight
+ 'keymap completion-preview--mouse-map))
+ 'completion-preview-end cur)
+ ;; The previous preview is no longer applicable, hide it.
+ (completion-preview-active-mode -1))))
+ ;; Run `completion-at-point-functions' to get a new candidate.
+ (while-no-input (completion-preview--update)))
+
+(defun completion-preview--post-command ()
+ "Create, update or delete completion preview post last command."
+ (if (and (completion-preview-require-certain-commands)
+ (completion-preview-require-minimum-symbol-length))
+ ;; We should show the preview.
+ (or
+ ;; If we're called after a command that itself updates the
+ ;; preview, don't do anything.
+ (completion-preview--internal-command-p)
+ ;; Otherwise, show the preview.
+ (completion-preview--show))
+ (completion-preview-active-mode -1)))
+
+(defun completion-preview-insert ()
+ "Insert the completion candidate that the preview is showing."
+ (interactive)
+ (if completion-preview-active-mode
+ (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-cands))
+ (efn (completion-preview--get 'completion-preview-exit-fn))
+ (aft (completion-preview--get 'after-string))
+ (str (concat pre (nth ind all))))
+ (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")))
+
+(defun completion-preview-prev-candidate ()
+ "Cycle the candidate that the preview is showing to the previous suggestion."
+ (interactive)
+ (completion-preview-next-candidate -1))
+
+(defun completion-preview-next-candidate (direction)
+ "Cycle the candidate that the preview is showing in direction DIRECTION.
+
+DIRECTION should be either 1 which means cycle forward, or -1
+which means cycle backward. Interactively, DIRECTION is the
+prefix argument and defaults to 1."
+ (interactive "p")
+ (when completion-preview-active-mode
+ (let* ((beg (completion-preview--get 'completion-preview-beg))
+ (all (completion-preview--get 'completion-preview-cands))
+ (cur (completion-preview--get 'completion-preview-index))
+ (len (length all))
+ (new (mod (+ cur direction) len))
+ (str (nth new all))
+ (pos (point)))
+ (while (or (<= (+ beg (length str)) pos)
+ (not (string-prefix-p (buffer-substring beg pos) str)))
+ (setq new (mod (+ new direction) len) str (nth new all)))
+ (let ((aft (propertize (substring str (- pos beg))
+ 'face (if (< 1 len)
+ 'completion-preview
+ 'completion-preview-exact)
+ 'mouse-face 'completion-preview-highlight
+ 'keymap completion-preview--mouse-map)))
+ (add-text-properties 0 1 '(cursor 1) aft)
+ (overlay-put completion-preview--overlay 'completion-preview-index new)
+ (overlay-put completion-preview--overlay 'after-string aft))
+ (when completion-preview-message-format
+ (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."
+ (buffer-local-value 'completion-preview-active-mode buffer))
+
+(dolist (cmd '(completion-preview-insert
+ completion-preview-prev-candidate
+ completion-preview-next-candidate))
+ (put cmd 'completion-predicate #'completion-preview--active-p))
+
+;;;###autoload
+(define-minor-mode completion-preview-mode
+ "Show in-buffer completion suggestions in a preview as you type.
+
+This mode automatically shows and updates the completion preview
+according to the text around point.
+\\<completion-preview-active-mode-map>\
+When the preview is visible, \\[completion-preview-insert]
+accepts the completion suggestion,
+\\[completion-preview-next-candidate] cycles forward to the next
+completion suggestion, and \\[completion-preview-prev-candidate]
+cycles backward."
+ :lighter " CP"
+ (if completion-preview-mode
+ (add-hook 'post-command-hook #'completion-preview--post-command nil t)
+ (remove-hook 'post-command-hook #'completion-preview--post-command t)
+ (completion-preview-active-mode -1)))
+
+(provide 'completion-preview)
+;;; completion-preview.el ends here
diff --git a/lisp/completion.el b/lisp/completion.el
index eed6e77da4c..ab7f2a7bc52 100644
--- a/lisp/completion.el
+++ b/lisp/completion.el
@@ -1,6 +1,6 @@
;;; completion.el --- dynamic word-completion code -*- lexical-binding: t; -*-
-;; Copyright (C) 1990-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1990-2024 Free Software Foundation, Inc.
;; Maintainer: emacs-devel@gnu.org
;; Keywords: abbrev convenience
@@ -2133,7 +2133,25 @@ TYPE is the type of the wrapper to be added. Can be :before or :under."
;;;###autoload
(define-minor-mode dynamic-completion-mode
- "Toggle dynamic word-completion on or off."
+ "Toggle dynamic word-completion on or off.
+
+When this minor mode is turned on, typing \\`M-RET' or \\`C-RET'
+invokes the command `complete', which completes the word or
+symbol at point using the record of words/symbols you used
+previously and the previously-inserted completions. Typing
+a word or moving point across it constitutes \"using\" the
+word.
+
+By default, the database of all the dynamic completions that
+were inserted by \\[complete] is saved on the file specified
+by `save-completions-file-name' when you exit Emacs, and will
+be loaded from that file when this mode is enabled in a future
+Emacs session.
+
+The following important options control the various aspects of
+this mode: `enable-completion', `save-completions-flag', and
+`save-completions-retention-time'. Few other less important
+options can be found in the `completion' group."
:global t
;; This is always good, not specific to dynamic-completion-mode.
(define-key function-key-map [C-return] [?\C-\r])
diff --git a/lisp/composite.el b/lisp/composite.el
index 3ae3e64d5b9..326e8f10aee 100644
--- a/lisp/composite.el
+++ b/lisp/composite.el
@@ -1,6 +1,6 @@
;;; composite.el --- support character composition -*- lexical-binding: t; -*-
-;; Copyright (C) 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2024 Free Software Foundation, Inc.
;; Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
;; 2008, 2009, 2010, 2011
diff --git a/lisp/cus-dep.el b/lisp/cus-dep.el
index 00f497d4e90..55965841a76 100644
--- a/lisp/cus-dep.el
+++ b/lisp/cus-dep.el
@@ -1,6 +1,6 @@
;;; cus-dep.el --- find customization dependencies -*- lexical-binding: t; -*-
;;
-;; Copyright (C) 1997, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997, 2001-2024 Free Software Foundation, Inc.
;;
;; Author: Per Abrahamsen <abraham@dina.kvl.dk>
;; Keywords: internal
diff --git a/lisp/cus-edit.el b/lisp/cus-edit.el
index 9b73a72b238..0eeca7c2f31 100644
--- a/lisp/cus-edit.el
+++ b/lisp/cus-edit.el
@@ -1,6 +1,6 @@
;;; cus-edit.el --- tools for customizing Emacs and Lisp packages -*- lexical-binding:t -*-
-;; Copyright (C) 1996-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-2024 Free Software Foundation, Inc.
;; Author: Per Abrahamsen <abraham@dina.kvl.dk>
;; Maintainer: emacs-devel@gnu.org
@@ -177,7 +177,7 @@
(defgroup wp nil
"Support for editing text files.
-Use group `text' for this instead. This group is deprecated."
+Use group `text' for this instead. This group is obsolete."
:group 'emacs)
(defgroup text nil
@@ -512,6 +512,13 @@ WIDGET is the widget to apply the filter entries of MENU on."
(push name result)))
(nreverse result)))
+(defun custom--editable-field-p (widget)
+ "Non-nil if WIDGET is an editable-field widget, or inherits from it."
+ (let ((type (widget-type widget)))
+ (while (and type (not (eq type 'editable-field)))
+ (setq type (widget-type (get type 'widget-type))))
+ type))
+
;;; Unlispify.
(defvar custom-prefix-list nil
@@ -973,8 +980,7 @@ it as the third element in the list."
(let ((prop (get var 'variable-interactive))
(type (get var 'custom-type))
(prompt (format prompt-val var)))
- (unless (listp type)
- (setq type (list type)))
+ (setq type (ensure-list type))
(cond (prop
;; Use VAR's `variable-interactive' property
;; as an interactive spec for prompting.
@@ -4149,7 +4155,10 @@ Optional EVENT is the location for the menu."
;; If recreating a widget that may have been edited by the user, remember
;; to always save the edited value into the :shown-value property, so
;; we use that value for the recreated widget. (Bug#44331)
- (widget-put widget :shown-value (custom-face-widget-to-spec widget))
+ (let ((child (car (widget-get widget :children))))
+ (if (eq (widget-type child) 'custom-face-edit)
+ (widget-put widget :shown-value `((t ,(widget-value child))))
+ (widget-put widget :shown-value (widget-value child))))
(custom-face-edit-all widget)
(widget-put widget :shown-value nil) ; Reset it after we used it.
(custom-face-mark-to-save widget)
@@ -5145,8 +5154,7 @@ This function does not save the buffer."
(defun custom-variable-menu-create (_widget symbol)
"Ignoring WIDGET, create a menu entry for customization variable SYMBOL."
(let ((type (get symbol 'custom-type)))
- (unless (listp type)
- (setq type (list type)))
+ (setq type (ensure-list type))
(if (and type (widget-get type :custom-menu))
(widget-apply type :custom-menu symbol)
(vector (custom-unlispify-menu-entry symbol)
@@ -5365,11 +5373,6 @@ The following properties have special meanings for this widget:
:hidden-states should be a list of widget states for which the
widget's initial contents are to be hidden.
-:custom-form should be a symbol describing how to display and
- edit the variable---either `edit' (using edit widgets),
- `lisp' (as a Lisp sexp), or `mismatch' (should not happen);
- if nil, use the return value of `custom-variable-default-form'.
-
:shown-value, if non-nil, should be a list whose `car' is the
variable value to display in place of the current value.
@@ -5382,11 +5385,34 @@ The following properties have special meanings for this widget:
:custom-category 'option
:custom-state nil
:custom-form nil
- :value-create 'custom-icon-value-create
+ :value-create #'custom-icon-value-create
:hidden-states '(standard)
- :custom-set 'custom-icon-set
- :custom-reset-current 'custom-redraw
- :custom-reset-saved 'custom-variable-reset-saved)
+ :action #'custom-icon-action
+ :custom-set #'custom-icon-set
+ :custom-reset-current #'custom-redraw)
+ ;; Not implemented yet.
+ ;; :custom-reset-saved 'custom-icon-reset-saved)
+
+(defvar custom-icon-extended-menu
+ (let ((map (make-sparse-keymap)))
+ (define-key-after map [custom-icon-set]
+ '(menu-item "Set for Current Session" custom-icon-set
+ :enable (eq (widget-get custom-actioned-widget :custom-state)
+ 'modified)))
+ (when (or custom-file init-file-user)
+ (define-key-after map [custom-icon-save]
+ '(menu-item "Save for Future Sessions" custom-icon-save
+ :enable (memq
+ (widget-get custom-actioned-widget :custom-state)
+ '(modified set changed)))))
+ (define-key-after map [custom-redraw]
+ '(menu-item "Undo Edits" custom-redraw
+ :enable (memq
+ (widget-get custom-actioned-widget :custom-state)
+ '(modified changed))))
+ map)
+ "A menu for `custom-icon' widgets.
+Used in `custom-icon-action' to show a menu to the user.")
(defun custom-icon-value-create (widget)
"Here is where you edit the icon's specification."
@@ -5516,6 +5542,24 @@ The following properties have special meanings for this widget:
(custom-add-parent-links widget))
(custom-add-see-also widget)))))
+(defun custom-icon-action (widget &optional event)
+ "Show the menu for `custom-icon' WIDGET.
+Optional EVENT is the location for the menu."
+ (if (eq (widget-get widget :custom-state) 'hidden)
+ (custom-toggle-hide widget)
+ (unless (eq (widget-get widget :custom-state) 'modified)
+ (custom-icon-state-set widget))
+ (custom-redraw-magic widget)
+ (let* ((completion-ignore-case t)
+ (custom-actioned-widget widget)
+ (answer (widget-choose (concat "Operation on "
+ (custom-unlispify-tag-name
+ (widget-get widget :value)))
+ custom-icon-extended-menu
+ event)))
+ (when answer
+ (funcall answer widget)))))
+
(defun custom-toggle-hide-icon (visibility-widget &rest _ignore)
"Toggle the visibility of a `custom-icon' parent widget.
By default, this signals an error if the parent has unsaved
@@ -5552,10 +5596,21 @@ changes."
(user-error "Cannot update hidden icon"))
(setq val (custom--icons-widget-value child))
- (unless (equal val (icon-complete-spec symbol))
- (custom-variable-backup-value widget))
+ ;; FIXME: What was the intention here?
+ ;; (unless (equal val (icon-complete-spec symbol))
+ ;; (custom-variable-backup-value widget))
(custom-push-theme 'theme-icon symbol 'user 'set val)
- (custom-redraw-magic widget)))
+ (custom-redraw widget)))
+
+(defun custom-icon-save (widget)
+ "Save value of icon edited by widget WIDGET."
+ (custom-set-icons (cons (widget-value widget)
+ (list
+ (custom--icons-widget-value
+ (car (widget-get widget :children))))))
+ (custom-save-all)
+ (custom-icon-state-set widget)
+ (custom-redraw-magic widget))
;;;###autoload
(defun customize-icon (icon)
@@ -5644,6 +5699,288 @@ This stores EXP (without evaluating it) as the saved spec for SYMBOL."
(prin1 value (current-buffer)))
(insert ")\n")))))
+;;; Directory Local Variables.
+;; The following code provides an Easy Customization interface to manage
+;; `.dir-locals.el' files.
+;; The main command is `customize-dirlocals'. It presents a Custom-like buffer
+;; but with a few tweaks. Variables are inserted in a repeat widget, and
+;; update its associated widget (the one for editing the value) upon the user
+;; hitting RET or TABbing out of it.
+;; This is unlike the `cus-theme.el' interface for editing themes, that prompts
+;; the user for the variable to then create the appropriate widget.
+(defvar-local custom-dirlocals-widget nil
+ "Widget that holds the dir-locals customizations.")
+
+(defvar-local custom-dirlocals-file-widget nil
+ "Widget that holds the name of the dir-locals file being customized.")
+
+(defvar-keymap custom-dirlocals-map
+ :doc "Keymap used in the \"*Customize Dirlocals*\" buffer."
+ :full t
+ :parent widget-keymap
+ "SPC" #'scroll-up-command
+ "S-SPC" #'scroll-down-command
+ "DEL" #'scroll-down-command
+ "C-x C-s" #'Custom-dirlocals-save
+ "q" #'Custom-buffer-done
+ "n" #'widget-forward
+ "p" #'widget-backward)
+
+(defvar custom-dirlocals-field-map
+ (let ((map (copy-keymap custom-field-keymap)))
+ (define-key map "\C-x\C-s" #'Custom-dirlocals-save)
+ (define-key map "\C-m" #'widget-field-activate)
+ map)
+ "Keymap for the editable fields in the \"*Customize Dirlocals*\" buffer .")
+
+(defvar custom-dirlocals-commands
+ '((" Save Settings " Custom-dirlocals-save t
+ "Save Settings to the dir-locals file." "save" "Save" t)
+ (" Undo Edits " Custom-dirlocals-revert-buffer t
+ "Revert buffer, undoing any editions."
+ "refresh" "Undo" t)
+ (" Help for Customize " Custom-help t "Get help for using Customize."
+ "help" "Help" t)
+ (" Exit " Custom-buffer-done t "Exit Customize." "exit" "Exit" t))
+ "Alist of specifications for Customize menu items, tool bar icons and buttons.
+See `custom-commands' for further explanation.")
+
+(easy-menu-define
+ Custom-dirlocals-menu (list custom-dirlocals-map
+ custom-dirlocals-field-map)
+ "Menu used in dirlocals customization buffers."
+ (nconc (list "Custom"
+ (customize-menu-create 'customize))
+ (mapcar (lambda (arg)
+ (let ((tag (nth 0 arg))
+ (command (nth 1 arg))
+ (visible (nth 2 arg))
+ (help (nth 3 arg))
+ (active (nth 6 arg)))
+ (vector tag command :visible (eval visible)
+ :active `(eq t ',active)
+ :help help)))
+ custom-dirlocals-commands)))
+
+(defvar custom-dirlocals-tool-bar-map nil
+ "Keymap for the toolbar in \"*Customize Dirlocals*\" buffer.")
+
+(define-widget 'custom-dirlocals-key 'menu-choice
+ "Menu to choose between possible keys in a dir-locals file.
+
+Possible values are nil, a symbol (standing for a major mode) or a directory
+name."
+ :tag "Specification"
+ :value nil
+ :help-echo "Select a key for the dir-locals specification."
+ :args '((const :tag "All modes" nil)
+ (symbol :tag "Major mode" fundamental-mode)
+ (directory :tag "Subdirectory")))
+
+(define-widget 'custom-dynamic-cons 'cons
+ "A cons widget that changes its 2nd type based on the 1st type."
+ :value-create #'custom-dynamic-cons-value-create)
+
+(defun custom-dynamic-cons-value-create (widget)
+ "Select an appropriate 2nd type for the cons WIDGET and create WIDGET.
+
+The appropriate types are:
+- A symbol, if the value to represent is a minor-mode.
+- A boolean, if the value to represent is either the unibyte value or the
+ subdirs value.
+- A widget type suitable for editing a variable, in case of specifying a
+ variable's value.
+- A sexp widget, if none of the above happens."
+ (let* ((args (widget-get widget :args))
+ (value (widget-get widget :value))
+ (val (car value)))
+ (cond
+ ((eq val 'mode) (setf (nth 1 args)
+ '(symbol :keymap custom-dirlocals-field-map
+ :tag "Minor mode")))
+ ((eq val 'unibyte) (setf (nth 1 args) '(boolean)))
+ ((eq val 'subdirs) (setf (nth 1 args) '(boolean)))
+ ((custom-variable-p val)
+ (let ((w (widget-convert (custom-variable-type val))))
+ (when (custom--editable-field-p w)
+ (widget-put w :keymap custom-dirlocals-field-map))
+ (setf (nth 1 args) w)))
+ (t (setf (nth 1 args) '(sexp :keymap custom-dirlocals-field-map))))
+ (widget-put (nth 0 args) :keymap custom-dirlocals-field-map)
+ (widget-group-value-create widget)))
+
+(defun custom-dirlocals-maybe-update-cons ()
+ "If focusing out from the first widget in a cons widget, update its value."
+ (when-let ((w (widget-at)))
+ (when (widget-get w :custom-dirlocals-symbol)
+ (widget-value-set (widget-get w :parent)
+ (cons (widget-value w) ""))
+ (widget-setup))))
+
+(define-widget 'custom-dirlocals 'editable-list
+ "An editable list to edit settings in a dir-locals file."
+ :entry-format "%i %d %v"
+ :insert-button-args '(:help-echo "Insert new specification here.")
+ :append-button-args '(:help-echo "Append new specification here.")
+ :delete-button-args '(:help-echo "Delete this specification.")
+ :args '((group :format "%v"
+ custom-dirlocals-key
+ (repeat
+ :tag "Settings"
+ :inline t
+ (custom-dynamic-cons
+ :tag "Setting"
+ (symbol :action custom-dirlocals-symbol-action
+ :custom-dirlocals-symbol t)
+ ;; Will change according to the option being customized.
+ (sexp :tag "Value"))))))
+
+(defun custom-dirlocals-symbol-action (widget &optional _event)
+ "Action for the symbol WIDGET.
+
+Sets the value of its parent, a cons widget, in order to create an
+appropriate widget to edit the value of WIDGET.
+
+Moves point into the widget that holds the value."
+ (setq widget (or widget (widget-at)))
+ (widget-value-set (widget-get widget :parent)
+ (cons (widget-value widget) ""))
+ (widget-setup)
+ (widget-forward 1))
+
+(defun custom-dirlocals-change-file (widget &optional _event)
+ "Switch to a buffer to customize the dir-locals file in WIDGET."
+ (customize-dirlocals (expand-file-name (widget-value widget))))
+
+(defun custom-dirlocals--set-widget-vars ()
+ "Set local variables for the Widget library."
+ (custom--initialize-widget-variables)
+ (add-hook 'widget-forward-hook #'custom-dirlocals-maybe-update-cons nil t))
+
+(defmacro custom-dirlocals-with-buffer (&rest body)
+ "Arrange to execute BODY in a \"*Customize Dirlocals*\" buffer."
+ ;; We don't use `custom-buffer-create' because the settings here
+ ;; don't go into the `custom-file'.
+ `(progn
+ (switch-to-buffer "*Customize Dirlocals*")
+ (kill-all-local-variables)
+ (let ((inhibit-read-only t))
+ (erase-buffer))
+ (remove-overlays)
+ (custom-dirlocals--set-widget-vars)
+ ,@body
+ (setq-local tool-bar-map
+ (or custom-dirlocals-tool-bar-map
+ ;; Set up `custom-dirlocals-tool-bar-map'.
+ (let ((map (make-sparse-keymap)))
+ (mapc
+ (lambda (arg)
+ (tool-bar-local-item-from-menu
+ (nth 1 arg) (nth 4 arg) map custom-dirlocals-map
+ :label (nth 5 arg)))
+ custom-dirlocals-commands)
+ (setq custom-dirlocals-tool-bar-map map))))
+ (setq-local revert-buffer-function #'Custom-dirlocals-revert-buffer)
+ (use-local-map custom-dirlocals-map)
+ (widget-setup)))
+
+(defun custom-dirlocals-get-options ()
+ "Return all options inside a custom-dirlocals widget."
+ (let* ((groups (widget-get custom-dirlocals-widget :children))
+ (repeats (mapcar (lambda (group)
+ (nth 1 (widget-get group :children)))
+ groups)))
+ (mapcan (lambda (repeat)
+ (mapcar (lambda (w)
+ (nth 1 (widget-get w :children)))
+ (widget-get repeat :children)))
+ repeats)))
+
+(defun custom-dirlocals-validate ()
+ "Non-nil if all customization options validate.
+
+If at least an option doesn't validate, signals an error and moves point
+to the widget with the invalid value."
+ (dolist (opt (custom-dirlocals-get-options))
+ (when-let ((w (widget-apply opt :validate)))
+ (goto-char (widget-get w :from))
+ (error "%s" (widget-get w :error))))
+ t)
+
+(defun Custom-dirlocals-revert-buffer (&rest _ignored)
+ "Revert the buffer for Directory Local Variables customization."
+ (interactive)
+ (customize-dirlocals (widget-get custom-dirlocals-file-widget :value)))
+
+(defun Custom-dirlocals-save (&rest _ignore)
+ "Save the settings to the dir-locals file being customized."
+ (interactive)
+ (when (custom-dirlocals-validate)
+ (let* ((file (widget-value custom-dirlocals-file-widget))
+ (old (widget-get custom-dirlocals-widget :value))
+ (dirlocals (widget-value custom-dirlocals-widget)))
+ (dolist (spec old)
+ (let ((mode (car spec))
+ (settings (cdr spec)))
+ (dolist (setting settings)
+ (delete-dir-local-variable mode (car setting) file))))
+ (dolist (spec dirlocals)
+ (let ((mode (car spec))
+ (settings (cdr spec)))
+ (dolist (setting (reverse settings))
+ (when (memq (car setting) '(mode eval))
+ (delete-dir-local-variable mode (car setting) file))
+ (add-dir-local-variable mode (car setting) (cdr setting) file)))))
+ ;; Write the dir-locals file and kill its buffer, to come back to
+ ;; our own buffer.
+ (write-file (expand-file-name buffer-file-name) nil)
+ (kill-buffer)))
+
+;;;###autoload
+(defun customize-dirlocals (&optional filename)
+ "Customize Directory Local Variables in the current directory.
+
+With optional argument FILENAME non-nil, customize the `.dir-locals.el' file
+that FILENAME specifies."
+ (interactive)
+ (let* ((file (or filename (expand-file-name ".dir-locals.el")))
+ (dirlocals (when (file-exists-p file)
+ (with-current-buffer (find-file-noselect file)
+ (goto-char (point-min))
+ (prog1
+ (condition-case _
+ (read (current-buffer))
+ (end-of-file nil))
+ (kill-buffer))))))
+ (custom-dirlocals-with-buffer
+ (widget-insert
+ "This buffer is for customizing the Directory Local Variables in:\n")
+ (setq custom-dirlocals-file-widget
+ (widget-create `(file :action ,#'custom-dirlocals-change-file
+ ,file)))
+ (widget-insert
+ (substitute-command-keys
+ "
+To select another file, edit the above field and hit RET.
+
+After you enter a user option name under the symbol field,
+be sure to press \\`RET' or \\`TAB', so that the field that holds the
+value changes to an appropriate field for the option.
+
+Type \\`C-x C-s' when you've finished editing it, to save the
+settings to the file."))
+ (widget-insert "\n\n\n")
+ (widget-create 'push-button :tag " Revert "
+ :action #'Custom-dirlocals-revert-buffer)
+ (widget-insert " ")
+ (widget-create 'push-button :tag " Save Settings "
+ :action #'Custom-dirlocals-save)
+ (widget-insert "\n\n")
+ (setq custom-dirlocals-widget
+ (widget-create 'custom-dirlocals :value dirlocals))
+ (setq default-directory (file-name-directory file))
+ (goto-char (point-min)))))
+
(provide 'cus-edit)
;;; cus-edit.el ends here
diff --git a/lisp/cus-face.el b/lisp/cus-face.el
index a3a27263a7c..0c8b6b0b97c 100644
--- a/lisp/cus-face.el
+++ b/lisp/cus-face.el
@@ -1,6 +1,6 @@
;;; cus-face.el --- customization support for faces -*- lexical-binding: t; -*-
;;
-;; Copyright (C) 1996-1997, 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-1997, 1999-2024 Free Software Foundation, Inc.
;;
;; Author: Per Abrahamsen <abraham@dina.kvl.dk>
;; Keywords: help, faces
diff --git a/lisp/cus-start.el b/lisp/cus-start.el
index 6d83aaf4d14..36879029282 100644
--- a/lisp/cus-start.el
+++ b/lisp/cus-start.el
@@ -1,6 +1,6 @@
;;; cus-start.el --- define customization properties of builtins -*- lexical-binding:t -*-
-;; Copyright (C) 1997, 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997, 1999-2024 Free Software Foundation, Inc.
;; Author: Per Abrahamsen <abraham@dina.kvl.dk>
;; Keywords: internal
diff --git a/lisp/cus-theme.el b/lisp/cus-theme.el
index 5d3f2585976..1aa995a1d91 100644
--- a/lisp/cus-theme.el
+++ b/lisp/cus-theme.el
@@ -1,6 +1,6 @@
;;; cus-theme.el --- custom theme creation user interface -*- lexical-binding: t -*-
-;; Copyright (C) 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2024 Free Software Foundation, Inc.
;; Author: Alex Schroeder <alex@gnu.org>
;; Maintainer: emacs-devel@gnu.org
@@ -490,6 +490,29 @@ It includes all faces in list FACES."
(with-current-buffer standard-output
(describe-theme-1 theme))))
+(defun describe-theme-from-file (theme &optional file short)
+ "Describe THEME from its FILE without loading it.
+
+If FILE is nil try to look in `custom-theme-load-path' for the
+theme's file using the theme's name.
+If SHORT is non-nil, show only the first line of thene's documentation."
+ (let ((file (or file
+ (locate-file (concat (symbol-name theme) "-theme.el")
+ (custom-theme--load-path)
+ '("" "c")))))
+ (with-temp-buffer
+ (insert-file-contents file)
+ (catch 'found
+ (let (sexp)
+ (while (setq sexp (let ((read-circle nil))
+ (condition-case nil
+ (read (current-buffer))
+ (end-of-file nil))))
+ (when (eq (car-safe sexp) 'deftheme)
+ (throw 'found (if short
+ (car (split-string (nth 2 sexp) "\n"))
+ (nth 2 sexp))))))))))
+
(defun describe-theme-1 (theme)
(prin1 theme)
(princ " is a custom theme")
@@ -510,16 +533,9 @@ It includes all faces in list FACES."
(princ "It is loaded but disabled."))
(setq doc (get theme 'theme-documentation)))
(princ "It is not loaded.")
- ;; Attempt to grab the theme documentation
+ ;; Attempt to grab the theme documentation from file.
(when fn
- (with-temp-buffer
- (insert-file-contents fn)
- (let ((sexp (let ((read-circle nil))
- (condition-case nil
- (read (current-buffer))
- (end-of-file nil)))))
- (and (eq (car-safe sexp) 'deftheme)
- (setq doc (nth 2 sexp)))))))
+ (setq doc (describe-theme-from-file theme fn))))
(princ "\n\nDocumentation:\n")
(princ (if (stringp doc)
(substitute-command-keys doc)
diff --git a/lisp/custom.el b/lisp/custom.el
index 083349e3591..a19b14aaf8a 100644
--- a/lisp/custom.el
+++ b/lisp/custom.el
@@ -1,6 +1,6 @@
;;; custom.el --- tools for declaring and initializing options -*- lexical-binding: t -*-
;;
-;; Copyright (C) 1996-1997, 1999, 2001-2023 Free Software Foundation,
+;; Copyright (C) 1996-1997, 1999, 2001-2024 Free Software Foundation,
;; Inc.
;;
;; Author: Per Abrahamsen <abraham@dina.kvl.dk>
@@ -1208,7 +1208,7 @@ The command `customize-create-theme' writes theme files into this
directory. By default, Emacs searches for custom themes in this
directory first---see `custom-theme-load-path'."
:initialize #'custom-initialize-delay
- :type 'string
+ :type 'directory
:group 'customize
:version "22.1")
diff --git a/lisp/dabbrev.el b/lisp/dabbrev.el
index a4b4d07b688..853c0f4b290 100644
--- a/lisp/dabbrev.el
+++ b/lisp/dabbrev.el
@@ -1,6 +1,6 @@
;;; dabbrev.el --- dynamic abbreviation package -*- lexical-binding: t -*-
-;; Copyright (C) 1985-1986, 1992, 1994, 1996-1997, 2000-2023 Free
+;; Copyright (C) 1985-1986, 1992, 1994, 1996-1997, 2000-2024 Free
;; Software Foundation, Inc.
;; Author: Don Morrison
diff --git a/lisp/delim-col.el b/lisp/delim-col.el
index 1bbcaf736f1..3e744168cd0 100644
--- a/lisp/delim-col.el
+++ b/lisp/delim-col.el
@@ -1,6 +1,6 @@
;;; delim-col.el --- prettify all columns in a region or rectangle -*- lexical-binding: t; -*-
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
;; Author: Vinicius Jose Latorre <viniciusjl.gnu@gmail.com>
;; Old-Version: 2.1
diff --git a/lisp/delsel.el b/lisp/delsel.el
index 48656bc8ba3..df99a56d7bc 100644
--- a/lisp/delsel.el
+++ b/lisp/delsel.el
@@ -1,6 +1,6 @@
;;; delsel.el --- delete selection if you insert -*- lexical-binding:t -*-
-;; Copyright (C) 1992, 1997-1998, 2001-2023 Free Software Foundation,
+;; Copyright (C) 1992, 1997-1998, 2001-2024 Free Software Foundation,
;; Inc.
;; Author: Matthieu Devin <devin@lucid.com>
diff --git a/lisp/descr-text.el b/lisp/descr-text.el
index 4834c2eb7ba..eeab995c37d 100644
--- a/lisp/descr-text.el
+++ b/lisp/descr-text.el
@@ -1,6 +1,6 @@
;;; descr-text.el --- describe text mode -*- lexical-binding:t -*-
-;; Copyright (C) 1994-1996, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1994-1996, 2001-2024 Free Software Foundation, Inc.
;; Author: Boris Goldowsky <boris@gnu.org>
;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/desktop.el b/lisp/desktop.el
index f096f13ab80..ff113c85e12 100644
--- a/lisp/desktop.el
+++ b/lisp/desktop.el
@@ -1,6 +1,6 @@
;;; desktop.el --- save partial status of Emacs when killed -*- lexical-binding: t -*-
-;; Copyright (C) 1993-1995, 1997, 2000-2023 Free Software Foundation,
+;; Copyright (C) 1993-1995, 1997, 2000-2024 Free Software Foundation,
;; Inc.
;; Author: Morten Welinder <terra@diku.dk>
@@ -293,7 +293,7 @@ May be used to show a dired buffer."
:version "22.1")
(defcustom desktop-not-loaded-hook nil
- "Normal hook run when the user declines to re-use a desktop file.
+ "Normal hook run when the user declines to reuse a desktop file.
Run in the directory in which the desktop file was found.
May be used to deal with accidental multiple Emacs jobs."
:type 'hook
diff --git a/lisp/dframe.el b/lisp/dframe.el
index 995bb0a25d1..4031e0784c2 100644
--- a/lisp/dframe.el
+++ b/lisp/dframe.el
@@ -1,6 +1,6 @@
;;; dframe.el --- dedicate frame support modes -*- lexical-binding:t -*-
-;; Copyright (C) 1996-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
;; Keywords: file, tags, tools
diff --git a/lisp/dired-aux.el b/lisp/dired-aux.el
index 28513a2c61a..f091101ea27 100644
--- a/lisp/dired-aux.el
+++ b/lisp/dired-aux.el
@@ -1,6 +1,6 @@
;;; dired-aux.el --- less commonly used parts of dired -*- lexical-binding: t -*-
-;; Copyright (C) 1985-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1985-2024 Free Software Foundation, Inc.
;; Author: Sebastian Kremer <sk@thp.uni-koeln.de>.
;; Maintainer: emacs-devel@gnu.org
@@ -264,7 +264,8 @@ the string of command switches used as the third argument of `diff'."
(read-string "Options for diff: "
(if (stringp diff-switches)
diff-switches
- (mapconcat #'identity diff-switches " ")))))))
+ (mapconcat #'identity diff-switches " "))))))
+ dired-mode)
(let ((current (dired-get-filename t)))
(when (or (equal (expand-file-name file)
(expand-file-name current))
@@ -290,7 +291,8 @@ With prefix arg, prompt for argument SWITCHES which is options for `diff'."
(if (stringp diff-switches)
diff-switches
(mapconcat #'identity diff-switches " "))))
- nil))
+ nil)
+ dired-mode)
(diff-backup (dired-get-filename) switches))
;;;###autoload
@@ -336,7 +338,8 @@ only in the active region if `dired-mark-region' is non-nil."
(read-directory-name (format "Compare %s with: "
(dired-current-directory))
target-dir target-dir t)))
- (read-from-minibuffer "Mark if (lisp expr or RET): " nil nil t nil "nil")))
+ (read-from-minibuffer "Mark if (lisp expr or RET): " nil nil t nil "nil"))
+ dired-mode)
(let* ((dir1 (dired-current-directory))
(file-alist1 (dired-files-attributes dir1))
(file-alist2 (dired-files-attributes dir2))
@@ -497,7 +500,7 @@ Alternatively, see the man page for \"chmod(1)\".
Note that on MS-Windows only the `w' (write) bit is meaningful:
resetting it makes the file read-only. Changing any other bit
has no effect on MS-Windows."
- (interactive "P")
+ (interactive "P" dired-mode)
(let* ((files (dired-get-marked-files t arg nil nil t))
;; The source of default file attributes is the file at point.
(default-file (dired-get-filename t t))
@@ -541,7 +544,7 @@ has no effect on MS-Windows."
Type \\<minibuffer-local-completion-map>\\[next-history-element] \
to pull the file attributes of the file at point
into the minibuffer."
- (interactive "P")
+ (interactive "P" dired-mode)
(if (and (memq system-type '(ms-dos windows-nt))
(not (file-remote-p default-directory)))
(error "chgrp not supported on this system"))
@@ -553,7 +556,7 @@ into the minibuffer."
Type \\<minibuffer-local-completion-map>\\[next-history-element] \
to pull the file attributes of the file at point
into the minibuffer."
- (interactive "P")
+ (interactive "P" dired-mode)
(if (and (memq system-type '(ms-dos windows-nt))
(not (file-remote-p default-directory)))
(error "chown not supported on this system"))
@@ -566,7 +569,7 @@ This calls touch.
Type Type \\<minibuffer-local-completion-map>\\[next-history-element] \
to pull the file attributes of the file at point
into the minibuffer."
- (interactive "P")
+ (interactive "P" dired-mode)
(dired-do-chxxx "Timestamp" dired-touch-program 'touch arg))
;; Process all the files in FILES in batches of a convenient size,
@@ -618,7 +621,7 @@ into the minibuffer."
"Print the marked (or next ARG) files.
Uses the shell command coming from variables `lpr-command' and
`lpr-switches' as default."
- (interactive "P")
+ (interactive "P" dired-mode)
(require 'lpr)
(let* ((file-list (dired-get-marked-files t arg nil nil t))
(lpr-switches
@@ -674,7 +677,7 @@ Negative prefix arg KEEP overrides `kept-old-versions' with KEEP made positive.
To clear the flags on these files, you can use \\[dired-flag-backup-files]
with a prefix argument."
- (interactive "P")
+ (interactive "P" dired-mode)
(setq keep (if keep (prefix-numeric-value keep) dired-kept-versions))
(let ((early-retention (if (< keep 0) (- keep) kept-old-versions))
(late-retention (if (<= keep 0) dired-kept-versions keep))
@@ -760,22 +763,6 @@ with a prefix argument."
;;; Shell commands
-(declare-function mailcap-file-default-commands "mailcap" (files))
-
-(defvar dired-aux-files)
-
-(defun dired-minibuffer-default-add-shell-commands ()
- "Return a list of all commands associated with current Dired files.
-This function is used to add all related commands retrieved by `mailcap'
-to the end of the list of defaults just after the default value."
- (interactive)
- (let ((commands (and (boundp 'dired-aux-files)
- (require 'mailcap nil t)
- (mailcap-file-default-commands dired-aux-files))))
- (if (listp minibuffer-default)
- (append minibuffer-default commands)
- (cons minibuffer-default commands))))
-
;; This is an extra function so that you can redefine it, e.g., to use gmhist.
(defun dired-read-shell-command (prompt arg files)
"Read a Dired shell command.
@@ -786,14 +773,9 @@ file names. The result is used as the prompt.
Use `dired-guess-shell-command' to offer a smarter default choice
of shell command."
- (minibuffer-with-setup-hook
- (lambda ()
- (setq-local dired-aux-files files)
- (setq-local minibuffer-default-add-function
- #'dired-minibuffer-default-add-shell-commands))
- (setq prompt (format prompt (dired-mark-prompt arg files)))
- (dired-mark-pop-up nil 'shell files
- 'dired-guess-shell-command prompt files)))
+ (setq prompt (format prompt (dired-mark-prompt arg files)))
+ (dired-mark-pop-up nil 'shell files
+ 'dired-guess-shell-command prompt files))
;;;###autoload
(defcustom dired-confirm-shell-command t
@@ -828,7 +810,8 @@ Commands that are run asynchronously do not accept user input."
;; Want to give feedback whether this file or marked files are used:
(dired-read-shell-command "& on %s: " current-prefix-arg files)
current-prefix-arg
- files)))
+ files))
+ dired-mode)
(unless (string-match-p "&[ \t]*\\'" command)
(setq command (concat command " &")))
(dired-do-shell-command command arg file-list))
@@ -895,7 +878,8 @@ Also see the `dired-confirm-shell-command' variable."
;; Want to give feedback whether this file or marked files are used:
(dired-read-shell-command "! on %s: " current-prefix-arg files)
current-prefix-arg
- files)))
+ files))
+ dired-mode)
(let* ((on-each (not (dired--star-or-qmark-p command "*" 'keep)))
(no-subst (not (dired--star-or-qmark-p command "?" 'keep)))
(confirmations nil)
@@ -1176,7 +1160,7 @@ Return the result of `process-file' - zero for success."
"unxz")
;; zstandard archives
- `(,(rx (or ".tar.zst" ".tzst") eos) "unzstd -c %i | tar -xf -")
+ `(,(rx (or ".tar.zst" ".tzst") eos) "unzstd -c ? | tar -xf -")
`(,(rx ".zst" eos) "unzstd --rm")
'("\\.shar\\.Z\\'" "zcat * | unshar")
@@ -1311,7 +1295,7 @@ See `dired-guess-shell-alist-user'."
;;;###autoload
(defun dired-guess-shell-command (prompt files)
"Ask user with PROMPT for a shell command, guessing a default from FILES."
- (let ((default (dired-guess-default files))
+ (let ((default (shell-command-guess files))
default-list val)
(if (null default)
;; Nothing to guess
@@ -1335,6 +1319,125 @@ See `dired-guess-shell-alist-user'."
;; If we got a return, then return default.
(if (equal val "") default val))))
+(defcustom shell-command-guess-functions
+ '(shell-command-guess-dired)
+ "List of functions that guess shell commands for files.
+Each function receives a list of commands and a list of file names
+and should return the same list of commands with changes
+such as added new commands."
+ :type '(repeat
+ (choice (function-item shell-command-guess-dired)
+ (function-item shell-command-guess-mailcap)
+ (function-item shell-command-guess-xdg)
+ (function-item shell-command-guess-open)
+ (function :tag "Custom function")))
+ :group 'dired
+ :version "30.1")
+
+(defun shell-command-guess (files)
+ "Return a list of shell commands, appropriate for FILES.
+The list is populated by calling functions from
+`shell-command-guess-functions'. Each function receives the list
+of commands and the list of file names and returns the same list
+after adding own commands to the composite list."
+ (let ((commands nil))
+ (run-hook-wrapped 'shell-command-guess-functions
+ (lambda (fun)
+ (setq commands (funcall fun commands files))
+ nil))
+ commands))
+
+(defun shell-command-guess-dired (commands files)
+ "Populate COMMANDS using `dired-guess-default'."
+ (append (ensure-list (dired-guess-default files)) commands))
+
+(declare-function mailcap-file-default-commands "mailcap" (files))
+
+(defun shell-command-guess-mailcap (commands files)
+ "Populate COMMANDS by MIME types of FILES."
+ (require 'mailcap)
+ (append (mailcap-file-default-commands files) commands))
+
+(declare-function xdg-mime-apps "xdg" (mime))
+(declare-function xdg-desktop-read-file "xdg" (filename &optional group))
+
+(defun shell-command-guess-xdg (commands files)
+ "Populate COMMANDS by XDG configuration for FILES."
+ (require 'xdg)
+ (let* ((xdg-mime (when (executable-find "xdg-mime")
+ (string-trim-right
+ (shell-command-to-string
+ (concat "xdg-mime query filetype "
+ (shell-quote-argument (car files)))))))
+ (xdg-mime-apps (unless (string-empty-p xdg-mime)
+ (xdg-mime-apps xdg-mime)))
+ (xdg-commands
+ (mapcar (lambda (desktop)
+ (setq desktop (xdg-desktop-read-file desktop))
+ (propertize
+ (replace-regexp-in-string
+ " .*" "" (gethash "Exec" desktop))
+ 'name (gethash "Name" desktop)))
+ xdg-mime-apps)))
+ (append xdg-commands commands)))
+
+(defcustom shell-command-guess-open
+ (cond
+ ((executable-find "xdg-open")
+ "xdg-open")
+ ((memq system-type '(gnu/linux darwin))
+ "open")
+ ((memq system-type '(windows-nt ms-dos))
+ "start")
+ ((eq system-type 'cygwin)
+ "cygstart")
+ ((executable-find "run-mailcap")
+ "run-mailcap"))
+ "A shell command to open a file externally."
+ :type 'string
+ :group 'dired
+ :version "30.1")
+
+(defun shell-command-guess-open (commands _files)
+ "Populate COMMANDS by the `open' command."
+ (append (ensure-list shell-command-guess-open) commands))
+
+(declare-function w32-shell-execute "w32fns.c")
+
+(defun dired-do-open (&optional arg)
+ "Open all marked (or next ARG) files using an external program.
+This \"opens\" the file(s) using the external command that is most
+appropriate for the file(s) according to the system conventions.
+If files are marked, run the command on each marked file. Otherwise,
+run it on the next ARG files, or on the file at mouse-click, or on the
+file at point. The appropriate command to \"open\" a file on each
+system is determined by `shell-command-guess-open'."
+ (interactive "P" dired-mode)
+ (let ((files (if (mouse-event-p last-nonmenu-event)
+ (save-excursion
+ (mouse-set-point last-nonmenu-event)
+ (dired-get-marked-files nil arg))
+ (dired-get-marked-files nil arg)))
+ (command shell-command-guess-open))
+ (when (and (memq system-type '(windows-nt))
+ (equal command "start"))
+ (setq command "open"))
+ (when command
+ (dolist (file files)
+ (cond
+ ((memq system-type '(gnu/linux))
+ (call-process command nil 0 nil file))
+ ((memq system-type '(ms-dos))
+ (shell-command (concat command " " (shell-quote-argument file))))
+ ((memq system-type '(windows-nt))
+ (w32-shell-execute command (convert-standard-filename file)))
+ ((memq system-type '(cygwin))
+ (call-process command nil nil nil file))
+ ((memq system-type '(darwin))
+ (start-process (concat command " " file) nil command file))
+ (t
+ (error "Open not supported on this system")))))))
+
;;; Commands that delete or redisplay part of the dired buffer
@@ -1342,7 +1445,7 @@ See `dired-guess-shell-alist-user'."
"Kill the current line (not the files).
With a prefix argument, kill that many lines starting with the current line.
(A negative argument kills backward.)"
- (interactive "P")
+ (interactive "P" dired-mode)
(setq arg (prefix-numeric-value arg))
(let (buffer-read-only file)
(while (/= 0 arg)
@@ -1383,7 +1486,7 @@ lines removed by this invocation, for the reporting message.
A FMT of \"\" will suppress the messaging."
;; Returns count of killed lines.
- (interactive "P")
+ (interactive "P" dired-mode)
(if arg
(if (dired-get-subdir)
(dired-kill-subdir)
@@ -1520,7 +1623,7 @@ output file. %i path(s) are relative, while %o is absolute.")
Prompt for the archive file name.
Choose the archiving command based on the archive file-name extension
and `dired-compress-files-alist'."
- (interactive)
+ (interactive nil dired-mode)
(let* ((in-files (dired-get-marked-files nil nil nil nil t))
(out-file (expand-file-name (read-file-name "Compress to: ")))
(rule (cl-find-if
@@ -1758,7 +1861,7 @@ the directory and all of its subdirectories, recursively,
into a .tar.gz archive.
If invoked on a .tar.gz or a .tgz or a .zip or a .7z archive,
uncompress and unpack all the files in the archive."
- (interactive "P")
+ (interactive "P" dired-mode)
(dired-map-over-marks-check #'dired-compress arg 'compress t))
@@ -1787,7 +1890,7 @@ uncompress and unpack all the files in the archive."
;;;###autoload
(defun dired-do-byte-compile (&optional arg)
"Byte compile marked (or next ARG) Emacs Lisp files."
- (interactive "P")
+ (interactive "P" dired-mode)
(dired-map-over-marks-check #'dired-byte-compile arg 'byte-compile t))
(defun dired-load ()
@@ -1804,7 +1907,7 @@ uncompress and unpack all the files in the archive."
;;;###autoload
(defun dired-do-load (&optional arg)
"Load the marked (or next ARG) Emacs Lisp files."
- (interactive "P")
+ (interactive "P" dired-mode)
(dired-map-over-marks-check #'dired-load arg 'load t))
;;;###autoload
@@ -1821,7 +1924,7 @@ You can reset all subdirectory switches to the default using
\\<dired-mode-map>\\[dired-reset-subdir-switches].
See Info node `(emacs)Subdir switches' for more details."
;; Moves point if the next ARG files are redisplayed.
- (interactive "P\np")
+ (interactive "P\np" dired-mode)
(if (and test-for-subdir (dired-get-subdir))
(let* ((dir (dired-get-subdir))
(switches (cdr (assoc-string dir dired-switches-alist))))
@@ -1851,7 +1954,7 @@ See Info node `(emacs)Subdir switches' for more details."
(defun dired-reset-subdir-switches ()
"Set `dired-switches-alist' to nil and revert Dired buffer."
- (interactive)
+ (interactive nil dired-mode)
(setq dired-switches-alist nil)
(revert-buffer))
@@ -2691,7 +2794,8 @@ FILENAME is a full file name."
Parent directories of DIRECTORY are created as needed.
If DIRECTORY already exists, signal an error."
(interactive
- (list (read-file-name "Create directory: " (dired-current-directory))))
+ (list (read-file-name "Create directory: " (dired-current-directory)))
+ dired-mode)
(let* ((expanded (directory-file-name (expand-file-name directory)))
new)
(if (file-exists-p expanded)
@@ -2708,7 +2812,7 @@ If DIRECTORY already exists, signal an error."
Add a new entry for the new file in the Dired buffer.
Parent directories of FILE are created as needed.
If FILE already exists, signal an error."
- (interactive (list (read-file-name "Create empty file: ")))
+ (interactive (list (read-file-name "Create empty file: ")) dired-mode)
(let* ((expanded (expand-file-name file))
new)
(if (file-exists-p expanded)
@@ -2771,7 +2875,7 @@ element 4 (`\\[universal-argument]'), the inverted value of
`dired-copy-dereference' will be used.
Also see `dired-do-revert-buffer'."
- (interactive "P")
+ (interactive "P" dired-mode)
(let ((dired-recursive-copies dired-recursive-copies)
(dired-copy-dereference (if (equal arg '(4))
(not dired-copy-dereference)
@@ -2794,7 +2898,7 @@ suggested for the target directory depends on the value of
For relative symlinks, use \\[dired-do-relsymlink].
Also see `dired-do-revert-buffer'."
- (interactive "P")
+ (interactive "P" dired-mode)
(dired-do-create-files 'symlink #'make-symbolic-link
"Symlink" arg dired-keep-marker-symlink))
@@ -2811,7 +2915,7 @@ not absolute ones like
foo -> /ugly/file/name/that/may/change/any/day/bar/foo
For absolute symlinks, use \\[dired-do-symlink]."
- (interactive "P")
+ (interactive "P" dired-mode)
(dired-do-create-files 'relsymlink #'dired-make-relative-symlink
"RelSymLink" arg dired-keep-marker-relsymlink))
@@ -2876,7 +2980,7 @@ suggested for the target directory depends on the value of
`dired-dwim-target', which see.
Also see `dired-do-revert-buffer'."
- (interactive "P")
+ (interactive "P" dired-mode)
(dired-do-create-files 'hardlink #'dired-hardlink
"Hardlink" arg dired-keep-marker-hardlink))
@@ -2897,7 +3001,7 @@ The default suggested for the target directory depends on the value
of `dired-dwim-target', which see.
Also see `dired-do-revert-buffer'."
- (interactive "P")
+ (interactive "P" dired-mode)
(when (seq-find (lambda (file)
(member (file-name-nondirectory file) '("." "..")))
(dired-get-marked-files nil arg))
@@ -2996,7 +3100,7 @@ REGEXP defaults to the last regexp used.
With a zero prefix arg, renaming by regexp affects the absolute file name.
Normally, only the non-directory part of the file name is used and changed."
- (interactive (dired-mark-read-regexp "Rename"))
+ (interactive (dired-mark-read-regexp "Rename") dired-mode)
(dired-do-create-files-regexp
#'dired-rename-file
"Rename" arg regexp newname whole-name dired-keep-marker-rename))
@@ -3005,7 +3109,7 @@ Normally, only the non-directory part of the file name is used and changed."
(defun dired-do-copy-regexp (regexp newname &optional arg whole-name)
"Copy selected files whose names match REGEXP to NEWNAME.
See function `dired-do-rename-regexp' for more info."
- (interactive (dired-mark-read-regexp "Copy"))
+ (interactive (dired-mark-read-regexp "Copy") dired-mode)
(let ((dired-recursive-copies nil)) ; No recursive copies.
(dired-do-create-files-regexp
#'dired-copy-file
@@ -3016,7 +3120,7 @@ See function `dired-do-rename-regexp' for more info."
(defun dired-do-hardlink-regexp (regexp newname &optional arg whole-name)
"Hardlink selected files whose names match REGEXP to NEWNAME.
See function `dired-do-rename-regexp' for more info."
- (interactive (dired-mark-read-regexp "HardLink"))
+ (interactive (dired-mark-read-regexp "HardLink") dired-mode)
(dired-do-create-files-regexp
#'add-name-to-file
"HardLink" arg regexp newname whole-name dired-keep-marker-hardlink))
@@ -3025,7 +3129,7 @@ See function `dired-do-rename-regexp' for more info."
(defun dired-do-symlink-regexp (regexp newname &optional arg whole-name)
"Symlink selected files whose names match REGEXP to NEWNAME.
See function `dired-do-rename-regexp' for more info."
- (interactive (dired-mark-read-regexp "SymLink"))
+ (interactive (dired-mark-read-regexp "SymLink") dired-mode)
(dired-do-create-files-regexp
#'make-symbolic-link
"SymLink" arg regexp newname whole-name dired-keep-marker-symlink))
@@ -3035,7 +3139,7 @@ See function `dired-do-rename-regexp' for more info."
"RelSymlink all marked files containing REGEXP to NEWNAME.
See functions `dired-do-rename-regexp' and `dired-do-relsymlink'
for more info."
- (interactive (dired-mark-read-regexp "RelSymLink"))
+ (interactive (dired-mark-read-regexp "RelSymLink") dired-mode)
(dired-do-create-files-regexp
#'dired-make-relative-symlink
"RelSymLink" arg regexp newname whole-name dired-keep-marker-relsymlink))
@@ -3080,13 +3184,13 @@ Type \\`SPC' or \\`y' to %s one file, \\`DEL' or \\`n' to skip to next,
;;;###autoload
(defun dired-upcase (&optional arg)
"Rename all marked (or next ARG) files to upper case."
- (interactive "P")
+ (interactive "P" dired-mode)
(dired-rename-non-directory #'upcase "Rename upcase" arg))
;;;###autoload
(defun dired-downcase (&optional arg)
"Rename all marked (or next ARG) files to lower case."
- (interactive "P")
+ (interactive "P" dired-mode)
(dired-rename-non-directory #'downcase "Rename downcase" arg))
@@ -3114,7 +3218,8 @@ See Info node `(emacs)Subdir switches' for more details."
(list (dired-get-filename)
(if current-prefix-arg
(read-string "Switches for listing: "
- (or dired-subdir-switches dired-actual-switches)))))
+ (or dired-subdir-switches dired-actual-switches))))
+ dired-mode)
(let ((opoint (point)))
;; We don't need a marker for opoint as the subdir is always
;; inserted *after* opoint.
@@ -3146,7 +3251,8 @@ This function takes some pains to conform to `ls -lR' output."
(list (dired-get-filename)
(if current-prefix-arg
(read-string "Switches for listing: "
- (or dired-subdir-switches dired-actual-switches)))))
+ (or dired-subdir-switches dired-actual-switches))))
+ dired-mode)
(setq dirname (file-name-as-directory (expand-file-name dirname)))
(or no-error-if-not-dir-p
(file-directory-p dirname)
@@ -3223,7 +3329,7 @@ In interactive use, the command prompts for DIRNAME.
When called from Lisp, if REMEMBER-MARKS is non-nil, return an alist
of marked files. If KILL-ROOT is non-nil, kill DIRNAME as well."
- (interactive "DKill tree below directory: \ni\nP")
+ (interactive "DKill tree below directory: \ni\nP" dired-mode)
(setq dirname (file-name-as-directory (expand-file-name dirname)))
(let ((s-alist dired-subdir-alist) dir m-alist)
(while s-alist
@@ -3377,7 +3483,8 @@ When called interactively and not on a subdir line, go to this subdir's line."
(list (if current-prefix-arg
(prefix-numeric-value current-prefix-arg)
;; if on subdir start already, don't stay there!
- (if (dired-get-subdir) 1 0))))
+ (if (dired-get-subdir) 1 0)))
+ dired-mode)
(dired-next-subdir (- arg) no-error-if-not-found no-skip))
;;;###autoload
@@ -3410,7 +3517,7 @@ The next char is \\n."
"Mark all files except `.' and `..' in current subdirectory.
If the Dired buffer shows multiple directories, this command
marks the files listed in the subdirectory that point is in."
- (interactive)
+ (interactive nil dired-mode)
(let ((p-min (dired-subdir-min)))
(dired-mark-files-in-region p-min (dired-subdir-max))))
@@ -3419,7 +3526,7 @@ marks the files listed in the subdirectory that point is in."
"Remove all lines of current subdirectory.
Lower levels are unaffected."
;; With optional REMEMBER-MARKS, return a mark-alist.
- (interactive)
+ (interactive nil dired-mode)
(let* ((beg (dired-subdir-min))
(end (dired-subdir-max))
(modflag (buffer-modified-p))
@@ -3446,7 +3553,7 @@ Lower levels are unaffected."
;;;###autoload
(defun dired-tree-up (arg)
"Go up ARG levels in the Dired tree."
- (interactive "p")
+ (interactive "p" dired-mode)
(let ((dir (dired-current-directory)))
(while (>= arg 1)
(setq arg (1- arg)
@@ -3458,7 +3565,7 @@ Lower levels are unaffected."
;;;###autoload
(defun dired-tree-down ()
"Go down in the Dired tree."
- (interactive)
+ (interactive nil dired-mode)
(let ((dir (dired-current-directory)) ; has slash
pos case-fold-search) ; filenames are case sensitive
(let ((rest (reverse dired-subdir-alist)) elt)
@@ -3480,7 +3587,7 @@ Lower levels are unaffected."
"Hide or unhide the current subdirectory and move to next directory.
Optional prefix arg is a repeat factor.
Use \\[dired-hide-all] to (un)hide all directories."
- (interactive "p")
+ (interactive "p" dired-mode)
(with-silent-modifications
(while (>= (setq arg (1- arg)) 0)
(let* ((cur-dir (dired-current-directory))
@@ -3501,7 +3608,7 @@ Use \\[dired-hide-all] to (un)hide all directories."
"Hide all subdirectories, leaving only their header lines.
If there is already something hidden, make everything visible again.
Use \\[dired-hide-subdir] to (un)hide a particular subdirectory."
- (interactive "P")
+ (interactive "P" dired-mode)
(with-silent-modifications
(if (text-property-any (point-min) (point-max) 'invisible 'dired)
(dired--unhide (point-min) (point-max))
@@ -3577,14 +3684,14 @@ It's intended to override the default search function."
;;;###autoload
(defun dired-isearch-filenames ()
"Search for a string using Isearch only in file names in the Dired buffer."
- (interactive)
+ (interactive nil dired-mode)
(setq-local dired-isearch-filenames t)
(isearch-forward nil t))
;;;###autoload
(defun dired-isearch-filenames-regexp ()
"Search for a regexp using Isearch only in file names in the Dired buffer."
- (interactive)
+ (interactive nil dired-mode)
(setq-local dired-isearch-filenames t)
(isearch-forward-regexp nil t))
@@ -3594,7 +3701,7 @@ It's intended to override the default search function."
;;;###autoload
(defun dired-do-isearch ()
"Search for a string through all marked files using Isearch."
- (interactive)
+ (interactive nil dired-mode)
(multi-isearch-files
(prog1 (dired-get-marked-files nil nil
#'dired-nondirectory-p nil t)
@@ -3603,7 +3710,7 @@ It's intended to override the default search function."
;;;###autoload
(defun dired-do-isearch-regexp ()
"Search for a regexp through all marked files using Isearch."
- (interactive)
+ (interactive nil dired-mode)
(prog1 (multi-isearch-files-regexp
(dired-get-marked-files nil nil
'dired-nondirectory-p nil t))
@@ -3619,7 +3726,7 @@ If no files are marked, search through the file under point.
Stops when a match is found.
To continue searching for next match, use command \\[fileloop-continue]."
- (interactive "sSearch marked files (regexp): ")
+ (interactive "sSearch marked files (regexp): " dired-mode)
(fileloop-initialize-search
regexp
(dired-get-marked-files nil nil #'dired-nondirectory-p)
@@ -3642,7 +3749,8 @@ resume the query replace with the command \\[fileloop-continue]."
(let ((common
(query-replace-read-args
"Query replace regexp in marked files" t t)))
- (list (nth 0 common) (nth 1 common) (nth 2 common))))
+ (list (nth 0 common) (nth 1 common) (nth 2 common)))
+ dired-mode)
(dolist (file (dired-get-marked-files nil nil #'dired-nondirectory-p nil t))
(let ((buffer (get-file-buffer file)))
(if (and buffer (with-current-buffer buffer
@@ -3655,6 +3763,22 @@ resume the query replace with the command \\[fileloop-continue]."
delimited)
(fileloop-continue))
+;;;###autoload
+(defun dired-do-replace-regexp-as-diff (from to &optional delimited)
+ "Do `replace-regexp' of FROM with TO as diff, on all marked files.
+Third arg DELIMITED (prefix arg) means replace only word-delimited matches.
+The replacements are displayed in the buffer *replace-diff* that
+you can later apply as a patch after reviewing the changes."
+ (interactive
+ (let ((common
+ (query-replace-read-args
+ "Replace regexp as diff in marked files" t t)))
+ (list (nth 0 common) (nth 1 common) (nth 2 common))))
+ (dired-post-do-command)
+ (multi-file-replace-regexp-as-diff
+ (dired-get-marked-files nil nil #'dired-nondirectory-p)
+ from to delimited))
+
(declare-function xref-query-replace-in-results "xref")
(declare-function project--files-in-directory "project")
@@ -3670,7 +3794,7 @@ matching `grep-find-ignored-directories' are skipped in the marked
directories.
REGEXP should use constructs supported by your local `grep' command."
- (interactive "sSearch marked files (regexp): ")
+ (interactive "sSearch marked files (regexp): " dired-mode)
(require 'grep)
(require 'xref)
(defvar grep-find-ignored-files)
@@ -3725,7 +3849,8 @@ function works."
(let ((common
(query-replace-read-args
"Query replace regexp in marked files" t t)))
- (list (nth 0 common) (nth 1 common))))
+ (list (nth 0 common) (nth 1 common)))
+ dired-mode)
(require 'xref)
(defvar xref-show-xrefs-function)
(defvar xref-auto-jump-to-first-xref)
@@ -3747,7 +3872,7 @@ function works."
If you give a prefix argument \\[universal-argument] to this command, and
FILE is a symbolic link, then the command will print the type
of the target of the link instead."
- (interactive (list (dired-get-filename t) current-prefix-arg))
+ (interactive (list (dired-get-filename t) current-prefix-arg) dired-mode)
(let (process-file-side-effects)
(with-temp-buffer
(if deref-symlinks
@@ -3780,7 +3905,7 @@ the same files/directories marked in the VC-Directory buffer that were
marked in the original Dired buffer. If the current directory doesn't
belong to a VCS repository, prompt for a repository directory. In this
case, the VERBOSE argument is ignored."
- (interactive "P")
+ (interactive "P" dired-mode)
(let* ((marked-files
(dired-get-marked-files nil nil nil nil t))
(mark-files
@@ -3829,9 +3954,6 @@ case, the VERBOSE argument is ignored."
(setq model (vc-checkout-model backend only-files-list))))
(list backend files only-files-list state model)))
-(define-obsolete-function-alias 'minibuffer-default-add-dired-shell-commands
- #'dired-minibuffer-default-add-shell-commands "29.1")
-
(provide 'dired-aux)
diff --git a/lisp/dired-x.el b/lisp/dired-x.el
index 5780f1353ad..62fdd916e69 100644
--- a/lisp/dired-x.el
+++ b/lisp/dired-x.el
@@ -1,6 +1,6 @@
;;; dired-x.el --- extra Dired functionality -*- lexical-binding:t -*-
-;; Copyright (C) 1993-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1993-2024 Free Software Foundation, Inc.
;; Author: Sebastian Kremer <sk@thp.uni-koeln.de>
;; Lawrence R. Dodd <dodd@roebling.poly.edu>
@@ -299,9 +299,8 @@ Optional MARKER-CHAR is marker to use.
Interactively, ask for EXTENSION.
Prefixed with one \\[universal-argument], unmark files instead.
Prefixed with two \\[universal-argument]'s, prompt for MARKER-CHAR and mark files with it."
- (interactive (dired--mark-suffix-interactive-spec))
- (unless (listp extension)
- (setq extension (list extension)))
+ (interactive (dired--mark-suffix-interactive-spec) dired-mode)
+ (setq extension (ensure-list extension))
(dired-mark-files-regexp
(concat ".";; don't match names with nothing but an extension
"\\("
@@ -324,9 +323,8 @@ Optional MARKER-CHAR is marker to use.
Interactively, ask for SUFFIX.
Prefixed with one \\[universal-argument], unmark files instead.
Prefixed with two \\[universal-argument]'s, prompt for MARKER-CHAR and mark files with it."
- (interactive (dired--mark-suffix-interactive-spec))
- (unless (listp suffix)
- (setq suffix (list suffix)))
+ (interactive (dired--mark-suffix-interactive-spec) dired-mode)
+ (setq suffix (ensure-list suffix))
(dired-mark-files-regexp
(concat ".";; don't match names with nothing but an extension
"\\("
@@ -337,7 +335,7 @@ Prefixed with two \\[universal-argument]'s, prompt for MARKER-CHAR and mark file
(defun dired-flag-extension (extension)
"In Dired, flag all files with a certain EXTENSION for deletion.
A `.' is *not* automatically prepended to the string entered."
- (interactive "sFlagging extension: ")
+ (interactive "sFlagging extension: " dired-mode)
(dired-mark-extension extension dired-del-marker))
;; Define some unpopular file extensions. Used for cleaning and omitting.
@@ -366,7 +364,7 @@ A `.' is *not* automatically prepended to the string entered."
(defun dired-clean-patch ()
"Flag dispensable files created by patch for deletion.
See variable `dired-patch-unclean-extensions'."
- (interactive)
+ (interactive nil dired-mode)
(dired-flag-extension dired-patch-unclean-extensions))
(defun dired-clean-tex ()
@@ -374,7 +372,7 @@ See variable `dired-patch-unclean-extensions'."
See variables `dired-tex-unclean-extensions',
`dired-latex-unclean-extensions', `dired-bibtex-unclean-extensions' and
`dired-texinfo-unclean-extensions'."
- (interactive)
+ (interactive nil dired-mode)
(dired-flag-extension (append dired-texinfo-unclean-extensions
dired-latex-unclean-extensions
dired-bibtex-unclean-extensions
@@ -385,7 +383,7 @@ See variables `dired-tex-unclean-extensions',
See variables `dired-texinfo-unclean-extensions',
`dired-latex-unclean-extensions', `dired-bibtex-unclean-extensions' and
`dired-texinfo-unclean-extensions'."
- (interactive)
+ (interactive nil dired-mode)
(dired-flag-extension (append dired-texinfo-unclean-extensions
dired-latex-unclean-extensions
dired-bibtex-unclean-extensions
@@ -421,7 +419,7 @@ Should never be used as marker by the user or other packages.")
(defun dired-mark-omitted ()
"Mark files matching `dired-omit-files' and `dired-omit-extensions'."
- (interactive)
+ (interactive nil dired-mode)
(let ((dired-omit-mode nil)) (revert-buffer)) ;; Show omitted files
(dired-mark-unmarked-files (dired-omit-regexp) nil nil dired-omit-localp
(dired-omit-case-fold-p (if (stringp dired-directory)
@@ -457,7 +455,7 @@ if called from Lisp and buffer is bigger than `dired-omit-size-limit'.
Optional arg INIT-COUNT is an initial count tha'is added to the number
of lines omitted by this invocation of `dired-omit-expunge', in the
status message."
- (interactive "sOmit files (regexp): \nP")
+ (interactive "sOmit files (regexp): \nP" dired-mode)
;; Bind `dired-marker-char' to `dired-omit-marker-char',
;; then call `dired-do-kill-lines'.
(if (and dired-omit-mode
@@ -493,7 +491,11 @@ status message."
(setq count (+ count
(dired-do-kill-lines
nil
- (if dired-omit-verbose "Omitted %d line%s" "")
+ (if dired-omit-verbose
+ (format "Omitted %%d line%%s in %s"
+ (abbreviate-file-name
+ dired-directory))
+ "")
init-count)))
(force-mode-line-update))))
;; Try to preserve modified state, so `%*' doesn't appear in
@@ -529,7 +531,8 @@ files in the active region if `dired-mark-region' is non-nil."
(list (read-regexp
(format-prompt "Mark unmarked files matching regexp" "all")
nil 'dired-regexp-history)
- nil current-prefix-arg nil))
+ nil current-prefix-arg nil)
+ dired-mode)
(let ((dired-marker-char (if unflag-p ?\s dired-marker-char)))
(dired-mark-if
(and
@@ -610,7 +613,8 @@ you can relist single subdirs using \\[dired-do-redisplay]."
(insert " "
(directory-file-name (file-name-directory default-directory))
":\n"))
- (dired-mode dirname (or switches dired-listing-switches))
+ (dired-mode
+ dirname (or switches (connection-local-value dired-listing-switches)))
(setq mode-name "Virtual Dired"
revert-buffer-function 'dired-virtual-revert
dired-subdir-alist nil)
@@ -734,7 +738,7 @@ displayed this way is restricted by the height of the current window and
To keep Dired buffer displayed, type \\[split-window-below] first.
To display just marked files, type \\[delete-other-windows] first."
- (interactive "P")
+ (interactive "P" dired-mode)
(dired-simultaneous-find-file (dired-get-marked-files nil nil nil nil t)
noselect))
@@ -778,7 +782,7 @@ NOSELECT the files are merely found but not selected."
"Run VM on this file.
With optional prefix argument, visits the folder read-only.
Otherwise obeys the value of `dired-vm-read-only-folders'."
- (interactive "P")
+ (interactive "P" dired-mode)
(let ((dir (dired-current-directory))
(fil (dired-get-filename)))
(vm-visit-folder fil (or read-only
@@ -790,7 +794,7 @@ Otherwise obeys the value of `dired-vm-read-only-folders'."
(defun dired-rmail ()
"Run RMAIL on this file."
- (interactive)
+ (interactive nil dired-mode)
(rmail (dired-get-filename)))
(defun dired-do-run-mail ()
@@ -798,7 +802,7 @@ Otherwise obeys the value of `dired-vm-read-only-folders'."
Prompt for confirmation first; if the user says yes, call
`dired-vm' if `dired-bind-vm' is non-nil, `dired-rmail'
otherwise."
- (interactive)
+ (interactive nil dired-mode)
(let ((file (dired-get-filename t)))
(if dired-bind-vm
(if (y-or-n-p (format-message
@@ -884,7 +888,8 @@ only in the active region if `dired-mark-region' is non-nil."
(if current-prefix-arg
"UNmark"
"Mark")))
- current-prefix-arg))
+ current-prefix-arg)
+ dired-mode)
(message "%s" predicate)
(let ((dired-marker-char (if unflag-p ?\040 dired-marker-char))
inode s mode nlink uid gid size time name sym)
@@ -1010,7 +1015,7 @@ is loaded then call \\[dired-x-bind-find-file]."
"Bind `dired-x-find-file' in place of `find-file' (or vice-versa).
Similarly for `dired-x-find-file-other-window' and `find-file-other-window'.
Binding direction based on `dired-x-hands-off-my-keys'."
- (interactive)
+ (interactive nil)
(if (called-interactively-p 'interactive)
(setq dired-x-hands-off-my-keys
(not (y-or-n-p (format-message
diff --git a/lisp/dired.el b/lisp/dired.el
index 27172c50a9f..69fa15dde73 100644
--- a/lisp/dired.el
+++ b/lisp/dired.el
@@ -1,6 +1,6 @@
;;; dired.el --- directory-browsing commands -*- lexical-binding: t -*-
-;; Copyright (C) 1985-1986, 1992-1997, 2000-2023 Free Software
+;; Copyright (C) 1985-1986, 1992-1997, 2000-2024 Free Software
;; Foundation, Inc.
;; Author: Sebastian Kremer <sk@thp.uni-koeln.de>
@@ -75,7 +75,9 @@ each option.
On systems such as MS-DOS and MS-Windows, which use `ls' emulation in Lisp,
some of the `ls' switches are not supported; see the doc string of
-`insert-directory' in `ls-lisp.el' for more details."
+`insert-directory' in `ls-lisp.el' for more details.
+
+For remote Dired buffers, this option supports connection-local values."
:type 'string
:group 'dired)
@@ -119,10 +121,11 @@ checks this alist to enable globstar in the shell subprocess.")
(defcustom dired-use-ls-dired 'unspecified
"Non-nil means Dired should pass the \"--dired\" option to \"ls\".
If nil, don't pass \"--dired\" to \"ls\".
-The special value of `unspecified' means to check whether \"ls\"
-supports the \"--dired\" option, and save the result in this
-variable. This is performed the first time `dired-insert-directory'
-is invoked.
+The special value of `unspecified' means to check whether
+`insert-directory-program' supports the \"--dired\" option, and save
+the result in this variable.
+This is performed the first time `dired-insert-directory'
+invokes `insert-directory-program'.
Note that if you set this option to nil, either through choice or
because your \"ls\" program does not support \"--dired\", Dired
@@ -294,7 +297,7 @@ then this will always be equivalent to `move'."
(revert-buffer nil t)))))
:type '(choice (const :tag "Don't allow dragging" nil)
(const :tag "Copy file to new location" t)
- (const :tag "Move file to new location" t)
+ (const :tag "Move file to new location" move)
(const :tag "Create symbolic link to file" link))
:group 'dired
:version "29.1")
@@ -348,6 +351,7 @@ with the buffer narrowed to the listing."
(defcustom dired-make-directory-clickable t
"When non-nil, make the directory at the start of the dired buffer clickable."
:version "29.1"
+ :group 'dired
:type 'boolean)
(defcustom dired-initial-position-hook nil
@@ -427,6 +431,7 @@ is anywhere on its Dired line, except the beginning of the line."
(defcustom dired-kill-when-opening-new-dired-buffer nil
"If non-nil, kill the current buffer when selecting a new directory."
:type 'boolean
+ :group 'dired
:version "28.1")
(defcustom dired-guess-shell-case-fold-search t
@@ -495,9 +500,41 @@ to nil: a pipe using `zcat' or `gunzip -c' will be used."
(string :tag "Switches"))
:version "29.1")
+(defcustom dired-movement-style nil
+ "Non-nil means point skips empty lines when moving in Dired buffers.
+This affects only `dired-next-line', `dired-previous-line',
+`dired-next-dirline', `dired-prev-dirline'.
+
+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."
+ :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))
+ :group 'dired
+ :version "30.1")
+
(defcustom dired-hide-details-preserved-columns nil
"List of columns which are not hidden in `dired-hide-details-mode'."
:type '(repeat integer)
+ :group 'dired
+ :version "30.1")
+
+(defcustom dired-filename-display-length nil
+ "If non-nil, restrict the display length of filenames.
+If the value is the symbol `window', the right edge of current
+window is used as the restriction. Otherwise, it should be an
+integer representing the maximum filename length.
+
+The middle part of filename whose length exceeds the restriction
+is hidden by using the `invisible' property and an ellipsis is
+displayed instead."
+ :type '(choice (const :tag "No restriction" nil)
+ (const :tag "Window" window)
+ (integer :tag "Integer"))
+ :group 'dired
:version "30.1")
@@ -1347,7 +1384,8 @@ The return value is the target column for the file names."
;; is passed in directory name syntax
;; if it was the name of a directory at all.
(file-name-directory dirname)))
- (or switches (setq switches dired-listing-switches))
+ (or switches
+ (setq switches (connection-local-value dired-listing-switches)))
(if mode (funcall mode)
(dired-mode dir-or-list switches))
;; default-directory and dired-actual-switches are set now
@@ -1485,18 +1523,21 @@ wildcards, erases the buffer, and builds the subdir-alist anew
(setq dir dired-directory
file-list nil))
(setq dir (expand-file-name dir))
- (if (and (equal "" (file-name-nondirectory dir))
- (not file-list))
- ;; If we are reading a whole single directory...
- (dired-insert-directory dir dired-actual-switches nil nil t)
- (if (and (not (insert-directory-wildcard-in-dir-p dir))
- (not (file-readable-p
- (directory-file-name (file-name-directory dir)))))
- (error "Directory %s inaccessible or nonexistent" dir))
+ (cond
+ ((and (equal "" (file-name-nondirectory dir))
+ (not file-list))
+ ;; If we are reading a whole single directory...
+ (dired-insert-directory dir dired-actual-switches nil
+ (not (file-directory-p dir)) t))
+ ((not (or (insert-directory-wildcard-in-dir-p dir)
+ (file-readable-p
+ (directory-file-name (file-name-directory dir)))))
+ (error "Directory %s inaccessible or nonexistent" dir))
+ (t
;; Else treat it as a wildcard spec
;; unless we have an explicit list of files.
(dired-insert-directory dir dired-actual-switches
- file-list (not file-list) t))))
+ file-list (not file-list) t)))))
(defun dired-align-file (beg end)
"Align the fields of a file to the ones of surrounding lines.
@@ -1505,7 +1546,7 @@ BEG..END is the line where the file info is located."
;; hold the largest element ("largest" in the current invocation, of
;; course). So when a single line is output, the size of each field is
;; just big enough for that one output. Thus when dired refreshes one
- ;; line, the alignment if this line w.r.t the rest is messed up because
+ ;; line, the alignment of this line w.r.t the rest is messed up because
;; the fields of that one line will generally be smaller.
;;
;; To work around this problem, we here add spaces to try and
@@ -1572,14 +1613,21 @@ BEG..END is the line where the file info is located."
;; the beginning or the end of the next field, depending on
;; whether this field is left or right aligned).
(align-pt-offset
- (save-excursion
- (goto-char other)
- (move-to-column curcol)
- (when (looking-at
- (concat
- (if (eq (char-before) ?\s) " *" "[^ ]* *")
- (if num-align "[0-9][^ ]*")))
- (- (match-end 0) (match-beginning 0)))))
+ ;; It is never TRT to realign the first column of
+ ;; file's data. But the code below does attempt to
+ ;; realign the first column if there's no whitespace
+ ;; before it, so we force it to let the first column
+ ;; alone.
+ (if (zerop curcol)
+ 0
+ (save-excursion
+ (goto-char other)
+ (move-to-column curcol)
+ (when (looking-at
+ (concat
+ (if (eq (char-before) ?\s) " *" "[^ ]* *")
+ (if num-align "[0-9][^ ]*")))
+ (- (match-end 0) (match-beginning 0))))))
;; Now, the number of spaces to insert is align-pt-offset
;; minus the distance to the equivalent point on the
;; current line.
@@ -1604,9 +1652,6 @@ BEG..END is the line where the file info is located."
(skip-chars-forward "^ ") (skip-chars-forward " "))
(set-marker file nil)))))
-
-(defvar ls-lisp-use-insert-directory-program)
-
(defun dired-check-switches (switches short &optional long)
"Return non-nil if the string SWITCHES matches LONG or SHORT format."
(let (case-fold-search)
@@ -1637,11 +1682,8 @@ If HDR is non-nil, insert a header line with the directory name."
(remotep (file-remote-p dir))
end)
(if (and
- ;; Don't try to invoke `ls' if we are on DOS/Windows where
- ;; ls-lisp emulation is used, except if they want to use `ls'
- ;; as indicated by `ls-lisp-use-insert-directory-program'.
- (not (and (featurep 'ls-lisp)
- (null ls-lisp-use-insert-directory-program)))
+ ;; Don't try to invoke `ls' if ls-lisp emulation should be used.
+ (files--use-insert-directory-program-p)
;; FIXME: Big ugly hack for Eshell's eshell-ls-use-in-dired.
(not (bound-and-true-p eshell-ls-use-in-dired))
(or remotep
@@ -1662,11 +1704,14 @@ see `dired-use-ls-dired' for more details.")
(unless remotep
(setq switches (concat "--dired -N " switches))))
;; Expand directory wildcards and fill file-list.
- (let ((dir-wildcard (insert-directory-wildcard-in-dir-p dir)))
- (cond (dir-wildcard
+ (let ((dir-wildcard (and (null file-list) wildcard
+ (insert-directory-wildcard-in-dir-p dir))))
+ (cond ((and dir-wildcard (files--use-insert-directory-program-p))
(setq switches (concat "-d " switches))
(let* ((default-directory (car dir-wildcard))
- (script (format "ls %s %s" switches (cdr dir-wildcard)))
+ (script (format "%s %s %s"
+ insert-directory-program
+ switches (cdr dir-wildcard)))
(sh (or (and remotep "/bin/sh")
(executable-find shell-file-name)
(executable-find "sh")))
@@ -1684,78 +1729,81 @@ see `dired-use-ls-dired' for more details.")
(user-error
"%s: No files matching wildcard" (cdr dir-wildcard)))
(insert-directory-clean (point) switches)))
- (t
- ;; We used to specify the C locale here, to force English
- ;; month names; but this should not be necessary any
- ;; more, with the new value of
- ;; `directory-listing-before-filename-regexp'.
- (if file-list
- (dolist (f file-list)
- (let ((beg (point)))
- (insert-directory f switches nil nil)
- ;; Re-align fields, if necessary.
- (dired-align-file beg (point))))
- (insert-directory dir switches wildcard (not wildcard))))))
- ;; Quote certain characters, unless ls quoted them for us.
- (if (not (dired-switches-escape-p dired-actual-switches))
+ ;; We used to specify the C locale here, to force English
+ ;; month names; but this should not be necessary any
+ ;; more, with the new value of
+ ;; `directory-listing-before-filename-regexp'.
+ ((or file-list dir-wildcard)
+ (let ((default-directory
+ (or (car dir-wildcard) default-directory)))
+ (dolist (f (or file-list
+ (file-expand-wildcards (cdr dir-wildcard))))
+ (let ((beg (point)))
+ (insert-directory f switches nil nil)
+ ;; Re-align fields, if necessary.
+ (dired-align-file beg (point))))))
+ (t
+ (insert-directory dir switches wildcard (not wildcard))))
+ ;; Quote certain characters, unless ls quoted them for us.
+ (if (not (dired-switches-escape-p dired-actual-switches))
+ (save-excursion
+ (setq end (point-marker))
+ (goto-char opoint)
+ (while (search-forward "\\" end t)
+ (replace-match (apply #'propertize
+ "\\\\"
+ (text-properties-at (match-beginning 0)))
+ nil t))
+ (goto-char opoint)
+ (while (search-forward "\^m" end t)
+ (replace-match (apply #'propertize
+ "\\015"
+ (text-properties-at (match-beginning 0)))
+ nil t))
+ (set-marker end nil))
+ ;; Replace any newlines in DIR with literal "\n"s, for the sake
+ ;; of the header line. To disambiguate a literal "\n" in the
+ ;; actual dirname, we also replace "\" with "\\".
+ ;; Personally, I think this should always be done, irrespective
+ ;; of the value of dired-actual-switches, because:
+ ;; i) Dired simply does not work with an unescaped newline in
+ ;; the directory name used in the header (bug=10469#28), and
+ ;; ii) "\" is always replaced with "\\" in the listing, so doing
+ ;; it in the header as well makes things consistent.
+ ;; But at present it is only done if "-b" is in ls-switches,
+ ;; because newlines in dirnames are uncommon, and people may
+ ;; have gotten used to seeing unescaped "\" in the headers.
+ ;; Note: adjust dired-build-subdir-alist if you change this.
+ (setq dir (string-replace "\\" "\\\\" dir)
+ dir (string-replace "\n" "\\n" dir)))
+ ;; If we used --dired and it worked, the lines are already indented.
+ ;; Otherwise, indent them.
+ (unless (save-excursion
+ (goto-char opoint)
+ (looking-at-p " "))
+ (let ((indent-tabs-mode nil))
+ (indent-rigidly opoint (point) 2)))
+ ;; Insert text at the beginning to standardize things.
+ (let ((content-point opoint))
(save-excursion
- (setq end (point-marker))
- (goto-char opoint)
- (while (search-forward "\\" end t)
- (replace-match (apply #'propertize
- "\\\\"
- (text-properties-at (match-beginning 0)))
- nil t))
(goto-char opoint)
- (while (search-forward "\^m" end t)
- (replace-match (apply #'propertize
- "\\015"
- (text-properties-at (match-beginning 0)))
- nil t))
- (set-marker end nil))
- ;; Replace any newlines in DIR with literal "\n"s, for the sake
- ;; of the header line. To disambiguate a literal "\n" in the
- ;; actual dirname, we also replace "\" with "\\".
- ;; Personally, I think this should always be done, irrespective
- ;; of the value of dired-actual-switches, because:
- ;; i) Dired simply does not work with an unescaped newline in
- ;; the directory name used in the header (bug=10469#28), and
- ;; ii) "\" is always replaced with "\\" in the listing, so doing
- ;; it in the header as well makes things consistent.
- ;; But at present it is only done if "-b" is in ls-switches,
- ;; because newlines in dirnames are uncommon, and people may
- ;; have gotten used to seeing unescaped "\" in the headers.
- ;; Note: adjust dired-build-subdir-alist if you change this.
- (setq dir (string-replace "\\" "\\\\" dir)
- dir (string-replace "\n" "\\n" dir)))
- ;; If we used --dired and it worked, the lines are already indented.
- ;; Otherwise, indent them.
- (unless (save-excursion
- (goto-char opoint)
- (looking-at-p " "))
- (let ((indent-tabs-mode nil))
- (indent-rigidly opoint (point) 2)))
- ;; Insert text at the beginning to standardize things.
- (let ((content-point opoint))
- (save-excursion
- (goto-char opoint)
- (when (and (or hdr wildcard)
- (not (and (looking-at "^ \\(.*\\):$")
- (file-name-absolute-p (match-string 1)))))
- ;; Note that dired-build-subdir-alist will replace the name
- ;; by its expansion, so it does not matter whether what we insert
- ;; here is fully expanded, but it should be absolute.
- (insert " " (or (car-safe (insert-directory-wildcard-in-dir-p dir))
- (directory-file-name (file-name-directory dir)))
- ":\n")
- (setq content-point (point)))
- (when wildcard
- ;; Insert "wildcard" line where "total" line would be for a full dir.
- (insert " wildcard " (or (cdr-safe (insert-directory-wildcard-in-dir-p dir))
- (file-name-nondirectory dir))
- "\n"))
- (setq content-point (dired--insert-disk-space opoint dir)))
- (dired-insert-set-properties content-point (point)))))
+ (when (and (or hdr wildcard)
+ (not (and (looking-at "^ \\(.*\\):$")
+ (file-name-absolute-p (match-string 1)))))
+ ;; Note that dired-build-subdir-alist will replace the name
+ ;; by its expansion, so it does not matter whether what we insert
+ ;; here is fully expanded, but it should be absolute.
+ (insert " " (or (car-safe dir-wildcard)
+ (directory-file-name (file-name-directory dir)))
+ ":\n")
+ (setq content-point (point)))
+ (when wildcard
+ ;; Insert "wildcard" line where "total" line would be for a full dir.
+ (insert " wildcard " (or (cdr-safe (insert-directory-wildcard-in-dir-p dir))
+ (file-name-nondirectory dir))
+ "\n"))
+ (setq content-point (dired--insert-disk-space opoint dir)))
+ (dired-insert-set-properties content-point (point))))))
(defun dired--insert-disk-space (beg file)
;; Try to insert the amount of free space.
@@ -1804,7 +1852,7 @@ see `dired-use-ls-dired' for more details.")
"Begin a drag-and-drop operation for the file at EVENT.
If there are marked files and that file is marked, drag every
other marked file as well. Otherwise, unmark all files."
- (interactive "e")
+ (interactive "e" dired-mode)
(when mark-active
(deactivate-mark))
(let* ((modifiers (event-modifiers event))
@@ -1881,51 +1929,72 @@ other marked file as well. Otherwise, unmark all files."
(defvar dired-click-to-select-map)
(defun dired-insert-set-properties (beg end)
- "Add various text properties to the lines in the region, from BEG to END."
+ "Add various text properties to the lines in the region, from BEG to END.
+Overlays could be added when some user options are enabled, e.g.,
+`dired-filename-display-length'."
+ (remove-overlays beg end 'invisible 'dired-filename-hide)
(save-excursion
(goto-char beg)
- (while (< (point) end)
- (ignore-errors
- (if (not (dired-move-to-filename))
- (unless (or (looking-at-p "^$")
- (looking-at-p dired-subdir-regexp))
- (put-text-property (line-beginning-position)
- (1+ (line-end-position))
- 'invisible 'dired-hide-details-information))
- (save-excursion
- (let ((end (1- (point)))
- (opoint (goto-char (1+ (pos-bol))))
- (i 0))
- (put-text-property opoint end 'invisible 'dired-hide-details-detail)
- (while (re-search-forward "[^ ]+" end t)
- (when (member (cl-incf i) dired-hide-details-preserved-columns)
- (put-text-property opoint (point) 'invisible nil))
- (setq opoint (point)))))
- (let ((beg (point)) (end (save-excursion
- (dired-move-to-end-of-filename)
- (1- (point)))))
- (if dired-click-to-select-mode
- (put-text-property beg end 'keymap
- dired-click-to-select-map)
- (when (and dired-mouse-drag-files (fboundp 'x-begin-drag))
- (put-text-property beg end 'keymap
- dired-mouse-drag-files-map)))
- (add-text-properties
- beg (1+ end)
- `(mouse-face
- highlight
- dired-filename t
- help-echo ,(if dired-click-to-select-mode
- "mouse-2: mark or unmark this file"
- (if (and dired-mouse-drag-files
- (fboundp 'x-begin-drag))
- "down-mouse-1: drag this file to another program
+ (let ((ell-len (dired--get-ellipsis-length)) maxlen filename-col)
+ (while (< (point) end)
+ (ignore-errors
+ (if (not (dired-move-to-filename))
+ (unless (or (looking-at-p "^$")
+ (looking-at-p dired-subdir-regexp))
+ (put-text-property (line-beginning-position)
+ (1+ (line-end-position))
+ 'invisible 'dired-hide-details-information))
+ (save-excursion
+ (let ((end (1- (point)))
+ (opoint (goto-char (1+ (pos-bol))))
+ (i 0))
+ (put-text-property opoint end 'invisible 'dired-hide-details-detail)
+ (while (re-search-forward "[^ ]+" end t)
+ (when (member (cl-incf i) dired-hide-details-preserved-columns)
+ (put-text-property opoint (point) 'invisible nil))
+ (setq opoint (point)))))
+ (let ((beg (point)) (end (save-excursion
+ (dired-move-to-end-of-filename)
+ (1- (point)))))
+ (if dired-click-to-select-mode
+ (put-text-property beg end 'keymap
+ dired-click-to-select-map)
+ (when (and dired-mouse-drag-files (fboundp 'x-begin-drag))
+ (put-text-property beg end 'keymap
+ dired-mouse-drag-files-map)))
+ (when dired-filename-display-length
+ (let ((len (string-width (buffer-substring beg (1+ end))))
+ ell-beg)
+ (or maxlen (setq maxlen (dired--get-filename-display-length)))
+ (when (and (integerp maxlen) (> len maxlen (+ ell-len 2)))
+ (or filename-col (setq filename-col (current-column)))
+ (move-to-column (+ filename-col (/ maxlen 2)))
+ (setq ell-beg (point))
+ (move-to-column (+ filename-col (/ maxlen 2)
+ (- len maxlen) ell-len))
+ ;; Here we use overlays because isearch by default
+ ;; doesn't support finding matches in hidden text
+ ;; made invisible via text properties.
+ (let ((ov (make-overlay ell-beg (point))))
+ (overlay-put ov 'invisible 'dired-filename-hide)
+ (overlay-put ov 'isearch-open-invisible #'delete-overlay)
+ (overlay-put ov 'evaporate t)))))
+ (add-text-properties
+ beg (1+ end)
+ `(mouse-face
+ highlight
+ dired-filename t
+ help-echo ,(if dired-click-to-select-mode
+ "mouse-2: mark or unmark this file"
+ (if (and dired-mouse-drag-files
+ (fboundp 'x-begin-drag))
+ "down-mouse-1: drag this file to another program
mouse-2: visit this file in other window"
- "mouse-2: visit this file in other window"))))
- (when (< (+ end 5) (line-end-position))
- (put-text-property (+ end 5) (line-end-position)
- 'invisible 'dired-hide-details-link)))))
- (forward-line 1))))
+ "mouse-2: visit this file in other window"))))
+ (when (< (+ end 5) (line-end-position))
+ (put-text-property (+ end 5) (line-end-position)
+ 'invisible 'dired-hide-details-link)))))
+ (forward-line 1)))))
(defun dired--make-directory-clickable ()
(save-excursion
@@ -1948,15 +2017,50 @@ mouse-2: visit this file in other window"
keymap ,(let* ((current-dir dir)
(click (lambda ()
(interactive)
- (if (assoc current-dir dired-subdir-alist)
- (dired-goto-subdir current-dir)
- (dired current-dir)))))
+ (cond
+ ((assoc current-dir dired-subdir-alist)
+ (dired-goto-subdir current-dir))
+ ;; If there is a wildcard chars
+ ;; in the directory name, don't
+ ;; use the alternate file machinery
+ ;; which tries to keep only one
+ ;; dired buffer open at once.
+ ;;
+ ;; FIXME: Is this code path reachable?
+ ((insert-directory-wildcard-in-dir-p
+ current-dir)
+ (dired current-dir))
+ (t
+ (dired--find-possibly-alternative-file
+ current-dir))))))
(define-keymap
"<mouse-2>" click
"<follow-link>" 'mouse-face
"RET" click))))
(setq segment-start (point)))))))
+(defun dired--get-ellipsis-length ()
+ "Return length of ellipsis."
+ (let* ((dt (or (window-display-table)
+ buffer-display-table
+ standard-display-table))
+ (glyphs (and dt (display-table-slot dt 'selective-display)))
+ (vlen (length glyphs))
+ (char-glyphs (make-vector vlen nil)))
+ (dotimes (i vlen)
+ (aset char-glyphs i (glyph-char (aref glyphs i))))
+ (string-width (if glyphs (concat char-glyphs) "..."))))
+
+(defun dired--get-filename-display-length ()
+ "Return maximum display length of filename.
+When `dired-filename-display-length' is not an integer, the
+function actually returns the number of columns available for
+displaying the file names, and should be called with point at the
+first character of the file name."
+ (if (integerp dired-filename-display-length)
+ dired-filename-display-length
+ (- (window-max-chars-per-line) 1 (current-column))))
+
;;; Reverting a dired buffer
@@ -2510,17 +2614,38 @@ Do so according to the former subdir alist OLD-SUBDIR-ALIST."
["Delete Image Tag..." image-dired-delete-tag
:help "Delete image tag from current or marked files"]))
+(declare-function shell-command-guess "dired-aux" (files))
+(defvar shell-command-guess-open)
+
(defun dired-context-menu (menu click)
"Populate MENU with Dired mode commands at CLICK."
(when (mouse-posn-property (event-start click) 'dired-filename)
(define-key menu [dired-separator] menu-bar-separator)
- (let ((easy-menu (make-sparse-keymap "Immediate")))
+ (let* ((filename (save-excursion
+ (mouse-set-point click)
+ (dired-get-filename nil t)))
+ (commands (shell-command-guess (list filename)))
+ (easy-menu (make-sparse-keymap "Immediate")))
(easy-menu-define nil easy-menu nil
- '("Immediate"
+ `("Immediate"
["Find This File" dired-mouse-find-file
:help "Edit file at mouse click"]
["Find in Other Window" dired-mouse-find-file-other-window
- :help "Edit file at mouse click in other window"]))
+ :help "Edit file at mouse click in other window"]
+ ,@(when shell-command-guess-open
+ '(["Open" dired-do-open
+ :help "Open externally"]))
+ ,@(when commands
+ (list (cons "Open With"
+ (append
+ (mapcar (lambda (command)
+ `[,(or (get-text-property 0 'name command)
+ command)
+ (lambda ()
+ (interactive)
+ (dired-do-async-shell-command
+ ,command nil (list ,filename)))])
+ commands)))))))
(dolist (item (reverse (lookup-key easy-menu [menu-bar immediate])))
(when (consp item)
(define-key menu (vector (car item)) (cdr item))))))
@@ -2598,6 +2723,7 @@ Keybindings:
mode-line-buffer-identification
(propertized-buffer-identification "%17b"))
(add-to-invisibility-spec '(dired . t))
+ (dired-filename-update-invisibility-spec)
;; Ignore dired-hide-details-* value of invisible text property by default.
(when (eq buffer-invisibility-spec t)
(setq buffer-invisibility-spec (list t)))
@@ -2611,7 +2737,8 @@ Keybindings:
(expand-file-name (if (listp dired-directory)
(car dired-directory)
dired-directory)))
- (setq-local dired-actual-switches (or switches dired-listing-switches))
+ (setq-local dired-actual-switches
+ (or switches (connection-local-value dired-listing-switches)))
(setq-local font-lock-defaults
'(dired-font-lock-keywords t nil nil beginning-of-line))
(setq-local desktop-save-buffer 'dired-desktop-buffer-misc-data)
@@ -2643,7 +2770,7 @@ Keybindings:
"Undo in a Dired buffer.
This doesn't recover lost files, it just undoes changes in the buffer itself.
You can use it to recover marks, killed lines or subdirs."
- (interactive)
+ (interactive nil dired-mode)
(let ((inhibit-read-only t))
(undo))
(dired-build-subdir-alist)
@@ -2655,7 +2782,7 @@ Actual changes in files cannot be undone by Emacs."))
If the current buffer can be edited with Wdired, (i.e. the major
mode is `dired-mode'), call `wdired-change-to-wdired-mode'.
Otherwise, toggle `read-only-mode'."
- (interactive)
+ (interactive nil dired-mode)
(unless (file-exists-p default-directory)
(user-error "The current directory no longer exists"))
(when (and (not (file-writable-p default-directory))
@@ -2666,28 +2793,73 @@ Otherwise, toggle `read-only-mode'."
(wdired-change-to-wdired-mode)
(read-only-mode 'toggle)))
-(defun dired-next-line (arg)
- "Move down lines then position at filename.
-Optional prefix ARG says how many lines to move; default is one line."
- (interactive "^p")
+(defun dired--trivial-next-line (arg)
+ "Move down ARG lines, then position at filename."
(let ((line-move-visual)
- (goal-column))
+ (goal-column))
(line-move arg t))
;; We never want to move point into an invisible line.
(while (and (invisible-p (point))
- (not (if (and arg (< arg 0)) (bobp) (eobp))))
+ (not (if (and arg (< arg 0)) (bobp) (eobp))))
(forward-char (if (and arg (< arg 0)) -1 1)))
(dired-move-to-filename))
+(defun dired-next-line (arg)
+ "Move down ARG lines, then position at filename.
+The argument ARG (interactively, prefix argument) says how many lines
+to move; the default is one line.
+
+Whether to skip empty lines and how to move from last line
+is controlled by `dired-movement-style'."
+ (interactive "^p" dired-mode)
+ (if dired-movement-style
+ (dired--move-to-next-line arg #'dired--trivial-next-line)
+ (dired--trivial-next-line arg)))
+
+(defun dired--move-to-next-line (arg jumpfun)
+ (let ((old-position (progn
+ ;; It's always true that we should move
+ ;; to the filename when possible.
+ (dired-move-to-filename)
+ (point)))
+ ;; Up/Down indicates the direction.
+ (moving-down (if (cl-plusp arg)
+ 1 ; means Down.
+ -1))) ; means Up.
+ ;; Line by line in case we forget to skip empty lines.
+ (while (not (zerop arg))
+ (funcall jumpfun moving-down)
+ (when (= old-position (point))
+ ;; Now point is at beginning/end of movable area,
+ ;; but it still wants to move farther.
+ (if (eq dired-movement-style 'cycle)
+ ;; `cycle': go to the other end.
+ (goto-char (if (cl-plusp moving-down)
+ (point-min)
+ (point-max)))
+ ;; `bounded': go back to the last non-empty line.
+ (while (dired-between-files)
+ (funcall jumpfun (- moving-down)))
+ ;; Encountered a boundary, so let's stop movement.
+ (setq arg moving-down)))
+ (unless (dired-between-files)
+ ;; Has moved to a non-empty line. This movement does
+ ;; make sense.
+ (cl-decf arg moving-down))
+ (setq old-position (point)))))
+
(defun dired-previous-line (arg)
- "Move up lines then position at filename.
-Optional prefix ARG says how many lines to move; default is one line."
- (interactive "^p")
+ "Move up ARG lines, then position at filename.
+The argument ARG (interactively, prefix argument) says how many lines
+to move; the default is one line.
+
+Whether to skip empty lines and how to move from first line
+is controlled by `dired-movement-style'."
+ (interactive "^p" dired-mode)
(dired-next-line (- (or arg 1))))
-(defun dired-next-dirline (arg &optional opoint)
+(defun dired--trivial-next-dirline (arg &optional opoint)
"Goto ARGth next directory file line."
- (interactive "p")
(or opoint (setq opoint (point)))
(if (if (> arg 0)
(re-search-forward dired-re-dir nil t arg)
@@ -2695,11 +2867,25 @@ Optional prefix ARG says how many lines to move; default is one line."
(re-search-backward dired-re-dir nil t (- arg)))
(dired-move-to-filename) ; user may type `i' or `f'
(goto-char opoint)
- (error "No more subdirectories")))
+ (unless dired-movement-style
+ (error "No more subdirectories"))))
+
+(defun dired-next-dirline (arg &optional _opoint)
+ "Goto ARGth next directory file line.
+
+Whether to skip empty lines and how to move from last line
+is controlled by `dired-movement-style'."
+ (interactive "p" dired-mode)
+ (if dired-movement-style
+ (dired--move-to-next-line arg #'dired--trivial-next-dirline)
+ (dired--trivial-next-dirline arg)))
(defun dired-prev-dirline (arg)
- "Goto ARGth previous directory file line."
- (interactive "p")
+ "Goto ARGth previous directory file line.
+
+Whether to skip empty lines and how to move from last line
+is controlled by `dired-movement-style'."
+ (interactive "p" dired-mode)
(dired-next-dirline (- arg)))
(defun dired-up-directory (&optional other-window)
@@ -2708,7 +2894,7 @@ Find the parent directory either in this buffer or another buffer.
Creates a buffer if necessary.
If OTHER-WINDOW (the optional prefix arg), display the parent
directory in another window."
- (interactive "P")
+ (interactive "P" dired-mode)
(let* ((dir (dired-current-directory))
(up (file-name-directory (directory-file-name dir))))
(or (dired-goto-file (directory-file-name dir))
@@ -2723,7 +2909,7 @@ directory in another window."
(defun dired-get-file-for-visit ()
"Get the current line's file name, with an error if file does not exist."
- (interactive)
+ (interactive nil dired-mode)
;; We pass t for second arg so that we don't get error for `.' and `..'.
(let ((raw (dired-get-filename nil t))
file-name)
@@ -2743,7 +2929,7 @@ directory in another window."
#'dired-find-file "23.2")
(defun dired-find-file ()
"In Dired, visit the file or directory named on this line."
- (interactive)
+ (interactive nil dired-mode)
(dired--find-possibly-alternative-file (dired-get-file-for-visit)))
(defun dired--find-possibly-alternative-file (file)
@@ -2775,7 +2961,7 @@ directory in another window."
(defun dired-find-alternate-file ()
"In Dired, visit file or directory on current line via `find-alternate-file'.
This kills the Dired buffer, then visits the current line's file or directory."
- (interactive)
+ (interactive nil dired-mode)
(set-buffer-modified-p nil)
(find-alternate-file (dired-get-file-for-visit)))
;; Don't override the setting from .emacs.
@@ -2789,7 +2975,7 @@ omitted or nil, these arguments default to `find-file' and `dired',
respectively. If `dired-kill-when-opening-new-dired-buffer' is
non-nil, FIND-DIR-FUNC defaults to `find-alternate-file' instead,
so that the original Dired buffer is not kept."
- (interactive "e")
+ (interactive "e" dired-mode)
(or find-file-func (setq find-file-func 'find-file))
(let (window pos file)
(save-excursion
@@ -2817,19 +3003,19 @@ so that the original Dired buffer is not kept."
(defun dired-mouse-find-file-other-window (event)
"In Dired, visit the file or directory name you click on in another window."
- (interactive "e")
+ (interactive "e" dired-mode)
(dired-mouse-find-file event 'find-file-other-window 'dired-other-window))
(defun dired-mouse-find-file-other-frame (event)
"In Dired, visit the file or directory name you click on in another frame."
- (interactive "e")
+ (interactive "e" dired-mode)
(dired-mouse-find-file event 'find-file-other-frame 'dired-other-frame))
(defun dired-view-file ()
"In Dired, examine a file in view mode, returning to Dired when done.
When file is a directory, show it in this buffer if it is inserted.
Otherwise, display it in another buffer."
- (interactive)
+ (interactive nil dired-mode)
(let ((file (dired-get-file-for-visit)))
(if (file-directory-p file)
(or (and (cdr dired-subdir-alist)
@@ -2839,12 +3025,12 @@ Otherwise, display it in another buffer."
(defun dired-find-file-other-window ()
"In Dired, visit this file or directory in another window."
- (interactive)
+ (interactive nil dired-mode)
(dired--find-file #'find-file-other-window (dired-get-file-for-visit)))
(defun dired-display-file ()
"In Dired, display this file or directory in another window."
- (interactive)
+ (interactive nil dired-mode)
(display-buffer (find-file-noselect (dired-get-file-for-visit))
t))
@@ -3006,7 +3192,7 @@ permissions are hidden from view.
See options: `dired-hide-details-hide-symlink-targets' and
`dired-hide-details-hide-information-lines'."
:group 'dired
- (unless (derived-mode-p 'dired-mode 'wdired-mode)
+ (unless (derived-mode-p '(dired-mode wdired-mode))
(error "Not a Dired buffer"))
(dired-hide-details-update-invisibility-spec)
(if dired-hide-details-mode
@@ -3038,6 +3224,15 @@ See options: `dired-hide-details-hide-symlink-targets' and
;;; Functions to hide/unhide text
+(defun dired-filename-update-invisibility-spec ()
+ "Update `buffer-invisibility-spec' for filenames.
+Specifically, the filename invisibility spec is added in Dired
+buffers and removed in WDired buffers."
+ (funcall (if (derived-mode-p 'dired-mode)
+ 'add-to-invisibility-spec
+ 'remove-from-invisibility-spec)
+ '(dired-filename-hide . t)))
+
(defun dired--find-hidden-pos (start end)
(text-property-any start end 'invisible 'dired))
@@ -3181,7 +3376,7 @@ If on a subdir headerline, use absolute subdirname instead;
prefix arg and marked files are ignored in this case.
You can then feed the file name(s) to other commands with \\[yank]."
- (interactive "P")
+ (interactive "P" dired-mode)
(let* ((files
(or (ensure-list (dired-get-subdir))
(if arg
@@ -3367,7 +3562,7 @@ As a side effect, killed dired buffers for DIR are removed from
;; Use 0 arg to go to this directory's header line.
;; NO-SKIP prevents moving to end of header line, returning whatever
;; position was found in dired-subdir-alist.
- (interactive "p")
+ (interactive "p" dired-mode)
(let ((this-dir (dired-current-directory))
pos index)
;; nth with negative arg does not return nil but the first element
@@ -3388,7 +3583,7 @@ As a side effect, killed dired buffers for DIR are removed from
Returns the new value of the alist.
If optional arg SWITCHES is non-nil, use its value
instead of `dired-actual-switches'."
- (interactive)
+ (interactive nil dired-mode)
(dired-clear-alist)
(save-excursion
(let* ((count 0)
@@ -3492,7 +3687,8 @@ instead of `dired-actual-switches'."
(list (expand-file-name
(read-file-name "Goto file: "
(dired-current-directory))))
- (push-mark)))
+ (push-mark))
+ dired-mode)
(unless (file-name-absolute-p file)
(error "File name `%s' is not absolute" file))
(setq file (directory-file-name file)) ; does no harm if not a directory
@@ -3691,7 +3887,7 @@ If NOMESSAGE is non-nil, we don't display any message
if there are no flagged files.
`dired-recursive-deletes' controls whether deletion of
non-empty directories is allowed."
- (interactive)
+ (interactive nil dired-mode)
(let* ((dired-marker-char dired-del-marker)
(regexp (dired-marker-regexp))
case-fold-search markers)
@@ -3721,7 +3917,7 @@ non-empty directories is allowed."
non-empty directories is allowed."
;; This is more consistent with the file marking feature than
;; dired-do-flagged-delete.
- (interactive "P")
+ (interactive "P" dired-mode)
(let (markers)
(dired-internal-do-deletions
(nreverse
@@ -4025,7 +4221,7 @@ marked file is found after this line.
Optional argument OPOINT specifies the buffer position to
return to if no ARGth marked file is found; it defaults to
the position where this command was invoked."
- (interactive "p\np")
+ (interactive "p\np" dired-mode)
(or opoint (setq opoint (point)));; return to where interactively started
(if (if (> arg 0)
(re-search-forward dired-re-mark nil t arg)
@@ -4046,7 +4242,7 @@ ARG is the numeric prefix argument and defaults to 1.
If WRAP is non-nil, which happens interactively, wrap around
to the end of the buffer and search backwards from there, if
no ARGth marked file is found before this line."
- (interactive "p\np")
+ (interactive "p\np" dired-mode)
(dired-next-marked-file (- arg) wrap))
(defun dired-file-marker (file)
@@ -4085,7 +4281,7 @@ If on a subdir headerline, mark all its files except `.' and `..'.
Use \\[dired-unmark-all-files] to remove all marks
and \\[dired-unmark] on a subdir to remove the marks in
this subdir."
- (interactive (list current-prefix-arg t))
+ (interactive (list current-prefix-arg t) dired-mode)
(cond
;; Mark files in the active region.
((and interactive dired-mark-region
@@ -4124,7 +4320,7 @@ Otherwise, with a prefix arg, unmark files on the next ARG lines.
If looking at a subdir, unmark all its files except `.' and `..'.
If the region is active in Transient Mark mode, unmark all files
in the active region."
- (interactive (list current-prefix-arg t))
+ (interactive (list current-prefix-arg t) dired-mode)
(let ((dired-marker-char ?\s))
(dired-mark arg interactive)))
@@ -4136,7 +4332,7 @@ Otherwise, with a prefix arg, flag files on the next ARG lines.
If on a subdir headerline, flag all its files except `.' and `..'.
If the region is active in Transient Mark mode, flag all files
in the active region."
- (interactive (list current-prefix-arg t))
+ (interactive (list current-prefix-arg t) dired-mode)
(let ((dired-marker-char dired-del-marker))
(dired-mark arg interactive)))
@@ -4146,7 +4342,7 @@ Optional prefix ARG says how many lines to unmark/unflag; default
is one line.
If the region is active in Transient Mark mode, unmark all files
in the active region."
- (interactive "p")
+ (interactive "p" dired-mode)
(dired-unmark (- arg) t))
(defun dired-toggle-marks ()
@@ -4158,7 +4354,7 @@ As always, hidden subdirs are not affected.
In Transient Mark mode, if the mark is active, operate on the contents
of the region if `dired-mark-region' is non-nil. Otherwise, operate
on the whole buffer."
- (interactive)
+ (interactive nil dired-mode)
(save-excursion
(let ((inhibit-read-only t)
(beg (dired-mark--region-beginning))
@@ -4209,7 +4405,8 @@ object files--just `.o' will mark more than you might think."
(dired-get-filename nil t) t))
"\\'"))))
'dired-regexp-history)
- (if current-prefix-arg ?\s)))
+ (if current-prefix-arg ?\s))
+ dired-mode)
(let ((dired-marker-char (or marker-char dired-marker-char)))
(dired-mark-if
(and (not (looking-at-p dired-re-dot))
@@ -4220,7 +4417,7 @@ object files--just `.o' will mark more than you might think."
(defun dired-number-of-marked-files ()
"Display the number and total size of the marked files."
- (interactive)
+ (interactive nil dired-mode)
(let* ((files (dired-get-marked-files nil nil nil t))
(nmarked
(cond ((null (cdr files))
@@ -4259,7 +4456,8 @@ since it was last visited."
(list (read-regexp (concat (if current-prefix-arg "Unmark" "Mark")
" files containing (regexp): ")
nil 'dired-regexp-history)
- (if current-prefix-arg ?\s)))
+ (if current-prefix-arg ?\s))
+ dired-mode)
(let ((dired-marker-char (or marker-char dired-marker-char)))
(dired-mark-if
(and (not (looking-at-p dired-re-dot))
@@ -4288,7 +4486,8 @@ The match is against the non-directory part of the filename. Use `^'
and `$' to anchor matches. Exclude subdirs by hiding them.
`.' and `..' are never flagged."
(interactive (list (read-regexp "Flag for deletion (regexp): "
- nil 'dired-regexp-history)))
+ nil 'dired-regexp-history))
+ dired-mode)
(dired-mark-files-regexp regexp dired-del-marker))
(defun dired-mark-symlinks (unflag-p)
@@ -4296,7 +4495,7 @@ The match is against the non-directory part of the filename. Use `^'
With prefix argument, unmark or unflag all those files.
If the region is active in Transient Mark mode, mark files
only in the active region if `dired-mark-region' is non-nil."
- (interactive "P")
+ (interactive "P" dired-mode)
(let ((dired-marker-char (if unflag-p ?\s dired-marker-char)))
(dired-mark-if (looking-at-p dired-re-sym) "symbolic link")))
@@ -4305,7 +4504,7 @@ only in the active region if `dired-mark-region' is non-nil."
With prefix argument, unmark or unflag all those files.
If the region is active in Transient Mark mode, mark files
only in the active region if `dired-mark-region' is non-nil."
- (interactive "P")
+ (interactive "P" dired-mode)
(let ((dired-marker-char (if unflag-p ?\s dired-marker-char)))
(dired-mark-if (and (looking-at-p dired-re-dir)
(not (looking-at-p dired-re-dot)))
@@ -4316,7 +4515,7 @@ only in the active region if `dired-mark-region' is non-nil."
With prefix argument, unmark or unflag all those files.
If the region is active in Transient Mark mode, mark files
only in the active region if `dired-mark-region' is non-nil."
- (interactive "P")
+ (interactive "P" dired-mode)
(let ((dired-marker-char (if unflag-p ?\s dired-marker-char)))
(dired-mark-if (looking-at-p dired-re-exe) "executable file")))
@@ -4328,7 +4527,7 @@ only in the active region if `dired-mark-region' is non-nil."
A prefix argument says to unmark or unflag those files instead.
If the region is active in Transient Mark mode, flag files
only in the active region if `dired-mark-region' is non-nil."
- (interactive "P")
+ (interactive "P" dired-mode)
(let ((dired-marker-char (if unflag-p ?\s dired-del-marker)))
(dired-mark-if
;; It is less than general to check for # here,
@@ -4362,7 +4561,7 @@ only in the active region if `dired-mark-region' is non-nil."
(defun dired-flag-garbage-files ()
"Flag for deletion all files that match `dired-garbage-files-regexp'."
- (interactive)
+ (interactive nil dired-mode)
(dired-flag-files-regexp dired-garbage-files-regexp))
(defun dired-flag-backup-files (&optional unflag-p)
@@ -4370,7 +4569,7 @@ only in the active region if `dired-mark-region' is non-nil."
With prefix argument, unmark or unflag these files.
If the region is active in Transient Mark mode, flag files
only in the active region if `dired-mark-region' is non-nil."
- (interactive "P")
+ (interactive "P" dired-mode)
(let ((dired-marker-char (if unflag-p ?\s dired-del-marker)))
(dired-mark-if
;; Don't call backup-file-name-p unless the last character looks like
@@ -4398,7 +4597,8 @@ OLD and NEW are both characters used to mark files."
(old (progn (message "Change (old mark): ") (read-char)))
(new (progn (message "Change %c marks to (new mark): " old)
(read-char))))
- (list old new)))
+ (list old new))
+ dired-mode)
(dolist (c (list new old))
(if (or (not (char-displayable-p c))
(eq c ?\r))
@@ -4417,7 +4617,7 @@ OLD and NEW are both characters used to mark files."
(defun dired-unmark-all-marks ()
"Remove all marks from all files in the Dired buffer."
- (interactive)
+ (interactive nil dired-mode)
(dired-unmark-all-files ?\r))
;; Bound in dired-unmark-all-files
@@ -4429,7 +4629,7 @@ After this command, type the mark character to remove,
or type RET to remove all marks.
With prefix arg, query for each marked file.
Type \\[help-command] at that time for help."
- (interactive "cRemove marks (RET means all): \nP")
+ (interactive "cRemove marks (RET means all): \nP" dired-mode)
(save-excursion
(let* ((count 0)
(inhibit-read-only t) case-fold-search
@@ -4606,7 +4806,7 @@ Possible values:
(defun dired-sort-toggle-or-edit (&optional arg)
"Toggle sorting by date, and refresh the Dired buffer.
With a prefix argument, edit the current listing switches instead."
- (interactive "P")
+ (interactive "P" dired-mode)
(when dired-sort-inhibit
(error "Cannot sort this Dired buffer"))
(if arg
@@ -4811,22 +5011,31 @@ Ask means pop up a menu for the user to select one of copy, move or link."
(eval-when-compile (require 'desktop))
(declare-function desktop-file-name "desktop" (filename dirname))
+(defun dired-desktop-save-p ()
+ "Should `dired-directory' be desktop saved?"
+ (or (null desktop-files-not-to-save)
+ (and (stringp desktop-files-not-to-save)
+ (if (consp dired-directory)
+ (not (string-match-p desktop-files-not-to-save (car dired-directory)))
+ (not (string-match-p desktop-files-not-to-save dired-directory))))))
+
(defun dired-desktop-buffer-misc-data (dirname)
"Auxiliary information to be saved in desktop file."
- (cons
- ;; Value of `dired-directory'.
- (if (consp dired-directory)
- ;; Directory name followed by list of files.
- (cons (desktop-file-name (car dired-directory) dirname)
- (cdr dired-directory))
- ;; Directory name, optionally with shell wildcard.
- (desktop-file-name dired-directory dirname))
- ;; Subdirectories in `dired-subdir-alist'.
- (cdr
- (nreverse
- (mapcar
- (lambda (f) (desktop-file-name (car f) dirname))
- dired-subdir-alist)))))
+ (when (dired-desktop-save-p)
+ (cons
+ ;; Value of `dired-directory'.
+ (if (consp dired-directory)
+ ;; Directory name followed by list of files.
+ (cons (desktop-file-name (car dired-directory) dirname)
+ (cdr dired-directory))
+ ;; Directory name, optionally with shell wildcard.
+ (desktop-file-name dired-directory dirname))
+ ;; Subdirectories in `dired-subdir-alist'.
+ (cdr
+ (nreverse
+ (mapcar
+ (lambda (f) (desktop-file-name (car f) dirname))
+ dired-subdir-alist))))))
(defun dired-restore-desktop-buffer (_file-name
_buffer-name
@@ -4932,6 +5141,7 @@ Interactively with prefix argument, read FILE-NAME."
;;; Miscellaneous commands
(declare-function Man-getpage-in-background "man" (topic))
+(defvar Man-support-remote-systems) ; from man.el
(defvar manual-program) ; from man.el
(defun dired-do-man ()
@@ -4939,10 +5149,11 @@ Interactively with prefix argument, read FILE-NAME."
(interactive nil dired-mode)
(require 'man)
(let* ((file (dired-get-file-for-visit))
+ (Man-support-remote-systems (file-remote-p file))
(manual-program (string-replace "*" "%s"
(dired-guess-shell-command
"Man command: " (list file)))))
- (Man-getpage-in-background file)))
+ (Man-getpage-in-background (file-local-name file))))
(defun dired-do-info ()
"In Dired, run `info' on this file."
@@ -4966,7 +5177,7 @@ Interactively with prefix argument, read FILE-NAME."
(defun dired-mark-for-click (event)
"Mark or unmark the file underneath the mouse click at EVENT.
See `dired-click-to-select-mode' for more details."
- (interactive "e")
+ (interactive "e" dired-mode)
(let ((posn (event-start event))
(inhibit-read-only t))
(with-selected-window (posn-window posn)
@@ -4989,7 +5200,7 @@ See `dired-click-to-select-mode' for more details."
"Enable `dired-click-to-select-mode' and mark the file under EVENT.
If there is no file under EVENT, call `touch-screen-hold' with
EVENT instead."
- (interactive "e")
+ (interactive "e" dired-mode)
(let* ((posn (event-start event))
(window (posn-window posn))
(point (posn-point posn)))
@@ -5018,7 +5229,7 @@ Dired operation (command whose name starts with `dired-do')
completes."
:group 'dired
:lighter " Click-To-Select"
- (unless (derived-mode-p 'dired-mode 'wdired-mode)
+ (unless (derived-mode-p '(dired-mode wdired-mode))
(error "Not a Dired buffer"))
(if dired-click-to-select-mode
(setq-local tool-bar-map
diff --git a/lisp/dirtrack.el b/lisp/dirtrack.el
index b171caa1333..07e176b8eea 100644
--- a/lisp/dirtrack.el
+++ b/lisp/dirtrack.el
@@ -1,6 +1,6 @@
;;; dirtrack.el --- Directory Tracking by watching the prompt -*- lexical-binding: t -*-
-;; Copyright (C) 1996, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996, 2001-2024 Free Software Foundation, Inc.
;; Author: Peter Breton <pbreton@cs.umb.edu>
;; Created: Sun Nov 17 1996
diff --git a/lisp/disp-table.el b/lisp/disp-table.el
index e8eef0010ec..50428d911a3 100644
--- a/lisp/disp-table.el
+++ b/lisp/disp-table.el
@@ -1,6 +1,6 @@
;;; disp-table.el --- functions for dealing with char tables -*- lexical-binding: t; -*-
-;; Copyright (C) 1987, 1994-1995, 1999, 2001-2023 Free Software
+;; Copyright (C) 1987, 1994-1995, 1999, 2001-2024 Free Software
;; Foundation, Inc.
;; Author: Erik Naggum <erik@naggum.no>
diff --git a/lisp/display-fill-column-indicator.el b/lisp/display-fill-column-indicator.el
index 45bdca2f5a5..ef0f2d4981c 100644
--- a/lisp/display-fill-column-indicator.el
+++ b/lisp/display-fill-column-indicator.el
@@ -1,6 +1,6 @@
;;; display-fill-column-indicator.el --- interface for display-fill-column-indicator -*- lexical-binding: t -*-
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
;; Maintainer: emacs-devel@gnu.org
;; Keywords: convenience
diff --git a/lisp/display-line-numbers.el b/lisp/display-line-numbers.el
index 4f87ffd0e22..c6ee588484c 100644
--- a/lisp/display-line-numbers.el
+++ b/lisp/display-line-numbers.el
@@ -1,6 +1,6 @@
;;; display-line-numbers.el --- interface for display-line-numbers -*- lexical-binding: t -*-
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
;; Maintainer: emacs-devel@gnu.org
;; Keywords: convenience
diff --git a/lisp/dnd.el b/lisp/dnd.el
index 67907ec403e..22cb18359a3 100644
--- a/lisp/dnd.el
+++ b/lisp/dnd.el
@@ -1,6 +1,6 @@
;;; dnd.el --- drag and drop support -*- lexical-binding: t; -*-
-;; Copyright (C) 2005-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2005-2024 Free Software Foundation, Inc.
;; Author: Jan Djärv <jan.h.d@swipnet.se>
;; Maintainer: emacs-devel@gnu.org
@@ -42,23 +42,25 @@
;;;###autoload
(defcustom dnd-protocol-alist
- `((,(purecopy "^file:///") . dnd-open-local-file) ; XDND format.
- (,(purecopy "^file://") . dnd-open-file) ; URL with host
- (,(purecopy "^file:") . dnd-open-local-file) ; Old KDE, Motif, Sun
- (,(purecopy "^\\(https?\\|ftp\\|file\\|nfs\\)://") . dnd-open-file))
-
+ `((,(purecopy "^file:///") . dnd-open-local-file) ; XDND format.
+ (,(purecopy "^file://[^/]") . dnd-open-file) ; URL with host
+ (,(purecopy "^file:/[^/]") . dnd-open-local-file) ; Old KDE, Motif, Sun
+ (,(purecopy "^file:[^/]") . dnd-open-local-file) ; MS-Windows
+ (,(purecopy "^\\(https?\\|ftp\\|nfs\\)://") . dnd-open-file))
"The functions to call for different protocols when a drop is made.
-This variable is used by `dnd-handle-one-url' and `dnd-handle-file-name'.
+This variable is used by `dnd-handle-multiple-urls'.
The list contains of (REGEXP . FUNCTION) pairs.
The functions shall take two arguments, URL, which is the URL dropped and
ACTION which is the action to be performed for the drop (move, copy, link,
private or ask).
+If a function's `dnd-multiple-handler' property is set, it is provided
+a list of each URI dropped instead.
If no match is found here, and the value of `browse-url-browser-function'
is a pair of (REGEXP . FUNCTION), those regexps are tried for a match.
If no match is found, the URL is inserted as text by calling `dnd-insert-text'.
The function shall return the action done (move, copy, link or private)
if some action was made, or nil if the URL is ignored."
- :version "22.1"
+ :version "30.1"
:type '(repeat (cons (regexp) (function)))
:group 'dnd)
@@ -159,7 +161,10 @@ If no match is found here, `browse-url-handlers' and
`browse-url-default-handlers' are searched for a match.
If no match is found, just call `dnd-insert-text'. WINDOW is
where the drop happened, ACTION is the action for the drop, URL
-is what has been dropped. Returns ACTION."
+is what has been dropped. Returns ACTION.
+
+This function has been obsolete since Emacs 30.1; it has been
+supplanted by `dnd-handle-multiple-urls'."
(let (ret)
(or
(catch 'done
@@ -180,6 +185,91 @@ is what has been dropped. Returns ACTION."
(setq ret 'private)))
ret))
+(make-obsolete 'dnd-handle-one-url 'dnd-handle-multiple-urls "30.1")
+
+(defun dnd-handle-multiple-urls (window urls action)
+ "Select a handler for, then open, each element of URLS.
+The argument ACTION is the action which must be taken, much as
+that to `dnd-begin-file-drag'.
+
+Assign and give each URL to one of the \"DND handler\" functions
+listed in the variable `dnd-protocol-alist'. When multiple
+handlers matching the same subset of URLs exist, give precedence
+to the handler assigned the greatest number of URLs.
+
+If a handler is a symbol with the property
+`dnd-multiple-handler', call it with ACTION and a list of every
+URL it is assigned. Otherwise, call it once for each URL
+assigned with ACTION and the URL in question.
+
+Subsequently open URLs that don't match any handlers opened with
+any handler selected by `browse-url-select-handler', and failing
+even that, insert them with `dnd-insert-text'.
+
+Return a symbol designating the actions taken by each DND handler
+called. If all DND handlers called return the same symbol,
+return that symbol; otherwise, or if no DND handlers are called,
+return `private'.
+
+Do not rely on the contents of URLS after calling this function,
+for it will be modified."
+ (let ((list nil) (return-value nil))
+ (with-selected-window window
+ (dolist (handler dnd-protocol-alist)
+ (let ((pattern (car handler))
+ (handler (cdr handler)))
+ (dolist (uri urls)
+ (when (string-match pattern uri)
+ (let ((cell (or (cdr (assq handler list))
+ (let ((cell (cons handler nil)))
+ (push cell list)
+ cell))))
+ (unless (memq uri cell)
+ (setcdr cell (cons uri (cdr cell)))))))))
+ (setq list (nreverse list))
+ ;; While unassessed handlers still exist...
+ (while list
+ ;; Sort list by the number of URLs assigned to each handler.
+ (setq list (sort list (lambda (first second)
+ (> (length (cdr first))
+ (length (cdr second))))))
+ ;; Call the handler in its car before removing each URL from
+ ;; URLs.
+ (let ((handler (caar list))
+ (entry-urls (cdar list)))
+ (setq list (cdr list))
+ (when entry-urls
+ (if (and (symbolp handler)
+ (get handler 'dnd-multiple-handler))
+ (progn
+ (let ((value (funcall handler entry-urls action)))
+ (if (or (not return-value)
+ (eq return-value value))
+ (setq return-value value)
+ (setq return-value 'private)))
+ (dolist (url entry-urls)
+ (setq urls (delq url urls))
+ ;; And each handler-URL list after this.
+ (dolist (item list)
+ (setcdr item (delq url (cdr item))))))
+ (dolist (url entry-urls)
+ (let ((value (funcall handler url action)))
+ (if (or (not return-value) (eq return-value value))
+ (setq return-value value)
+ (setq return-value 'private)))
+ (setq urls (delq url urls))
+ ;; And each handler-URL list after this.
+ (dolist (item list)
+ (setcdr item (delq url (cdr item)))))))))
+ ;; URLS should now incorporate only those which haven't been
+ ;; assigned their own handlers.
+ (dolist (leftover urls)
+ (setq return-value 'private)
+ (if-let ((handler (browse-url-select-handler leftover
+ 'internal)))
+ (funcall handler leftover action)
+ (dnd-insert-text window action leftover)))
+ (or return-value 'private))))
(defun dnd-get-local-file-uri (uri)
"Return an uri converted to file:/// syntax if uri is a local file.
@@ -201,6 +291,11 @@ Return nil if URI is not a local file."
(string-equal sysname-no-dot hostname)))
(concat "file://" (substring uri (+ 7 (length hostname))))))))
+(defvar dnd-unescape-file-uris t
+ "Whether to unescape file: URIs before they are opened.
+Bind this to nil when providing `dnd-get-local-file-name' with a
+file name that may incorporate URI escape sequences.")
+
(defun dnd--unescape-uri (uri)
;; Merge with corresponding code in URL library.
(replace-regexp-in-string
@@ -226,7 +321,10 @@ Return nil if URI is not a local file."
'utf-8
(or file-name-coding-system
default-file-name-coding-system))))
- (and f (setq f (decode-coding-string (dnd--unescape-uri f) coding)))
+ (and f (setq f (decode-coding-string
+ (if dnd-unescape-file-uris
+ (dnd--unescape-uri f) f)
+ coding)))
(when (and f must-exist (not (file-readable-p f)))
(setq f nil))
f))
diff --git a/lisp/doc-view.el b/lisp/doc-view.el
index e25e63a97ee..c4b384c35c6 100644
--- a/lisp/doc-view.el
+++ b/lisp/doc-view.el
@@ -1,6 +1,6 @@
;;; doc-view.el --- Document viewer for Emacs -*- lexical-binding: t -*-
-;; Copyright (C) 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2024 Free Software Foundation, Inc.
;;
;; Author: Tassilo Horn <tsdh@gnu.org>
;; Keywords: files, pdf, ps, dvi, djvu, epub, cbz, fb2, xps, openxps
@@ -204,10 +204,10 @@ are available (see Info node `(emacs)Document View')."
#'doc-view-pdf->png-converter-ghostscript)
"Function to call to convert a PDF file into a PNG file."
:type '(radio
- (function-item doc-view-pdf->png-converter-ghostscript
- :doc "Use ghostscript")
- (function-item doc-view-pdf->png-converter-mupdf
- :doc "Use mupdf")
+ (function-item :doc "Use Ghostscript"
+ doc-view-pdf->png-converter-ghostscript)
+ (function-item :doc "Use MuPDF"
+ doc-view-pdf->png-converter-mupdf)
function)
:version "24.4")
@@ -375,17 +375,15 @@ Needed for viewing OpenOffice.org (and MS Office) files."
:type 'file)
(defcustom doc-view-odf->pdf-converter-function
- (cond
- ((string-match "unoconv\\'" doc-view-odf->pdf-converter-program)
- #'doc-view-odf->pdf-converter-unoconv)
- ((string-match "soffice\\'" doc-view-odf->pdf-converter-program)
- #'doc-view-odf->pdf-converter-soffice))
- "Function to call to convert a ODF file into a PDF file."
+ (if (string-suffix-p "unoconv" doc-view-odf->pdf-converter-program)
+ #'doc-view-odf->pdf-converter-unoconv
+ #'doc-view-odf->pdf-converter-soffice)
+ "Function to call to convert an ODF file into a PDF file."
:type '(radio
- (function-item doc-view-odf->pdf-converter-unoconv
- :doc "Use unoconv")
- (function-item doc-view-odf->pdf-converter-soffice
- :doc "Use LibreOffice")
+ (function-item :doc "Use LibreOffice"
+ doc-view-odf->pdf-converter-soffice)
+ (function-item :doc "Use unoconv"
+ doc-view-odf->pdf-converter-unoconv)
function)
:version "24.4")
@@ -663,7 +661,9 @@ Typically \"page-%s.png\".")
'("DocView (edit)"
("Toggle edit/display"
["Edit document" (lambda ()) ; ignore but show no keybinding
- :style radio :selected (eq major-mode 'doc-view--text-view-mode)]
+ ;; This is always selected since its menu is singular to the
+ ;; display minor mode.
+ :style radio :selected t]
["Display document" doc-view-toggle-display
:style radio :selected (eq major-mode 'doc-view-mode)])
["Exit DocView Mode" doc-view-minor-mode]))
@@ -698,12 +698,12 @@ Typically \"page-%s.png\".")
(tool-bar-local-item-from-menu 'doc-view-previous-page "last-page"
map doc-view-mode-map :vert-only t
:enable '(> (doc-view-current-page) 1)
- :help "Move to the next page.")
+ :help "Move to the previous page.")
(tool-bar-local-item-from-menu 'doc-view-next-page "next-page"
map doc-view-mode-map :vert-only t
:enable '(< (doc-view-current-page)
(doc-view-last-page-number))
- :help "Move to the last page.")
+ :help "Move to the next page.")
map)
"Like the default `tool-bar-map', but with additions for DocView.")
@@ -940,8 +940,7 @@ Document types are symbols like `dvi', `ps', `pdf', `epub',
(and doc-view-pdfdraw-program
(executable-find doc-view-pdfdraw-program)))))
((eq type 'odf)
- (and doc-view-odf->pdf-converter-program
- (executable-find doc-view-odf->pdf-converter-program)
+ (and (executable-find doc-view-odf->pdf-converter-program)
(doc-view-mode-p 'pdf)))
((eq type 'djvu)
(executable-find "ddjvu"))
@@ -1283,7 +1282,8 @@ The test is performed using `doc-view-pdfdraw-program'."
(expand-file-name
doc-view-epub-user-stylesheet)))))))
(doc-view-start-process
- "pdf->png" doc-view-pdfdraw-program
+ (concat "pdf->" (symbol-name doc-view--image-type))
+ doc-view-pdfdraw-program
`(,@(doc-view-pdfdraw-program-subcommand)
,@options
,pdf
@@ -2133,7 +2133,7 @@ GOTO-PAGE-FN other than `doc-view-goto-page'."
;; zip-archives, so that this same association is used for
;; cbz files. This is fine, as cbz files should be handled
;; like epub anyway.
- ((looking-at "PK") '(epub odf))))))
+ ((looking-at "PK") '(epub odf cbz))))))
(setq-local
doc-view-doc-type
(car (or (nreverse (seq-intersection name-types content-types #'eq))
@@ -2238,8 +2238,15 @@ toggle between displaying the document or editing it as text.
;; supposed to return nil for things like local files accessed
;; via `su' or via file://...
((let ((file-name-handler-alist nil))
- (not (and buffer-file-name
- (file-readable-p buffer-file-name))))
+ (or (not (and buffer-file-name
+ (file-readable-p buffer-file-name)))
+ ;; If the system is Android and the file name
+ ;; begins with /content or /assets, it's not
+ ;; readable by local processes.
+ (and (eq system-type 'android)
+ (string-match-p "/\\(content\\|assets\\)[/$]"
+ (expand-file-name
+ buffer-file-name)))))
;; FIXME: there's a risk of name conflicts here.
(expand-file-name
(if buffer-file-name
diff --git a/lisp/dom.el b/lisp/dom.el
index 3066673954a..f7043ba8252 100644
--- a/lisp/dom.el
+++ b/lisp/dom.el
@@ -1,6 +1,6 @@
;;; dom.el --- XML/HTML (etc.) DOM manipulation and searching functions -*- lexical-binding: t -*-
-;; Copyright (C) 2014-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2014-2024 Free Software Foundation, Inc.
;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
;; Keywords: xml, html
diff --git a/lisp/dos-fns.el b/lisp/dos-fns.el
index 42ba646a4fb..987706920c4 100644
--- a/lisp/dos-fns.el
+++ b/lisp/dos-fns.el
@@ -1,6 +1,6 @@
;;; dos-fns.el --- MS-Dos specific functions -*- lexical-binding: t; -*-
-;; Copyright (C) 1991, 1993, 1995-1996, 2001-2023 Free Software
+;; Copyright (C) 1991, 1993, 1995-1996, 2001-2024 Free Software
;; Foundation, Inc.
;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/dos-vars.el b/lisp/dos-vars.el
index f2493ac573f..1e06911836a 100644
--- a/lisp/dos-vars.el
+++ b/lisp/dos-vars.el
@@ -1,6 +1,6 @@
;;; dos-vars.el --- MS-Dos specific user options -*- lexical-binding:t -*-
-;; Copyright (C) 1998, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998, 2001-2024 Free Software Foundation, Inc.
;; Maintainer: emacs-devel@gnu.org
;; Keywords: internal
diff --git a/lisp/dos-w32.el b/lisp/dos-w32.el
index 1db5419fc40..4302b66c4a0 100644
--- a/lisp/dos-w32.el
+++ b/lisp/dos-w32.el
@@ -1,6 +1,6 @@
;;; dos-w32.el --- Functions shared among MS-DOS and W32 (NT/95) platforms -*- lexical-binding: t; -*-
-;; Copyright (C) 1996, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996, 2001-2024 Free Software Foundation, Inc.
;; Maintainer: Geoff Voelker <voelker@cs.washington.edu>
;; Keywords: internal
diff --git a/lisp/double.el b/lisp/double.el
index 197bfd4df6f..abc7b654259 100644
--- a/lisp/double.el
+++ b/lisp/double.el
@@ -1,6 +1,6 @@
;;; double.el --- support for keyboard remapping with double clicking -*- lexical-binding: t -*-
-;; Copyright (C) 1994, 1997-1998, 2001-2023 Free Software Foundation,
+;; Copyright (C) 1994, 1997-1998, 2001-2024 Free Software Foundation,
;; Inc.
;; Author: Per Abrahamsen <abraham@dina.kvl.dk>
diff --git a/lisp/dynamic-setting.el b/lisp/dynamic-setting.el
index ebe25ab9c75..e54dce11541 100644
--- a/lisp/dynamic-setting.el
+++ b/lisp/dynamic-setting.el
@@ -1,6 +1,6 @@
;;; dynamic-setting.el --- Support dynamic changes -*- lexical-binding: t -*-
-;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
;; Author: Jan Djärv <jan.h.d@swipnet.se>
;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/ebuff-menu.el b/lisp/ebuff-menu.el
index 3038886034c..743b92578eb 100644
--- a/lisp/ebuff-menu.el
+++ b/lisp/ebuff-menu.el
@@ -1,6 +1,6 @@
;;; ebuff-menu.el --- electric-buffer-list mode -*- lexical-binding: t -*-
-;; Copyright (C) 1985-1986, 1994, 2001-2023 Free Software Foundation,
+;; Copyright (C) 1985-1986, 1994, 2001-2024 Free Software Foundation,
;; Inc.
;; Author: Richard Mlynarik <mly@ai.mit.edu>
diff --git a/lisp/echistory.el b/lisp/echistory.el
index 31af6eb6039..dfc1295e7ab 100644
--- a/lisp/echistory.el
+++ b/lisp/echistory.el
@@ -1,6 +1,6 @@
;;; echistory.el --- Electric Command History Mode -*- lexical-binding: t -*-
-;; Copyright (C) 1985, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1985, 2001-2024 Free Software Foundation, Inc.
;; Author: K. Shane Hartman
;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/ecomplete.el b/lisp/ecomplete.el
index c48c3c0650f..ee79dd5fa47 100644
--- a/lisp/ecomplete.el
+++ b/lisp/ecomplete.el
@@ -1,6 +1,6 @@
;;; ecomplete.el --- electric completion of addresses and the like -*- lexical-binding:t -*-
-;; Copyright (C) 2006-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2006-2024 Free Software Foundation, Inc.
;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
;; Keywords: mail
diff --git a/lisp/edmacro.el b/lisp/edmacro.el
index 69d20d2bad3..362ec0ecbb4 100644
--- a/lisp/edmacro.el
+++ b/lisp/edmacro.el
@@ -1,6 +1,6 @@
;;; edmacro.el --- keyboard macro editor -*- lexical-binding: t; -*-
-;; Copyright (C) 1993-1994, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1993-1994, 2001-2024 Free Software Foundation, Inc.
;; Author: Dave Gillespie <daveg@synaptics.com>
;; Keywords: abbrev
@@ -73,9 +73,19 @@ Default nil means to write characters above \\177 in octal notation."
:type 'boolean
:group 'kmacro)
+(defcustom edmacro-reverse-macro-lines nil
+ "If non-nil, `edit-kbd-macro' shows most recent line of key sequences first.
+
+This is useful when dealing with long lists of key sequences, such as
+from `kmacro-edit-lossage'."
+ :type 'boolean
+ :group 'kmacro
+ :version "30.1")
+
(defvar-keymap edmacro-mode-map
"C-c C-c" #'edmacro-finish-edit
- "C-c C-q" #'edmacro-insert-key)
+ "C-c C-q" #'edmacro-insert-key
+ "C-c C-r" #'edmacro-set-macro-to-region-lines)
(defface edmacro-label
'((default :inherit bold)
@@ -88,7 +98,10 @@ Default nil means to write characters above \\177 in octal notation."
:group 'kmacro)
(defvar edmacro-mode-font-lock-keywords
- `((,(rx bol (group (or "Command" "Key" "Macro") ":")) 0 'edmacro-label)
+ `((,(rx bol (group (or "Command" "Key"
+ (seq "Macro" (zero-or-one " (most recent line first)")))
+ ":"))
+ 0 'edmacro-label)
(,(rx bol
(group ";; Keyboard Macro Editor. Press ")
(group (*? nonl))
@@ -166,7 +179,13 @@ With a prefix argument, format the macro in a more concise way."
(let* ((oldbuf (current-buffer))
(mmac (edmacro-fix-menu-commands mac))
(fmt (edmacro-format-keys mmac 1))
- (fmtv (edmacro-format-keys mmac (not prefix)))
+ (fmtv (let ((fmtv (edmacro-format-keys mmac (not prefix))))
+ (if (not edmacro-reverse-macro-lines)
+ fmtv
+ (with-temp-buffer
+ (insert fmtv)
+ (reverse-region (point-min) (point-max))
+ (buffer-string)))))
(buf (get-buffer-create "*Edit Macro*")))
(message "Formatting keyboard macro...done")
(switch-to-buffer buf)
@@ -179,8 +198,11 @@ With a prefix argument, format the macro in a more concise way."
(setq-local edmacro-finish-hook finish-hook)
(setq-local edmacro-store-hook store-hook)
(setq-local font-lock-defaults
- '(edmacro-mode-font-lock-keywords nil nil nil nil))
+ '(edmacro-mode-font-lock-keywords nil nil ((?\" . "w"))))
(setq font-lock-multiline nil)
+ ;; Make buffer-local so that the commands still work
+ ;; even if the default value changes.
+ (make-local-variable 'edmacro-reverse-macro-lines)
(erase-buffer)
(insert (substitute-command-keys
(concat
@@ -202,7 +224,9 @@ With a prefix argument, format the macro in a more concise way."
(insert "Key: none\n")))
(when (and mac-counter mac-format)
(insert (format "Counter: %d\nFormat: \"%s\"\n" mac-counter mac-format))))
- (insert "\nMacro:\n\n")
+ (insert (format "\nMacro%s:\n\n" (if edmacro-reverse-macro-lines
+ " (most recent line first)"
+ "")))
(save-excursion
(insert fmtv "\n"))
(recenter '(4))
@@ -228,14 +252,14 @@ With a prefix argument, format the macro in a more concise way."
;;;###autoload
(defun read-kbd-macro (start &optional end)
"Read the region as a keyboard macro definition.
-The region is interpreted as spelled-out keystrokes, e.g., \"M-x abc RET\".
-See documentation for `edmacro-mode' for details.
+The region between START and END is interpreted as spelled-out keystrokes,
+e.g., \"M-x abc RET\". See documentation for `edmacro-mode' for details.
Leading/trailing \"C-x (\" and \"C-x )\" in the text are allowed and ignored.
The resulting macro is installed as the \"current\" keyboard macro.
In Lisp, may also be called with a single STRING argument in which case
the result is returned rather than being installed as the current macro.
-The result will be a string if possible, otherwise an event vector.
+The result is a vector of input events.
Second argument NEED-VECTOR means to return an event vector always."
(interactive "r")
(if (stringp start)
@@ -255,6 +279,33 @@ or nil, use a compact 80-column format."
;;; Commands for *Edit Macro* buffer.
+(defvar edmacro--skip-line-regexp
+ "[ \t]*\\($\\|;;\\|REM[ \t\n]\\)"
+ "A regexp identifying lines that should be ignored.")
+
+(defvar edmacro--command-line-regexp
+ "Command:[ \t]*\\([^ \t\n]*\\)[ \t]*$"
+ "A regexp identifying the line containing the command name.")
+
+(defvar edmacro--key-line-regexp
+ "Key:\\(.*\\)$"
+ "A regexp identifying the line containing the bound key sequence.")
+
+(defvar edmacro--counter-line-regexp
+ "Counter:[ \t]*\\([^ \t\n]*\\)[ \t]*$"
+ "A regexp identifying the line containing the counter value.")
+
+(defvar edmacro--format-line-regexp
+ "Format:[ \t]*\"\\([^\n]*\\)\"[ \t]*$"
+ "A regexp identifying the line containing the counter format.")
+
+(defvar edmacro--macro-lines-regexp
+ (rx "Macro"
+ (zero-or-one " (most recent line first)")
+ ":"
+ (zero-or-more (any " \t\n")))
+ "A regexp identifying the lines that precede the macro's contents.")
+
(defun edmacro-finish-edit ()
(interactive nil edmacro-mode)
(unless (eq major-mode 'edmacro-mode)
@@ -266,9 +317,9 @@ or nil, use a compact 80-column format."
(top (point-min)))
(goto-char top)
(let ((case-fold-search nil))
- (while (cond ((looking-at "[ \t]*\\($\\|;;\\|REM[ \t\n]\\)")
+ (while (cond ((looking-at edmacro--skip-line-regexp)
t)
- ((looking-at "Command:[ \t]*\\([^ \t\n]*\\)[ \t]*$")
+ ((looking-at edmacro--command-line-regexp)
(when edmacro-store-hook
(error "\"Command\" line not allowed in this context"))
(let ((str (match-string 1)))
@@ -283,7 +334,7 @@ or nil, use a compact 80-column format."
cmd)))
(keyboard-quit))))
t)
- ((looking-at "Key:\\(.*\\)$")
+ ((looking-at edmacro--key-line-regexp)
(when edmacro-store-hook
(error "\"Key\" line not allowed in this context"))
(let ((key (kbd (match-string 1))))
@@ -303,21 +354,21 @@ or nil, use a compact 80-column format."
(edmacro-format-keys key 1))))
(keyboard-quit))))))
t)
- ((looking-at "Counter:[ \t]*\\([^ \t\n]*\\)[ \t]*$")
+ ((looking-at edmacro--counter-line-regexp)
(when edmacro-store-hook
(error "\"Counter\" line not allowed in this context"))
(let ((str (match-string 1)))
(unless (equal str "")
(setq mac-counter (string-to-number str))))
t)
- ((looking-at "Format:[ \t]*\"\\([^\n]*\\)\"[ \t]*$")
+ ((looking-at edmacro--format-line-regexp)
(when edmacro-store-hook
(error "\"Format\" line not allowed in this context"))
(let ((str (match-string 1)))
(unless (equal str "")
(setq mac-format str)))
t)
- ((looking-at "Macro:[ \t\n]*")
+ ((looking-at edmacro--macro-lines-regexp)
(goto-char (match-end 0))
nil)
((eobp) nil)
@@ -336,7 +387,13 @@ or nil, use a compact 80-column format."
(when (buffer-name obuf)
(set-buffer obuf))
(message "Compiling keyboard macro...")
- (let ((mac (edmacro-parse-keys str)))
+ (let ((mac (edmacro-parse-keys (if edmacro-reverse-macro-lines
+ (with-temp-buffer
+ (insert str)
+ (reverse-region (point-min)
+ (point-max))
+ (buffer-string))
+ str))))
(message "Compiling keyboard macro...done")
(if store-hook
(funcall store-hook mac)
@@ -372,6 +429,36 @@ or nil, use a compact 80-column format."
(insert (edmacro-format-keys key t) "\n")
(insert (edmacro-format-keys key) " ")))
+(defun edmacro-set-macro-to-region-lines (beg end)
+ "Set the macro text to lines of text in the buffer between BEG and END.
+
+Interactively, BEG and END are the beginning and end of the
+region. If the region does not begin at the start of a line or
+if it does not end at the end of a line, the region is extended
+to include complete lines. If the region ends at the beginning
+of a line, that final line is excluded."
+ (interactive "*r" edmacro-mode)
+ ;; Use `save-excursion' to restore region if there are any errors.
+ ;; If there are no errors, update the macro text, then go to the
+ ;; beginning of the macro text.
+ (let ((final-position))
+ (save-excursion
+ (goto-char beg)
+ (unless (bolp) (setq beg (pos-bol)))
+ (goto-char end)
+ (unless (or (bolp) (eolp)) (setq end (pos-eol)))
+ (let ((text (buffer-substring beg end)))
+ (goto-char (point-min))
+ (if (not (let ((case-fold-search nil))
+ (re-search-forward edmacro--macro-lines-regexp nil t)))
+ (user-error "\"Macro:\" line not found")
+ (delete-region (match-end 0)
+ (point-max))
+ (goto-char (point-max))
+ (insert text)
+ (setq final-position (match-beginning 0)))))
+ (goto-char final-position)))
+
(defun edmacro-mode ()
"\\<edmacro-mode-map>Keyboard Macro Editing mode. Press \
\\[edmacro-finish-edit] to save and exit.
@@ -393,6 +480,10 @@ or \"none\" for no key bindings.
You can edit these lines to change the places where the new macro
is stored.
+Press \\[edmacro-set-macro-to-region-lines] to replace the text following the \"Macro:\" line
+with the text of the lines overlapping the region of text between
+point and mark. If that region ends at the beginning of a line,
+that final line is excluded.
Format of keyboard macros during editing:
@@ -672,6 +763,13 @@ This function assumes that the events can be stored in a string."
(defun edmacro-parse-keys (string &optional _need-vector)
(let ((result (kbd string)))
+ ;; Always return a vector. Stefan Monnier <monnier@iro.umontreal.ca>
+ ;; writes: "I want to eliminate the use of strings that stand for a
+ ;; sequence of events because it does nothing more than leave latent
+ ;; bugs and create confusion (between the strings used as input to
+ ;; `read-kbd-macro' and the strings that used to be output by
+ ;; `read-kbd-macro'), while increasing the complexity of the rest of
+ ;; the code which has to handle both vectors and strings."
(if (stringp result)
(seq-into result 'vector)
result)))
diff --git a/lisp/ehelp.el b/lisp/ehelp.el
index c0885340975..aeb5a7b4bb7 100644
--- a/lisp/ehelp.el
+++ b/lisp/ehelp.el
@@ -1,6 +1,6 @@
;;; ehelp.el --- bindings for electric-help mode -*- lexical-binding: t -*-
-;; Copyright (C) 1986, 1995, 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1986, 1995, 2000-2024 Free Software Foundation, Inc.
;; Author: Richard Mlynarik
;; (according to ack.texi and authors.el)
diff --git a/lisp/elec-pair.el b/lisp/elec-pair.el
index e101cbc9e6f..40618e9ef38 100644
--- a/lisp/elec-pair.el
+++ b/lisp/elec-pair.el
@@ -1,6 +1,6 @@
;;; elec-pair.el --- Automatic parenthesis pairing -*- lexical-binding:t -*-
-;; Copyright (C) 2013-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2024 Free Software Foundation, Inc.
;; Author: João Távora <joaotavora@gmail.com>
@@ -153,7 +153,7 @@ return value is considered instead."
:type '(choice (set (const :tag "Space" ?\s)
(const :tag "Tab" ?\t)
(const :tag "Newline" ?\n))
- (list character)))
+ (repeat (character :value " "))))
(defvar-local electric-pair-skip-whitespace-function
#'electric-pair--skip-whitespace
diff --git a/lisp/electric.el b/lisp/electric.el
index cef5326852c..fee0bf36d7f 100644
--- a/lisp/electric.el
+++ b/lisp/electric.el
@@ -1,6 +1,6 @@
;;; electric.el --- window maker and Command loop for `electric' modes -*- lexical-binding: t; -*-
-;; Copyright (C) 1985-1986, 1995, 2001-2023 Free Software Foundation,
+;; Copyright (C) 1985-1986, 1995, 2001-2024 Free Software Foundation,
;; Inc.
;; Author: K. Shane Hartman
diff --git a/lisp/elide-head.el b/lisp/elide-head.el
index f74c85fdfee..808bf55a05f 100644
--- a/lisp/elide-head.el
+++ b/lisp/elide-head.el
@@ -1,6 +1,6 @@
;;; elide-head.el --- hide headers in files -*- lexical-binding: t; -*-
-;; Copyright (C) 1999, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999, 2001-2024 Free Software Foundation, Inc.
;; Author: Dave Love <fx@gnu.org>
;; Keywords: outlines tools
diff --git a/lisp/emacs-lisp/advice.el b/lisp/emacs-lisp/advice.el
index 3265809f592..9489a9fd1b3 100644
--- a/lisp/emacs-lisp/advice.el
+++ b/lisp/emacs-lisp/advice.el
@@ -1,6 +1,6 @@
;;; advice.el --- An overloading mechanism for Emacs Lisp functions -*- lexical-binding: t -*-
-;; Copyright (C) 1993-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1993-2024 Free Software Foundation, Inc.
;; Author: Hans Chalupsky <hans@cs.buffalo.edu>
;; Maintainer: emacs-devel@gnu.org
@@ -2042,7 +2042,7 @@ in that CLASS."
function class name)))
(error "ad-remove-advice: `%s' is not advised" function)))
-(declare-function comp-subr-trampoline-install "comp")
+(declare-function comp-subr-trampoline-install "comp-run")
;;;###autoload
(defun ad-add-advice (function advice class position)
@@ -2067,9 +2067,6 @@ mapped to the closest extremal position).
If FUNCTION was not advised already, its advice info will be
initialized. Redefining a piece of advice whose name is part of
the cache-id will clear the cache."
- (when (and (featurep 'native-compile)
- (subr-primitive-p (symbol-function function)))
- (comp-subr-trampoline-install function))
(cond ((not (ad-is-advised function))
(ad-initialize-advice-info function)
(ad-set-advice-info-field
@@ -3131,7 +3128,7 @@ usage: (defadvice FUNCTION (CLASS NAME [POSITION] [ARGLIST] FLAG...)
[DOCSTRING] [INTERACTIVE-FORM]
BODY...)"
(declare (doc-string 3) (indent 2)
- (obsolete "use advice-add or define-advice" "30.1")
+ (obsolete "use `advice-add' or `define-advice'" "30.1")
(debug (&define name ;; thing being advised.
(name ;; class is [&or "before" "around" "after"
;; "activation" "deactivation"]
diff --git a/lisp/emacs-lisp/avl-tree.el b/lisp/emacs-lisp/avl-tree.el
index b42017d28fb..2b46a518cf5 100644
--- a/lisp/emacs-lisp/avl-tree.el
+++ b/lisp/emacs-lisp/avl-tree.el
@@ -1,6 +1,6 @@
;;; avl-tree.el --- balanced binary trees, AVL-trees -*- lexical-binding:t -*-
-;; Copyright (C) 1995, 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1995, 2007-2024 Free Software Foundation, Inc.
;; Author: Per Cederqvist <ceder@lysator.liu.se>
;; Inge Wallin <inge@lysator.liu.se>
diff --git a/lisp/emacs-lisp/backquote.el b/lisp/emacs-lisp/backquote.el
index 84527234207..6917128d70a 100644
--- a/lisp/emacs-lisp/backquote.el
+++ b/lisp/emacs-lisp/backquote.el
@@ -1,6 +1,6 @@
;;; backquote.el --- implement the ` Lisp construct -*- lexical-binding: t -*-
-;; Copyright (C) 1990, 1992, 1994, 2001-2023 Free Software Foundation,
+;; Copyright (C) 1990, 1992, 1994, 2001-2024 Free Software Foundation,
;; Inc.
;; Author: Rick Sladkey <jrs@world.std.com>
diff --git a/lisp/emacs-lisp/backtrace.el b/lisp/emacs-lisp/backtrace.el
index 1beeb523f08..e47e2662afa 100644
--- a/lisp/emacs-lisp/backtrace.el
+++ b/lisp/emacs-lisp/backtrace.el
@@ -1,6 +1,6 @@
;;; backtrace.el --- generic major mode for Elisp backtraces -*- lexical-binding: t -*-
-;; Copyright (C) 2018-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2018-2024 Free Software Foundation, Inc.
;; Author: Gemini Lasswell
;; Keywords: lisp, tools, maint
diff --git a/lisp/emacs-lisp/benchmark.el b/lisp/emacs-lisp/benchmark.el
index e50b8524f29..58e51d7565b 100644
--- a/lisp/emacs-lisp/benchmark.el
+++ b/lisp/emacs-lisp/benchmark.el
@@ -1,6 +1,6 @@
;;; benchmark.el --- support for benchmarking code -*- lexical-binding: t -*-
-;; Copyright (C) 2003-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003-2024 Free Software Foundation, Inc.
;; Author: Dave Love <fx@gnu.org>
;; Keywords: lisp, extensions
diff --git a/lisp/emacs-lisp/bindat.el b/lisp/emacs-lisp/bindat.el
index 6f2af7f975b..73745e8c7ac 100644
--- a/lisp/emacs-lisp/bindat.el
+++ b/lisp/emacs-lisp/bindat.el
@@ -1,6 +1,6 @@
;;; bindat.el --- binary data structure packing and unpacking. -*- lexical-binding: t; -*-
-;; Copyright (C) 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2024 Free Software Foundation, Inc.
;; Author: Kim F. Storm <storm@cua.dk>
;; Assignment name: struct.el
diff --git a/lisp/emacs-lisp/byte-opt.el b/lisp/emacs-lisp/byte-opt.el
index ecc5fff3b67..add13a5c312 100644
--- a/lisp/emacs-lisp/byte-opt.el
+++ b/lisp/emacs-lisp/byte-opt.el
@@ -1,6 +1,6 @@
;;; byte-opt.el --- the optimization passes of the emacs-lisp byte compiler -*- lexical-binding: t -*-
-;; Copyright (C) 1991, 1994, 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1991, 1994, 2000-2024 Free Software Foundation, Inc.
;; Author: Jamie Zawinski <jwz@lucid.com>
;; Hallvard Furuseth <hbf@ulrik.uio.no>
@@ -217,10 +217,10 @@ This indicates the loop discovery phase.")
(defvar byte-optimize--aliased-vars nil
"List of variables which may be aliased by other lexical variables.
-If an entry in `byte-optimize--lexvars' has another variable as its VALUE,
-then that other variable must be in this list.
-This variable thus carries no essential information but is maintained
-for speeding up processing.")
+Each element is (NAME . ALIAS) where NAME is the aliased variable
+and ALIAS the variable record (in the format described for
+`byte-optimize--lexvars') for an alias, which may have NAME as its VALUE.
+There can be multiple entries for the same NAME if it has several aliases.")
(defun byte-optimize--substitutable-p (expr)
"Whether EXPR is a constant that can be propagated."
@@ -440,7 +440,7 @@ for speeding up processing.")
(`(unwind-protect ,protected-expr :fun-body ,unwind-fun)
;; FIXME: The return value of UNWIND-FUN is never used so we
- ;; could potentially optimise it for-effect, but we don't do
+ ;; could potentially optimize it for-effect, but we don't do
;; that right no.
`(,fn ,(byte-optimize-form protected-expr for-effect)
:fun-body ,(byte-optimize-form unwind-fun)))
@@ -462,13 +462,17 @@ for speeding up processing.")
(setcar (cdr lexvar) t) ; Mark variable to be kept.
(setcdr (cdr lexvar) nil) ; Inhibit further substitution.
- (when (memq var byte-optimize--aliased-vars)
- ;; Cancel aliasing of variables aliased to this one.
- (dolist (v byte-optimize--lexvars)
- (when (eq (nth 2 v) var)
- ;; V is bound to VAR but VAR is now mutated:
- ;; cancel aliasing.
- (setcdr (cdr v) nil)))))
+ ;; Cancel substitution of variables aliasing this one.
+ (let ((aliased-vars byte-optimize--aliased-vars))
+ (while
+ (let ((alias (assq var aliased-vars)))
+ (and alias
+ (progn
+ ;; Found a variable bound to VAR but VAR is
+ ;; now mutated; cancel aliasing.
+ (setcdr (cddr alias) nil)
+ (setq aliased-vars (cdr (memq alias aliased-vars)))
+ t))))))
`(,fn ,var ,value)))
(`(defvar ,(and (pred symbolp) name) . ,rest)
@@ -481,10 +485,6 @@ for speeding up processing.")
(`(,(pred byte-code-function-p) . ,exps)
(cons fn (mapcar #'byte-optimize-form exps)))
- (`(,(pred (not symbolp)) . ,_)
- (byte-compile-warn-x form "`%s' is a malformed function" fn)
- form)
-
((guard (when for-effect
(if-let ((tmp (byte-opt--fget fn 'side-effect-free)))
(or byte-compile-delete-errors
@@ -587,7 +587,6 @@ for speeding up processing.")
(let* ((byte-optimize--lexvars byte-optimize--lexvars)
(byte-optimize--aliased-vars byte-optimize--aliased-vars)
(new-lexvars nil)
- (new-aliased-vars nil)
(let-vars nil)
(body (cdr form))
(bindings (car form)))
@@ -597,7 +596,7 @@ for speeding up processing.")
(expr (byte-optimize-form (cadr binding) nil)))
(setq bindings (cdr bindings))
(when (and (eq head 'let*)
- (memq name byte-optimize--aliased-vars))
+ (assq name byte-optimize--aliased-vars))
;; New variable shadows an aliased variable -- α-rename
;; it in this and all subsequent bindings.
(let ((new-name (make-symbol (symbol-name name))))
@@ -610,14 +609,12 @@ for speeding up processing.")
bindings))
(setq body (byte-optimize--rename-var-body name new-name body))
(setq name new-name)))
- (let* ((aliased nil)
- (value (and
- (or (byte-optimize--substitutable-p expr)
- ;; Aliasing another lexvar.
- (setq aliased
- (and (symbolp expr)
- (assq expr byte-optimize--lexvars))))
- (list expr)))
+ (let* ((aliased
+ ;; Aliasing another lexvar.
+ (and (symbolp expr) (assq expr byte-optimize--lexvars)))
+ (value (and (or aliased
+ (byte-optimize--substitutable-p expr))
+ (list expr)))
(lexical (not (or (special-variable-p name)
(memq name byte-compile-bound-variables)
(memq name byte-optimize--dynamic-vars))))
@@ -626,20 +623,16 @@ for speeding up processing.")
(when lexinfo
(push lexinfo (if (eq head 'let*)
byte-optimize--lexvars
- new-lexvars)))
- (when aliased
- (push expr (if (eq head 'let*)
- byte-optimize--aliased-vars
- new-aliased-vars))))))
-
- (setq byte-optimize--aliased-vars
- (append new-aliased-vars byte-optimize--aliased-vars))
+ new-lexvars))
+ (when aliased
+ (push (cons expr lexinfo) byte-optimize--aliased-vars))))))
+
(when (and (eq head 'let) byte-optimize--aliased-vars)
;; Find new variables that shadow aliased variables.
(let ((shadowing-vars nil))
(dolist (lexvar new-lexvars)
(let ((name (car lexvar)))
- (when (and (memq name byte-optimize--aliased-vars)
+ (when (and (assq name byte-optimize--aliased-vars)
(not (memq name shadowing-vars)))
(push name shadowing-vars))))
;; α-rename them
@@ -817,8 +810,29 @@ for speeding up processing.")
(or (not form) ; assume (quote nil) always being normalized to nil
(and (consp form)
(let ((head (car form)))
- ;; FIXME: There are many other expressions that are statically nil.
- (cond ((memq head '(while ignore)) t)
+ (cond ((memq head
+ ;; Some forms that are statically nil.
+ ;; FIXME: Replace with a function property?
+ '( while ignore
+ insert insert-and-inherit insert-before-markers
+ insert-before-markers-and-inherit
+ insert-char insert-byte insert-buffer-substring
+ delete-region delete-char
+ widen narrow-to-region transpose-regions
+ forward-char backward-char
+ beginning-of-line end-of-line
+ erase-buffer buffer-swap-text
+ delete-overlay delete-all-overlays
+ remhash
+ maphash
+ map-charset-chars map-char-table
+ mapbacktrace
+ mapatoms
+ ding beep sleep-for
+ json-insert
+ set-match-data
+ ))
+ t)
((eq head 'if)
(and (byte-compile-nilconstp (nth 2 form))
(byte-compile-nilconstp (car (last (cdddr form))))))
@@ -980,7 +994,7 @@ for speeding up processing.")
(list (car form) (nth 2 form) (nth 1 form)))))
(defun byte-opt--nary-comparison (form)
- "Optimise n-ary comparisons such as `=', `<' etc."
+ "Optimize n-ary comparisons such as `=', `<' etc."
(let ((nargs (length (cdr form))))
(cond
((= nargs 1)
@@ -995,7 +1009,7 @@ for speeding up processing.")
(if (memq nil (mapcar #'macroexp-copyable-p (cddr form)))
;; At least one arg beyond the first is non-constant non-variable:
;; create temporaries for all args to guard against side-effects.
- ;; The optimiser will eliminate trivial bindings later.
+ ;; The optimizer will eliminate trivial bindings later.
(let ((i 1))
(dolist (arg (cdr form))
(let ((var (make-symbol (format "arg%d" i))))
@@ -1465,7 +1479,7 @@ See Info node `(elisp) Integer Basics'."
(put 'let* 'byte-optimizer #'byte-optimize-letX)
(defun byte-optimize-letX (form)
(pcase form
- ;; No bindings.
+ ;; Bindings list is empty.
(`(,_ () . ,body)
`(progn . ,body))
@@ -1475,7 +1489,7 @@ See Info node `(elisp) Integer Basics'."
`(progn ,@(mapcar #'cadr bindings) ,const)
`(,head ,(butlast bindings) ,(cadar (last bindings)) ,const)))
- ;; Body is last variable.
+ ;; Body does nothing but return the last variable in bindings.
(`(,head ,(and bindings
(let last-var (caar (last bindings))))
,(and last-var ; non-linear pattern
diff --git a/lisp/emacs-lisp/byte-run.el b/lisp/emacs-lisp/byte-run.el
index a377ec395e1..cc176821026 100644
--- a/lisp/emacs-lisp/byte-run.el
+++ b/lisp/emacs-lisp/byte-run.el
@@ -1,6 +1,6 @@
;;; byte-run.el --- byte-compiler support for inlining -*- lexical-binding: t -*-
-;; Copyright (C) 1992, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1992, 2001-2024 Free Software Foundation, Inc.
;; Author: Jamie Zawinski <jwz@lucid.com>
;; Hallvard Furuseth <hbf@ulrik.uio.no>
@@ -494,6 +494,11 @@ convention was modified."
Return t if there isn't any."
(gethash function advertised-signature-table t))
+(defun byte-run--constant-obsolete-warning (obsolete-name)
+ (if (memq obsolete-name '(nil t))
+ (error "Can't make `%s' obsolete; did you forget a quote mark?"
+ obsolete-name)))
+
(defun make-obsolete (obsolete-name current-name when)
"Make the byte-compiler warn that function OBSOLETE-NAME is obsolete.
OBSOLETE-NAME should be a function name or macro name (a symbol).
@@ -503,6 +508,7 @@ If CURRENT-NAME is a string, that is the `use instead' message
\(it should end with a period, and not start with a capital).
WHEN should be a string indicating when the function
was first made obsolete, for example a date or a release number."
+ (byte-run--constant-obsolete-warning obsolete-name)
(put obsolete-name 'byte-obsolete-info
;; The second entry used to hold the `byte-compile' handler, but
;; is not used any more nowadays.
@@ -539,6 +545,7 @@ WHEN should be a string indicating when the variable
was first made obsolete, for example a date or a release number.
ACCESS-TYPE if non-nil should specify the kind of access that will trigger
obsolescence warnings; it can be either `get' or `set'."
+ (byte-run--constant-obsolete-warning obsolete-name)
(put obsolete-name 'byte-obsolete-variable
(purecopy (list current-name access-type when)))
obsolete-name)
diff --git a/lisp/emacs-lisp/bytecomp.el b/lisp/emacs-lisp/bytecomp.el
index c98d02b1ec1..1ef3f0fba6d 100644
--- a/lisp/emacs-lisp/bytecomp.el
+++ b/lisp/emacs-lisp/bytecomp.el
@@ -1,6 +1,6 @@
;;; bytecomp.el --- compilation of Lisp code into byte code -*- lexical-binding: t -*-
-;; Copyright (C) 1985-1987, 1992, 1994, 1998, 2000-2023 Free Software
+;; Copyright (C) 1985-1987, 1992, 1994, 1998, 2000-2024 Free Software
;; Foundation, Inc.
;; Author: Jamie Zawinski <jwz@lucid.com>
@@ -292,46 +292,51 @@ The information is logged to `byte-compile-log-buffer'."
;;;###autoload(put 'byte-compile-error-on-warn 'safe-local-variable 'booleanp)
(defconst byte-compile-warning-types
- '(redefine callargs free-vars unresolved
- obsolete noruntime interactive-only
- make-local mapcar constants suspicious lexical lexical-dynamic
- docstrings docstrings-non-ascii-quotes not-unused
- empty-body)
+ '( callargs constants
+ docstrings docstrings-non-ascii-quotes docstrings-wide
+ empty-body free-vars ignored-return-value interactive-only
+ lexical lexical-dynamic make-local
+ mapcar ; obsolete
+ mutate-constant noruntime not-unused obsolete redefine suspicious
+ unresolved)
"The list of warning types used when `byte-compile-warnings' is t.")
(defcustom byte-compile-warnings t
"List of warnings that the byte-compiler should issue (t for almost all).
Elements of the list may be:
- free-vars references to variables not in the current lexical scope.
- unresolved calls to unknown functions.
callargs function calls with args that don't match the definition.
- redefine function name redefined from a macro to ordinary function or vice
- versa, or redefined to take a different number of arguments.
- obsolete obsolete variables and functions.
- noruntime functions that may not be defined at runtime (typically
- defined only under `eval-when-compile').
+ constants let-binding of, or assignment to, constants/nonvariables.
+ docstrings various docstring stylistic issues, such as incorrect use
+ of single quotes
+ docstrings-non-ascii-quotes
+ docstrings that have non-ASCII quotes.
+ Only enabled when `docstrings' also is.
+ docstrings-wide
+ docstrings that are too wide, containing lines longer than both
+ `byte-compile-docstring-max-column' and `fill-column' characters.
+ Only enabled when `docstrings' also is.
+ empty-body body argument to a special form or macro is empty.
+ free-vars references to variables not in the current lexical scope.
+ ignored-return-value
+ function called without using the return value where this
+ is likely to be a mistake.
interactive-only
commands that normally shouldn't be called from Lisp code.
lexical global/dynamic variables lacking a prefix.
lexical-dynamic
lexically bound variable declared dynamic elsewhere
make-local calls to `make-variable-buffer-local' that may be incorrect.
- ignored-return-value
- function called without using the return value where this
- is likely to be a mistake
+ mutate-constant
+ code that mutates program constants such as quoted lists.
+ noruntime functions that may not be defined at runtime (typically
+ defined only under `eval-when-compile').
not-unused warning about using variables with symbol names starting with _.
- constants let-binding of, or assignment to, constants/nonvariables.
- docstrings docstrings that are too wide (longer than
- `byte-compile-docstring-max-column' or
- `fill-column' characters, whichever is bigger) or
- have other stylistic issues.
- docstrings-non-ascii-quotes docstrings that have non-ASCII quotes.
- This depends on the `docstrings' warning type.
+ obsolete obsolete variables and functions.
+ redefine function name redefined from a macro to ordinary function or vice
+ versa, or redefined to take a different number of arguments.
suspicious constructs that usually don't do what the coder wanted.
- empty-body body argument to a special form or macro is empty.
- mutate-constant
- code that mutates program constants such as quoted lists
+ unresolved calls to unknown functions.
If the list begins with `not', then the remaining elements specify warnings to
suppress. For example, (not free-vars) will suppress the `free-vars' warning.
@@ -339,7 +344,8 @@ suppress. For example, (not free-vars) will suppress the `free-vars' warning.
The t value means \"all non experimental warning types\", and
excludes the types in `byte-compile--emacs-build-warning-types'.
A value of `all' really means all."
- :type `(choice (const :tag "All" t)
+ :type `(choice (const :tag "Default selection" t)
+ (const :tag "All" all)
(set :menu-tag "Some"
,@(mapcar (lambda (x) `(const ,x))
byte-compile-warning-types))))
@@ -1618,57 +1624,6 @@ extra args."
(dolist (elt '(format message format-message error))
(put elt 'byte-compile-format-like t))
-(defun byte-compile--defcustom-type-quoted (type)
- "Whether defcustom TYPE contains an accidentally quoted value."
- ;; Detect mistakes such as (const 'abc).
- ;; We don't actually follow the syntax for defcustom types, but this
- ;; should be good enough.
- (and (consp type)
- (proper-list-p type)
- (if (memq (car type) '(const other))
- (assq 'quote type)
- (let ((elts (cdr type)))
- (while (and elts (not (byte-compile--defcustom-type-quoted
- (car elts))))
- (setq elts (cdr elts)))
- elts))))
-
-;; Warn if a custom definition fails to specify :group, or :type.
-(defun byte-compile-nogroup-warn (form)
- (let ((keyword-args (cdr (cdr (cdr (cdr form)))))
- (name (cadr form)))
- (when (eq (car-safe name) 'quote)
- (when (eq (car form) 'custom-declare-variable)
- (let ((type (plist-get keyword-args :type)))
- (cond
- ((not type)
- (byte-compile-warn-x (cadr name)
- "defcustom for `%s' fails to specify type"
- (cadr name)))
- ((byte-compile--defcustom-type-quoted type)
- (byte-compile-warn-x
- (cadr name)
- "defcustom for `%s' may have accidentally quoted value in type `%s'"
- (cadr name) type)))))
- (if (and (memq (car form) '(custom-declare-face custom-declare-variable))
- byte-compile-current-group)
- ;; The group will be provided implicitly.
- nil
- (or (and (eq (car form) 'custom-declare-group)
- (equal name ''emacs))
- (plist-get keyword-args :group)
- (byte-compile-warn-x (cadr name)
- "%s for `%s' fails to specify containing group"
- (cdr (assq (car form)
- '((custom-declare-group . defgroup)
- (custom-declare-face . defface)
- (custom-declare-variable . defcustom))))
- (cadr name)))
- ;; Update the current group, if needed.
- (if (and byte-compile-current-file ;Only when compiling a whole file.
- (eq (car form) 'custom-declare-group))
- (setq byte-compile-current-group (cadr name)))))))
-
;; Warn if the function or macro is being redefined with a different
;; number of arguments.
(defun byte-compile-arglist-warn (name arglist macrop)
@@ -1719,53 +1674,75 @@ extra args."
(if (equal sig1 '(1 . 1)) "argument" "arguments")
(byte-compile-arglist-signature-string sig2)))))))
-(defvar byte-compile--wide-docstring-substitution-len 3
- "Substitution width used in `byte-compile--wide-docstring-p'.
-This is a heuristic for guessing the width of a documentation
-string: `byte-compile--wide-docstring-p' assumes that any
-`substitute-command-keys' command substitutions are this long.")
-
-(defun byte-compile--wide-docstring-p (docstring col)
- "Return t if string DOCSTRING is wider than COL.
+(defun bytecomp--docstring-line-width (str)
+ "An approximation of the displayed width of docstring line STR."
+ ;; For literal key sequence substitutions (e.g. "\\`C-h'"), just
+ ;; remove the markup as `substitute-command-keys' would.
+ (when (string-search "\\`" str)
+ (setq str (replace-regexp-in-string
+ (rx "\\`" (group (* (not "'"))) "'")
+ "\\1"
+ str t)))
+ ;; Heuristic: We can't reliably do `substitute-command-keys'
+ ;; substitutions, since the value of a keymap in general can't be
+ ;; known at compile time. So instead, we assume that these
+ ;; substitutions are of some constant length.
+ (when (string-search "\\[" str)
+ (setq str (replace-regexp-in-string
+ (rx "\\[" (* (not "]")) "]")
+ ;; We assume that substitutions have this length.
+ ;; To preserve the non-expansive property of the transform,
+ ;; it shouldn't be more than 3 characters long.
+ "xxx"
+ str t t)))
+ (setq str
+ (replace-regexp-in-string
+ (rx (or
+ ;; Ignore some URLs.
+ (seq "http" (? "s") "://" (* nonl))
+ ;; Ignore these `substitute-command-keys' substitutions.
+ (seq "\\" (or "="
+ (seq "<" (* (not ">")) ">")
+ (seq "{" (* (not "}")) "}")))
+ ;; Ignore the function signature that's stashed at the end of
+ ;; the doc string (in some circumstances).
+ (seq bol "(" (+ (any word "-/:[]&"))
+ ;; One or more arguments.
+ (+ " " (or
+ ;; Arguments.
+ (+ (or (syntax symbol)
+ (any word "-/:[]&=()<>.,?^\\#*'\"")))
+ ;; Argument that is a list.
+ (seq "(" (* (not ")")) ")")))
+ ")")))
+ "" str t t))
+ (length str))
+
+(defun byte-compile--wide-docstring-p (docstring max-width)
+ "Whether DOCSTRING contains a line wider than MAX-WIDTH.
Ignore all `substitute-command-keys' substitutions, except for
-the `\\\\=[command]' ones that are assumed to be of length
-`byte-compile--wide-docstring-substitution-len'. Also ignore
-URLs."
- (string-match
- (format "^.\\{%d,\\}$" (min (1+ col) #xffff)) ; Heed RE_DUP_MAX.
- (replace-regexp-in-string
- (rx (or
- ;; Ignore some URLs.
- (seq "http" (? "s") "://" (* nonl))
- ;; Ignore these `substitute-command-keys' substitutions.
- (seq "\\" (or "="
- (seq "<" (* (not ">")) ">")
- (seq "{" (* (not "}")) "}")))
- ;; Ignore the function signature that's stashed at the end of
- ;; the doc string (in some circumstances).
- (seq bol "(" (+ (any word "-/:[]&"))
- ;; One or more arguments.
- (+ " " (or
- ;; Arguments.
- (+ (or (syntax symbol)
- (any word "-/:[]&=()<>.,?^\\#*'\"")))
- ;; Argument that is a list.
- (seq "(" (* (not ")")) ")")))
- ")")))
- ""
- ;; Heuristic: We can't reliably do `substitute-command-keys'
- ;; substitutions, since the value of a keymap in general can't be
- ;; known at compile time. So instead, we assume that these
- ;; substitutions are of some length N.
- (replace-regexp-in-string
- (rx "\\[" (* (not "]")) "]")
- (make-string byte-compile--wide-docstring-substitution-len ?x)
- ;; For literal key sequence substitutions (e.g. "\\`C-h'"), just
- ;; remove the markup as `substitute-command-keys' would.
- (replace-regexp-in-string
- (rx "\\`" (group (* (not "'"))) "'")
- "\\1"
- docstring)))))
+the `\\\\=[command]' ones that are assumed to be of a fixed length.
+Also ignore URLs."
+ (let ((string-len (length docstring))
+ (start 0)
+ (too-wide nil))
+ (while (< start string-len)
+ (let ((eol (or (string-search "\n" docstring start)
+ string-len)))
+ ;; Since `bytecomp--docstring-line-width' is non-expansive,
+ ;; we can safely assume that if the raw length is
+ ;; within the allowed width, then so is the transformed width.
+ ;; This allows us to avoid the very expensive transformation in
+ ;; most cases.
+ (if (and (> (- eol start) max-width)
+ (> (bytecomp--docstring-line-width
+ (substring docstring start eol))
+ max-width))
+ (progn
+ (setq too-wide t)
+ (setq start string-len))
+ (setq start (1+ eol)))))
+ too-wide))
(defcustom byte-compile-docstring-max-column 80
"Recommended maximum width of doc string lines.
@@ -1786,8 +1763,11 @@ Warn if documentation string of FORM is too wide.
It is too wide if it has any lines longer than the largest of
`fill-column' and `byte-compile-docstring-max-column'."
(when (byte-compile-warning-enabled-p 'docstrings)
- (let ((col (max byte-compile-docstring-max-column fill-column))
- kind name docs)
+ (let* ((kind nil) (name nil) (docs nil)
+ (prefix (lambda ()
+ (format "%s%s"
+ kind
+ (if name (format-message " `%s' " name) "")))))
(pcase (car form)
((or 'autoload 'custom-declare-variable 'defalias
'defconst 'define-abbrev-table
@@ -1795,20 +1775,19 @@ It is too wide if it has any lines longer than the largest of
'custom-declare-face)
(setq kind (nth 0 form))
(setq name (nth 1 form))
+ (when (and (consp name) (eq (car name) 'quote))
+ (setq name (cadr name)))
(setq docs (nth 3 form)))
('lambda
(setq kind "") ; can't be "function", unfortunately
- (setq docs (and (stringp (nth 2 form))
- (nth 2 form)))))
- (when (and (consp name) (eq (car name) 'quote))
- (setq name (cadr name)))
- (setq name (if name (format " `%s' " name) ""))
+ (setq docs (nth 2 form))))
(when (and kind docs (stringp docs))
- (when (byte-compile--wide-docstring-p docs col)
- (byte-compile-warn-x
- name
- "%s%sdocstring wider than %s characters"
- kind name col))
+ (let ((col (max byte-compile-docstring-max-column fill-column)))
+ (when (and (byte-compile-warning-enabled-p 'docstrings-wide)
+ (byte-compile--wide-docstring-p docs col))
+ (byte-compile-warn-x
+ name
+ "%sdocstring wider than %s characters" (funcall prefix) col)))
;; There's a "naked" ' character before a symbol/list, so it
;; should probably be quoted with \=.
(when (string-match-p (rx (| (in " \t") bol)
@@ -1818,16 +1797,19 @@ It is too wide if it has any lines longer than the largest of
docs)
(byte-compile-warn-x
name
- (concat "%s%sdocstring has wrong usage of unescaped single quotes"
+ (concat "%sdocstring has wrong usage of unescaped single quotes"
" (use \\=%c or different quoting such as %c...%c)")
- kind name ?' ?` ?'))
+ (funcall prefix) ?' ?` ?'))
;; There's a "Unicode quote" in the string -- it should probably
;; be an ASCII one instead.
(when (byte-compile-warning-enabled-p 'docstrings-non-ascii-quotes)
- (when (string-match-p "\\( \"\\|[ \t]\\|^\\)[‘’]" docs)
+ (when (string-match-p (rx (| " \"" (in " \t") bol)
+ (in "‘’"))
+ docs)
(byte-compile-warn-x
- name "%s%sdocstring has wrong usage of \"fancy\" single quotation marks"
- kind name))))))
+ name
+ "%sdocstring uses curved single quotes; use %s instead of ‘...’"
+ (funcall prefix) "`...'"))))))
form)
;; If we have compiled any calls to functions which are not known to be
@@ -1879,8 +1861,6 @@ It is too wide if it has any lines longer than the largest of
(byte-compile-dynamic byte-compile-dynamic)
(byte-compile-dynamic-docstrings
byte-compile-dynamic-docstrings)
- ;; (byte-compile-generate-emacs19-bytecodes
- ;; byte-compile-generate-emacs19-bytecodes)
(byte-compile-warnings byte-compile-warnings)
;; Indicate that we're not currently loading some file.
;; This is used in `macroexp-file-name' to make sure that
@@ -1896,35 +1876,37 @@ It is too wide if it has any lines longer than the largest of
(defmacro displaying-byte-compile-warnings (&rest body)
(declare (debug (def-body)))
- `(let* ((--displaying-byte-compile-warnings-fn (lambda () ,@body))
- (warning-series-started
- (and (markerp warning-series)
- (eq (marker-buffer warning-series)
- (get-buffer byte-compile-log-buffer))))
- (byte-compile-form-stack byte-compile-form-stack))
- (if (or (eq warning-series 'byte-compile-warning-series)
- warning-series-started)
- ;; warning-series does come from compilation,
- ;; so don't bind it, but maybe do set it.
- (let (tem)
- ;; Log the file name. Record position of that text.
- (setq tem (byte-compile-log-file))
- (unless warning-series-started
- (setq warning-series (or tem 'byte-compile-warning-series)))
- (if byte-compile-debug
- (funcall --displaying-byte-compile-warnings-fn)
- (condition-case error-info
- (funcall --displaying-byte-compile-warnings-fn)
- (error (byte-compile-report-error error-info)))))
- ;; warning-series does not come from compilation, so bind it.
- (let ((warning-series
- ;; Log the file name. Record position of that text.
- (or (byte-compile-log-file) 'byte-compile-warning-series)))
- (if byte-compile-debug
- (funcall --displaying-byte-compile-warnings-fn)
- (condition-case error-info
- (funcall --displaying-byte-compile-warnings-fn)
- (error (byte-compile-report-error error-info))))))))
+ `(bytecomp--displaying-warnings (lambda () ,@body)))
+
+(defun bytecomp--displaying-warnings (body-fn)
+ (let* ((warning-series-started
+ (and (markerp warning-series)
+ (eq (marker-buffer warning-series)
+ (get-buffer byte-compile-log-buffer))))
+ (byte-compile-form-stack byte-compile-form-stack))
+ (if (or (eq warning-series 'byte-compile-warning-series)
+ warning-series-started)
+ ;; warning-series does come from compilation,
+ ;; so don't bind it, but maybe do set it.
+ (let (tem)
+ ;; Log the file name. Record position of that text.
+ (setq tem (byte-compile-log-file))
+ (unless warning-series-started
+ (setq warning-series (or tem 'byte-compile-warning-series)))
+ (if byte-compile-debug
+ (funcall body-fn)
+ (condition-case error-info
+ (funcall body-fn)
+ (error (byte-compile-report-error error-info)))))
+ ;; warning-series does not come from compilation, so bind it.
+ (let ((warning-series
+ ;; Log the file name. Record position of that text.
+ (or (byte-compile-log-file) 'byte-compile-warning-series)))
+ (if byte-compile-debug
+ (funcall body-fn)
+ (condition-case error-info
+ (funcall body-fn)
+ (error (byte-compile-report-error error-info))))))))
;;;###autoload
(defun byte-force-recompile (directory)
@@ -2221,6 +2203,11 @@ See also `emacs-lisp-byte-compile-and-load'."
filename buffer-file-name))
;; Don't inherit lexical-binding from caller (bug#12938).
(unless (local-variable-p 'lexical-binding)
+ (let ((byte-compile-current-buffer (current-buffer)))
+ (displaying-byte-compile-warnings
+ (byte-compile-warn-x
+ (position-symbol 'a (point-min))
+ "file has no `lexical-binding' directive on its first line")))
(setq-local lexical-binding nil))
;; Set the default directory, in case an eval-when-compile uses it.
(setq default-directory (file-name-directory filename)))
@@ -2493,10 +2480,9 @@ Call from the source buffer."
(print-quoted t)
(print-gensym t)
(print-circle t)) ; Handle circular data structures.
- (if (and (memq (car-safe form) '(defvar defvaralias defconst
- autoload custom-declare-variable))
- (stringp (nth 3 form)))
- (byte-compile-output-docform nil nil '("\n(" 3 ")") form nil
+ (if (memq (car-safe form) '(defvar defvaralias defconst
+ autoload custom-declare-variable))
+ (byte-compile-output-docform nil nil nil '("\n(" ")") form nil 3 nil
(memq (car form)
'(defvaralias autoload
custom-declare-variable)))
@@ -2506,10 +2492,105 @@ Call from the source buffer."
(defvar byte-compile--for-effect)
-(defun byte-compile-output-docform (preface name info form specindex quoted)
- "Print a form with a doc string. INFO is (prefix doc-index postfix).
-If PREFACE and NAME are non-nil, print them too,
-before INFO and the FORM but after the doc string itself.
+(defun byte-compile--output-docform-recurse
+ (info position form cvecindex docindex specindex quoted)
+ "Print a form with a doc string. INFO is (prefix postfix).
+POSITION is where the next doc string is to be inserted.
+CVECINDEX is the index in the FORM of the constant vector, or nil.
+DOCINDEX is the index of the doc string (or nil) in the FORM.
+If SPECINDEX is non-nil, it is the index in FORM
+of the function bytecode string. In that case,
+we output that argument and the following argument
+\(the constants vector) together, for lazy loading.
+QUOTED says that we have to put a quote before the
+list that represents a doc string reference.
+`defvaralias', `autoload' and `custom-declare-variable' need that.
+
+Return the position after any inserted docstrings as comments."
+ (let ((index 0)
+ doc-string-position)
+ ;; Insert the doc string, and make it a comment with #@LENGTH.
+ (when (and byte-compile-dynamic-docstrings
+ (stringp (nth docindex form)))
+ (goto-char position)
+ (setq doc-string-position
+ (byte-compile-output-as-comment
+ (nth docindex form) nil)
+ position (point))
+ (goto-char (point-max)))
+
+ (insert (car info))
+ (prin1 (car form) byte-compile--outbuffer)
+ (while (setq form (cdr form))
+ (setq index (1+ index))
+ (insert " ")
+ (cond ((and (numberp specindex) (= index specindex)
+ ;; Don't handle the definition dynamically
+ ;; if it refers (or might refer)
+ ;; to objects already output
+ ;; (for instance, gensyms in the arg list).
+ (let (non-nil)
+ (when (hash-table-p print-number-table)
+ (maphash (lambda (_k v) (if v (setq non-nil t)))
+ print-number-table))
+ (not non-nil)))
+ ;; Output the byte code and constants specially
+ ;; for lazy dynamic loading.
+ (goto-char position)
+ (let ((lazy-position (byte-compile-output-as-comment
+ (cons (car form) (nth 1 form))
+ t)))
+ (setq position (point))
+ (goto-char (point-max))
+ (princ (format "(#$ . %d) nil" lazy-position)
+ byte-compile--outbuffer)
+ (setq form (cdr form))
+ (setq index (1+ index))))
+ ((eq index cvecindex)
+ (let* ((cvec (car form))
+ (len (length cvec))
+ (index2 0)
+ elt)
+ (insert "[")
+ (while (< index2 len)
+ (setq elt (aref cvec index2))
+ (if (byte-code-function-p elt)
+ (setq position
+ (byte-compile--output-docform-recurse
+ '("#[" "]") position
+ (append elt nil) ; Convert the vector to a list.
+ 2 4 specindex nil))
+ (prin1 elt byte-compile--outbuffer))
+ (setq index2 (1+ index2))
+ (unless (eq index2 len)
+ (insert " ")))
+ (insert "]")))
+ ((= index docindex)
+ (cond
+ (doc-string-position
+ (princ (format (if quoted "'(#$ . %d)" "(#$ . %d)")
+ doc-string-position)
+ byte-compile--outbuffer))
+ ((stringp (car form))
+ (let ((print-escape-newlines nil))
+ (goto-char (prog1 (1+ (point))
+ (prin1 (car form)
+ byte-compile--outbuffer)))
+ (insert "\\\n")
+ (goto-char (point-max))))
+ (t (prin1 (car form) byte-compile--outbuffer))))
+ (t (prin1 (car form) byte-compile--outbuffer))))
+ (insert (cadr info))
+ position))
+
+(defun byte-compile-output-docform (preface tailpiece name info form
+ cvecindex docindex
+ specindex quoted)
+ "Print a form with a doc string. INFO is (prefix postfix).
+If PREFACE, NAME, and TAILPIECE are non-nil, print them too,
+before/after INFO and the FORM but after the doc string itself.
+CVECINDEX is the index in the FORM of the constant vector, or nil.
+DOCINDEX is the index of the doc string (or nil) in the FORM.
If SPECINDEX is non-nil, it is the index in FORM
of the function bytecode string. In that case,
we output that argument and the following argument
@@ -2519,73 +2600,30 @@ list that represents a doc string reference.
`defvaralias', `autoload' and `custom-declare-variable' need that."
;; We need to examine byte-compile-dynamic-docstrings
;; in the input buffer (now current), not in the output buffer.
- (let ((dynamic-docstrings byte-compile-dynamic-docstrings))
+ (let ((byte-compile-dynamic-docstrings byte-compile-dynamic-docstrings))
(with-current-buffer byte-compile--outbuffer
- (let (position)
- ;; Insert the doc string, and make it a comment with #@LENGTH.
- (when (and (>= (nth 1 info) 0) dynamic-docstrings)
- (setq position (byte-compile-output-as-comment
- (nth (nth 1 info) form) nil)))
-
- (let ((print-continuous-numbering t)
- print-number-table
- (index 0)
- ;; FIXME: The bindings below are only needed for when we're
- ;; called from ...-defmumble.
- (print-escape-newlines t)
- (print-length nil)
- (print-level nil)
- (print-quoted t)
- (print-gensym t)
- (print-circle t)) ; Handle circular data structures.
- (if preface
- (progn
- ;; FIXME: We don't handle uninterned names correctly.
- ;; E.g. if cl-define-compiler-macro uses uninterned name we get:
- ;; (defalias '#1=#:foo--cmacro #[514 ...])
- ;; (put 'foo 'compiler-macro '#:foo--cmacro)
- (insert preface)
- (prin1 name byte-compile--outbuffer)))
- (insert (car info))
- (prin1 (car form) byte-compile--outbuffer)
- (while (setq form (cdr form))
- (setq index (1+ index))
- (insert " ")
- (cond ((and (numberp specindex) (= index specindex)
- ;; Don't handle the definition dynamically
- ;; if it refers (or might refer)
- ;; to objects already output
- ;; (for instance, gensyms in the arg list).
- (let (non-nil)
- (when (hash-table-p print-number-table)
- (maphash (lambda (_k v) (if v (setq non-nil t)))
- print-number-table))
- (not non-nil)))
- ;; Output the byte code and constants specially
- ;; for lazy dynamic loading.
- (let ((position
- (byte-compile-output-as-comment
- (cons (car form) (nth 1 form))
- t)))
- (princ (format "(#$ . %d) nil" position)
- byte-compile--outbuffer)
- (setq form (cdr form))
- (setq index (1+ index))))
- ((= index (nth 1 info))
- (if position
- (princ (format (if quoted "'(#$ . %d)" "(#$ . %d)")
- position)
- byte-compile--outbuffer)
- (let ((print-escape-newlines nil))
- (goto-char (prog1 (1+ (point))
- (prin1 (car form)
- byte-compile--outbuffer)))
- (insert "\\\n")
- (goto-char (point-max)))))
- (t
- (prin1 (car form) byte-compile--outbuffer)))))
- (insert (nth 2 info)))))
- nil)
+ (let ((position (point))
+ (print-continuous-numbering t)
+ print-number-table
+ ;; FIXME: The bindings below are only needed for when we're
+ ;; called from ...-defmumble.
+ (print-escape-newlines t)
+ (print-length nil)
+ (print-level nil)
+ (print-quoted t)
+ (print-gensym t)
+ (print-circle t)) ; Handle circular data structures.
+ (when preface
+ ;; FIXME: We don't handle uninterned names correctly.
+ ;; E.g. if cl-define-compiler-macro uses uninterned name we get:
+ ;; (defalias '#1=#:foo--cmacro #[514 ...])
+ ;; (put 'foo 'compiler-macro '#:foo--cmacro)
+ (insert preface)
+ (prin1 name byte-compile--outbuffer))
+ (byte-compile--output-docform-recurse
+ info position form cvecindex docindex specindex quoted)
+ (when tailpiece
+ (insert tailpiece))))))
(defun byte-compile-keep-pending (form &optional handler)
(if (memq byte-optimize '(t source))
@@ -2628,16 +2666,12 @@ list that represents a doc string reference.
;; byte-hunk-handlers cannot call this!
(defun byte-compile-toplevel-file-form (top-level-form)
- ;; (let ((byte-compile-form-stack
- ;; (cons top-level-form byte-compile-form-stack)))
- (push top-level-form byte-compile-form-stack)
- (prog1
- (byte-compile-recurse-toplevel
- top-level-form
- (lambda (form)
- (let ((byte-compile-current-form nil)) ; close over this for warnings.
- (byte-compile-file-form (byte-compile-preprocess form t)))))
- (pop byte-compile-form-stack)))
+ (macroexp--with-extended-form-stack top-level-form
+ (byte-compile-recurse-toplevel
+ top-level-form
+ (lambda (form)
+ (let ((byte-compile-current-form nil)) ; close over this for warnings.
+ (byte-compile-file-form (byte-compile-preprocess form t)))))))
;; byte-hunk-handlers can call this.
(defun byte-compile-file-form (form)
@@ -2913,60 +2947,58 @@ not to take responsibility for the actual compilation of the code."
;; Otherwise, we have a bona-fide defun/defmacro definition, and use
;; special code to allow dynamic docstrings and byte-code.
(byte-compile-flush-pending)
- (let ((index
- ;; If there's no doc string, provide -1 as the "doc string
- ;; index" so that no element will be treated as a doc string.
- (if (not (stringp (documentation code t))) -1 4)))
- (when byte-native-compiling
- ;; Spill output for the native compiler here.
- (push
- (if macro
- (make-byte-to-native-top-level
- :form `(defalias ',name '(macro . ,code) nil)
- :lexical lexical-binding)
- (make-byte-to-native-func-def :name name
- :byte-func code))
- byte-to-native-top-level-forms))
- ;; Output the form by hand, that's much simpler than having
- ;; b-c-output-file-form analyze the defalias.
- (byte-compile-output-docform
- "\n(defalias '"
- bare-name
- (if macro `(" '(macro . #[" ,index "])") `(" #[" ,index "]"))
- (append code nil) ; Turn byte-code-function-p into list.
- (and (atom code) byte-compile-dynamic
- 1)
- nil))
- (princ ")" byte-compile--outbuffer)
+ (when byte-native-compiling
+ ;; Spill output for the native compiler here.
+ (push
+ (if macro
+ (make-byte-to-native-top-level
+ :form `(defalias ',name '(macro . ,code) nil)
+ :lexical lexical-binding)
+ (make-byte-to-native-func-def :name name
+ :byte-func code))
+ byte-to-native-top-level-forms))
+ ;; Output the form by hand, that's much simpler than having
+ ;; b-c-output-file-form analyze the defalias.
+ (byte-compile-output-docform
+ "\n(defalias '" ")"
+ bare-name
+ (if macro '(" '(macro . #[" "])") '(" #[" "]"))
+ (append code nil) ; Turn byte-code-function-p into list.
+ 2 4
+ (and (atom code) byte-compile-dynamic 1)
+ nil)
t)))))
(defun byte-compile-output-as-comment (exp quoted)
- "Print Lisp object EXP in the output file, inside a comment.
-Return the file (byte) position it will have.
-If QUOTED is non-nil, print with quoting; otherwise, print without quoting."
+ "Print Lisp object EXP in the output file at point, inside a comment.
+Return the file (byte) position it will have. Leave point after
+the inserted text. If QUOTED is non-nil, print with quoting;
+otherwise, print without quoting."
(with-current-buffer byte-compile--outbuffer
- (let ((position (point)))
-
+ (let ((position (point)) end)
;; Insert EXP, and make it a comment with #@LENGTH.
(insert " ")
(if quoted
(prin1 exp byte-compile--outbuffer)
(princ exp byte-compile--outbuffer))
+ (setq end (point-marker))
+ (set-marker-insertion-type end t)
+
(goto-char position)
;; Quote certain special characters as needed.
;; get_doc_string in doc.c does the unquoting.
- (while (search-forward "\^A" nil t)
+ (while (search-forward "\^A" end t)
(replace-match "\^A\^A" t t))
(goto-char position)
- (while (search-forward "\000" nil t)
+ (while (search-forward "\000" end t)
(replace-match "\^A0" t t))
(goto-char position)
- (while (search-forward "\037" nil t)
+ (while (search-forward "\037" end t)
(replace-match "\^A_" t t))
- (goto-char (point-max))
+ (goto-char end)
(insert "\037")
(goto-char position)
- (insert "#@" (format "%d" (- (position-bytes (point-max))
+ (insert "#@" (format "%d" (- (position-bytes end)
(position-bytes position))))
;; Save the file position of the object.
@@ -2975,7 +3007,8 @@ If QUOTED is non-nil, print with quoting; otherwise, print without quoting."
;; position to a file position.
(prog1
(- (position-bytes (point)) (point-min) -1)
- (goto-char (point-max))))))
+ (goto-char end)
+ (set-marker end nil)))))
(defun byte-compile--reify-function (fun)
"Return an expression which will evaluate to a function value FUN.
@@ -3449,127 +3482,126 @@ lambda-expression."
;;
(defun byte-compile-form (form &optional for-effect)
(let ((byte-compile--for-effect for-effect))
- (push form byte-compile-form-stack)
- (cond
- ((not (consp form))
- (cond ((or (not (symbolp form)) (macroexp--const-symbol-p form))
- (byte-compile-constant form))
- ((and byte-compile--for-effect byte-compile-delete-errors)
- (setq byte-compile--for-effect nil))
- (t (byte-compile-variable-ref form))))
- ((symbolp (car form))
- (let* ((fn (car form))
- (handler (get fn 'byte-compile))
- (interactive-only
- (or (function-get fn 'interactive-only)
- (memq fn byte-compile-interactive-only-functions))))
- (when (memq fn '(set symbol-value run-hooks ;; add-to-list
- add-hook remove-hook run-hook-with-args
- run-hook-with-args-until-success
- run-hook-with-args-until-failure))
- (pcase (cdr form)
- (`(',var . ,_)
- (when (and (memq var byte-compile-lexical-variables)
- (byte-compile-warning-enabled-p 'lexical var))
- (byte-compile-warn
- (format-message "%s cannot use lexical var `%s'" fn var))))))
- ;; Warn about using obsolete hooks.
- (if (memq fn '(add-hook remove-hook))
- (let ((hook (car-safe (cdr form))))
- (if (eq (car-safe hook) 'quote)
- (byte-compile-check-variable (cadr hook) nil))))
- (when (and (byte-compile-warning-enabled-p 'suspicious)
- (macroexp--const-symbol-p fn))
- (byte-compile-warn-x fn "`%s' called as a function" fn))
- (when (and (byte-compile-warning-enabled-p 'interactive-only fn)
- interactive-only)
- (byte-compile-warn-x fn "`%s' is for interactive use only%s"
- fn
- (cond ((stringp interactive-only)
- (format "; %s"
- (substitute-command-keys
- interactive-only)))
- ((and (symbolp interactive-only)
- (not (eq interactive-only t)))
- (format-message "; use `%s' instead."
- interactive-only))
- (t "."))))
- (let ((mutargs (function-get (car form) 'mutates-arguments)))
- (when mutargs
- (dolist (idx (if (eq mutargs 'all-but-last)
- (number-sequence 1 (- (length form) 2))
- mutargs))
- (let ((arg (nth idx form)))
- (when (and (or (and (eq (car-safe arg) 'quote)
- (consp (nth 1 arg)))
- (arrayp arg))
- (byte-compile-warning-enabled-p
- 'mutate-constant (car form)))
- (byte-compile-warn-x form "`%s' on constant %s (arg %d)"
- (car form)
- (if (consp arg) "list" (type-of arg))
- idx))))))
-
- (let ((funargs (function-get (car form) 'funarg-positions)))
- (dolist (funarg funargs)
- (let ((arg (if (numberp funarg)
- (nth funarg form)
- (cadr (memq funarg form)))))
- (when (and (eq 'quote (car-safe arg))
- (eq 'lambda (car-safe (cadr arg))))
+ (macroexp--with-extended-form-stack form
+ (cond
+ ((not (consp form))
+ (cond ((or (not (symbolp form)) (macroexp--const-symbol-p form))
+ (byte-compile-constant form))
+ ((and byte-compile--for-effect byte-compile-delete-errors)
+ (setq byte-compile--for-effect nil))
+ (t (byte-compile-variable-ref form))))
+ ((symbolp (car form))
+ (let* ((fn (car form))
+ (handler (get fn 'byte-compile))
+ (interactive-only
+ (or (function-get fn 'interactive-only)
+ (memq fn byte-compile-interactive-only-functions))))
+ (when (memq fn '(set symbol-value run-hooks ;; add-to-list
+ add-hook remove-hook run-hook-with-args
+ run-hook-with-args-until-success
+ run-hook-with-args-until-failure))
+ (pcase (cdr form)
+ (`(',var . ,_)
+ (when (and (memq var byte-compile-lexical-variables)
+ (byte-compile-warning-enabled-p 'lexical var))
+ (byte-compile-warn
+ (format-message "%s cannot use lexical var `%s'" fn var))))))
+ ;; Warn about using obsolete hooks.
+ (if (memq fn '(add-hook remove-hook))
+ (let ((hook (car-safe (cdr form))))
+ (if (eq (car-safe hook) 'quote)
+ (byte-compile-check-variable (cadr hook) nil))))
+ (when (and (byte-compile-warning-enabled-p 'suspicious)
+ (macroexp--const-symbol-p fn))
+ (byte-compile-warn-x fn "`%s' called as a function" fn))
+ (when (and (byte-compile-warning-enabled-p 'interactive-only fn)
+ interactive-only)
+ (byte-compile-warn-x fn "`%s' is for interactive use only%s"
+ fn
+ (cond ((stringp interactive-only)
+ (format "; %s"
+ (substitute-command-keys
+ interactive-only)))
+ ((and (symbolp interactive-only)
+ (not (eq interactive-only t)))
+ (format-message "; use `%s' instead."
+ interactive-only))
+ (t "."))))
+ (let ((mutargs (function-get (car form) 'mutates-arguments)))
+ (when mutargs
+ (dolist (idx (if (eq mutargs 'all-but-last)
+ (number-sequence 1 (- (length form) 2))
+ mutargs))
+ (let ((arg (nth idx form)))
+ (when (and (or (and (eq (car-safe arg) 'quote)
+ (consp (nth 1 arg)))
+ (arrayp arg))
+ (byte-compile-warning-enabled-p
+ 'mutate-constant (car form)))
+ (byte-compile-warn-x form "`%s' on constant %s (arg %d)"
+ (car form)
+ (if (consp arg) "list" (type-of arg))
+ idx))))))
+
+ (let ((funargs (function-get (car form) 'funarg-positions)))
+ (dolist (funarg funargs)
+ (let ((arg (if (numberp funarg)
+ (nth funarg form)
+ (cadr (memq funarg form)))))
+ (when (and (eq 'quote (car-safe arg))
+ (eq 'lambda (car-safe (cadr arg))))
+ (byte-compile-warn-x
+ arg "(lambda %s ...) quoted with %s rather than with #%s"
+ (or (nth 1 (cadr arg)) "()")
+ "'" "'"))))) ; avoid styled quotes
+
+ (if (eq (car-safe (symbol-function (car form))) 'macro)
+ (byte-compile-report-error
+ (format-message "`%s' defined after use in %S (missing `require' of a library file?)"
+ (car form) form)))
+
+ (when byte-compile--for-effect
+ (let ((sef (function-get (car form) 'side-effect-free)))
+ (cond
+ ((and sef (or (eq sef 'error-free)
+ byte-compile-delete-errors))
+ ;; This transform is normally done in the Lisp optimizer,
+ ;; so maybe we don't need to bother about it here?
+ (setq form (cons 'progn (cdr form)))
+ (setq handler #'byte-compile-progn))
+ ((and (or sef (function-get (car form) 'important-return-value))
+ ;; Don't warn for arguments to `ignore'.
+ (not (eq byte-compile--for-effect 'for-effect-no-warn))
+ (byte-compile-warning-enabled-p
+ 'ignored-return-value (car form)))
(byte-compile-warn-x
- arg "(lambda %s ...) quoted with %s rather than with #%s"
- (or (nth 1 (cadr arg)) "()")
- "'" "'"))))) ; avoid styled quotes
-
- (if (eq (car-safe (symbol-function (car form))) 'macro)
- (byte-compile-report-error
- (format-message "`%s' defined after use in %S (missing `require' of a library file?)"
- (car form) form)))
-
- (when byte-compile--for-effect
- (let ((sef (function-get (car form) 'side-effect-free)))
- (cond
- ((and sef (or (eq sef 'error-free)
- byte-compile-delete-errors))
- ;; This transform is normally done in the Lisp optimiser,
- ;; so maybe we don't need to bother about it here?
- (setq form (cons 'progn (cdr form)))
- (setq handler #'byte-compile-progn))
- ((and (or sef (function-get (car form) 'important-return-value))
- ;; Don't warn for arguments to `ignore'.
- (not (eq byte-compile--for-effect 'for-effect-no-warn))
- (byte-compile-warning-enabled-p
- 'ignored-return-value (car form)))
- (byte-compile-warn-x
- (car form)
- "value from call to `%s' is unused%s"
- (car form)
- (cond ((eq (car form) 'mapcar)
- "; use `mapc' or `dolist' instead")
- (t "")))))))
-
- (if (and handler
- ;; Make sure that function exists.
- (and (functionp handler)
- ;; Ignore obsolete byte-compile function used by former
- ;; CL code to handle compiler macros (we do it
- ;; differently now).
- (not (eq handler 'cl-byte-compile-compiler-macro))))
- (funcall handler form)
- (byte-compile-normal-call form))))
- ((and (byte-code-function-p (car form))
- (memq byte-optimize '(t lap)))
- (byte-compile-unfold-bcf form))
- ((byte-compile-normal-call form)))
- (if byte-compile--for-effect
- (byte-compile-discard))
- (pop byte-compile-form-stack)))
+ (car form)
+ "value from call to `%s' is unused%s"
+ (car form)
+ (cond ((eq (car form) 'mapcar)
+ "; use `mapc' or `dolist' instead")
+ (t "")))))))
+
+ (if (and handler
+ ;; Make sure that function exists.
+ (and (functionp handler)
+ ;; Ignore obsolete byte-compile function used by former
+ ;; CL code to handle compiler macros (we do it
+ ;; differently now).
+ (not (eq handler 'cl-byte-compile-compiler-macro))))
+ (funcall handler form)
+ (byte-compile-normal-call form))))
+ ((and (byte-code-function-p (car form))
+ (memq byte-optimize '(t lap)))
+ (byte-compile-unfold-bcf form))
+ ((byte-compile-normal-call form)))
+ (if byte-compile--for-effect
+ (byte-compile-discard)))))
(let ((important-return-value-fns
'(
;; These functions are side-effect-free except for the
- ;; behaviour of functions passed as argument.
+ ;; behavior of functions passed as argument.
mapcar mapcan mapconcat
assoc plist-get plist-member
@@ -3697,10 +3729,6 @@ lambda-expression."
(defun byte-compile-normal-call (form)
(when (and (symbolp (car form))
(byte-compile-warning-enabled-p 'callargs (car form)))
- (if (memq (car form)
- '(custom-declare-group custom-declare-variable
- custom-declare-face))
- (byte-compile-nogroup-warn form))
(byte-compile-callargs-warn form))
(if byte-compile-generate-call-tree
(byte-compile-annotate-call-tree form))
@@ -4118,7 +4146,7 @@ If it is nil, then the handler is \"byte-compile-SYMBOL.\""
(byte-compile-two-args
(if (macroexp-const-p (nth 1 form))
;; First argument is constant: flip it so that the constant
- ;; is last, which may allow more lapcode optimisations.
+ ;; is last, which may allow more lapcode optimizations.
(let* ((op (car form))
(flipped-op (cdr (assq op '((< . >) (<= . >=)
(> . <) (>= . <=) (= . =))))))
@@ -4282,7 +4310,7 @@ This function is never called when `lexical-binding' is nil."
(arg2 (nth 2 form)))
(when (and (memq (car form) '(+ *))
(macroexp-const-p arg1))
- ;; Put constant argument last for better LAP optimisation.
+ ;; Put constant argument last for better LAP optimization.
(cl-rotatef arg1 arg2))
(byte-compile-form arg1)
(byte-compile-form arg2)
@@ -5271,6 +5299,194 @@ binding slots have been popped."
(pcase form (`(,_ ',var) (byte-compile--declare-var var)))
(byte-compile-normal-call form))
+;; Warn about mistakes in `defcustom', `defface', `defgroup', `define-widget'
+
+(defvar bytecomp--cus-function)
+(defvar bytecomp--cus-name)
+
+(defun bytecomp--cus-warn (form format &rest args)
+ "Emit a warning about a `defcustom' type.
+FORM is used to provide location, `bytecomp--cus-function' and
+`bytecomp--cus-name' for context."
+ (let* ((actual-fun (or (cdr (assq bytecomp--cus-function
+ '((custom-declare-group . defgroup)
+ (custom-declare-face . defface)
+ (custom-declare-variable . defcustom))))
+ bytecomp--cus-function))
+ (prefix (format "in %s%s: "
+ actual-fun
+ (if bytecomp--cus-name
+ (format " for `%s'" bytecomp--cus-name)
+ ""))))
+ (apply #'byte-compile-warn-x form (concat prefix format) args)))
+
+(defun bytecomp--check-cus-type (type)
+ "Warn about common mistakes in the `defcustom' type TYPE."
+ (let ((invalid-types
+ '(
+ ;; Lisp type predicates, often confused with customization types:
+ functionp numberp integerp fixnump natnump floatp booleanp
+ characterp listp stringp consp vectorp symbolp keywordp
+ hash-table-p facep
+ ;; other mistakes occasionally seen (oh yes):
+ or and nil t
+ interger intger lits bool boolen constant filename
+ kbd any list-of auto
+ ;; from botched backquoting
+ \, \,@ \`
+ )))
+ (cond
+ ((consp type)
+ (let* ((head (car type))
+ (tail (cdr type)))
+ (while (and (keywordp (car tail)) (cdr tail))
+ (setq tail (cddr tail)))
+ (cond
+ ((plist-member (cdr type) :convert-widget) nil)
+ ((let ((tl tail))
+ (and (not (keywordp (car tail)))
+ (progn
+ (while (and tl (not (keywordp (car tl))))
+ (setq tl (cdr tl)))
+ (and tl
+ (progn
+ (bytecomp--cus-warn
+ tl "misplaced %s keyword in `%s' type" (car tl) head)
+ t))))))
+ ((memq head '(choice radio))
+ (unless tail
+ (bytecomp--cus-warn type "`%s' without any types inside" head))
+ (let ((clauses tail)
+ (constants nil)
+ (tags nil))
+ (while clauses
+ (let* ((ty (car clauses))
+ (ty-head (car-safe ty)))
+ (when (and (eq ty-head 'other) (cdr clauses))
+ (bytecomp--cus-warn ty "`other' not last in `%s'" head))
+ (when (memq ty-head '(const other))
+ (let ((ty-tail (cdr ty))
+ (val nil))
+ (while (and (keywordp (car ty-tail)) (cdr ty-tail))
+ (when (eq (car ty-tail) :value)
+ (setq val (cadr ty-tail)))
+ (setq ty-tail (cddr ty-tail)))
+ (when ty-tail
+ (setq val (car ty-tail)))
+ (when (member val constants)
+ (bytecomp--cus-warn
+ ty "duplicated value in `%s': `%S'" head val))
+ (push val constants)))
+ (let ((tag (and (consp ty) (plist-get (cdr ty) :tag))))
+ (when (stringp tag)
+ (when (member tag tags)
+ (bytecomp--cus-warn
+ ty "duplicated :tag string in `%s': %S" head tag))
+ (push tag tags)))
+ (bytecomp--check-cus-type ty))
+ (setq clauses (cdr clauses)))))
+ ((eq head 'cons)
+ (unless (= (length tail) 2)
+ (bytecomp--cus-warn
+ type "`cons' requires 2 type specs, found %d" (length tail)))
+ (dolist (ty tail)
+ (bytecomp--check-cus-type ty)))
+ ((memq head '(list group vector set repeat))
+ (unless tail
+ (bytecomp--cus-warn type "`%s' without type specs" head))
+ (dolist (ty tail)
+ (bytecomp--check-cus-type ty)))
+ ((memq head '(alist plist))
+ (let ((key-tag (memq :key-type (cdr type)))
+ (value-tag (memq :value-type (cdr type))))
+ (when key-tag
+ (bytecomp--check-cus-type (cadr key-tag)))
+ (when value-tag
+ (bytecomp--check-cus-type (cadr value-tag)))))
+ ((memq head '(const other))
+ (let* ((value-tag (memq :value (cdr type)))
+ (n (length tail))
+ (val (car tail)))
+ (cond
+ ((or (> n 1) (and value-tag tail))
+ (bytecomp--cus-warn type "`%s' with too many values" head))
+ (value-tag
+ (setq val (cadr value-tag)))
+ ;; ;; This is a useful check but it results in perhaps
+ ;; ;; a bit too many complaints.
+ ;; ((null tail)
+ ;; (bytecomp--cus-warn
+ ;; type "`%s' without value is implicitly nil" head))
+ )
+ (when (memq (car-safe val) '(quote function))
+ (bytecomp--cus-warn type "`%s' with quoted value: %S" head val))))
+ ((eq head 'quote)
+ (bytecomp--cus-warn type "type should not be quoted: %s" (cadr type)))
+ ((memq head invalid-types)
+ (bytecomp--cus-warn type "`%s' is not a valid type" head))
+ ((or (not (symbolp head)) (keywordp head))
+ (bytecomp--cus-warn type "irregular type `%S'" head))
+ )))
+ ((or (not (symbolp type)) (keywordp type))
+ (bytecomp--cus-warn type "irregular type `%S'" type))
+ ((memq type '( list cons group vector choice radio const other
+ function-item variable-item set repeat restricted-sexp))
+ (bytecomp--cus-warn type "`%s' without arguments" type))
+ ((memq type invalid-types)
+ (bytecomp--cus-warn type "`%s' is not a valid type" type))
+ )))
+
+;; Unified handler for multiple functions with similar arguments:
+;; (NAME SOMETHING DOC KEYWORD-ARGS...)
+(byte-defop-compiler-1 define-widget bytecomp--custom-declare)
+(byte-defop-compiler-1 custom-declare-group bytecomp--custom-declare)
+(byte-defop-compiler-1 custom-declare-face bytecomp--custom-declare)
+(byte-defop-compiler-1 custom-declare-variable bytecomp--custom-declare)
+(defun bytecomp--custom-declare (form)
+ (when (>= (length form) 4)
+ (let* ((name-arg (nth 1 form))
+ (name (and (eq (car-safe name-arg) 'quote)
+ (symbolp (nth 1 name-arg))
+ (nth 1 name-arg)))
+ (keyword-args (nthcdr 4 form))
+ (fun (car form))
+ (bytecomp--cus-function fun)
+ (bytecomp--cus-name name))
+
+ ;; Check :type
+ (when (memq fun '(custom-declare-variable define-widget))
+ (let ((type-tag (memq :type keyword-args)))
+ (if (null type-tag)
+ ;; :type only mandatory for `defcustom'
+ (when (eq fun 'custom-declare-variable)
+ (bytecomp--cus-warn form "missing :type keyword parameter"))
+ (let ((dup-type (memq :type (cdr type-tag))))
+ (when dup-type
+ (bytecomp--cus-warn
+ dup-type "duplicated :type keyword argument")))
+ (let ((type-arg (cadr type-tag)))
+ (when (or (null type-arg)
+ (eq (car-safe type-arg) 'quote))
+ (bytecomp--check-cus-type (cadr type-arg)))))))
+
+ ;; Check :group
+ (when (cond
+ ((memq fun '(custom-declare-variable custom-declare-face))
+ (not byte-compile-current-group))
+ ((eq fun 'custom-declare-group)
+ (not (eq name 'emacs))))
+ (unless (plist-get keyword-args :group)
+ (bytecomp--cus-warn form "fails to specify containing group")))
+
+ ;; Update current group
+ (when (and name
+ byte-compile-current-file ; only when compiling a whole file
+ (eq fun 'custom-declare-group))
+ (setq byte-compile-current-group name))))
+
+ (byte-compile-normal-call form))
+
+
(put 'function-put 'byte-hunk-handler 'byte-compile-define-symbol-prop)
(put 'define-symbol-prop 'byte-hunk-handler 'byte-compile-define-symbol-prop)
(defun byte-compile-define-symbol-prop (form)
diff --git a/lisp/emacs-lisp/cconv.el b/lisp/emacs-lisp/cconv.el
index 3e75020a013..e210cfdf5ce 100644
--- a/lisp/emacs-lisp/cconv.el
+++ b/lisp/emacs-lisp/cconv.el
@@ -1,6 +1,6 @@
;;; cconv.el --- Closure conversion for statically scoped Emacs Lisp. -*- lexical-binding: t -*-
-;; Copyright (C) 2011-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2011-2024 Free Software Foundation, Inc.
;; Author: Igor Kuzmin <kzuminig@iro.umontreal.ca>
;; Maintainer: emacs-devel@gnu.org
@@ -328,300 +328,309 @@ places where they originally did not directly appear."
;; to find the number of a specific variable in the environment vector,
;; so we never touch it(unless we enter to the other closure).
;;(if (listp form) (print (car form)) form)
- (pcase form
- (`(,(and letsym (or 'let* 'let)) ,binders . ,body)
+ (macroexp--with-extended-form-stack form
+ (pcase form
+ (`(,(and letsym (or 'let* 'let)) ,binders . ,body)
; let and let* special forms
- (let ((binders-new '())
- (new-env env)
- (new-extend extend))
-
- (dolist (binder binders)
- (let* ((value nil)
- (var (if (not (consp binder))
- (prog1 binder (setq binder (list binder)))
- (when (cddr binder)
- (byte-compile-warn-x
- binder
- "Malformed `%S' binding: %S"
- letsym binder))
- (setq value (cadr binder))
- (car binder))))
- (cond
- ;; Ignore bindings without a valid name.
- ((not (symbolp var))
- (byte-compile-warn-x var "attempt to let-bind nonvariable `%S'" var))
- ((or (booleanp var) (keywordp var))
- (byte-compile-warn-x var "attempt to let-bind constant `%S'" var))
- (t
- (let ((new-val
- (pcase (cconv--var-classification binder form)
- ;; Check if var is a candidate for lambda lifting.
- ((and :lambda-candidate
- (guard
- (progn
- (cl-assert (and (eq (car value) 'function)
- (eq (car (cadr value)) 'lambda)))
- (cl-assert (equal (cddr (cadr value))
- (caar cconv-freevars-alist)))
- ;; Peek at the freevars to decide whether
- ;; to λ-lift.
- (let* ((fvs (cdr (car cconv-freevars-alist)))
- (fun (cadr value))
- (funargs (cadr fun))
- (funcvars (append fvs funargs)))
+ (let ((binders-new '())
+ (new-env env)
+ (new-extend extend))
+
+ (dolist (binder binders)
+ (let* ((value nil)
+ (var (if (not (consp binder))
+ (prog1 binder (setq binder (list binder)))
+ (when (cddr binder)
+ (byte-compile-warn-x
+ binder
+ "Malformed `%S' binding: %S"
+ letsym binder))
+ (setq value (cadr binder))
+ (car binder))))
+ (cond
+ ;; Ignore bindings without a valid name.
+ ((not (symbolp var))
+ (byte-compile-warn-x
+ var "attempt to let-bind nonvariable `%S'" var))
+ ((or (booleanp var) (keywordp var))
+ (byte-compile-warn-x
+ var "attempt to let-bind constant `%S'" var))
+ (t
+ (let ((new-val
+ (pcase (cconv--var-classification binder form)
+ ;; Check if var is a candidate for lambda lifting.
+ ((and :lambda-candidate
+ (guard
+ (progn
+ (cl-assert
+ (and (eq (car value) 'function)
+ (eq (car (cadr value)) 'lambda)))
+ (cl-assert (equal (cddr (cadr value))
+ (caar cconv-freevars-alist)))
+ ;; Peek at the freevars to decide whether
+ ;; to λ-lift.
+ (let* ((fvs (cdr (car cconv-freevars-alist)))
+ (fun (cadr value))
+ (funargs (cadr fun))
+ (funcvars (append fvs funargs)))
; lambda lifting condition
- (and fvs (>= cconv-liftwhen
- (length funcvars)))))))
+ (and fvs (>= cconv-liftwhen
+ (length funcvars)))))))
; Lift.
- (let* ((fvs (cdr (pop cconv-freevars-alist)))
- (fun (cadr value))
- (funargs (cadr fun))
- (funcvars (append fvs funargs))
- (funcbody (cddr fun))
- (funcbody-env ()))
- (push `(,var . (apply-partially ,var . ,fvs)) new-env)
- (dolist (fv fvs)
- (cl-pushnew fv new-extend)
- (if (and (eq 'car-safe (car-safe
- (cdr (assq fv env))))
- (not (memq fv funargs)))
- (push `(,fv . (car-safe ,fv)) funcbody-env)))
- `(function (lambda ,funcvars .
- ,(cconv--convert-funcbody
- funargs funcbody funcbody-env value)))))
-
- ;; Check if it needs to be turned into a "ref-cell".
- (:captured+mutated
- ;; Declared variable is mutated and captured.
- (push `(,var . (car-safe ,var)) new-env)
- `(list ,(cconv-convert value env extend)))
-
- ;; Check if it needs to be turned into a "ref-cell".
- (:unused
- ;; Declared variable is unused.
- (if (assq var new-env)
- (push `(,var) new-env)) ;FIXME:Needed?
- (let* ((Ignore (if (symbol-with-pos-p var)
- (position-symbol 'ignore var)
- 'ignore))
- (newval `(,Ignore
- ,(cconv-convert value env extend)))
- (msg (cconv--warn-unused-msg var "variable")))
- (if (null msg) newval
- (macroexp--warn-wrap var msg newval 'lexical))))
-
- ;; Normal default case.
- (_
- (if (assq var new-env) (push `(,var) new-env))
- (cconv-convert value env extend)))))
-
- (when (and (eq letsym 'let*) (memq var new-extend))
- ;; One of the lambda-lifted vars is shadowed, so add
- ;; a reference to the outside binding and arrange to use
- ;; that reference.
- (let ((var-def (cconv--lifted-arg var env))
- (closedsym (make-symbol (format "closed-%s" var))))
- (setq new-env (cconv--remap-llv new-env var closedsym))
- ;; FIXME: `closedsym' doesn't need to be added to `extend'
- ;; but adding it makes it easier to write the assertion at
- ;; the beginning of this function.
- (setq new-extend (cons closedsym (remq var new-extend)))
- (push `(,closedsym ,var-def) binders-new)))
-
- ;; We push the element after redefined free variables are
- ;; processed. This is important to avoid the bug when free
- ;; variable and the function have the same name.
- (push (list var new-val) binders-new)
-
- (when (eq letsym 'let*)
- (setq env new-env)
- (setq extend new-extend))))))
- ) ; end of dolist over binders
-
- (when (not (eq letsym 'let*))
- ;; We can't do the cconv--remap-llv at the same place for let and
- ;; let* because in the case of `let', the shadowing may occur
- ;; before we know that the var will be in `new-extend' (bug#24171).
- (dolist (binder binders-new)
- (when (memq (car-safe binder) new-extend)
- ;; One of the lambda-lifted vars is shadowed.
- (let* ((var (car-safe binder))
- (var-def (cconv--lifted-arg var env))
- (closedsym (make-symbol (format "closed-%s" var))))
- (setq new-env (cconv--remap-llv new-env var closedsym))
- (setq new-extend (cons closedsym (remq var new-extend)))
- (push `(,closedsym ,var-def) binders-new)))))
-
- `(,letsym ,(nreverse binders-new)
- . ,(mapcar (lambda (form)
- (cconv-convert
- form new-env new-extend))
- body))))
+ (let* ((fvs (cdr (pop cconv-freevars-alist)))
+ (fun (cadr value))
+ (funargs (cadr fun))
+ (funcvars (append fvs funargs))
+ (funcbody (cddr fun))
+ (funcbody-env ()))
+ (push `(,var . (apply-partially ,var . ,fvs))
+ new-env)
+ (dolist (fv fvs)
+ (cl-pushnew fv new-extend)
+ (if (and (eq 'car-safe (car-safe
+ (cdr (assq fv env))))
+ (not (memq fv funargs)))
+ (push `(,fv . (car-safe ,fv)) funcbody-env)))
+ `(function
+ (lambda ,funcvars
+ . ,(cconv--convert-funcbody
+ funargs funcbody funcbody-env value)))))
+
+ ;; Check if it needs to be turned into a "ref-cell".
+ (:captured+mutated
+ ;; Declared variable is mutated and captured.
+ (push `(,var . (car-safe ,var)) new-env)
+ `(list ,(cconv-convert value env extend)))
+
+ ;; Check if it needs to be turned into a "ref-cell".
+ (:unused
+ ;; Declared variable is unused.
+ (if (assq var new-env)
+ (push `(,var) new-env)) ;FIXME:Needed?
+ (let* ((Ignore (if (symbol-with-pos-p var)
+ (position-symbol 'ignore var)
+ 'ignore))
+ (newval `(,Ignore
+ ,(cconv-convert value env extend)))
+ (msg (cconv--warn-unused-msg var "variable")))
+ (if (null msg) newval
+ (macroexp--warn-wrap var msg newval 'lexical))))
+
+ ;; Normal default case.
+ (_
+ (if (assq var new-env) (push `(,var) new-env))
+ (cconv-convert value env extend)))))
+
+ (when (and (eq letsym 'let*) (memq var new-extend))
+ ;; One of the lambda-lifted vars is shadowed, so add
+ ;; a reference to the outside binding and arrange to use
+ ;; that reference.
+ (let ((var-def (cconv--lifted-arg var env))
+ (closedsym (make-symbol (format "closed-%s" var))))
+ (setq new-env (cconv--remap-llv new-env var closedsym))
+ ;; FIXME: `closedsym' doesn't need to be added to `extend'
+ ;; but adding it makes it easier to write the assertion at
+ ;; the beginning of this function.
+ (setq new-extend (cons closedsym (remq var new-extend)))
+ (push `(,closedsym ,var-def) binders-new)))
+
+ ;; We push the element after redefined free variables are
+ ;; processed. This is important to avoid the bug when free
+ ;; variable and the function have the same name.
+ (push (list var new-val) binders-new)
+
+ (when (eq letsym 'let*)
+ (setq env new-env)
+ (setq extend new-extend))))))
+ ) ; end of dolist over binders
+
+ (when (not (eq letsym 'let*))
+ ;; We can't do the cconv--remap-llv at the same place for let and
+ ;; let* because in the case of `let', the shadowing may occur
+ ;; before we know that the var will be in `new-extend' (bug#24171).
+ (dolist (binder binders-new)
+ (when (memq (car-safe binder) new-extend)
+ ;; One of the lambda-lifted vars is shadowed.
+ (let* ((var (car-safe binder))
+ (var-def (cconv--lifted-arg var env))
+ (closedsym (make-symbol (format "closed-%s" var))))
+ (setq new-env (cconv--remap-llv new-env var closedsym))
+ (setq new-extend (cons closedsym (remq var new-extend)))
+ (push `(,closedsym ,var-def) binders-new)))))
+
+ `(,letsym ,(nreverse binders-new)
+ . ,(mapcar (lambda (form)
+ (cconv-convert
+ form new-env new-extend))
+ body))))
;end of let let* forms
- ; first element is lambda expression
- (`(,(and `(lambda . ,_) fun) . ,args)
- ;; FIXME: it's silly to create a closure just to call it.
- ;; Running byte-optimize-form earlier would resolve this.
- `(funcall
- ,(cconv-convert `(function ,fun) env extend)
- ,@(mapcar (lambda (form)
- (cconv-convert form env extend))
- args)))
-
- (`(cond . ,cond-forms) ; cond special form
- `(,(car form) . ,(mapcar (lambda (branch)
- (mapcar (lambda (form)
- (cconv-convert form env extend))
- branch))
- cond-forms)))
-
- (`(function (lambda ,args . ,body) . ,rest)
- (let* ((docstring (if (eq :documentation (car-safe (car body)))
- (cconv-convert (cadr (pop body)) env extend)))
- (bf (if (stringp (car body)) (cdr body) body))
- (if (when (eq 'interactive (car-safe (car bf)))
- (gethash form cconv--interactive-form-funs)))
- (wrapped (pcase if (`#'(lambda (&rest _cconv--dummy) .,_) t) (_ nil)))
- (cif (when if (cconv-convert if env extend)))
- (cf nil))
- ;; TODO: Because we need to non-destructively modify body, this code
- ;; is particularly ugly. This should ideally be moved to
- ;; cconv--convert-function.
- (pcase cif
- ('nil (setq bf nil))
- (`#',f
- (pcase-let ((`((,f1 . (,_ . ,f2)) . ,f3) bf))
- (setq bf `((,f1 . (,(if wrapped (nth 2 f) cif) . ,f2)) . ,f3)))
- (setq cif nil))
- ;; The interactive form needs special treatment, so the form
- ;; inside the `interactive' won't be used any further.
- (_ (pcase-let ((`((,f1 . (,_ . ,f2)) . ,f3) bf))
- (setq bf `((,f1 . (nil . ,f2)) . ,f3)))))
- (when bf
- ;; If we modified bf, re-build body and form as
- ;; copies with the modified bits.
- (setq body (if (stringp (car body))
- (cons (car body) bf)
- bf)
- form `(function (lambda ,args . ,body) . ,rest))
- ;; Also, remove the current old entry on the alist, replacing
- ;; it with the new one.
- (let ((entry (pop cconv-freevars-alist)))
- (push (cons body (cdr entry)) cconv-freevars-alist)))
- (setq cf (cconv--convert-function args body env form docstring))
- (if (not cif)
- ;; Normal case, the interactive form needs no special treatment.
- cf
- `(cconv--interactive-helper
- ,cf ,(if wrapped cif `(list 'quote ,cif))))))
-
- (`(internal-make-closure . ,_)
- (byte-compile-report-error
- "Internal error in compiler: cconv called twice?"))
-
- (`(quote . ,_) form)
- (`(function . ,_) form)
+ ; first element is lambda expression
+ (`(,(and `(lambda . ,_) fun) . ,args)
+ ;; FIXME: it's silly to create a closure just to call it.
+ ;; Running byte-optimize-form earlier would resolve this.
+ `(funcall
+ ,(cconv-convert `(function ,fun) env extend)
+ ,@(mapcar (lambda (form)
+ (cconv-convert form env extend))
+ args)))
+
+ (`(cond . ,cond-forms) ; cond special form
+ `(,(car form) . ,(mapcar (lambda (branch)
+ (mapcar (lambda (form)
+ (cconv-convert form env extend))
+ branch))
+ cond-forms)))
+
+ (`(function (lambda ,args . ,body) . ,rest)
+ (let* ((docstring (if (eq :documentation (car-safe (car body)))
+ (cconv-convert (cadr (pop body)) env extend)))
+ (bf (if (stringp (car body)) (cdr body) body))
+ (if (when (eq 'interactive (car-safe (car bf)))
+ (gethash form cconv--interactive-form-funs)))
+ (wrapped (pcase if (`#'(lambda (&rest _cconv--dummy) .,_) t)))
+ (cif (when if (cconv-convert if env extend)))
+ (cf nil))
+ ;; TODO: Because we need to non-destructively modify body, this code
+ ;; is particularly ugly. This should ideally be moved to
+ ;; cconv--convert-function.
+ (pcase cif
+ ('nil (setq bf nil))
+ (`#',f
+ (pcase-let ((`((,f1 . (,_ . ,f2)) . ,f3) bf))
+ (setq bf `((,f1 . (,(if wrapped (nth 2 f) cif) . ,f2)) . ,f3)))
+ (setq cif nil))
+ ;; The interactive form needs special treatment, so the form
+ ;; inside the `interactive' won't be used any further.
+ (_ (pcase-let ((`((,f1 . (,_ . ,f2)) . ,f3) bf))
+ (setq bf `((,f1 . (nil . ,f2)) . ,f3)))))
+ (when bf
+ ;; If we modified bf, re-build body and form as
+ ;; copies with the modified bits.
+ (setq body (if (stringp (car body))
+ (cons (car body) bf)
+ bf)
+ form `(function (lambda ,args . ,body) . ,rest))
+ ;; Also, remove the current old entry on the alist, replacing
+ ;; it with the new one.
+ (let ((entry (pop cconv-freevars-alist)))
+ (push (cons body (cdr entry)) cconv-freevars-alist)))
+ (setq cf (cconv--convert-function args body env form docstring))
+ (if (not cif)
+ ;; Normal case, the interactive form needs no special treatment.
+ cf
+ `(cconv--interactive-helper
+ ,cf ,(if wrapped cif `(list 'quote ,cif))))))
+
+ (`(internal-make-closure . ,_)
+ (byte-compile-report-error
+ "Internal error in compiler: cconv called twice?"))
+
+ (`(quote . ,_) form)
+ (`(function . ,_) form)
;defconst, defvar
- (`(,(and sym (or 'defconst 'defvar)) ,definedsymbol . ,forms)
- `(,sym ,definedsymbol
- . ,(when (consp forms)
- (cons (cconv-convert (car forms) env extend)
- ;; The rest (i.e. docstring, of any) is not evaluated,
- ;; and may be an invalid expression (e.g. ($# . 678)).
- (cdr forms)))))
+ (`(,(and sym (or 'defconst 'defvar)) ,definedsymbol . ,forms)
+ `(,sym ,definedsymbol
+ . ,(when (consp forms)
+ (cons (cconv-convert (car forms) env extend)
+ ;; The rest (i.e. docstring, of any) is not evaluated,
+ ;; and may be an invalid expression (e.g. ($# . 678)).
+ (cdr forms)))))
; condition-case
- (`(condition-case ,var ,protected-form . ,handlers)
- (let* ((class (and var (cconv--var-classification (list var) form)))
- (newenv
- (cond ((eq class :captured+mutated)
- (cons `(,var . (car-safe ,var)) env))
- ((assq var env) (cons `(,var) env))
- (t env)))
- (msg (when (eq class :unused)
- (cconv--warn-unused-msg var "variable")))
- (newprotform (cconv-convert protected-form env extend)))
- `(,(car form) ,var
- ,(if msg
- (macroexp--warn-wrap var msg newprotform 'lexical)
- newprotform)
- ,@(mapcar
- (lambda (handler)
- `(,(car handler)
- ,@(let ((body
- (mapcar (lambda (form)
- (cconv-convert form newenv extend))
- (cdr handler))))
- (if (not (eq class :captured+mutated))
- body
- `((let ((,var (list ,var))) ,@body))))))
- handlers))))
-
- (`(unwind-protect ,form1 . ,body)
- `(,(car form) ,(cconv-convert form1 env extend)
- :fun-body ,(cconv--convert-function () body env form1)))
-
- (`(setq ,var ,expr)
- (let ((var-new (or (cdr (assq var env)) var))
- (value (cconv-convert expr env extend)))
- (pcase var-new
- ((pred symbolp) `(,(car form) ,var-new ,value))
- (`(car-safe ,iexp) `(setcar ,iexp ,value))
- ;; This "should never happen", but for variables which are
- ;; mutated+captured+unused, we may end up trying to `setq'
- ;; on a closed-over variable, so just drop the setq.
- (_ ;; (byte-compile-report-error
- ;; (format "Internal error in cconv of (setq %s ..)"
- ;; sym-new))
- value))))
-
- (`(,(and (or 'funcall 'apply) callsym) ,fun . ,args)
- ;; These are not special forms but we treat them separately for the needs
- ;; of lambda lifting.
- (let ((mapping (cdr (assq fun env))))
- (pcase mapping
- (`(apply-partially ,_ . ,(and fvs `(,_ . ,_)))
- (cl-assert (eq (cadr mapping) fun))
- `(,callsym ,fun
- ,@(mapcar (lambda (fv)
- (let ((exp (or (cdr (assq fv env)) fv)))
- (pcase exp
- (`(car-safe ,iexp . ,_) iexp)
- (_ exp))))
- fvs)
- ,@(mapcar (lambda (arg)
- (cconv-convert arg env extend))
- args)))
- (_ `(,callsym ,@(mapcar (lambda (arg)
+ (`(condition-case ,var ,protected-form . ,handlers)
+ (let* ((class (and var (cconv--var-classification (list var) form)))
+ (newenv
+ (cond ((eq class :captured+mutated)
+ (cons `(,var . (car-safe ,var)) env))
+ ((assq var env) (cons `(,var) env))
+ (t env)))
+ (msg (when (eq class :unused)
+ (cconv--warn-unused-msg var "variable")))
+ (newprotform (cconv-convert protected-form env extend)))
+ `(,(car form) ,var
+ ,(if msg
+ (macroexp--warn-wrap var msg newprotform 'lexical)
+ newprotform)
+ ,@(mapcar
+ (lambda (handler)
+ `(,(car handler)
+ ,@(let ((body
+ (mapcar (lambda (form)
+ (cconv-convert form newenv extend))
+ (cdr handler))))
+ (if (not (eq class :captured+mutated))
+ body
+ `((let ((,var (list ,var))) ,@body))))))
+ handlers))))
+
+ (`(unwind-protect ,form1 . ,body)
+ `(,(car form) ,(cconv-convert form1 env extend)
+ :fun-body ,(cconv--convert-function () body env form1)))
+
+ (`(setq ,var ,expr)
+ (let ((var-new (or (cdr (assq var env)) var))
+ (value (cconv-convert expr env extend)))
+ (pcase var-new
+ ((pred symbolp) `(,(car form) ,var-new ,value))
+ (`(car-safe ,iexp) `(setcar ,iexp ,value))
+ ;; This "should never happen", but for variables which are
+ ;; mutated+captured+unused, we may end up trying to `setq'
+ ;; on a closed-over variable, so just drop the setq.
+ (_ ;; (byte-compile-report-error
+ ;; (format "Internal error in cconv of (setq %s ..)"
+ ;; sym-new))
+ value))))
+
+ (`(,(and (or 'funcall 'apply) callsym) ,fun . ,args)
+ ;; These are not special forms but we treat them separately for the needs
+ ;; of lambda lifting.
+ (let ((mapping (cdr (assq fun env))))
+ (pcase mapping
+ (`(apply-partially ,_ . ,(and fvs `(,_ . ,_)))
+ (cl-assert (eq (cadr mapping) fun))
+ `(,callsym ,fun
+ ,@(mapcar (lambda (fv)
+ (let ((exp (or (cdr (assq fv env)) fv)))
+ (pcase exp
+ (`(car-safe ,iexp . ,_) iexp)
+ (_ exp))))
+ fvs)
+ ,@(mapcar (lambda (arg)
(cconv-convert arg env extend))
- (cons fun args)))))))
-
- ;; The form (if any) is converted beforehand as part of the `lambda' case.
- (`(interactive . ,_) form)
-
- ;; `declare' should now be macro-expanded away (and if they're not, we're
- ;; in trouble because they *can* contain code nowadays).
- ;; (`(declare . ,_) form) ;The args don't contain code.
-
- (`(oclosure--fix-type (ignore . ,vars) ,exp)
- (dolist (var vars)
- (let ((x (assq var env)))
- (pcase (cdr x)
- (`(car-safe . ,_) (error "Slot %S should not be mutated" var))
- (_ (cl-assert (null (cdr x)))))))
- (cconv-convert exp env extend))
-
- (`(,func . ,forms)
- ;; First element is function or whatever function-like forms are: or, and,
- ;; if, catch, progn, prog1, while, until
- `(,func . ,(mapcar (lambda (form)
- (cconv-convert form env extend))
- forms)))
-
- (_ (or (cdr (assq form env)) form))))
+ args)))
+ (_ `(,callsym ,@(mapcar (lambda (arg)
+ (cconv-convert arg env extend))
+ (cons fun args)))))))
+
+ ;; The form (if any) is converted beforehand as part of the `lambda' case.
+ (`(interactive . ,_) form)
+
+ ;; `declare' should now be macro-expanded away (and if they're not, we're
+ ;; in trouble because they *can* contain code nowadays).
+ ;; (`(declare . ,_) form) ;The args don't contain code.
+
+ (`(oclosure--fix-type (ignore . ,vars) ,exp)
+ (dolist (var vars)
+ (let ((x (assq var env)))
+ (pcase (cdr x)
+ (`(car-safe . ,_) (error "Slot %S should not be mutated" var))
+ (_ (cl-assert (null (cdr x)))))))
+ (cconv-convert exp env extend))
+
+ (`(,func . ,forms)
+ (if (symbolp func)
+ ;; First element is function or whatever function-like forms are:
+ ;; or, and, if, catch, progn, prog1, while, until
+ `(,func . ,(mapcar (lambda (form)
+ (cconv-convert form env extend))
+ forms))
+ (byte-compile-warn-x form "Malformed function `%S'" func)
+ nil))
+
+ (_ (or (cdr (assq form env)) form)))))
(defvar byte-compile-lexical-variables)
diff --git a/lisp/emacs-lisp/chart.el b/lisp/emacs-lisp/chart.el
index 2d4f10123d1..da61e45213d 100644
--- a/lisp/emacs-lisp/chart.el
+++ b/lisp/emacs-lisp/chart.el
@@ -1,6 +1,6 @@
;;; chart.el --- Draw charts (bar charts, etc) -*- lexical-binding: t -*-
-;; Copyright (C) 1996-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
;; Old-Version: 0.2
diff --git a/lisp/emacs-lisp/check-declare.el b/lisp/emacs-lisp/check-declare.el
index c887d95210c..0362c7d2c24 100644
--- a/lisp/emacs-lisp/check-declare.el
+++ b/lisp/emacs-lisp/check-declare.el
@@ -1,6 +1,6 @@
;;; check-declare.el --- Check declare-function statements -*- lexical-binding: t; -*-
-;; Copyright (C) 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2024 Free Software Foundation, Inc.
;; Author: Glenn Morris <rgm@gnu.org>
;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/emacs-lisp/checkdoc.el b/lisp/emacs-lisp/checkdoc.el
index aadd6480086..80eaf93c3b7 100644
--- a/lisp/emacs-lisp/checkdoc.el
+++ b/lisp/emacs-lisp/checkdoc.el
@@ -1,6 +1,6 @@
;;; checkdoc.el --- check documentation strings for style requirements -*- lexical-binding:t -*-
-;; Copyright (C) 1997-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
;; Old-Version: 0.6.2
@@ -1611,8 +1611,11 @@ may require more formatting")
(let ((f nil) (m nil) (start (point))
;; Ignore the "A-" modifier: it is uncommon in practice,
;; and leads to false positives in regexp ranges.
- (re "[^`‘A-Za-z0-9_]\\([CMs]-[a-zA-Z]\\|\\(\\([CMs]-\\)?\
-mouse-[0-3]\\)\\)\\>"))
+ (re (rx (not (any "0-9A-Za-z_`‘-"))
+ (group (or (seq (any "CMs") "-" (any "A-Za-z"))
+ (group (opt (group (any "CMs") "-"))
+ "mouse-" (any "0-3"))))
+ eow)))
;; Find the first key sequence not in a sample
(while (and (not f) (setq m (re-search-forward re e t)))
(setq f (not (checkdoc-in-sample-code-p start e))))
@@ -1779,7 +1782,7 @@ function,command,variable,option or symbol." ms1))))))
(order (and (nth 3 fp) (car (nth 3 fp))))
(nocheck (append '("&optional" "&rest" "&key" "&aux"
"&context" "&environment" "&whole"
- "&body" "&allow-other-keys")
+ "&body" "&allow-other-keys" "nil")
(nth 3 fp)))
(inopts nil))
(while (and args found (> found last-pos))
@@ -2042,8 +2045,7 @@ from the comment."
(condition-case nil
(setq lst (read (current-buffer)))
(error (setq lst nil))) ; error in text
- (if (not (listp lst)) ; not a list of args
- (setq lst (list lst)))
+ (setq lst (ensure-list lst))
(if (and lst (not (symbolp (car lst)))) ;weird arg
(setq lst nil))
(while lst
@@ -2546,11 +2548,11 @@ Argument END is the maximum bounds to search in."
(rx "("
(* (syntax whitespace))
(group
- (or (seq (* (group (or wordchar (syntax symbol))))
+ (or (seq (* (or wordchar (syntax symbol)))
"error")
- (seq (* (group (or wordchar (syntax symbol))))
+ (seq (* (or wordchar (syntax symbol)))
(or "y-or-n-p" "yes-or-no-p")
- (? (group "-with-timeout")))
+ (? "-with-timeout"))
"checkdoc-autofix-ask-replace"))
(+ (any "\n\t ")))
end t))
diff --git a/lisp/emacs-lisp/cl-extra.el b/lisp/emacs-lisp/cl-extra.el
index a89bbc3a748..9281cd9821e 100644
--- a/lisp/emacs-lisp/cl-extra.el
+++ b/lisp/emacs-lisp/cl-extra.el
@@ -1,6 +1,6 @@
;;; cl-extra.el --- Common Lisp features, part 2 -*- lexical-binding: t -*-
-;; Copyright (C) 1993, 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1993, 2000-2024 Free Software Foundation, Inc.
;; Author: Dave Gillespie <daveg@synaptics.com>
;; Keywords: extensions
@@ -441,7 +441,10 @@ as an integer unless JUNK-ALLOWED is non-nil."
;; Random numbers.
(defun cl--random-time ()
- (car (time-convert nil t)))
+ "Return high-precision timestamp from `time-convert'.
+
+For example, suitable for use as seed by `cl-make-random-state'."
+ (car (time-convert nil t)))
;;;###autoload (autoload 'cl-random-state-p "cl-extra")
(cl-defstruct (cl--random-state
@@ -635,13 +638,12 @@ PROPLIST is a list of the sort returned by `symbol-plist'.
(and (cdr p) (progn (setcdr p (cdr (cdr (cdr p)))) t))))
;;;###autoload
-(defun cl-remprop (sym tag)
- "Remove from SYMBOL's plist the property PROPNAME and its value.
-\n(fn SYMBOL PROPNAME)"
- (let ((plist (symbol-plist sym)))
- (if (and plist (eq tag (car plist)))
- (progn (setplist sym (cdr (cdr plist))) t)
- (cl--do-remf plist tag))))
+(defun cl-remprop (symbol propname)
+ "Remove from SYMBOL's plist the property PROPNAME and its value."
+ (let ((plist (symbol-plist symbol)))
+ (if (and plist (eq propname (car plist)))
+ (progn (setplist symbol (cdr (cdr plist))) t)
+ (cl--do-remf plist propname))))
;;; Streams.
@@ -735,7 +737,11 @@ PROPLIST is a list of the sort returned by `symbol-plist'.
(declare-function help-fns-short-filename "help-fns" (filename))
;;;###autoload
-(defun cl-find-class (type) (cl--find-class type))
+(defun cl-find-class (type)
+ "Return CL class of TYPE.
+
+Call `cl--find-class' to get TYPE's propname `cl--class'"
+ (cl--find-class type))
;;;###autoload
(defun cl-describe-type (type)
@@ -872,7 +878,7 @@ PROPLIST is a list of the sort returned by `symbol-plist'.
"%s")
formats)
(cl-incf col (+ col-space (aref cols i))))
- (let ((format (mapconcat #'identity (nreverse formats) "")))
+ (let ((format (mapconcat #'identity (nreverse formats))))
(insert (apply #'format format
(mapcar (lambda (str) (propertize str 'face 'italic))
header))
diff --git a/lisp/emacs-lisp/cl-generic.el b/lisp/emacs-lisp/cl-generic.el
index dec14bd5df6..48f5c06e390 100644
--- a/lisp/emacs-lisp/cl-generic.el
+++ b/lisp/emacs-lisp/cl-generic.el
@@ -1,6 +1,6 @@
;;; cl-generic.el --- CLOS-style generic functions for Elisp -*- lexical-binding: t; -*-
-;; Copyright (C) 2015-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2024 Free Software Foundation, Inc.
;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
;; Version: 1.0
@@ -272,7 +272,7 @@ DEFAULT-BODY, if present, is used as the body of a default method.
(list
(macroexp-warn-and-return
(format "Non-symbol arguments to cl-defgeneric: %s"
- (mapconcat #'prin1-to-string nonsymargs ""))
+ (mapconcat #'prin1-to-string nonsymargs " "))
nil nil nil nonsymargs)))))
next-head)
(while (progn (setq next-head (car-safe (car options-and-methods)))
@@ -1379,6 +1379,7 @@ See the full list and their hierarchy in `cl--typeof-types'."
(cl--generic-prefill-dispatchers 0 integer)
(cl--generic-prefill-dispatchers 1 integer)
(cl--generic-prefill-dispatchers 0 cl--generic-generalizer integer)
+(cl--generic-prefill-dispatchers 0 (eql 'x) integer)
;;; Dispatch on major mode.
@@ -1391,11 +1392,8 @@ See the full list and their hierarchy in `cl--typeof-types'."
(defun cl--generic-derived-specializers (mode &rest _)
;; FIXME: Handle (derived-mode <mode1> ... <modeN>)
- (let ((specializers ()))
- (while mode
- (push `(derived-mode ,mode) specializers)
- (setq mode (get mode 'derived-mode-parent)))
- (nreverse specializers)))
+ (mapcar (lambda (mode) `(derived-mode ,mode))
+ (derived-mode-all-parents mode)))
(cl-generic-define-generalizer cl--generic-derived-generalizer
90 (lambda (name) `(and (symbolp ,name) (functionp ,name) ,name))
diff --git a/lisp/emacs-lisp/cl-indent.el b/lisp/emacs-lisp/cl-indent.el
index ee50f572157..f3d076772e3 100644
--- a/lisp/emacs-lisp/cl-indent.el
+++ b/lisp/emacs-lisp/cl-indent.el
@@ -1,6 +1,6 @@
;;; cl-indent.el --- Enhanced lisp-indent mode -*- lexical-binding:t -*-
-;; Copyright (C) 1987, 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1987, 2000-2024 Free Software Foundation, Inc.
;; Author: Richard Mlynarik <mly@eddie.mit.edu>
;; Created: July 1987
diff --git a/lisp/emacs-lisp/cl-lib.el b/lisp/emacs-lisp/cl-lib.el
index 7fee780a735..108dcd31f48 100644
--- a/lisp/emacs-lisp/cl-lib.el
+++ b/lisp/emacs-lisp/cl-lib.el
@@ -1,6 +1,6 @@
;;; cl-lib.el --- Common Lisp extensions for Emacs -*- lexical-binding: t -*-
-;; Copyright (C) 1993, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1993, 2001-2024 Free Software Foundation, Inc.
;; Author: Dave Gillespie <daveg@synaptics.com>
;; Version: 1.0
@@ -157,6 +157,7 @@ to an element already in the list stored in PLACE.
`(cl-callf2 cl-adjoin ,x ,place ,@keys)))
(defun cl--set-buffer-substring (start end val)
+ "Delete region from START to END and insert VAL."
(save-excursion (delete-region start end)
(goto-char start)
(insert val)
@@ -170,6 +171,17 @@ to an element already in the list stored in PLACE.
val
(and (< end (length str)) (substring str end))))
+(gv-define-expander substring
+ (lambda (do place from &optional to)
+ (gv-letplace (getter setter) place
+ (macroexp-let2* nil ((start from) (end to))
+ (funcall do `(substring ,getter ,start ,end)
+ (lambda (v)
+ (macroexp-let2 nil v v
+ `(progn
+ ,(funcall setter `(cl--set-substring
+ ,getter ,start ,end ,v))
+ ,v))))))))
;;; Blocks and exits.
@@ -183,6 +195,8 @@ to an element already in the list stored in PLACE.
;; the target form to return the values as a list.
(defun cl--defalias (cl-f el-f &optional doc)
+ "Define function CL-F as definition EL-F.
+Like `defalias' but marks the alias itself as inlinable."
(defalias cl-f el-f doc)
(put cl-f 'byte-optimizer 'byte-compile-inline-expand))
@@ -522,7 +536,12 @@ If ALIST is non-nil, the new pairs are prepended to it."
(unless (load "cl-loaddefs" 'noerror 'quiet)
;; When bootstrapping, cl-loaddefs hasn't been built yet!
(require 'cl-macs)
- (require 'cl-seq))
+ (require 'cl-seq)
+ ;; FIXME: Arguably we should also load `cl-extra', except that this
+ ;; currently causes more bootstrap troubles, and `cl-extra' is
+ ;; rarely used, so instead we explicitly (require 'cl-extra) at
+ ;; those rare places where we do need it.
+ )
(defun cl--old-struct-type-of (orig-fun object)
(or (and (vectorp object) (> (length object) 0)
@@ -560,6 +579,7 @@ of record objects."
(advice-add 'type-of :around #'cl--old-struct-type-of))
(t
(advice-remove 'type-of #'cl--old-struct-type-of))))
+(make-obsolete 'cl-old-struct-compat-mode nil "30.1")
(defun cl-constantly (value)
"Return a function that takes any number of arguments, but returns VALUE."
diff --git a/lisp/emacs-lisp/cl-macs.el b/lisp/emacs-lisp/cl-macs.el
index 254a10781fe..88447203a64 100644
--- a/lisp/emacs-lisp/cl-macs.el
+++ b/lisp/emacs-lisp/cl-macs.el
@@ -1,6 +1,6 @@
;;; cl-macs.el --- Common Lisp macros -*- lexical-binding: t -*-
-;; Copyright (C) 1993, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1993, 2001-2024 Free Software Foundation, Inc.
;; Author: Dave Gillespie <daveg@synaptics.com>
;; Old-Version: 2.02
@@ -101,6 +101,7 @@
(and (> size 0) (1- size))))
(defun cl--simple-exprs-p (xs)
+ "Map `cl--simple-expr-p' to each element of list XS."
(while (and xs (cl--simple-expr-p (car xs)))
(setq xs (cdr xs)))
(not xs))
@@ -116,8 +117,10 @@
(while (and (setq x (cdr x)) (cl--safe-expr-p (car x))))
(null x)))))
-;;; Check if constant (i.e., no side effects or dependencies).
(defun cl--const-expr-p (x)
+ "Check if X is constant (i.e., no side effects or dependencies).
+
+See `macroexp-const-p' for similar functionality without cl-lib dependency."
(cond ((consp x)
(or (eq (car x) 'quote)
(and (memq (car x) '(function cl-function))
@@ -1465,6 +1468,7 @@ For more details, see Info node `(cl)Loop Facility'.
(t (setq buf (cl--pop2 cl--loop-args)))))
(if (and (consp var) (symbolp (car var)) (symbolp (cdr var)))
(setq var1 (car var) var2 (cdr var))
+ (push (list var nil) loop-for-bindings)
(push (list var `(cons ,var1 ,var2)) loop-for-sets))
(cl--loop-set-iterator-function
'intervals (lambda (body)
@@ -2075,22 +2079,20 @@ info node `(cl) Function Bindings' for details.
\(fn ((FUNC ARGLIST BODY...) ...) FORM...)"
(declare (indent 1)
- (debug ((&rest [&or
- ;; This spec must come first so that a
- ;; binding of the form (FN FORM) is always
- ;; interpreted as FORM being a form
- ;; returning a function, instead of FORM
- ;; being a cl-lambda-list and FN returning
- ;; nil.
- (&define [&name symbolp "@cl-flet@"]
- [&name [] gensym] ;Make it unique!
- def-form)
- (&define [&name symbolp "@cl-flet@"]
- [&name [] gensym] ;Make it unique!
- cl-lambda-list
- cl-declarations-or-string
- [&optional ("interactive" interactive)]
- def-body)])
+ ;; The first (symbolp form) case doesn't use `&name' because
+ ;; it's hard to associate this name with the body of the function
+ ;; that `form' will return (bug#65344).
+ ;; We could try and use a `&name' for those cases where the
+ ;; body of the function can be found, (e.g. the form wraps
+ ;; some `prog1/progn/let' around the final `lambda'), but it's
+ ;; not clear it's worth the trouble.
+ (debug ((&rest [&or (symbolp form)
+ (&define [&name symbolp "@cl-flet@"]
+ [&name [] gensym] ;Make it unique!
+ cl-lambda-list
+ cl-declarations-or-string
+ [&optional ("interactive" interactive)]
+ def-body)])
cl-declarations body)))
(let ((binds ()) (newenv macroexpand-all-environment))
(dolist (binding bindings)
@@ -2932,7 +2934,14 @@ The function's arguments should be treated as immutable.
,(if (memq '&key args)
`(&whole cl-whole &cl-quote ,@args)
(cons '&cl-quote args))
- ,(format "compiler-macro for inlining `%s'." name)
+ ;; NB. This will produce incorrect results in some
+ ;; cases, as our coding conventions says that the first
+ ;; line must be a full sentence. However, if we don't
+ ;; word wrap we will have byte-compiler warnings about
+ ;; overly long docstrings. So we can't have a perfect
+ ;; result here, and choose to avoid the byte-compiler
+ ;; warnings.
+ ,(internal--format-docstring-line "compiler-macro for `%s'." name)
(cl--defsubst-expand
',argns '(cl-block ,name ,@(cdr (macroexp-parse-body body)))
nil
@@ -3086,7 +3095,11 @@ To see the documentation for a defined struct type, use
descs)))
(t
(error "Structure option %s unrecognized" opt)))))
- (unless (or include-name type)
+ (unless (or include-name type
+ ;; Don't create a bogus parent to `cl-structure-object'
+ ;; while compiling the (cl-defstruct cl-structure-object ..)
+ ;; in `cl-preloaded.el'.
+ (eq name cl--struct-default-parent))
(setq include-name cl--struct-default-parent))
(when include-name (setq include (cl--struct-get-class include-name)))
(if print-func
@@ -3181,18 +3194,30 @@ To see the documentation for a defined struct type, use
;; The arg "cl-x" is referenced by name in e.g. pred-form
;; and pred-check, so changing it is not straightforward.
(push `(,defsym ,accessor (cl-x)
- ,(concat
- ;; NB. This will produce incorrect results
- ;; in some cases, as our coding conventions
- ;; says that the first line must be a full
- ;; sentence. However, if we don't word wrap
- ;; we will have byte-compiler warnings about
- ;; overly long docstrings. So we can't have
- ;; a perfect result here, and choose to avoid
- ;; the byte-compiler warnings.
- (internal--format-docstring-line
- "Access slot \"%s\" of `%s' struct CL-X." slot name)
- (if doc (concat "\n" doc) ""))
+ ,(let ((long-docstring
+ (format "Access slot \"%s\" of `%s' struct CL-X." slot name)))
+ (concat
+ ;; NB. This will produce incorrect results
+ ;; in some cases, as our coding conventions
+ ;; says that the first line must be a full
+ ;; sentence. However, if we don't word
+ ;; wrap we will have byte-compiler warnings
+ ;; about overly long docstrings. So we
+ ;; can't have a perfect result here, and
+ ;; choose to avoid the byte-compiler
+ ;; warnings.
+ (if (>= (length long-docstring)
+ (or (bound-and-true-p
+ byte-compile-docstring-max-column)
+ 80))
+ (concat
+ (internal--format-docstring-line
+ "Access slot \"%s\" of CL-X." slot)
+ "\n"
+ (internal--format-docstring-line
+ "Struct CL-X is a `%s'." name))
+ (internal--format-docstring-line long-docstring))
+ (if doc (concat "\n" doc) "")))
(declare (side-effect-free t))
,access-body)
forms)
@@ -3268,7 +3293,16 @@ To see the documentation for a defined struct type, use
(push `(,cldefsym ,cname
(&cl-defs (nil ,@descs) ,@args)
,(if (stringp doc) doc
- (format "Constructor for objects of type `%s'." name))
+ ;; NB. This will produce incorrect results in
+ ;; some cases, as our coding conventions says that
+ ;; the first line must be a full sentence.
+ ;; However, if we don't word wrap we will have
+ ;; byte-compiler warnings about overly long
+ ;; docstrings. So we can't have a perfect result
+ ;; here, and choose to avoid the byte-compiler
+ ;; warnings.
+ (internal--format-docstring-line
+ "Constructor for objects of type `%s'." name))
,@(if (cl--safe-expr-p `(progn ,@(mapcar #'cl-second descs)))
'((declare (side-effect-free t))))
(,con-fun ,@make))
@@ -3303,19 +3337,6 @@ To see the documentation for a defined struct type, use
;;; Add cl-struct support to pcase
-;;In use by comp.el
-(defun cl--struct-all-parents (class)
- (when (cl--struct-class-p class)
- (let ((res ())
- (classes (list class)))
- ;; BFS precedence.
- (while (let ((class (pop classes)))
- (push class res)
- (setq classes
- (append classes
- (cl--class-parents class)))))
- (nreverse res))))
-
;;;###autoload
(pcase-defmacro cl-struct (type &rest fields)
"Pcase patterns that match cl-struct EXPVAL of type TYPE.
@@ -3361,8 +3382,8 @@ the form NAME which is a shorthand for (NAME NAME)."
(let ((c1 (cl--find-class t1))
(c2 (cl--find-class t2)))
(and c1 c2
- (not (or (memq c1 (cl--struct-all-parents c2))
- (memq c2 (cl--struct-all-parents c1)))))))
+ (not (or (memq t1 (cl--class-allparents c2))
+ (memq t2 (cl--class-allparents c1)))))))
(let ((c1 (and (symbolp t1) (cl--find-class t1))))
(and c1 (cl--struct-class-p c1)
(funcall orig (cl--defstruct-predicate t1)
@@ -3475,7 +3496,8 @@ Of course, we really can't know that for sure, so it's just a heuristic."
(symbol . symbolp)
(vector . vectorp)
(window . windowp)
- ;; FIXME: Do we really want to consider this a type?
+ ;; FIXME: Do we really want to consider these types?
+ (number-or-marker . number-or-marker-p)
(integer-or-marker . integer-or-marker-p)
))
(put type 'cl-deftype-satisfies pred))
@@ -3594,7 +3616,8 @@ possible. Unlike regular macros, BODY can decide to \"punt\" and leave the
original function call alone by declaring an initial `&whole foo' parameter
and then returning foo."
;; Like `cl-defmacro', but with the `&whole' special case.
- (declare (debug (&define name cl-macro-list
+ (declare (debug (&define [&name symbolp "@cl-compiler-macro"]
+ cl-macro-list
cl-declarations-or-string def-body))
(indent 2))
(let ((p args) (res nil))
@@ -3699,7 +3722,7 @@ macro that returns its `&whole' argument."
;;; Things that are inline.
(cl-proclaim '(inline cl-acons cl-map cl-notany cl-notevery cl-revappend
- cl-nreconc gethash))
+ cl-nreconc))
;;; Things that are side-effect-free.
(mapc (lambda (x) (function-put x 'side-effect-free t))
@@ -3716,7 +3739,7 @@ macro that returns its `&whole' argument."
(mapc (lambda (x) (function-put x 'important-return-value t))
'(
;; Functions that are side-effect-free except for the
- ;; behaviour of functions passed as argument.
+ ;; behavior of functions passed as argument.
cl-mapcar cl-mapcan cl-maplist cl-map cl-mapcon
cl-reduce
cl-assoc cl-assoc-if cl-assoc-if-not
diff --git a/lisp/emacs-lisp/cl-preloaded.el b/lisp/emacs-lisp/cl-preloaded.el
index f410270d340..20e68555578 100644
--- a/lisp/emacs-lisp/cl-preloaded.el
+++ b/lisp/emacs-lisp/cl-preloaded.el
@@ -1,6 +1,6 @@
;;; cl-preloaded.el --- Preloaded part of the CL library -*- lexical-binding: t; -*-
-;; Copyright (C) 2015-2023 Free Software Foundation, Inc
+;; Copyright (C) 2015-2024 Free Software Foundation, Inc
;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
;; Package: emacs
@@ -52,20 +52,20 @@
(defconst cl--typeof-types
;; Hand made from the source code of `type-of'.
- '((integer number number-or-marker atom)
+ '((integer number integer-or-marker number-or-marker atom)
(symbol-with-pos symbol atom) (symbol atom) (string array sequence atom)
(cons list sequence)
;; Markers aren't `numberp', yet they are accepted wherever integers are
;; accepted, pretty much.
- (marker number-or-marker atom)
- (overlay atom) (float number atom) (window-configuration atom)
- (process atom) (window atom)
+ (marker integer-or-marker number-or-marker atom)
+ (overlay atom) (float number number-or-marker atom)
+ (window-configuration atom) (process atom) (window atom)
;; FIXME: We'd want to put `function' here, but that's only true
;; for those `subr's which aren't special forms!
(subr atom)
;; FIXME: We should probably reverse the order between
;; `compiled-function' and `byte-code-function' since arguably
- ;; `subr' and also "compiled functions" but not "byte code functions",
+ ;; `subr' is also "compiled functions" but not "byte code functions",
;; but it would require changing the value returned by `type-of' for
;; byte code objects, which risks breaking existing code, which doesn't
;; seem worth the trouble.
@@ -159,7 +159,9 @@ supertypes from the most specific to least specific.")
(cl-check-type name (satisfies cl--struct-name-p))
(unless type
;; Legacy defstruct, using tagged vectors. Enable backward compatibility.
- (cl-old-struct-compat-mode 1))
+ (with-suppressed-warnings ((obsolete cl-old-struct-compat-mode))
+ (message "cl-old-struct-compat-mode is obsolete!")
+ (cl-old-struct-compat-mode 1)))
(if (eq type 'record)
;; Defstruct using record objects.
(setq type nil))
@@ -321,15 +323,12 @@ supertypes from the most specific to least specific.")
(cl-assert (cl--class-p (cl--find-class 'cl-structure-object)))
(defun cl--class-allparents (class)
- (let ((parents ())
- (classes (list class)))
- ;; BFS precedence. FIXME: Use a topological sort.
- (while (let ((class (pop classes)))
- (cl-pushnew (cl--class-name class) parents)
- (setq classes
- (append classes
- (cl--class-parents class)))))
- (nreverse parents)))
+ (cons (cl--class-name class)
+ (merge-ordered-lists (mapcar #'cl--class-allparents
+ (cl--class-parents class)))))
+
+(eval-and-compile
+ (cl-assert (null (cl--class-parents (cl--find-class 'cl-structure-object)))))
;; Make sure functions defined with cl-defsubst can be inlined even in
;; packages which do not require CL. We don't put an autoload cookie
diff --git a/lisp/emacs-lisp/cl-print.el b/lisp/emacs-lisp/cl-print.el
index 71929caabb8..c35353ec3d0 100644
--- a/lisp/emacs-lisp/cl-print.el
+++ b/lisp/emacs-lisp/cl-print.el
@@ -1,6 +1,6 @@
;;; cl-print.el --- CL-style generic printing -*- lexical-binding: t; -*-
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
;; Keywords:
@@ -165,6 +165,7 @@ Print the contents hidden by the ellipsis to STREAM."
(defvar cl-print-compiled nil
"Control how to print byte-compiled functions.
Acceptable values include:
+- `raw' to print out the full contents of the function using `prin1'.
- `static' to print the vector of constants.
- `disassemble' to print the disassembly of the code.
- nil to skip printing any details about the code.")
@@ -187,42 +188,54 @@ into a button whose action shows the function's disassembly.")
(if args
(prin1 args stream)
(princ "()" stream)))
- (pcase (help-split-fundoc (documentation object 'raw) object)
- ;; Drop args which `help-function-arglist' already printed.
- (`(,_usage . ,(and doc (guard (stringp doc))))
- (princ " " stream)
- (prin1 doc stream)))
- (let ((inter (interactive-form object)))
- (when inter
- (princ " " stream)
- (cl-print-object
- (if (eq 'byte-code (car-safe (cadr inter)))
- `(interactive ,(make-byte-code nil (nth 1 (cadr inter))
- (nth 2 (cadr inter))
- (nth 3 (cadr inter))))
- inter)
- stream)))
- (if (eq cl-print-compiled 'disassemble)
- (princ
- (with-temp-buffer
- (insert "\n")
- (disassemble-1 object 0)
- (buffer-string))
- stream)
- (princ " " stream)
- (let ((button-start (and cl-print-compiled-button
- (bufferp stream)
- (with-current-buffer stream (point)))))
- (princ (format "#<bytecode %#x>" (sxhash object)) stream)
- (when (eq cl-print-compiled 'static)
+ (if (eq cl-print-compiled 'raw)
+ (let ((button-start
+ (and cl-print-compiled-button
+ (bufferp stream)
+ (with-current-buffer stream (1+ (point))))))
(princ " " stream)
- (cl-print-object (aref object 2) stream))
- (when button-start
- (with-current-buffer stream
- (make-text-button button-start (point)
- :type 'help-byte-code
- 'byte-code-function object)))))
- (princ ")" stream))
+ (prin1 object stream)
+ (when button-start
+ (with-current-buffer stream
+ (make-text-button button-start (point)
+ :type 'help-byte-code
+ 'byte-code-function object))))
+ (pcase (help-split-fundoc (documentation object 'raw) object)
+ ;; Drop args which `help-function-arglist' already printed.
+ (`(,_usage . ,(and doc (guard (stringp doc))))
+ (princ " " stream)
+ (prin1 doc stream)))
+ (let ((inter (interactive-form object)))
+ (when inter
+ (princ " " stream)
+ (cl-print-object
+ (if (eq 'byte-code (car-safe (cadr inter)))
+ `(interactive ,(make-byte-code nil (nth 1 (cadr inter))
+ (nth 2 (cadr inter))
+ (nth 3 (cadr inter))))
+ inter)
+ stream)))
+ (if (eq cl-print-compiled 'disassemble)
+ (princ
+ (with-temp-buffer
+ (insert "\n")
+ (disassemble-1 object 0)
+ (buffer-string))
+ stream)
+ (princ " " stream)
+ (let ((button-start (and cl-print-compiled-button
+ (bufferp stream)
+ (with-current-buffer stream (point)))))
+ (princ (format "#<bytecode %#x>" (sxhash object)) stream)
+ (when (eq cl-print-compiled 'static)
+ (princ " " stream)
+ (cl-print-object (aref object 2) stream))
+ (when button-start
+ (with-current-buffer stream
+ (make-text-button button-start (point)
+ :type 'help-byte-code
+ 'byte-code-function object)))))
+ (princ ")" stream)))
;; This belongs in oclosure.el, of course, but some load-ordering issues make it
;; complicated.
@@ -261,12 +274,26 @@ into a button whose action shows the function's disassembly.")
(cl-defmethod cl-print-object-contents ((object cl-structure-object) start stream)
(cl-print--struct-contents object start stream)) ;FIXME: η-redex!
+(defvar cl-print-string-length nil
+ "Maximum length of string to print before abbreviating.
+A value of nil means no limit.
+
+When Emacs abbreviates a string, it prints the first
+`cl-print-string-length' characters of the string, followed by
+\"...\". You can type RET, or click on this ellipsis to expand
+the string.
+
+This variable has effect only in the `cl-prin*' functions, not in
+primitives such as `prin1'.")
+
(cl-defmethod cl-print-object ((object string) stream)
(unless stream (setq stream standard-output))
(let* ((has-properties (or (text-properties-at 0 object)
(next-property-change 0 object)))
(len (length object))
- (limit (if (natnump print-length) (min print-length len) len)))
+ (limit (if (natnump cl-print-string-length)
+ (min cl-print-string-length len)
+ len)))
(if (and has-properties
cl-print--depth
(natnump print-level)
@@ -325,8 +352,9 @@ into a button whose action shows the function's disassembly.")
(let* ((len (length object)))
(if (atom start)
;; Print part of the string.
- (let* ((limit (if (natnump print-length)
- (min (+ start print-length) len) len))
+ (let* ((limit (if (natnump cl-print-string-length)
+ (min (+ start cl-print-string-length) len)
+ len))
(substr (substring-no-properties object start limit))
(printed (prin1-to-string substr))
(trimmed (substring printed 1 -1)))
@@ -534,14 +562,14 @@ node `(elisp)Output Variables'."
(defun cl-print-to-string-with-limit (print-function value limit)
"Return a string containing a printed representation of VALUE.
Attempt to get the length of the returned string under LIMIT
-characters with appropriate settings of `print-level' and
-`print-length.' Use PRINT-FUNCTION to print, which should take
-the arguments VALUE and STREAM and which should respect
-`print-length' and `print-level'. LIMIT may be nil or zero in
-which case PRINT-FUNCTION will be called with `print-level' and
-`print-length' bound to nil, and it can also be t in which case
-PRINT-FUNCTION will be called with the current values of `print-level'
-and `print-length'.
+characters with appropriate settings of `print-level',
+`print-length', and `cl-print-string-length'. Use
+PRINT-FUNCTION to print, which should take the arguments VALUE
+and STREAM and which should respect `print-length',
+`print-level', and `cl-print-string-length'. LIMIT may be nil or
+zero in which case PRINT-FUNCTION will be called with these
+settings bound to nil, and it can also be t in which case
+PRINT-FUNCTION will be called with their current values.
Use this function with `cl-prin1' to print an object,
abbreviating it with ellipses to fit within a size limit."
@@ -550,13 +578,18 @@ abbreviating it with ellipses to fit within a size limit."
;; limited, if you increase print-level here, add more depth in
;; call_debugger (bug#31919).
(let* ((print-length (cond
- ((null limit) nil)
((eq limit t) print-length)
+ ((or (null limit) (zerop limit)) nil)
(t (min limit 50))))
(print-level (cond
- ((null limit) nil)
((eq limit t) print-level)
+ ((or (null limit) (zerop limit)) nil)
(t (min 8 (truncate (log limit))))))
+ (cl-print-string-length
+ (cond
+ ((eq limit t) cl-print-string-length)
+ ((or (null limit) (zerop limit)) nil)
+ (t (max 0 (- limit 3)))))
(delta-length (when (natnump limit)
(max 1 (truncate (/ print-length print-level))))))
(with-temp-buffer
@@ -572,7 +605,10 @@ abbreviating it with ellipses to fit within a size limit."
(let* ((ratio (/ result limit))
(delta-level (max 1 (min (- print-level 2) ratio))))
(cl-decf print-level delta-level)
- (cl-decf print-length (* delta-length delta-level)))))))))
+ (cl-decf print-length (* delta-length delta-level))
+ (when cl-print-string-length
+ (cl-decf cl-print-string-length
+ (ceiling cl-print-string-length 4.0))))))))))
(provide 'cl-print)
;;; cl-print.el ends here
diff --git a/lisp/emacs-lisp/cl-seq.el b/lisp/emacs-lisp/cl-seq.el
index ec481121ae6..e46955fd968 100644
--- a/lisp/emacs-lisp/cl-seq.el
+++ b/lisp/emacs-lisp/cl-seq.el
@@ -1,6 +1,6 @@
;;; cl-seq.el --- Common Lisp features, part 3 -*- lexical-binding: t -*-
-;; Copyright (C) 1993, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1993, 2001-2024 Free Software Foundation, Inc.
;; Author: Dave Gillespie <daveg@synaptics.com>
;; Old-Version: 2.02
diff --git a/lisp/emacs-lisp/comp-common.el b/lisp/emacs-lisp/comp-common.el
new file mode 100644
index 00000000000..6ba9664ea5c
--- /dev/null
+++ b/lisp/emacs-lisp/comp-common.el
@@ -0,0 +1,553 @@
+;;; comp-common.el --- common code -*- lexical-binding: t -*-
+
+;; Copyright (C) 2023-2024 Free Software Foundation, Inc.
+
+;; Author: Andrea Corallo <acorallo@gnu.org>
+;; Keywords: lisp
+;; Package: emacs
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; This file holds common code required by comp.el and comp-run.el.
+
+;;; Code:
+
+(eval-when-compile (require 'cl-lib))
+
+;; These variables and functions are defined in comp.c
+(defvar comp-native-version-dir)
+(defvar native-comp-eln-load-path)
+
+(defgroup comp-common nil
+ "Emacs Lisp native compiler common code."
+ :group 'lisp)
+
+(defcustom native-comp-verbose 0
+ "Compiler verbosity for native compilation, a number between 0 and 3.
+This is intended for debugging the compiler itself.
+ 0 no logging.
+ 1 final LIMPLE is logged.
+ 2 LAP, final LIMPLE, and some pass info are logged.
+ 3 max verbosity."
+ :type 'natnum
+ :risky t
+ :version "28.1")
+
+(defcustom native-comp-never-optimize-functions
+ ;; We used to list those functions here that were advised during
+ ;; preload, but we now prefer to disallow preload advices in
+ ;; loadup.el (bug#67005).
+ '(eval)
+ "Primitive functions to exclude from trampoline optimization.
+
+Primitive functions included in this list will not be called
+directly by the natively-compiled code, which makes trampolines for
+those primitives unnecessary in case of function redefinition/advice."
+ :type '(repeat symbol)
+ :version "30.1")
+
+(defcustom native-comp-async-env-modifier-form nil
+ "Form evaluated before compilation by each asynchronous compilation subprocess.
+Used to modify the compiler environment."
+ :type 'sexp
+ :risky t
+ :version "28.1")
+
+(defconst comp-known-type-specifiers
+ `(
+ ;; Functions we can trust not to be redefined, or, if redefined,
+ ;; to expose the same type. The vast majority of these are
+ ;; either pure or primitive; the original list is the union of
+ ;; pure + side-effect-free-fns + side-effect-and-error-free-fns:
+ (% (function ((or number marker) (or number marker)) number))
+ (* (function (&rest (or number marker)) number))
+ (+ (function (&rest (or number marker)) number))
+ (- (function (&rest (or number marker)) number))
+ (/ (function ((or number marker) &rest (or number marker)) number))
+ (/= (function ((or number marker) (or number marker)) boolean))
+ (1+ (function ((or number marker)) number))
+ (1- (function ((or number marker)) number))
+ (< (function ((or number marker) &rest (or number marker)) boolean))
+ (<= (function ((or number marker) &rest (or number marker)) boolean))
+ (= (function ((or number marker) &rest (or number marker)) boolean))
+ (> (function ((or number marker) &rest (or number marker)) boolean))
+ (>= (function ((or number marker) &rest (or number marker)) boolean))
+ (abs (function (number) number))
+ (acos (function (number) float))
+ (append (function (&rest t) t))
+ (aref (function (t fixnum) t))
+ (arrayp (function (t) boolean))
+ (ash (function (integer integer) integer))
+ (asin (function (number) float))
+ (assq (function (t list) list))
+ (atan (function (number &optional number) float))
+ (atom (function (t) boolean))
+ (bignump (function (t) boolean))
+ (bobp (function () boolean))
+ (bolp (function () boolean))
+ (bool-vector-count-consecutive
+ (function (bool-vector boolean integer) fixnum))
+ (bool-vector-count-population (function (bool-vector) fixnum))
+ (bool-vector-not (function (bool-vector &optional bool-vector) bool-vector))
+ (bool-vector-p (function (t) boolean))
+ (bool-vector-subsetp (function (bool-vector bool-vector) boolean))
+ (boundp (function (symbol) boolean))
+ (buffer-end (function ((or number marker)) integer))
+ (buffer-file-name (function (&optional buffer) (or string null)))
+ (buffer-list (function (&optional frame) list))
+ (buffer-local-variables (function (&optional buffer) list))
+ (buffer-modified-p
+ (function (&optional buffer) (or boolean (member autosaved))))
+ (buffer-size (function (&optional buffer) integer))
+ (buffer-string (function () string))
+ (buffer-substring
+ (function ((or integer marker) (or integer marker)) string))
+ (bufferp (function (t) boolean))
+ (byte-code-function-p (function (t) boolean))
+ (capitalize (function (or integer string) (or integer string)))
+ (car (function (list) t))
+ (car-less-than-car (function (list list) boolean))
+ (car-safe (function (t) t))
+ (case-table-p (function (t) boolean))
+ (cdr (function (list) t))
+ (cdr-safe (function (t) t))
+ (ceiling (function (number &optional number) integer))
+ (char-after (function (&optional (or marker integer)) (or fixnum null)))
+ (char-before (function (&optional (or marker integer)) (or fixnum null)))
+ (char-equal (function (integer integer) boolean))
+ (char-or-string-p (function (t) boolean))
+ (char-to-string (function (fixnum) string))
+ (char-width (function (fixnum) fixnum))
+ (characterp (function (t &optional t) boolean))
+ (charsetp (function (t) boolean))
+ (commandp (function (t &optional t) boolean))
+ (compare-strings
+ (function (string (or integer marker null) (or integer marker null) string
+ (or integer marker null) (or integer marker null)
+ &optional t)
+ (or (member t) fixnum)))
+ (concat (function (&rest sequence) string))
+ (cons (function (t t) cons))
+ (consp (function (t) boolean))
+ (coordinates-in-window-p
+ (function (cons window)
+ (or cons null
+ (member bottom-divider right-divider mode-line header-line
+ tab-line left-fringe right-fringe vertical-line
+ left-margin right-margin))))
+ (copy-alist (function (list) list))
+ (copy-marker (function (&optional (or integer marker) boolean) marker))
+ (copy-sequence (function (sequence) sequence))
+ (copysign (function (float float) float))
+ (cos (function (number) float))
+ (count-lines
+ (function ((or integer marker) (or integer marker) &optional t) integer))
+ (current-buffer (function () buffer))
+ (current-global-map (function () cons))
+ (current-indentation (function () integer))
+ (current-local-map (function () (or cons null)))
+ (current-minor-mode-maps (function () (or cons null)))
+ (current-time (function () cons))
+ (current-time-string (function (&optional (or number list)
+ (or symbol string cons integer))
+ string))
+ (current-time-zone (function (&optional (or number list)
+ (or symbol string cons integer))
+ cons))
+ (custom-variable-p (function (symbol) t))
+ (decode-char (function (cons t) (or fixnum null)))
+ (decode-time (function (&optional (or number list)
+ (or symbol string cons integer)
+ symbol)
+ cons))
+ (default-boundp (function (symbol) boolean))
+ (default-value (function (symbol) t))
+ (degrees-to-radians (function (number) float))
+ (documentation
+ (function ((or function symbol subr) &optional t) (or null string)))
+ (downcase (function ((or fixnum string)) (or fixnum string)))
+ (elt (function (sequence integer) t))
+ (encode-char (function (fixnum symbol) (or fixnum null)))
+ (encode-time (function (cons &rest t) cons))
+ (eobp (function () boolean))
+ (eolp (function () boolean))
+ (eq (function (t t) boolean))
+ (eql (function (t t) boolean))
+ (equal (function (t t) boolean))
+ (error-message-string (function (list) string))
+ (eventp (function (t) boolean))
+ (exp (function (number) float))
+ (expt (function (number number) number))
+ (fboundp (function (symbol) boolean))
+ (fceiling (function (float) float))
+ (featurep (function (symbol &optional symbol) boolean))
+ (ffloor (function (float) float))
+ (file-directory-p (function (string) boolean))
+ (file-exists-p (function (string) boolean))
+ (file-locked-p (function (string) (or boolean string)))
+ (file-name-absolute-p (function (string) boolean))
+ (file-newer-than-file-p (function (string string) boolean))
+ (file-readable-p (function (string) boolean))
+ (file-symlink-p (function (string) (or boolean string)))
+ (file-writable-p (function (string) boolean))
+ (fixnump (function (t) boolean))
+ (float (function (number) float))
+ (float-time (function (&optional (or number list)) float))
+ (floatp (function (t) boolean))
+ (floor (function (number &optional number) integer))
+ (following-char (function () fixnum))
+ (format (function (string &rest t) string))
+ (format-time-string (function (string &optional (or number list)
+ (or symbol string cons integer))
+ string))
+ (frame-first-window (function ((or frame window)) window))
+ (frame-root-window (function (&optional (or frame window)) window))
+ (frame-selected-window (function (&optional (or frame window)) window))
+ (frame-visible-p (function (frame) (or boolean (member icon))))
+ (framep (function (t) symbol))
+ (fround (function (float) float))
+ (ftruncate (function (float) float))
+ (get (function (symbol symbol) t))
+ (get-buffer (function ((or buffer string)) (or buffer null)))
+ (get-buffer-window
+ (function (&optional (or buffer string) (or symbol (integer 0 0)))
+ (or null window)))
+ (get-file-buffer (function (string) (or null buffer)))
+ (get-largest-window (function (&optional t t t) (or window null)))
+ (get-lru-window (function (&optional t t t) (or window null)))
+ (getenv (function (string &optional frame) (or null string)))
+ (gethash (function (t hash-table &optional t) t))
+ (hash-table-count (function (hash-table) integer))
+ (hash-table-p (function (t) boolean))
+ (identity (function (t) t))
+ (ignore (function (&rest t) null))
+ (int-to-string (function (number) string))
+ (integer-or-marker-p (function (t) boolean))
+ (integerp (function (t) boolean))
+ (interactive-p (function () boolean))
+ (intern-soft (function ((or string symbol) &optional vector) symbol))
+ (invocation-directory (function () string))
+ (invocation-name (function () string))
+ (isnan (function (float) boolean))
+ (keymap-parent (function (cons) (or cons null)))
+ (keymapp (function (t) boolean))
+ (keywordp (function (t) boolean))
+ (last (function (list &optional integer) list))
+ (lax-plist-get (function (list t) t))
+ (ldexp (function (number integer) float))
+ (length (function (t) (integer 0 *)))
+ (length< (function (sequence fixnum) boolean))
+ (length= (function (sequence fixnum) boolean))
+ (length> (function (sequence fixnum) boolean))
+ (line-beginning-position (function (&optional integer) integer))
+ (line-end-position (function (&optional integer) integer))
+ (list (function (&rest t) list))
+ (listp (function (t) boolean))
+ (local-variable-if-set-p (function (symbol &optional buffer) boolean))
+ (local-variable-p (function (symbol &optional buffer) boolean))
+ (locale-info (function ((member codeset days months paper)) (or null string)))
+ (log (function (number number) float))
+ (log10 (function (number) float))
+ (logand (function (&rest (or integer marker)) integer))
+ (logb (function (number) integer))
+ (logcount (function (integer) integer))
+ (logior (function (&rest (or integer marker)) integer))
+ (lognot (function (integer) integer))
+ (logxor (function (&rest (or integer marker)) integer))
+ ;; (lsh (function ((integer ,most-negative-fixnum *) integer) integer)) ?
+ (lsh (function (integer integer) integer))
+ (make-byte-code
+ (function ((or fixnum list) string vector integer &optional string t
+ &rest t)
+ vector))
+ (make-list (function (integer t) list))
+ (make-marker (function () marker))
+ (make-string (function (integer fixnum &optional t) string))
+ (make-symbol (function (string) symbol))
+ (mark (function (&optional t) (or integer null)))
+ (mark-marker (function () marker))
+ (marker-buffer (function (marker) (or buffer null)))
+ (markerp (function (t) boolean))
+ (max (function ((or number marker) &rest (or number marker)) number))
+ (max-char (function (&optional t) fixnum))
+ (member (function (t list) list))
+ (memory-limit (function () integer))
+ (memq (function (t list) list))
+ (memql (function (t list) list))
+ (min (function ((or number marker) &rest (or number marker)) number))
+ (minibuffer-selected-window (function () (or window null)))
+ (minibuffer-window (function (&optional frame) window))
+ (mod
+ (function ((or number marker) (or number marker))
+ (or (integer 0 *) (float 0 *))))
+ (mouse-movement-p (function (t) boolean))
+ (multibyte-char-to-unibyte (function (fixnum) fixnum))
+ (natnump (function (t) boolean))
+ (next-window (function (&optional window t t) window))
+ (nlistp (function (t) boolean))
+ (not (function (t) boolean))
+ (nth (function (integer list) t))
+ (nthcdr (function (integer t) t))
+ (null (function (t) boolean))
+ (number-or-marker-p (function (t) boolean))
+ (number-to-string (function (number) string))
+ (numberp (function (t) boolean))
+ (one-window-p (function (&optional t t) boolean))
+ (overlayp (function (t) boolean))
+ (parse-colon-path (function (string) cons))
+ (plist-get (function (list t &optional t) t))
+ (plist-member (function (list t &optional t) list))
+ (point (function () integer))
+ (point-marker (function () marker))
+ (point-max (function () integer))
+ (point-min (function () integer))
+ (preceding-char (function () fixnum))
+ (previous-window (function (&optional window t t) window))
+ (prin1-to-string (function (t &optional t t) string))
+ (processp (function (t) boolean))
+ (proper-list-p (function (t) (or fixnum null)))
+ (propertize (function (string &rest t) string))
+ (radians-to-degrees (function (number) float))
+ (rassoc (function (t list) list))
+ (rassq (function (t list) list))
+ (read-from-string (function (string &optional integer integer) cons))
+ (recent-keys (function (&optional (or cons null)) vector))
+ (recursion-depth (function () integer))
+ (regexp-opt (function (list) string))
+ (regexp-quote (function (string) string))
+ (region-beginning (function () integer))
+ (region-end (function () integer))
+ (reverse (function (sequence) sequence))
+ (round (function (number &optional number) integer))
+ (safe-length (function (t) integer))
+ (selected-frame (function () frame))
+ (selected-window (function () window))
+ (sequencep (function (t) boolean))
+ (sin (function (number) float))
+ (sqrt (function (number) float))
+ (standard-case-table (function () char-table))
+ (standard-syntax-table (function () char-table))
+ (string (function (&rest fixnum) string))
+ (string-as-multibyte (function (string) string))
+ (string-as-unibyte (function (string) string))
+ (string-equal (function ((or string symbol) (or string symbol)) boolean))
+ (string-lessp (function ((or string symbol) (or string symbol)) boolean))
+ (string-make-multibyte (function (string) string))
+ (string-make-unibyte (function (string) string))
+ (string-search (function (string string &optional integer) (or integer null)))
+ (string-to-char (function (string) fixnum))
+ (string-to-multibyte (function (string) string))
+ (string-to-number (function (string &optional integer) number))
+ (string-to-syntax (function (string) (or cons null)))
+ (string< (function ((or string symbol) (or string symbol)) boolean))
+ (string= (function ((or string symbol) (or string symbol)) boolean))
+ (stringp (function (t) boolean))
+ (subrp (function (t) boolean))
+ (substring
+ (function ((or string vector) &optional integer integer) (or string vector)))
+ (sxhash (function (t) integer))
+ (sxhash-eq (function (t) integer))
+ (sxhash-eql (function (t) integer))
+ (sxhash-equal (function (t) integer))
+ (symbol-function (function (symbol) t))
+ (symbol-name (function (symbol) string))
+ (symbol-plist (function (symbol) list))
+ (symbol-value (function (symbol) t))
+ (symbolp (function (t) boolean))
+ (syntax-table (function () char-table))
+ (syntax-table-p (function (t) boolean))
+ (tan (function (number) float))
+ (this-command-keys (function () string))
+ (this-command-keys-vector (function () vector))
+ (this-single-command-keys (function () vector))
+ (this-single-command-raw-keys (function () vector))
+ (time-convert (function ((or number list) &optional (or symbol integer))
+ (or cons number)))
+ (truncate (function (number &optional number) integer))
+ (type-of (function (t) symbol))
+ (unibyte-char-to-multibyte (function (fixnum) fixnum)) ;; byte is fixnum
+ (upcase (function ((or fixnum string)) (or fixnum string)))
+ (user-full-name (function (&optional integer) (or string null)))
+ (user-login-name (function (&optional integer) (or string null)))
+ (user-original-login-name (function (&optional integer) (or string null)))
+ (user-real-login-name (function () string))
+ (user-real-uid (function () integer))
+ (user-uid (function () integer))
+ (vconcat (function (&rest sequence) vector))
+ (vector (function (&rest t) vector))
+ (vectorp (function (t) boolean))
+ (visible-frame-list (function () list))
+ (wholenump (function (t) boolean))
+ (window-configuration-p (function (t) boolean))
+ (window-live-p (function (t) boolean))
+ (window-valid-p (function (t) boolean))
+ (windowp (function (t) boolean))
+ (zerop (function (number) boolean))
+ ;; Type hints
+ (comp-hint-fixnum (function (t) fixnum))
+ (comp-hint-cons (function (t) cons))
+ ;; Non returning functions
+ (throw (function (t t) nil))
+ (error (function (string &rest t) nil))
+ (signal (function (symbol t) nil)))
+ "Alist used for type propagation.")
+
+(defconst comp-limple-calls '(call
+ callref
+ direct-call
+ direct-callref)
+ "Limple operators used to call subrs.")
+
+(defconst comp-limple-sets '(set
+ setimm
+ set-par-to-local
+ set-args-to-local
+ set-rest-args-to-local)
+ "Limple set operators.")
+
+(defconst comp-limple-assignments `(assume
+ fetch-handler
+ ,@comp-limple-sets)
+ "Limple operators that clobber the first m-var argument.")
+
+(defconst comp-limple-branches '(jump cond-jump)
+ "Limple operators used for conditional and unconditional branches.")
+
+(defconst comp-limple-ops `(,@comp-limple-calls
+ ,@comp-limple-assignments
+ ,@comp-limple-branches
+ return)
+ "All Limple operators.")
+
+(defconst comp-limple-lock-keywords
+ `((,(rx bol "(comment" (1+ not-newline)) . font-lock-comment-face)
+ (,(rx "#(" (group-n 1 "mvar"))
+ (1 font-lock-function-name-face))
+ (,(rx bol "(" (group-n 1 "phi"))
+ (1 font-lock-variable-name-face))
+ (,(rx bol "(" (group-n 1 (or "return" "unreachable")))
+ (1 font-lock-warning-face))
+ (,(rx (group-n 1 (or "entry"
+ (seq (or "entry_" "entry_fallback_" "bb_")
+ (1+ num) (? (or "_latch"
+ (seq "_cstrs_" (1+ num))))))))
+ (1 font-lock-constant-face))
+ (,(rx-to-string
+ `(seq "(" (group-n 1 (or ,@(mapcar #'symbol-name comp-limple-ops)))))
+ (1 font-lock-keyword-face)))
+ "Highlights used by `native-comp-limple-mode'.")
+
+(defconst comp-log-buffer-name "*Native-compile-Log*"
+ "Name of the native-compiler log buffer.")
+
+(cl-defun comp-log (data &optional (level 1) quoted)
+ "Log DATA at LEVEL.
+LEVEL is a number from 1-3, and defaults to 1; if it is less
+than `native-comp-verbose', do nothing. If `noninteractive', log
+with `message'. Otherwise, log with `comp-log-to-buffer'."
+ (when (>= native-comp-verbose level)
+ (if noninteractive
+ (cl-typecase data
+ (atom (message "%s" data))
+ (t (dolist (elem data)
+ (message "%s" elem))))
+ (comp-log-to-buffer data quoted))))
+
+(define-derived-mode native-comp-limple-mode fundamental-mode "LIMPLE"
+ "Syntax-highlight LIMPLE IR."
+ (setf font-lock-defaults '(comp-limple-lock-keywords)))
+
+(cl-defun comp-log-to-buffer (data &optional quoted)
+ "Log DATA to `comp-log-buffer-name'."
+ (let* ((print-f (if quoted #'prin1 #'princ))
+ (log-buffer
+ (or (get-buffer comp-log-buffer-name)
+ (with-current-buffer (get-buffer-create comp-log-buffer-name)
+ (unless (derived-mode-p 'compilation-mode)
+ (emacs-lisp-compilation-mode))
+ (current-buffer))))
+ (log-window (get-buffer-window log-buffer))
+ (inhibit-read-only t)
+ at-end-p)
+ (with-current-buffer log-buffer
+ (unless (eq major-mode 'native-comp-limple-mode)
+ (native-comp-limple-mode))
+ (when (= (point) (point-max))
+ (setf at-end-p t))
+ (save-excursion
+ (goto-char (point-max))
+ (cl-typecase data
+ (atom (funcall print-f data log-buffer))
+ (t (dolist (elem data)
+ (funcall print-f elem log-buffer)
+ (insert "\n"))))
+ (insert "\n"))
+ (when (and at-end-p log-window)
+ ;; When log window's point is at the end, follow the tail.
+ (with-selected-window log-window
+ (goto-char (point-max)))))))
+
+(defun comp-ensure-native-compiler ()
+ "Make sure Emacs has native compiler support and libgccjit can be loaded.
+Signal an error otherwise.
+To be used by all entry points."
+ (cond
+ ((null (featurep 'native-compile))
+ (error "Emacs was not compiled with native compiler support (--with-native-compilation)"))
+ ((null (native-comp-available-p))
+ (error "Cannot find libgccjit library"))))
+
+(defun comp-trampoline-filename (subr-name)
+ "Given SUBR-NAME return the filename containing the trampoline."
+ (concat (comp-c-func-name subr-name "subr--trampoline-" t) ".eln"))
+
+(defun comp-eln-load-path-eff ()
+ "Return a list of effective eln load directories.
+Account for `native-comp-eln-load-path' and `comp-native-version-dir'."
+ (mapcar (lambda (dir)
+ (expand-file-name comp-native-version-dir
+ (file-name-as-directory
+ (expand-file-name dir invocation-directory))))
+ native-comp-eln-load-path))
+
+;;;###autoload
+(defun comp-function-type-spec (function)
+ "Return the type specifier of FUNCTION.
+
+This function returns a cons cell whose car is the function
+specifier, and cdr is a symbol, either `inferred' or `know'.
+If the symbol is `inferred', the type specifier is automatically
+inferred from the code itself by the native compiler; if it is
+`know', the type specifier comes from `comp-known-type-specifiers'."
+ (let ((kind 'know)
+ type-spec )
+ (when-let ((res (assoc function comp-known-type-specifiers)))
+ (setf type-spec (cadr res)))
+ (let ((f (and (symbolp function)
+ (symbol-function function))))
+ (when (and f
+ (null type-spec)
+ (subr-native-elisp-p f))
+ (setf kind 'inferred
+ type-spec (subr-type f))))
+ (when type-spec
+ (cons type-spec kind))))
+
+(provide 'comp-common)
+
+;;; comp-common.el ends here
diff --git a/lisp/emacs-lisp/comp-cstr.el b/lisp/emacs-lisp/comp-cstr.el
index 7e3ca1f3bae..c65af16b725 100644
--- a/lisp/emacs-lisp/comp-cstr.el
+++ b/lisp/emacs-lisp/comp-cstr.el
@@ -1,6 +1,6 @@
;;; comp-cstr.el --- native compiler constraint library -*- lexical-binding: t -*-
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
;; Author: Andrea Corallo <acorallo@gnu.org>
;; Keywords: lisp
@@ -36,7 +36,7 @@
;;; Code:
(require 'cl-lib)
-(require 'cl-macs)
+(require 'cl-extra) ;HACK: For `cl-find-class' when `cl-loaddefs' is missing.
(defconst comp--typeof-builtin-types (mapcar (lambda (x)
(append x '(t)))
@@ -89,8 +89,10 @@ Integer values are handled in the `range' slot.")
(defun comp--cl-class-hierarchy (x)
"Given a class name `x' return its hierarchy."
- `(,@(mapcar #'cl--struct-class-name (cl--struct-all-parents
- (cl--struct-get-class x)))
+ `(,@(cl--class-allparents (cl--struct-get-class x))
+ ;; FIXME: AFAICT, `comp--all-classes' will also find those struct types
+ ;; which use :type and can thus be either `vector' or `cons' (the latter
+ ;; isn't `atom').
atom
t))
@@ -262,69 +264,130 @@ Return them as multiple value."
;;; Type handling.
-(defun comp-normalize-typeset (typeset)
- "Sort TYPESET and return it."
- (cl-sort (cl-remove-duplicates typeset)
- (lambda (x y)
- (string-lessp (symbol-name x)
- (symbol-name y)))))
+(defun comp--sym-lessp (x y)
+ "Like `string-lessp' but for symbol names."
+ (string-lessp (symbol-name x)
+ (symbol-name y)))
-(defun comp-supertypes (type)
- "Return a list of pairs (supertype . hierarchy-level) for TYPE."
- (cl-loop
- named outer
- with found = nil
- for l in (comp-cstr-ctxt-typeof-types comp-ctxt)
- do (cl-loop
- for x in l
- for i from (length l) downto 0
- when (eq type x)
- do (setf found t)
- when found
- collect `(,x . ,i) into res
- finally (when found
- (cl-return-from outer res)))))
-
-(defun comp-common-supertype-2 (type1 type2)
- "Return the first common supertype of TYPE1 TYPE2."
- (when-let ((types (cl-intersection
- (comp-supertypes type1)
- (comp-supertypes type2)
- :key #'car)))
- (car (cl-reduce (lambda (x y)
- (if (> (cdr x) (cdr y)) x y))
- types))))
-
-(defun comp-common-supertype (&rest types)
- "Return the first common supertype of TYPES."
- (or (gethash types (comp-cstr-ctxt-common-supertype-mem comp-ctxt))
- (puthash types
- (cl-reduce #'comp-common-supertype-2 types)
- (comp-cstr-ctxt-common-supertype-mem comp-ctxt))))
+(defun comp--direct-supertypes (type)
+ "Return the direct supertypes of TYPE."
+ (let ((supers (comp-supertypes type)))
+ (cl-assert (eq type (car supers)))
+ (cl-loop
+ with notdirect = nil
+ with direct = nil
+ for parent in (cdr supers)
+ unless (memq parent notdirect)
+ do (progn
+ (push parent direct)
+ (setq notdirect (append notdirect (comp-supertypes parent))))
+ finally return direct)))
(defsubst comp-subtype-p (type1 type2)
"Return t if TYPE1 is a subtype of TYPE2 or nil otherwise."
(let ((types (cons type1 type2)))
(or (gethash types (comp-cstr-ctxt-subtype-p-mem comp-ctxt))
(puthash types
- (eq (comp-common-supertype-2 type1 type2) type2)
+ (memq type2 (comp-supertypes type1))
(comp-cstr-ctxt-subtype-p-mem comp-ctxt)))))
+(defun comp--normalize-typeset0 (typeset)
+ ;; For every type search its supertypes. If all the subtypes of a
+ ;; supertype are presents remove all of them, add the identified
+ ;; supertype and restart.
+ ;; FIXME: The intention is to return a 100% equivalent but simpler
+ ;; typeset, but this is only the case when the supertype is abstract
+ ;; and "final/closed" (i.e. can't have new subtypes).
+ (when typeset
+ (while (eq 'restart
+ (cl-loop
+ named main
+ for sup in (cl-remove-duplicates
+ (apply #'append
+ (mapcar #'comp--direct-supertypes typeset)))
+ for subs = (comp--direct-subtypes sup)
+ when (and (length> subs 1) ;;FIXME: Why?
+ ;; Every subtype of `sup` is a subtype of
+ ;; some element of `typeset`?
+ ;; It's tempting to just check (member x typeset),
+ ;; but think of the typeset (marker number),
+ ;; where `sup' is `integer-or-marker' and `sub'
+ ;; is `integer'.
+ (cl-every (lambda (sub)
+ (cl-some (lambda (type)
+ (comp-subtype-p sub type))
+ typeset))
+ subs))
+ do (progn
+ (setq typeset (cons sup (cl-set-difference typeset subs)))
+ (cl-return-from main 'restart)))))
+ typeset))
+
+(defun comp-normalize-typeset (typeset)
+ "Sort TYPESET and return it."
+ (cl-sort (comp--normalize-typeset0 (cl-remove-duplicates typeset)) #'comp--sym-lessp))
+
+(defun comp--direct-subtypes (type)
+ "Return all the direct subtypes of TYPE."
+ ;; TODO: memoize.
+ (let ((subtypes ()))
+ (dolist (j (comp-cstr-ctxt-typeof-types comp-ctxt))
+ (let ((occur (memq type j)))
+ (when occur
+ (while (not (eq j occur))
+ (let ((candidate (pop j)))
+ (when (and (not (memq candidate subtypes))
+ (memq type (comp--direct-supertypes candidate)))
+ (push candidate subtypes)))))))
+ (cl-sort subtypes #'comp--sym-lessp)))
+
+(defun comp--intersection (list1 list2)
+ "Like `cl-intersection` but preserves the order of one of its args."
+ (if (equal list1 list2) list1
+ (let ((res nil))
+ (while list2
+ (if (memq (car list2) list1)
+ (push (car list2) res))
+ (pop list2))
+ (nreverse res))))
+
+(defun comp-supertypes (type)
+ "Return the ordered list of supertypes of TYPE."
+ ;; FIXME: We should probably keep the results in
+ ;; `comp-cstr-ctxt-typeof-types' (or maybe even precompute them
+ ;; and maybe turn `comp-cstr-ctxt-typeof-types' into a hash-table).
+ ;; Or maybe we shouldn't keep structs and defclasses in it,
+ ;; and just use `cl--class-allparents' when needed (and refuse to
+ ;; compute their direct subtypes since we can't know them).
+ (cl-loop
+ named loop
+ with above
+ for lane in (comp-cstr-ctxt-typeof-types comp-ctxt)
+ do (let ((x (memq type lane)))
+ (cond
+ ((null x) nil)
+ ((eq x lane) (cl-return-from loop x)) ;A base type: easy case.
+ (t (setq above
+ (if above (comp--intersection x above) x)))))
+ finally return above))
+
(defun comp-union-typesets (&rest typesets)
"Union types present into TYPESETS."
(or (gethash typesets (comp-cstr-ctxt-union-typesets-mem comp-ctxt))
(puthash typesets
(cl-loop
- with types = (apply #'append typesets)
+ ;; List of (TYPE . SUPERTYPES)", ordered from
+ ;; "most general" to "least general"
+ with typess = (sort (mapcar #'comp-supertypes
+ (apply #'append typesets))
+ (lambda (l1 l2)
+ (<= (length l1) (length l2))))
with res = '()
- for lane in (comp-cstr-ctxt-typeof-types comp-ctxt)
- do (cl-loop
- with last = nil
- for x in lane
- when (memq x types)
- do (setf last x)
- finally (when last
- (push last res)))
+ for types in typess
+ ;; Don't keep this type if it's a subtype of one of
+ ;; the other types.
+ unless (comp--intersection types res)
+ do (push (car types) res)
finally return (comp-normalize-typeset res))
(comp-cstr-ctxt-union-typesets-mem comp-ctxt))))
@@ -734,7 +797,7 @@ DST is returned."
(cl-loop
for val in (valset src)
;; If (member value) is subtypep of all other sources then
- ;; is good to be colleted.
+ ;; is good to be collected.
when (cl-every (lambda (s)
(or (memql val (valset s))
(cl-some (lambda (type)
@@ -818,7 +881,7 @@ Non memoized version of `comp-cstr-intersection-no-mem'."
(comp-subtype-p neg-type pos-type))
do (cl-loop
with found
- for (type . _) in (comp-supertypes neg-type)
+ for type in (comp-supertypes neg-type)
when found
collect type into res
when (eq type pos-type)
diff --git a/lisp/emacs-lisp/comp-run.el b/lisp/emacs-lisp/comp-run.el
new file mode 100644
index 00000000000..5d1a193269d
--- /dev/null
+++ b/lisp/emacs-lisp/comp-run.el
@@ -0,0 +1,460 @@
+;;; comp-runtime.el --- runtime Lisp native compiler code -*- lexical-binding: t -*-
+
+;; Copyright (C) 2023-2024 Free Software Foundation, Inc.
+
+;; Author: Andrea Corallo <acorallo@gnu.org>
+;; Keywords: lisp
+;; Package: emacs
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; While the main native compiler is implemented in comp.el, when
+;; commonly used as a jit compiler it is only loaded by Emacs sub
+;; processes performing async compilation. This files contains all
+;; the code needed to drive async compilations and any Lisp code
+;; needed at runtime to run native code.
+
+;;; Code:
+
+(eval-when-compile (require 'cl-lib))
+(require 'comp-common)
+(require 'bytecomp) ;; For `emacs-lisp-compilation-mode'.
+
+(defgroup comp-run nil
+ "Emacs Lisp native compiler runtime."
+ :group 'lisp)
+
+(defcustom native-comp-jit-compilation-deny-list
+ '()
+ "List of regexps to exclude matching files from deferred native compilation.
+Files whose names match any regexp are excluded from native compilation."
+ :type '(repeat regexp)
+ :version "28.1")
+
+(defcustom native-comp-async-jobs-number 0
+ "Default number of subprocesses used for async native compilation.
+Value of zero means to use half the number of the CPU's execution units,
+or one if there's just one execution unit."
+ :type 'natnum
+ :risky t
+ :version "28.1")
+
+(defcustom native-comp-async-report-warnings-errors t
+ "Whether to report warnings and errors from asynchronous native compilation.
+
+When native compilation happens asynchronously, it can produce
+warnings and errors, some of which might not be emitted by a
+byte-compilation. The typical case for that is native-compiling
+a file that is missing some `require' of a necessary feature,
+while having it already loaded into the environment when
+byte-compiling.
+
+As asynchronous native compilation always starts from a pristine
+environment, it is more sensitive to such omissions, and might be
+unable to compile such Lisp source files correctly.
+
+Set this variable to nil to suppress warnings altogether, or to
+the symbol `silent' to log warnings but not pop up the *Warnings*
+buffer."
+ :type '(choice
+ (const :tag "Do not report warnings" nil)
+ (const :tag "Report and display warnings" t)
+ (const :tag "Report but do not display warnings" silent))
+ :version "28.1")
+
+(defcustom native-comp-always-compile nil
+ "Non-nil means unconditionally (re-)compile all files."
+ :type 'boolean
+ :version "28.1")
+
+(make-obsolete-variable 'native-comp-deferred-compilation-deny-list
+ 'native-comp-jit-compilation-deny-list
+ "29.1")
+
+(defcustom native-comp-async-cu-done-functions nil
+ "List of functions to call when asynchronous compilation of a file is done.
+Each function is called with one argument FILE, the filename whose
+compilation has completed."
+ :type 'hook
+ :version "28.1")
+
+(defcustom native-comp-async-all-done-hook nil
+ "Hook run after completing asynchronous compilation of all input files."
+ :type 'hook
+ :version "28.1")
+
+(defcustom native-comp-async-query-on-exit nil
+ "Whether to query the user about killing async compilations when exiting.
+If this is non-nil, Emacs will ask for confirmation to exit and kill the
+asynchronous native compilations if any are running. If nil, when you
+exit Emacs, it will silently kill those asynchronous compilations even
+if `confirm-kill-processes' is non-nil."
+ :type 'boolean
+ :version "28.1")
+
+(defconst comp-async-buffer-name "*Async-native-compile-log*"
+ "Name of the async compilation buffer log.")
+
+(defvar comp-no-spawn nil
+ "Non-nil don't spawn native compilation processes.")
+
+(defvar comp-async-compilations (make-hash-table :test #'equal)
+ "Hash table file-name -> async compilation process.")
+
+;; These variables and functions are defined in comp.c
+(defvar comp--no-native-compile)
+(defvar comp-deferred-pending-h)
+(defvar comp-installed-trampolines-h)
+(defvar native-comp-enable-subr-trampolines)
+
+(declare-function comp--install-trampoline "comp.c")
+(declare-function comp-el-to-eln-filename "comp.c")
+(declare-function native-elisp-load "comp.c")
+
+(defun native-compile-async-skip-p (file load selector)
+ "Return non-nil if FILE's compilation should be skipped.
+
+LOAD and SELECTOR work as described in `native--compile-async'."
+ ;; Make sure we are not already compiling `file' (bug#40838).
+ (or (gethash file comp-async-compilations)
+ (gethash (file-name-with-extension file "elc") comp--no-native-compile)
+ (cond
+ ((null selector) nil)
+ ((functionp selector) (not (funcall selector file)))
+ ((stringp selector) (not (string-match-p selector file)))
+ (t (error "SELECTOR must be a function a regexp or nil")))
+ ;; Also exclude files from deferred compilation if
+ ;; any of the regexps in
+ ;; `native-comp-jit-compilation-deny-list' matches.
+ (and (eq load 'late)
+ (seq-some (lambda (re)
+ (string-match-p re file))
+ native-comp-jit-compilation-deny-list))))
+
+(defvar comp-files-queue ()
+ "List of Emacs Lisp files to be compiled.")
+
+(defvar comp-async-compilations (make-hash-table :test #'equal)
+ "Hash table file-name -> async compilation process.")
+
+(defun comp-async-runnings ()
+ "Return the number of async compilations currently running.
+This function has the side effect of cleaning-up finished
+processes from `comp-async-compilations'"
+ (cl-loop
+ for file-name in (cl-loop
+ for file-name being each hash-key of comp-async-compilations
+ for prc = (gethash file-name comp-async-compilations)
+ unless (process-live-p prc)
+ collect file-name)
+ do (remhash file-name comp-async-compilations))
+ (hash-table-count comp-async-compilations))
+
+(defvar comp-num-cpus nil)
+(defun comp-effective-async-max-jobs ()
+ "Compute the effective number of async jobs."
+ (if (zerop native-comp-async-jobs-number)
+ (or comp-num-cpus
+ (setf comp-num-cpus
+ (max 1 (/ (num-processors) 2))))
+ native-comp-async-jobs-number))
+
+(defvar comp-last-scanned-async-output nil)
+(make-variable-buffer-local 'comp-last-scanned-async-output)
+;; From warnings.el
+(defvar warning-suppress-types)
+(defun comp-accept-and-process-async-output (process)
+ "Accept PROCESS output and check for diagnostic messages."
+ (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)
+ warning-suppress-types)))
+ (with-current-buffer (process-buffer process)
+ (save-excursion
+ (accept-process-output process)
+ (goto-char (or comp-last-scanned-async-output (point-min)))
+ (while (re-search-forward "^.*?\\(?:Error\\|Warning\\): .*$"
+ nil t)
+ (display-warning 'comp (match-string 0)))
+ (setq comp-last-scanned-async-output (point-max)))))
+ (accept-process-output process)))
+
+(defconst comp-valid-source-re (rx ".el" (? ".gz") eos)
+ "Regexp to match filename of valid input source files.")
+
+(defun comp-run-async-workers ()
+ "Start compiling files from `comp-files-queue' asynchronously.
+When compilation is finished, run `native-comp-async-all-done-hook' and
+display a message."
+ (cl-assert (null comp-no-spawn))
+ (if (or comp-files-queue
+ (> (comp-async-runnings) 0))
+ (unless (>= (comp-async-runnings) (comp-effective-async-max-jobs))
+ (cl-loop
+ for (source-file . load) = (pop comp-files-queue)
+ while source-file
+ do (cl-assert (string-match-p comp-valid-source-re source-file) nil
+ "`comp-files-queue' should be \".el\" files: %s"
+ source-file)
+ when (or native-comp-always-compile
+ load ; Always compile when the compilation is
+ ; commanded for late load.
+ ;; Skip compilation if `comp-el-to-eln-filename' fails
+ ;; to find a writable directory.
+ (with-demoted-errors "Async compilation :%S"
+ (file-newer-than-file-p
+ source-file (comp-el-to-eln-filename source-file))))
+ do (let* ((expr `((require 'comp)
+ (setq comp-async-compilation t
+ warning-fill-column most-positive-fixnum)
+ ,(let ((set (list 'setq)))
+ (dolist (var '(comp-file-preloaded-p
+ native-compile-target-directory
+ native-comp-speed
+ native-comp-debug
+ native-comp-verbose
+ comp-libgccjit-reproducer
+ native-comp-eln-load-path
+ native-comp-compiler-options
+ native-comp-driver-options
+ load-path
+ backtrace-line-length
+ byte-compile-warnings
+ ;; package-load-list
+ ;; package-user-dir
+ ;; package-directory-list
+ ))
+ (when (boundp var)
+ (push var set)
+ (push `',(symbol-value var) set)))
+ (nreverse set))
+ ;; FIXME: Activating all packages would align the
+ ;; functionality offered with what is usually done
+ ;; for ELPA packages (and thus fix some compilation
+ ;; issues with some ELPA packages), but it's too
+ ;; blunt an instrument (e.g. we don't even know if
+ ;; we're compiling such an ELPA package at
+ ;; this point).
+ ;;(package-activate-all)
+ ,native-comp-async-env-modifier-form
+ (message "Compiling %s..." ,source-file)
+ (comp--native-compile ,source-file ,(and load t))))
+ (source-file1 source-file) ;; Make the closure works :/
+ (temp-file (make-temp-file
+ (concat "emacs-async-comp-"
+ (file-name-base source-file) "-")
+ nil ".el"))
+ (expr-strings (let ((print-length nil)
+ (print-level nil))
+ (mapcar #'prin1-to-string expr)))
+ (_ (progn
+ (with-temp-file temp-file
+ (mapc #'insert expr-strings))
+ (comp-log "\n")
+ (mapc #'comp-log expr-strings)))
+ (load1 load)
+ (default-directory invocation-directory)
+ (process (make-process
+ :name (concat "Compiling: " source-file)
+ :buffer (with-current-buffer
+ (get-buffer-create
+ comp-async-buffer-name)
+ (unless (derived-mode-p 'compilation-mode)
+ (emacs-lisp-compilation-mode))
+ (current-buffer))
+ :command (list
+ (expand-file-name invocation-name
+ invocation-directory)
+ "-no-comp-spawn" "-Q" "--batch"
+ "--eval"
+ ;; Suppress Abort dialogs on MS-Windows
+ "(setq w32-disable-abort-dialog t)"
+ "-l" temp-file)
+ :sentinel
+ (lambda (process _event)
+ (run-hook-with-args
+ 'native-comp-async-cu-done-functions
+ source-file)
+ (comp-accept-and-process-async-output process)
+ (ignore-errors (delete-file temp-file))
+ (let ((eln-file (comp-el-to-eln-filename
+ source-file1)))
+ (when (and load1
+ (zerop (process-exit-status
+ process))
+ (file-exists-p eln-file))
+ (native-elisp-load eln-file
+ (eq load1 'late))))
+ (comp-run-async-workers))
+ :noquery (not native-comp-async-query-on-exit))))
+ (puthash source-file process comp-async-compilations))
+ when (>= (comp-async-runnings) (comp-effective-async-max-jobs))
+ do (cl-return)))
+ ;; No files left to compile and all processes finished.
+ (run-hooks 'native-comp-async-all-done-hook)
+ (with-current-buffer (get-buffer-create comp-async-buffer-name)
+ (save-excursion
+ (unless (derived-mode-p 'compilation-mode)
+ (emacs-lisp-compilation-mode))
+ (let ((inhibit-read-only t))
+ (goto-char (point-max))
+ (insert "Compilation finished.\n"))))
+ ;; `comp-deferred-pending-h' should be empty at this stage.
+ ;; Reset it anyway.
+ (clrhash comp-deferred-pending-h)))
+
+(defconst comp-warn-primitives
+ '(null memq gethash and subrp not subr-native-elisp-p
+ comp--install-trampoline concat if symbolp symbol-name make-string
+ length aset aref length> mapcar expand-file-name
+ file-name-as-directory file-exists-p native-elisp-load)
+ "List of primitives we want to warn about in case of redefinition.
+This are essential for the trampoline machinery to work properly.")
+
+(defun comp-trampoline-search (subr-name)
+ "Search a trampoline file for SUBR-NAME.
+Return the trampoline if found or nil otherwise."
+ (cl-loop
+ with rel-filename = (comp-trampoline-filename subr-name)
+ for dir in (comp-eln-load-path-eff)
+ for filename = (expand-file-name rel-filename dir)
+ when (file-exists-p filename)
+ do (cl-return (native-elisp-load filename))))
+
+(declare-function comp-trampoline-compile "comp")
+;;;###autoload
+(defun comp-subr-trampoline-install (subr-name)
+ "Make SUBR-NAME effectively advice-able when called from native code."
+ (when (memq subr-name comp-warn-primitives)
+ (warn "Redefining `%s' might break native compilation of trampolines."
+ subr-name))
+ (unless (or (null native-comp-enable-subr-trampolines)
+ (memq subr-name native-comp-never-optimize-functions)
+ (gethash subr-name comp-installed-trampolines-h))
+ (cl-assert (subr-primitive-p (symbol-function subr-name)))
+ (when-let ((trampoline (or (comp-trampoline-search subr-name)
+ (comp-trampoline-compile subr-name))))
+ (comp--install-trampoline subr-name trampoline))))
+
+;;;###autoload
+(defun native--compile-async (files &optional recursively load selector)
+ ;; BEWARE, this function is also called directly from C.
+ "Compile FILES asynchronously.
+FILES is one filename or a list of filenames or directories.
+
+If optional argument RECURSIVELY is non-nil, recurse into
+subdirectories of given directories.
+
+If optional argument LOAD is non-nil, request to load the file
+after compiling.
+
+The optional argument SELECTOR has the following valid values:
+
+nil -- Select all files.
+a string -- A regular expression selecting files with matching names.
+a function -- A function selecting files with matching names.
+
+The variable `native-comp-async-jobs-number' specifies the number
+of (commands) to run simultaneously.
+
+LOAD can also be the symbol `late'. This is used internally if
+the byte code has already been loaded when this function is
+called. It means that we request the special kind of load
+necessary in that situation, called \"late\" loading.
+
+During a \"late\" load, instead of executing all top-level forms
+of the original files, only function definitions are
+loaded (paying attention to have these effective only if the
+bytecode definition was not changed in the meantime)."
+ (comp-ensure-native-compiler)
+ (unless (member load '(nil t late))
+ (error "LOAD must be nil, t or 'late"))
+ (unless (listp files)
+ (setf files (list files)))
+ (let ((added-something nil)
+ file-list)
+ (dolist (file-or-dir files)
+ (cond ((file-directory-p file-or-dir)
+ (dolist (file (if recursively
+ (directory-files-recursively
+ file-or-dir comp-valid-source-re)
+ (directory-files file-or-dir
+ t comp-valid-source-re)))
+ (push file file-list)))
+ ((file-exists-p file-or-dir) (push file-or-dir file-list))
+ (t (signal 'native-compiler-error
+ (list "Not a file nor directory" file-or-dir)))))
+ (dolist (file file-list)
+ (if-let ((entry (seq-find (lambda (x) (string= file (car x))) comp-files-queue)))
+ ;; Most likely the byte-compiler has requested a deferred
+ ;; compilation, so update `comp-files-queue' to reflect that.
+ (unless (or (null load)
+ (eq load (cdr entry)))
+ (setf comp-files-queue
+ (cl-loop for i in comp-files-queue
+ with old = (car entry)
+ if (string= (car i) old)
+ collect (cons file load)
+ else
+ collect i)))
+
+ (unless (native-compile-async-skip-p file load selector)
+ (let* ((out-filename (comp-el-to-eln-filename file))
+ (out-dir (file-name-directory out-filename)))
+ (unless (file-exists-p out-dir)
+ (make-directory out-dir t))
+ (if (file-writable-p out-filename)
+ (setf comp-files-queue
+ (append comp-files-queue `((,file . ,load)))
+ added-something t)
+ (display-warning 'comp
+ (format "No write access for %s skipping."
+ out-filename)))))))
+ ;; Perhaps nothing passed `native-compile-async-skip-p'?
+ (when (and added-something
+ ;; Don't start if there's one already running.
+ (zerop (comp-async-runnings)))
+ (comp-run-async-workers))))
+
+;;;###autoload
+(defun native-compile-async (files &optional recursively load selector)
+ "Compile FILES asynchronously.
+FILES is one file or a list of filenames or directories.
+
+If optional argument RECURSIVELY is non-nil, recurse into
+subdirectories of given directories.
+
+If optional argument LOAD is non-nil, request to load the file
+after compiling.
+
+The optional argument SELECTOR has the following valid values:
+
+nil -- Select all files.
+a string -- A regular expression selecting files with matching names.
+a function -- A function selecting files with matching names.
+
+The variable `native-comp-async-jobs-number' specifies the number
+of (commands) to run simultaneously."
+ ;; Normalize: we only want to pass t or nil, never e.g. `late'.
+ (let ((load (not (not load))))
+ (native--compile-async files recursively load selector)))
+
+(provide 'comp-run)
+
+;;; comp-run.el ends here
diff --git a/lisp/emacs-lisp/comp.el b/lisp/emacs-lisp/comp.el
index ad0077dadda..260bd2f1acb 100644
--- a/lisp/emacs-lisp/comp.el
+++ b/lisp/emacs-lisp/comp.el
@@ -1,6 +1,6 @@
;;; comp.el --- compilation of Lisp code into native code -*- lexical-binding: t -*-
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
;; Author: Andrea Corallo <acorallo@gnu.org>
;; Keywords: lisp
@@ -29,32 +29,26 @@
;;; Code:
(require 'bytecomp)
-(require 'cl-extra)
(require 'cl-lib)
-(require 'cl-macs)
-(require 'cl-seq)
(require 'gv)
(require 'rx)
(require 'subr-x)
(require 'warnings)
+(require 'comp-common)
(require 'comp-cstr)
;; These variables and functions are defined in comp.c
-(defvar native-comp-enable-subr-trampolines)
-(defvar comp-installed-trampolines-h)
+(defvar comp-native-version-dir)
(defvar comp-subr-arities-h)
(defvar native-comp-eln-load-path)
-(defvar comp-native-version-dir)
-(defvar comp-deferred-pending-h)
-(defvar comp--no-native-compile)
+(defvar native-comp-enable-subr-trampolines)
-(declare-function comp-el-to-eln-rel-filename "comp.c")
-(declare-function native-elisp-load "comp.c")
-(declare-function comp--release-ctxt "comp.c")
-(declare-function comp--init-ctxt "comp.c")
(declare-function comp--compile-ctxt-to-file "comp.c")
+(declare-function comp--init-ctxt "comp.c")
+(declare-function comp--release-ctxt "comp.c")
(declare-function comp-el-to-eln-filename "comp.c")
-(declare-function comp--install-trampoline "comp.c")
+(declare-function comp-el-to-eln-rel-filename "comp.c")
+(declare-function native-elisp-load "comp.c")
(defgroup comp nil
"Emacs Lisp native compiler."
@@ -86,33 +80,6 @@ This is intended for debugging the compiler itself.
:safe #'natnump
:version "29.1")
-(defcustom native-comp-verbose 0
- "Compiler verbosity for native compilation, a number between 0 and 3.
-This is intended for debugging the compiler itself.
- 0 no logging.
- 1 final LIMPLE is logged.
- 2 LAP, final LIMPLE, and some pass info are logged.
- 3 max verbosity."
- :type 'natnum
- :risky t
- :version "28.1")
-
-(defcustom native-comp-always-compile nil
- "Non-nil means unconditionally (re-)compile all files."
- :type 'boolean
- :version "28.1")
-
-(defcustom native-comp-jit-compilation-deny-list
- '()
- "List of regexps to exclude matching files from deferred native compilation.
-Files whose names match any regexp are excluded from native compilation."
- :type '(repeat regexp)
- :version "28.1")
-
-(make-obsolete-variable 'native-comp-deferred-compilation-deny-list
- 'native-comp-jit-compilation-deny-list
- "29.1")
-
(defcustom native-comp-bootstrap-deny-list
'()
"List of regexps to exclude files from native compilation during bootstrap.
@@ -121,78 +88,6 @@ during bootstrap."
:type '(repeat regexp)
:version "28.1")
-(defcustom native-comp-never-optimize-functions
- '(;; The following two are mandatory for Emacs to be working
- ;; correctly (see comment in `advice--add-function'). DO NOT
- ;; REMOVE.
- macroexpand rename-buffer)
- "Primitive functions to exclude from trampoline optimization.
-
-Primitive functions included in this list will not be called
-directly by the natively-compiled code, which makes trampolines for
-those primitives unnecessary in case of function redefinition/advice."
- :type '(repeat symbol)
- :version "28.1")
-
-(defcustom native-comp-async-jobs-number 0
- "Default number of subprocesses used for async native compilation.
-Value of zero means to use half the number of the CPU's execution units,
-or one if there's just one execution unit."
- :type 'natnum
- :risky t
- :version "28.1")
-
-(defcustom native-comp-async-cu-done-functions nil
- "List of functions to call when asynchronous compilation of a file is done.
-Each function is called with one argument FILE, the filename whose
-compilation has completed."
- :type 'hook
- :version "28.1")
-
-(defcustom native-comp-async-all-done-hook nil
- "Hook run after completing asynchronous compilation of all input files."
- :type 'hook
- :version "28.1")
-
-(defcustom native-comp-async-env-modifier-form nil
- "Form evaluated before compilation by each asynchronous compilation subprocess.
-Used to modify the compiler environment."
- :type 'sexp
- :risky t
- :version "28.1")
-
-(defcustom native-comp-async-report-warnings-errors t
- "Whether to report warnings and errors from asynchronous native compilation.
-
-When native compilation happens asynchronously, it can produce
-warnings and errors, some of which might not be emitted by a
-byte-compilation. The typical case for that is native-compiling
-a file that is missing some `require' of a necessary feature,
-while having it already loaded into the environment when
-byte-compiling.
-
-As asynchronous native compilation always starts from a pristine
-environment, it is more sensitive to such omissions, and might be
-unable to compile such Lisp source files correctly.
-
-Set this variable to nil to suppress warnings altogether, or to
-the symbol `silent' to log warnings but not pop up the *Warnings*
-buffer."
- :type '(choice
- (const :tag "Do not report warnings" nil)
- (const :tag "Report and display warnings" t)
- (const :tag "Report but do not display warnings" silent))
- :version "28.1")
-
-(defcustom native-comp-async-query-on-exit nil
- "Whether to query the user about killing async compilations when exiting.
-If this is non-nil, Emacs will ask for confirmation to exit and kill the
-asynchronous native compilations if any are running. If nil, when you
-exit Emacs, it will silently kill those asynchronous compilations even
-if `confirm-kill-processes' is non-nil."
- :type 'boolean
- :version "28.1")
-
(defcustom native-comp-compiler-options nil
"Command line options passed verbatim to GCC compiler.
Note that not all options are meaningful and some options might even
@@ -248,15 +143,6 @@ Emacs Lisp file:
(defvar comp-dry-run nil
"If non-nil, run everything but the C back-end.")
-(defconst comp-valid-source-re (rx ".el" (? ".gz") eos)
- "Regexp to match filename of valid input source files.")
-
-(defconst comp-log-buffer-name "*Native-compile-Log*"
- "Name of the native-compiler log buffer.")
-
-(defconst comp-async-buffer-name "*Async-native-compile-log*"
- "Name of the async compilation buffer log.")
-
(defvar comp-native-compiling nil
"This gets bound to t during native compilation.
Intended to be used by code that needs to work differently when
@@ -291,346 +177,6 @@ For internal use by the test suite only.")
Each function in FUNCTIONS is run after PASS.
Useful to hook into pass checkers.")
-;; FIXME this probably should not be here but... good for now.
-(defconst comp-known-type-specifiers
- `(
- ;; Functions we can trust not to be redefined, or, if redefined,
- ;; to expose the same type. The vast majority of these are
- ;; either pure or primitive; the original list is the union of
- ;; pure + side-effect-free-fns + side-effect-and-error-free-fns:
- (% (function ((or number marker) (or number marker)) number))
- (* (function (&rest (or number marker)) number))
- (+ (function (&rest (or number marker)) number))
- (- (function (&rest (or number marker)) number))
- (/ (function ((or number marker) &rest (or number marker)) number))
- (/= (function ((or number marker) (or number marker)) boolean))
- (1+ (function ((or number marker)) number))
- (1- (function ((or number marker)) number))
- (< (function ((or number marker) &rest (or number marker)) boolean))
- (<= (function ((or number marker) &rest (or number marker)) boolean))
- (= (function ((or number marker) &rest (or number marker)) boolean))
- (> (function ((or number marker) &rest (or number marker)) boolean))
- (>= (function ((or number marker) &rest (or number marker)) boolean))
- (abs (function (number) number))
- (acos (function (number) float))
- (append (function (&rest t) t))
- (aref (function (t fixnum) t))
- (arrayp (function (t) boolean))
- (ash (function (integer integer) integer))
- (asin (function (number) float))
- (assq (function (t list) list))
- (atan (function (number &optional number) float))
- (atom (function (t) boolean))
- (bignump (function (t) boolean))
- (bobp (function () boolean))
- (bolp (function () boolean))
- (bool-vector-count-consecutive
- (function (bool-vector boolean integer) fixnum))
- (bool-vector-count-population (function (bool-vector) fixnum))
- (bool-vector-not (function (bool-vector &optional bool-vector) bool-vector))
- (bool-vector-p (function (t) boolean))
- (bool-vector-subsetp (function (bool-vector bool-vector) boolean))
- (boundp (function (symbol) boolean))
- (buffer-end (function ((or number marker)) integer))
- (buffer-file-name (function (&optional buffer) (or string null)))
- (buffer-list (function (&optional frame) list))
- (buffer-local-variables (function (&optional buffer) list))
- (buffer-modified-p
- (function (&optional buffer) (or boolean (member autosaved))))
- (buffer-size (function (&optional buffer) integer))
- (buffer-string (function () string))
- (buffer-substring
- (function ((or integer marker) (or integer marker)) string))
- (bufferp (function (t) boolean))
- (byte-code-function-p (function (t) boolean))
- (capitalize (function (or integer string) (or integer string)))
- (car (function (list) t))
- (car-less-than-car (function (list list) boolean))
- (car-safe (function (t) t))
- (case-table-p (function (t) boolean))
- (cdr (function (list) t))
- (cdr-safe (function (t) t))
- (ceiling (function (number &optional number) integer))
- (char-after (function (&optional (or marker integer)) (or fixnum null)))
- (char-before (function (&optional (or marker integer)) (or fixnum null)))
- (char-equal (function (integer integer) boolean))
- (char-or-string-p (function (t) boolean))
- (char-to-string (function (fixnum) string))
- (char-width (function (fixnum) fixnum))
- (characterp (function (t &optional t) boolean))
- (charsetp (function (t) boolean))
- (commandp (function (t &optional t) boolean))
- (compare-strings
- (function (string (or integer marker null) (or integer marker null) string
- (or integer marker null) (or integer marker null)
- &optional t)
- (or (member t) fixnum)))
- (concat (function (&rest sequence) string))
- (cons (function (t t) cons))
- (consp (function (t) boolean))
- (coordinates-in-window-p
- (function (cons window)
- (or cons null
- (member bottom-divider right-divider mode-line header-line
- tab-line left-fringe right-fringe vertical-line
- left-margin right-margin))))
- (copy-alist (function (list) list))
- (copy-marker (function (&optional (or integer marker) boolean) marker))
- (copy-sequence (function (sequence) sequence))
- (copysign (function (float float) float))
- (cos (function (number) float))
- (count-lines
- (function ((or integer marker) (or integer marker) &optional t) integer))
- (current-buffer (function () buffer))
- (current-global-map (function () cons))
- (current-indentation (function () integer))
- (current-local-map (function () (or cons null)))
- (current-minor-mode-maps (function () (or cons null)))
- (current-time (function () cons))
- (current-time-string (function (&optional (or number list)
- (or symbol string cons integer))
- string))
- (current-time-zone (function (&optional (or number list)
- (or symbol string cons integer))
- cons))
- (custom-variable-p (function (symbol) t))
- (decode-char (function (cons t) (or fixnum null)))
- (decode-time (function (&optional (or number list)
- (or symbol string cons integer)
- symbol)
- cons))
- (default-boundp (function (symbol) boolean))
- (default-value (function (symbol) t))
- (degrees-to-radians (function (number) float))
- (documentation
- (function ((or function symbol subr) &optional t) (or null string)))
- (downcase (function ((or fixnum string)) (or fixnum string)))
- (elt (function (sequence integer) t))
- (encode-char (function (fixnum symbol) (or fixnum null)))
- (encode-time (function (cons &rest t) cons))
- (eobp (function () boolean))
- (eolp (function () boolean))
- (eq (function (t t) boolean))
- (eql (function (t t) boolean))
- (equal (function (t t) boolean))
- (error-message-string (function (list) string))
- (eventp (function (t) boolean))
- (exp (function (number) float))
- (expt (function (number number) number))
- (fboundp (function (symbol) boolean))
- (fceiling (function (float) float))
- (featurep (function (symbol &optional symbol) boolean))
- (ffloor (function (float) float))
- (file-directory-p (function (string) boolean))
- (file-exists-p (function (string) boolean))
- (file-locked-p (function (string) (or boolean string)))
- (file-name-absolute-p (function (string) boolean))
- (file-newer-than-file-p (function (string string) boolean))
- (file-readable-p (function (string) boolean))
- (file-symlink-p (function (string) (or boolean string)))
- (file-writable-p (function (string) boolean))
- (fixnump (function (t) boolean))
- (float (function (number) float))
- (float-time (function (&optional (or number list)) float))
- (floatp (function (t) boolean))
- (floor (function (number &optional number) integer))
- (following-char (function () fixnum))
- (format (function (string &rest t) string))
- (format-time-string (function (string &optional (or number list)
- (or symbol string cons integer))
- string))
- (frame-first-window (function ((or frame window)) window))
- (frame-root-window (function (&optional (or frame window)) window))
- (frame-selected-window (function (&optional (or frame window)) window))
- (frame-visible-p (function (frame) (or boolean (member icon))))
- (framep (function (t) symbol))
- (fround (function (float) float))
- (ftruncate (function (float) float))
- (get (function (symbol symbol) t))
- (get-buffer (function ((or buffer string)) (or buffer null)))
- (get-buffer-window
- (function (&optional (or buffer string) (or symbol (integer 0 0)))
- (or null window)))
- (get-file-buffer (function (string) (or null buffer)))
- (get-largest-window (function (&optional t t t) (or window null)))
- (get-lru-window (function (&optional t t t) (or window null)))
- (getenv (function (string &optional frame) (or null string)))
- (gethash (function (t hash-table &optional t) t))
- (hash-table-count (function (hash-table) integer))
- (hash-table-p (function (t) boolean))
- (identity (function (t) t))
- (ignore (function (&rest t) null))
- (int-to-string (function (number) string))
- (integer-or-marker-p (function (t) boolean))
- (integerp (function (t) boolean))
- (interactive-p (function () boolean))
- (intern-soft (function ((or string symbol) &optional vector) symbol))
- (invocation-directory (function () string))
- (invocation-name (function () string))
- (isnan (function (float) boolean))
- (keymap-parent (function (cons) (or cons null)))
- (keymapp (function (t) boolean))
- (keywordp (function (t) boolean))
- (last (function (list &optional integer) list))
- (lax-plist-get (function (list t) t))
- (ldexp (function (number integer) float))
- (length (function (t) (integer 0 *)))
- (length< (function (sequence fixnum) boolean))
- (length= (function (sequence fixnum) boolean))
- (length> (function (sequence fixnum) boolean))
- (line-beginning-position (function (&optional integer) integer))
- (line-end-position (function (&optional integer) integer))
- (list (function (&rest t) list))
- (listp (function (t) boolean))
- (local-variable-if-set-p (function (symbol &optional buffer) boolean))
- (local-variable-p (function (symbol &optional buffer) boolean))
- (locale-info (function ((member codeset days months paper)) (or null string)))
- (log (function (number number) float))
- (log10 (function (number) float))
- (logand (function (&rest (or integer marker)) integer))
- (logb (function (number) integer))
- (logcount (function (integer) integer))
- (logior (function (&rest (or integer marker)) integer))
- (lognot (function (integer) integer))
- (logxor (function (&rest (or integer marker)) integer))
- ;; (lsh (function ((integer ,most-negative-fixnum *) integer) integer)) ?
- (lsh (function (integer integer) integer))
- (make-byte-code
- (function ((or fixnum list) string vector integer &optional string t
- &rest t)
- vector))
- (make-list (function (integer t) list))
- (make-marker (function () marker))
- (make-string (function (integer fixnum &optional t) string))
- (make-symbol (function (string) symbol))
- (mark (function (&optional t) (or integer null)))
- (mark-marker (function () marker))
- (marker-buffer (function (marker) (or buffer null)))
- (markerp (function (t) boolean))
- (max (function ((or number marker) &rest (or number marker)) number))
- (max-char (function (&optional t) fixnum))
- (member (function (t list) list))
- (memory-limit (function () integer))
- (memq (function (t list) list))
- (memql (function (t list) list))
- (min (function ((or number marker) &rest (or number marker)) number))
- (minibuffer-selected-window (function () (or window null)))
- (minibuffer-window (function (&optional frame) window))
- (mod
- (function ((or number marker) (or number marker))
- (or (integer 0 *) (float 0 *))))
- (mouse-movement-p (function (t) boolean))
- (multibyte-char-to-unibyte (function (fixnum) fixnum))
- (natnump (function (t) boolean))
- (next-window (function (&optional window t t) window))
- (nlistp (function (t) boolean))
- (not (function (t) boolean))
- (nth (function (integer list) t))
- (nthcdr (function (integer t) t))
- (null (function (t) boolean))
- (number-or-marker-p (function (t) boolean))
- (number-to-string (function (number) string))
- (numberp (function (t) boolean))
- (one-window-p (function (&optional t t) boolean))
- (overlayp (function (t) boolean))
- (parse-colon-path (function (string) cons))
- (plist-get (function (list t &optional t) t))
- (plist-member (function (list t &optional t) list))
- (point (function () integer))
- (point-marker (function () marker))
- (point-max (function () integer))
- (point-min (function () integer))
- (preceding-char (function () fixnum))
- (previous-window (function (&optional window t t) window))
- (prin1-to-string (function (t &optional t t) string))
- (processp (function (t) boolean))
- (proper-list-p (function (t) (or fixnum null)))
- (propertize (function (string &rest t) string))
- (radians-to-degrees (function (number) float))
- (rassoc (function (t list) list))
- (rassq (function (t list) list))
- (read-from-string (function (string &optional integer integer) cons))
- (recent-keys (function (&optional (or cons null)) vector))
- (recursion-depth (function () integer))
- (regexp-opt (function (list) string))
- (regexp-quote (function (string) string))
- (region-beginning (function () integer))
- (region-end (function () integer))
- (reverse (function (sequence) sequence))
- (round (function (number &optional number) integer))
- (safe-length (function (t) integer))
- (selected-frame (function () frame))
- (selected-window (function () window))
- (sequencep (function (t) boolean))
- (sin (function (number) float))
- (sqrt (function (number) float))
- (standard-case-table (function () char-table))
- (standard-syntax-table (function () char-table))
- (string (function (&rest fixnum) string))
- (string-as-multibyte (function (string) string))
- (string-as-unibyte (function (string) string))
- (string-equal (function ((or string symbol) (or string symbol)) boolean))
- (string-lessp (function ((or string symbol) (or string symbol)) boolean))
- (string-make-multibyte (function (string) string))
- (string-make-unibyte (function (string) string))
- (string-search (function (string string &optional integer) (or integer null)))
- (string-to-char (function (string) fixnum))
- (string-to-multibyte (function (string) string))
- (string-to-number (function (string &optional integer) number))
- (string-to-syntax (function (string) (or cons null)))
- (string< (function ((or string symbol) (or string symbol)) boolean))
- (string= (function ((or string symbol) (or string symbol)) boolean))
- (stringp (function (t) boolean))
- (subrp (function (t) boolean))
- (substring
- (function ((or string vector) &optional integer integer) (or string vector)))
- (sxhash (function (t) integer))
- (sxhash-eq (function (t) integer))
- (sxhash-eql (function (t) integer))
- (sxhash-equal (function (t) integer))
- (symbol-function (function (symbol) t))
- (symbol-name (function (symbol) string))
- (symbol-plist (function (symbol) list))
- (symbol-value (function (symbol) t))
- (symbolp (function (t) boolean))
- (syntax-table (function () char-table))
- (syntax-table-p (function (t) boolean))
- (tan (function (number) float))
- (this-command-keys (function () string))
- (this-command-keys-vector (function () vector))
- (this-single-command-keys (function () vector))
- (this-single-command-raw-keys (function () vector))
- (time-convert (function ((or number list) &optional (or symbol integer))
- (or cons number)))
- (truncate (function (number &optional number) integer))
- (type-of (function (t) symbol))
- (unibyte-char-to-multibyte (function (fixnum) fixnum)) ;; byte is fixnum
- (upcase (function ((or fixnum string)) (or fixnum string)))
- (user-full-name (function (&optional integer) (or string null)))
- (user-login-name (function (&optional integer) (or string null)))
- (user-original-login-name (function (&optional integer) (or string null)))
- (user-real-login-name (function () string))
- (user-real-uid (function () integer))
- (user-uid (function () integer))
- (vconcat (function (&rest sequence) vector))
- (vector (function (&rest t) vector))
- (vectorp (function (t) boolean))
- (visible-frame-list (function () list))
- (wholenump (function (t) boolean))
- (window-configuration-p (function (t) boolean))
- (window-live-p (function (t) boolean))
- (window-valid-p (function (t) boolean))
- (windowp (function (t) boolean))
- (zerop (function (number) boolean))
- ;; Type hints
- (comp-hint-fixnum (function (t) fixnum))
- (comp-hint-cons (function (t) cons))
- ;; Non returning functions
- (throw (function (t t) nil))
- (error (function (string &rest t) nil))
- (signal (function (symbol t) nil)))
- "Alist used for type propagation.")
-
(defconst comp-known-func-cstr-h
(cl-loop
with comp-ctxt = (make-comp-cstr-ctxt)
@@ -678,13 +224,13 @@ Useful to hook into pass checkers.")
finally return h)
"Hash table function -> `comp-constraint'.")
-(defun comp-known-predicate-p (predicate)
+(defun comp--known-predicate-p (predicate)
"Return t if PREDICATE is known."
(when (or (gethash predicate comp-known-predicates-h)
(gethash predicate (comp-cstr-ctxt-pred-type-h comp-ctxt)))
t))
-(defun comp-pred-to-cstr (predicate)
+(defun comp--pred-to-cstr (predicate)
"Given PREDICATE, return the corresponding constraint."
(or (gethash predicate comp-known-predicates-h)
(gethash predicate (comp-cstr-ctxt-pred-type-h comp-ctxt))))
@@ -697,33 +243,6 @@ Useful to hook into pass checkers.")
comp-hint-cons)
"List of fake functions used to give compiler hints.")
-(defconst comp-limple-sets '(set
- setimm
- set-par-to-local
- set-args-to-local
- set-rest-args-to-local)
- "Limple set operators.")
-
-(defconst comp-limple-assignments `(assume
- fetch-handler
- ,@comp-limple-sets)
- "Limple operators that clobber the first m-var argument.")
-
-(defconst comp-limple-calls '(call
- callref
- direct-call
- direct-callref)
- "Limple operators used to call subrs.")
-
-(defconst comp-limple-branches '(jump cond-jump)
- "Limple operators used for conditional and unconditional branches.")
-
-(defconst comp-limple-ops `(,@comp-limple-calls
- ,@comp-limple-assignments
- ,@comp-limple-branches
- return)
- "All Limple operators.")
-
(defvar comp-func nil
"Bound to the current function by most passes.")
@@ -741,30 +260,6 @@ Useful to hook into pass checkers.")
(defvar comp-no-spawn nil
"Non-nil don't spawn native compilation processes.")
-(defconst comp-warn-primitives
- '(null memq gethash and subrp not subr-native-elisp-p
- comp--install-trampoline concat if symbolp symbol-name make-string
- length aset aref length> mapcar expand-file-name
- file-name-as-directory file-exists-p native-elisp-load)
- "List of primitives we want to warn about in case of redefinition.
-This are essential for the trampoline machinery to work properly.")
-
-;; Moved early to avoid circularity when comp.el is loaded and
-;; `macroexpand' needs to be advised (bug#47049).
-;;;###autoload
-(defun comp-subr-trampoline-install (subr-name)
- "Make SUBR-NAME effectively advice-able when called from native code."
- (when (memq subr-name comp-warn-primitives)
- (warn "Redefining `%s' might break native compilation of trampolines."
- subr-name))
- (unless (or (null native-comp-enable-subr-trampolines)
- (memq subr-name native-comp-never-optimize-functions)
- (gethash subr-name comp-installed-trampolines-h))
- (cl-assert (subr-primitive-p (symbol-function subr-name)))
- (when-let ((trampoline (or (comp-trampoline-search subr-name)
- (comp-trampoline-compile subr-name))))
- (comp--install-trampoline subr-name trampoline))))
-
(cl-defstruct (comp-vec (:copier nil))
"A re-sizable vector like object."
@@ -935,7 +430,7 @@ non local exit (ends with an `unreachable' insn)."))
(:include comp-block))
"A basic block holding only constraints.")
-(cl-defstruct (comp-edge (:copier nil) (:constructor make--comp-edge))
+(cl-defstruct (comp-edge (:copier nil) (:constructor comp--edge-make0))
"An edge connecting two basic blocks."
(src nil :type (or null comp-block))
(dst nil :type (or null comp-block))
@@ -943,19 +438,19 @@ non local exit (ends with an `unreachable' insn)."))
:documentation "The index number corresponding to this edge in the
edge hash."))
-(defun make-comp-edge (&rest args)
+(defun comp--edge-make (&rest args)
"Create a `comp-edge' with basic blocks SRC and DST."
(let ((n (funcall (comp-func-edge-cnt-gen comp-func))))
(puthash
n
- (apply #'make--comp-edge :number n args)
+ (apply #'comp--edge-make0 :number n args)
(comp-func-edges-h comp-func))))
-(defun comp-block-preds (basic-block)
+(defun comp--block-preds (basic-block)
"Return the list of predecessors of BASIC-BLOCK."
(mapcar #'comp-edge-src (comp-block-in-edges basic-block)))
-(defun comp-gen-counter ()
+(defun comp--gen-counter ()
"Return a sequential number generator."
(let ((n -1))
(lambda ()
@@ -989,9 +484,9 @@ CFG is mutated by a pass.")
:documentation "LAP label -> LIMPLE basic block name.")
(edges-h (make-hash-table) :type hash-table
:documentation "Hash edge-num -> edge connecting basic two blocks.")
- (block-cnt-gen (funcall #'comp-gen-counter) :type function
+ (block-cnt-gen (funcall #'comp--gen-counter) :type function
:documentation "Generates block numbers.")
- (edge-cnt-gen (funcall #'comp-gen-counter) :type function
+ (edge-cnt-gen (funcall #'comp--gen-counter) :type function
:documentation "Generates edges numbers.")
(has-non-local nil :type boolean
:documentation "t if non local jumps are present.")
@@ -1030,49 +525,39 @@ In use by the back-end."
-(defun comp-ensure-native-compiler ()
- "Make sure Emacs has native compiler support and libgccjit can be loaded.
-Signal an error otherwise.
-To be used by all entry points."
- (cond
- ((null (featurep 'native-compile))
- (error "Emacs was not compiled with native compiler support (--with-native-compilation)"))
- ((null (native-comp-available-p))
- (error "Cannot find libgccjit library"))))
-
-(defun comp-equality-fun-p (function)
+(defun comp--equality-fun-p (function)
"Equality functions predicate for FUNCTION."
(when (memq function '(eq eql equal)) t))
-(defun comp-arithm-cmp-fun-p (function)
+(defun comp--arithm-cmp-fun-p (function)
"Predicate for arithmetic comparison functions."
(when (memq function '(= > < >= <=)) t))
-(defun comp-set-op-p (op)
+(defun comp--set-op-p (op)
"Assignment predicate for OP."
(when (memq op comp-limple-sets) t))
-(defun comp-assign-op-p (op)
+(defun comp--assign-op-p (op)
"Assignment predicate for OP."
(when (memq op comp-limple-assignments) t))
-(defun comp-call-op-p (op)
+(defun comp--call-op-p (op)
"Call predicate for OP."
(when (memq op comp-limple-calls) t))
-(defun comp-branch-op-p (op)
+(defun comp--branch-op-p (op)
"Branch predicate for OP."
(when (memq op comp-limple-branches) t))
-(defsubst comp-limple-insn-call-p (insn)
+(defsubst comp--limple-insn-call-p (insn)
"Limple INSN call predicate."
- (comp-call-op-p (car-safe insn)))
+ (comp--call-op-p (car-safe insn)))
-(defun comp-type-hint-p (func)
+(defun comp--type-hint-p (func)
"Type-hint predicate for function name FUNC."
(when (memq func comp-type-hints) t))
-(defun comp-func-unique-in-cu-p (func)
+(defun comp--func-unique-in-cu-p (func)
"Return t if FUNC is known to be unique in the current compilation unit."
(if (symbolp func)
(cl-loop with h = (make-hash-table :test #'eq)
@@ -1084,111 +569,46 @@ To be used by all entry points."
finally return t)
t))
-(defsubst comp-symbol-func-to-fun (symbol-funcion)
+(defsubst comp--symbol-func-to-fun (symbol-funcion)
"Given a function called SYMBOL-FUNCION return its `comp-func'."
(gethash (gethash symbol-funcion (comp-ctxt-sym-to-c-name-h
comp-ctxt))
(comp-ctxt-funcs-h comp-ctxt)))
-(defun comp-function-pure-p (f)
+(defun comp--function-pure-p (f)
"Return t if F is pure."
(or (get f 'pure)
- (when-let ((func (comp-symbol-func-to-fun f)))
+ (when-let ((func (comp--symbol-func-to-fun f)))
(comp-func-pure func))))
-(defun comp-alloc-class-to-container (alloc-class)
+(defun comp--alloc-class-to-container (alloc-class)
"Given ALLOC-CLASS, return the data container for the current context.
Assume allocation class `d-default' as default."
(cl-struct-slot-value 'comp-ctxt (or alloc-class 'd-default) comp-ctxt))
-(defsubst comp-add-const-to-relocs (obj)
+(defsubst comp--add-const-to-relocs (obj)
"Keep track of OBJ into the ctxt relocations."
- (puthash obj t (comp-data-container-idx (comp-alloc-class-to-container
+ (puthash obj t (comp-data-container-idx (comp--alloc-class-to-container
comp-curr-allocation-class))))
;;; Log routines.
-(defconst comp-limple-lock-keywords
- `((,(rx bol "(comment" (1+ not-newline)) . font-lock-comment-face)
- (,(rx "#(" (group-n 1 "mvar"))
- (1 font-lock-function-name-face))
- (,(rx bol "(" (group-n 1 "phi"))
- (1 font-lock-variable-name-face))
- (,(rx bol "(" (group-n 1 (or "return" "unreachable")))
- (1 font-lock-warning-face))
- (,(rx (group-n 1 (or "entry"
- (seq (or "entry_" "entry_fallback_" "bb_")
- (1+ num) (? (or "_latch"
- (seq "_cstrs_" (1+ num))))))))
- (1 font-lock-constant-face))
- (,(rx-to-string
- `(seq "(" (group-n 1 (or ,@(mapcar #'symbol-name comp-limple-ops)))))
- (1 font-lock-keyword-face)))
- "Highlights used by `native-comp-limple-mode'.")
-
-(define-derived-mode native-comp-limple-mode fundamental-mode "LIMPLE"
- "Syntax-highlight LIMPLE IR."
- (setf font-lock-defaults '(comp-limple-lock-keywords)))
-
-(cl-defun comp-log (data &optional (level 1) quoted)
- "Log DATA at LEVEL.
-LEVEL is a number from 1-3, and defaults to 1; if it is less
-than `native-comp-verbose', do nothing. If `noninteractive', log
-with `message'. Otherwise, log with `comp-log-to-buffer'."
- (when (>= native-comp-verbose level)
- (if noninteractive
- (cl-typecase data
- (atom (message "%s" data))
- (t (dolist (elem data)
- (message "%s" elem))))
- (comp-log-to-buffer data quoted))))
-
-(cl-defun comp-log-to-buffer (data &optional quoted)
- "Log DATA to `comp-log-buffer-name'."
- (let* ((print-f (if quoted #'prin1 #'princ))
- (log-buffer
- (or (get-buffer comp-log-buffer-name)
- (with-current-buffer (get-buffer-create comp-log-buffer-name)
- (unless (derived-mode-p 'compilation-mode)
- (emacs-lisp-compilation-mode))
- (current-buffer))))
- (log-window (get-buffer-window log-buffer))
- (inhibit-read-only t)
- at-end-p)
- (with-current-buffer log-buffer
- (unless (eq major-mode 'native-comp-limple-mode)
- (native-comp-limple-mode))
- (when (= (point) (point-max))
- (setf at-end-p t))
- (save-excursion
- (goto-char (point-max))
- (cl-typecase data
- (atom (funcall print-f data log-buffer))
- (t (dolist (elem data)
- (funcall print-f elem log-buffer)
- (insert "\n"))))
- (insert "\n"))
- (when (and at-end-p log-window)
- ;; When log window's point is at the end, follow the tail.
- (with-selected-window log-window
- (goto-char (point-max)))))))
-
-(defun comp-prettyformat-mvar (mvar)
+(defun comp--prettyformat-mvar (mvar)
(format "#(mvar %s %s %S)"
(comp-mvar-id mvar)
(comp-mvar-slot mvar)
(comp-cstr-to-type-spec mvar)))
-(defun comp-prettyformat-insn (insn)
+(defun comp--prettyformat-insn (insn)
(cond
((comp-mvar-p insn)
- (comp-prettyformat-mvar insn))
+ (comp--prettyformat-mvar insn))
((proper-list-p insn)
- (concat "(" (mapconcat #'comp-prettyformat-insn insn " ") ")"))
+ (concat "(" (mapconcat #'comp--prettyformat-insn insn " ") ")"))
(t (prin1-to-string insn))))
-(defun comp-log-func (func verbosity)
+(defun comp--log-func (func verbosity)
"Log function FUNC at VERBOSITY.
VERBOSITY is a number between 0 and 3."
(when (>= native-comp-verbose verbosity)
@@ -1199,9 +619,9 @@ VERBOSITY is a number between 0 and 3."
do (comp-log (concat "<" (symbol-name block-name) ">") verbosity)
(cl-loop
for insn in (comp-block-insns bb)
- do (comp-log (comp-prettyformat-insn insn) verbosity)))))
+ do (comp-log (comp--prettyformat-insn insn) verbosity)))))
-(defun comp-log-edges (func)
+(defun comp--log-edges (func)
"Log edges in FUNC."
(let ((edges (comp-func-edges-h func)))
(comp-log (format "\nEdges in function: %s\n"
@@ -1319,86 +739,31 @@ clashes."
nil ".eln")))
(let* ((f (symbol-function function-name))
(byte-code (byte-compile function-name))
- (c-name (comp-c-func-name function-name "F"))
- (func
- (if (comp-lex-byte-func-p byte-code)
- (make-comp-func-l :name function-name
- :c-name c-name
- :doc (documentation f t)
- :int-spec (interactive-form f)
- :command-modes (command-modes f)
- :speed (comp-spill-speed function-name)
- :pure (comp-spill-decl-spec function-name
- 'pure))
- (make-comp-func-d :name function-name
- :c-name c-name
- :doc (documentation f t)
- :int-spec (interactive-form f)
- :command-modes (command-modes f)
- :speed (comp-spill-speed function-name)
- :pure (comp-spill-decl-spec function-name
- 'pure)))))
+ (c-name (comp-c-func-name function-name "F")))
(when (byte-code-function-p f)
(signal 'native-compiler-error
'("can't native compile an already byte-compiled function")))
- (setf (comp-func-byte-func func) byte-code)
- (let ((lap (byte-to-native-lambda-lap
- (gethash (aref (comp-func-byte-func func) 1)
- byte-to-native-lambdas-h))))
- (cl-assert lap)
- (comp-log lap 2 t)
- (if (comp-func-l-p func)
- (let ((arg-list (aref (comp-func-byte-func func) 0)))
- (setf (comp-func-l-args func)
- (comp-decrypt-arg-list arg-list function-name)))
- (setf (comp-func-d-lambda-list func) (cadr f)))
- (setf (comp-func-lap func)
- lap
- (comp-func-frame-size func)
- (comp-byte-frame-size (comp-func-byte-func func))
- (comp-ctxt-top-level-forms comp-ctxt)
+ (setf (comp-ctxt-top-level-forms comp-ctxt)
(list (make-byte-to-native-func-def :name function-name
- :c-name c-name)))
- (comp-add-func-to-ctxt func))))
+ :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)
+ (unless (memq (car-safe form) '(lambda closure))
(signal 'native-compiler-error
- '("Cannot native-compile, form is not a lambda")))
+ '("Cannot native-compile, form is not a lambda or closure")))
(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))
- (c-name (comp-c-func-name "anonymous-lambda" "F"))
- (func (if (comp-lex-byte-func-p byte-code)
- (make-comp-func-l :c-name c-name
- :doc (documentation form t)
- :int-spec (interactive-form form)
- :command-modes (command-modes form)
- :speed (comp-ctxt-speed comp-ctxt))
- (make-comp-func-d :c-name c-name
- :doc (documentation form t)
- :int-spec (interactive-form form)
- :command-modes (command-modes form)
- :speed (comp-ctxt-speed comp-ctxt)))))
- (let ((lap (byte-to-native-lambda-lap
- (gethash (aref byte-code 1)
- byte-to-native-lambdas-h))))
- (cl-assert lap)
- (comp-log lap 2 t)
- (if (comp-func-l-p func)
- (setf (comp-func-l-args func)
- (comp-decrypt-arg-list (aref byte-code 0) byte-code))
- (setf (comp-func-d-lambda-list func) (cadr form)))
- (setf (comp-func-lap func) lap
- (comp-func-frame-size func) (comp-byte-frame-size
- byte-code))
- (setf (comp-func-byte-func func) byte-code
- (comp-ctxt-top-level-forms comp-ctxt)
+ (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)))
- (comp-add-func-to-ctxt func))))
+ :c-name c-name
+ :byte-func byte-code)))
+ (maphash #'comp-intern-func-in-ctxt byte-to-native-lambdas-h)))
(defun comp-intern-func-in-ctxt (_ obj)
"Given OBJ of type `byte-to-native-lambda', create a function in `comp-ctxt'."
@@ -1598,7 +963,7 @@ STACK-OFF is the index of the first slot frame involved."
"`comp-mvar' initializer."
(let ((mvar (make--comp-mvar :slot slot)))
(when const-vld
- (comp-add-const-to-relocs constant)
+ (comp--add-const-to-relocs constant)
(setf (comp-cstr-imm mvar) constant))
(when type
(setf (comp-mvar-typeset mvar) (list type)))
@@ -1643,7 +1008,7 @@ If DST-N is specified, use it; otherwise assume it to be the current slot."
(defsubst comp-emit-setimm (val)
"Set constant VAL to current slot."
- (comp-add-const-to-relocs val)
+ (comp--add-const-to-relocs val)
;; Leave relocation index nil on purpose, will be fixed-up in final
;; by `comp-finalize-relocs'.
(comp-emit `(setimm ,(comp-slot) ,val)))
@@ -1851,7 +1216,7 @@ SP-DELTA is the stack adjustment."
(eval-when-compile
(defun comp-op-to-fun (x)
"Given the LAP op strip \"byte-\" to have the subr name."
- (intern (replace-regexp-in-string "byte-" "" x)))
+ (intern (string-replace "byte-" "" x)))
(defun comp-body-eff (body op-name sp-delta)
"Given the original BODY, compute the effective one.
@@ -2131,7 +1496,7 @@ and the annotation emission."
(cl-loop for bb being the hash-value in (comp-func-blocks func)
do (setf (comp-block-insns bb)
(nreverse (comp-block-insns bb))))
- (comp-log-func func 2)
+ (comp--log-func func 2)
func)
(cl-defgeneric comp-prepare-args-for-top-level (function)
@@ -2205,7 +1570,7 @@ and the annotation emission."
These are stored in the reloc data array."
(let ((args (comp-prepare-args-for-top-level func)))
(let ((comp-curr-allocation-class 'd-impure))
- (comp-add-const-to-relocs (comp-func-byte-func func)))
+ (comp--add-const-to-relocs (comp-func-byte-func func)))
(comp-emit
(comp-call 'comp--register-lambda
;; mvar to be fixed-up when containers are
@@ -2408,7 +1773,7 @@ into the C code forwarding the compilation unit."
do (cl-loop
for insn in (comp-block-insns b)
for (op . args) = insn
- if (comp-assign-op-p op)
+ if (comp--assign-op-p op)
do (comp-collect-mvars (cdr args))
else
do (comp-collect-mvars args))))
@@ -2457,7 +1822,7 @@ The assume is emitted at the beginning of the block BB."
(comp-cstr-negation-make rhs)
rhs)))
(comp-block-insns bb))))
- ((pred comp-arithm-cmp-fun-p)
+ ((pred comp--arithm-cmp-fun-p)
(when-let ((kind (if negated
(comp-negate-arithm-cmp-fun kind)
kind)))
@@ -2490,7 +1855,7 @@ Return OP otherwise."
(cl-loop
with new-bb = (make-comp-block-cstr :name bb-symbol
:insns `((jump ,(comp-block-name bb-b))))
- with new-edge = (make-comp-edge :src bb-a :dst new-bb)
+ with new-edge = (comp--edge-make :src bb-a :dst new-bb)
for ed in (comp-block-in-edges bb-b)
when (eq (comp-edge-src ed) bb-a)
do
@@ -2521,7 +1886,7 @@ Keep on searching till EXIT-INSN is encountered."
when (eq insn exit-insn)
do (cl-return (and (comp-mvar-p res) res))
do (pcase insn
- (`(,(pred comp-assign-op-p) ,(pred targetp) ,rhs)
+ (`(,(pred comp--assign-op-p) ,(pred targetp) ,rhs)
(setf res rhs)))
finally (cl-assert nil))))
@@ -2602,14 +1967,18 @@ TARGET-BB-SYM is the symbol name of the target block."
(set ,(and (pred comp-mvar-p) mvar-3)
(call memq ,(and (pred comp-mvar-p) mvar-1) ,(and (pred comp-mvar-p) mvar-2)))
(cond-jump ,(and (pred comp-mvar-p) mvar-3) ,(pred comp-mvar-p) ,bb1 ,bb2))
- (push `(assume ,mvar-tested ,(make-comp-mvar :type (comp-cstr-cl-tag mvar-tag)))
- (comp-block-insns (comp-add-cond-cstrs-target-block b bb2)))
- (push `(assume ,mvar-tested ,(make-comp-mvar :type (comp-cstr-cl-tag mvar-tag) :neg t))
- (comp-block-insns (comp-add-cond-cstrs-target-block b bb1))))
+ (comp-emit-assume 'and mvar-tested
+ (make-comp-mvar :type (comp-cstr-cl-tag mvar-tag))
+ (comp-add-cond-cstrs-target-block b bb2)
+ nil)
+ (comp-emit-assume 'and mvar-tested
+ (make-comp-mvar :type (comp-cstr-cl-tag mvar-tag))
+ (comp-add-cond-cstrs-target-block b bb1)
+ t))
(`((set ,(and (pred comp-mvar-p) cmp-res)
- (,(pred comp-call-op-p)
- ,(and (or (pred comp-equality-fun-p)
- (pred comp-arithm-cmp-fun-p))
+ (,(pred comp--call-op-p)
+ ,(and (or (pred comp--equality-fun-p)
+ (pred comp--arithm-cmp-fun-p))
fun)
,op1 ,op2))
;; (comment ,_comment-str)
@@ -2641,14 +2010,14 @@ TARGET-BB-SYM is the symbol name of the target block."
block-target negated)))
finally (cl-return-from in-the-basic-block)))
(`((set ,(and (pred comp-mvar-p) cmp-res)
- (,(pred comp-call-op-p)
- ,(and (pred comp-known-predicate-p) fun)
+ (,(pred comp--call-op-p)
+ ,(and (pred comp--known-predicate-p) fun)
,op))
;; (comment ,_comment-str)
(cond-jump ,cmp-res ,(pred comp-mvar-p) . ,blocks))
(cl-loop
with target-mvar = (comp-cond-cstrs-target-mvar op (car insns-seq) b)
- with cstr = (comp-pred-to-cstr fun)
+ with cstr = (comp--pred-to-cstr fun)
for branch-target-cell on blocks
for branch-target = (car branch-target-cell)
for negated in '(t nil)
@@ -2660,14 +2029,14 @@ TARGET-BB-SYM is the symbol name of the target block."
finally (cl-return-from in-the-basic-block)))
;; Match predicate on the negated branch (unless).
(`((set ,(and (pred comp-mvar-p) cmp-res)
- (,(pred comp-call-op-p)
- ,(and (pred comp-known-predicate-p) fun)
+ (,(pred comp--call-op-p)
+ ,(and (pred comp--known-predicate-p) fun)
,op))
(set ,neg-cmp-res (call eq ,cmp-res ,(pred comp-cstr-null-p)))
(cond-jump ,neg-cmp-res ,(pred comp-mvar-p) . ,blocks))
(cl-loop
with target-mvar = (comp-cond-cstrs-target-mvar op (car insns-seq) b)
- with cstr = (comp-pred-to-cstr fun)
+ with cstr = (comp--pred-to-cstr fun)
for branch-target-cell on blocks
for branch-target = (car branch-target-cell)
for negated in '(nil t)
@@ -2719,10 +2088,10 @@ TARGET-BB-SYM is the symbol name of the target block."
(comp-loop-insn-in-block bb
(when-let ((match
(pcase insn
- (`(set ,lhs (,(pred comp-call-op-p) ,f . ,args))
+ (`(set ,lhs (,(pred comp--call-op-p) ,f . ,args))
(when-let ((cstr-f (gethash f comp-known-func-cstr-h)))
(cl-values f cstr-f lhs args)))
- (`(,(pred comp-call-op-p) ,f . ,args)
+ (`(,(pred comp--call-op-p) ,f . ,args)
(when-let ((cstr-f (gethash f comp-known-func-cstr-h)))
(cl-values f cstr-f nil args))))))
(cl-multiple-value-bind (f cstr-f lhs args) match
@@ -2761,7 +2130,7 @@ blocks."
(comp-add-cond-cstrs-simple)
(comp-add-cond-cstrs)
(comp-add-call-cstr)
- (comp-log-func comp-func 3))))
+ (comp--log-func comp-func 3))))
(comp-ctxt-funcs-h comp-ctxt)))
@@ -2780,9 +2149,9 @@ blocks."
do (cl-loop
for insn in (comp-block-insns b)
do (pcase insn
- (`(set ,_lval (,(pred comp-call-op-p) ,f . ,_rest))
+ (`(set ,_lval (,(pred comp--call-op-p) ,f . ,_rest))
(puthash f t h))
- (`(,(pred comp-call-op-p) ,f . ,_rest)
+ (`(,(pred comp--call-op-p) ,f . ,_rest)
(puthash f t h))))
finally return (cl-loop
for f being each hash-key of h
@@ -2795,7 +2164,7 @@ blocks."
(defun comp-pure-infer-func (f)
"If all functions called by F are pure then F is pure too."
(when (and (cl-every (lambda (x)
- (or (comp-function-pure-p x)
+ (or (comp--function-pure-p x)
(eq x (comp-func-name f))))
(comp-collect-calls f))
(not (eq (comp-func-pure f) t)))
@@ -2859,16 +2228,16 @@ blocks."
for (op first second third forth) = last-insn
do (cl-case op
(jump
- (make-comp-edge :src bb :dst (gethash first blocks)))
+ (comp--edge-make :src bb :dst (gethash first blocks)))
(cond-jump
- (make-comp-edge :src bb :dst (gethash third blocks))
- (make-comp-edge :src bb :dst (gethash forth blocks)))
+ (comp--edge-make :src bb :dst (gethash third blocks))
+ (comp--edge-make :src bb :dst (gethash forth blocks)))
(cond-jump-narg-leq
- (make-comp-edge :src bb :dst (gethash second blocks))
- (make-comp-edge :src bb :dst (gethash third blocks)))
+ (comp--edge-make :src bb :dst (gethash second blocks))
+ (comp--edge-make :src bb :dst (gethash third blocks)))
(push-handler
- (make-comp-edge :src bb :dst (gethash third blocks))
- (make-comp-edge :src bb :dst (gethash forth blocks)))
+ (comp--edge-make :src bb :dst (gethash third blocks))
+ (comp--edge-make :src bb :dst (gethash forth blocks)))
(return)
(unreachable)
(otherwise
@@ -2885,7 +2254,7 @@ blocks."
(comp-block-out-edges (comp-edge-src edge)))
(push edge
(comp-block-in-edges (comp-edge-dst edge))))
- (comp-log-edges comp-func)))
+ (comp--log-edges comp-func)))
(defun comp-collect-rev-post-order (basic-block)
"Walk BASIC-BLOCK children and return their name in reversed post-order."
@@ -2918,7 +2287,7 @@ blocks."
finger2 (comp-block-post-num b2))))
b1))
(first-processed (l)
- (if-let ((p (cl-find-if (lambda (p) (comp-block-idom p)) l)))
+ (if-let ((p (cl-find-if #'comp-block-idom l)))
p
(signal 'native-ice '("can't find first preprocessed")))))
@@ -2941,7 +2310,7 @@ blocks."
do (cl-loop
for name in (cdr rev-bb-list)
for b = (gethash name blocks)
- for preds = (comp-block-preds b)
+ for preds = (comp--block-preds b)
for new-idom = (first-processed preds)
initially (setf changed nil)
do (cl-loop for p in (delq new-idom preds)
@@ -2961,7 +2330,7 @@ blocks."
(cl-loop with blocks = (comp-func-blocks comp-func)
for b-name being each hash-keys of blocks
using (hash-value b)
- for preds = (comp-block-preds b)
+ for preds = (comp--block-preds b)
when (length> preds 1) ; All joins
do (cl-loop for p in preds
for runner = p
@@ -2993,7 +2362,7 @@ blocks."
;; Return t if a SLOT-N was assigned within BB.
(cl-loop for insn in (comp-block-insns bb)
for op = (car insn)
- when (or (and (comp-assign-op-p op)
+ when (or (and (comp--assign-op-p op)
(eql slot-n (comp-mvar-slot (cadr insn))))
;; fetch-handler is after a non local
;; therefore clobbers all frame!!!
@@ -3059,7 +2428,7 @@ PRE-LAMBDA and POST-LAMBDA are called in pre or post-order if non-nil."
(setf (comp-vec-aref frame slot-n) mvar
(cadr insn) mvar))))
(pcase insn
- (`(,(pred comp-assign-op-p) ,(pred targetp) . ,_)
+ (`(,(pred comp--assign-op-p) ,(pred targetp) . ,_)
(let ((mvar (comp-vec-aref frame slot-n)))
(setf (cddr insn) (cl-nsubst-if mvar #'targetp (cddr insn))))
(new-lvalue))
@@ -3146,7 +2515,7 @@ Return t when one or more block was removed, nil otherwise."
(comp-place-phis)
(comp-ssa-rename)
(comp-finalize-phis)
- (comp-log-func comp-func 3)
+ (comp--log-func comp-func 3)
(setf (comp-func-ssa-status f) t))))
(comp-ctxt-funcs-h comp-ctxt)))
@@ -3209,7 +2578,7 @@ Forward propagate immediate involed in assignments." ; FIXME: Typo. Involved or
(defun comp-function-foldable-p (f args)
"Given function F called with ARGS, return non-nil when optimizable."
- (and (comp-function-pure-p f)
+ (and (comp--function-pure-p f)
(cl-every #'comp-cstr-imm-vld-p args)))
(defun comp-function-call-maybe-fold (insn f args)
@@ -3217,7 +2586,7 @@ Forward propagate immediate involed in assignments." ; FIXME: Typo. Involved or
Return non-nil if the function is folded successfully."
(cl-flet ((rewrite-insn-as-setimm (insn value)
;; See `comp-emit-setimm'.
- (comp-add-const-to-relocs value)
+ (comp--add-const-to-relocs value)
(setf (car insn) 'setimm
(cddr insn) `(,value))))
(cond
@@ -3234,7 +2603,7 @@ Return non-nil if the function is folded successfully."
;; should do basic block pruning in order to be sure that this
;; is not dead-code. This is now left to gcc, to be
;; implemented only if we want a reliable diagnostic here.
- (let* ((f (if-let (f-in-ctxt (comp-symbol-func-to-fun f))
+ (let* ((f (if-let (f-in-ctxt (comp--symbol-func-to-fun f))
;; If the function is IN the compilation ctxt
;; and know to be pure.
(comp-func-byte-func f-in-ctxt)
@@ -3280,6 +2649,8 @@ Fold the call in case."
(_
(comp-cstr-shallow-copy lval rval))))
(`(assume ,lval ,(and (pred comp-mvar-p) rval))
+ ;; NOTE we should probably assert this case in the future when
+ ;; will be possible.
(comp-cstr-shallow-copy lval rval))
(`(assume ,lval (,kind . ,operands))
(cl-case kind
@@ -3311,7 +2682,7 @@ Fold the call in case."
(comp-func-blocks comp-func))))
(or (comp-latch-p bb)
(when (comp-block-cstr-p bb)
- (comp-latch-p (car (comp-block-preds bb)))))))
+ (comp-latch-p (car (comp--block-preds bb)))))))
rest))
(prop-fn (if from-latch
#'comp-cstr-union-no-range
@@ -3378,7 +2749,7 @@ Return t if something was changed."
(format "fwprop pass jammed into %s?" (comp-func-name f))))
(comp-log (format "Propagation run %d times\n" i) 2))
(comp-rewrite-non-locals)
- (comp-log-func comp-func 3))))
+ (comp--log-func comp-func 3))))
(comp-ctxt-funcs-h comp-ctxt)))
@@ -3401,7 +2772,7 @@ Return t if something was changed."
"Given FUNC return the `comp-fun' definition in the current context.
FUNCTION can be a function-name or byte compiled function."
(if (symbolp func)
- (comp-symbol-func-to-fun func)
+ (comp--symbol-func-to-fun func)
(cl-assert (byte-code-function-p func))
(gethash func (comp-ctxt-byte-func-to-func-h comp-ctxt))))
@@ -3418,6 +2789,14 @@ FUNCTION can be a function-name or byte compiled function."
(symbol-function callee)
(cl-assert (byte-code-function-p callee))
callee))
+ ;; Below call to `subrp' returns nil on an advised
+ ;; primitive F, so that we do not optimize calls to F
+ ;; with the funcall trampoline removal below. But if F
+ ;; is advised while we compile its call, it is very
+ ;; likely to be advised also when that call is executed.
+ ;; And in that case an "unoptimized" call to F is
+ ;; actually cheaper since it avoids the call to the
+ ;; intermediate native trampoline (bug#67005).
(subrp (subrp f))
(comp-func-callee (comp-func-in-unit callee)))
(cond
@@ -3439,7 +2818,7 @@ FUNCTION can be a function-name or byte compiled function."
((and comp-func-callee
(comp-func-c-name comp-func-callee)
(or (and (>= (comp-func-speed comp-func) 3)
- (comp-func-unique-in-cu-p callee))
+ (comp--func-unique-in-cu-p callee))
(and (>= (comp-func-speed comp-func) 2)
;; Anonymous lambdas can't be redefined so are
;; always safe to optimize.
@@ -3451,7 +2830,7 @@ FUNCTION can be a function-name or byte compiled function."
args
(fill-args args (comp-args-max func-args)))))
`(,call-type ,(comp-func-c-name comp-func-callee) ,@args)))
- ((comp-type-hint-p callee)
+ ((comp--type-hint-p callee)
`(call ,callee ,@args)))))))
(defun comp-call-optim-func ()
@@ -3508,7 +2887,7 @@ Return the list of m-var ids nuked."
do (cl-loop
for insn in (comp-block-insns b)
for (op arg0 . rest) = insn
- if (comp-assign-op-p op)
+ if (comp--assign-op-p op)
do (push (comp-mvar-id arg0) l-vals)
(setf r-vals (nconc (comp-collect-mvar-ids rest) r-vals))
else
@@ -3526,10 +2905,10 @@ Return the list of m-var ids nuked."
for b being each hash-value of (comp-func-blocks comp-func)
do (comp-loop-insn-in-block b
(cl-destructuring-bind (op &optional arg0 arg1 &rest rest) insn
- (when (and (comp-assign-op-p op)
+ (when (and (comp--assign-op-p op)
(memq (comp-mvar-id arg0) nuke-list))
(setf insn
- (if (comp-limple-insn-call-p arg1)
+ (if (comp--limple-insn-call-p arg1)
arg1
`(comment ,(format "optimized out: %s"
insn))))))))
@@ -3546,7 +2925,7 @@ Return the list of m-var ids nuked."
for i from 1
while (comp-dead-assignments-func)
finally (comp-log (format "dead code rm run %d times\n" i) 2)
- (comp-log-func comp-func 3))))
+ (comp--log-func comp-func 3))))
(comp-ctxt-funcs-h comp-ctxt)))
@@ -3586,7 +2965,7 @@ Return the list of m-var ids nuked."
(not (comp-func-has-non-local f)))
(let ((comp-func f))
(comp-tco-func)
- (comp-log-func comp-func 3))))
+ (comp--log-func comp-func 3))))
(comp-ctxt-funcs-h comp-ctxt)))
@@ -3602,7 +2981,7 @@ These are substituted with a normal `set' op."
for b being each hash-value of (comp-func-blocks comp-func)
do (comp-loop-insn-in-block b
(pcase insn
- (`(set ,l-val (call ,(pred comp-type-hint-p) ,r-val))
+ (`(set ,l-val (call ,(pred comp--type-hint-p) ,r-val))
(setf insn `(set ,l-val ,r-val)))))))
(defun comp-remove-type-hints (_)
@@ -3611,7 +2990,7 @@ These are substituted with a normal `set' op."
(when (>= (comp-func-speed f) 2)
(let ((comp-func f))
(comp-remove-type-hints-func)
- (comp-log-func comp-func 3))))
+ (comp--log-func comp-func 3))))
(comp-ctxt-funcs-h comp-ctxt)))
@@ -3664,7 +3043,7 @@ Set it into the `type' slot."
finally return res)))
(type `(function ,(comp-args-to-lambda-list (comp-func-l-args func))
,(comp-cstr-to-type-spec res-mvar))))
- (comp-add-const-to-relocs type)
+ (comp--add-const-to-relocs type)
;; Fix it up.
(setf (comp-cstr-imm (comp-func-type func)) type))))
@@ -3693,7 +3072,7 @@ Update all insn accordingly."
;; Symbols imported by C inlined functions. We do this here because
;; is better to add all objs to the relocation containers before we
;; compacting them.
- (mapc #'comp-add-const-to-relocs '(nil t consp listp symbol-with-pos-p))
+ (mapc #'comp--add-const-to-relocs '(nil t consp listp symbol-with-pos-p))
(let* ((d-default (comp-ctxt-d-default comp-ctxt))
(d-default-idx (comp-data-container-idx d-default))
@@ -3748,7 +3127,7 @@ Prepare every function for final compilation and drive the C back-end."
(let ((dir (file-name-directory name)))
(comp-finalize-relocs)
(maphash (lambda (_ f)
- (comp-log-func f 1))
+ (comp--log-func f 1))
(comp-ctxt-funcs-h comp-ctxt))
(unless (file-exists-p dir)
;; In case it's created in the meanwhile.
@@ -3757,13 +3136,10 @@ Prepare every function for final compilation and drive the C back-end."
(comp--compile-ctxt-to-file name)))
(defun comp-final1 ()
- (let (compile-result)
- (comp--init-ctxt)
- (unwind-protect
- (setf compile-result
- (comp-compile-ctxt-to-file (comp-ctxt-output comp-ctxt)))
- (and (comp--release-ctxt)
- compile-result))))
+ (comp--init-ctxt)
+ (unwind-protect
+ (comp-compile-ctxt-to-file (comp-ctxt-output comp-ctxt))
+ (comp--release-ctxt)))
(defvar comp-async-compilation nil
"Non-nil while executing an asynchronous native compilation.")
@@ -3847,19 +3223,6 @@ Prepare every function for final compilation and drive the C back-end."
;; Primitive function advice machinery
-(defun comp-eln-load-path-eff ()
- "Return a list of effective eln load directories.
-Account for `native-comp-eln-load-path' and `comp-native-version-dir'."
- (mapcar (lambda (dir)
- (expand-file-name comp-native-version-dir
- (file-name-as-directory
- (expand-file-name dir invocation-directory))))
- native-comp-eln-load-path))
-
-(defun comp-trampoline-filename (subr-name)
- "Given SUBR-NAME return the filename containing the trampoline."
- (concat (comp-c-func-name subr-name "subr--trampoline-" t) ".eln"))
-
(defun comp-make-lambda-list-from-subr (subr)
"Given SUBR return the equivalent lambda-list."
(pcase-let ((`(,min . ,max) (subr-arity subr))
@@ -3875,16 +3238,6 @@ Account for `native-comp-eln-load-path' and `comp-native-version-dir'."
(push (gensym "arg") lambda-list))
(reverse lambda-list)))
-(defun comp-trampoline-search (subr-name)
- "Search a trampoline file for SUBR-NAME.
-Return the trampoline if found or nil otherwise."
- (cl-loop
- with rel-filename = (comp-trampoline-filename subr-name)
- for dir in (comp-eln-load-path-eff)
- for filename = (expand-file-name rel-filename dir)
- when (file-exists-p filename)
- do (cl-return (native-elisp-load filename))))
-
(defun comp--trampoline-abs-filename (subr-name)
"Return the absolute filename for a trampoline for SUBR-NAME."
(cl-loop
@@ -3910,6 +3263,8 @@ Return the trampoline if found or nil otherwise."
(make-temp-file (file-name-sans-extension rel-filename) nil ".eln"
nil))))
+;; Called from comp-run.el
+;;;###autoload
(defun comp-trampoline-compile (subr-name)
"Synthesize compile and return a trampoline for SUBR-NAME."
(let* ((lambda-list (comp-make-lambda-list-from-subr
@@ -3984,177 +3339,9 @@ session."
;; Remove the old eln instead of copying the new one into it
;; to get a new inode and prevent crashes in case the old one
;; is currently loaded.
- (t (delete-file oldfile)
- (when newfile
- (rename-file newfile oldfile)))))
-
-(defvar comp-files-queue ()
- "List of Emacs Lisp files to be compiled.")
-
-(defvar comp-async-compilations (make-hash-table :test #'equal)
- "Hash table file-name -> async compilation process.")
-
-(defun comp-async-runnings ()
- "Return the number of async compilations currently running.
-This function has the side effect of cleaning-up finished
-processes from `comp-async-compilations'"
- (cl-loop
- for file-name in (cl-loop
- for file-name being each hash-key of comp-async-compilations
- for prc = (gethash file-name comp-async-compilations)
- unless (process-live-p prc)
- collect file-name)
- do (remhash file-name comp-async-compilations))
- (hash-table-count comp-async-compilations))
-
-(defvar comp-num-cpus nil)
-(defun comp-effective-async-max-jobs ()
- "Compute the effective number of async jobs."
- (if (zerop native-comp-async-jobs-number)
- (or comp-num-cpus
- (setf comp-num-cpus
- (max 1 (/ (num-processors) 2))))
- native-comp-async-jobs-number))
-
-(defvar comp-last-scanned-async-output nil)
-(make-variable-buffer-local 'comp-last-scanned-async-output)
-(defun comp-accept-and-process-async-output (process)
- "Accept PROCESS output and check for diagnostic messages."
- (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)
- warning-suppress-types)))
- (with-current-buffer (process-buffer process)
- (save-excursion
- (accept-process-output process)
- (goto-char (or comp-last-scanned-async-output (point-min)))
- (while (re-search-forward "^.*?\\(?:Error\\|Warning\\): .*$"
- nil t)
- (display-warning 'comp (match-string 0)))
- (setq comp-last-scanned-async-output (point-max)))))
- (accept-process-output process)))
-
-(defun comp-run-async-workers ()
- "Start compiling files from `comp-files-queue' asynchronously.
-When compilation is finished, run `native-comp-async-all-done-hook' and
-display a message."
- (cl-assert (null comp-no-spawn))
- (if (or comp-files-queue
- (> (comp-async-runnings) 0))
- (unless (>= (comp-async-runnings) (comp-effective-async-max-jobs))
- (cl-loop
- for (source-file . load) = (pop comp-files-queue)
- while source-file
- do (cl-assert (string-match-p comp-valid-source-re source-file) nil
- "`comp-files-queue' should be \".el\" files: %s"
- source-file)
- when (or native-comp-always-compile
- load ; Always compile when the compilation is
- ; commanded for late load.
- ;; Skip compilation if `comp-el-to-eln-filename' fails
- ;; to find a writable directory.
- (with-demoted-errors "Async compilation :%S"
- (file-newer-than-file-p
- source-file (comp-el-to-eln-filename source-file))))
- do (let* ((expr `((require 'comp)
- (setq comp-async-compilation t
- warning-fill-column most-positive-fixnum)
- ,(let ((set (list 'setq)))
- (dolist (var '(comp-file-preloaded-p
- native-compile-target-directory
- native-comp-speed
- native-comp-debug
- native-comp-verbose
- comp-libgccjit-reproducer
- native-comp-eln-load-path
- native-comp-compiler-options
- native-comp-driver-options
- load-path
- backtrace-line-length
- byte-compile-warnings
- ;; package-load-list
- ;; package-user-dir
- ;; package-directory-list
- ))
- (when (boundp var)
- (push var set)
- (push `',(symbol-value var) set)))
- (nreverse set))
- ;; FIXME: Activating all packages would align the
- ;; functionality offered with what is usually done
- ;; for ELPA packages (and thus fix some compilation
- ;; issues with some ELPA packages), but it's too
- ;; blunt an instrument (e.g. we don't even know if
- ;; we're compiling such an ELPA package at
- ;; this point).
- ;;(package-activate-all)
- ,native-comp-async-env-modifier-form
- (message "Compiling %s..." ,source-file)
- (comp--native-compile ,source-file ,(and load t))))
- (source-file1 source-file) ;; Make the closure works :/
- (temp-file (make-temp-file
- (concat "emacs-async-comp-"
- (file-name-base source-file) "-")
- nil ".el"))
- (expr-strings (let ((print-length nil)
- (print-level nil))
- (mapcar #'prin1-to-string expr)))
- (_ (progn
- (with-temp-file temp-file
- (mapc #'insert expr-strings))
- (comp-log "\n")
- (mapc #'comp-log expr-strings)))
- (load1 load)
- (default-directory invocation-directory)
- (process (make-process
- :name (concat "Compiling: " source-file)
- :buffer (with-current-buffer
- (get-buffer-create
- comp-async-buffer-name)
- (unless (derived-mode-p 'compilation-mode)
- (emacs-lisp-compilation-mode))
- (current-buffer))
- :command (list
- (expand-file-name invocation-name
- invocation-directory)
- "-no-comp-spawn" "-Q" "--batch"
- "--eval"
- ;; Suppress Abort dialogs on MS-Windows
- "(setq w32-disable-abort-dialog t)"
- "-l" temp-file)
- :sentinel
- (lambda (process _event)
- (run-hook-with-args
- 'native-comp-async-cu-done-functions
- source-file)
- (comp-accept-and-process-async-output process)
- (ignore-errors (delete-file temp-file))
- (let ((eln-file (comp-el-to-eln-filename
- source-file1)))
- (when (and load1
- (zerop (process-exit-status
- process))
- (file-exists-p eln-file))
- (native-elisp-load eln-file
- (eq load1 'late))))
- (comp-run-async-workers))
- :noquery (not native-comp-async-query-on-exit))))
- (puthash source-file process comp-async-compilations))
- when (>= (comp-async-runnings) (comp-effective-async-max-jobs))
- do (cl-return)))
- ;; No files left to compile and all processes finished.
- (run-hooks 'native-comp-async-all-done-hook)
- (with-current-buffer (get-buffer-create comp-async-buffer-name)
- (save-excursion
- (unless (derived-mode-p 'compilation-mode)
- (emacs-lisp-compilation-mode))
- (let ((inhibit-read-only t))
- (goto-char (point-max))
- (insert "Compilation finished.\n"))))
- ;; `comp-deferred-pending-h' should be empty at this stage.
- ;; Reset it anyway.
- (clrhash comp-deferred-pending-h)))
+ (t (if newfile
+ (rename-file newfile oldfile t)
+ (delete-file oldfile)))))
(defun comp--native-compile (function-or-file &optional with-late-load output)
"Compile FUNCTION-OR-FILE into native code.
@@ -4177,19 +3364,20 @@ the deferred compilation mechanism."
(symbols-with-pos-enabled t)
;; Have byte compiler signal an error when compilation fails.
(byte-compile-debug t)
- (comp-ctxt (make-comp-ctxt :output output
+ (comp-ctxt (make-comp-ctxt :output (when output
+ (expand-file-name output))
:with-late-load with-late-load)))
(comp-log "\n \n" 1)
(unwind-protect
(progn
- (condition-case err
+ (condition-case-unless-debug err
(cl-loop
with report = nil
for t0 = (current-time)
for pass in comp-passes
unless (memq pass comp-disabled-passes)
do
- (comp-log (format "(%s) Running pass %s:\n"
+ (comp-log (format "\n(%s) Running pass %s:\n"
function-or-file pass)
2)
(setf data (funcall pass data))
@@ -4201,7 +3389,8 @@ the deferred compilation mechanism."
(comp-log (format "Done compiling %s" data) 0)
(cl-loop for (pass . time) in (reverse report)
do (comp-log (format "Pass %s took: %fs."
- pass time) 0))))
+ pass time)
+ 0))))
(native-compiler-skip)
(t
(let ((err-val (cdr err)))
@@ -4236,102 +3425,6 @@ the deferred compilation mechanism."
(ignore-errors (delete-file (comp-ctxt-output comp-ctxt))))
(t (delete-file (comp-ctxt-output comp-ctxt))))))))))
-(defun native-compile-async-skip-p (file load selector)
- "Return non-nil if FILE's compilation should be skipped.
-
-LOAD and SELECTOR work as described in `native--compile-async'."
- ;; Make sure we are not already compiling `file' (bug#40838).
- (or (gethash file comp-async-compilations)
- (gethash (file-name-with-extension file "elc") comp--no-native-compile)
- (cond
- ((null selector) nil)
- ((functionp selector) (not (funcall selector file)))
- ((stringp selector) (not (string-match-p selector file)))
- (t (error "SELECTOR must be a function a regexp or nil")))
- ;; Also exclude files from deferred compilation if
- ;; any of the regexps in
- ;; `native-comp-jit-compilation-deny-list' matches.
- (and (eq load 'late)
- (cl-some (lambda (re)
- (string-match-p re file))
- native-comp-jit-compilation-deny-list))))
-
-;;;###autoload
-(defun native--compile-async (files &optional recursively load selector)
- ;; BEWARE, this function is also called directly from C.
- "Compile FILES asynchronously.
-FILES is one filename or a list of filenames or directories.
-
-If optional argument RECURSIVELY is non-nil, recurse into
-subdirectories of given directories.
-
-If optional argument LOAD is non-nil, request to load the file
-after compiling.
-
-The optional argument SELECTOR has the following valid values:
-
-nil -- Select all files.
-a string -- A regular expression selecting files with matching names.
-a function -- A function selecting files with matching names.
-
-The variable `native-comp-async-jobs-number' specifies the number
-of (commands) to run simultaneously.
-
-LOAD can also be the symbol `late'. This is used internally if
-the byte code has already been loaded when this function is
-called. It means that we request the special kind of load
-necessary in that situation, called \"late\" loading.
-
-During a \"late\" load, instead of executing all top-level forms
-of the original files, only function definitions are
-loaded (paying attention to have these effective only if the
-bytecode definition was not changed in the meantime)."
- (comp-ensure-native-compiler)
- (unless (member load '(nil t late))
- (error "LOAD must be nil, t or 'late"))
- (unless (listp files)
- (setf files (list files)))
- (let ((added-something nil)
- file-list)
- (dolist (file-or-dir files)
- (cond ((file-directory-p file-or-dir)
- (dolist (file (if recursively
- (directory-files-recursively
- file-or-dir comp-valid-source-re)
- (directory-files file-or-dir
- t comp-valid-source-re)))
- (push file file-list)))
- ((file-exists-p file-or-dir) (push file-or-dir file-list))
- (t (signal 'native-compiler-error
- (list "Not a file nor directory" file-or-dir)))))
- (dolist (file file-list)
- (if-let ((entry (cl-find file comp-files-queue :key #'car :test #'string=)))
- ;; Most likely the byte-compiler has requested a deferred
- ;; compilation, so update `comp-files-queue' to reflect that.
- (unless (or (null load)
- (eq load (cdr entry)))
- (setf comp-files-queue
- (cl-substitute (cons file load) (car entry) comp-files-queue
- :key #'car :test #'string=)))
-
- (unless (native-compile-async-skip-p file load selector)
- (let* ((out-filename (comp-el-to-eln-filename file))
- (out-dir (file-name-directory out-filename)))
- (unless (file-exists-p out-dir)
- (make-directory out-dir t))
- (if (file-writable-p out-filename)
- (setf comp-files-queue
- (append comp-files-queue `((,file . ,load)))
- added-something t)
- (display-warning 'comp
- (format "No write access for %s skipping."
- out-filename)))))))
- ;; Perhaps nothing passed `native-compile-async-skip-p'?
- (when (and added-something
- ;; Don't start if there's one already running.
- (zerop (comp-async-runnings)))
- (comp-run-async-workers))))
-
;;; Compiler entry points.
@@ -4404,7 +3497,7 @@ last directory in `native-comp-eln-load-path')."
Make sure that eln file is younger than byte-compiled one and
return the filename of this last.
-This function can be used only in conjuntion with
+This function can be used only in conjunction with
`byte+native-compile' `byte-to-native-output-buffer-file' (see
`batch-byte+native-compile')."
(pcase byte-to-native-output-buffer-file
@@ -4439,29 +3532,6 @@ variable \"NATIVE_DISABLED\" is set, only byte compile."
(comp-write-bytecode-file eln-file)
(setq command-line-args-left (cdr command-line-args-left)))))
-;;;###autoload
-(defun native-compile-async (files &optional recursively load selector)
- "Compile FILES asynchronously.
-FILES is one file or a list of filenames or directories.
-
-If optional argument RECURSIVELY is non-nil, recurse into
-subdirectories of given directories.
-
-If optional argument LOAD is non-nil, request to load the file
-after compiling.
-
-The optional argument SELECTOR has the following valid values:
-
-nil -- Select all files.
-a string -- A regular expression selecting files with matching names.
-a function -- A function selecting files with matching names.
-
-The variable `native-comp-async-jobs-number' specifies the number
-of (commands) to run simultaneously."
- ;; Normalize: we only want to pass t or nil, never e.g. `late'.
- (let ((load (not (not load))))
- (native--compile-async files recursively load selector)))
-
(defun native-compile-prune-cache ()
"Remove .eln files that aren't applicable to the current Emacs invocation."
(interactive)
@@ -4492,27 +3562,6 @@ of (commands) to run simultaneously."
(delete-directory subdir))))))
(message "Cache cleared"))
-;;;###autoload
-(defun comp-function-type-spec (function)
- "Return the type specifier of FUNCTION.
-
-This function returns a cons cell whose car is the function
-specifier, and cdr is a symbol, either `inferred' or `know'.
-If the symbol is `inferred', the type specifier is automatically
-inferred from the code itself by the native compiler; if it is
-`know', the type specifier comes from `comp-known-type-specifiers'."
- (let ((kind 'know)
- type-spec )
- (when-let ((res (gethash function comp-known-func-cstr-h)))
- (setf type-spec (comp-cstr-to-type-spec res)))
- (let ((f (symbol-function function)))
- (when (and (null type-spec)
- (subr-native-elisp-p f))
- (setf kind 'inferred
- type-spec (subr-type f))))
- (when type-spec
- (cons type-spec kind))))
-
(provide 'comp)
;; LocalWords: limplified limplification limplify Limple LIMPLE libgccjit elc eln
diff --git a/lisp/emacs-lisp/copyright.el b/lisp/emacs-lisp/copyright.el
index 8295f86c078..54997318426 100644
--- a/lisp/emacs-lisp/copyright.el
+++ b/lisp/emacs-lisp/copyright.el
@@ -1,6 +1,6 @@
;;; copyright.el --- update the copyright notice in current buffer -*- lexical-binding: t -*-
-;; Copyright (C) 1991-1995, 1998, 2001-2023 Free Software Foundation,
+;; Copyright (C) 1991-1995, 1998, 2001-2024 Free Software Foundation,
;; Inc.
;; Author: Daniel Pfeiffer <occitan@esperanto.org>
diff --git a/lisp/emacs-lisp/crm.el b/lisp/emacs-lisp/crm.el
index 920118bb093..253dfc6237a 100644
--- a/lisp/emacs-lisp/crm.el
+++ b/lisp/emacs-lisp/crm.el
@@ -1,6 +1,6 @@
;;; crm.el --- read multiple strings with completion -*- lexical-binding: t; -*-
-;; Copyright (C) 1985-1986, 1993-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1985-1986, 1993-2024 Free Software Foundation, Inc.
;; Author: Sen Nagata <sen@eccosys.com>
;; Keywords: completion, minibuffer, multiple elements
diff --git a/lisp/emacs-lisp/cursor-sensor.el b/lisp/emacs-lisp/cursor-sensor.el
index e20365e61e8..3fe41dc5004 100644
--- a/lisp/emacs-lisp/cursor-sensor.el
+++ b/lisp/emacs-lisp/cursor-sensor.el
@@ -1,6 +1,6 @@
;;; cursor-sensor.el --- React to cursor movement -*- lexical-binding: t; -*-
-;; Copyright (C) 2015-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2024 Free Software Foundation, Inc.
;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
;; Keywords:
diff --git a/lisp/emacs-lisp/debug-early.el b/lisp/emacs-lisp/debug-early.el
index e393daee879..f2eb8792bfa 100644
--- a/lisp/emacs-lisp/debug-early.el
+++ b/lisp/emacs-lisp/debug-early.el
@@ -1,6 +1,6 @@
;;; debug-early.el --- Dump a Lisp backtrace without frills -*- lexical-binding: t; -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;; Author: Alan Mackenzie <acm@muc.de>
;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/emacs-lisp/debug.el b/lisp/emacs-lisp/debug.el
index dc23b071f0d..506b73f6fa2 100644
--- a/lisp/emacs-lisp/debug.el
+++ b/lisp/emacs-lisp/debug.el
@@ -1,6 +1,6 @@
;;; debug.el --- debuggers and related commands for Emacs -*- lexical-binding: t -*-
-;; Copyright (C) 1985-1986, 1994, 2001-2023 Free Software Foundation,
+;; Copyright (C) 1985-1986, 1994, 2001-2024 Free Software Foundation,
;; Inc.
;; Maintainer: emacs-devel@gnu.org
@@ -158,6 +158,13 @@ where CAUSE can be:
;;;###autoload
(defun debug (&rest args)
"Enter debugger. \\<debugger-mode-map>`\\[debugger-continue]' returns from the debugger.
+
+In interactive sessions, this switches to a backtrace buffer and shows
+the Lisp backtrace of function calls there. In batch mode (more accurately,
+when `noninteractive' is non-nil), it shows the Lisp backtrace on the
+standard error stream (unless `backtrace-on-error-noninteractive' is nil),
+and then kills Emacs, causing it to exit with a negative exit code.
+
Arguments are mainly for use when this is called from the internals
of the evaluator.
@@ -230,12 +237,11 @@ the debugger will not be entered."
(unwind-protect
(save-excursion
(when (eq (car debugger-args) 'debug)
- ;; Skip the frames for backtrace-debug, byte-code,
- ;; debug--implement-debug-on-entry and the advice's `apply'.
- (backtrace-debug 4 t)
- ;; Place an extra debug-on-exit for macro's.
- (when (eq 'lambda (car-safe (cadr (backtrace-frame 4))))
- (backtrace-debug 5 t)))
+ (let ((base (debugger--backtrace-base)))
+ (backtrace-debug 1 t base) ;FIXME!
+ ;; Place an extra debug-on-exit for macro's.
+ (when (eq 'lambda (car-safe (cadr (backtrace-frame 1 base))))
+ (backtrace-debug 2 t base))))
(with-current-buffer debugger-buffer
(unless (derived-mode-p 'debugger-mode)
(debugger-mode))
@@ -336,11 +342,10 @@ Make functions into cross-reference buttons if DO-XREFS is non-nil."
(defun debugger-setup-buffer (args)
"Initialize the `*Backtrace*' buffer for entry to the debugger.
That buffer should be current already and in `debugger-mode'."
- (setq backtrace-frames (nthcdr
- ;; Remove debug--implement-debug-on-entry and the
- ;; advice's `apply' frame.
- (if (eq (car args) 'debug) 3 1)
- (backtrace-get-frames 'debug)))
+ (setq backtrace-frames
+ ;; The `base' frame is the one that gets index 0 and it is the entry to
+ ;; the debugger, so drop it with `cdr'.
+ (cdr (backtrace-get-frames (debugger--backtrace-base))))
(when (eq (car-safe args) 'exit)
(setq debugger-value (nth 1 args))
(setf (cl-getf (backtrace-frame-flags (car backtrace-frames))
@@ -470,26 +475,29 @@ removes itself from that hook."
(setq debugger-jumping-flag nil)
(remove-hook 'post-command-hook 'debugger-reenable))
-(defun debugger-frame-number (&optional skip-base)
+(defun debugger-frame-number ()
"Return number of frames in backtrace before the one point points at."
- (let ((index (backtrace-get-index))
- (count 0))
+ (let ((index (backtrace-get-index)))
(unless index
(error "This line is not a function call"))
- (unless skip-base
- (while (not (eq (cadr (backtrace-frame count)) 'debug))
- (setq count (1+ count)))
- ;; Skip debug--implement-debug-on-entry frame.
- (when (eq 'debug--implement-debug-on-entry
- (cadr (backtrace-frame (1+ count))))
- (setq count (+ 2 count))))
- (+ count index)))
+ ;; We have 3 representations of the backtrace: the real in C in `specpdl',
+ ;; the one stored in `backtrace-frames' and the textual version in
+ ;; the buffer. Check here that the one from `backtrace-frames' is in sync
+ ;; with the one from `specpdl'.
+ (cl-assert (equal (backtrace-frame-fun (nth index backtrace-frames))
+ (nth 1 (backtrace-frame (1+ index)
+ (debugger--backtrace-base)))))
+ ;; The `base' frame is the one that gets index 0 and it is the entry to
+ ;; the debugger, so the first non-debugger frame is 1.
+ ;; This `+1' skips the same frame as the `cdr' in
+ ;; `debugger-setup-buffer'.
+ (1+ index)))
(defun debugger-frame ()
"Request entry to debugger when this frame exits.
Applies to the frame whose line point is on in the backtrace."
(interactive)
- (backtrace-debug (debugger-frame-number) t)
+ (backtrace-debug (debugger-frame-number) t (debugger--backtrace-base))
(setf
(cl-getf (backtrace-frame-flags (nth (backtrace-get-index) backtrace-frames))
:debug-on-exit)
@@ -500,7 +508,7 @@ Applies to the frame whose line point is on in the backtrace."
"Do not enter debugger when this frame exits.
Applies to the frame whose line point is on in the backtrace."
(interactive)
- (backtrace-debug (debugger-frame-number) nil)
+ (backtrace-debug (debugger-frame-number) nil (debugger--backtrace-base))
(setf
(cl-getf (backtrace-frame-flags (nth (backtrace-get-index) backtrace-frames))
:debug-on-exit)
@@ -519,10 +527,8 @@ Applies to the frame whose line point is on in the backtrace."
(defun debugger--backtrace-base ()
"Return the function name that marks the top of the backtrace.
See `backtrace-frame'."
- (cond ((eq 'debug--implement-debug-on-entry
- (cadr (backtrace-frame 1 'debug)))
- 'debug--implement-debug-on-entry)
- (t 'debug)))
+ (or (cadr (memq :backtrace-base debugger-args))
+ #'debug))
(defun debugger-eval-expression (exp &optional nframe)
"Eval an expression, in an environment like that outside the debugger.
@@ -530,7 +536,7 @@ The environment used is the one when entering the activation frame at point."
(interactive
(list (read--expression "Eval in stack frame: ")))
(let ((nframe (or nframe
- (condition-case nil (1+ (debugger-frame-number 'skip-base))
+ (condition-case nil (debugger-frame-number)
(error 0)))) ;; If on first line.
(base (debugger--backtrace-base)))
(debugger-env-macro
@@ -663,7 +669,10 @@ functions to break on entry."
(if (or inhibit-debug-on-entry debugger-jumping-flag)
nil
(let ((inhibit-debug-on-entry t))
- (funcall debugger 'debug))))
+ (funcall debugger 'debug :backtrace-base
+ ;; An offset of 1 because we need to skip the advice
+ ;; OClosure that called us.
+ '(1 . debug--implement-debug-on-entry)))))
;;;###autoload
(defun debug-on-entry (function)
diff --git a/lisp/emacs-lisp/derived.el b/lisp/emacs-lisp/derived.el
index b35994364a7..5c224362708 100644
--- a/lisp/emacs-lisp/derived.el
+++ b/lisp/emacs-lisp/derived.el
@@ -1,7 +1,7 @@
;;; derived.el --- allow inheritance of major modes -*- lexical-binding: t; -*-
;; (formerly mode-clone.el)
-;; Copyright (C) 1993-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1993-2024 Free Software Foundation, Inc.
;; Author: David Megginson <dmeggins@aix1.uottawa.ca>
;; Maintainer: emacs-devel@gnu.org
@@ -240,7 +240,9 @@ No problems result if this variable is not bound.
(unless (get ',abbrev 'variable-documentation)
(put ',abbrev 'variable-documentation
(purecopy ,(format "Abbrev table for `%s'." child))))))
- (put ',child 'derived-mode-parent ',parent)
+ (if (fboundp 'derived-mode-set-parent) ;; Emacs≥30.1
+ (derived-mode-set-parent ',child ',parent)
+ (put ',child 'derived-mode-parent ',parent))
,(if group `(put ',child 'custom-mode-group ,group))
(defun ,child ()
diff --git a/lisp/emacs-lisp/disass.el b/lisp/emacs-lisp/disass.el
index dd59a2e02e1..a876e6b5744 100644
--- a/lisp/emacs-lisp/disass.el
+++ b/lisp/emacs-lisp/disass.el
@@ -1,6 +1,6 @@
;;; disass.el --- disassembler for compiled Emacs Lisp code -*- lexical-binding:t -*-
-;; Copyright (C) 1986, 1991, 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1986, 1991, 2002-2024 Free Software Foundation, Inc.
;; Author: Doug Cutting <doug@csli.stanford.edu>
;; Jamie Zawinski <jwz@lucid.com>
@@ -92,17 +92,16 @@ redefine OBJECT if it is a symbol."
(subr-native-elisp-p obj))
(progn
(require 'comp)
- (call-process "objdump" nil (current-buffer) t "-S"
- (native-comp-unit-file (subr-native-comp-unit obj)))
+ (let ((eln (native-comp-unit-file (subr-native-comp-unit obj))))
+ (if (file-exists-p eln)
+ (call-process "objdump" nil (current-buffer) t "-S" eln)
+ (error "Missing eln file for #<subr %s>" name)))
(goto-char (point-min))
- (re-search-forward (concat "^.*"
+ (re-search-forward (concat "^.*<_?"
(regexp-quote
- (concat "<"
- (when (eq system-type 'darwin)
- "_")
- (comp-c-func-name
- (subr-name obj) "F" t)
- ">:"))))
+ (comp-c-func-name
+ (subr-name obj) "F" t))
+ ">:"))
(beginning-of-line)
(delete-region (point-min) (point))
(when (re-search-forward "^.*<.*>:" nil t 2)
@@ -302,6 +301,23 @@ OBJ should be a call to BYTE-CODE generated by the byte compiler."
(insert "\n")))))
nil)
+(defun re-disassemble (regexp &optional case-table)
+ "Describe the compiled form of REGEXP in a separate window.
+If CASE-TABLE is non-nil, use it as translation table for case-folding.
+
+This function is mainly intended for maintenance of Emacs itself
+and may change at any time. It requires Emacs to be built with
+`--enable-checking'."
+ (interactive "XRegexp (Lisp expression): ")
+ (let ((desc (with-temp-buffer
+ (when case-table
+ (set-case-table case-table))
+ (let ((case-fold-search (and case-table t)))
+ (re--describe-compiled regexp)))))
+ (with-output-to-temp-buffer "*Regexp-disassemble*"
+ (with-current-buffer standard-output
+ (insert desc)))))
+
(provide 'disass)
;;; disass.el ends here
diff --git a/lisp/emacs-lisp/easy-mmode.el b/lisp/emacs-lisp/easy-mmode.el
index 529f6e90e88..05b23a86fc0 100644
--- a/lisp/emacs-lisp/easy-mmode.el
+++ b/lisp/emacs-lisp/easy-mmode.el
@@ -1,6 +1,6 @@
;;; easy-mmode.el --- easy definition for major and minor modes -*- lexical-binding: t; -*-
-;; Copyright (C) 1997, 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997, 2000-2024 Free Software Foundation, Inc.
;; Author: Georges Brun-Cottan <Georges.Brun-Cottan@inria.fr>
;; Maintainer: Stefan Monnier <monnier@gnu.org>
@@ -661,7 +661,7 @@ list."
(throw 'found nil))
((and (consp elem)
(eq (car elem) 'not))
- (when (apply #'derived-mode-p (cdr elem))
+ (when (derived-mode-p (cdr elem))
(throw 'found nil)))
((symbolp elem)
(when (derived-mode-p elem)
diff --git a/lisp/emacs-lisp/easymenu.el b/lisp/emacs-lisp/easymenu.el
index 21c70fa70e0..6740c2af58d 100644
--- a/lisp/emacs-lisp/easymenu.el
+++ b/lisp/emacs-lisp/easymenu.el
@@ -1,6 +1,6 @@
;;; easymenu.el --- support the easymenu interface for defining a menu -*- lexical-binding:t -*-
-;; Copyright (C) 1994, 1996, 1998-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1994, 1996, 1998-2024 Free Software Foundation, Inc.
;; Keywords: emulations
;; Author: Richard Stallman <rms@gnu.org>
diff --git a/lisp/emacs-lisp/edebug.el b/lisp/emacs-lisp/edebug.el
index 9a06807bcdc..a8a51502503 100644
--- a/lisp/emacs-lisp/edebug.el
+++ b/lisp/emacs-lisp/edebug.el
@@ -1,6 +1,6 @@
;;; edebug.el --- a source-level debugger for Emacs Lisp -*- lexical-binding: t -*-
-;; Copyright (C) 1988-1995, 1997, 1999-2023 Free Software Foundation,
+;; Copyright (C) 1988-1995, 1997, 1999-2024 Free Software Foundation,
;; Inc.
;; Author: Daniel LaLiberte <liberte@holonexus.org>
@@ -1544,9 +1544,7 @@ contains a circular object."
(defun edebug-list-form (cursor)
;; Return an instrumented form built from the list form.
;; The after offset will be left in the cursor after processing the form.
- (let ((head (edebug-top-element-required cursor "Expected elements"))
- ;; Prevent backtracking whenever instrumenting.
- (edebug-gate t))
+ (let ((head (edebug-top-element-required cursor "Expected elements")))
;; Skip the first offset.
(edebug-set-cursor cursor (edebug-cursor-expressions cursor)
(cdr (edebug-cursor-offsets cursor)))
@@ -2469,12 +2467,52 @@ MSG is printed after `::::} '."
(setf (cdr (assq 'edebug edebug-behavior-alist))
'(edebug-default-enter edebug-fast-before edebug-fast-after)))
-(defalias 'edebug-before nil
+;; The following versions of `edebug-before' and `edebug-after' exist
+;; to handle the error which occurs if either of them gets called
+;; without an enclosing `edebug-enter'. This can happen, for example,
+;; when a macro mistakenly has a `form' element in its edebug spec,
+;; and it additionally, at macro-expansion time, calls `eval',
+;; `apply', or `funcall' (etc.) on the corresponding argument. This
+;; is intended to fix bug#65620.
+
+(defun edebug-b/a-error (func)
+ "Throw an error for an invalid call of FUNC.
+FUNC is expected to be `edebug-before' or `edebug-after'."
+ (let (this-macro
+ (n 0)
+ bt-frame)
+ (while (and (setq bt-frame (backtrace-frame n))
+ (not (and (car bt-frame)
+ (memq (cadr bt-frame)
+ '(macroexpand macroexpand-1)))))
+ (setq n (1+ n)))
+ (when bt-frame
+ (setq this-macro (caaddr bt-frame)))
+
+ (error
+ (concat "Invalid call to `" (symbol-name func) "'"
+ (if this-macro
+ (concat ". Is the edebug spec for `"
+ (symbol-name this-macro)
+ "' correct?")
+ "" ; Not sure this case is possible (ACM, 2023-09-02)
+ )))))
+
+(defun edebug-before (_before-index)
"Function called by Edebug before a form is evaluated.
-See `edebug-behavior-alist' for implementations.")
-(defalias 'edebug-after nil
+See `edebug-behavior-alist' for other implementations. This
+version of `edebug-before' gets called when edebug is not yet set
+up. `edebug-enter' binds the function cell to a real function
+when edebug becomes active."
+ (edebug-b/a-error 'edebug-before))
+
+(defun edebug-after (_before-index _after-index _form)
"Function called by Edebug after a form is evaluated.
-See `edebug-behavior-alist' for implementations.")
+See `edebug-behavior-alist' for other implementations. This
+version of `edebug-after' gets called when edebug is not yet set
+up. `edebug-enter' binds the function cell to a real function
+when edebug becomes active."
+ (edebug-b/a-error 'edebug-after))
(defun edebug--update-coverage (after-index value)
(let ((old-result (aref edebug-coverage after-index)))
diff --git a/lisp/emacs-lisp/eieio-base.el b/lisp/emacs-lisp/eieio-base.el
index 31ca91ad317..1df33be8571 100644
--- a/lisp/emacs-lisp/eieio-base.el
+++ b/lisp/emacs-lisp/eieio-base.el
@@ -1,6 +1,6 @@
;;; eieio-base.el --- Base classes for EIEIO. -*- lexical-binding:t -*-
-;; Copyright (C) 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2000-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
;; Keywords: OO, lisp
diff --git a/lisp/emacs-lisp/eieio-core.el b/lisp/emacs-lisp/eieio-core.el
index f5ff04ff372..9c526f67204 100644
--- a/lisp/emacs-lisp/eieio-core.el
+++ b/lisp/emacs-lisp/eieio-core.el
@@ -1,6 +1,6 @@
;;; eieio-core.el --- Core implementation for eieio -*- lexical-binding:t -*-
-;; Copyright (C) 1995-1996, 1998-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1995-1996, 1998-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
;; Version: 1.4
@@ -951,7 +951,10 @@ not nil."
(let ((slots (eieio--class-slots (eieio--object-class obj))))
(dotimes (i (length slots))
(let* ((name (cl--slot-descriptor-name (aref slots i)))
- (df (eieio-oref-default obj name)))
+ ;; If the `:initform` signals an error, just skip it,
+ ;; since the error is intended to be signal'ed from
+ ;; `initialize-instance` rather than at the time of `defclass`.
+ (df (ignore-errors (eieio-oref-default obj name))))
(if (or df set-all)
(eieio-oset obj name df))))))
@@ -964,49 +967,6 @@ need be... May remove that later...)"
(cdr tuple)
nil)))
-;;;
-;; Method Invocation order: C3
-(defun eieio--c3-candidate (class remaining-inputs)
- "Return CLASS if it can go in the result now, otherwise nil."
- ;; Ensure CLASS is not in any position but the first in any of the
- ;; element lists of REMAINING-INPUTS.
- (and (not (let ((found nil))
- (while (and remaining-inputs (not found))
- (setq found (member class (cdr (car remaining-inputs)))
- remaining-inputs (cdr remaining-inputs)))
- found))
- class))
-
-(defun eieio--c3-merge-lists (reversed-partial-result remaining-inputs)
- "Try to merge REVERSED-PARTIAL-RESULT REMAINING-INPUTS in a consistent order.
-If a consistent order does not exist, signal an error."
- (setq remaining-inputs (delq nil remaining-inputs))
- (if (null remaining-inputs)
- ;; If all remaining inputs are empty lists, we are done.
- (nreverse reversed-partial-result)
- ;; Otherwise, we try to find the next element of the result. This
- ;; is achieved by considering the first element of each
- ;; (non-empty) input list and accepting a candidate if it is
- ;; consistent with the rests of the input lists.
- (let* ((found nil)
- (tail remaining-inputs)
- (next (progn
- (while (and tail (not found))
- (setq found (eieio--c3-candidate (caar tail)
- remaining-inputs)
- tail (cdr tail)))
- found)))
- (if next
- ;; The graph is consistent so far, add NEXT to result and
- ;; merge input lists, dropping NEXT from their heads where
- ;; applicable.
- (eieio--c3-merge-lists
- (cons next reversed-partial-result)
- (mapcar (lambda (l) (if (eq (cl-first l) next) (cl-rest l) l))
- remaining-inputs))
- ;; The graph is inconsistent, give up
- (signal 'inconsistent-class-hierarchy (list remaining-inputs))))))
-
(defsubst eieio--class/struct-parents (class)
(or (eieio--class-parents class)
`(,eieio-default-superclass)))
@@ -1014,14 +974,16 @@ If a consistent order does not exist, signal an error."
(defun eieio--class-precedence-c3 (class)
"Return all parents of CLASS in c3 order."
(let ((parents (eieio--class-parents class)))
- (eieio--c3-merge-lists
- (list class)
- (append
- (or
- (mapcar #'eieio--class-precedence-c3 parents)
- `((,eieio-default-superclass)))
- (list parents))))
- )
+ (cons class
+ (merge-ordered-lists
+ (append
+ (or
+ (mapcar #'eieio--class-precedence-c3 parents)
+ `((,eieio-default-superclass)))
+ (list parents))
+ (lambda (remaining-inputs)
+ (signal 'inconsistent-class-hierarchy
+ (list remaining-inputs)))))))
;;;
;; Method Invocation Order: Depth First
diff --git a/lisp/emacs-lisp/eieio-custom.el b/lisp/emacs-lisp/eieio-custom.el
index 1e1b9d721b0..704eac65ea2 100644
--- a/lisp/emacs-lisp/eieio-custom.el
+++ b/lisp/emacs-lisp/eieio-custom.el
@@ -1,6 +1,6 @@
;;; eieio-custom.el --- eieio object customization -*- lexical-binding:t -*-
-;; Copyright (C) 1999-2001, 2005, 2007-2023 Free Software Foundation,
+;; Copyright (C) 1999-2001, 2005, 2007-2024 Free Software Foundation,
;; Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/lisp/emacs-lisp/eieio-datadebug.el b/lisp/emacs-lisp/eieio-datadebug.el
index a80d1ae2720..455092d1c9b 100644
--- a/lisp/emacs-lisp/eieio-datadebug.el
+++ b/lisp/emacs-lisp/eieio-datadebug.el
@@ -1,6 +1,6 @@
;;; eieio-datadebug.el --- EIEIO extensions to the data debugger. -*- lexical-binding:t -*-
-;; Copyright (C) 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
;; Keywords: OO, lisp
diff --git a/lisp/emacs-lisp/eieio-opt.el b/lisp/emacs-lisp/eieio-opt.el
index 7b054169ca1..893f8cd7e7f 100644
--- a/lisp/emacs-lisp/eieio-opt.el
+++ b/lisp/emacs-lisp/eieio-opt.el
@@ -1,6 +1,6 @@
;;; eieio-opt.el --- eieio optional functions (debug, printing, speedbar) -*- lexical-binding: t; -*-
-;; Copyright (C) 1996, 1998-2003, 2005, 2008-2023 Free Software
+;; Copyright (C) 1996, 1998-2003, 2005, 2008-2024 Free Software
;; Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/lisp/emacs-lisp/eieio-speedbar.el b/lisp/emacs-lisp/eieio-speedbar.el
index 25626d01ecc..f3094b8b5d6 100644
--- a/lisp/emacs-lisp/eieio-speedbar.el
+++ b/lisp/emacs-lisp/eieio-speedbar.el
@@ -1,6 +1,6 @@
;;; eieio-speedbar.el --- Classes for managing speedbar displays. -*- lexical-binding:t -*-
-;; Copyright (C) 1999-2002, 2005, 2007-2023 Free Software Foundation,
+;; Copyright (C) 1999-2002, 2005, 2007-2024 Free Software Foundation,
;; Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/lisp/emacs-lisp/eieio.el b/lisp/emacs-lisp/eieio.el
index 9a1f5b9db0f..df85a64baf3 100644
--- a/lisp/emacs-lisp/eieio.el
+++ b/lisp/emacs-lisp/eieio.el
@@ -1,7 +1,7 @@
;;; eieio.el --- Enhanced Implementation of Emacs Interpreted Objects -*- lexical-binding:t -*-
;;; or maybe Eric's Implementation of Emacs Interpreted Objects
-;; Copyright (C) 1995-1996, 1998-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1995-1996, 1998-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
;; Version: 1.4
@@ -213,9 +213,8 @@ and reference them using the function `class-option'."
,(internal--format-docstring-line
"Retrieve the slot `%S' from an object of class `%S'."
sname name)
- ;; FIXME: Why is this different from the :reader case?
- (if (slot-boundp this ',sname) (eieio-oref this ',sname)))
- accessors)
+ (slot-value this ',sname))
+ accessors)
(when (and eieio-backward-compatibility (eq alloc :class))
;; FIXME: How could I declare this *method* as obsolete.
(push `(cl-defmethod ,acces ((this (subclass ,name)))
@@ -449,16 +448,13 @@ If EXTRA, include that in the string returned to represent the symbol."
(defun eieio-class-parents (class)
;; FIXME: What does "(overload of variable)" mean here?
- "Return parent classes to CLASS. (overload of variable).
-
-The CLOS function `class-direct-superclasses' is aliased to this function."
+ "Return parent classes to CLASS. (overload of variable)."
(eieio--class-parents (eieio--full-class-object class)))
(define-obsolete-function-alias 'class-parents #'eieio-class-parents "24.4")
(defun eieio-class-children (class)
- "Return child classes to CLASS.
-The CLOS function `class-direct-subclasses' is aliased to this function."
+ "Return child classes to CLASS."
(cl-check-type class class)
(eieio--class-children (cl--find-class class)))
(define-obsolete-function-alias
@@ -652,8 +648,7 @@ If SLOT is unbound, bind it to the list containing ITEM."
(setq ov (list item))
(setq ov (eieio-oref object slot))
;; turn it into a list.
- (unless (listp ov)
- (setq ov (list ov)))
+ (setq ov (ensure-list ov))
;; Do the combination
(if (not (member item ov))
(setq ov
diff --git a/lisp/emacs-lisp/eldoc.el b/lisp/emacs-lisp/eldoc.el
index 3a786bb321b..06970d40e8a 100644
--- a/lisp/emacs-lisp/eldoc.el
+++ b/lisp/emacs-lisp/eldoc.el
@@ -1,11 +1,11 @@
;;; eldoc.el --- Show function arglist or variable docstring in echo area -*- lexical-binding:t; -*-
-;; Copyright (C) 1996-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-2024 Free Software Foundation, Inc.
;; Author: Noah Friedman <friedman@splode.com>
;; Keywords: extensions
;; Created: 1995-10-06
-;; Version: 1.14.0
+;; Version: 1.15.0
;; Package-Requires: ((emacs "26.3"))
;; This is a GNU ELPA :core package. Avoid functionality that is not
@@ -65,7 +65,8 @@ If this variable is set to 0, display the documentation without any delay."
(defcustom eldoc-print-after-edit nil
"If non-nil, eldoc info is only shown after editing commands.
Changing the value requires toggling `eldoc-mode'."
- :type 'boolean)
+ :type 'boolean
+ :version "24.4")
(defcustom eldoc-echo-area-display-truncation-message t
"If non-nil, provide verbose help when a message has been truncated.
@@ -132,7 +133,10 @@ documentation in the echo area if the dedicated documentation
buffer (displayed by `eldoc-doc-buffer') is already displayed in
some window. If the value is the symbol `maybe', then the echo area
is only skipped if the documentation needs to be truncated there."
- :type 'boolean)
+ :type '(choice (const :tag "Prefer ElDoc's documentation buffer" t)
+ (const :tag "Prefer echo area" nil)
+ (const :tag "Skip echo area if truncating" maybe))
+ :version "28.1")
(defface eldoc-highlight-function-argument
'((t (:inherit bold)))
@@ -601,25 +605,29 @@ known to be truncated."
'maybe)))
(get-buffer-window eldoc--doc-buffer t)))
-(defun eldoc-display-in-echo-area (docs _interactive)
+(defun eldoc-display-in-echo-area (docs interactive)
"Display DOCS in echo area.
-Honor `eldoc-echo-area-use-multiline-p' and
+INTERACTIVE is non-nil if user explicitly invoked ElDoc. Honor
+`eldoc-echo-area-use-multiline-p' and
`eldoc-echo-area-prefer-doc-buffer'."
(cond
- (;; Check if we have permission to mess with echo area at all. For
- ;; example, if this-command is non-nil while running via an idle
- ;; timer, we're still in the middle of executing a command, e.g. a
- ;; query-replace where it would be annoying to overwrite the echo
- ;; area.
- (or
- (not (eldoc-display-message-no-interference-p))
- this-command
- (not (eldoc--message-command-p last-command))))
- (;; If we do but nothing to report, clear the echo area.
+ ((and (not interactive)
+ ;; When called non-interactively, check if we have permission
+ ;; to mess with echo area at all. For example, if
+ ;; this-command is non-nil while running via an idle timer,
+ ;; we're still in the middle of executing a command, e.g. a
+ ;; query-replace where it would be annoying to overwrite the
+ ;; echo area.
+ (or
+ (not (eldoc-display-message-no-interference-p))
+ this-command
+ (not (eldoc--message-command-p last-command)))))
+ (;; If nothing to report, clear the echo area.
(null docs)
(eldoc--message nil))
(t
- ;; Otherwise, establish some parameters.
+ ;; Otherwise, proceed to change the echo area. Start by
+ ;; establishing some parameters.
(let*
((width (1- (window-width (minibuffer-window))))
(val (if (and (symbolp eldoc-echo-area-use-multiline-p)
@@ -925,7 +933,7 @@ the docstrings eventually produced, using
(let* ((eldoc--make-callback #'make-callback)
(res (funcall eldoc-documentation-strategy)))
;; Observe the old and the new protocol:
- (cond (;; Old protocol: got string, e-d-strategy is iself the
+ (cond (;; Old protocol: got string, e-d-strategy is itself the
;; origin function, and we output immediately;
(stringp res)
(register-doc 0 res nil eldoc-documentation-strategy)
diff --git a/lisp/emacs-lisp/elint.el b/lisp/emacs-lisp/elint.el
index 9812c663ea8..a8bc4bdd1e0 100644
--- a/lisp/emacs-lisp/elint.el
+++ b/lisp/emacs-lisp/elint.el
@@ -1,8 +1,9 @@
;;; elint.el --- Lint Emacs Lisp -*- lexical-binding: t -*-
-;; Copyright (C) 1997, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997-2024 Free Software Foundation, Inc.
;; Author: Peter Liljenberg <petli@lysator.liu.se>
+;; Maintainer: emacs-devel@gnu.org
;; Created: May 1997
;; Keywords: lisp
@@ -27,7 +28,7 @@
;; misspellings and undefined variables, although it can also catch
;; function calls with the wrong number of arguments.
-;; To use, call `elint-current-buffer' or `elint-defun' to lint a buffer
+;; To use it, call `elint-current-buffer' or `elint-defun' to lint a buffer
;; or defun. The first call runs `elint-initialize' to set up some
;; argument data, which may take a while.
@@ -37,9 +38,9 @@
;;; To do:
-;; * Adding type checking. (Stop that sniggering!)
+;; * Adding type checking. (Stop that sniggering!)
;; * Make eval-when-compile be sensitive to the difference between
-;; funcs and macros.
+;; functions and macros.
;; * Requires within function bodies.
;; * Handle defstruct.
;; * Prevent recursive requires.
@@ -79,16 +80,16 @@ are as follows, and suppress messages about the indicated features:
empty-let - let-bindings with empty variable lists"
:type '(choice (const :tag "Don't suppress any warnings" nil)
(repeat :tag "List of issues to ignore"
- (choice (const undefined-functions
- :tag "Calls to unknown functions")
- (const unbound-reference
- :tag "Reference to unknown variables")
- (const unbound-assignment
- :tag "Assignment to unknown variables")
- (const macro-expansion
- :tag "Failure to expand macros")
- (const empty-let
- :tag "Let-binding with empty varlist"))))
+ (choice (const :tag "Calls to unknown functions"
+ undefined-functions)
+ (const :tag "Reference to unknown variables"
+ unbound-reference)
+ (const :tag "Assignment to unknown variables"
+ unbound-assignment)
+ (const :tag "Failure to expand macros"
+ macro-expansion)
+ (const :tag "Let-binding with empty varlist"
+ empty-let))))
:safe (lambda (value) (or (null value)
(and (listp value)
(equal value
diff --git a/lisp/emacs-lisp/elp.el b/lisp/emacs-lisp/elp.el
index d50d0e029e9..9181b498a2e 100644
--- a/lisp/emacs-lisp/elp.el
+++ b/lisp/emacs-lisp/elp.el
@@ -1,6 +1,6 @@
;;; elp.el --- Emacs Lisp Profiler -*- lexical-binding: t -*-
-;; Copyright (C) 1994-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1994-2024 Free Software Foundation, Inc.
;; Author: Barry A. Warsaw
;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/emacs-lisp/ert-font-lock.el b/lisp/emacs-lisp/ert-font-lock.el
new file mode 100644
index 00000000000..29114712f92
--- /dev/null
+++ b/lisp/emacs-lisp/ert-font-lock.el
@@ -0,0 +1,364 @@
+;;; ert-font-lock.el --- ERT Font Lock -*- lexical-binding: t -*-
+
+;; Copyright (C) 2023-2024 Free Software Foundation, Inc.
+
+;; Author: Vladimir Kazanov
+;; Keywords: lisp, tools
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+;;
+;; ERT Font Lock is an extension to the Emacs Lisp Regression Test
+;; library (ERT) providing a convenient way to check syntax
+;; highlighting provided by font-lock.
+;;
+;; ert-font-lock entry points are functions
+;; `ert-font-lock-test-string' and `ert-font-lock-test-file' and
+;; convenience macros: `ert-font-lock-deftest' and
+;; `ert-font-lock-deftest-file'.
+;;
+;; See unit tests in ert-font-lock-tests.el for usage examples.
+
+;;; Code:
+
+(require 'ert)
+(require 'newcomment)
+(require 'pcase)
+
+(defconst ert-font-lock--assertion-re
+ (rx
+ ;; column specifiers
+ (group (or "^" "<-"))
+ (one-or-more " ")
+ ;; optional negation of the face specification
+ (group (optional "!"))
+ ;; face symbol name
+ (group (one-or-more (or alphanumeric "-" "_" "."))))
+ "An ert-font-lock assertion regex.")
+
+(defun ert-font-lock--validate-major-mode (mode)
+ "Validate if MODE is a valid major mode."
+ (unless (functionp mode)
+ (error "Invalid major mode: %S. Please specify a valid major mode for
+ syntax highlighting tests" mode)))
+
+(defun ert-font-lock--test-body-str (mode str test-name)
+ "Run assertions from STR.
+Argument MODE - major mode to test.
+Argument TEST-NAME - name of the currently running ert test."
+ (ert-font-lock--validate-major-mode mode)
+ (with-temp-buffer
+ (insert str)
+ (funcall mode)
+ (font-lock-ensure)
+ (let ((tests (ert-font-lock--parse-comments)))
+ (ert-font-lock--check-faces tests)))
+ test-name)
+
+(defun ert-font-lock--test-body-file (mode file test-name)
+ "Run assertions from FILE.
+Argument MODE - major mode to test.
+Argument TEST-NAME - name of the currently running ert test."
+ (ert-font-lock--validate-major-mode mode)
+ (ert-font-lock-test-file file mode)
+ test-name)
+
+(defun ert-font-lock--parse-macro-args (doc-keys-mode-arg)
+ "Parse DOC-KEYS-MODE-ARG macro argument list."
+ (let (doc doc-p mode arg)
+
+ (when (stringp (car doc-keys-mode-arg))
+ (setq doc (pop doc-keys-mode-arg)
+ doc-p t))
+
+ (pcase-let
+ ((`(,keys ,mode-arg)
+ (ert--parse-keys-and-body doc-keys-mode-arg)))
+
+ (unless (symbolp (car mode-arg))
+ (error "A major mode symbol expected: %S" (car mode-arg)))
+ (setq mode (pop mode-arg))
+
+ (unless (stringp (car mode-arg))
+ (error "A string or file with assertions expected: %S" (car mode-arg)))
+ (setq arg (pop mode-arg))
+
+ (list doc doc-p keys mode arg))))
+
+;;;###autoload
+(defmacro ert-font-lock-deftest (name &rest docstring-keys-mode-and-str)
+ "Define test NAME (a symbol) using assertions from TEST-STR.
+
+Other than MAJOR-MODE and TEST-STR parameters, this macro accepts
+the same parameters and keywords as `ert-deftest' and is intended
+to be used through `ert'.
+
+\(fn NAME () [DOCSTRING] [:expected-result RESULT-TYPE] \
+[:tags \\='(TAG...)] MAJOR-MODE TEST-STR)"
+ (declare (debug (&define [&name "test@" symbolp]
+ sexp [&optional stringp]
+ [&rest keywordp sexp]
+ symbolp
+ stringp))
+ (doc-string 3)
+ (indent 2))
+ (pcase-let ((`(,documentation
+ ,documentation-supplied-p
+ ,keys ,mode ,arg)
+ (ert-font-lock--parse-macro-args docstring-keys-mode-and-str)))
+
+ `(ert-set-test ',name
+ (make-ert-test
+ :name ',name
+ ,@(when documentation-supplied-p
+ `(:documentation ,documentation))
+ ,@(when (map-contains-key keys :expected-result)
+ `(:expected-result-type ,(map-elt keys :expected-result)))
+ ,@(when (map-contains-key keys :tags)
+ `(:tags ,(map-elt keys :tags)))
+ :body (lambda () (ert-font-lock--test-body-str ',mode ,arg ',name))
+
+ :file-name ,(or (macroexp-file-name) buffer-file-name)))))
+
+;;;###autoload
+(defmacro ert-font-lock-deftest-file (name &rest docstring-keys-mode-and-file)
+ "Define test NAME (a symbol) using assertions from FILE.
+
+FILE - path to a file with assertions in ERT resource director as
+return by `ert-resource-directory'.
+
+Other than MAJOR-MODE and FILE parameters, this macro accepts the
+same parameters and keywords as `ert-deftest' and is intended to
+be used through `ert'.
+
+\(fn NAME () [DOCSTRING] [:expected-result RESULT-TYPE] \
+[:tags \\='(TAG...)] MAJOR-MODE FILE)"
+ (declare (debug (&define [&name "test@" symbolp]
+ sexp [&optional stringp]
+ [&rest keywordp sexp]
+ symbolp
+ stringp))
+ (doc-string 3)
+ (indent 2))
+
+ (pcase-let ((`(,documentation
+ ,documentation-supplied-p
+ ,keys ,mode ,arg)
+ (ert-font-lock--parse-macro-args docstring-keys-mode-and-file)))
+
+ `(ert-set-test ',name
+ (make-ert-test
+ :name ',name
+ ,@(when documentation-supplied-p
+ `(:documentation ,documentation))
+ ,@(when (map-contains-key keys :expected-result)
+ `(:expected-result-type ,(map-elt keys :expected-result)))
+ ,@(when (map-contains-key keys :tags)
+ `(:tags ,(map-elt keys :tags)))
+ :body (lambda () (ert-font-lock--test-body-file
+ ',mode (ert-resource-file ,arg) ',name))
+ :file-name ,(or (macroexp-file-name) buffer-file-name)))))
+
+(defun ert-font-lock--in-comment-p ()
+ "Check if the current point is inside a comment."
+ (nth 4 (syntax-ppss)))
+
+(defun ert-font-lock--comment-start-p ()
+ "Check if the current point starts a comment."
+ (or
+ ;; regexps use syntax tables so let's check that first
+ (looking-at "\\s<")
+
+ ;; check newcomment.el facilities
+ (and comment-start (looking-at (regexp-quote comment-start)))
+ (and comment-start-skip (looking-at comment-start-skip))
+
+ ;; sometimes comment syntax is just hardcoded
+ (and (derived-mode-p '(c-mode c++-mode java-mode))
+ (looking-at-p "//"))))
+
+(defun ert-font-lock--line-comment-p ()
+ "Return t if the current line is a comment-only line."
+ (syntax-ppss)
+ (save-excursion
+ (beginning-of-line)
+ (skip-syntax-forward " ")
+ ;; skip empty lines
+ (unless (eolp)
+ (or
+ ;; multiline comments
+ (ert-font-lock--in-comment-p)
+
+ ;; single line comments
+ (ert-font-lock--comment-start-p)))))
+
+(defun ert-font-lock--line-assertion-p ()
+ "Return t if the current line contains an assertion."
+ (syntax-ppss)
+ (save-excursion
+ (beginning-of-line)
+ (skip-syntax-forward " ")
+ (re-search-forward ert-font-lock--assertion-re
+ (line-end-position) t 1)))
+
+(defun ert-font-lock--goto-first-char ()
+ "Move the point to the first character."
+ (beginning-of-line)
+ (skip-syntax-forward " "))
+
+(defun ert-font-lock--get-first-char-column ()
+ "Get the position of the first non-empty char in the current line."
+ (save-excursion
+ (ert-font-lock--goto-first-char)
+ (- (point) (line-beginning-position))))
+
+(defun ert-font-lock--parse-comments ()
+ "Read test assertions from comments in the current buffer."
+ (let ((tests '())
+ (curline 1)
+ (linetocheck -1))
+
+ (goto-char (point-min))
+
+ ;; Go through all lines, for comments check if there are
+ ;; assertions. For non-comment and comment/non-assert lines
+ ;; remember the last line seen.
+ (while (not (eobp))
+ (catch 'nextline
+
+ ;; Not a comment? remember the line, move to the next one
+ (unless (ert-font-lock--line-comment-p)
+ (setq linetocheck curline)
+ (throw 'nextline t))
+
+ ;; A comment. Not an assertion? remember the line to be
+ ;; checked, move to the next line
+ (unless (ert-font-lock--line-assertion-p)
+ (setq linetocheck curline)
+ (throw 'nextline t))
+
+
+ ;; Collect the assertion
+ (when (re-search-forward ert-font-lock--assertion-re
+ (line-end-position) t 1)
+
+ (unless (> linetocheck -1)
+ (user-error "Invalid test comment syntax at line %d. Expected a line to test before the comment line" curline))
+
+ ;; construct a test
+ (let* (;; either comment start char column (for arrows) or
+ ;; caret column
+ (column-checked (if (equal (match-string-no-properties 1) "^")
+ (- (match-beginning 1) (line-beginning-position))
+ (ert-font-lock--get-first-char-column)))
+ ;; negate the face?
+ (negation (string-equal (match-string-no-properties 2) "!"))
+ ;; the face that is supposed to be in the position specified
+ (face (match-string-no-properties 3)))
+
+ (push (list :line-checked linetocheck
+ :line-assert curline
+ :column-checked column-checked
+ :face face
+ :negation negation)
+ tests))))
+
+ ;; next line
+ (setq curline (1+ curline))
+ (forward-line 1))
+
+ (reverse tests)))
+
+(defun ert-font-lock--point-at-line-and-column (line column)
+ "Get the buffer position for LINE and COLUMN."
+ (save-excursion
+ (goto-char (point-min))
+ (forward-line (1- line))
+ (move-to-column column)
+ (point)))
+
+(defun ert-font-lock--get-line (line-number)
+ "Return the content of the line specified by LINE-NUMBER."
+ (save-excursion
+ (goto-char (point-min))
+ (forward-line (1- line-number))
+ (buffer-substring-no-properties (line-beginning-position) (line-end-position))))
+
+(defun ert-font-lock--check-faces (tests)
+ "Check if the current buffer is fontified correctly.
+TESTS - tests to run.
+
+The function is meant to be run from within an ERT test."
+ (dolist (test tests)
+ (let* ((line-checked (plist-get test :line-checked))
+ (line-assert (plist-get test :line-assert))
+ (column-checked (plist-get test :column-checked))
+ (expected-face (intern (plist-get test :face)))
+ (negation (plist-get test :negation))
+
+ (actual-face (get-text-property (ert-font-lock--point-at-line-and-column line-checked column-checked) 'face))
+ (line-str (ert-font-lock--get-line line-checked))
+ (line-assert-str (ert-font-lock--get-line line-assert)))
+
+ (when (not (eq actual-face expected-face))
+ (ert-fail
+ (list (format "Expected face %S, got %S on line %d column %d"
+ expected-face actual-face line-checked column-checked)
+ :line line-str
+ :assert line-assert-str)))
+
+ (when (and negation (eq actual-face expected-face))
+ (ert-fail
+ (list (format "Did not expect face %S face on line %d, column %d"
+ actual-face line-checked column-checked)
+ :line line-str
+ :assert line-assert-str))))))
+
+;;;###autoload
+(defun ert-font-lock-test-string (test-string mode)
+ "Check font faces in TEST-STRING set by MODE.
+
+The function is meant to be run from within an ERT test."
+ (ert-font-lock--validate-major-mode mode)
+ (with-temp-buffer
+ (insert test-string)
+ (funcall mode)
+ (font-lock-ensure)
+
+ (ert-font-lock--check-faces (ert-font-lock--parse-comments)))
+
+ (ert-pass))
+
+;;;###autoload
+(defun ert-font-lock-test-file (filename mode)
+ "Check font faces in FILENAME set by MODE.
+
+The function is meant to be run from within an ERT test."
+ (ert-font-lock--validate-major-mode mode)
+ (with-temp-buffer
+ (insert-file-contents filename)
+ (funcall mode)
+ (font-lock-ensure)
+
+ (ert-font-lock--check-faces (ert-font-lock--parse-comments)))
+
+ (ert-pass))
+
+
+(provide 'ert-font-lock)
+
+;;; ert-font-lock.el ends here
diff --git a/lisp/emacs-lisp/ert-x.el b/lisp/emacs-lisp/ert-x.el
index e8b0dd92989..05da0f1844e 100644
--- a/lisp/emacs-lisp/ert-x.el
+++ b/lisp/emacs-lisp/ert-x.el
@@ -1,6 +1,6 @@
;;; ert-x.el --- Staging area for experimental extensions to ERT -*- lexical-binding: t -*-
-;; Copyright (C) 2008, 2010-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008, 2010-2024 Free Software Foundation, Inc.
;; Author: Lennart Borgman (lennart O borgman A gmail O com)
;; Christian Ohler <ohler@gnu.org>
diff --git a/lisp/emacs-lisp/ert.el b/lisp/emacs-lisp/ert.el
index 4ea894f4ede..353c1bd09d2 100644
--- a/lisp/emacs-lisp/ert.el
+++ b/lisp/emacs-lisp/ert.el
@@ -1,6 +1,6 @@
;;; ert.el --- Emacs Lisp Regression Testing -*- lexical-binding: t -*-
-;; Copyright (C) 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2024 Free Software Foundation, Inc.
;; Author: Christian Ohler <ohler@gnu.org>
;; Keywords: lisp, tools
@@ -34,17 +34,18 @@
;; `ert-run-tests-batch-and-exit' for non-interactive use.
;;
;; The body of `ert-deftest' forms resembles a function body, but the
-;; additional operators `should', `should-not', `should-error' and
-;; `skip-unless' are available. `should' is similar to cl's `assert',
-;; but signals a different error when its condition is violated that
-;; is caught and processed by ERT. In addition, it analyzes its
-;; argument form and records information that helps debugging
-;; (`cl-assert' tries to do something similar when its second argument
-;; SHOW-ARGS is true, but `should' is more sophisticated). For
-;; information on `should-not' and `should-error', see their
-;; docstrings. `skip-unless' skips the test immediately without
-;; processing further, this is useful for checking the test
-;; environment (like availability of features, external binaries, etc).
+;; additional operators `should', `should-not', `should-error',
+;; `skip-when' and `skip-unless' are available. `should' is similar
+;; to cl's `assert', but signals a different error when its condition
+;; is violated that is caught and processed by ERT. In addition, it
+;; analyzes its argument form and records information that helps
+;; debugging (`cl-assert' tries to do something similar when its
+;; second argument SHOW-ARGS is true, but `should' is more
+;; sophisticated). For information on `should-not' and
+;; `should-error', see their docstrings. The `skip-when' and
+;; `skip-unless' forms skip the test immediately, which is useful for
+;; checking the test environment (like availability of features,
+;; external binaries, etc).
;;
;; See ERT's Info manual `(ert) Top' as well as the docstrings for
;; more details. To see some examples of tests written in ERT, see
@@ -98,7 +99,7 @@ Even modest settings for `print-length' and `print-level' can
produce extremely long lines in backtraces and lengthy delays in
forming them. This variable governs the target maximum line
length by manipulating these two variables while printing stack
-traces. Setting this variable to t will re-use the value of
+traces. Setting this variable to t will reuse the value of
`backtrace-line-length' while printing stack traces in ERT batch
mode. Any other value will be temporarily bound to
`backtrace-line-length' when producing stack traces in batch
@@ -151,7 +152,7 @@ mode.")
(when (and noninteractive (get symbol 'ert--test))
;; Make sure duplicated tests are discovered since the older test would
;; be ignored silently otherwise.
- (error "Test `%s' redefined" symbol))
+ (error "Test `%s' redefined (or loaded twice)" symbol))
(define-symbol-prop symbol 'ert--test definition)
definition)
@@ -194,8 +195,8 @@ and the body."
BODY is evaluated as a `progn' when the test is run. It should
signal a condition on failure or just return if the test passes.
-`should', `should-not', `should-error' and `skip-unless' are
-useful for assertions in BODY.
+`should', `should-not', `should-error', `skip-when', and
+`skip-unless' are useful for assertions in BODY.
Use `ert' to run tests interactively.
@@ -227,7 +228,8 @@ in batch mode, an error is signaled.
(tags nil tags-supplied-p))
body)
(ert--parse-keys-and-body docstring-keys-and-body)
- `(cl-macrolet ((skip-unless (form) `(ert--skip-unless ,form)))
+ `(cl-macrolet ((skip-when (form) `(ert--skip-when ,form))
+ (skip-unless (form) `(ert--skip-unless ,form)))
(ert-set-test ',name
(make-ert-test
:name ',name
@@ -464,6 +466,15 @@ failed."
(list
:fail-reason "did not signal an error")))))))))
+(cl-defmacro ert--skip-when (form)
+ "Evaluate FORM. If it returns t, skip the current test.
+Errors during evaluation are caught and handled like t."
+ (declare (debug t))
+ (ert--expand-should `(skip-when ,form) form
+ (lambda (inner-form form-description-form _value-var)
+ `(when (condition-case nil ,inner-form (t t))
+ (ert-skip ,form-description-form)))))
+
(cl-defmacro ert--skip-unless (form)
"Evaluate FORM. If it returns nil, skip the current test.
Errors during evaluation are caught and handled like nil."
diff --git a/lisp/emacs-lisp/ewoc.el b/lisp/emacs-lisp/ewoc.el
index 56527afcf12..da481c9850a 100644
--- a/lisp/emacs-lisp/ewoc.el
+++ b/lisp/emacs-lisp/ewoc.el
@@ -1,6 +1,6 @@
;;; ewoc.el --- utility to maintain a view of a list of objects in a buffer -*- lexical-binding: t -*-
-;; Copyright (C) 1991-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1991-2024 Free Software Foundation, Inc.
;; Author: Per Cederqvist <ceder@lysator.liu.se>
;; Inge Wallin <inge@lysator.liu.se>
diff --git a/lisp/emacs-lisp/faceup.el b/lisp/emacs-lisp/faceup.el
index f8d6c263cd1..f54bd08428c 100644
--- a/lisp/emacs-lisp/faceup.el
+++ b/lisp/emacs-lisp/faceup.el
@@ -1,6 +1,6 @@
;;; faceup.el --- Markup language for faces and font-lock regression testing -*- lexical-binding: t -*-
-;; Copyright (C) 2013-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2024 Free Software Foundation, Inc.
;; Author: Anders Lindgren
;; Version: 0.0.6
diff --git a/lisp/emacs-lisp/find-func.el b/lisp/emacs-lisp/find-func.el
index d393ccc759a..63f547ebeb8 100644
--- a/lisp/emacs-lisp/find-func.el
+++ b/lisp/emacs-lisp/find-func.el
@@ -1,6 +1,6 @@
;;; find-func.el --- find the definition of the Emacs Lisp function near point -*- lexical-binding:t -*-
-;; Copyright (C) 1997, 1999, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997, 1999, 2001-2024 Free Software Foundation, Inc.
;; Author: Jens Petersen <petersen@kurims.kyoto-u.ac.jp>
;; Keywords: emacs-lisp, functions, variables
@@ -42,8 +42,6 @@
;;; Code:
-(eval-when-compile (require 'cl-lib))
-
;;; User variables:
(defgroup find-function nil
@@ -247,13 +245,19 @@ LIBRARY should be a string (the name of the library)."
;; LIBRARY may be "foo.el" or "foo".
(let ((load-re
(concat "\\(" (regexp-quote (file-name-sans-extension library)) "\\)"
- (regexp-opt (get-load-suffixes)) "\\'")))
- (cl-loop
- for (file . _) in load-history thereis
- (and (stringp file) (string-match load-re file)
- (let ((dir (substring file 0 (match-beginning 1)))
- (basename (match-string 1 file)))
- (locate-file basename (list dir) (find-library-suffixes)))))))
+ (regexp-opt (get-load-suffixes)) "\\'"))
+ (alist load-history)
+ elt file found)
+ (while (and alist (null found))
+ (setq elt (car alist)
+ alist (cdr alist)
+ file (car elt)
+ found (and (stringp file) (string-match load-re file)
+ (let ((dir (substring file 0 (match-beginning 1)))
+ (basename (match-string 1 file)))
+ (locate-file basename (list dir)
+ (find-library-suffixes))))))
+ found))
(defvar find-function-C-source-directory
(let ((dir (expand-file-name "src" source-directory)))
@@ -469,7 +473,8 @@ Return t if any PRED returns t."
((not (consp form)) nil)
((funcall pred form) t)
(t
- (cl-destructuring-bind (left-child . right-child) form
+ (let ((left-child (car form))
+ (right-child (cdr form)))
(or
(find-function--any-subform-p left-child pred)
(find-function--any-subform-p right-child pred))))))
diff --git a/lisp/emacs-lisp/float-sup.el b/lisp/emacs-lisp/float-sup.el
index 84083c65292..32c0b31bdcf 100644
--- a/lisp/emacs-lisp/float-sup.el
+++ b/lisp/emacs-lisp/float-sup.el
@@ -1,6 +1,6 @@
;;; float-sup.el --- define some constants useful for floating point numbers. -*- lexical-binding:t -*-
-;; Copyright (C) 1985-1987, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1985-1987, 2001-2024 Free Software Foundation, Inc.
;; Maintainer: emacs-devel@gnu.org
;; Keywords: internal
diff --git a/lisp/emacs-lisp/generate-lisp-file.el b/lisp/emacs-lisp/generate-lisp-file.el
index b2f67ab848d..2c4d2c7cb9a 100644
--- a/lisp/emacs-lisp/generate-lisp-file.el
+++ b/lisp/emacs-lisp/generate-lisp-file.el
@@ -1,6 +1,6 @@
;;; generate-lisp-file.el --- utility functions for generated files -*- lexical-binding: t -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;; Keywords: maint
;; Package: emacs
diff --git a/lisp/emacs-lisp/generator.el b/lisp/emacs-lisp/generator.el
index 9b0e5ad6352..605622904c0 100644
--- a/lisp/emacs-lisp/generator.el
+++ b/lisp/emacs-lisp/generator.el
@@ -1,6 +1,6 @@
;;; generator.el --- generators -*- lexical-binding: t -*-
-;; Copyright (C) 2015-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2024 Free Software Foundation, Inc.
;; Author: Daniel Colascione <dancol@dancol.org>
;; Keywords: extensions, elisp
diff --git a/lisp/emacs-lisp/generic.el b/lisp/emacs-lisp/generic.el
index b734bff1108..2d51f93a77b 100644
--- a/lisp/emacs-lisp/generic.el
+++ b/lisp/emacs-lisp/generic.el
@@ -1,6 +1,6 @@
;;; generic.el --- defining simple major modes with comment and font-lock -*- lexical-binding: t; -*-
;;
-;; Copyright (C) 1997, 1999, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997, 1999, 2001-2024 Free Software Foundation, Inc.
;;
;; Author: Peter Breton <pbreton@cs.umb.edu>
;; Created: Fri Sep 27 1996
diff --git a/lisp/emacs-lisp/gv.el b/lisp/emacs-lisp/gv.el
index a5e29dd5e3b..fa9b437fcfd 100644
--- a/lisp/emacs-lisp/gv.el
+++ b/lisp/emacs-lisp/gv.el
@@ -1,6 +1,6 @@
;;; gv.el --- generalized variables -*- lexical-binding: t -*-
-;; Copyright (C) 2012-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2012-2024 Free Software Foundation, Inc.
;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
;; Keywords: extensions
@@ -411,7 +411,6 @@ The return value is the last VAL in the list.
(gv-define-setter buffer-local-value (val var buf)
(macroexp-let2 nil v val
`(with-current-buffer ,buf (set (make-local-variable ,var) ,v))))
-(make-obsolete-generalized-variable 'buffer-local-value nil "29.1")
(gv-define-expander alist-get
(lambda (do key alist &optional default remove testfn)
@@ -639,7 +638,7 @@ REF must have been previously obtained with `gv-ref'."
;;; Generalized variables.
-;; You'd think noone would write `(setf (error ...) ..)' but it
+;; You'd think no one would write `(setf (error ...) ..)' but it
;; appears naturally as the result of macroexpansion of things like
;; (setf (pcase-exhaustive ...)).
;; We could generalize this to `throw' and `signal', but it seems
@@ -822,17 +821,5 @@ REF must have been previously obtained with `gv-ref'."
((eq ,getter ,val) ,(funcall setter `(not ,val))))))))))
(make-obsolete-generalized-variable 'eq nil "29.1")
-(gv-define-expander substring
- (lambda (do place from &optional to)
- (gv-letplace (getter setter) place
- (macroexp-let2* nil ((start from) (end to))
- (funcall do `(substring ,getter ,start ,end)
- (lambda (v)
- (macroexp-let2 nil v v
- `(progn
- ,(funcall setter `(cl--set-substring
- ,getter ,start ,end ,v))
- ,v))))))))
-
(provide 'gv)
;;; gv.el ends here
diff --git a/lisp/emacs-lisp/helper.el b/lisp/emacs-lisp/helper.el
index 5d6fa6a77ea..0446109f5ac 100644
--- a/lisp/emacs-lisp/helper.el
+++ b/lisp/emacs-lisp/helper.el
@@ -1,6 +1,6 @@
;;; helper.el --- utility help package supporting help in electric modes -*- lexical-binding: t; -*-
-;; Copyright (C) 1985-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1985-2024 Free Software Foundation, Inc.
;; Author: K. Shane Hartman
;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/emacs-lisp/hierarchy.el b/lisp/emacs-lisp/hierarchy.el
index 05509378c82..9011f3d164d 100644
--- a/lisp/emacs-lisp/hierarchy.el
+++ b/lisp/emacs-lisp/hierarchy.el
@@ -1,6 +1,6 @@
;;; hierarchy.el --- Library to create and display hierarchical structures -*- lexical-binding: t; -*-
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
;; Author: Damien Cassou <damien@cassou.me>
;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/emacs-lisp/icons.el b/lisp/emacs-lisp/icons.el
index cb08c1a6b81..a35a00ec1f3 100644
--- a/lisp/emacs-lisp/icons.el
+++ b/lisp/emacs-lisp/icons.el
@@ -1,6 +1,6 @@
;;; icons.el --- Handling icons -*- lexical-binding:t -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;; Author: Lars Ingebrigtsen <larsi@gnus.org>
;; Keywords: icons buttons
@@ -181,9 +181,9 @@ present if the icon is represented by an image."
(let ((parent-keywords (icon-spec-keywords elem))
(current-keywords (icon-spec-keywords current)))
(while parent-keywords
- (unless (plist-get (car parent-keywords) current-keywords)
- (nconc current (take 2 parent-keywords))
- (setq parent-keywords (cddr parent-keywords))))))))
+ (unless (plist-get current-keywords (car parent-keywords))
+ (nconc current (take 2 parent-keywords)))
+ (setq parent-keywords (cddr parent-keywords)))))))
merged)
(cl-defmethod icons--create ((_type (eql 'image)) icon keywords)
diff --git a/lisp/emacs-lisp/inline.el b/lisp/emacs-lisp/inline.el
index f761fda29a8..c774296084e 100644
--- a/lisp/emacs-lisp/inline.el
+++ b/lisp/emacs-lisp/inline.el
@@ -1,6 +1,6 @@
;;; inline.el --- Define functions by their inliner -*- lexical-binding:t; -*-
-;; Copyright (C) 2014-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2014-2024 Free Software Foundation, Inc.
;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
diff --git a/lisp/emacs-lisp/let-alist.el b/lisp/emacs-lisp/let-alist.el
index d9ad46b2af7..cdd476d9df6 100644
--- a/lisp/emacs-lisp/let-alist.el
+++ b/lisp/emacs-lisp/let-alist.el
@@ -1,6 +1,6 @@
;;; let-alist.el --- Easily let-bind values of an assoc-list by their names -*- lexical-binding: t; -*-
-;; Copyright (C) 2014-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2014-2024 Free Software Foundation, Inc.
;; Author: Artur Malabarba <emacs@endlessparentheses.com>
;; Package-Requires: ((emacs "24.1"))
@@ -9,8 +9,8 @@
;; Prefix: let-alist
;; Separator: -
-;; This is an Elpa :core package. Don't use functionality that is not
-;; compatible with Emacs 24.1.
+;; This is a GNU ELPA :core package. Avoid functionality that is not
+;; compatible with the version of Emacs recorded above.
;; This file is part of GNU Emacs.
@@ -60,7 +60,7 @@
;; the variables of the outer one. You can, however, access alists
;; inside the original alist by using dots inside the symbol, as
;; displayed in the example above by the `.site.contents'.
-;;
+
;;; Code:
@@ -139,7 +139,14 @@ essentially expands to
If you nest `let-alist' invocations, the inner one can't access
the variables of the outer one. You can, however, access alists
inside the original alist by using dots inside the symbol, as
-displayed in the example above."
+displayed in the example above.
+
+Note that there is no way to differentiate the case where a key
+is missing from when it is present, but its value is nil. Thus,
+the following form evaluates to nil:
+
+ (let-alist \\='((some-key . nil))
+ .some-key)"
(declare (indent 1) (debug t))
(let ((var (make-symbol "alist")))
`(let ((,var ,alist))
diff --git a/lisp/emacs-lisp/lisp-mnt.el b/lisp/emacs-lisp/lisp-mnt.el
index cb7cff43555..f111a77663c 100644
--- a/lisp/emacs-lisp/lisp-mnt.el
+++ b/lisp/emacs-lisp/lisp-mnt.el
@@ -1,6 +1,7 @@
;;; lisp-mnt.el --- utility functions for Emacs Lisp maintainers -*- lexical-binding:t -*-
-;; Copyright (C) 1992-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1992, 1994, 1997, 2000-2024 Free Software Foundation,
+;; Inc.
;; Author: Eric S. Raymond <esr@thyrsus.com>
;; Maintainer: emacs-devel@gnu.org
@@ -434,6 +435,38 @@ This can be found in an RCS or SCCS header."
header-max t)
(match-string-no-properties 1)))))))
+(defun lm--prepare-package-dependencies (deps)
+ "Turn DEPS into an acceptable list of dependencies.
+
+Any parts missing a version string get a default version string
+of \"0\" (meaning any version) and an appropriate level of lists
+is wrapped around any parts requiring it."
+ (cond
+ ((not (listp deps))
+ (error "Invalid requirement specifier: %S" deps))
+ (t (mapcar (lambda (dep)
+ (cond
+ ((symbolp dep) `(,dep "0"))
+ ((stringp dep)
+ (error "Invalid requirement specifier: %S" dep))
+ ((and (listp dep) (null (cdr dep)))
+ (list (car dep) "0"))
+ (t dep)))
+ deps))))
+
+(declare-function package-read-from-string "package" (str))
+
+(defun lm-package-requires (&optional file)
+ "Return dependencies listed in file FILE, or current buffer if FILE is nil.
+The return value is a list of elements of the form (PACKAGE VERSION)
+where PACKAGE is the package name (a symbol) and VERSION is the
+package version (a string)."
+ (require 'package)
+ (lm-with-file file
+ (and-let* ((require-lines (lm-header-multiline "package-requires")))
+ (lm--prepare-package-dependencies
+ (package-read-from-string (mapconcat #'identity require-lines " "))))))
+
(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
diff --git a/lisp/emacs-lisp/lisp-mode.el b/lisp/emacs-lisp/lisp-mode.el
index 3bf9a2f10db..1bb9c2fdc2e 100644
--- a/lisp/emacs-lisp/lisp-mode.el
+++ b/lisp/emacs-lisp/lisp-mode.el
@@ -1,6 +1,6 @@
;;; lisp-mode.el --- Lisp mode, and its idiosyncratic commands -*- lexical-binding:t -*-
-;; Copyright (C) 1985-1986, 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1985-1986, 1999-2024 Free Software Foundation, Inc.
;; Maintainer: emacs-devel@gnu.org
;; Keywords: lisp, languages
@@ -31,11 +31,6 @@
(eval-when-compile (require 'cl-lib))
(eval-when-compile (require 'subr-x))
-(defvar font-lock-comment-face)
-(defvar font-lock-doc-face)
-(defvar font-lock-keywords-case-fold-search)
-(defvar font-lock-string-face)
-
(define-abbrev-table 'lisp-mode-abbrev-table ()
"Abbrev table for Lisp mode.")
diff --git a/lisp/emacs-lisp/lisp.el b/lisp/emacs-lisp/lisp.el
index a4aa79c171e..c57b1357f63 100644
--- a/lisp/emacs-lisp/lisp.el
+++ b/lisp/emacs-lisp/lisp.el
@@ -1,6 +1,6 @@
;;; lisp.el --- Lisp editing commands for Emacs -*- lexical-binding:t -*-
-;; Copyright (C) 1985-1986, 1994, 2000-2023 Free Software Foundation,
+;; Copyright (C) 1985-1986, 1994, 2000-2024 Free Software Foundation,
;; Inc.
;; Maintainer: emacs-devel@gnu.org
@@ -93,7 +93,7 @@ report errors as appropriate for this kind of usage."
(defun mark-sexp (&optional arg allow-extend)
"Set mark ARG sexps from point or move mark one sexp.
-When called from Lisp with ALLOW-EXTEND ommitted or nil, mark is
+When called from Lisp with ALLOW-EXTEND omitted or nil, mark is
set ARG sexps from point.
With ARG and ALLOW-EXTEND both non-nil (interactively, with prefix
argument), the place to which mark goes is the same place \\[forward-sexp]
@@ -422,7 +422,8 @@ of a defun, nil if it failed to find one."
"\\(?:" defun-prompt-regexp "\\)\\s(")
"^\\s(")
nil 'move arg))
- (nth 8 (syntax-ppss))))
+ (save-match-data
+ (nth 8 (syntax-ppss)))))
found)
(progn (goto-char (1- (match-end 0)))
t)))
diff --git a/lisp/emacs-lisp/loaddefs-gen.el b/lisp/emacs-lisp/loaddefs-gen.el
index d7b9b131bc8..5f152d3b509 100644
--- a/lisp/emacs-lisp/loaddefs-gen.el
+++ b/lisp/emacs-lisp/loaddefs-gen.el
@@ -1,6 +1,6 @@
;;; loaddefs-gen.el --- generate loaddefs.el files -*- lexical-binding: t -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;; Keywords: maint
;; Package: emacs
@@ -48,6 +48,7 @@ Standard prefixes won't be registered anyway. I.e. if a file
\"foo.el\" defines variables or functions that use \"foo-\" as
prefix, that will not be registered. But all other prefixes will
be included.")
+;;;###autoload
(put 'autoload-compute-prefixes 'safe-local-variable #'booleanp)
(defvar no-update-autoloads nil
diff --git a/lisp/emacs-lisp/macroexp.el b/lisp/emacs-lisp/macroexp.el
index 6d5cf8723f9..0e4fd3ea521 100644
--- a/lisp/emacs-lisp/macroexp.el
+++ b/lisp/emacs-lisp/macroexp.el
@@ -1,6 +1,6 @@
;;; macroexp.el --- Additional macro-expansion support -*- lexical-binding: t -*-
;;
-;; Copyright (C) 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2004-2024 Free Software Foundation, Inc.
;;
;; Author: Miles Bader <miles@gnu.org>
;; Keywords: lisp, compiler, macros
@@ -39,6 +39,18 @@ 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.")
+(defmacro macroexp--with-extended-form-stack (expr &rest body)
+ "Evaluate BODY with EXPR pushed onto `byte-compile-form-stack'."
+ (declare (indent 1))
+ ;; FIXME: We really should just be using a simple dynamic let-binding here,
+ ;; but these explicit push and pop make the extended stack value visible
+ ;; to error handlers. Remove that need for that!
+ `(progn
+ (push ,expr byte-compile-form-stack)
+ (prog1
+ (progn ,@body)
+ (pop byte-compile-form-stack))))
+
;; Bound by the top-level `macroexpand-all', and modified to include any
;; macros defined by `defmacro'.
(defvar macroexpand-all-environment nil)
@@ -105,13 +117,21 @@ each clause."
(macroexp--all-forms clause skip)
clause)))
+(defvar macroexp-inhibit-compiler-macros nil
+ "Inhibit application of compiler macros if non-nil.")
+
(defun macroexp--compiler-macro (handler form)
- (condition-case-unless-debug err
- (apply handler form (cdr form))
- (error
- (message "Warning: Optimization failure for %S: Handler: %S\n%S"
- (car form) handler err)
- form)))
+ "Apply compiler macro HANDLER to FORM and return the result.
+Unless `macroexp-inhibit-compiler-macros' is non-nil, in which
+case return FORM unchanged."
+ (if macroexp-inhibit-compiler-macros
+ form
+ (condition-case-unless-debug err
+ (apply handler form (cdr form))
+ (error
+ (message "Warning: Optimization failure for %S: Handler: %S\n%S"
+ (car form) handler err)
+ form))))
(defun macroexp--funcall-if-compiled (_form)
"Pseudo function used internally by macroexp to delay warnings.
@@ -314,8 +334,7 @@ Only valid during macro-expansion."
"Expand all macros in FORM.
This is an internal version of `macroexpand-all'.
Assumes the caller has bound `macroexpand-all-environment'."
- (push form byte-compile-form-stack)
- (prog1
+ (macroexp--with-extended-form-stack form
(if (eq (car-safe form) 'backquote-list*)
;; Special-case `backquote-list*', as it is normally a macro that
;; generates exceedingly deep expansions from relatively shallow input
@@ -330,7 +349,34 @@ Assumes the caller has bound `macroexpand-all-environment'."
(let ((fn (car-safe form)))
(pcase form
(`(cond . ,clauses)
- (macroexp--cons fn (macroexp--all-clauses clauses) form))
+ ;; Check for rubbish clauses at the end before macro-expansion,
+ ;; to avoid nuisance warnings from clauses that become
+ ;; unconditional through that process.
+ ;; FIXME: this strategy is defeated by forced `macroexpand-all',
+ ;; such as in `cl-flet'. Haven't seen that in the wild, though.
+ (let ((default-tail nil)
+ (n 0)
+ (rest clauses))
+ (while rest
+ (let ((c (car-safe (car rest))))
+ (when (cond ((consp c) (and (memq (car c) '(quote function))
+ (cadr c)))
+ ((symbolp c) (or (eq c t) (keywordp c)))
+ (t t))
+ ;; This is unquestionably a default clause.
+ (setq default-tail (cdr rest))
+ (setq clauses (take (1+ n) clauses)) ; trim the tail
+ (setq rest nil)))
+ (setq n (1+ n))
+ (setq rest (cdr rest)))
+ (let ((expanded-form
+ (macroexp--cons fn (macroexp--all-clauses clauses) form)))
+ (if default-tail
+ (macroexp-warn-and-return
+ (format-message
+ "Useless clause following default `cond' clause")
+ expanded-form '(suspicious cond) t default-tail)
+ expanded-form))))
(`(condition-case . ,(or `(,err ,body . ,handlers) pcase--dontcare))
(let ((exp-body (macroexp--expand-all body)))
(if handlers
@@ -473,8 +519,7 @@ Assumes the caller has bound `macroexpand-all-environment'."
newform
(macroexp--expand-all form)))
(macroexp--expand-all newform))))))
- (_ form))))
- (pop byte-compile-form-stack)))
+ (_ form))))))
;;;###autoload
(defun macroexpand-all (form &optional environment)
@@ -498,11 +543,17 @@ definitions to shadow the loaded ones for use in file byte-compilation."
(defun macroexp-parse-body (body)
"Parse a function BODY into (DECLARATIONS . EXPS)."
(let ((decls ()))
- (while (and (cdr body)
- (let ((e (car body)))
- (or (stringp e)
- (memq (car-safe e)
- '(:documentation declare interactive cl-declare)))))
+ (while
+ (and body
+ (let ((e (car body)))
+ (or (and (stringp e)
+ ;; If there is only a string literal with
+ ;; nothing following, we consider this to be
+ ;; part of the body (the return value) rather
+ ;; than a declaration at this point.
+ (cdr body))
+ (memq (car-safe e)
+ '(:documentation declare interactive cl-declare)))))
(push (pop body) decls))
(cons (nreverse decls) body)))
@@ -785,7 +836,7 @@ test of free variables in the following ways:
(if full-p
(macroexpand--all-toplevel form)
(macroexpand form)))
- (error
+ ((debug error)
;; Hopefully this shouldn't happen thanks to the cycle detection,
;; but in case it does happen, let's catch the error and give the
;; code a chance to macro-expand later.
diff --git a/lisp/emacs-lisp/map-ynp.el b/lisp/emacs-lisp/map-ynp.el
index cb1cc88e78f..b603f2e6d0b 100644
--- a/lisp/emacs-lisp/map-ynp.el
+++ b/lisp/emacs-lisp/map-ynp.el
@@ -1,6 +1,6 @@
;;; map-ynp.el --- general-purpose boolean question-asker -*- lexical-binding:t -*-
-;; Copyright (C) 1991-1995, 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1991-1995, 2000-2024 Free Software Foundation, Inc.
;; Author: Roland McGrath <roland@gnu.org>
;; Maintainer: emacs-devel@gnu.org
@@ -168,16 +168,14 @@ The function's value is the number of actions taken."
(key-description (vector help-char)))
(if minibuffer-auto-raise
(raise-frame (window-frame (minibuffer-window))))
- (while (progn
- (setq char (read-event))
- ;; If we get -1, from end of keyboard
- ;; macro, try again.
- (equal char -1)))
+ (setq char (read-event))
;; Show the answer to the question.
(message "%s(y, n, !, ., q, %sor %s) %s"
prompt user-keys
(key-description (vector help-char))
- (single-key-description char)))
+ (if (equal char -1)
+ "[end-of-keyboard-macro]"
+ (single-key-description char))))
(setq def (lookup-key map (vector char))))
(cond ((eq def 'exit)
(setq next (lambda () nil)))
diff --git a/lisp/emacs-lisp/map.el b/lisp/emacs-lisp/map.el
index b55eb431668..ffbb29615da 100644
--- a/lisp/emacs-lisp/map.el
+++ b/lisp/emacs-lisp/map.el
@@ -1,6 +1,6 @@
;;; map.el --- Map manipulation functions -*- lexical-binding: t; -*-
-;; Copyright (C) 2015-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2024 Free Software Foundation, Inc.
;; Author: Nicolas Petton <nicolas@petton.fr>
;; Maintainer: emacs-devel@gnu.org
@@ -8,6 +8,9 @@
;; Version: 3.3.1
;; Package-Requires: ((emacs "26"))
+;; This is a GNU ELPA :core package. Avoid functionality that is not
+;; compatible with the version of Emacs recorded above.
+
;; This file is part of GNU Emacs.
;; GNU Emacs is free software: you can redistribute it and/or modify
diff --git a/lisp/emacs-lisp/memory-report.el b/lisp/emacs-lisp/memory-report.el
index 36754277034..661f28ffcb8 100644
--- a/lisp/emacs-lisp/memory-report.el
+++ b/lisp/emacs-lisp/memory-report.el
@@ -1,6 +1,6 @@
;;; memory-report.el --- Short function summaries -*- lexical-binding: t -*-
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
;; Keywords: lisp, help
diff --git a/lisp/emacs-lisp/multisession.el b/lisp/emacs-lisp/multisession.el
index b09777be407..8299e3dffcc 100644
--- a/lisp/emacs-lisp/multisession.el
+++ b/lisp/emacs-lisp/multisession.el
@@ -1,6 +1,6 @@
;;; multisession.el --- Multisession storage for variables -*- lexical-binding: t; -*-
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -137,8 +137,6 @@ DOC should be a doc string, and ARGS are keywords as applicable to
(declare-function sqlite-select "sqlite.c")
(declare-function sqlite-open "sqlite.c")
(declare-function sqlite-pragma "sqlite.c")
-(declare-function sqlite-transaction "sqlite.c")
-(declare-function sqlite-commit "sqlite.c")
(defvar multisession--db nil)
diff --git a/lisp/emacs-lisp/nadvice.el b/lisp/emacs-lisp/nadvice.el
index cd80df2c41d..0d45b4b95fa 100644
--- a/lisp/emacs-lisp/nadvice.el
+++ b/lisp/emacs-lisp/nadvice.el
@@ -1,6 +1,6 @@
;;; nadvice.el --- Light-weight advice primitives for Elisp functions -*- lexical-binding: t -*-
-;; Copyright (C) 2012-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2012-2024 Free Software Foundation, Inc.
;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
;; Keywords: extensions, lisp, tools
@@ -292,14 +292,13 @@ HOW is a symbol to select an entry in `advice--how-alist'."
(equal function (cdr (assq 'name props))))
(list (advice--remove-function rest function)))))))
-(defvar advice--buffer-local-function-sample nil
- "Keeps an example of the special \"run the default value\" functions.
-These functions play the same role as t in buffer-local hooks, and to recognize
-them, we keep a sample here against which to compare. Each instance is
-different, but `function-equal' will hopefully ignore those differences.")
+(oclosure-define (advice--forward
+ (:predicate advice--forward-p))
+ "Redirect to the global value of a var.
+These functions act like the t special value in buffer-local hooks.")
(defun advice--set-buffer-local (var val)
- (if (function-equal val advice--buffer-local-function-sample)
+ (if (advice--forward-p val)
(kill-local-variable var)
(set (make-local-variable var) val)))
@@ -308,11 +307,10 @@ different, but `function-equal' will hopefully ignore those differences.")
"Buffer-local value of VAR, presumed to contain a function."
(declare (gv-setter advice--set-buffer-local))
(if (local-variable-p var) (symbol-value var)
- (setq advice--buffer-local-function-sample
- ;; This function acts like the t special value in buffer-local hooks.
- ;; FIXME: Provide an `advice-bottom' function that's like
- ;; `advice-cd*r' but also follows through this proxy.
- (lambda (&rest args) (apply (default-value var) args)))))
+ ;; FIXME: Provide an `advice-bottom' function that's like
+ ;; `advice--cd*r' but also follows through this proxy.
+ (oclosure-lambda (advice--forward) (&rest args)
+ (apply (default-value var) args))))
(eval-and-compile
(defun advice--normalize-place (place)
@@ -391,26 +389,8 @@ is also interactive. There are 3 cases:
`(advice--add-function ,how (gv-ref ,(advice--normalize-place place))
,function ,props))
-(declare-function comp-subr-trampoline-install "comp")
-
;;;###autoload
(defun advice--add-function (how ref function props)
- (when (and (featurep 'native-compile)
- (subr-primitive-p (gv-deref ref)))
- (let ((subr-name (intern (subr-name (gv-deref ref)))))
- ;; Requiring the native compiler to advice `macroexpand' cause a
- ;; circular dependency in eager macro expansion. uniquify is
- ;; advising `rename-buffer' while being loaded in loadup.el.
- ;; This would require the whole native compiler machinery but we
- ;; don't want to include it in the dump. Because these two
- ;; functions are already handled in
- ;; `native-comp-never-optimize-functions' we hack the problem
- ;; this way for now :/
- (unless (memq subr-name '(macroexpand rename-buffer))
- ;; Must require explicitly as during bootstrap we have no
- ;; autoloads.
- (require 'comp)
- (comp-subr-trampoline-install subr-name))))
(let* ((name (cdr (assq 'name props)))
(a (advice--member-p (or name function) (if name t) (gv-deref ref))))
(when a
@@ -529,8 +509,6 @@ HOW can be one of:
<<>>"
;; TODO:
;; - record the advice location, to display in describe-function.
- ;; - change all defadvice in lisp/**/*.el.
- ;; - obsolete advice.el.
(let* ((f (symbol-function symbol))
(nf (advice--normalize symbol f)))
(unless (eq f nf) (fset symbol nf))
diff --git a/lisp/emacs-lisp/oclosure.el b/lisp/emacs-lisp/oclosure.el
index 466822e0e06..26cd8594dfc 100644
--- a/lisp/emacs-lisp/oclosure.el
+++ b/lisp/emacs-lisp/oclosure.el
@@ -1,8 +1,9 @@
;;; oclosure.el --- Open Closures -*- lexical-binding: t; -*-
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
+;; Package: emacs
;; This file is part of GNU Emacs.
@@ -349,6 +350,7 @@ MUTABLE is a list of symbols indicating which of the BINDINGS
should be mutable.
No checking is performed."
(declare (indent 3) (debug (sexp (&rest (sexp form)) sexp def-body)))
+ (cl-assert lexical-binding) ;Can't work in dynbind dialect.
;; FIXME: Fundamentally `oclosure-lambda' should be a special form.
;; We define it here as a macro which expands to something that
;; looks like "normal code" in order to avoid backward compatibility
diff --git a/lisp/emacs-lisp/package-vc.el b/lisp/emacs-lisp/package-vc.el
index b8737e5ccd2..db0cc515e46 100644
--- a/lisp/emacs-lisp/package-vc.el
+++ b/lisp/emacs-lisp/package-vc.el
@@ -1,6 +1,6 @@
;;; package-vc.el --- Manage packages from VC checkouts -*- lexical-binding: t; -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;; Author: Philip Kaludercic <philipk@posteo.net>
;; Keywords: tools
@@ -29,7 +29,7 @@
;; To install a package from source use `package-vc-install'. If you
;; aren't interested in activating a package, you can use
;; `package-vc-checkout' instead, which will prompt you for a target
-;; directory. If you wish to re-use an existing checkout, the command
+;; directory. If you wish to reuse an existing checkout, the command
;; `package-vc-install-from-checkout' will create a symbolic link and
;; prepare the package.
;;
@@ -62,6 +62,18 @@
(defconst package-vc--elpa-packages-version 1
"Version number of the package specification format understood by package-vc.")
+(defconst package-vc--backend-type
+ `(choice :convert-widget
+ ,(lambda (widget)
+ (let (opts)
+ (dolist (be vc-handled-backends)
+ (when (or (vc-find-backend-function be 'clone)
+ (alist-get 'clone (get be 'vc-functions)))
+ (push (widget-convert (list 'const be)) opts)))
+ (widget-put widget :args opts))
+ widget))
+ "The type of VC backends that support cloning package VCS repositories.")
+
(defcustom package-vc-heuristic-alist
`((,(rx bos "http" (? "s") "://"
(or (: (? "www.") "github.com"
@@ -94,22 +106,27 @@
(+ (or alnum "-" "." "_")) (? "/")))
eos)
. Bzr))
- "Heuristic mapping URL regular expressions to VC backends."
+ "Alist mapping repository URLs to VC backends.
+`package-vc-install' consults this alist to determine the VC
+backend from the repository URL when you call it without
+specifying a backend. Each element of the alist has the form
+\(URL-REGEXP . BACKEND). `package-vc-install' will use BACKEND of
+the first association for which the URL of the repository matches
+the URL-REGEXP of the association. If no match is found,
+`package-vc-install' uses `package-vc-default-backend' instead."
:type `(alist :key-type (regexp :tag "Regular expression matching URLs")
- :value-type (choice :tag "VC Backend"
- ,@(mapcar (lambda (b) `(const ,b))
- vc-handled-backends)))
+ :value-type ,package-vc--backend-type)
:version "29.1")
(defcustom package-vc-default-backend 'Git
- "Default VC backend used when cloning a package repository.
-If no repository type was specified or could be guessed by
-`package-vc-heuristic-alist', this is the default VC backend
-used as fallback. The value must be a member of
-`vc-handled-backends' and the named backend must implement
-the `clone' function."
- :type `(choice ,@(mapcar (lambda (b) (list 'const b))
- vc-handled-backends))
+ "Default VC backend to use for cloning package repositories.
+`package-vc-install' uses this backend when you specify neither
+the backend nor a repository URL that's recognized via
+`package-vc-heuristic-alist'.
+
+The value must be a member of `vc-handled-backends' that supports
+the `clone' VC function."
+ :type package-vc--backend-type
:version "29.1")
(defcustom package-vc-register-as-project t
@@ -140,20 +157,21 @@ the `clone' function."
(package-desc-create :name name :kind 'vc))
spec)))))))
-(defcustom package-vc-selected-packages '()
- "List of packages that must be installed.
-Each member of the list is of the form (NAME . SPEC), where NAME
-is a symbol designating the package and SPEC is one of:
+
+(defcustom package-vc-selected-packages nil
+ "List of packages to install from their VCS repositories.
+Each element is of the form (NAME . SPEC), where NAME is a symbol
+designating the package and SPEC is one of:
- nil, if any package version can be installed;
- a version string, if that specific revision is to be installed;
-- a property list, describing a package specification. For more
- details, please consult the subsection \"Specifying Package
- Sources\" in the Info node `(emacs)Fetching Package Sources'.
+- a property list, describing a package specification. For possible
+ values, see the subsection \"Specifying Package Sources\" in the
+ Info node `(emacs)Fetching Package Sources'.
-This user option will be automatically updated to store package
-specifications for packages that are not specified in any
-archive."
+The command `package-vc-install' updates the value of this user
+option to store package specifications for packages that are not
+specified in any archive."
:type '(alist :tag "List of packages you want to be installed"
:key-type (symbol :tag "Package")
:value-type
@@ -344,20 +362,27 @@ asynchronously."
"\n")
nil pkg-file nil 'silent))))
-(defcustom package-vc-allow-side-effects nil
- "Whether to process :make and :shell-command spec arguments.
+(defcustom package-vc-allow-build-commands nil
+ "Whether to run extra build commands when installing VC packages.
+
+Some packages specify \"make\" targets or other shell commands
+that should run prior to building the package, by including the
+:make or :shell-command keywords in their specification. By
+default, Emacs ignores these keywords when installing and
+upgrading VC packages, but if the value is a list of package
+names (symbols), the build commands will be run for those
+packages. If the value is t, always respect :make and
+:shell-command keywords.
It may be necessary to run :make and :shell-command arguments in
order to initialize a package or build its documentation, but
please be careful when changing this option, as installing and
updating a package can run potentially harmful code.
-When set to a list of symbols (packages), run commands for only
-packages in the list. When nil, never run commands. Otherwise
-when non-nil, run commands for any package with :make or
-:shell-command specified.
-
-Package specs are loaded from trusted package archives."
+This applies to package specifications that come from your
+configured package archives, as well as from entries in
+`package-vc-selected-packages' and specifications that you give
+to `package-vc-install' directly."
:type '(choice (const :tag "Run for all packages" t)
(repeat :tag "Run only for selected packages" (symbol :tag "Package name"))
(const :tag "Never run" nil))
@@ -388,42 +413,48 @@ otherwise it's assumed to be an Info file."
(default-directory (package-desc-dir pkg-desc))
(docs-directory (file-name-directory (expand-file-name file)))
(output (expand-file-name (format "%s.info" pkg-name)))
+ (log-buffer (get-buffer-create (format " *package-vc doc: %s*" pkg-name)))
clean-up)
- (when (string-match-p "\\.org\\'" file)
- (require 'ox)
- (require 'ox-texinfo)
- (with-temp-buffer
- (insert-file-contents file)
- (setq file (make-temp-file "ox-texinfo-"))
- (let ((default-directory docs-directory))
- (org-export-to-file 'texinfo file))
- (setq clean-up t)))
- (with-current-buffer (get-buffer-create " *package-vc doc*")
- (erase-buffer)
- (cond
- ((/= 0 (call-process "makeinfo" nil t nil
- "-I" docs-directory
- "--no-split" file
- "-o" output))
- (message "Failed to build manual %s, see buffer %S"
- file (buffer-name)))
- ((/= 0 (call-process "install-info" nil t nil
- output (expand-file-name "dir")))
- (message "Failed to install manual %s, see buffer %S"
- output (buffer-name)))
- ((kill-buffer))))
+ (with-current-buffer log-buffer
+ (erase-buffer))
+ (condition-case err
+ (progn
+ (when (string-match-p "\\.org\\'" file)
+ (require 'ox)
+ (require 'ox-texinfo)
+ (with-temp-buffer
+ (insert-file-contents file)
+ (setq file (make-temp-file "ox-texinfo-"))
+ (let ((default-directory docs-directory))
+ (org-export-to-file 'texinfo file))
+ (setq clean-up t)))
+ (cond
+ ((/= 0 (call-process "makeinfo" nil log-buffer nil
+ "-I" docs-directory
+ "--no-split" file
+ "-o" output))
+ (message "Failed to build manual %s, see buffer %S"
+ file (buffer-name)))
+ ((/= 0 (call-process "install-info" nil log-buffer nil
+ output (expand-file-name "dir")))
+ (message "Failed to install manual %s, see buffer %S"
+ output (buffer-name)))
+ ((kill-buffer log-buffer))))
+ (error (with-current-buffer log-buffer
+ (insert (error-message-string err)))
+ (message "Failed to export org manual for %s, see buffer %S" pkg-name log-buffer)))
(when clean-up
(delete-file file))))
-(defun package-vc-install-dependencies (requirements)
- "Install missing dependencies, and return missing ones.
-The return value will be nil if everything was found, or a list
-of (NAME VERSION) pairs of all packages that couldn't be found.
+(defun package-vc-install-dependencies (deps)
+ "Install missing dependencies according to DEPS.
-REQUIREMENTS should be a list of additional requirements; each
-element in this list should have the form (PACKAGE VERSION-LIST),
-where PACKAGE is a package name and VERSION-LIST is the required
-version of that package."
+DEPS is a list of elements (PACKAGE VERSION-LIST), where
+PACKAGE is a package name and VERSION-LIST is the required
+version of that package.
+
+Return a list of dependencies that couldn't be met (or nil, when
+this function successfully installs all given dependencies)."
(let ((to-install '()) (missing '()))
(cl-labels ((search (pkg)
"Attempt to find all dependencies for PKG."
@@ -457,7 +488,7 @@ version of that package."
(let ((desc-a (package-desc-name a))
(desc-b (package-desc-name b)))
(depends-on-p desc-a desc-b))))
- (mapc #'search requirements)
+ (mapc #'search deps)
(cl-callf sort to-install #'version-order)
(cl-callf seq-uniq to-install #'duplicate-p)
(cl-callf sort to-install #'dependent-order))
@@ -470,26 +501,35 @@ This includes downloading missing dependencies, generating
autoloads, generating a package description file (used to
identify a package as a VC package later on), building
documentation and marking the package as installed."
- (let (missing)
- ;; Remove any previous instance of PKG-DESC from `package-alist'
- (let ((pkgs (assq (package-desc-name pkg-desc) package-alist)))
- (when pkgs
- (setf (cdr pkgs) (seq-remove #'package-vc-p (cdr pkgs)))))
+ (let ((pkg-spec (package-vc--desc->spec pkg-desc))
+ missing)
;; In case the package was installed directly from source, the
;; dependency list wasn't know beforehand, and they might have
;; to be installed explicitly.
- (let ((deps '()))
+ (let ((ignored-files
+ (if (plist-get pkg-spec :ignored-files)
+ (mapconcat
+ (lambda (ignore)
+ (wildcard-to-regexp
+ (if (string-match-p "\\`/" ignore)
+ (concat pkg-dir ignore)
+ (concat "*/" ignore))))
+ (plist-get pkg-spec :ignored-files)
+ "\\|")
+ regexp-unmatchable))
+ (deps '()))
(dolist (file (directory-files pkg-dir t "\\.el\\'" t))
- (with-temp-buffer
- (insert-file-contents file)
- (when-let* ((require-lines (lm-header-multiline "package-requires")))
- (thread-last
- (mapconcat #'identity require-lines " ")
- package-read-from-string
- package--prepare-dependencies
- (nconc deps)
- (setq deps)))))
+ (unless (string-match-p ignored-files file)
+ (with-temp-buffer
+ (insert-file-contents file)
+ (when-let* ((require-lines (lm-header-multiline "package-requires")))
+ (thread-last
+ (mapconcat #'identity require-lines " ")
+ package-read-from-string
+ lm--prepare-package-dependencies
+ (nconc deps)
+ (setq deps))))))
(dolist (dep deps)
(cl-callf version-to-list (cadr dep)))
(setf missing (package-vc-install-dependencies (delete-dups deps)))
@@ -498,8 +538,7 @@ documentation and marking the package as installed."
missing)))
(let ((default-directory (file-name-as-directory pkg-dir))
- (pkg-file (expand-file-name (package--description-file pkg-dir) pkg-dir))
- (pkg-spec (package-vc--desc->spec pkg-desc)))
+ (pkg-file (expand-file-name (package--description-file pkg-dir) pkg-dir)))
;; Generate autoloads
(let* ((name (package-desc-name pkg-desc))
(auto-name (format "%s-autoloads.el" name))
@@ -523,9 +562,9 @@ documentation and marking the package as installed."
(package-vc--generate-description-file pkg-desc pkg-file)
;; Process :make and :shell-command arguments before building documentation
- (when (or (eq package-vc-allow-side-effects t)
+ (when (or (eq package-vc-allow-build-commands t)
(memq (package-desc-name pkg-desc)
- package-vc-allow-side-effects))
+ package-vc-allow-build-commands))
(package-vc--make pkg-spec pkg-desc))
;; Detect a manual
@@ -533,6 +572,11 @@ documentation and marking the package as installed."
(dolist (doc-file (ensure-list (plist-get pkg-spec :doc)))
(package-vc--build-documentation pkg-desc doc-file))))
+ ;; Remove any previous instance of PKG-DESC from `package-alist'
+ (let ((pkgs (assq (package-desc-name pkg-desc) package-alist)))
+ (when pkgs
+ (setf (cdr pkgs) (seq-remove #'package-vc-p (cdr pkgs)))))
+
;; Update package-alist.
(let ((new-desc (package-load-descriptor pkg-dir)))
;; Activation has to be done before compilation, so that if we're
@@ -718,7 +762,10 @@ installed package."
;;;###autoload
(defun package-vc-upgrade-all ()
- "Attempt to upgrade all installed VC packages."
+ "Upgrade all installed VC packages.
+
+This may fail if the local VCS state of one of the packages
+conflicts with its remote repository state."
(interactive)
(dolist (package package-alist)
(dolist (pkg-desc (cdr package))
@@ -728,7 +775,10 @@ installed package."
;;;###autoload
(defun package-vc-upgrade (pkg-desc)
- "Attempt to upgrade the package PKG-DESC."
+ "Upgrade the package described by PKG-DESC from package's VC repository.
+
+This may fail if the local VCS state of the package conflicts
+with the remote repository state."
(interactive (list (package-vc--read-package-desc "Upgrade VC package: " t)))
;; HACK: To run `package-vc--unpack-1' after checking out the new
;; revision, we insert a hook into `vc-post-command-functions', and
@@ -791,34 +841,45 @@ If no such revision can be found, return nil."
;;;###autoload
(defun package-vc-install (package &optional rev backend name)
- "Fetch a PACKAGE and set it up for using with Emacs.
-
-If PACKAGE is a string containing an URL, download the package
-from the repository at that URL; the function will try to guess
-the name of the package from the URL. This can be overridden by
-passing the optional argument NAME. If PACKAGE is a cons-cell,
-it should have the form (NAME . SPEC), where NAME is a symbol
-indicating the package name and SPEC is a plist as described in
-`package-vc-selected-packages'. Otherwise PACKAGE should be a
-symbol whose name is the package name, and the URL for the
-package will be taken from the package's metadata.
+ "Fetch a package described by PACKAGE and set it up for use with Emacs.
+
+PACKAGE specifies which package to install, where to find its
+source repository and how to build it.
+
+If PACKAGE is a symbol, install the package with that name
+according to metadata that package archives provide for it. This
+is the simplest way to call this function, but it only works if
+the package you want to install is listed in a package archive
+you have configured.
+
+If PACKAGE is a string, it specifies the URL of the package
+repository. In this case, optional argument BACKEND specifies
+the VC backend to use for cloning the repository; if it's nil,
+this function tries to infer which backend to use according to
+the value of `package-vc-heuristic-alist' and if that fails it
+uses `package-vc-default-backend'. Optional argument NAME
+specifies the package name in this case; if it's nil, this
+package uses `file-name-base' on the URL to obtain the package
+name, otherwise NAME is the package name as a symbol.
+
+PACKAGE can also be a cons cell (PNAME . SPEC) where PNAME is the
+package name as a symbol, and SPEC is a plist that specifies how
+to fetch and build the package. For possible values, see the
+subsection \"Specifying Package Sources\" in the Info
+node `(emacs)Fetching Package Sources'.
By default, this function installs the last revision of the
package available from its repository. If REV is a string, it
-describes the revision to install, as interpreted by the VC
-backend. The special value `:last-release' (interactively, the
-prefix argument), will use the commit of the latest release, if
-it exists. The last release is the latest revision which changed
-the \"Version:\" header of the package's main Lisp file.
-
-Optional argument BACKEND specifies the VC backend to use for cloning
-the package's repository; this is only possible if NAME-OR-URL is a URL,
-a string. If BACKEND is omitted or nil, the function
-uses `package-vc-heuristic-alist' to guess the backend.
-Note that by default, a VC package will be prioritized over a
-regular package, but it will not remove a VC package.
-
-\(fn PACKAGE &optional REV BACKEND)"
+describes the revision to install, as interpreted by the relevant
+VC backend. The special value `:last-release' (interactively,
+the prefix argument), says to use the commit of the latest
+release, if it exists. The last release is the latest revision
+which changed the \"Version:\" header of the package's main Lisp
+file.
+
+If you use this function to install a package that you also have
+installed from a package archive, the version this function
+installs takes precedence."
(interactive
(progn
;; Initialize the package system to get the list of package
@@ -893,18 +954,19 @@ for the last released version of the package."
(find-file directory)))
;;;###autoload
-(defun package-vc-install-from-checkout (dir name)
- "Set up the package NAME in DIR by linking it into the ELPA directory.
+(defun package-vc-install-from-checkout (dir &optional name)
+ "Install the package NAME from its source directory DIR.
+NAME defaults to the base name of DIR.
Interactively, prompt the user for DIR, which should be a directory
under version control, typically one created by `package-vc-checkout'.
If invoked interactively with a prefix argument, prompt the user
-for the NAME of the package to set up. Otherwise infer the package
-name from the base name of DIR."
- (interactive (let ((dir (read-directory-name "Directory: ")))
- (list dir
- (if current-prefix-arg
- (read-string "Package name: ")
- (file-name-base (directory-file-name dir))))))
+for the NAME of the package to set up."
+ (interactive (let* ((dir (read-directory-name "Directory: "))
+ (base (file-name-base (directory-file-name dir))))
+ (list dir (and current-prefix-arg
+ (read-string
+ (format-prompt "Package name" base)
+ nil nil base)))))
(unless (vc-responsible-backend dir)
(user-error "Directory %S is not under version control" dir))
(package-vc--archives-initialize)
@@ -936,13 +998,17 @@ prompt for the name of the package to rebuild."
;;;###autoload
(defun package-vc-prepare-patch (pkg-desc subject revisions)
- "Send patch for REVISIONS to maintainer of the package PKG using SUBJECT.
-The function uses `vc-prepare-patch', passing SUBJECT and
-REVISIONS directly. PKG-DESC must be a package description.
+ "Email patches for REVISIONS to maintainer of package PKG-DESC using SUBJECT.
+
+PKG-DESC is a package descriptor and SUBJECT is the subject of
+the message.
+
Interactively, prompt for PKG-DESC, SUBJECT, and REVISIONS. When
invoked with a numerical prefix argument, use the last N
revisions. When invoked interactively in a Log View buffer with
-marked revisions, use those."
+marked revisions, use those.
+
+See also `vc-prepare-patch'."
(interactive
(list (package-vc--read-package-desc "Package to prepare a patch for: " t)
(and (not vc-prepare-patches-separately)
diff --git a/lisp/emacs-lisp/package-x.el b/lisp/emacs-lisp/package-x.el
index 6c4e2a578b2..ca1b8532fa4 100644
--- a/lisp/emacs-lisp/package-x.el
+++ b/lisp/emacs-lisp/package-x.el
@@ -1,6 +1,6 @@
;;; package-x.el --- Package extras -*- lexical-binding: t; -*-
-;; Copyright (C) 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2024 Free Software Foundation, Inc.
;; Author: Tom Tromey <tromey@redhat.com>
;; Created: 10 Mar 2007
diff --git a/lisp/emacs-lisp/package.el b/lisp/emacs-lisp/package.el
index a7ace5553ad..80f746d7429 100644
--- a/lisp/emacs-lisp/package.el
+++ b/lisp/emacs-lisp/package.el
@@ -1,6 +1,6 @@
;;; package.el --- Simple package system for Emacs -*- lexical-binding:t -*-
-;; Copyright (C) 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2024 Free Software Foundation, Inc.
;; Author: Tom Tromey <tromey@redhat.com>
;; Daniel Hackney <dan@haxney.org>
@@ -1150,27 +1150,8 @@ Signal an error if the entire string was not used."
(error "Can't read whole string"))
(end-of-file expr))))
-(defun package--prepare-dependencies (deps)
- "Turn DEPS into an acceptable list of dependencies.
-
-Any parts missing a version string get a default version string
-of \"0\" (meaning any version) and an appropriate level of lists
-is wrapped around any parts requiring it."
- (cond
- ((not (listp deps))
- (error "Invalid requirement specifier: %S" deps))
- (t (mapcar (lambda (dep)
- (cond
- ((symbolp dep) `(,dep "0"))
- ((stringp dep)
- (error "Invalid requirement specifier: %S" dep))
- ((and (listp dep) (null (cdr dep)))
- (list (car dep) "0"))
- (t dep)))
- deps))))
-
(declare-function lm-header "lisp-mnt" (header))
-(declare-function lm-header-multiline "lisp-mnt" (header))
+(declare-function lm-package-requires "lisp-mnt" (&optional file))
(declare-function lm-website "lisp-mnt" (&optional file))
(declare-function lm-keywords-list "lisp-mnt" (&optional file))
(declare-function lm-maintainers "lisp-mnt" (&optional file))
@@ -1193,8 +1174,14 @@ boundaries."
;; 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)
- (lwarn '(package package-format) :warning
- "Package lacks a terminating comment"))
+ ;; 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"))))
;; Try to include a trailing newline.
(forward-line)
(narrow-to-region start (point))
@@ -1213,9 +1200,7 @@ boundaries."
(error "Package lacks a \"Version\" or \"Package-Version\" header")))
(package-desc-from-define
file-name pkg-version desc
- (and-let* ((require-lines (lm-header-multiline "package-requires")))
- (package--prepare-dependencies
- (package-read-from-string (mapconcat #'identity require-lines " "))))
+ (lm-package-requires)
:kind 'single
:url website
:keywords keywords
@@ -1721,18 +1706,26 @@ The variable `package-load-list' controls which packages to load."
package-quickstart-file))))
;; The quickstart file presumes that it has a blank slate,
;; so don't use it if we already activated some packages.
- (if (and qs (not (bound-and-true-p package-activated-list)))
- ;; Skip load-source-file-function which would slow us down by a factor
- ;; 2 when loading the .el file (this assumes we were careful to
- ;; save this file so it doesn't need any decoding).
- (let ((load-source-file-function nil))
- (unless (boundp 'package-activated-list)
- (setq package-activated-list nil))
- (load qs nil 'nomessage))
- (require 'package)
- (package--activate-all)))))
+ (or (and qs (not (bound-and-true-p package-activated-list))
+ ;; Skip `load-source-file-function' which would slow us down by
+ ;; a factor 2 when loading the .el file (this assumes we were
+ ;; careful to save this file so it doesn't need any decoding).
+ (with-demoted-errors "Error during quickstart: %S"
+ (let ((load-source-file-function nil))
+ (unless (boundp 'package-activated-list)
+ (setq package-activated-list nil))
+ (load qs nil 'nomessage)
+ t)))
+ (progn
+ (require 'package)
+ ;; Silence the "unknown function" warning when this is compiled
+ ;; inside `loaddefs.el'.
+ ;; FIXME: We use `with-no-warnings' because the effect of
+ ;; `declare-function' is currently not scoped, so if we use
+ ;; it here, we end up with a redefinition warning instead :-)
+ (with-no-warnings
+ (package--activate-all)))))))
-;;;###autoload
(defun package--activate-all ()
(dolist (elt (package--alist))
(condition-case err
@@ -1983,8 +1976,11 @@ Used to populate `package-selected-packages'."
(defun package--save-selected-packages (&optional value)
"Set and save `package-selected-packages' to VALUE."
- (when value
- (setq package-selected-packages value))
+ (when (or value after-init-time)
+ ;; It is valid to set it to nil, for example when the last package
+ ;; is uninstalled. But it shouldn't be done at init time, to
+ ;; avoid overwriting configurations that haven't yet been loaded.
+ (setq package-selected-packages (sort value #'string<)))
(if after-init-time
(customize-save-variable 'package-selected-packages package-selected-packages)
(add-hook 'after-init-hook #'package--save-selected-packages)))
@@ -2485,7 +2481,9 @@ Clean-up the corresponding .eln files if Emacs is native
compiled."
(when (featurep 'native-compile)
(cl-loop
- for file in (directory-files-recursively dir "\\.el\\'")
+ for file in (directory-files-recursively dir
+ ;; Exclude lockfiles
+ (rx bos (or (and "." (not "#")) (not ".")) (* nonl) ".el" eos))
do (comp-clean-up-stale-eln (comp-el-to-eln-filename file))))
(if (file-symlink-p (directory-file-name dir))
(delete-file (directory-file-name dir))
@@ -2517,8 +2515,12 @@ If NOSAVE is non-nil, the package is not removed from
nil t)))
(list (cdr (assoc package-name package-table))
current-prefix-arg nil))))
- (let ((dir (package-desc-dir pkg-desc))
- (name (package-desc-name pkg-desc))
+ (let* ((dir (package-desc-dir pkg-desc))
+ (name (package-desc-name pkg-desc))
+ (new-package-alist (let ((pkgs (assq name package-alist)))
+ (if (null (remove pkg-desc (cdr pkgs)))
+ (remq pkgs package-alist)
+ package-alist)))
pkg-used-elsewhere-by)
;; If the user is trying to delete this package, they definitely
;; don't want it marked as selected, so we remove it from
@@ -2537,7 +2539,8 @@ If NOSAVE is non-nil, the package is not removed from
(package-desc-full-name pkg-desc)))
((and (null force)
(setq pkg-used-elsewhere-by
- (package--used-elsewhere-p pkg-desc)))
+ (let ((package-alist new-package-alist))
+ (package--used-elsewhere-p pkg-desc)))) ;See bug#65475
;; Don't delete packages used as dependency elsewhere.
(error "Package `%s' is used by `%s' as dependency, not deleting"
(package-desc-full-name pkg-desc)
@@ -2558,10 +2561,7 @@ If NOSAVE is non-nil, the package is not removed from
(when (file-exists-p file)
(delete-file file))))
;; Update package-alist.
- (let ((pkgs (assq name package-alist)))
- (delete pkg-desc pkgs)
- (unless (cdr pkgs)
- (setq package-alist (delq pkgs package-alist))))
+ (setq package-alist new-package-alist)
(package--quickstart-maybe-refresh)
(message "Package `%s' deleted."
(package-desc-full-name pkg-desc))))))
@@ -2806,7 +2806,7 @@ Helper function for `describe-package'."
(incompatible-reason (package--incompatible-p desc))
(signed (if desc (package-desc-signed desc)))
(maintainers (or (cdr (assoc :maintainers extras))
- (cdr (assoc :maintainer extras))))
+ (list (cdr (assoc :maintainer extras)))))
(authors (cdr (assoc :authors extras)))
(news (and-let* (pkg-dir
((not built-in))
@@ -4606,8 +4606,8 @@ activations need to be changed, such as when `package-load-list' is modified."
(let ((load-suffixes '(".el" ".elc")))
(locate-library (package--autoloads-file-name pkg))))
(pfile (prin1-to-string file)))
- (insert "(let ((load-true-file-name " pfile ")\
-\(load-file-name " pfile "))\n")
+ (insert "(let* ((load-file-name " pfile ")\
+\(load-true-file-name load-file-name))\n")
(insert-file-contents file)
;; Fixup the special #$ reader form and throw away comments.
(while (re-search-forward "#\\$\\|^;\\(.*\n\\)" nil 'move)
diff --git a/lisp/emacs-lisp/pcase.el b/lisp/emacs-lisp/pcase.el
index 1c5ce5169ab..5ac4b289a80 100644
--- a/lisp/emacs-lisp/pcase.el
+++ b/lisp/emacs-lisp/pcase.el
@@ -1,6 +1,6 @@
;;; pcase.el --- ML-style pattern-matching macro for Elisp -*- lexical-binding: t -*-
-;; Copyright (C) 2010-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2010-2024 Free Software Foundation, Inc.
;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
;; Keywords: extensions
@@ -609,6 +609,16 @@ recording whether the var has been referenced by earlier parts of the match."
(symbolp . byte-code-function-p)
(symbolp . compiled-function-p)
(symbolp . recordp)
+ (null . integerp)
+ (null . numberp)
+ (null . numberp)
+ (null . consp)
+ (null . arrayp)
+ (null . vectorp)
+ (null . stringp)
+ (null . byte-code-function-p)
+ (null . compiled-function-p)
+ (null . recordp)
(integerp . consp)
(integerp . arrayp)
(integerp . vectorp)
diff --git a/lisp/emacs-lisp/pp.el b/lisp/emacs-lisp/pp.el
index 95ad222cc4d..1d722051406 100644
--- a/lisp/emacs-lisp/pp.el
+++ b/lisp/emacs-lisp/pp.el
@@ -1,6 +1,6 @@
;;; pp.el --- pretty printer for Emacs Lisp -*- lexical-binding: t -*-
-;; Copyright (C) 1989, 1993, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1989, 1993, 2001-2024 Free Software Foundation, Inc.
;; Author: Randal Schwartz <merlyn@stonehenge.com>
;; Keywords: lisp
@@ -25,7 +25,6 @@
;;; Code:
(require 'cl-lib)
-(defvar font-lock-verbose)
(defgroup pp nil
"Pretty printer for Emacs Lisp."
@@ -263,7 +262,7 @@ Non-interactively can also be called with a single argument, in which
case that argument will be inserted pretty-printed at point."
(interactive "r")
(if (null end) (pp--object beg #'pp-29)
- (save-restriction beg end
+ (with-restriction beg end
(goto-char (point-min))
(while (not (eobp))
(cond
diff --git a/lisp/emacs-lisp/radix-tree.el b/lisp/emacs-lisp/radix-tree.el
index 9b80b6c4614..7c4354fdc48 100644
--- a/lisp/emacs-lisp/radix-tree.el
+++ b/lisp/emacs-lisp/radix-tree.el
@@ -1,6 +1,6 @@
;;; radix-tree.el --- A simple library of radix trees -*- lexical-binding: t; -*-
-;; Copyright (C) 2016-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2016-2024 Free Software Foundation, Inc.
;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
;; Keywords:
diff --git a/lisp/emacs-lisp/range.el b/lisp/emacs-lisp/range.el
index f441c240a27..19a6da34acb 100644
--- a/lisp/emacs-lisp/range.el
+++ b/lisp/emacs-lisp/range.el
@@ -1,6 +1,6 @@
;;; ranges.el --- range functions -*- lexical-binding: t; -*-
-;; Copyright (C) 1996-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-2024 Free Software Foundation, Inc.
;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
diff --git a/lisp/emacs-lisp/re-builder.el b/lisp/emacs-lisp/re-builder.el
index 0b2b9cde795..0a47cca0231 100644
--- a/lisp/emacs-lisp/re-builder.el
+++ b/lisp/emacs-lisp/re-builder.el
@@ -1,6 +1,6 @@
;;; re-builder.el --- building Regexps with visual feedback -*- lexical-binding: t -*-
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
;; Author: Detlev Zundel <dzu@gnu.org>
;; Keywords: matching, lisp, tools
diff --git a/lisp/emacs-lisp/regexp-opt.el b/lisp/emacs-lisp/regexp-opt.el
index 39325a3c35e..59c1b7d8e10 100644
--- a/lisp/emacs-lisp/regexp-opt.el
+++ b/lisp/emacs-lisp/regexp-opt.el
@@ -1,6 +1,6 @@
;;; regexp-opt.el --- generate efficient regexps to match strings -*- lexical-binding: t -*-
-;; Copyright (C) 1994-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1994-2024 Free Software Foundation, Inc.
;; Author: Simon Marshall <simon@gnu.org>
;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/emacs-lisp/regi.el b/lisp/emacs-lisp/regi.el
index cac617c9637..8c87edcb6db 100644
--- a/lisp/emacs-lisp/regi.el
+++ b/lisp/emacs-lisp/regi.el
@@ -1,6 +1,6 @@
;;; regi.el --- REGular expression Interpreting engine -*- lexical-binding: t; -*-
-;; Copyright (C) 1993, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1993, 2001-2024 Free Software Foundation, Inc.
;; Author: 1993 Barry A. Warsaw, Century Computing, Inc. <bwarsaw@cen.com>
;; Created: 24-Feb-1993
diff --git a/lisp/emacs-lisp/ring.el b/lisp/emacs-lisp/ring.el
index d0d96721121..efd9316b2ef 100644
--- a/lisp/emacs-lisp/ring.el
+++ b/lisp/emacs-lisp/ring.el
@@ -1,6 +1,6 @@
;;; ring.el --- handle rings of items -*- lexical-binding: t; -*-
-;; Copyright (C) 1992, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1992, 2001-2024 Free Software Foundation, Inc.
;; Maintainer: emacs-devel@gnu.org
;; Keywords: extensions
diff --git a/lisp/emacs-lisp/rmc.el b/lisp/emacs-lisp/rmc.el
index bfd7434be9a..378687c0326 100644
--- a/lisp/emacs-lisp/rmc.el
+++ b/lisp/emacs-lisp/rmc.el
@@ -1,6 +1,6 @@
;;; rmc.el --- read from a multiple choice question -*- lexical-binding: t -*-
-;; Copyright (C) 2016-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2016-2024 Free Software Foundation, Inc.
;; Maintainer: emacs-devel@gnu.org
@@ -126,7 +126,8 @@
(defun read-multiple-choice (prompt choices &optional help-string show-help
long-form)
"Ask user to select an entry from CHOICES, prompting with PROMPT.
-This function allows to ask the user a multiple-choice question.
+This function is used to ask the user a question with multiple
+choices.
CHOICES should be a list of the form (KEY NAME [DESCRIPTION]).
KEY is a character the user should type to select the entry.
diff --git a/lisp/emacs-lisp/rx.el b/lisp/emacs-lisp/rx.el
index afc9826eefa..246e41cff0b 100644
--- a/lisp/emacs-lisp/rx.el
+++ b/lisp/emacs-lisp/rx.el
@@ -1,6 +1,6 @@
;;; rx.el --- S-exp notation for regexps --*- lexical-binding: t -*-
-;; Copyright (C) 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/lisp/emacs-lisp/seq.el b/lisp/emacs-lisp/seq.el
index 6917c541f2e..4c6553972c2 100644
--- a/lisp/emacs-lisp/seq.el
+++ b/lisp/emacs-lisp/seq.el
@@ -1,10 +1,10 @@
;;; seq.el --- Sequence manipulation functions -*- lexical-binding: t -*-
-;; Copyright (C) 2014-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2014-2024 Free Software Foundation, Inc.
;; Author: Nicolas Petton <nicolas@petton.fr>
;; Keywords: sequences
-;; Version: 2.23
+;; Version: 2.24
;; Package: seq
;; Maintainer: emacs-devel@gnu.org
@@ -38,9 +38,6 @@
;; the sequence as their second argument. All other functions take
;; the sequence as their first argument.
;;
-;; While seq.el version 1.8 is in GNU ELPA for convenience, seq.el
-;; version 2.0 requires Emacs>=25.1.
-;;
;; seq.el can be extended to support new type of sequences. Here are
;; the generic functions that must be implemented by new seq types:
;; - `seq-elt'
@@ -51,11 +48,17 @@
;; - `seq-into-sequence'
;; - `seq-copy'
;; - `seq-into'
-;;
-;; All functions are tested in test/lisp/emacs-lisp/seq-tests.el
;;; Code:
+;; Note regarding the `seq' package on GNU ELPA:
+;;
+;; It was decided not to bother upgrading seq beyond 2.24 on GNU ELPA.
+;; The main purpose of the GNU ELPA package was to encourage adoption
+;; and accommodate changes more easily, but it's mature enough that
+;; changes are fairly slow. Thus, we can now rely on "the usual"
+;; solutions to deal with compatibility issues. (Bug#60990)
+
(eval-when-compile (require 'cl-generic))
;; We used to use some sequence functions from cl-lib, but this
diff --git a/lisp/emacs-lisp/shadow.el b/lisp/emacs-lisp/shadow.el
index 12c3ffde2c1..e1aa9da14ba 100644
--- a/lisp/emacs-lisp/shadow.el
+++ b/lisp/emacs-lisp/shadow.el
@@ -1,6 +1,6 @@
;;; shadow.el --- locate Emacs Lisp file shadowings -*- lexical-binding: t; -*-
-;; Copyright (C) 1995, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1995, 2001-2024 Free Software Foundation, Inc.
;; Author: Terry Jones <terry@santafe.edu>
;; Keywords: lisp
diff --git a/lisp/emacs-lisp/shortdoc.el b/lisp/emacs-lisp/shortdoc.el
index dbc061d8a70..17cbf6b2d31 100644
--- a/lisp/emacs-lisp/shortdoc.el
+++ b/lisp/emacs-lisp/shortdoc.el
@@ -1,6 +1,6 @@
;;; shortdoc.el --- Short function summaries -*- lexical-binding: t -*-
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
;; Keywords: lisp, help
;; Package: emacs
@@ -1388,7 +1388,7 @@ A FUNC form can have any number of `:no-eval' (or `:no-value'),
(set-text-properties
:no-eval (set-text-properties (point) (1+ (point)) '(face error)))
(add-face-text-property
- (add-face-text-property START END '(:foreground "green")))
+ :no-eval (add-face-text-property START END '(:foreground "green")))
(propertize
:eval (propertize "foo" 'face 'italic 'mouse-face 'bold-italic))
"Searching for Text Properties"
diff --git a/lisp/emacs-lisp/shorthands.el b/lisp/emacs-lisp/shorthands.el
index bb18ac33497..6348aaccf93 100644
--- a/lisp/emacs-lisp/shorthands.el
+++ b/lisp/emacs-lisp/shorthands.el
@@ -1,9 +1,10 @@
;;; shorthands.el --- Read code considering Elisp shorthands -*- lexical-binding: t; -*-
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
;; Author: João Távora <joaotavora@gmail.com>
;; Keywords: lisp
+;; Package: emacs
;; This file is part of GNU Emacs.
@@ -52,11 +53,16 @@
:group 'font-lock-faces)
(defun shorthands--mismatch-from-end (str1 str2)
+ "Tell index of first mismatch in STR1 and STR2, from end.
+The index is a valid 0-based index on STR1. Returns nil if STR1
+equals STR2. Return 0 if STR1 is a suffix of STR2."
(cl-loop with l1 = (length str1) with l2 = (length str2)
for i from 1
for i1 = (- l1 i) for i2 = (- l2 i)
- while (and (>= i1 0) (>= i2 0) (eq (aref str1 i1) (aref str2 i2)))
- finally (return (1- i))))
+ while (eq (aref str1 i1) (aref str2 i2))
+ if (zerop i2) return (if (zerop i1) nil i1)
+ if (zerop i1) return 0
+ finally (return i1)))
(defun shorthands-font-lock-shorthands (limit)
(when read-symbol-shorthands
@@ -68,10 +74,16 @@
font-lock-string-face)))
(intern-soft (match-string 1))))
(sname (and probe (symbol-name probe)))
- (mm (and sname (shorthands--mismatch-from-end
- (match-string 1) sname))))
- (unless (or (null mm) (= mm (length sname)))
- (add-face-text-property (match-beginning 1) (1+ (- (match-end 1) mm))
+ (mismatch (and sname (shorthands--mismatch-from-end
+ (match-string 1) sname)))
+ (guess (and mismatch (1+ mismatch))))
+ (when guess
+ (when (and (< guess (1- (length (match-string 1))))
+ ;; In bug#67390 we allow other separators
+ (eq (char-syntax (aref (match-string 1) guess)) ?_))
+ (setq guess (1+ guess)))
+ (add-face-text-property (match-beginning 1)
+ (+ (match-beginning 1) guess)
'elisp-shorthand-font-lock-face))))))
(font-lock-add-keywords 'emacs-lisp-mode '((shorthands-font-lock-shorthands)) t)
diff --git a/lisp/emacs-lisp/smie.el b/lisp/emacs-lisp/smie.el
index 19a0c22027a..c5eea4b3427 100644
--- a/lisp/emacs-lisp/smie.el
+++ b/lisp/emacs-lisp/smie.el
@@ -1,6 +1,6 @@
;;; smie.el --- Simple Minded Indentation Engine -*- lexical-binding: t -*-
-;; Copyright (C) 2010-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2010-2024 Free Software Foundation, Inc.
;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
;; Keywords: languages, lisp, internal, parsing, indentation
@@ -56,8 +56,8 @@
;; which includes a kind of tutorial to get started with SMIE:
;;
;; SMIE: Weakness is Power! Auto-indentation with incomplete information
-;; Stefan Monnier, <Programming> Journal 2020, volume 5, issue 1.
-;; doi: 10.22152/programming-journal.org/2021/5/1
+;; Stefan Monnier, <Programming> Journal 2021, volume 5, issue 1.
+;; doi: https://doi.org/10.22152/programming-journal.org/2021/5/1
;; A good background to understand the development (especially the parts
;; building the 2D precedence tables and then computing the precedence levels
diff --git a/lisp/emacs-lisp/subr-x.el b/lisp/emacs-lisp/subr-x.el
index 572822351b1..699be767ee7 100644
--- a/lisp/emacs-lisp/subr-x.el
+++ b/lisp/emacs-lisp/subr-x.el
@@ -1,6 +1,6 @@
;;; subr-x.el --- extra Lisp functions -*- lexical-binding:t -*-
-;; Copyright (C) 2013-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2024 Free Software Foundation, Inc.
;; Maintainer: emacs-devel@gnu.org
;; Keywords: convenience
@@ -341,10 +341,9 @@ This construct can only be used with lexical binding."
;; Keeping a work buffer around is more efficient than creating a
;; new temporary buffer.
(with-current-buffer (get-buffer-create " *string-pixel-width*")
- ;; If `display-line-numbers-mode' is enabled in internal
- ;; buffers, it breaks width calculation, so disable it (bug#59311)
- (when (bound-and-true-p display-line-numbers-mode)
- (display-line-numbers-mode -1))
+ ;; If `display-line-numbers' is enabled in internal buffers
+ ;; (e.g. globally), it breaks width calculation (bug#59311)
+ (setq-local display-line-numbers nil)
(delete-region (point-min) (point-max))
;; Disable line-prefix and wrap-prefix, for the same reason.
(setq line-prefix nil
diff --git a/lisp/emacs-lisp/syntax.el b/lisp/emacs-lisp/syntax.el
index d8f6c58f6ca..e8eb8598fd0 100644
--- a/lisp/emacs-lisp/syntax.el
+++ b/lisp/emacs-lisp/syntax.el
@@ -1,6 +1,6 @@
;;; syntax.el --- helper functions to find syntactic context -*- lexical-binding: t -*-
-;; Copyright (C) 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2000-2024 Free Software Foundation, Inc.
;; Maintainer: emacs-devel@gnu.org
;; Keywords: internal
@@ -617,150 +617,150 @@ running the hook."
(syntax-propertize pos)
;;
(with-syntax-table (or syntax-ppss-table (syntax-table))
- (let* ((cell (syntax-ppss--data))
- (ppss-last (car cell))
- (ppss-cache (cdr cell))
- (old-ppss (cdr ppss-last))
- (old-pos (car ppss-last))
- (ppss nil)
- (pt-min (point-min)))
- (if (and old-pos (> old-pos pos)) (setq old-pos nil))
- ;; Use the OLD-POS if usable and close. Don't update the `last' cache.
- (condition-case nil
- (if (and old-pos (< (- pos old-pos)
- ;; The time to use syntax-begin-function and
- ;; find PPSS is assumed to be about 2 * distance.
- (let ((pair (aref syntax-ppss-stats 5)))
- (/ (* 2 (cdr pair)) (car pair)))))
- (progn
- (syntax-ppss--update-stats 0 old-pos pos)
- (parse-partial-sexp old-pos pos nil nil old-ppss))
-
- (cond
- ;; Use OLD-PPSS if possible and close enough.
- ((and (not old-pos) old-ppss
- ;; If `pt-min' is too far from `pos', we could try to use
- ;; other positions in (nth 9 old-ppss), but that doesn't
- ;; seem to happen in practice and it would complicate this
- ;; code (and the before-change-function code even more).
- ;; But maybe it would be useful in "degenerate" cases such
- ;; as when the whole file is wrapped in a set
- ;; of parentheses.
- (setq pt-min (or (syntax-ppss-toplevel-pos old-ppss)
- (nth 2 old-ppss)))
- (<= pt-min pos) (< (- pos pt-min) syntax-ppss-max-span))
- (syntax-ppss--update-stats 1 pt-min pos)
- (setq ppss (parse-partial-sexp pt-min pos)))
- ;; The OLD-* data can't be used. Consult the cache.
- (t
- (let ((cache-pred nil)
- (cache ppss-cache)
- (pt-min (point-min))
- ;; I differentiate between PT-MIN and PT-BEST because
- ;; I feel like it might be important to ensure that the
- ;; cache is only filled with 100% sure data (whereas
- ;; syntax-begin-function might return incorrect data).
- ;; Maybe that's just stupid.
- (pt-best (point-min))
- (ppss-best nil))
- ;; look for a usable cache entry.
- (while (and cache (< pos (caar cache)))
- (setq cache-pred cache)
- (setq cache (cdr cache)))
- (if cache (setq pt-min (caar cache) ppss (cdar cache)))
-
- ;; Setup the before-change function if necessary.
- (unless (or ppss-cache ppss-last)
- ;; Note: combine-change-calls-1 needs to be kept in sync
- ;; with this!
- (add-hook 'before-change-functions
- #'syntax-ppss-flush-cache
- ;; We should be either the very last function on
- ;; before-change-functions or the very first on
- ;; after-change-functions.
- 99 t))
-
- ;; Use the best of OLD-POS and CACHE.
- (if (or (not old-pos) (< old-pos pt-min))
- (setq pt-best pt-min ppss-best ppss)
- (syntax-ppss--update-stats 4 old-pos pos)
- (setq pt-best old-pos ppss-best old-ppss))
-
- ;; Use the `syntax-begin-function' if available.
- ;; We could try using that function earlier, but:
- ;; - The result might not be 100% reliable, so it's better to use
- ;; the cache if available.
- ;; - The function might be slow.
- ;; - If this function almost always finds a safe nearby spot,
- ;; the cache won't be populated, so consulting it is cheap.
- (when (and syntax-begin-function
- (progn (goto-char pos)
- (funcall syntax-begin-function)
- ;; Make sure it's better.
- (> (point) pt-best))
- ;; Simple sanity checks.
- (< (point) pos) ; backward-paragraph can fail here.
- (not (memq (get-text-property (point) 'face)
- '(font-lock-string-face font-lock-doc-face
- font-lock-comment-face))))
- (syntax-ppss--update-stats 5 (point) pos)
- (setq pt-best (point) ppss-best nil))
-
- (cond
- ;; Quick case when we found a nearby pos.
- ((< (- pos pt-best) syntax-ppss-max-span)
- (syntax-ppss--update-stats 2 pt-best pos)
- (setq ppss (parse-partial-sexp pt-best pos nil nil ppss-best)))
- ;; Slow case: compute the state from some known position and
- ;; populate the cache so we won't need to do it again soon.
- (t
- (syntax-ppss--update-stats 3 pt-min pos)
- (setq syntax-ppss--updated-cache t)
-
- ;; If `pt-min' is too far, add a few intermediate entries.
- (while (> (- pos pt-min) (* 2 syntax-ppss-max-span))
- (setq ppss (parse-partial-sexp
- pt-min (setq pt-min (/ (+ pt-min pos) 2))
- nil nil ppss))
- (push (cons pt-min ppss)
- (if cache-pred (cdr cache-pred) ppss-cache)))
-
- ;; Compute the actual return value.
- (setq ppss (parse-partial-sexp pt-min pos nil nil ppss))
-
- ;; Debugging check.
- ;; (let ((real-ppss (parse-partial-sexp (point-min) pos)))
- ;; (setcar (last ppss 4) 0)
- ;; (setcar (last real-ppss 4) 0)
- ;; (setcar (last ppss 8) nil)
- ;; (setcar (last real-ppss 8) nil)
- ;; (unless (equal ppss real-ppss)
- ;; (message "!!Syntax: %s != %s" ppss real-ppss)
- ;; (setq ppss real-ppss)))
-
- ;; Store it in the cache.
- (let ((pair (cons pos ppss)))
- (if cache-pred
- (if (> (- (caar cache-pred) pos) syntax-ppss-max-span)
- (push pair (cdr cache-pred))
- (setcar cache-pred pair))
- (if (or (null ppss-cache)
- (> (- (caar ppss-cache) pos)
- syntax-ppss-max-span))
- (push pair ppss-cache)
- (setcar ppss-cache pair)))))))))
-
- (setq syntax-ppss--updated-cache t)
- (setq ppss-last (cons pos ppss))
- (setcar cell ppss-last)
- (setcdr cell ppss-cache)
- ppss)
- (args-out-of-range
- ;; If the buffer is more narrowed than when we built the cache,
- ;; we may end up calling parse-partial-sexp with a position before
- ;; point-min. In that case, just parse from point-min assuming
- ;; a nil state.
- (parse-partial-sexp (point-min) pos))))))
+ (let* ((cell (syntax-ppss--data))
+ (ppss-last (car cell))
+ (ppss-cache (cdr cell))
+ (old-ppss (cdr ppss-last))
+ (old-pos (car ppss-last))
+ (ppss nil)
+ (pt-min (point-min)))
+ (if (and old-pos (> old-pos pos)) (setq old-pos nil))
+ ;; Use the OLD-POS if usable and close. Don't update the `last' cache.
+ (condition-case nil
+ (if (and old-pos (< (- pos old-pos)
+ ;; The time to use syntax-begin-function and
+ ;; find PPSS is assumed to be about 2 * distance.
+ (let ((pair (aref syntax-ppss-stats 5)))
+ (/ (* 2 (cdr pair)) (car pair)))))
+ (progn
+ (syntax-ppss--update-stats 0 old-pos pos)
+ (parse-partial-sexp old-pos pos nil nil old-ppss))
+
+ (cond
+ ;; Use OLD-PPSS if possible and close enough.
+ ((and (not old-pos) old-ppss
+ ;; If `pt-min' is too far from `pos', we could try to use
+ ;; other positions in (nth 9 old-ppss), but that doesn't
+ ;; seem to happen in practice and it would complicate this
+ ;; code (and the before-change-function code even more).
+ ;; But maybe it would be useful in "degenerate" cases such
+ ;; as when the whole file is wrapped in a set
+ ;; of parentheses.
+ (setq pt-min (or (syntax-ppss-toplevel-pos old-ppss)
+ (nth 2 old-ppss)))
+ (<= pt-min pos) (< (- pos pt-min) syntax-ppss-max-span))
+ (syntax-ppss--update-stats 1 pt-min pos)
+ (setq ppss (parse-partial-sexp pt-min pos)))
+ ;; The OLD-* data can't be used. Consult the cache.
+ (t
+ (let ((cache-pred nil)
+ (cache ppss-cache)
+ (pt-min (point-min))
+ ;; I differentiate between PT-MIN and PT-BEST because
+ ;; I feel like it might be important to ensure that the
+ ;; cache is only filled with 100% sure data (whereas
+ ;; syntax-begin-function might return incorrect data).
+ ;; Maybe that's just stupid.
+ (pt-best (point-min))
+ (ppss-best nil))
+ ;; look for a usable cache entry.
+ (while (and cache (< pos (caar cache)))
+ (setq cache-pred cache)
+ (setq cache (cdr cache)))
+ (if cache (setq pt-min (caar cache) ppss (cdar cache)))
+
+ ;; Setup the before-change function if necessary.
+ (unless (or ppss-cache ppss-last)
+ ;; Note: combine-change-calls-1 needs to be kept in sync
+ ;; with this!
+ (add-hook 'before-change-functions
+ #'syntax-ppss-flush-cache
+ ;; We should be either the very last function on
+ ;; before-change-functions or the very first on
+ ;; after-change-functions.
+ 99 t))
+
+ ;; Use the best of OLD-POS and CACHE.
+ (if (or (not old-pos) (< old-pos pt-min))
+ (setq pt-best pt-min ppss-best ppss)
+ (syntax-ppss--update-stats 4 old-pos pos)
+ (setq pt-best old-pos ppss-best old-ppss))
+
+ ;; Use the `syntax-begin-function' if available.
+ ;; We could try using that function earlier, but:
+ ;; - The result might not be 100% reliable, so it's better to use
+ ;; the cache if available.
+ ;; - The function might be slow.
+ ;; - If this function almost always finds a safe nearby spot,
+ ;; the cache won't be populated, so consulting it is cheap.
+ (when (and syntax-begin-function
+ (progn (goto-char pos)
+ (funcall syntax-begin-function)
+ ;; Make sure it's better.
+ (> (point) pt-best))
+ ;; Simple sanity checks.
+ (< (point) pos) ; backward-paragraph can fail here.
+ (not (memq (get-text-property (point) 'face)
+ '(font-lock-string-face font-lock-doc-face
+ font-lock-comment-face))))
+ (syntax-ppss--update-stats 5 (point) pos)
+ (setq pt-best (point) ppss-best nil))
+
+ (cond
+ ;; Quick case when we found a nearby pos.
+ ((< (- pos pt-best) syntax-ppss-max-span)
+ (syntax-ppss--update-stats 2 pt-best pos)
+ (setq ppss (parse-partial-sexp pt-best pos nil nil ppss-best)))
+ ;; Slow case: compute the state from some known position and
+ ;; populate the cache so we won't need to do it again soon.
+ (t
+ (syntax-ppss--update-stats 3 pt-min pos)
+ (setq syntax-ppss--updated-cache t)
+
+ ;; If `pt-min' is too far, add a few intermediate entries.
+ (while (> (- pos pt-min) (* 2 syntax-ppss-max-span))
+ (setq ppss (parse-partial-sexp
+ pt-min (setq pt-min (/ (+ pt-min pos) 2))
+ nil nil ppss))
+ (push (cons pt-min ppss)
+ (if cache-pred (cdr cache-pred) ppss-cache)))
+
+ ;; Compute the actual return value.
+ (setq ppss (parse-partial-sexp pt-min pos nil nil ppss))
+
+ ;; Debugging check.
+ ;; (let ((real-ppss (parse-partial-sexp (point-min) pos)))
+ ;; (setcar (last ppss 4) 0)
+ ;; (setcar (last real-ppss 4) 0)
+ ;; (setcar (last ppss 8) nil)
+ ;; (setcar (last real-ppss 8) nil)
+ ;; (unless (equal ppss real-ppss)
+ ;; (message "!!Syntax: %s != %s" ppss real-ppss)
+ ;; (setq ppss real-ppss)))
+
+ ;; Store it in the cache.
+ (let ((pair (cons pos ppss)))
+ (if cache-pred
+ (if (> (- (caar cache-pred) pos) syntax-ppss-max-span)
+ (push pair (cdr cache-pred))
+ (setcar cache-pred pair))
+ (if (or (null ppss-cache)
+ (> (- (caar ppss-cache) pos)
+ syntax-ppss-max-span))
+ (push pair ppss-cache)
+ (setcar ppss-cache pair)))))))))
+
+ (setq syntax-ppss--updated-cache t)
+ (setq ppss-last (cons pos ppss))
+ (setcar cell ppss-last)
+ (setcdr cell ppss-cache)
+ ppss)
+ (args-out-of-range
+ ;; If the buffer is more narrowed than when we built the cache,
+ ;; we may end up calling parse-partial-sexp with a position before
+ ;; point-min. In that case, just parse from point-min assuming
+ ;; a nil state.
+ (parse-partial-sexp (point-min) pos))))))
;; Debugging functions
diff --git a/lisp/emacs-lisp/tabulated-list.el b/lisp/emacs-lisp/tabulated-list.el
index ddac6ed1746..9884a2fc24b 100644
--- a/lisp/emacs-lisp/tabulated-list.el
+++ b/lisp/emacs-lisp/tabulated-list.el
@@ -1,6 +1,6 @@
;;; tabulated-list.el --- generic major mode for tabulated lists -*- lexical-binding: t -*-
-;; Copyright (C) 2011-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2011-2024 Free Software Foundation, Inc.
;; Author: Chong Yidong <cyd@stupidchicken.com>
;; Keywords: extensions, lisp
diff --git a/lisp/emacs-lisp/tcover-ses.el b/lisp/emacs-lisp/tcover-ses.el
index 75df1ed0db8..4f66f7eade2 100644
--- a/lisp/emacs-lisp/tcover-ses.el
+++ b/lisp/emacs-lisp/tcover-ses.el
@@ -1,6 +1,6 @@
;;; tcover-ses.el --- Example use of `testcover' to test "SES" -*- lexical-binding: t; -*-
-;; Copyright (C) 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2024 Free Software Foundation, Inc.
;; Author: Jonathan Yavner <jyavner@member.fsf.org>
;; Keywords: spreadsheet lisp utility
diff --git a/lisp/emacs-lisp/testcover.el b/lisp/emacs-lisp/testcover.el
index ed31b90ca32..fb4a2a82d07 100644
--- a/lisp/emacs-lisp/testcover.el
+++ b/lisp/emacs-lisp/testcover.el
@@ -1,6 +1,6 @@
;;; testcover.el --- Visual code-coverage tool -*- lexical-binding:t -*-
-;; Copyright (C) 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2024 Free Software Foundation, Inc.
;; Author: Jonathan Yavner <jyavner@member.fsf.org>
;; Keywords: lisp utility
diff --git a/lisp/emacs-lisp/text-property-search.el b/lisp/emacs-lisp/text-property-search.el
index 669cdd97319..f05219f839b 100644
--- a/lisp/emacs-lisp/text-property-search.el
+++ b/lisp/emacs-lisp/text-property-search.el
@@ -1,6 +1,6 @@
;;; text-property-search.el --- search for text properties -*- lexical-binding:t -*-
-;; Copyright (C) 2018-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2018-2024 Free Software Foundation, Inc.
;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
;; Keywords: convenience
diff --git a/lisp/emacs-lisp/thunk.el b/lisp/emacs-lisp/thunk.el
index 45d69c6e164..1776ca0de40 100644
--- a/lisp/emacs-lisp/thunk.el
+++ b/lisp/emacs-lisp/thunk.el
@@ -1,6 +1,6 @@
;;; thunk.el --- Lazy form evaluation -*- lexical-binding: t -*-
-;; Copyright (C) 2015-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2024 Free Software Foundation, Inc.
;; Author: Nicolas Petton <nicolas@petton.fr>
;; Keywords: sequences
diff --git a/lisp/emacs-lisp/timer-list.el b/lisp/emacs-lisp/timer-list.el
index b9a171adc07..52309a247c0 100644
--- a/lisp/emacs-lisp/timer-list.el
+++ b/lisp/emacs-lisp/timer-list.el
@@ -1,6 +1,6 @@
;;; timer-list.el --- list active timers in a buffer -*- lexical-binding:t -*-
-;; Copyright (C) 2016-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2016-2024 Free Software Foundation, Inc.
;; Maintainer: emacs-devel@gnu.org
;; Package: emacs
diff --git a/lisp/emacs-lisp/timer.el b/lisp/emacs-lisp/timer.el
index 468c46519fd..f6f2a8d87c0 100644
--- a/lisp/emacs-lisp/timer.el
+++ b/lisp/emacs-lisp/timer.el
@@ -1,6 +1,6 @@
;;; timer.el --- run a function with args at some time in future -*- lexical-binding: t -*-
-;; Copyright (C) 1996-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996, 2001-2024 Free Software Foundation, Inc.
;; Maintainer: emacs-devel@gnu.org
;; Package: emacs
diff --git a/lisp/emacs-lisp/tq.el b/lisp/emacs-lisp/tq.el
index 700e7c45e1e..b45efa3e331 100644
--- a/lisp/emacs-lisp/tq.el
+++ b/lisp/emacs-lisp/tq.el
@@ -1,6 +1,6 @@
;;; tq.el --- utility to maintain a transaction queue -*- lexical-binding:t -*-
-;; Copyright (C) 1985-1987, 1992, 2001-2023 Free Software Foundation,
+;; Copyright (C) 1985-1987, 1992, 2001-2024 Free Software Foundation,
;; Inc.
;; Author: Scott Draves <spot@cs.cmu.edu>
diff --git a/lisp/emacs-lisp/trace.el b/lisp/emacs-lisp/trace.el
index d802648d8ab..2c8b913ec33 100644
--- a/lisp/emacs-lisp/trace.el
+++ b/lisp/emacs-lisp/trace.el
@@ -1,6 +1,6 @@
;;; trace.el --- tracing facility for Emacs Lisp functions -*- lexical-binding: t -*-
-;; Copyright (C) 1993-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1993-2024 Free Software Foundation, Inc.
;; Author: Hans Chalupsky <hans@cs.buffalo.edu>
;; Maintainer: emacs-devel@gnu.org
@@ -128,6 +128,8 @@
;;; Code:
+(require 'cl-print)
+
(defgroup trace nil
"Tracing facility for Emacs Lisp functions."
:prefix "trace-"
@@ -168,13 +170,13 @@ and CONTEXT is a string describing the dynamic context (e.g. values of
some global variables)."
(let ((print-circle t)
(print-escape-newlines t))
- (format "%s%s%d -> %S%s\n"
+ (format "%s%s%d -> %s%s\n"
(mapconcat #'char-to-string (make-string (max 0 (1- level)) ?|) " ")
(if (> level 1) " " "")
level
;; FIXME: Make it so we can click the function name to jump to its
;; definition and/or untrace it.
- (cons function args)
+ (cl-prin1-to-string (cons function args))
context)))
(defun trace-exit-message (function level value context)
@@ -184,13 +186,13 @@ and CONTEXT is a string describing the dynamic context (e.g. values of
some global variables)."
(let ((print-circle t)
(print-escape-newlines t))
- (format "%s%s%d <- %s: %S%s\n"
+ (format "%s%s%d <- %s: %s%s\n"
(mapconcat 'char-to-string (make-string (1- level) ?|) " ")
(if (> level 1) " " "")
level
function
;; Do this so we'll see strings:
- value
+ (cl-prin1-to-string value)
context)))
(defvar trace--timer nil)
diff --git a/lisp/emacs-lisp/unsafep.el b/lisp/emacs-lisp/unsafep.el
index e722cbc52dd..c64619e9b9e 100644
--- a/lisp/emacs-lisp/unsafep.el
+++ b/lisp/emacs-lisp/unsafep.el
@@ -1,6 +1,6 @@
;;; unsafep.el --- Determine whether a Lisp form is safe to evaluate -*- lexical-binding: t; -*-
-;; Copyright (C) 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2024 Free Software Foundation, Inc.
;; Author: Jonathan Yavner <jyavner@member.fsf.org>
;; Keywords: safety lisp utility
diff --git a/lisp/emacs-lisp/vtable.el b/lisp/emacs-lisp/vtable.el
index 0551053df8e..02020552e7f 100644
--- a/lisp/emacs-lisp/vtable.el
+++ b/lisp/emacs-lisp/vtable.el
@@ -1,6 +1,6 @@
;;; vtable.el --- Displaying data in tables -*- lexical-binding: t; -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -240,13 +240,14 @@ See info node `(vtable)Top' for vtable documentation."
(defun vtable-beginning-of-table ()
"Go to the start of the current table."
- (if (text-property-search-backward 'vtable (vtable-current-table))
+ (if (or (text-property-search-backward 'vtable (vtable-current-table) #'eq)
+ (get-text-property (point) 'vtable))
(point)
(goto-char (point-min))))
(defun vtable-end-of-table ()
"Go to the end of the current table."
- (if (text-property-search-forward 'vtable (vtable-current-table))
+ (if (text-property-search-forward 'vtable (vtable-current-table) #'eq)
(point)
(goto-char (point-max))))
diff --git a/lisp/emacs-lisp/warnings.el b/lisp/emacs-lisp/warnings.el
index 31b840d6c83..6c62a56e99c 100644
--- a/lisp/emacs-lisp/warnings.el
+++ b/lisp/emacs-lisp/warnings.el
@@ -1,6 +1,6 @@
;;; warnings.el --- log and display warnings -*- lexical-binding:t -*-
-;; Copyright (C) 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2024 Free Software Foundation, Inc.
;; Maintainer: emacs-devel@gnu.org
;; Keywords: internal
@@ -106,6 +106,7 @@ so only the element (FOO) will match it."
:type '(repeat (repeat symbol))
:version "22.1")
+;;;###autoload
(defcustom warning-suppress-types nil
"List of warning types not to display immediately.
If any element of this list matches the TYPE argument to `display-warning',
diff --git a/lisp/emacs-lock.el b/lisp/emacs-lock.el
index a7ea4896129..633b223f730 100644
--- a/lisp/emacs-lock.el
+++ b/lisp/emacs-lock.el
@@ -1,6 +1,6 @@
;;; emacs-lock.el --- protect buffers against killing or exiting -*- lexical-binding: t -*-
-;; Copyright (C) 2011-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2011-2024 Free Software Foundation, Inc.
;; Author: Juanma Barranquero <lekktu@gmail.com>
;; Inspired by emacs-lock.el by Tom Wurgler <twurgler@goodyear.com>
diff --git a/lisp/emulation/cua-base.el b/lisp/emulation/cua-base.el
index a6d6f47ead5..fb6a8515d9e 100644
--- a/lisp/emulation/cua-base.el
+++ b/lisp/emulation/cua-base.el
@@ -1,6 +1,6 @@
;;; cua-base.el --- emulate CUA key bindings -*- lexical-binding: t; -*-
-;; Copyright (C) 1997-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997-2024 Free Software Foundation, Inc.
;; Author: Kim F. Storm <storm@cua.dk>
;; Keywords: keyboard emulations convenience cua
@@ -1134,7 +1134,7 @@ If ARG is the atom `-', scroll upward by nearly full screen."
(defun cua--M/H-key (map key fct)
;; bind H-KEY or M-KEY to FCT in MAP
- (unless (listp key) (setq key (list key)))
+ (setq key (ensure-list key))
(define-key map (vector (cons cua--rectangle-modifier-key key)) fct))
(defun cua--self-insert-char-p (def)
diff --git a/lisp/emulation/cua-gmrk.el b/lisp/emulation/cua-gmrk.el
index ccf1c96eb01..88369ac3bea 100644
--- a/lisp/emulation/cua-gmrk.el
+++ b/lisp/emulation/cua-gmrk.el
@@ -1,6 +1,6 @@
;;; cua-gmrk.el --- CUA unified global mark support -*- lexical-binding: t; -*-
-;; Copyright (C) 1997-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997-2024 Free Software Foundation, Inc.
;; Author: Kim F. Storm <storm@cua.dk>
;; Keywords: keyboard emulations convenience cua mark
diff --git a/lisp/emulation/cua-rect.el b/lisp/emulation/cua-rect.el
index 4e52abbb2c9..e50924dbd1f 100644
--- a/lisp/emulation/cua-rect.el
+++ b/lisp/emulation/cua-rect.el
@@ -1,6 +1,6 @@
;;; cua-rect.el --- CUA unified rectangle support -*- lexical-binding: t; -*-
-;; Copyright (C) 1997-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997-2024 Free Software Foundation, Inc.
;; Author: Kim F. Storm <storm@cua.dk>
;; Keywords: keyboard emulations convenience CUA
diff --git a/lisp/emulation/edt-lk201.el b/lisp/emulation/edt-lk201.el
index a0696737482..09e834503bf 100644
--- a/lisp/emulation/edt-lk201.el
+++ b/lisp/emulation/edt-lk201.el
@@ -1,6 +1,6 @@
;;; edt-lk201.el --- enhanced EDT keypad mode emulation for LK-201 keyboards -*- lexical-binding: t -*-
-;; Copyright (C) 1986, 1992-1993, 1995, 2001-2023 Free Software
+;; Copyright (C) 1986, 1992-1993, 1995, 2001-2024 Free Software
;; Foundation, Inc.
;; Author: Kevin Gallagher <kevin.gal@verizon.net>
diff --git a/lisp/emulation/edt-mapper.el b/lisp/emulation/edt-mapper.el
index af2b02eb74e..00b7ab82cea 100644
--- a/lisp/emulation/edt-mapper.el
+++ b/lisp/emulation/edt-mapper.el
@@ -1,6 +1,6 @@
;;; edt-mapper.el --- create an EDT LK-201 map file for X-Windows Emacs -*- lexical-binding: t; -*-
-;; Copyright (C) 1994-1995, 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1994-1995, 2000-2024 Free Software Foundation, Inc.
;; Author: Kevin Gallagher <kevin.gal@verizon.net>
;; Keywords: emulations
diff --git a/lisp/emulation/edt-pc.el b/lisp/emulation/edt-pc.el
index 5e42db7b45b..33179f84d0b 100644
--- a/lisp/emulation/edt-pc.el
+++ b/lisp/emulation/edt-pc.el
@@ -1,6 +1,6 @@
;;; edt-pc.el --- enhanced EDT keypad mode emulation for PC 101 keyboards -*- lexical-binding: t -*-
-;; Copyright (C) 1986, 1994-1995, 2001-2023 Free Software Foundation,
+;; Copyright (C) 1986, 1994-1995, 2001-2024 Free Software Foundation,
;; Inc.
;; Author: Kevin Gallagher <kevin.gal@verizon.net>
diff --git a/lisp/emulation/edt-vt100.el b/lisp/emulation/edt-vt100.el
index d0dcebb2670..a34f6f2a19d 100644
--- a/lisp/emulation/edt-vt100.el
+++ b/lisp/emulation/edt-vt100.el
@@ -1,6 +1,6 @@
;;; edt-vt100.el --- enhanced EDT keypad mode emulation for VT series terminals -*- lexical-binding: t -*-
-;; Copyright (C) 1986, 1992-1993, 1995, 2002-2023 Free Software
+;; Copyright (C) 1986, 1992-1993, 1995, 2002-2024 Free Software
;; Foundation, Inc.
;; Author: Kevin Gallagher <kevin.gal@verizon.net>
diff --git a/lisp/emulation/edt.el b/lisp/emulation/edt.el
index ca353d6dfd2..d5a8fc36758 100644
--- a/lisp/emulation/edt.el
+++ b/lisp/emulation/edt.el
@@ -1,6 +1,6 @@
;;; edt.el --- enhanced EDT keypad mode emulation for GNU Emacs -*- lexical-binding: t; -*-
-;; Copyright (C) 1986, 1992-1995, 2000-2023 Free Software Foundation,
+;; Copyright (C) 1986, 1992-1995, 2000-2024 Free Software Foundation,
;; Inc.
;; Author: Kevin Gallagher <kevin.gal@verizon.net>
diff --git a/lisp/emulation/keypad.el b/lisp/emulation/keypad.el
index ba133ae27a8..73c62a64cb3 100644
--- a/lisp/emulation/keypad.el
+++ b/lisp/emulation/keypad.el
@@ -1,6 +1,6 @@
;;; keypad.el --- simplified keypad bindings -*- lexical-binding: t; -*-
-;; Copyright (C) 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2024 Free Software Foundation, Inc.
;; Author: Kim F. Storm <storm@cua.dk>
;; Keywords: keyboard convenience
diff --git a/lisp/emulation/viper-cmd.el b/lisp/emulation/viper-cmd.el
index 78114db0972..9c42f38dc45 100644
--- a/lisp/emulation/viper-cmd.el
+++ b/lisp/emulation/viper-cmd.el
@@ -1,6 +1,6 @@
;;; viper-cmd.el --- Vi command support for Viper -*- lexical-binding:t -*-
-;; Copyright (C) 1997-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997-2024 Free Software Foundation, Inc.
;; Author: Michael Kifer <kifer@cs.stonybrook.edu>
;; Package: viper
diff --git a/lisp/emulation/viper-ex.el b/lisp/emulation/viper-ex.el
index ecbcace2dd4..11e00aef33d 100644
--- a/lisp/emulation/viper-ex.el
+++ b/lisp/emulation/viper-ex.el
@@ -1,6 +1,6 @@
;;; viper-ex.el --- functions implementing the Ex commands for Viper -*- lexical-binding: t; -*-
-;; Copyright (C) 1994-1998, 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1994-1998, 2000-2024 Free Software Foundation, Inc.
;; Author: Michael Kifer <kifer@cs.stonybrook.edu>
;; Package: viper
diff --git a/lisp/emulation/viper-init.el b/lisp/emulation/viper-init.el
index c39e3cf5142..30750951887 100644
--- a/lisp/emulation/viper-init.el
+++ b/lisp/emulation/viper-init.el
@@ -1,6 +1,6 @@
;;; viper-init.el --- some common definitions for Viper -*- lexical-binding: t; -*-
-;; Copyright (C) 1997-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997-2024 Free Software Foundation, Inc.
;; Author: Michael Kifer <kifer@cs.stonybrook.edu>
;; Package: viper
diff --git a/lisp/emulation/viper-keym.el b/lisp/emulation/viper-keym.el
index 9bf13bbea41..9b550932ccd 100644
--- a/lisp/emulation/viper-keym.el
+++ b/lisp/emulation/viper-keym.el
@@ -1,6 +1,6 @@
;;; viper-keym.el --- Viper keymaps -*- lexical-binding:t -*-
-;; Copyright (C) 1994-1997, 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1994-1997, 2000-2024 Free Software Foundation, Inc.
;; Author: Michael Kifer <kifer@cs.stonybrook.edu>
;; Package: viper
diff --git a/lisp/emulation/viper-macs.el b/lisp/emulation/viper-macs.el
index a983e8ed130..68e6ed1a1db 100644
--- a/lisp/emulation/viper-macs.el
+++ b/lisp/emulation/viper-macs.el
@@ -1,6 +1,6 @@
;;; viper-macs.el --- functions implementing keyboard macros for Viper -*- lexical-binding:t -*-
-;; Copyright (C) 1994-1997, 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1994-1997, 2000-2024 Free Software Foundation, Inc.
;; Author: Michael Kifer <kifer@cs.stonybrook.edu>
;; Package: viper
diff --git a/lisp/emulation/viper-mous.el b/lisp/emulation/viper-mous.el
index 65e2d0968dd..322027b56c4 100644
--- a/lisp/emulation/viper-mous.el
+++ b/lisp/emulation/viper-mous.el
@@ -1,6 +1,6 @@
;;; viper-mous.el --- mouse support for Viper -*- lexical-binding: t; -*-
-;; Copyright (C) 1994-1997, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1994-1997, 2001-2024 Free Software Foundation, Inc.
;; Author: Michael Kifer <kifer@cs.stonybrook.edu>
;; Package: viper
diff --git a/lisp/emulation/viper-util.el b/lisp/emulation/viper-util.el
index 4a38e6640d7..d28c319de98 100644
--- a/lisp/emulation/viper-util.el
+++ b/lisp/emulation/viper-util.el
@@ -1,6 +1,6 @@
;;; viper-util.el --- Utilities used by viper.el -*- lexical-binding:t -*-
-;; Copyright (C) 1994-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1994-2024 Free Software Foundation, Inc.
;; Author: Michael Kifer <kifer@cs.stonybrook.edu>
;; Package: viper
diff --git a/lisp/emulation/viper.el b/lisp/emulation/viper.el
index 96da914275b..83fcdf89375 100644
--- a/lisp/emulation/viper.el
+++ b/lisp/emulation/viper.el
@@ -3,7 +3,7 @@
;; and a venomous VI PERil.
;; Viper Is also a Package for Emacs Rebels.
-;; Copyright (C) 1994-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1994-2024 Free Software Foundation, Inc.
;; Author: Michael Kifer <kifer@cs.stonybrook.edu>
;; Keywords: emulations
@@ -593,8 +593,8 @@ This startup message appears whenever you load Viper, unless you type \\`y' now.
))
(viper-set-expert-level 'dont-change-unless)))
- (or (apply #'derived-mode-p viper-emacs-state-mode-list) ; don't switch to Vi
- (apply #'derived-mode-p viper-insert-state-mode-list) ; don't switch
+ (or (derived-mode-p viper-emacs-state-mode-list) ; don't switch to Vi
+ (derived-mode-p viper-insert-state-mode-list) ; don't switch
(viper-change-state-to-vi))
))
@@ -607,9 +607,9 @@ This startup message appears whenever you load Viper, unless you type \\`y' now.
;; that are not listed in viper-vi-state-mode-list
(defun viper-this-major-mode-requires-vi-state (mode)
(let ((major-mode mode))
- (cond ((apply #'derived-mode-p viper-vi-state-mode-list) t)
- ((apply #'derived-mode-p viper-emacs-state-mode-list) nil)
- ((apply #'derived-mode-p viper-insert-state-mode-list) nil)
+ (cond ((derived-mode-p viper-vi-state-mode-list) t)
+ ((derived-mode-p viper-emacs-state-mode-list) nil)
+ ((derived-mode-p viper-insert-state-mode-list) nil)
(t (and (eq (key-binding "a") 'self-insert-command)
(eq (key-binding " ") 'self-insert-command))))))
diff --git a/lisp/env.el b/lisp/env.el
index 281934af054..e0a8df8476c 100644
--- a/lisp/env.el
+++ b/lisp/env.el
@@ -1,6 +1,6 @@
;;; env.el --- functions to manipulate environment variables -*- lexical-binding:t -*-
-;; Copyright (C) 1991-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1991-2024 Free Software Foundation, Inc.
;; Maintainer: emacs-devel@gnu.org
;; Keywords: processes, unix
diff --git a/lisp/epa-dired.el b/lisp/epa-dired.el
index 309d4358883..5fa576bb7b0 100644
--- a/lisp/epa-dired.el
+++ b/lisp/epa-dired.el
@@ -1,6 +1,6 @@
;;; epa-dired.el --- the EasyPG Assistant, dired extension -*- lexical-binding: t -*-
-;; Copyright (C) 2006-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2006-2024 Free Software Foundation, Inc.
;; Author: Daiki Ueno <ueno@unixuser.org>
;; Keywords: PGP, GnuPG
diff --git a/lisp/epa-file.el b/lisp/epa-file.el
index a27f241c0c3..a4942e78de7 100644
--- a/lisp/epa-file.el
+++ b/lisp/epa-file.el
@@ -1,6 +1,6 @@
;;; epa-file.el --- the EasyPG Assistant, transparent file encryption -*- lexical-binding: t -*-
-;; Copyright (C) 2006-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2006-2024 Free Software Foundation, Inc.
;; Author: Daiki Ueno <ueno@unixuser.org>
;; Keywords: PGP, GnuPG
diff --git a/lisp/epa-hook.el b/lisp/epa-hook.el
index 00df6732e52..458db3e0323 100644
--- a/lisp/epa-hook.el
+++ b/lisp/epa-hook.el
@@ -1,6 +1,6 @@
;;; epa-hook.el --- preloaded code to enable epa-file.el -*- lexical-binding: t -*-
-;; Copyright (C) 2006-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2006-2024 Free Software Foundation, Inc.
;; Author: Daiki Ueno <ueno@unixuser.org>
;; Keywords: PGP, GnuPG
diff --git a/lisp/epa-ks.el b/lisp/epa-ks.el
index 015bf910ac6..c3c11bb0b0b 100644
--- a/lisp/epa-ks.el
+++ b/lisp/epa-ks.el
@@ -1,9 +1,10 @@
;;; epa-ks.el --- EasyPG Key Server Client -*- lexical-binding: t -*-
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
;; Author: Philip K. <philipk@posteo.net>
;; Keywords: PGP, GnuPG
+;; Package: epa
;; This file is part of GNU Emacs.
diff --git a/lisp/epa-mail.el b/lisp/epa-mail.el
index 749d4471a39..0c93b18eea1 100644
--- a/lisp/epa-mail.el
+++ b/lisp/epa-mail.el
@@ -1,6 +1,6 @@
;;; epa-mail.el --- the EasyPG Assistant, minor-mode for mail composer -*- lexical-binding: t -*-
-;; Copyright (C) 2006-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2006-2024 Free Software Foundation, Inc.
;; Author: Daiki Ueno <ueno@unixuser.org>
;; Keywords: PGP, GnuPG, mail, message
diff --git a/lisp/epa.el b/lisp/epa.el
index 8126584e4fb..53da3bf6cce 100644
--- a/lisp/epa.el
+++ b/lisp/epa.el
@@ -1,6 +1,6 @@
;;; epa.el --- the EasyPG Assistant -*- lexical-binding: t -*-
-;; Copyright (C) 2006-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2006-2024 Free Software Foundation, Inc.
;; Author: Daiki Ueno <ueno@unixuser.org>
;; Keywords: PGP, GnuPG
@@ -384,7 +384,7 @@ DOC is documentation text to insert at the start."
(epa--list-keys name nil
"The letters at the start of a line have these meanings.
e expired key. n never trust. m trust marginally. u trust ultimately.
-f trust fully (keys you have signed, usually).
+f trust fully (keys you have signed, usually). r revoked key.
q trust status questionable. - trust status unspecified.
See GPG documentation for more explanation.
\n"))
diff --git a/lisp/epg-config.el b/lisp/epg-config.el
index 6797e159ba7..01ee2cff5b5 100644
--- a/lisp/epg-config.el
+++ b/lisp/epg-config.el
@@ -1,6 +1,6 @@
;;; epg-config.el --- configuration of the EasyPG Library -*- lexical-binding: t -*-
-;; Copyright (C) 2006-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2006-2024 Free Software Foundation, Inc.
;; Author: Daiki Ueno <ueno@unixuser.org>
;; Keywords: PGP, GnuPG
diff --git a/lisp/epg.el b/lisp/epg.el
index 9da5a36ba3d..7bec91f616d 100644
--- a/lisp/epg.el
+++ b/lisp/epg.el
@@ -1,6 +1,6 @@
;;; epg.el --- the EasyPG Library -*- lexical-binding: t -*-
-;; Copyright (C) 1999-2000, 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2000, 2002-2024 Free Software Foundation, Inc.
;; Author: Daiki Ueno <ueno@unixuser.org>
;; Keywords: PGP, GnuPG
@@ -266,11 +266,11 @@ car is a function and cdr is a callback data.
The function gets three arguments: the context, the key-id in
question, and the callback data (if any).
-The callback may not be called if you use GnuPG 2.x, which relies
-on the external program called `gpg-agent' for passphrase query.
-If you really want to intercept passphrase query, consider
-installing GnuPG 1.x _along with_ GnuPG 2.x, which does passphrase
-query by itself and Emacs can intercept them."
+The callback may not be called if you use GnuPG 2.0, which relies
+only on external programs for passphrase query and does not
+provide loopback pinentry. For details see Info node `(epa)
+GnuPG version compatibility' and Info node `(epa) GnuPG
+Pinentry'."
;; (declare (obsolete setf "25.1"))
(setf (epg-context-passphrase-callback context)
(if (functionp passphrase-callback)
@@ -595,7 +595,12 @@ callback data (if any)."
(if (epg-context-textmode context) '("--textmode"))
(if (epg-context-output-file context)
(list "--output" (epg-context-output-file context)))
- (if (epg-context-pinentry-mode context)
+ (if (and (epg-context-pinentry-mode context)
+ (not
+ ;; loopback doesn't work with gpgsm
+ (and (eq (epg-context-protocol context) 'CMS)
+ (eq (epg-context-pinentry-mode context)
+ 'loopback))))
(list "--pinentry-mode"
(symbol-name (epg-context-pinentry-mode
context))))
@@ -1264,8 +1269,7 @@ callback data (if any)."
keys string field index)
(if name
(progn
- (unless (listp name)
- (setq name (list name)))
+ (setq name (ensure-list name))
(while name
(setq args (append args (list list-keys-option (car name)))
name (cdr name))))
@@ -2019,9 +2023,7 @@ PARAMETERS is a string which tells how to create the key."
(defun epg-start-edit-key (context key edit-callback handback)
"Initiate an edit operation on KEY.
-EDIT-CALLBACK is called from process filter and takes four
-arguments: the context, a status, an argument string, and the
-handback argument.
+See `epg-edit-key' for a description of the arguments.
If you use this function, you will need to wait for the completion of
`epg-gpg-program' by using `epg-wait-for-completion' and call
@@ -2036,7 +2038,47 @@ If you are unsure, use synchronous version of this function
(car (epg-key-sub-key-list key))))))
(defun epg-edit-key (context key edit-callback handback)
- "Edit KEY in the keyring."
+ "Edit KEY in the keyring.
+
+This function and function `epg-start-edit-key' use the
+line-based protocol enabled by \"gpg\" parameter \"--status-fd\"
+to edit KEY. For each GnuPG status line, these functions or,
+more precisely, the EPG process filter calls EDIT-CALLBACK with
+four arguments: argument CONTEXT, the GnuPG status keyword, the
+GnuPG status argument string, and argument HANDBACK.
+
+The following example uses a simple state machine to trust the
+first subkey of key KEY ultimately:
+
+ (let ((state 0))
+ (epg-edit-key
+ context key
+ (lambda (context status string _handback)
+ (pcase (vector state status string)
+ (\\=`[0 \"KEY_CONSIDERED\" ,_])
+ (\\='[1 \"GET_LINE\" \"keyedit.prompt\"]
+ (process-send-string (epg-context-process context) \"1\\n\"))
+ (\\='[2 \"GOT_IT\" \"\"])
+ (\\='[3 \"GET_LINE\" \"keyedit.prompt\"]
+ (process-send-string (epg-context-process context) \"trust\\n\"))
+ (\\='[4 \"GOT_IT\" \"\"])
+ (\\='[5 \"GET_LINE\" \"edit_ownertrust.value\"]
+ (process-send-string (epg-context-process context) \"5\\n\"))
+ (\\='[6 \"GOT_IT\" \"\"])
+ (\\='[7 \"GET_BOOL\" \"edit_ownertrust.set_ultimate.okay\"]
+ (process-send-string (epg-context-process context) \"yes\\n\"))
+ (\\='[8 \"GOT_IT\" \"\"])
+ (\\='[9 \"GET_LINE\" \"keyedit.prompt\"]
+ (process-send-string (epg-context-process context) \"quit\\n\"))
+ (\\='[10 \"GOT_IT\" \"\"])
+ (_
+ (error \"Key edit protocol error in state %d\" state)))
+ (setq state (1+ state)))
+ nil))
+
+This is a slightly simplified example: Ideally, it should have
+double-checked the fingerprint argument to the \"KEY_CONSIDERED\"
+status keyword instead of ignoring it."
(unwind-protect
(progn
(epg-start-edit-key context key edit-callback handback)
diff --git a/lisp/erc/ChangeLog.1 b/lisp/erc/ChangeLog.1
index 8a569ebfdb3..f1605f70f3e 100644
--- a/lisp/erc/ChangeLog.1
+++ b/lisp/erc/ChangeLog.1
@@ -11703,7 +11703,7 @@
* erc-speak.el, erc.el: New file.
- Copyright (C) 2001-2023 Free Software Foundation, Inc.
+ Copyright (C) 2001-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/lisp/erc/ChangeLog.2 b/lisp/erc/ChangeLog.2
index ebef621064b..b10b0b68f00 100644
--- a/lisp/erc/ChangeLog.2
+++ b/lisp/erc/ChangeLog.2
@@ -757,7 +757,7 @@
See ChangeLog.1 for earlier changes.
- Copyright (C) 2009-2023 Free Software Foundation, Inc.
+ Copyright (C) 2009-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/lisp/erc/erc-autoaway.el b/lisp/erc/erc-autoaway.el
index b586d4523b4..13da725f1ac 100644
--- a/lisp/erc/erc-autoaway.el
+++ b/lisp/erc/erc-autoaway.el
@@ -1,6 +1,6 @@
;;; erc-autoaway.el --- Provides autoaway for ERC -*- lexical-binding: t; -*-
-;; Copyright (C) 2002-2004, 2006-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2004, 2006-2024 Free Software Foundation, Inc.
;; Author: Jorgen Schaefer <forcer@forcix.cx>
;; Maintainer: Amin Bandali <bandali@gnu.org>, F. Jason Park <jp@neverwas.me>
diff --git a/lisp/erc/erc-backend.el b/lisp/erc/erc-backend.el
index eb3ec39fedd..4162df00595 100644
--- a/lisp/erc/erc-backend.el
+++ b/lisp/erc/erc-backend.el
@@ -1,6 +1,6 @@
;;; erc-backend.el --- Backend network communication for ERC -*- lexical-binding:t -*-
-;; Copyright (C) 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2004-2024 Free Software Foundation, Inc.
;; Filename: erc-backend.el
;; Author: Lawrence Mitchell <wence@gmx.li>
@@ -101,39 +101,27 @@
(eval-when-compile (require 'cl-lib))
(require 'erc-common)
-(defvar erc--called-as-input-p)
(defvar erc--display-context)
(defvar erc--target)
-(defvar erc--user-from-nick-function)
(defvar erc-channel-list)
-(defvar erc-channel-users)
+(defvar erc-channel-members)
(defvar erc-default-nicks)
(defvar erc-default-recipients)
(defvar erc-ensure-target-buffer-on-privmsg)
-(defvar erc-format-nick-function)
-(defvar erc-format-query-as-channel-p)
(defvar erc-hide-prompt)
(defvar erc-input-marker)
(defvar erc-insert-marker)
-(defvar erc-invitation)
(defvar erc-join-buffer)
-(defvar erc-kill-buffer-on-part)
-(defvar erc-kill-server-buffer-on-quit)
-(defvar erc-log-p)
-(defvar erc-minibuffer-ignored)
(defvar erc-networks--id)
(defvar erc-nick)
(defvar erc-nick-change-attempt-count)
-(defvar erc-prompt-for-channel-key)
-(defvar erc-prompt-hidden)
-(defvar erc-receive-query-display)
-(defvar erc-receive-query-display-defer)
-(defvar erc-reuse-buffers)
(defvar erc-verbose-server-ping)
-(defvar erc-whowas-on-nosuchnick)
+(declare-function erc--init-channel-modes "erc" (channel raw-args))
(declare-function erc--open-target "erc" (target))
+(declare-function erc--parse-nuh "erc" (string))
(declare-function erc--target-from-string "erc" (string))
+(declare-function erc--update-modes "erc" (raw-args))
(declare-function erc-active-buffer "erc" nil)
(declare-function erc-add-default-channel "erc" (channel))
(declare-function erc-banlist-update "erc" (proc parsed))
@@ -154,7 +142,6 @@
(declare-function erc-display-server-message "erc" (_proc parsed))
(declare-function erc-emacs-time-to-erc-time "erc" (&optional specified-time))
(declare-function erc-format-message "erc" (msg &rest args))
-(declare-function erc-format-privmessage "erc" (nick msg privp msgp))
(declare-function erc-get-buffer "erc" (target &optional proc))
(declare-function erc-handle-login "erc" nil)
(declare-function erc-handle-user-status-change "erc" (type nlh &optional l))
@@ -164,7 +151,6 @@
(declare-function erc-is-message-ctcp-p "erc" (message))
(declare-function erc-log-irc-protocol "erc" (string &optional outbound))
(declare-function erc-login "erc" nil)
-(declare-function erc-make-notice "erc" (message))
(declare-function erc-network "erc-networks" nil)
(declare-function erc-networks--id-given "erc-networks" (arg &rest args))
(declare-function erc-networks--id-reload "erc-networks" (arg &rest args))
@@ -180,13 +166,15 @@
(declare-function erc-server-buffer "erc" nil)
(declare-function erc-set-active-buffer "erc" (buffer))
(declare-function erc-set-current-nick "erc" (nick))
-(declare-function erc-set-modes "erc" (tgt mode-string))
(declare-function erc-time-diff "erc" (t1 t2))
(declare-function erc-trim-string "erc" (s))
(declare-function erc-update-mode-line "erc" (&optional buffer))
(declare-function erc-update-mode-line-buffer "erc" (buffer))
(declare-function erc-wash-quit-reason "erc" (reason nick login host))
+(declare-function erc--determine-speaker-message-format-args "erc"
+ (nick target message queryp privmsgp statusmsgp inputp
+ &optional prefix disp-nick))
(declare-function erc-display-message "erc"
(parsed type buffer msg &rest args))
(declare-function erc-get-buffer-create "erc"
@@ -195,8 +183,6 @@
(proc parsed nick login host msg))
(declare-function erc-update-channel-topic "erc"
(channel topic &optional modify))
-(declare-function erc-update-modes "erc"
- (tgt mode-string &optional _nick _host _login))
(declare-function erc-update-user-nick "erc"
(nick &optional new-nick host login full-name info))
(declare-function erc-open "erc"
@@ -511,7 +497,7 @@ It should take same arguments as `open-network-stream' does."
"Either nil or a list of strings.
Each string is a IRC message type, like PRIVMSG or NOTICE.
All Message types in that list of subjected to duplicate prevention."
- :type '(choice (const nil) (list string)))
+ :type '(repeat string))
(defcustom erc-server-duplicate-timeout 60
"The time allowed in seconds between duplicate messages.
@@ -729,7 +715,7 @@ error data is something ERC recognizes. Print an explanation to
the server buffer in any case."
(when (eq (process-status process) 'failed)
(erc-display-message
- nil 'error (process-buffer process)
+ nil '(notice error) (process-buffer process)
(format "Process exit status: %S" (process-exit-status process)))
(pcase (process-exit-status process)
(111
@@ -818,6 +804,7 @@ Make sure you are in an ERC buffer when running this."
nil nil nil erc-session-client-certificate
erc-session-username
(erc-networks--id-given erc-networks--id))
+ (defvar erc-reuse-buffers)
(unless (with-suppressed-warnings ((obsolete erc-reuse-buffers))
erc-reuse-buffers)
(cl-assert (not (eq buffer (current-buffer)))))))))
@@ -996,7 +983,7 @@ When `erc-server-reconnect-attempts' is a number, increment
(- erc-server-reconnect-attempts
(cl-incf erc-server-reconnect-count (or incr 1)))))
(proc (buffer-local-value 'erc-server-process buffer)))
- (erc-display-message nil 'error buffer 'reconnecting
+ (erc-display-message nil '(notice error) buffer 'reconnecting
?m erc-server-reconnect-timeout
?i (if count erc-server-reconnect-count "N")
?n (if count erc-server-reconnect-attempts "A"))
@@ -1040,18 +1027,27 @@ Conditionally try to reconnect and take appropriate action."
(erc-update-mode-line)
;; Kill server buffer if user wants it
(set-buffer-modified-p nil)
+ (defvar erc-kill-server-buffer-on-quit)
(when erc-kill-server-buffer-on-quit
(kill-buffer (current-buffer))))
;; unexpected disconnect
(erc-process-sentinel-2 event buffer))))
+(defvar-local erc--hidden-prompt-overlay nil
+ "Overlay for hiding the prompt when disconnected.")
+
(cl-defmethod erc--reveal-prompt ()
- (remove-text-properties erc-insert-marker erc-input-marker
- '(display nil)))
+ (when erc--hidden-prompt-overlay
+ (delete-overlay erc--hidden-prompt-overlay)
+ (setq erc--hidden-prompt-overlay nil)))
(cl-defmethod erc--conceal-prompt ()
- (add-text-properties erc-insert-marker (1- erc-input-marker)
- `(display ,erc-prompt-hidden)))
+ (when-let (((null erc--hidden-prompt-overlay))
+ (ov (make-overlay erc-insert-marker (1- erc-input-marker)
+ nil 'front-advance)))
+ (defvar erc-prompt-hidden)
+ (overlay-put ov 'display erc-prompt-hidden)
+ (setq erc--hidden-prompt-overlay ov)))
(defun erc--prompt-hidden-p ()
(and (marker-position erc-insert-marker)
@@ -1063,7 +1059,8 @@ Conditionally try to reconnect and take appropriate action."
(marker-position erc-input-marker))
(with-silent-modifications
(put-text-property erc-insert-marker (1- erc-input-marker) 'erc-prompt t)
- (erc--reveal-prompt))))
+ (erc--reveal-prompt)
+ (run-hooks 'erc--refresh-prompt-hook))))
(defun erc--unhide-prompt-on-self-insert ()
(when (and (eq this-command #'self-insert-command)
@@ -1088,8 +1085,9 @@ Change value of property `erc-prompt' from t to `hidden'."
(with-silent-modifications
(put-text-property erc-insert-marker (1- erc-input-marker)
'erc-prompt 'hidden)
- (erc--conceal-prompt))
- (add-hook 'pre-command-hook #'erc--unhide-prompt-on-self-insert 91 t))))
+ (erc--conceal-prompt)
+ (run-hooks 'erc--refresh-prompt-hook))
+ (add-hook 'pre-command-hook #'erc--unhide-prompt-on-self-insert 80 t))))
(defun erc-process-sentinel (cproc event)
"Sentinel function for ERC process."
@@ -1104,15 +1102,16 @@ Change value of property `erc-prompt' from t to `hidden'."
(erc--register-connection)
;; assume event is 'failed
(erc-with-all-buffers-of-server cproc nil
- (setq erc-server-connected nil))
+ (setq erc-server-connected nil))
(when erc-server-ping-handler
(progn (cancel-timer erc-server-ping-handler)
(setq erc-server-ping-handler nil)))
(run-hook-with-args 'erc-disconnected-hook
(erc-current-nick) (system-name) "")
- (dolist (buf (erc-buffer-filter (lambda () (boundp 'erc-channel-users)) cproc))
- (with-current-buffer buf
- (setq erc-channel-users (make-hash-table :test 'equal))))
+ (erc-with-all-buffers-of-server cproc (lambda () erc-channel-members)
+ (when (erc--target-channel-p erc--target)
+ (setf (erc--target-channel-joined-p erc--target) nil))
+ (clrhash erc-channel-members))
;; Hide the prompt
(erc--hide-prompt cproc)
;; Decide what to do with the buffer
@@ -1170,7 +1169,7 @@ Use DISPLAY-FN to show the results."
When FORCE is non-nil, bypass flood protection so that STRING is
sent directly without modifying the queue. When FORCE is the
symbol `no-penalty', exempt this round from accumulating a
-timeout penalty.
+timeout penalty and schedule it to run ASAP instead of blocking.
If TARGET is specified, look up encoding information for that
channel in `erc-encoding-coding-alist' or
@@ -1178,6 +1177,11 @@ channel in `erc-encoding-coding-alist' or
See `erc-server-flood-margin' for an explanation of the flood
protection algorithm."
+ (erc--server-send string force target))
+
+(cl-defmethod erc--server-send (string force target)
+ "Encode and send STRING to `erc-server-process'.
+Expect STRING, FORCE, and TARGET to originate from `erc-server-send'."
(erc-log (concat "erc-server-send: " string "(" (buffer-name) ")"))
(setq erc-server-last-sent-time (erc-current-time))
(let ((encoding (erc-coding-system-for-target target)))
@@ -1198,14 +1202,17 @@ protection algorithm."
(when (fboundp 'set-process-coding-system)
(set-process-coding-system erc-server-process
'raw-text encoding))
- (process-send-string erc-server-process str))
+ (if (and (eq force 'no-penalty))
+ (run-at-time nil nil #'process-send-string
+ erc-server-process str)
+ (process-send-string erc-server-process str)))
;; See `erc-server-send-queue' for full
;; explanation of why we need this condition-case
(error nil)))
(setq erc-server-flood-queue
(append erc-server-flood-queue
(list (cons str encoding))))
- (erc-server-send-queue (current-buffer))))
+ (run-at-time nil nil #'erc-server-send-queue (current-buffer))))
t)
(message "ERC: No process running")
nil)))
@@ -1275,8 +1282,10 @@ protection algorithm."
nil #'erc-server-send-queue buffer)))))))
(defun erc-message (message-command line &optional force)
- "Send LINE to the server as a privmsg or a notice.
-MESSAGE-COMMAND should be either \"PRIVMSG\" or \"NOTICE\".
+ "Send LINE, possibly expanding a target specifier beforehand.
+Expect MESSAGE-COMMAND to be an IRC command with a single
+positional target parameter followed by a trailing parameter.
+
If the target is \",\", the last person you've got a message from will
be used. If the target is \".\", the last person you've sent a message
to will be used."
@@ -1612,7 +1621,9 @@ Would expand to:
\(fn (NAME &rest ALIASES) &optional EXTRA-FN-DOC EXTRA-VAR-DOC &rest FN-BODY)"
(declare (debug (&define [&name "erc-response-handler@"
- (symbolp &rest symbolp)]
+ ;; No `def-edebug-elem-spec' in 27.
+ ([&or integerp symbolp]
+ &rest [&or integerp symbolp])]
&optional sexp sexp def-body))
(indent defun))
(if (numberp name) (setq name (intern (format "%03i" name))))
@@ -1695,6 +1706,7 @@ add things to `%s' instead."
(chnl (erc-response.contents parsed)))
(pcase-let ((`(,nick ,login ,host)
(erc-parse-user (erc-response.sender parsed))))
+ (defvar erc-invitation)
(setq erc-invitation chnl)
(when (string= target (erc-current-nick))
(erc-display-message
@@ -1718,7 +1730,7 @@ add things to `%s' instead."
(if (string-match "^\\(.*\\)\^g.*$" chnl)
(setq chnl (match-string 1 chnl)))
(save-excursion
- (let* ((str (cond
+ (let ((args (cond
;; If I have joined a channel
((erc-current-nick-p nick)
(let ((erc--display-context
@@ -1730,23 +1742,21 @@ add things to `%s' instead."
(with-suppressed-warnings
((obsolete erc-add-default-channel))
(erc-add-default-channel chnl))
+ (setf (erc--target-channel-joined-p erc--target) t)
(erc-server-send (format "MODE %s" chnl)))
(erc-with-buffer (chnl proc)
(erc-channel-begin-receiving-names))
(erc-update-mode-line)
(run-hooks 'erc-join-hook)
- (erc-make-notice
- (erc-format-message 'JOIN-you ?c chnl)))
+ (list 'JOIN-you ?c chnl))
(t
(setq buffer (erc-get-buffer chnl proc))
- (erc-make-notice
- (erc-format-message
- 'JOIN ?n nick ?u login ?h host ?c chnl))))))
+ (list 'JOIN ?n nick ?u login ?h host ?c chnl)))))
(when buffer (set-buffer buffer))
(erc-update-channel-member chnl nick nick t nil nil nil nil nil host login)
;; on join, we want to stay in the new channel buffer
;;(set-buffer ob)
- (erc-display-message parsed nil buffer str))))))
+ (apply #'erc-display-message parsed 'notice buffer args))))))
(define-erc-response-handler (KICK)
"Handle kick messages received from the server." nil
@@ -1793,7 +1803,7 @@ add things to `%s' instead."
(t (erc-get-buffer tgt)))))
(with-current-buffer (or buf
(current-buffer))
- (erc-update-modes tgt mode nick host login))
+ (erc--update-modes (cdr (erc-response.command-args parsed))))
(if (or (string= login "") (string= host ""))
(erc-display-message parsed 'notice buf
'MODE-nick ?n nick
@@ -1869,6 +1879,7 @@ add things to `%s' instead."
(with-suppressed-warnings ((obsolete erc-delete-default-channel))
(erc-delete-default-channel chnl buffer))
(erc-update-mode-line buffer)
+ (defvar erc-kill-buffer-on-part)
(when erc-kill-buffer-on-part
(kill-buffer buffer))))))
@@ -1896,16 +1907,80 @@ add things to `%s' instead."
?s (if (/= erc-server-lag 1) "s" "")))
(erc-update-mode-line))))
+(defun erc--statusmsg-target (target)
+ "Return actual target from given TARGET if it has a leading prefix char."
+ (and-let* ((erc-ensure-target-buffer-on-privmsg)
+ ((not (eq erc-ensure-target-buffer-on-privmsg 'status)))
+ ((not (erc-channel-p target)))
+ (chars (erc--get-isupport-entry 'STATUSMSG 'single))
+ ((string-search (string (aref target 0)) chars))
+ (trimmed (substring target 1))
+ ((erc-channel-p trimmed)))
+ trimmed))
+
+;; Moved to this file from erc.el in ERC 5.6.
+(defvar-local erc-current-message-catalog 'english
+ "Current language or context catalog for formatting inserted messages.
+See `erc-format-message'.")
+
+;; This variable can be made public if the current design proves
+;; sufficient.
+(defvar erc--message-speaker-catalog '-speaker
+ "The \"speaker\" catalog symbol used to format PRIVMSGs and NOTICEs.
+
+This symbol defines a \"catalog\" of variables and functions
+whose names reflect their membership via a corresponding CATALOG
+component, as in \"erc-message-CATALOG-KEY\". Here, KEY refers
+to a common set of interface members (variables or functions),
+that an implementer must define:
+
+- `statusmsg' and `statusmsg-input': PRIVMSGs whose target is a
+ status-prefixed channel; the latter is the \"echoed\" version
+
+- `chan-privmsg', `query-privmsg', `chan-notice', `query-notice':
+ standard chat messages traditionally prefixed by a <nickname>
+ indicating the message's \"speaker\"
+
+- `input-chan-privmsg', `input-query-privmsg', `input-query-notice',
+ `input-chan-notice': \"echoed\" versions of the above
+
+- `ctcp-action', `ctcp-action-input', `ctcp-action-statusmsg',
+ `ctcp-action-statusmsg-input': \"CTCP ACTION\" versions of the
+ above
+
+The other part of this interface is the per-key collection of
+`format-spec' parameters members must support. For simplicity,
+this catalog currently defines a common set for all keys, some of
+which may be assigned the empty string when not applicable:
+
+ %n - nickname
+ %m - message body
+ %p - nickname's status prefix (when applicable)
+ %s - current target's STATUSMSG prefix (when applicable)
+
+As an added means of communicating with various modules, if this
+catalog's symbol has the property `erc--msg-prop-overrides',
+consumers calling `erc-display-message' will see the value added
+to the `erc--msg-props' \"environment\" in modification hooks,
+like `erc-insert-modify-hook'.")
+
+(defvar erc--speaker-status-prefix-wanted-p (gensym "erc-")
+ "Sentinel to detect whether `erc-format-@nick' has just run.")
+
(define-erc-response-handler (PRIVMSG NOTICE)
"Handle private messages, including messages in channels." nil
(let ((sender-spec (erc-response.sender parsed))
(cmd (erc-response.command parsed))
(tgt (car (erc-response.command-args parsed)))
(msg (erc-response.contents parsed)))
- (if (or (erc-ignored-user-p sender-spec)
- (erc-ignored-reply-p msg tgt proc))
+ (defvar erc-minibuffer-ignored)
+ (defvar erc-ignore-list)
+ (defvar erc-ignore-reply-list)
+ (if (or (and erc-ignore-list (erc-ignored-user-p sender-spec))
+ (and erc-ignore-reply-list (erc-ignored-reply-p msg tgt proc)))
(when erc-minibuffer-ignored
(message "Ignored %s from %s to %s" cmd sender-spec tgt))
+ (defvar erc--msg-prop-overrides)
(let* ((sndr (erc-parse-user sender-spec))
(nick (nth 0 sndr))
(login (nth 1 sndr))
@@ -1913,16 +1988,22 @@ add things to `%s' instead."
(msgp (string= cmd "PRIVMSG"))
(noticep (string= cmd "NOTICE"))
;; S.B. downcase *both* tgt and current nick
- (privp (erc-current-nick-p tgt))
+ (medown (erc-downcase (erc-current-nick)))
+ (inputp (string= medown (erc-downcase nick)))
+ (privp (string= (erc-downcase tgt) medown))
(erc--display-context `((erc-buffer-display . ,(intern cmd))
,@erc--display-context))
- s buffer
- fnick)
- (setf (erc-response.contents parsed) msg)
+ (erc--msg-prop-overrides `((erc--tmp) ,@erc--msg-prop-overrides))
+ (erc--speaker-status-prefix-wanted-p nil)
+ (erc-current-message-catalog erc--message-speaker-catalog)
+ ;;
+ buffer statusmsg cmem-prefix fnick)
(setq buffer (erc-get-buffer (if privp nick tgt) proc))
;; Even worth checking for empty target here? (invalid anyway)
(unless (or buffer noticep (string-empty-p tgt) (eq ?$ (aref tgt 0))
(erc-is-message-ctcp-and-not-action-p msg))
+ (defvar erc-receive-query-display)
+ (defvar erc-receive-query-display-defer)
(if privp
(when-let ((erc-join-buffer
(or (and (not erc-receive-query-display-defer)
@@ -1933,9 +2014,14 @@ add things to `%s' instead."
(push `(erc-receive-query-display . ,(intern cmd))
erc--display-context)
(setq buffer (erc--open-target nick)))
- ;; A channel buffer has been killed but is still joined.
- (when erc-ensure-target-buffer-on-privmsg
- (setq buffer (erc--open-target tgt)))))
+ (cond
+ ;; Target is a channel and contains leading @+ chars.
+ ((and-let* ((trimmed(erc--statusmsg-target tgt)))
+ (setq buffer (erc-get-buffer trimmed proc)
+ statusmsg (and buffer (substring tgt 0 1)))))
+ ;; A channel buffer has been killed but is still joined.
+ (erc-ensure-target-buffer-on-privmsg
+ (setq buffer (erc--open-target tgt))))))
(when buffer
(with-current-buffer buffer
(when privp (erc--unhide-prompt))
@@ -1944,35 +2030,43 @@ add things to `%s' instead."
;; at this point.
(erc-update-channel-member (if privp nick tgt) nick nick
privp nil nil nil nil nil host login nil nil t)
- (let ((cdata (funcall erc--user-from-nick-function
+ (defvar erc--cmem-from-nick-function)
+ (defvar erc-format-nick-function)
+ (defvar erc-show-speaker-membership-status)
+ (defvar erc-speaker-from-channel-member-function)
+ (let ((cdata (funcall erc--cmem-from-nick-function
(erc-downcase nick) sndr parsed)))
- (setq fnick (funcall erc-format-nick-function
- (car cdata) (cdr cdata))))))
- (cond
- ((erc-is-message-ctcp-p msg)
- (setq s (if msgp
- (erc-process-ctcp-query proc parsed nick login host)
- (erc-process-ctcp-reply proc parsed nick login host
- (match-string 1 msg)))))
- (t
+ (setq fnick (funcall erc-speaker-from-channel-member-function
+ (car cdata) (cdr cdata))
+ cmem-prefix (and (or erc--speaker-status-prefix-wanted-p
+ erc-show-speaker-membership-status
+ inputp)
+ (cdr cdata))))))
+ (if (erc-is-message-ctcp-p msg)
+ (if noticep
+ (erc-process-ctcp-reply proc parsed nick login host
+ (match-string 1 msg))
+ (setq parsed (erc--ctcp-response-from-parsed
+ :parsed parsed :buffer buffer :statusmsg statusmsg
+ :prefix cmem-prefix :dispname fnick))
+ (erc-process-ctcp-query proc parsed nick login host))
(setq erc-server-last-peers (cons nick (cdr erc-server-last-peers)))
- (setq s (erc-format-privmessage
- (or fnick nick) msg
- ;; If buffer is a query buffer,
- ;; format the nick as for a channel.
- (and (not (and buffer
- (erc-query-buffer-p buffer)
- erc-format-query-as-channel-p))
- privp)
- msgp))))
- (when s
- (if (and noticep privp)
- (progn
- (run-hook-with-args 'erc-echo-notice-always-hook
- s parsed buffer nick)
- (run-hook-with-args-until-success
- 'erc-echo-notice-hook s parsed buffer nick))
- (erc-display-message parsed nil buffer s)))))))
+ (with-current-buffer (or buffer (current-buffer))
+ ;; Re-bind in case either buffer has a local value.
+ (let ((erc-current-message-catalog erc--message-speaker-catalog)
+ (msg-args (erc--determine-speaker-message-format-args
+ nick msg privp msgp inputp statusmsg
+ cmem-prefix fnick)))
+ (if (or msgp (not privp))
+ ;; This is a PRIVMSG or a NOTICE to a channel.
+ (apply #'erc-display-message parsed nil buffer msg-args)
+ ;; This is a NOTICE directed at the client's current nick.
+ (push (cons 'erc--msg (car msg-args)) erc--msg-prop-overrides)
+ (let ((fmtmsg (apply #'erc-format-message msg-args)))
+ (run-hook-with-args 'erc-echo-notice-always-hook
+ fmtmsg parsed buffer nick)
+ (run-hook-with-args-until-success
+ 'erc-echo-notice-hook fmtmsg parsed buffer nick))))))))))
(define-erc-response-handler (QUIT)
"Another user has quit IRC." nil
@@ -2087,7 +2181,9 @@ primitive value."
(erc-with-server-buffer erc--isupport-params)))
(value (with-memoization (gethash key table)
(when-let ((v (assoc (symbol-name key)
- erc-server-parameters)))
+ (or erc-server-parameters
+ (erc-with-server-buffer
+ erc-server-parameters)))))
(if (cdr v)
(erc--parse-isupport-value (cdr v))
'--empty--)))))
@@ -2097,6 +2193,22 @@ primitive value."
(when table
(remhash key table))))
+;; While it's better to depend on interfaces than specific types,
+;; using `cl-struct-slot-value' or similar to extract a known slot at
+;; runtime would incur a small "ducktyping" tax, which should probably
+;; be avoided when running dozens of times per incoming message.
+(defmacro erc--with-isupport-data (param var &rest body)
+ "Return structured data stored in VAR for \"ISUPPORT\" PARAM.
+Expect VAR's value to be an instance of `erc--isupport-data'. If
+VAR is uninitialized or stale, evaluate BODY and assign the
+result to VAR."
+ (declare (indent defun))
+ `(erc-with-server-buffer
+ (pcase-let (((,@(list '\` (list param '\, 'key)))
+ (erc--get-isupport-entry ',param)))
+ (or (and ,var (eq key (erc--isupport-data-key ,var)) ,var)
+ (setq ,var (progn ,@body))))))
+
(define-erc-response-handler (005)
"Set the variable `erc-server-parameters' and display the received message.
@@ -2117,8 +2229,11 @@ A server may send more than one 005 message."
key
value
negated)
- (when (string-match "^\\([A-Z]+\\)=\\(.*\\)$\\|^\\(-\\)?\\([A-Z]+\\)$"
- section)
+ (when (string-match
+ (rx bot (| (: (group (+ (any "A-Z"))) "=" (group (* nonl)))
+ (: (? (group "-")) (group (+ (any "A-Z")))))
+ eot)
+ section)
(setq key (or (match-string 1 section) (match-string 4 section))
value (match-string 2 section)
negated (and (match-string 3 section) '-))
@@ -2133,7 +2248,7 @@ A server may send more than one 005 message."
(let* ((nick (car (erc-response.command-args parsed)))
(modes (mapconcat #'identity
(cdr (erc-response.command-args parsed)) " ")))
- (erc-set-modes nick modes)
+ (erc--update-modes (cdr (erc-response.command-args parsed)))
(erc-display-message parsed 'notice 'active 's221 ?n nick ?m modes)))
(define-erc-response-handler (252)
@@ -2299,7 +2414,7 @@ See `erc-display-server-message'." nil
(let ((channel (cadr (erc-response.command-args parsed)))
(modes (mapconcat #'identity (cddr (erc-response.command-args parsed))
" ")))
- (erc-set-modes channel modes)
+ (erc--init-channel-modes channel (cddr (erc-response.command-args parsed)))
(erc-display-message
parsed 'notice (erc-get-buffer channel proc)
's324 ?c channel ?m modes)))
@@ -2371,6 +2486,7 @@ See `erc-display-server-message'." nil
(erc-display-message parsed 'notice (erc-get-buffer channel proc)
's341 ?n nick ?c channel)))
+;; FIXME update or add server user instead when channel is "*".
(define-erc-response-handler (352)
"WHO notice." nil
(pcase-let ((`(,channel ,user ,host ,_server ,nick ,away-flag)
@@ -2436,9 +2552,28 @@ See `erc-display-server-message'." nil
's391 ?s (cadr (erc-response.command-args parsed))
?t (nth 2 (erc-response.command-args parsed))))
+;; https://defs.ircdocs.horse/defs/numerics.html#rpl-visiblehost-396
+;; As of ERC 5.6, if the client hasn't yet joined any channels,
+;; there's a good chance a server user for the current nick simply
+;; doesn't exist (and there's not enough info in this reply to create
+;; one). To fix this, ERC could WHO itself on 372 or similar if it
+;; hasn't yet received a 900.
+(define-erc-response-handler (396)
+ "RPL_VISIBLEHOST or RPL_YOURDISPLAYHOST or RPL_HOSTHIDDEN." nil
+ (pcase-let* ((userhost (cadr (erc-response.command-args parsed)))
+ ;; Behavior blindly copied from event_hosthidden in irssi 1.4.
+ (rejectrx (rx (| (: bot (in ?@ ?: ?-)) (in ?* ?? ?! ?# ?& ?\s)
+ (: ?- eot))))
+ (`(,_ ,user ,host) (and (not (string-match rejectrx userhost))
+ (erc--parse-nuh userhost))))
+ (when host
+ (erc-update-user-nick (erc-current-nick) nil host user)
+ (erc-display-message parsed 'notice 'active 's396 ?s userhost))))
+
(define-erc-response-handler (401)
"No such nick/channel." nil
(let ((nick/channel (cadr (erc-response.command-args parsed))))
+ (defvar erc-whowas-on-nosuchnick)
(when erc-whowas-on-nosuchnick
(erc-log (format "cmd: WHOWAS: %s" nick/channel))
(erc-server-send (format "WHOWAS %s 1" nick/channel)))
@@ -2539,6 +2674,8 @@ See `erc-display-server-message'." nil
"Channel key needed." nil
(erc-display-message parsed '(notice error) nil 's475
?c (cadr (erc-response.command-args parsed)))
+ (defvar erc-prompt-for-channel-key)
+ (defvar erc--called-as-input-p)
(when erc-prompt-for-channel-key
(let ((channel (cadr (erc-response.command-args parsed)))
(erc--called-as-input-p t)
diff --git a/lisp/erc/erc-button.el b/lisp/erc/erc-button.el
index bfaf4fa821a..27406a76f59 100644
--- a/lisp/erc/erc-button.el
+++ b/lisp/erc/erc-button.el
@@ -1,6 +1,6 @@
;;; erc-button.el --- A way of buttonizing certain things in ERC buffers -*- lexical-binding:t -*-
-;; Copyright (C) 1996-2004, 2006-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-2004, 2006-2024 Free Software Foundation, Inc.
;; Author: Mario Lang <mlang@delysid.org>
;; Maintainer: Amin Bandali <bandali@gnu.org>, F. Jason Park <jp@neverwas.me>
@@ -70,6 +70,11 @@
"ERC button face."
:group 'erc-faces)
+(defface erc-button-nick-default-face '((t :inherit erc-nick-default-face))
+ "Default face for a buttonized nickname."
+ :package-version '(ERC . "5.6")
+ :group 'erc-faces)
+
(defcustom erc-button-face 'erc-button
"Face used for highlighting buttons in ERC buffers.
@@ -78,8 +83,9 @@ A button is a piece of text that you can activate by pressing
:type 'face
:group 'erc-faces)
-(defcustom erc-button-nickname-face 'erc-nick-default-face
+(defcustom erc-button-nickname-face 'erc-button-nick-default-face
"Face used for ERC nickname buttons."
+ :package-version '(ERC . "5.6")
:type 'face
:group 'erc-faces)
@@ -189,7 +195,7 @@ CALLBACK is the function to call when the user push this button.
PAR is a number of a regexp grouping whose text will be passed to
CALLBACK. There can be several PAR arguments."
- :package-version '(ERC . "5.6") ; FIXME sync on release
+ :package-version '(ERC . "5.6")
:type '(repeat
(list :tag "Button"
(choice :tag "Matches"
@@ -216,6 +222,9 @@ PAR is a number of a regexp grouping whose text will be passed to
"URL of the EmacsWiki ELisp area."
:type 'string)
+(defvar erc-button-highlight-nick-once '(QUIT PART JOIN)
+ "Messages for which to buttonize only the first nick occurrence.")
+
(defvar erc-button-keymap
(let ((map (make-sparse-keymap)))
(define-key map (kbd "RET") #'erc-button-press-button)
@@ -357,13 +366,14 @@ specified by `erc-button-alist'."
( user nil :type (or null erc-server-user)
;; Not necessarily present in `erc-server-users'.
:documentation "A possibly nil or spoofed `erc-server-user'.")
- ( cuser nil :type (or null erc-channel-user)
- ;; The CDR of a value from an `erc-channel-users' table.
+ ( cusr nil :type (or null erc-channel-user)
+ ;; The CDR of a value from an `erc-channel-members' table.
:documentation "A possibly nil `erc-channel-user'.")
( nickname-face erc-button-nickname-face :type symbol
:documentation "Temp `erc-button-nickname-face' while buttonizing.")
( mouse-face erc-button-mouse-face :type symbol
- :documentation "Temp `erc-button-mouse-face' while buttonizing."))
+ :documentation "Function to return possibly cached face.")
+ ( face-cache nil :type (or null function)))
;; This variable is intended to serve as a "core" to be wrapped by
;; (built-in) modules during setup. It's unclear whether
@@ -380,32 +390,48 @@ buttonizing ought to proceed and nil otherwise. While running,
all faces defined in `erc-button' are bound temporarily and can
be updated at will.")
-(defvar-local erc-button--phantom-users nil)
+(defvar-local erc-button--phantom-cmems nil)
-(defvar erc-button--fallback-user-function #'ignore
- "Function to determine `erc-server-user' if not found in the usual places.
-Called with DOWNCASED-NICK, NICK, and NICK-BOUNDS when
+(defvar erc-button--fallback-cmem-function
+ #'erc-button--get-user-from-spkr-prop
+ "Function to determine channel member if not found in the usual places.
+Called with DOWNCASED-NICK, NICK, NICK-BOUNDS, and COUNT when
`erc-button-add-nickname-buttons' cannot find a user object for
-DOWNCASED-NICK in `erc-channel-users' or `erc-server-users'.")
+DOWNCASED-NICK in `erc-channel-members' or `erc-server-users'.
+NICK-BOUNDS is a cons of buffer positions, and COUNT is a number
+incremented with each visit, starting at 1.")
+
+(defun erc-button--get-user-from-spkr-prop (_ _ _ count)
+ "Attempt to obtain an `erc-channel-user' from current \"msg props\".
+But only do so when COUNT is 1, meaning this is the first button
+candidate in the just-inserted message."
+ (and-let* (((= 1 count))
+ (nick (erc--check-msg-prop 'erc--spkr)))
+ (gethash nick erc-channel-members)))
+
+;; Historical or fictitious users. As long as these two structs
+;; remain superficial "subclasses" with the same slots and defaults,
+;; they can live here instead of in erc-common.el.
+(cl-defstruct (erc--phantom-channel-user (:include erc-channel-user)))
+(cl-defstruct (erc--phantom-server-user (:include erc-server-user)))
(defun erc-button--add-phantom-speaker (downcased nuh _parsed)
- "Stash fictitious `erc-server-user' while processing \"PRIVMSG\".
-Expect DOWNCASED to be the downcased nickname, NUH to be a triple
-of (NICK LOGIN HOST), and parsed to be an `erc-response' object."
(pcase-let* ((`(,nick ,login ,host) nuh)
- (user (or (gethash downcased erc-button--phantom-users)
- (make-erc-server-user
+ (cmem (gethash downcased erc-button--phantom-cmems))
+ (user (or (car cmem)
+ (make-erc--phantom-server-user
:nickname nick
:host (and (not (string-empty-p host)) host)
- :login (and (not (string-empty-p login)) login)))))
- (list (puthash downcased user erc-button--phantom-users))))
+ :login (and (not (string-empty-p login)) login))))
+ (cuser (or (cdr cmem)
+ (make-erc--phantom-channel-user
+ :last-message-time (current-time)))))
+ (puthash downcased (cons user cuser) erc-button--phantom-cmems)
+ (cons user cuser)))
-(defun erc-button--get-phantom-user (down _word _bounds)
- (gethash down erc-button--phantom-users))
+(defun erc-button--get-phantom-cmem (down _word _bounds _count)
+ (gethash down erc-button--phantom-cmems))
-;; In the future, we'll most likely create temporary
-;; `erc-channel-users' tables during BATCH chathistory playback, thus
-;; obviating the need for this mode entirely.
(define-minor-mode erc-button--phantom-users-mode
"Minor mode to recognize unknown speakers.
Expect to be used by module setup code for creating placeholder
@@ -415,22 +441,22 @@ appeared in a prior \"353\" message and are thus a known member
of the channel. However, don't bother creating an actual
`erc-channel-user' object because their status prefix is unknown.
Instead, just spoof an `erc-server-user' and stash it during
-\"PRIVMSG\" handling via `erc--user-from-nick-function' and
+\"PRIVMSG\" handling via `erc--cmem-from-nick-function' and
retrieve it during buttonizing via
`erc-button--fallback-user-function'."
:interactive nil
(if erc-button--phantom-users-mode
(progn
- (add-function :after-until (local 'erc--user-from-nick-function)
- #'erc-button--add-phantom-speaker '((depth . -50)))
- (add-function :after-until (local 'erc-button--fallback-user-function)
- #'erc-button--get-phantom-user '((depth . 50)))
- (setq erc-button--phantom-users (make-hash-table :test #'equal)))
- (remove-function (local 'erc--user-from-nick-function)
+ (add-function :after-until (local 'erc--cmem-from-nick-function)
+ #'erc-button--add-phantom-speaker '((depth . 30)))
+ (add-function :after-until (local 'erc-button--fallback-cmem-function)
+ #'erc-button--get-phantom-cmem '((depth . 50)))
+ (setq erc-button--phantom-cmems (make-hash-table :test #'equal)))
+ (remove-function (local 'erc--cmem-from-nick-function)
#'erc-button--add-phantom-speaker)
- (remove-function (local 'erc-button--fallback-user-function)
- #'erc-button--get-phantom-user)
- (kill-local-variable 'erc-nicks--phantom-users)))
+ (remove-function (local 'erc-button--fallback-cmem-function)
+ #'erc-button--get-phantom-cmem)
+ (kill-local-variable 'erc-button--phantom-cmems)))
(defun erc-button-add-nickname-buttons (entry)
"Search through the buffer for nicknames, and add buttons."
@@ -441,36 +467,37 @@ retrieve it during buttonizing via
(and erc-button-buttonize-nicks
erc-button--modify-nick-function)))
(erc-button--extract-form form)))
+ (oncep (if-let ((erc-button-highlight-nick-once)
+ (c (erc--check-msg-prop 'erc--cmd))
+ ((memq c erc-button-highlight-nick-once)))
+ 1 0))
(seen 0))
(goto-char (point-min))
(while-let
- (((erc-forward-word))
+ (((or (zerop seen) (zerop oncep)))
+ ((erc-forward-word))
(bounds (or (and (= 1 (cl-incf seen)) (erc--get-speaker-bounds))
(erc-bounds-of-word-at-point)))
(word (buffer-substring-no-properties (car bounds) (cdr bounds)))
(down (erc-downcase word)))
- (let* ((erc-button-mouse-face erc-button-mouse-face)
- (erc-button-nickname-face erc-button-nickname-face)
- (cuser (and erc-channel-users (gethash down erc-channel-users)))
- (user (or (and cuser (car cuser))
- (and erc-server-users (gethash down erc-server-users))
- (funcall erc-button--fallback-user-function
- down word bounds)))
+ (let* ((nick-obj t)
+ (cmem (and erc-channel-members
+ (or (gethash down erc-channel-members)
+ (funcall erc-button--fallback-cmem-function
+ down word bounds seen))))
+ (user (or (and cmem (car cmem))
+ (and erc-server-users (gethash down erc-server-users))))
(data (list word)))
(when (or (not (functionp form))
- (and-let* ((user)
- (obj (funcall form (make-erc-button--nick
- :bounds bounds :data data
- :downcased down :user user
- :cuser (cdr cuser)))))
- (setq erc-button-mouse-face ; might be null
- (erc-button--nick-mouse-face obj)
- erc-button-nickname-face ; might be null
- (erc-button--nick-nickname-face obj)
- data (erc-button--nick-data obj)
- bounds (erc-button--nick-bounds obj))))
+ (and user
+ (setq nick-obj (funcall form (make-erc-button--nick
+ :bounds bounds :data data
+ :downcased down :user user
+ :cusr (cdr cmem)))
+ data (erc-button--nick-data nick-obj)
+ bounds (erc-button--nick-bounds nick-obj))))
(erc-button-add-button (car bounds) (cdr bounds) (nth 3 entry)
- 'nickp data))))))
+ nick-obj data))))))
(defun erc-button-add-buttons-1 (regexp entry)
"Search through the buffer for matches to ENTRY and add buttons."
@@ -529,13 +556,20 @@ REGEXP is the regular expression which matched for this button."
(move-marker pos (point))))))
(if nick-p
(when erc-button-nickname-face
- (erc-button-add-face from to erc-button-nickname-face))
+ (erc--merge-prop from to 'font-lock-face
+ (if (erc-button--nick-p nick-p)
+ (erc-button--nick-nickname-face nick-p)
+ erc-button-nickname-face)
+ nil (and (erc-button--nick-p nick-p)
+ (erc-button--nick-face-cache nick-p))))
(when erc-button-face
- (erc-button-add-face from to erc-button-face)))
+ (erc--merge-prop from to 'font-lock-face erc-button-face)))
(add-text-properties
from to
- (nconc (and erc-button-mouse-face
- (list 'mouse-face erc-button-mouse-face))
+ (nconc (and-let* ((face (or (and (erc-button--nick-p nick-p)
+ (erc-button--nick-mouse-face nick-p))
+ erc-button-mouse-face)))
+ (list 'mouse-face face))
(list 'erc-callback fun)
(list 'keymap erc-button-keymap)
(list 'rear-nonsticky t)
@@ -707,7 +741,7 @@ Examples:
(format
\"ldapsearch -x -P 2 -h db.debian.org -b dc=debian,dc=org ircnick=%s\"
nick)))"
- :package-version '(ERC . "5.6") ; FIXME sync on release
+ :package-version '(ERC . "5.6")
:type '(repeat (cons (string :tag "Op")
(choice function sexp))))
@@ -727,11 +761,11 @@ In server buffers, also prompt for a channel."
(erc-get-channel-user nick)))
t nil t (caar targets))))
nick
- (read-from-minibuffer "Reason: ")))
+ (read-string "Reason: ")))
(defun erc-button-cmd-MSG (nick)
"Prompt for a message to NICK, and send it via `erc-cmd-MSG'."
- (let ((msg (read-from-minibuffer (concat "Message to " nick ": "))))
+ (let ((msg (read-string (concat "Message to " nick ": "))))
(erc-cmd-MSG (concat nick " " msg))))
(defvar-local erc-button--nick-popup-alist nil
@@ -787,33 +821,34 @@ and `apropos' for other symbols."
(erc-button-add-button from (point) fun nick-p data regexp)))
;;;###autoload
-(defun erc-button--display-error-notice-with-keys (&optional parsed buffer
- &rest strings)
+(defun erc-button--display-error-notice-with-keys (maybe-buffer &rest strings)
"Add help keys to STRINGS for configuration-related admonishments.
-Return inserted result. Expect PARSED to be an `erc-response'
-object, a string, or nil. Expect BUFFER to be a buffer, a string,
-or nil. As a special case, allow PARSED to be a buffer as long
-as BUFFER is a string or nil. If STRINGS contains any trailing
+Return inserted result. Expect MAYBE-BUFFER to be an ERC buffer,
+a string, or nil. When it's a buffer, specify the `buffer'
+argument when calling `erc-display-message'. Otherwise, add it
+to STRINGS. If STRINGS contains any trailing non-nil
non-strings, concatenate leading string members before applying
`format'. Otherwise, just concatenate everything."
- (when (stringp buffer)
- (push buffer strings)
- (setq buffer nil))
- (when (stringp parsed)
- (push parsed strings)
- (setq parsed nil))
- (when (bufferp parsed)
- (cl-assert (null buffer))
- (setq buffer parsed
- parsed nil))
- (let* ((op (if (seq-every-p #'stringp (cdr strings))
+ (defvar erc-stamp--skip)
+ (let* ((buffer (if (bufferp maybe-buffer)
+ maybe-buffer
+ (when (stringp maybe-buffer)
+ (push maybe-buffer strings))
+ 'active))
+ (op (if (seq-every-p (lambda (o) (or (not o) (stringp o)))
+ (cdr strings))
#'concat
(let ((head (pop strings)))
- (while (stringp (car strings))
+ (while (or (stringp (car strings))
+ (and strings (not (car strings))))
(setq head (concat head (pop strings))))
(push head strings))
#'format))
(string (apply op strings))
+ ;; Avoid timestamps unless left-sided.
+ (erc-stamp--skip (or (bound-and-true-p erc-stamp--display-margin-mode)
+ (not (fboundp 'erc-timestamp-offset))
+ (zerop (erc-timestamp-offset))))
(erc-insert-post-hook
(cons (lambda ()
(setq string (buffer-substring (point-min)
@@ -824,7 +859,7 @@ non-strings, concatenate leading string members before applying
erc-button--display-error-with-buttons
erc-button-describe-symbol 1)
,@erc-button-alist)))
- (erc-display-message parsed '(t notice error) (or buffer 'active) string)
+ (erc-display-message nil '(t notice error) buffer string)
string))
;;;###autoload
@@ -837,8 +872,8 @@ non-strings, concatenate leading string members before applying
(with-syntax-table lisp-mode-syntax-table
(skip-syntax-forward "^-"))
(forward-char)
- (display-warning
- 'erc (buffer-substring-no-properties (point) (point-max))))))
+ (erc--lwarn
+ 'erc :warning (buffer-substring-no-properties (point) (point-max))))))
(provide 'erc-button)
diff --git a/lisp/erc/erc-capab.el b/lisp/erc/erc-capab.el
index bb0921da7f0..ca86e88fccb 100644
--- a/lisp/erc/erc-capab.el
+++ b/lisp/erc/erc-capab.el
@@ -1,6 +1,6 @@
;;; erc-capab.el --- support for dancer-ircd and hyperion's CAPAB -*- lexical-binding: t; -*-
-;; Copyright (C) 2006-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2006-2024 Free Software Foundation, Inc.
;; Maintainer: Amin Bandali <bandali@gnu.org>, F. Jason Park <jp@neverwas.me>
diff --git a/lisp/erc/erc-common.el b/lisp/erc/erc-common.el
index 08c11d518a8..b8ba0673355 100644
--- a/lisp/erc/erc-common.el
+++ b/lisp/erc/erc-common.el
@@ -1,6 +1,6 @@
;;; erc-common.el --- Macros and types for ERC -*- lexical-binding:t -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;;
;; Maintainer: Amin Bandali <bandali@gnu.org>, F. Jason Park <jp@neverwas.me>
;; Keywords: comm, IRC, chat, client, internet
@@ -29,9 +29,7 @@
(defvar erc--casemapping-rfc1459)
(defvar erc--casemapping-rfc1459-strict)
(defvar erc-channel-users)
-(defvar erc-dbuf)
(defvar erc-insert-this)
-(defvar erc-log-p)
(defvar erc-modules)
(defvar erc-send-this)
(defvar erc-server-process)
@@ -51,7 +49,7 @@
(declare-function widget-type "wid-edit" (widget))
(cl-defstruct erc-input
- string insertp sendp refoldp)
+ string insertp sendp)
(cl-defstruct (erc--input-split (:include erc-input
(string :read-only)
@@ -59,7 +57,9 @@
(sendp (with-suppressed-warnings
((obsolete erc-send-this))
erc-send-this))))
+ (refoldp nil :type boolean)
(lines nil :type (list-of string))
+ (abortp nil :type (list-of symbol))
(cmdp nil :type boolean))
(cl-defstruct (erc-server-user (:type vector) :named)
@@ -68,8 +68,23 @@
;; Buffers
(buffers nil))
-(cl-defstruct (erc-channel-user (:type vector) :named)
- voice halfop op admin owner
+(cl-defstruct (erc-channel-user (:type vector)
+ (:constructor
+ erc-channel-user--make
+ (&key (status 0) (last-message-time nil)))
+ (:constructor
+ make-erc-channel-user
+ ( &key voice halfop op admin owner
+ last-message-time
+ &aux (status (+ (if voice 1 0)
+ (if halfop 2 0)
+ (if op 4 0)
+ (if admin 8 0)
+ (if owner 16 0)))))
+ :named)
+ "Object containing channel-specific data for a single user."
+ ;; voice halfop op admin owner
+ (status 0 :type integer)
;; Last message time (in the form of the return value of
;; (current-time)
;;
@@ -80,16 +95,13 @@
(string "" :type string :documentation "Received name of target.")
(symbol nil :type symbol :documentation "Case-mapped name as symbol."))
-;; At some point, it may make sense to add a query type with an
-;; account field, which may help support reassociation across
-;; reconnects and nick changes (likely requires v3 extensions).
-;;
-;; These channel variants should probably take on a `joined' field to
-;; track "joinedness", which `erc-server-JOIN', `erc-server-PART',
-;; etc. should toggle. Functions like `erc--current-buffer-joined-p'
-;; may find it useful.
+;; At some point, it may make sense to add a separate query type,
+;; possibly with an account field to help reassociation across
+;; reconnects and nick changes.
+
+(cl-defstruct (erc--target-channel (:include erc--target))
+ (joined-p nil :type boolean :documentation "Whether channel is joined."))
-(cl-defstruct (erc--target-channel (:include erc--target)))
(cl-defstruct (erc--target-channel-local (:include erc--target-channel)))
;; Beginning in 5.5/29.1, the `tags' field may take on one of two
@@ -103,6 +115,41 @@
(contents "" :type string)
(tags '() :type list))
+(cl-defstruct (erc--ctcp-response
+ (:include erc-response)
+ (:constructor
+ erc--ctcp-response-from-parsed
+ (&key parsed buffer statusmsg prefix dispname
+ &aux (unparsed (erc-response.unparsed parsed))
+ (sender (erc-response.sender parsed))
+ (command (erc-response.command parsed))
+ (command-args (erc-response.command-args parsed))
+ (contents (erc-response.contents parsed))
+ (tags (erc-response.tags parsed)))))
+ "Data for a processed CTCP query or reply."
+ (buffer nil :type (or buffer null))
+ (statusmsg nil :type (or null string))
+ (prefix nil :type (or erc-channel-user null))
+ (dispname nil :type (or string null)))
+
+(cl-defstruct erc--isupport-data
+ "Abstract \"class\" for parsed ISUPPORT data.
+For use with the macro `erc--with-isupport-data'."
+ (key nil :type (or null cons)))
+
+(cl-defstruct (erc--parsed-prefix (:include erc--isupport-data))
+ "Server-local data for recognized membership-status prefixes.
+Derived from the advertised \"PREFIX\" ISUPPORT parameter."
+ (letters "qaohv" :type string)
+ (statuses "~&@%+" :type string)
+ (alist nil :type (list-of cons)))
+
+(cl-defstruct (erc--channel-mode-types (:include erc--isupport-data))
+ "Server-local \"CHANMODES\" data."
+ (fallbackp nil :type boolean)
+ (table (make-char-table 'erc--channel-mode-types) :type char-table)
+ (shortargs (make-hash-table :test #'equal)))
+
;; After dropping 28, we can use prefixed "erc-autoload" cookies.
(defun erc--normalize-module-symbol (symbol)
"Return preferred SYMBOL for `erc--modules'."
@@ -270,18 +317,20 @@ instead of a `set' state, which precludes any actual saving."
" above."))))))
(defun erc--fill-module-docstring (&rest strings)
+ "Concatenate STRINGS and fill as a doc string."
+ ;; Perhaps it's better to mimic `internal--format-docstring-line'
+ ;; and use basic filling instead of applying a major mode?
(with-temp-buffer
- (emacs-lisp-mode)
- (insert "(defun foo ()\n"
- (format "%S" (apply #'concat strings))
- "\n(ignore))")
+ (delay-mode-hooks
+ (if (fboundp 'lisp-data-mode) (lisp-data-mode) (emacs-lisp-mode)))
+ (insert (format "%S" (apply #'concat strings)))
(goto-char (point-min))
- (forward-line 2)
- (let ((emacs-lisp-docstring-fill-column 65)
+ (forward-line)
+ (let ((fill-column 65)
(sentence-end-double-space t))
(fill-paragraph))
(goto-char (point-min))
- (nth 3 (read (current-buffer)))))
+ (read (current-buffer))))
(defmacro erc--find-feature (name alias)
`(pcase (erc--find-group ',name ,(and alias (list 'quote alias)))
@@ -424,6 +473,13 @@ nil."
,@forms))
,process)))
+(defvar-local erc--target nil
+ "A permanent `erc--target' struct instance in channel and query buffers.")
+
+(define-inline erc-target ()
+ "Return target of current buffer, if any, as a string."
+ (inline-quote (and erc--target (erc--target-string erc--target))))
+
(defun erc-log-aux (string)
"Do the debug logging of STRING."
(let ((cb (current-buffer))
@@ -433,6 +489,7 @@ nil."
(if session-buffer
(progn
(set-buffer session-buffer)
+ (defvar erc-dbuf)
(if (not (and erc-dbuf (bufferp erc-dbuf) (buffer-live-p erc-dbuf)))
(progn
(setq erc-dbuf (get-buffer-create
@@ -448,6 +505,9 @@ nil."
(set-buffer cb))
(message "ERC: ** %s" string))))
+(defvar erc-log-p nil
+ "When non-nil, generate debug messages in an \"*ERC-DEBUG*\" buffer.")
+
(define-inline erc-log (string)
"Logs STRING if logging is on (see `erc-log-p')."
(inline-quote
@@ -463,24 +523,79 @@ Use the CASEMAPPING ISUPPORT parameter to determine the style."
(_ erc--casemapping-rfc1459))
(downcase string)))
-(define-inline erc-get-channel-user (nick)
- "Find NICK in the current buffer's `erc-channel-users' hash table."
+(define-inline erc-get-channel-member (nick)
+ "Find NICK in the current buffer's `erc-channel-members' hash table."
(inline-quote (gethash (erc-downcase ,nick) erc-channel-users)))
+(defalias 'erc-get-channel-user #'erc-get-channel-member)
(define-inline erc-get-server-user (nick)
"Find NICK in the current server's `erc-server-users' hash table."
(inline-letevals (nick)
- (inline-quote (erc-with-server-buffer
- (gethash (erc-downcase ,nick) erc-server-users)))))
+ (inline-quote
+ (gethash (erc-downcase ,nick)
+ (erc-with-server-buffer erc-server-users)))))
(defmacro erc--with-dependent-type-match (type &rest features)
"Massage Custom :type TYPE with :match function that pre-loads FEATURES."
- `(backquote (,(car type)
- :match
- ,(list '\, `(lambda (w v)
+ `(backquote-list* ',(car type)
+ :match (lambda (w v)
,@(mapcar (lambda (ft) `(require ',ft)) features)
- (,(widget-get (widget-convert type) :match) w v)))
- ,@(cdr type))))
+ (,(widget-get (widget-convert type) :match) w v))
+ ',(cdr type)))
+
+;; This internal variant exists as a transition aid to avoid
+;; immediately having to reflow lengthy definition lists, like the one
+;; in erc.el. These sites should switch to using the public macro
+;; when undergoing their next major edit.
+(defmacro erc--define-catalog (name entries)
+ "Define `erc-display-message' formatting templates for NAME, a symbol.
+
+See `erc-define-message-format-catalog' for the meaning of
+ENTRIES, an alist, and `erc-tests-common-pp-propertized-parts' in
+tests/lisp/erc/erc-tests.el for a convenience command to convert
+a literal string into a sequence of `propertize' forms, which are
+much easier to review and edit."
+ (declare (indent 1))
+ (let (out)
+ (dolist (e entries (cons 'progn (nreverse out)))
+ (push `(defvar ,(intern (format "erc-message-%s-%s" name (car e)))
+ ,(cdr e)
+ ,(let* ((first (format "Message template for key `%s'" (car e)))
+ (last (format "catalog `%s'." name))
+ (combined (concat first " in " last)))
+ (if (< (length combined) 80)
+ combined
+ (concat first ".\nFor use with " last))))
+ out))))
+
+(defmacro erc-define-message-format-catalog (language &rest entries)
+ "Define message-formatting templates for LANGUAGE, a symbol.
+Expect ENTRIES to be pairs of (KEY . FORMAT), where KEY is a
+symbol, and FORMAT evaluates to a format string compatible with
+`format-spec'. Expect modules that only define a handful of
+entries to do so manually, instead of using this macro, so that
+the resulting variables will end up with more useful doc strings."
+ (declare (indent 1))
+ `(erc--define-catalog ,language ,entries))
+
+(defmacro erc--doarray (spec &rest body)
+ "Map over ARRAY, running BODY with VAR bound to iteration element.
+Behave more or less like `seq-doseq', but tailor operations for
+arrays.
+
+\(fn (VAR ARRAY [RESULT]) BODY...)"
+ (declare (indent 1) (debug ((symbolp form &optional form) body)))
+ (let ((array (make-symbol "array"))
+ (len (make-symbol "len"))
+ (i (make-symbol "i")))
+ `(let* ((,array ,(nth 1 spec))
+ (,len (length ,array))
+ (,i 0))
+ (while-let (((< ,i ,len))
+ (,(car spec) (aref ,array ,i)))
+ ,@body
+ (cl-incf ,i))
+ ,(nth 2 spec))))
(provide 'erc-common)
diff --git a/lisp/erc/erc-compat.el b/lisp/erc/erc-compat.el
index 109b5d245ab..dede833a93d 100644
--- a/lisp/erc/erc-compat.el
+++ b/lisp/erc/erc-compat.el
@@ -1,6 +1,6 @@
;;; erc-compat.el --- ERC compatibility code for older Emacsen -*- lexical-binding: t; -*-
-;; Copyright (C) 2002-2003, 2005-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2003, 2005-2024 Free Software Foundation, Inc.
;; Author: Alex Schroeder <alex@gnu.org>
;; Maintainer: Amin Bandali <bandali@gnu.org>, F. Jason Park <jp@neverwas.me>
@@ -444,6 +444,41 @@ If START or END is negative, it counts from the end."
(cons '("\\`irc6?s?://" . erc-compat--29-browse-url-irc)
existing))))))
+;; We can't store (TICKS . HZ) style timestamps on 27 and 28 because
+;; `time-less-p' and friends do
+;;
+;; message("obsolete timestamp with cdr ...", ...)
+;; decode_lisp_time(_, WARN_OBSOLETE_TIMESTAMPS, ...)
+;; lisp_time_struct(...)
+;; time_cmp(...)
+;;
+;; which spams *Messages* (and stderr when running the test suite).
+(defmacro erc-compat--current-lisp-time ()
+ "Return `current-time' as a (TICKS . HZ) pair on 29+."
+ (if (>= emacs-major-version 29)
+ '(let (current-time-list) (current-time))
+ '(current-time)))
+
+(defmacro erc-compat--defer-format-spec-in-buffer (&rest spec)
+ "Transform SPEC forms into functions that run in the current buffer.
+For convenience, ensure function wrappers return \"\" as a
+fallback."
+ (cl-check-type (car spec) cons)
+ (let ((buffer (make-symbol "buffer")))
+ `(let ((,buffer (current-buffer)))
+ ,(list '\`
+ (mapcar
+ (pcase-lambda (`(,k . ,v))
+ (cons k
+ (list '\,(if (>= emacs-major-version 29)
+ `(lambda ()
+ (or (if (eq ,buffer (current-buffer))
+ ,v
+ (with-current-buffer ,buffer
+ ,v))
+ ""))
+ `(or ,v "")))))
+ spec)))))
(provide 'erc-compat)
diff --git a/lisp/erc/erc-dcc.el b/lisp/erc/erc-dcc.el
index f05ae41fc51..522973a0156 100644
--- a/lisp/erc/erc-dcc.el
+++ b/lisp/erc/erc-dcc.el
@@ -1,6 +1,6 @@
;;; erc-dcc.el --- CTCP DCC module for ERC -*- lexical-binding: t; -*-
-;; Copyright (C) 1993-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1993-2024 Free Software Foundation, Inc.
;; Author: Ben A. Mesander <ben@gnu.ai.mit.edu>
;; Noah Friedman <friedman@prep.ai.mit.edu>
@@ -131,9 +131,8 @@ Looks like:
(open-network-stream procname buffer addr port
:type (and (plist-get entry :secure) 'tls))))
-(erc-define-catalog
- 'english
- '((dcc-chat-discarded
+(erc--define-catalog english
+ ((dcc-chat-discarded
. "DCC: previous chat request from %n (%u@%h) discarded")
(dcc-chat-ended . "DCC: chat with %n ended %t: %e")
(dcc-chat-no-request . "DCC: chat request from %n not found")
@@ -714,8 +713,8 @@ It extracts the information about the dcc request and adds it to
(port (match-string 4 query))
(size (match-string 5 query))
(sub (substring (match-string 6 query) 0 -4))
- (secure (seq-contains-p sub ?S #'eq))
- (turbo (seq-contains-p sub ?T #'eq)))
+ (secure (string-search "S" sub))
+ (turbo (string-search "T" sub)))
;; FIXME: a warning really should also be sent
;; if the ip address != the host the dcc sender is on.
(erc-display-message
@@ -1252,14 +1251,16 @@ other client."
(defun erc-dcc-chat-parse-output (proc str)
(save-match-data
(let ((posn 0)
+ (erc--msg-prop-overrides `((erc--spkr . ,erc-dcc-from)))
+ (nick (propertize (erc--speakerize-nick erc-dcc-from)
+ 'font-lock-face 'erc-nick-default-face))
line)
(while (string-match "\n" str posn)
(setq line (substring str posn (match-beginning 0)))
(setq posn (match-end 0))
(erc-display-message
nil nil proc
- 'dcc-chat-privmsg ?n (propertize erc-dcc-from 'font-lock-face
- 'erc-nick-default-face) ?m line))
+ 'dcc-chat-privmsg ?n nick ?m line))
(setq erc-dcc-unprocessed-output (substring str posn)))))
(defun erc-dcc-chat-buffer-killed ()
diff --git a/lisp/erc/erc-desktop-notifications.el b/lisp/erc/erc-desktop-notifications.el
index 5721bc0204a..2e905097f97 100644
--- a/lisp/erc/erc-desktop-notifications.el
+++ b/lisp/erc/erc-desktop-notifications.el
@@ -1,6 +1,6 @@
;;; erc-desktop-notifications.el --- Send notification on PRIVMSG or mentions -*- lexical-binding:t -*-
-;; Copyright (C) 2012-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2012-2024 Free Software Foundation, Inc.
;; Author: Julien Danjou <julien@danjou.info>
;; Maintainer: Amin Bandali <bandali@gnu.org>, F. Jason Park <jp@neverwas.me>
diff --git a/lisp/erc/erc-ezbounce.el b/lisp/erc/erc-ezbounce.el
index 38ac4de5ac7..33d01438819 100644
--- a/lisp/erc/erc-ezbounce.el
+++ b/lisp/erc/erc-ezbounce.el
@@ -1,6 +1,6 @@
;;; erc-ezbounce.el --- Handle EZBounce bouncer commands -*- lexical-binding: t; -*-
-;; Copyright (C) 2002, 2004, 2006-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002, 2004, 2006-2024 Free Software Foundation, Inc.
;; Author: Andreas Fuchs <asf@void.at>
;; Maintainer: Amin Bandali <bandali@gnu.org>, F. Jason Park <jp@neverwas.me>
diff --git a/lisp/erc/erc-fill.el b/lisp/erc/erc-fill.el
index f4835f71278..b91ce007087 100644
--- a/lisp/erc/erc-fill.el
+++ b/lisp/erc/erc-fill.el
@@ -1,6 +1,6 @@
;;; erc-fill.el --- Filling IRC messages in various ways -*- lexical-binding: t; -*-
-;; Copyright (C) 2001-2004, 2006-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2004, 2006-2024 Free Software Foundation, Inc.
;; Author: Andreas Fuchs <asf@void.at>
;; Mario Lang <mlang@delysid.org>
@@ -49,8 +49,8 @@ the channel buffers are filled."
;; other modules. Ideally, this module's processing should happen
;; after "morphological" modifications to a message's text but
;; before superficial decorations.
- ((add-hook 'erc-insert-modify-hook #'erc-fill 40)
- (add-hook 'erc-send-modify-hook #'erc-fill 40))
+ ((add-hook 'erc-insert-modify-hook #'erc-fill 60)
+ (add-hook 'erc-send-modify-hook #'erc-fill 60))
((remove-hook 'erc-insert-modify-hook #'erc-fill)
(remove-hook 'erc-send-modify-hook #'erc-fill)))
@@ -86,10 +86,13 @@ function is called.
A third style resembles static filling but \"wraps\" instead of
fills, thanks to `visual-line-mode' mode, which ERC automatically
-enables when this option is `erc-fill-wrap' or when
-`erc-fill-wrap-mode' is active. Set `erc-fill-static-center' to
-your preferred initial \"prefix\" width. For adjusting the width
-during a session, see the command `erc-fill-wrap-nudge'."
+enables when this option is `erc-fill-wrap' or when the module
+`fill-wrap' is active. Use `erc-fill-static-center' to specify
+an initial \"prefix\" width and `erc-fill-wrap-margin-width'
+instead of `erc-fill-column' for influencing initial message
+width. For adjusting these during a session, see the commands
+`erc-fill-wrap-nudge' and `erc-fill-wrap-refill-buffer'. Read
+more about this style in the doc string for `erc-fill-wrap-mode'."
:type '(choice (const :tag "Variable Filling" erc-fill-variable)
(const :tag "Static Filling" erc-fill-static)
(const :tag "Dynamic word-wrap" erc-fill-wrap)
@@ -110,7 +113,8 @@ https://en.wikipedia.org/wiki/Hanging_indent."
(defcustom erc-fill-variable-maximum-indentation 17
"Don't indent a line after a long nick more than this many characters.
Set to nil to disable."
- :type 'integer)
+ :type '(choice (const :tag "Disable" nil)
+ integer))
(defcustom erc-fill-column 78
"The column at which a filled paragraph is broken."
@@ -124,7 +128,7 @@ However, when `erc-fill-wrap-margin-side' is `left' or
\"resolves\" to `left', ERC uses the width of the prompt if it's
wider on MOTD's end, which really only matters when `erc-prompt'
is a function."
- :package-version '(ERC . "5.6") ; FIXME sync on release
+ :package-version '(ERC . "5.6")
:type '(choice (const nil) integer))
(defcustom erc-fill-wrap-margin-side nil
@@ -132,19 +136,22 @@ is a function."
A value of nil means ERC should decide based on the value of
`erc-insert-timestamp-function', which does not work for
user-defined functions."
- :package-version '(ERC . "5.6") ; FIXME sync on release
+ :package-version '(ERC . "5.6")
:type '(choice (const nil) (const left) (const right)))
-(defcustom erc-fill-line-spacing nil
- "Extra space between messages on graphical displays.
-Its value should be larger than that of the variable
-`line-spacing', if set. When unsure, start with 0.5."
- :package-version '(ERC . "5.6") ; FIXME sync on release
- :type '(choice (const nil) number))
+(defcustom erc-fill-wrap-align-prompt nil
+ "Whether to align the prompt at the common `wrap-prefix'."
+ :package-version '(ERC . "5.6")
+ :type 'boolean)
-(defvar erc-fill--spaced-commands '(PRIVMSG NOTICE)
- "Types of messages to add space between on graphical displays.
-Only considered when `erc-fill-line-spacing' is non-nil.")
+(defvar erc-fill-line-spacing nil
+ "Extra space between messages on graphical displays.
+Its value should probably be larger than that of the variable
+`line-spacing', if non-nil. When unsure, start with 1.0. Note
+that as of ERC 5.6, this feature doesn't combine well with the
+`scrolltobottom' module, which is de facto required when using
+the `fill-wrap' filling style. Users should therefore regard
+this variable as experimental for the time being.")
(defvar-local erc-fill--function nil
"Internal copy of `erc-fill-function'.
@@ -158,23 +165,24 @@ You can put this on `erc-insert-modify-hook' and/or `erc-send-modify-hook'."
(when (or erc-fill--function erc-fill-function)
;; skip initial empty lines
(goto-char (point-min))
- (save-match-data
- (while (and (looking-at "[ \t\n]*$")
- (= (forward-line 1) 0))))
+ ;; Note the following search pattern was altered in 5.6 to adapt
+ ;; to a change in Emacs regexp behavior that turned out to be a
+ ;; regression (which has since been fixed). The patterns appear
+ ;; to be equivalent in practice, so this was left as is (wasn't
+ ;; reverted) to avoid additional git-blame(1)-related churn.
+ (while (and (looking-at (rx bol (* (in " \t")) eol))
+ (zerop (forward-line 1))))
(unless (eobp)
(save-restriction
(narrow-to-region (point) (point-max))
(funcall (or erc-fill--function erc-fill-function))
- (when-let* ((erc-fill-line-spacing)
- (p (point-min)))
+ (when-let ((erc-fill-line-spacing)
+ (p (point-min)))
(widen)
- (when (or (and-let* ((cmd (get-text-property p 'erc-command)))
- (memq cmd erc-fill--spaced-commands))
- (and-let* ((cmd (save-excursion
- (forward-line -1)
- (get-text-property (point)
- 'erc-command))))
- (memq cmd erc-fill--spaced-commands)))
+ (when (or (erc--check-msg-prop 'erc--spkr)
+ (save-excursion
+ (forward-line -1)
+ (erc--get-inserted-msg-prop 'erc--spkr)))
(put-text-property (1- p) p
'line-spacing erc-fill-line-spacing))))))))
@@ -182,15 +190,17 @@ You can put this on `erc-insert-modify-hook' and/or `erc-send-modify-hook'."
"Fills a text such that messages start at column `erc-fill-static-center'."
(save-restriction
(goto-char (point-min))
- (looking-at "^\\(\\S-+\\)")
- (let ((nick (match-string 1)))
+ (when-let (((looking-at "^\\(\\S-+\\)"))
+ ((not (erc--check-msg-prop 'erc--msg 'datestamp)))
+ (nick (match-string 1)))
+ (progn
(let ((fill-column (- erc-fill-column (erc-timestamp-offset)))
(fill-prefix (make-string erc-fill-static-center 32)))
(insert (make-string (max 0 (- erc-fill-static-center
(length nick) 1))
32))
(erc-fill-regarding-timestamp))
- (erc-restore-text-properties))))
+ (erc-restore-text-properties)))))
(defun erc-fill-variable ()
"Fill from `point-min' to `point-max'."
@@ -220,13 +230,11 @@ You can put this on `erc-insert-modify-hook' and/or `erc-send-modify-hook'."
(defvar-local erc-fill--wrap-value nil)
(defvar-local erc-fill--wrap-visual-keys nil)
-(defcustom erc-fill-wrap-use-pixels t
+(defvar erc-fill-wrap-use-pixels t
"Whether to calculate padding in pixels when possible.
A value of nil means ERC should use columns, which may happen
regardless, depending on the Emacs version. This option only
-matters when `erc-fill-wrap-mode' is enabled."
- :package-version '(ERC . "5.6") ; FIXME sync on release
- :type 'boolean)
+matters when `erc-fill-wrap-mode' is enabled.")
(defcustom erc-fill-wrap-visual-keys 'non-input
"Whether to retain keys defined by `visual-line-mode'.
@@ -234,25 +242,90 @@ A value of t tells ERC to use movement commands defined by
`visual-line-mode' everywhere in an ERC buffer along with visual
editing commands in the input area. A value of nil means to
never do so. A value of `non-input' tells ERC to act like the
-value is nil in the input area and t elsewhere. This option only
-plays a role when `erc-fill-wrap-mode' is enabled."
- :package-version '(ERC . "5.6") ; FIXME sync on release
+value is nil in the input area and t elsewhere. See related
+option `erc-fill-wrap-force-screen-line-movement' for behavior
+involving `next-line' and `previous-line'."
+ :package-version '(ERC . "5.6")
:type '(choice (const nil) (const t) (const non-input)))
+(defcustom erc-fill-wrap-force-screen-line-movement '(non-input)
+ "Exceptions for vertical movement by logical line.
+Including a symbol known to `erc-fill-wrap-visual-keys' in this
+set tells `next-line' and `previous-line' to move vertically by
+screen line even if the current `erc-fill-wrap-visual-keys' value
+would normally do otherwise. For example, setting this to
+\\='(nil non-input) disables logical-line movement regardless of
+the value of `erc-fill-wrap-visual-keys'."
+ :package-version '(ERC . "5.6")
+ :type '(set (const nil) (const non-input)))
+
(defcustom erc-fill-wrap-merge t
- "Whether to consolidate messages from the same speaker.
-This tells ERC to omit redundant speaker labels for subsequent
-messages less than a day apart."
- :package-version '(ERC . "5.6") ; FIXME sync on release
+ "Whether to consolidate consecutive messages from the same speaker.
+When non-nil, ERC omits redundant speaker labels for subsequent
+messages less than a day apart. To help distinguish between
+merged messages, see option `erc-fill-wrap-merge-indicator'."
+ :package-version '(ERC . "5.6")
:type 'boolean)
-(defun erc-fill--wrap-move (normal-cmd visual-cmd arg)
- (funcall (pcase erc-fill--wrap-visual-keys
- ('non-input
- (if (>= (point) erc-input-marker) normal-cmd visual-cmd))
- ('t visual-cmd)
- (_ normal-cmd))
- arg))
+(defface erc-fill-wrap-merge-indicator-face
+ '((((min-colors 88) (background light)) :foreground "Gray")
+ (((min-colors 16) (background light)) :foreground "LightGray")
+ (((min-colors 16) (background dark)) :foreground "DimGray")
+ (t :inherit shadow))
+ "ERC `fill-wrap' merge-indicator face."
+ :group 'erc-faces)
+
+(defcustom erc-fill-wrap-merge-indicator nil
+ "Indicator to help distinguish between merged messages.
+Only matters when the option `erc-fill-wrap-merge' is enabled.
+If the first element is the symbol `pre', ERC uses this option to
+generate a replacement for the speaker's name tag. If the first
+element is `post', ERC affixes a short string to the end of the
+previous message. In either case, the second element should be a
+character, like ?>, and the last element a valid face. In
+special cases, you may also specify a cons of either
+aforementioned symbol and a string, which tells ERC not to manage
+the process for you. If unsure, try either of the first two
+presets, both of which replace a continued speaker's name with a
+dot-product-like character in a `shadow'-like face.
+
+Note that as of ERC 5.6, this option is still experimental, and
+changing its value mid-session is not yet supported (though, if
+you must, make sure to run \\[erc-fill-wrap-refill-buffer]
+afterward). Also note that users on versions of Emacs older than
+29.2 may experience a \"glitching\" effect when point resides on
+a \"merged\" message occupying the first or last line in a
+window. If that happens, try replacing `top' with the integer 1
+in the option `recenter-positions' while also maybe adjusting
+`scroll-margin' and/or `scroll-preserve-screen-position' to avoid
+\"dragging\" point when issuing a `scroll-up' or `scroll-down'
+command."
+ :package-version '(ERC . "5.6")
+ :type
+ '(choice (const nil)
+ (const :tag "Leading MIDDLE DOT (U+00B7) as speaker"
+ (pre #xb7 erc-fill-wrap-merge-indicator-face))
+ (const :tag "Leading MIDDLE DOT (U+00B7) sans gap"
+ (pre . #("\u00b7" 0 1 (font-lock-face
+ erc-fill-wrap-merge-indicator-face))))
+ (const :tag "Leading RIGHT-ANGLE BRACKET (>) as speaker"
+ (pre ?> erc-fill-wrap-merge-indicator-face))
+ (const :tag "Trailing PARAGRAPH SIGN (U+00B6)"
+ (post #xb6 erc-fill-wrap-merge-indicator-face))
+ (const :tag "Trailing TILDE (~)"
+ (post ?~ erc-fill-wrap-merge-indicator-face))
+ (cons :tag "User-provided string (advanced)"
+ (choice (const pre) (const post)) string)
+ (list :tag "User-provided character-face pairing"
+ (choice (const pre) (const post)) character face)))
+
+(defun erc-fill--wrap-move (normal-cmd visual-cmd &rest args)
+ (apply (pcase erc-fill--wrap-visual-keys
+ ('non-input
+ (if (>= (point) erc-input-marker) normal-cmd visual-cmd))
+ ('t visual-cmd)
+ (_ normal-cmd))
+ args))
(defun erc-fill--wrap-kill-line (arg)
"Defer to `kill-line' or `kill-visual-line'."
@@ -283,17 +356,23 @@ Basically mimic what `move-beginning-of-line' does with invisible text."
(defun erc-fill--wrap-previous-line (&optional arg try-vscroll)
"Move to ARGth previous logical or screen line."
(interactive "^p\np")
- (if erc-fill--wrap-visual-keys
- (with-no-warnings (previous-line arg try-vscroll))
- (prog1 (previous-logical-line arg try-vscroll)
- (erc-fill--wrap-escape-hidden-speaker))))
+ ;; Return value seems undefined but preserve anyway just in case.
+ (prog1
+ (let ((visp (memq erc-fill--wrap-visual-keys
+ erc-fill-wrap-force-screen-line-movement)))
+ (erc-fill--wrap-move (if visp #'previous-line #'previous-logical-line)
+ #'previous-line
+ arg try-vscroll))
+ (erc-fill--wrap-escape-hidden-speaker)))
(defun erc-fill--wrap-next-line (&optional arg try-vscroll)
"Move to ARGth next logical or screen line."
(interactive "^p\np")
- (if erc-fill--wrap-visual-keys
- (with-no-warnings (next-line arg try-vscroll))
- (next-logical-line arg try-vscroll)))
+ (let ((visp (memq erc-fill--wrap-visual-keys
+ erc-fill-wrap-force-screen-line-movement)))
+ (erc-fill--wrap-move (if visp #'next-line #'next-logical-line)
+ #'next-line
+ arg try-vscroll)))
(defun erc-fill--wrap-end-of-line (arg)
"Defer to `move-end-of-line' or `end-of-visual-line'."
@@ -381,15 +460,26 @@ is 0, reset to value of `erc-fill-wrap-visual-keys'."
(define-erc-module fill-wrap nil
"Fill style leveraging `visual-line-mode'.
This module displays nicks overhanging leftward to a common
-offset, as determined by the option `erc-fill-static-center'. To
-use it, either include `fill-wrap' in `erc-modules' or set
-`erc-fill-function' to `erc-fill-wrap'. Most users will want to
-enable the `scrolltobottom' module as well. Once active, use
+offset, as determined by the option `erc-fill-static-center'.
+And it \"wraps\" messages at a common margin width, as determined
+by the option `erc-fill-wrap-margin-width'. To use it, either
+include `fill-wrap' in `erc-modules' or set `erc-fill-function'
+to `erc-fill-wrap'. Most users will want to enable the
+`scrolltobottom' module as well.
+
+During sessions in which this module is active, use
\\[erc-fill-wrap-nudge] to adjust the width of the indent and the
stamp margin, and use \\[erc-fill-wrap-toggle-truncate-lines] for
cycling between logical- and screen-line oriented command
-movement. Also see related options `erc-fill-line-spacing' and
-`erc-fill-wrap-merge'.
+movement. Similarly, use \\[erc-fill-wrap-refill-buffer] to fix
+alignment problems after running certain commands, like
+`text-scale-adjust'. Also see related stylistic options
+`erc-fill-wrap-merge', and `erc-fill-wrap-merge-indicator'.
+\(Hint: in narrow windows, where is space tight, try setting
+`erc-fill-static-center' to 1. And if you also use the option
+`erc-fill-wrap-merge-indicator', set that to value-menu item
+\"Leading MIDDLE DOT sans gap\" or one of the various
+\"trailing\" items.)
This module imposes various restrictions on the appearance of
timestamps. Most notably, it insists on displaying them in the
@@ -423,9 +513,14 @@ is not recommended."
(or (eq erc-fill-wrap-margin-side 'left)
(eq (default-value 'erc-insert-timestamp-function)
#'erc-insert-timestamp-left)))
+ (when erc-fill-wrap-align-prompt
+ (add-hook 'erc--refresh-prompt-hook
+ #'erc-fill--wrap-indent-prompt nil t))
+ (when erc-stamp--margin-left-p
+ (if erc-fill-wrap-align-prompt
+ (setq erc-stamp--skip-left-margin-prompt-p t)
+ (setq erc--inhibit-prompt-display-property-p t)))
(setq erc-fill--function #'erc-fill-wrap)
- (add-function :after (local 'erc-stamp--insert-date-function)
- #'erc-fill--wrap-stamp-insert-prefixed-date)
(when erc-fill-wrap-merge
(add-hook 'erc-button--prev-next-predicate-functions
#'erc-fill--wrap-merged-button-p nil t))
@@ -436,10 +531,14 @@ is not recommended."
(kill-local-variable 'erc-fill--wrap-value)
(kill-local-variable 'erc-fill--function)
(kill-local-variable 'erc-fill--wrap-visual-keys)
+ (kill-local-variable 'erc-fill--wrap-last-msg)
+ (kill-local-variable 'erc--inhibit-prompt-display-property-p)
+ (kill-local-variable 'erc-fill--wrap-merge-indicator-pre)
+ (kill-local-variable 'erc-fill--wrap-merge-indicator-post)
+ (remove-hook 'erc--refresh-prompt-hook
+ #'erc-fill--wrap-indent-prompt)
(remove-hook 'erc-button--prev-next-predicate-functions
- #'erc-fill--wrap-merged-button-p t)
- (remove-function (local 'erc-stamp--insert-date-function)
- #'erc-fill--wrap-stamp-insert-prefixed-date))
+ #'erc-fill--wrap-merged-button-p t))
'local)
(defvar-local erc-fill--wrap-length-function nil
@@ -453,56 +552,56 @@ behavior of taking the length from the first \"word\". This
variable can be converted to a public one if needed by third
parties.")
-(defvar-local erc-fill--wrap-last-msg nil)
-(defvar-local erc-fill--wrap-max-lull (* 24 60 60))
+(defvar-local erc-fill--wrap-last-msg nil "Marker for merging speakers.")
+(defvar erc-fill--wrap-max-lull (* 24 60 60) "Max secs for merging speakers.")
(defun erc-fill--wrap-continued-message-p ()
- (prog1 (and-let*
- ((m (or erc-fill--wrap-last-msg
- (setq erc-fill--wrap-last-msg (point-min-marker))
- nil))
- ((< (1+ (point-min)) (- (point) 2)))
- (props (save-restriction
- (widen)
- (when (eq 'erc-timestamp (field-at-pos m))
- (set-marker m (field-end m)))
- (and-let*
- (((eq 'PRIVMSG (get-text-property m 'erc-command)))
- ((not (eq (get-text-property m 'erc-ctcp)
- 'ACTION)))
- (spr (next-single-property-change m 'erc-speaker)))
- (cons (get-text-property m 'erc-timestamp)
- (get-text-property spr 'erc-speaker)))))
- (ts (pop props))
- (props)
- ((not (time-less-p (erc-stamp--current-time) ts)))
- ((time-less-p (time-subtract (erc-stamp--current-time) ts)
- erc-fill--wrap-max-lull))
- (speaker (next-single-property-change (point-min) 'erc-speaker))
- ((not (eq (get-text-property speaker 'erc-ctcp) 'ACTION)))
- (nick (get-text-property speaker 'erc-speaker))
- ((erc-nick-equal-p props nick))))
- (set-marker erc-fill--wrap-last-msg (point-min))))
-
-(defun erc-fill--wrap-stamp-insert-prefixed-date (&rest args)
- "Apply `line-prefix' property to args."
- (let* ((ts-left (car args))
- (start)
- ;; Insert " " to simulate gap between <speaker> and msg beg.
- (end (save-excursion (skip-chars-backward "\n")
- (setq start (pos-bol))
- (insert " ")
- (point)))
- (width (if (and erc-fill-wrap-use-pixels
- (fboundp 'buffer-text-pixel-size))
- (save-restriction (narrow-to-region start end)
- (list (car (buffer-text-pixel-size))))
- (length (string-trim-left ts-left)))))
- (delete-region (1- end) end)
- ;; Use `point-min' instead of `start' to cover leading newilnes.
- (put-text-property (point-min) (point) 'line-prefix
- `(space :width (- erc-fill--wrap-value ,width))))
- args)
+ "Return non-nil when the current speaker hasn't changed.
+But only if the `erc--msg' text property also hasn't. That is,
+indicate whether the chat message just inserted is from the same
+person as the prior one and is formatted in the same manner. As
+a side effect, advance `erc-fill--wrap-last-msg' unless the
+message has been marked `erc--ephemeral'."
+ (and-let*
+ (((not (erc--check-msg-prop 'erc--ephemeral)))
+ ;; Always set/move `erc-fill--wrap-last-msg' from here on down.
+ (m (or (and erc-fill--wrap-last-msg
+ (prog1 (marker-position erc-fill--wrap-last-msg)
+ (set-marker erc-fill--wrap-last-msg (point-min))))
+ (ignore (setq erc-fill--wrap-last-msg (point-min-marker)))))
+ ((>= (point) 4)) ; skip the first message
+ (props (save-restriction
+ (widen)
+ (and-let* ((speaker (get-text-property m 'erc--spkr))
+ (type (get-text-property m 'erc--msg))
+ ((not (invisible-p m))))
+ (list (get-text-property m 'erc--ts) type speaker))))
+ (ts (nth 0 props))
+ (type (nth 1 props))
+ (speaker (nth 2 props))
+ ((not (time-less-p (erc-stamp--current-time) ts)))
+ ((time-less-p (time-subtract (erc-stamp--current-time) ts)
+ erc-fill--wrap-max-lull))
+ ((erc--check-msg-prop 'erc--msg type))
+ ((erc-nick-equal-p speaker (erc--check-msg-prop 'erc--spkr))))))
+
+(defun erc-fill--wrap-measure (beg end)
+ "Return display spec width for inserted region between BEG and END.
+Ignore any `invisible' props that may be present when figuring.
+Expect the target region to be free of `line-prefix' and
+`wrap-prefix' properties, and expect `display-line-numbers-mode'
+to be disabled."
+ (if (fboundp 'buffer-text-pixel-size)
+ ;; `buffer-text-pixel-size' can move point!
+ (save-excursion
+ (save-restriction
+ (narrow-to-region beg end)
+ (let* ((buffer-invisibility-spec)
+ (rv (car (buffer-text-pixel-size))))
+ (if erc-fill-wrap-use-pixels
+ (if (zerop rv) 0 (list rv))
+ (/ rv (frame-char-width))))))
+ (- end beg)))
;; An escape hatch for third-party code expecting speakers of ACTION
;; messages to be exempt from `line-prefix'. This could be converted
@@ -510,6 +609,54 @@ parties.")
(defvar erc-fill--wrap-action-dedent-p t
"Whether to dedent speakers in CTCP \"ACTION\" lines.")
+(defvar-local erc-fill--wrap-merge-indicator-pre nil)
+(defvar-local erc-fill--wrap-merge-indicator-post nil)
+
+;; To support `erc-fill-line-spacing' with the "post" variant, we'd
+;; need to use a new "replacing" `display' spec value for each
+;; insertion, and add a sentinel property alongside it atop every
+;; affected newline, e.g., (erc-fill-eol-display START-POS), where
+;; START-POS is the position of the newline in the replacing string.
+;; Then, upon spotting this sentinel in `erc-fill' (and maybe
+;; `erc-fill-wrap-refill-buffer'), we'd add `line-spacing' to the
+;; corresponding `display' replacement, starting at START-POS.
+(defun erc-fill--wrap-insert-merged-post ()
+ "Add `display' property at end of previous line."
+ (save-excursion
+ (goto-char (point-min))
+ (save-restriction
+ (widen)
+ (cl-assert (= ?\n (char-before (point))))
+ (unless erc-fill--wrap-merge-indicator-post
+ (let ((option (cdr erc-fill-wrap-merge-indicator)))
+ (setq erc-fill--wrap-merge-indicator-post
+ (if (stringp option)
+ (concat option
+ (and (not (string-suffix-p "\n" option)) "\n"))
+ (propertize (concat (string (car option)) "\n")
+ 'font-lock-face (cadr option))))))
+ (unless (eq (field-at-pos (- (point) 2)) 'erc-timestamp)
+ (put-text-property (1- (point)) (point)
+ 'display erc-fill--wrap-merge-indicator-post)))
+ 0))
+
+(defun erc-fill--wrap-insert-merged-pre ()
+ "Add `display' property in lieu of speaker."
+ (if erc-fill--wrap-merge-indicator-pre
+ (progn
+ (put-text-property (point-min) (point) 'display
+ (car erc-fill--wrap-merge-indicator-pre))
+ (cdr erc-fill--wrap-merge-indicator-pre))
+ (let* ((option (cdr erc-fill-wrap-merge-indicator))
+ (s (if (stringp option)
+ (concat option)
+ (concat (propertize (string (car option))
+ 'font-lock-face (cadr option))
+ " "))))
+ (put-text-property (point-min) (point) 'display s)
+ (cdr (setq erc-fill--wrap-merge-indicator-pre
+ (cons s (erc-fill--wrap-measure (point-min) (point))))))))
+
(defun erc-fill-wrap ()
"Use text props to mimic the effect of `erc-fill-static'.
See `erc-fill-wrap-mode' for details."
@@ -519,33 +666,135 @@ See `erc-fill-wrap-mode' for details."
(goto-char (point-min))
(let ((len (or (and erc-fill--wrap-length-function
(funcall erc-fill--wrap-length-function))
- (progn
+ (and-let* ((msg-prop (erc--check-msg-prop 'erc--msg))
+ ((not (eq msg-prop 'unknown))))
(when-let ((e (erc--get-speaker-bounds))
(b (pop e))
((or erc-fill--wrap-action-dedent-p
- (not (eq (get-text-property b 'erc-ctcp)
- 'ACTION)))))
+ (not (erc--check-msg-prop 'erc--ctcp
+ 'ACTION)))))
(goto-char e))
(skip-syntax-forward "^-")
(forward-char)
- ;; Using the `invisible' property might make more
- ;; sense, but that would require coordination
- ;; with other modules, like `erc-match'.
- (cond ((and erc-fill-wrap-merge
+ (cond ((eq msg-prop 'datestamp)
+ (when erc-fill--wrap-last-msg
+ (set-marker erc-fill--wrap-last-msg (point-min)))
+ (save-excursion
+ (goto-char (point-max))
+ (skip-chars-backward "\n")
+ (let ((beg (pos-bol)))
+ (insert " ")
+ (prog1 (erc-fill--wrap-measure beg (point))
+ (delete-region (1- (point)) (point))))))
+ ((and erc-fill-wrap-merge
(erc-fill--wrap-continued-message-p))
(put-text-property (point-min) (point)
'display "")
- 0)
- ((and erc-fill-wrap-use-pixels
- (fboundp 'buffer-text-pixel-size))
- (save-restriction
- (narrow-to-region (point-min) (point))
- (list (car (buffer-text-pixel-size)))))
- (t (- (point) (point-min))))))))
- (erc-put-text-properties (point-min) (1- (point-max)) ; exclude "\n"
- '(line-prefix wrap-prefix) nil
- `((space :width (- erc-fill--wrap-value ,len))
- (space :width erc-fill--wrap-value))))))
+ (if erc-fill-wrap-merge-indicator
+ (pcase (car erc-fill-wrap-merge-indicator)
+ ('pre (erc-fill--wrap-insert-merged-pre))
+ ('post (erc-fill--wrap-insert-merged-post)))
+ 0))
+ (t
+ (erc-fill--wrap-measure (point-min) (point))))))))
+ (add-text-properties
+ (point-min) (1- (point-max)) ; exclude "\n"
+ `( line-prefix (space :width ,(if len
+ `(- erc-fill--wrap-value ,len)
+ 'erc-fill--wrap-value))
+ wrap-prefix (space :width erc-fill--wrap-value))))))
+
+(defun erc-fill--wrap-indent-prompt ()
+ "Recompute the `line-prefix' of the prompt."
+ ;; Clear an existing `line-prefix' before measuring (bug#64971).
+ (remove-text-properties erc-insert-marker erc-input-marker
+ '(line-prefix nil wrap-prefix nil))
+ ;; Restoring window configuration seems to prevent unwanted
+ ;; recentering reminiscent of `scrolltobottom'-related woes.
+ (let ((c (and (get-buffer-window) (current-window-configuration)))
+ (len (erc-fill--wrap-measure erc-insert-marker erc-input-marker)))
+ (when c
+ (set-window-configuration c))
+ (put-text-property erc-insert-marker erc-input-marker
+ 'line-prefix
+ `(space :width (- erc-fill--wrap-value ,len)))))
+
+(defvar erc-fill--wrap-rejigger-last-message nil
+ "Temporary working instance of `erc-fill--wrap-last-msg'.")
+
+(defun erc-fill--wrap-rejigger-region (start finish on-next repairp)
+ "Recalculate `line-prefix' from START to FINISH.
+After refilling each message, call ON-NEXT with no args. But
+stash and restore `erc-fill--wrap-last-msg' before doing so, in
+case this module's insert hooks run by way of the process filter.
+With REPAIRP, destructively fill gaps and re-merge speakers."
+ (goto-char start)
+ (cl-assert (null erc-fill--wrap-rejigger-last-message))
+ (setq erc-fill--wrap-merge-indicator-pre nil
+ erc-fill--wrap-merge-indicator-post nil)
+ (let (erc-fill--wrap-rejigger-last-message)
+ (while-let
+ (((< (point) finish))
+ (beg (if (get-text-property (point) 'line-prefix)
+ (point)
+ (next-single-property-change (point) 'line-prefix)))
+ (val (get-text-property beg 'line-prefix))
+ (end (text-property-not-all beg finish 'line-prefix val)))
+ ;; If this is a left-side stamp on its own line.
+ (remove-text-properties beg (1+ end) '(line-prefix nil wrap-prefix nil))
+ (when-let ((repairp)
+ (dbeg (text-property-not-all beg end 'display nil))
+ ((get-text-property (1+ dbeg) 'erc--speaker))
+ (dval (get-text-property dbeg 'display))
+ ((equal "" dval)))
+ (remove-text-properties
+ dbeg (text-property-not-all dbeg end 'display dval) '(display)))
+ ;; This "should" work w/o `front-sticky' and `rear-nonsticky'.
+ (let* ((pos (if-let (((eq 'erc-timestamp (field-at-pos beg)))
+ (b (field-beginning beg))
+ ((eq 'datestamp (get-text-property b 'erc--msg))))
+ b
+ beg))
+ (erc--msg-props (map-into (text-properties-at pos) 'hash-table))
+ (erc-stamp--current-time (gethash 'erc--ts erc--msg-props)))
+ (save-restriction
+ (narrow-to-region beg (1+ end))
+ (let ((erc-fill--wrap-last-msg erc-fill--wrap-rejigger-last-message))
+ (erc-fill-wrap)
+ (setq erc-fill--wrap-rejigger-last-message
+ erc-fill--wrap-last-msg))))
+ (when on-next
+ (funcall on-next))
+ ;; Skip to end of message upon encountering accidental gaps
+ ;; introduced by third parties (or bugs).
+ (if-let (((/= ?\n (char-after end)))
+ (next (erc--get-inserted-msg-end beg)))
+ (progn
+ (cl-assert (= ?\n (char-after next)))
+ (when repairp ; eol <= next
+ (put-text-property end (pos-eol) 'line-prefix val))
+ (goto-char next))
+ (goto-char end)))))
+
+(defun erc-fill-wrap-refill-buffer (repair)
+ "Recalculate all `fill-wrap' prefixes in the current buffer.
+With REPAIR, attempt to refresh \"speaker merges\", which may be
+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."))
+ (save-excursion
+ (with-silent-modifications
+ (let* ((rep (make-progress-reporter
+ "Rewrap" 0 (line-number-at-pos erc-insert-marker) 1))
+ (seen 0)
+ (callback (lambda ()
+ (progress-reporter-update rep (cl-incf seen))
+ (accept-process-output nil 0.000001))))
+ (erc-fill--wrap-rejigger-region (point-min) erc-insert-marker
+ callback repair)
+ (progress-reporter-done rep)))))
;; FIXME use own text property to avoid false positives.
(defun erc-fill--wrap-merged-button-p (point)
diff --git a/lisp/erc/erc-goodies.el b/lisp/erc/erc-goodies.el
index b37855cbecc..c5ab25bea98 100644
--- a/lisp/erc/erc-goodies.el
+++ b/lisp/erc/erc-goodies.el
@@ -1,6 +1,6 @@
;;; erc-goodies.el --- Collection of ERC modules -*- lexical-binding: t; -*-
-;; Copyright (C) 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2024 Free Software Foundation, Inc.
;; Author: Jorgen Schaefer <forcer@forcix.cx>
;; Maintainer: Amin Bandali <bandali@gnu.org>, F. Jason Park <jp@neverwas.me>
@@ -44,42 +44,177 @@
This should be an integer specifying the line of the buffer on which
the input line should stay. A value of \"-1\" would keep the input
line positioned on the last line in the buffer. This is passed as an
-argument to `recenter'."
+argument to `recenter', unless `erc-scrolltobottom-all' is
+`relaxed', in which case, ERC interprets it as additional lines
+to scroll down by per message insertion (minus one for the
+prompt)."
:group 'erc-display
:type '(choice integer (const nil)))
+(defcustom erc-scrolltobottom-all nil
+ "Whether to scroll all windows or just the selected one.
+ERC expects this option to be configured before module
+initialization. A value of nil preserves pre-5.6 behavior, in
+which scrolling only affects the selected window. A value of t
+means ERC attempts to recenter all visible windows whose point
+resides in the input area.
+
+A value of `relaxed' tells ERC to forgo forcing prompt to the
+bottom of the window. When point is at the prompt, ERC scrolls
+the window up when inserting messages, making the prompt appear
+stationary. Users who find this effect too \"stagnant\" can
+adjust the option `erc-input-line-position', borrowed here to
+express a scroll step offset. Setting that value to zero lets
+the prompt drift toward the bottom by one line per message, which
+is generally slow enough not to distract while composing input.
+Of course, this doesn't apply when receiving a large influx of
+messages, such as after typing \"/msg NickServ help\".
+
+Note that users should consider this option's non-nil behavior to
+be experimental. It currently only works with Emacs 28+."
+ :group 'erc-display
+ :package-version '(ERC . "5.6")
+ :type '(choice boolean (const relaxed)))
+
;;;###autoload(autoload 'erc-scrolltobottom-mode "erc-goodies" nil t)
(define-erc-module scrolltobottom nil
"This mode causes the prompt to stay at the end of the window."
- ((add-hook 'erc-mode-hook #'erc-add-scroll-to-bottom)
- (add-hook 'erc-insert-done-hook #'erc-possibly-scroll-to-bottom)
- (unless erc--updating-modules-p (erc-buffer-do #'erc-add-scroll-to-bottom)))
- ((remove-hook 'erc-mode-hook #'erc-add-scroll-to-bottom)
- (remove-hook 'erc-insert-done-hook #'erc-possibly-scroll-to-bottom)
- (dolist (buffer (erc-buffer-list))
- (with-current-buffer buffer
- (remove-hook 'post-command-hook #'erc-scroll-to-bottom t)))))
+ ((add-hook 'erc-mode-hook #'erc--scrolltobottom-setup)
+ (when (and erc-scrolltobottom-all (< emacs-major-version 28))
+ (erc-button--display-error-notice-with-keys
+ "Option `erc-scrolltobottom-all' requires Emacs 28+. Disabling.")
+ (setopt erc-scrolltobottom-all nil))
+ (unless erc--updating-modules-p (erc-buffer-do #'erc--scrolltobottom-setup))
+ (if erc-scrolltobottom-all
+ (progn
+ (add-hook 'erc-insert-pre-hook #'erc--scrolltobottom-on-pre-insert 25)
+ (add-hook 'erc-pre-send-functions #'erc--scrolltobottom-on-pre-insert)
+ (add-hook 'erc-insert-done-hook #'erc--scrolltobottom-all)
+ (add-hook 'erc-send-completed-hook #'erc--scrolltobottom-all))
+ (add-hook 'erc-insert-done-hook #'erc-possibly-scroll-to-bottom)))
+ ((remove-hook 'erc-mode-hook #'erc--scrolltobottom-setup)
+ (erc-buffer-do #'erc--scrolltobottom-setup)
+ (remove-hook 'erc-insert-pre-hook #'erc--scrolltobottom-on-pre-insert)
+ (remove-hook 'erc-send-completed-hook #'erc--scrolltobottom-all)
+ (remove-hook 'erc-insert-done-hook #'erc--scrolltobottom-all)
+ (remove-hook 'erc-pre-send-functions #'erc--scrolltobottom-on-pre-insert)
+ (remove-hook 'erc-insert-done-hook #'erc-possibly-scroll-to-bottom)))
(defun erc-possibly-scroll-to-bottom ()
"Like `erc-add-scroll-to-bottom', but only if window is selected."
(when (eq (selected-window) (get-buffer-window))
(erc-scroll-to-bottom)))
+(defvar-local erc--scrolltobottom-window-info nil
+ "Alist with windows as keys and lists of window-related info as values.
+Values are lists containing the last window start position and
+the last \"window line\" of point. The \"window line\", which
+may be nil, is the number of lines between `window-start' and
+`window-point', inclusive.")
+
+;; FIXME treat `end-of-buffer' specially and always recenter -1.
+;; FIXME make this work when `erc-scrolltobottom-all' is set to
+;; `relaxed'.
+(defvar erc--scrolltobottom-post-ignore-commands '(text-scale-adjust)
+ "Commands to skip instead of force-scroll on `post-command-hook'.")
+
+(defun erc--scrolltobottom-on-post-command ()
+ "Scroll selected window unless `this-command' is exempted."
+ (when (eq (selected-window) (get-buffer-window))
+ (unless (memq this-command erc--scrolltobottom-post-ignore-commands)
+ (setq erc--scrolltobottom-window-info nil)
+ (erc--scrolltobottom-confirm))))
+
+;; It may be desirable to also restore the relative line position of
+;; window point after changing dimensions. Perhaps stashing the
+;; previous ratio of window line to body height and later recentering
+;; proportionally would achieve this.
+(defun erc--scrolltobottom-on-win-conf-change ()
+ "Scroll window to bottom when at prompt and using the minibuffer."
+ (setq erc--scrolltobottom-window-info nil)
+ (erc--scrolltobottom-confirm))
+
+(defun erc--scrolltobottom-all (&rest _)
+ "Maybe put prompt on last line in all windows displaying current buffer.
+Expect to run when narrowing is in effect, such as on insertion
+or send-related hooks. When recentering has not been performed,
+attempt to restore last `window-start', if known."
+ (dolist (window (get-buffer-window-list nil nil 'visible))
+ (with-selected-window window
+ (when-let
+ ((erc--scrolltobottom-window-info)
+ (found (assq window erc--scrolltobottom-window-info))
+ ((not (erc--scrolltobottom-confirm (nth 2 found)))))
+ (set-window-start window (cadr found) 'no-force))))
+ ;; Necessary unless we're sure `erc--scrolltobottom-on-pre-insert'
+ ;; always runs between calls to this function.
+ (setq erc--scrolltobottom-window-info nil))
+
(defun erc-add-scroll-to-bottom ()
"A hook function for `erc-mode-hook' to recenter output at bottom of window.
If you find that ERC hangs when using this function, try customizing
the value of `erc-input-line-position'.
-This works whenever scrolling happens, so it's added to
-`window-scroll-functions' rather than `erc-insert-post-hook'."
+Note that the prior suggestion comes from a time when this
+function used `window-scroll-functions', which was replaced by
+`post-command-hook' in ERC 5.3."
+ (declare (obsolete erc--scrolltobottom-setup "30.1"))
(add-hook 'post-command-hook #'erc-scroll-to-bottom nil t))
+(defun erc--scrolltobottom-setup ()
+ "Perform buffer-local setup for module `scrolltobottom'."
+ (if erc-scrolltobottom-mode
+ (if erc-scrolltobottom-all
+ (progn
+ (setq-local read-minibuffer-restore-windows nil)
+ (when (zerop scroll-conservatively)
+ (setq-local scroll-step 1))
+ (unless (eq erc-scrolltobottom-all 'relaxed)
+ (add-hook 'window-configuration-change-hook
+ #'erc--scrolltobottom-on-win-conf-change 50 t)
+ (add-hook 'post-command-hook
+ #'erc--scrolltobottom-on-post-command 50 t)))
+ (add-hook 'post-command-hook #'erc-scroll-to-bottom nil t))
+ (remove-hook 'post-command-hook #'erc-scroll-to-bottom t)
+ (remove-hook 'post-command-hook #'erc--scrolltobottom-on-post-command t)
+ (remove-hook 'window-configuration-change-hook
+ #'erc--scrolltobottom-on-win-conf-change t)
+ (kill-local-variable 'read-minibuffer-restore-windows)
+ (kill-local-variable 'scroll-step)
+ (kill-local-variable 'erc--scrolltobottom-window-info)))
+
+(defun erc--scrolltobottom-on-pre-insert (_)
+ "Remember `window-start' before inserting a message."
+ (setq erc--scrolltobottom-window-info
+ (mapcar (lambda (w)
+ (list w
+ (window-start w)
+ (and-let*
+ (((eq erc-scrolltobottom-all 'relaxed))
+ (c (count-screen-lines (window-start w)
+ (point-max) nil w)))
+ (if (= ?\n (char-before (point-max))) (1+ c) c))))
+ (get-buffer-window-list nil nil 'visible))))
+
+(defun erc--scrolltobottom-confirm (&optional scroll-to)
+ "Like `erc-scroll-to-bottom', but use `window-point'.
+Position current line (with `recenter') SCROLL-TO lines below
+window's top. Return nil if point is not in prompt area or if
+prompt isn't ready."
+ (when erc-insert-marker
+ (let ((resize-mini-windows nil))
+ (save-restriction
+ (widen)
+ (when (>= (window-point) erc-input-marker)
+ (save-excursion
+ (goto-char (point-max))
+ (recenter (+ (or scroll-to 0) (or erc-input-line-position -1)))
+ t))))))
+
(defun erc-scroll-to-bottom ()
"Recenter WINDOW so that `point' is on the last line.
-This is added to `window-scroll-functions' by `erc-add-scroll-to-bottom'.
-
You can control which line is recentered to by customizing the
variable `erc-input-line-position'."
;; Temporarily bind resize-mini-windows to nil so that users who have it
@@ -102,8 +237,8 @@ variable `erc-input-line-position'."
;;;###autoload(autoload 'erc-readonly-mode "erc-goodies" nil t)
(define-erc-module readonly nil
"This mode causes all inserted text to be read-only."
- ((add-hook 'erc-insert-post-hook #'erc-make-read-only)
- (add-hook 'erc-send-post-hook #'erc-make-read-only))
+ ((add-hook 'erc-insert-post-hook #'erc-make-read-only 70)
+ (add-hook 'erc-send-post-hook #'erc-make-read-only 70))
((remove-hook 'erc-insert-post-hook #'erc-make-read-only)
(remove-hook 'erc-send-post-hook #'erc-make-read-only)))
@@ -135,13 +270,13 @@ Put this function on `erc-insert-post-hook' and/or `erc-send-post-hook'."
(defun erc-move-to-prompt-setup ()
"Initialize the move-to-prompt module."
- (add-hook 'pre-command-hook #'erc-move-to-prompt nil t))
+ (add-hook 'pre-command-hook #'erc-move-to-prompt 70 t))
;;; Keep place in unvisited channels
;;;###autoload(autoload 'erc-keep-place-mode "erc-goodies" nil t)
(define-erc-module keep-place nil
"Leave point above un-viewed text in other channels."
- ((add-hook 'erc-insert-pre-hook #'erc-keep-place))
+ ((add-hook 'erc-insert-pre-hook #'erc-keep-place 65))
((remove-hook 'erc-insert-pre-hook #'erc-keep-place)))
(defcustom erc-keep-place-indicator-style t
@@ -151,21 +286,26 @@ displays an arrow in the left fringe or margin. When it's
`face', ERC adds the face `erc-keep-place-indicator-line' to the
appropriate line. A value of t does both."
:group 'erc
- :package-version '(ERC . "5.6") ; FIXME sync on release
- :type '(choice (const t) (const server) (const target)))
+ :package-version '(ERC . "5.6")
+ :type '(choice (const :tag "Use arrow" arrow)
+ (const :tag "Use face" face)
+ (const :tag "Use both arrow and face" t)))
(defcustom erc-keep-place-indicator-buffer-type t
"ERC buffer type in which to display `keep-place-indicator'.
A value of t means \"all\" ERC buffers."
:group 'erc
- :package-version '(ERC . "5.6") ; FIXME sync on release
+ :package-version '(ERC . "5.6")
:type '(choice (const t) (const server) (const target)))
(defcustom erc-keep-place-indicator-follow nil
"Whether to sync visual kept place to window's top when reading.
-For use with `erc-keep-place-indicator-mode'."
+For use with `erc-keep-place-indicator-mode'. When enabled, the
+indicator updates when the last window displaying the same buffer
+switches away, but only if the indicator resides earlier in the
+buffer than the window's start."
:group 'erc
- :package-version '(ERC . "5.6") ; FIXME sync on release
+ :package-version '(ERC . "5.6")
:type 'boolean)
(defface erc-keep-place-indicator-line
@@ -191,17 +331,26 @@ For use with `erc-keep-place-indicator-mode'."
(defvar-local erc--keep-place-indicator-overlay nil
"Overlay for `erc-keep-place-indicator-mode'.")
-(defun erc--keep-place-indicator-on-window-configuration-change ()
+(defun erc--keep-place-indicator-on-window-buffer-change (window)
"Maybe sync `erc--keep-place-indicator-overlay'.
-Specifically, do so unless switching to or from another window in
-the active frame."
- (when erc-keep-place-indicator-follow
- (unless (or (minibuffer-window-active-p (minibuffer-window))
- (eq (window-old-buffer) (current-buffer)))
- (when (< (overlay-end erc--keep-place-indicator-overlay)
- (window-start)
- erc-insert-marker)
- (erc-keep-place-move (window-start))))))
+Do so only when switching to a new buffer in the same window if
+the replaced buffer is no longer visible in another window and
+its `window-start' at the time of switching is strictly greater
+than the indicator's position."
+ (when-let ((erc-keep-place-indicator-follow)
+ ((eq window (selected-window)))
+ (old-buffer (window-old-buffer window))
+ ((buffer-live-p old-buffer))
+ ((not (eq old-buffer (current-buffer))))
+ (ov (buffer-local-value 'erc--keep-place-indicator-overlay
+ old-buffer))
+ ((not (get-buffer-window old-buffer 'visible)))
+ (prev (assq old-buffer (window-prev-buffers window)))
+ (old-start (nth 1 prev))
+ (old-inmkr (buffer-local-value 'erc-insert-marker old-buffer))
+ ((< (overlay-end ov) old-start old-inmkr)))
+ (with-current-buffer old-buffer
+ (erc-keep-place-move old-start))))
(defun erc--keep-place-indicator-setup ()
"Initialize buffer for maintaining `erc--keep-place-indicator-overlay'."
@@ -210,15 +359,18 @@ the active frame."
erc--keep-place-indicator-overlay (make-overlay 0 0))
(add-hook 'erc-keep-place-mode-hook
#'erc--keep-place-indicator-on-global-module nil t)
- (add-hook 'window-configuration-change-hook
- #'erc--keep-place-indicator-on-window-configuration-change nil t)
+ (add-hook 'window-buffer-change-functions
+ #'erc--keep-place-indicator-on-window-buffer-change 40 t)
(when-let* (((memq erc-keep-place-indicator-style '(t arrow)))
+ (ov-property (if (zerop (fringe-columns 'left))
+ 'after-string
+ 'before-string))
(display (if (zerop (fringe-columns 'left))
`((margin left-margin) ,overlay-arrow-string)
'(left-fringe right-triangle
erc-keep-place-indicator-arrow)))
(bef (propertize " " 'display display)))
- (overlay-put erc--keep-place-indicator-overlay 'before-string bef))
+ (overlay-put erc--keep-place-indicator-overlay ov-property bef))
(when (memq erc-keep-place-indicator-style '(t face))
(overlay-put erc--keep-place-indicator-overlay 'face
'erc-keep-place-indicator-line)))
@@ -228,12 +380,16 @@ the active frame."
"Buffer-local `keep-place' with fringe arrow and/or highlighted face.
Play nice with global module `keep-place' but don't depend on it.
Expect that users may want different combinations of `keep-place'
-and `keep-place-indicator' in different buffers."
+and `keep-place-indicator' in different buffers. Unlike global
+`keep-place', when `switch-to-buffer-preserve-window-point' is
+enabled, don't forcibly sync point in all windows where buffer
+has previously been shown because that defeats the purpose of
+having a placeholder."
((cond (erc-keep-place-mode)
((memq 'keep-place erc-modules)
(erc-keep-place-mode +1))
;; Enable a local version of `keep-place-mode'.
- (t (add-hook 'erc-insert-pre-hook #'erc-keep-place 90 t)))
+ (t (add-hook 'erc-insert-pre-hook #'erc-keep-place 65 t)))
(if (pcase erc-keep-place-indicator-buffer-type
('target erc--target)
('server (not erc--target))
@@ -242,8 +398,8 @@ and `keep-place-indicator' in different buffers."
(erc-keep-place-indicator-mode -1)))
((when erc--keep-place-indicator-overlay
(delete-overlay erc--keep-place-indicator-overlay))
- (remove-hook 'window-configuration-change-hook
- #'erc--keep-place-indicator-on-window-configuration-change t)
+ (remove-hook 'window-buffer-change-functions
+ #'erc--keep-place-indicator-on-window-buffer-change t)
(remove-hook 'erc-keep-place-mode-hook
#'erc--keep-place-indicator-on-global-module t)
(remove-hook 'erc-insert-pre-hook #'erc-keep-place t)
@@ -256,7 +412,7 @@ That is, ensure the local module can survive a user toggling the
global one."
(if erc-keep-place-mode
(remove-hook 'erc-insert-pre-hook #'erc-keep-place t)
- (add-hook 'erc-insert-pre-hook #'erc-keep-place 90 t)))
+ (add-hook 'erc-insert-pre-hook #'erc-keep-place 65 t)))
(defun erc-keep-place-move (pos)
"Move keep-place indicator to current line or POS.
@@ -310,8 +466,7 @@ For use with `keep-place-indicator' module."
(forward-line -1)
(when erc-keep-place-indicator-mode
(unless (or (minibuffer-window-active-p (selected-window))
- (and (frame-visible-p (selected-frame))
- (get-buffer-window (current-buffer) (selected-frame))))
+ (get-buffer-window nil 'visible))
(erc-keep-place-move nil)))
;; if `switch-to-buffer-preserve-window-point' is set,
;; we cannot rely on point being saved, and must commit
@@ -331,21 +486,26 @@ For use with `keep-place-indicator' module."
erc-cmd-COUNTRY
erc-cmd-SV
erc-cmd-SM
- erc-cmd-SMV
+ erc-cmd-SAY
erc-cmd-LASTLOG)
- "List of commands that are aliases for CTCP ACTION or for ERC messages.
-
-If a command's function symbol is in this list, the typed command
-does not appear in the ERC buffer after the user presses ENTER.")
+ "List of client \"slash commands\" that perform their own buffer I/O.
+The `command-indicator' module forgoes echoing these commands,
+most of which aren't actual interactive lisp commands.")
;;;###autoload(autoload 'erc-noncommands-mode "erc-goodies" nil t)
(define-erc-module noncommands nil
- "This mode distinguishes non-commands.
-Commands listed in `erc-insert-this' know how to display
-themselves."
+ "Treat commands that display themselves specially.
+This module has been a no-op since ERC 5.3 and has likely only
+ever made sense in the context of `erc-command-indicator'. It
+was deprecated in ERC 5.6."
((add-hook 'erc--input-review-functions #'erc-send-distinguish-noncommands))
((remove-hook 'erc--input-review-functions
#'erc-send-distinguish-noncommands)))
+(make-obsolete-variable 'erc-noncommand-mode
+ 'erc-command-indicator-mode "30.1")
+(make-obsolete 'erc-noncommand-mode 'erc-command-indicator-mode "30.1")
+(make-obsolete 'erc-noncommand-enable 'erc-command-indicator-enable "30.1")
+(make-obsolete 'erc-noncommand-disable 'erc-command-indicator-disable "30.1")
(defun erc-send-distinguish-noncommands (state)
"If STR is an ERC non-command, set `insertp' in STATE to nil."
@@ -359,6 +519,106 @@ themselves."
;; Inhibit sending this string.
(setf (erc-input-insertp state) nil))))
+
+;;; Command-indicator
+
+(defface erc-command-indicator-face
+ '((t :inherit (erc-input-face fixed-pitch-serif)))
+ "Face for echoed command lines, including the prompt.
+See option `erc-command-indicator'."
+ :package-version '(ERC . "5.6") ; standard value, from bold
+ :group 'erc-faces)
+
+(defcustom erc-command-indicator 'erc-prompt
+ "Pseudo prompt for echoed command lines.
+An analog of the option `erc-prompt' that replaces the \"speaker
+label\" for echoed \"slash\" commands submitted at the prompt. A
+value of nil means ERC only inserts the command-line portion
+alone, without the prompt, which may trick certain modules, like
+`fill', into treating the leading slash command itself as the
+message's speaker."
+ :package-version '(ERC . "5.6")
+ :group 'erc-display
+ :type '(choice (const :tag "Defer to `erc-prompt'" erc-prompt)
+ (const :tag "Print command lines without a prompt" nil)
+ (string :tag "User-provided string")
+ (function :tag "User-provided function")))
+
+;;;###autoload(autoload 'erc-command-indicator-mode "erc-goodies" nil t)
+(define-erc-module command-indicator nil
+ "Echo command lines for \"slash commands,\" like /JOIN, /HELP, etc.
+Skip those appearing in `erc-noncommands-list'.
+
+Users can run \\[erc-command-indicator-toggle-hidden] to hide and
+reveal echoed command lines after they've been inserted."
+ ((add-hook 'erc--input-review-functions
+ #'erc--command-indicator-permit-insertion 80 t)
+ (erc-command-indicator-toggle-hidden -1))
+ ((remove-hook 'erc--input-review-functions
+ #'erc--command-indicator-permit-insertion t)
+ (erc-command-indicator-toggle-hidden +1))
+ 'local)
+
+(defun erc-command-indicator ()
+ "Return the command-indicator prompt as a string.
+Do nothing if the variable `erc-command-indicator' is nil."
+ (and erc-command-indicator
+ (let ((prompt (if (functionp erc-command-indicator)
+ (funcall erc-command-indicator)
+ erc-command-indicator)))
+ (concat prompt (and (not (string-empty-p prompt))
+ (not (string-suffix-p " " prompt))
+ " ")))))
+
+(defun erc-command-indicator-toggle-hidden (arg)
+ "Toggle whether echoed \"slash commands\" are visible."
+ (interactive "P")
+ (erc--toggle-hidden 'command-indicator arg))
+
+(defun erc--command-indicator-permit-insertion (state)
+ "Insert `erc-input' STATE's message if it's an echoed command."
+ (cl-assert erc-command-indicator-mode)
+ (when (erc--input-split-cmdp state)
+ (setf (erc--input-split-insertp state) #'erc--command-indicator-display)
+ (erc-send-distinguish-noncommands state)))
+
+;; This function used to be called `erc-display-command'. It was
+;; neutered in ERC 5.3.x (Emacs 24.5), commented out in 5.4, removed
+;; in 5.5, and restored in 5.6.
+(defun erc--command-indicator-display (line)
+ "Insert command LINE as echoed input resembling that of REPLs and shells."
+ (when erc-insert-this
+ (save-excursion
+ (erc--assert-input-bounds)
+ (let ((insert-position (marker-position (goto-char erc-insert-marker)))
+ (erc--msg-props (or erc--msg-props
+ (let ((ovs erc--msg-prop-overrides))
+ (map-into `((erc--msg . slash-cmd)
+ ,@(reverse ovs))
+ 'hash-table)))))
+ (when-let ((string (erc-command-indicator))
+ (erc-input-marker (copy-marker erc-input-marker)))
+ (erc-display-prompt nil nil string 'erc-command-indicator-face)
+ (remove-text-properties insert-position (point)
+ '(field nil erc-prompt nil))
+ (set-marker erc-input-marker nil))
+ (let ((beg (point)))
+ (insert line)
+ (erc-put-text-property beg (point)
+ 'font-lock-face 'erc-command-indicator-face)
+ (insert "\n"))
+ (save-restriction
+ (narrow-to-region insert-position (point))
+ (run-hooks 'erc-send-modify-hook)
+ (run-hooks 'erc-send-post-hook)
+ (cl-assert (> (- (point-max) (point-min)) 1))
+ (erc--hide-message 'command-indicator)
+ (add-text-properties (point-min) (1+ (point-min))
+ (erc--order-text-properties-from-hash
+ erc--msg-props))))
+ (erc--refresh-prompt))))
+
+
;;; IRC control character processing.
(defgroup erc-control-characters nil
"Dealing with control characters."
diff --git a/lisp/erc/erc-ibuffer.el b/lisp/erc/erc-ibuffer.el
index 612814ac6da..6e8a196255b 100644
--- a/lisp/erc/erc-ibuffer.el
+++ b/lisp/erc/erc-ibuffer.el
@@ -1,6 +1,6 @@
;;; erc-ibuffer.el --- ibuffer integration with ERC -*- lexical-binding: t; -*-
-;; Copyright (C) 2002, 2004, 2006-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002, 2004, 2006-2024 Free Software Foundation, Inc.
;; Author: Mario Lang <mlang@delysid.org>
;; Maintainer: Amin Bandali <bandali@gnu.org>, F. Jason Park <jp@neverwas.me>
@@ -27,6 +27,9 @@
;; needs work. Usage: Type / C-e C-h when in Ibuffer-mode to see new
;; limiting commands
+;; This library does not contain a module, but you can `require' it
+;; after loading `erc' to make use of its functionality.
+
;;; Code:
(require 'ibuffer)
@@ -118,11 +121,11 @@
(define-ibuffer-column
erc-members (:name "Users")
- (if (and (eq major-mode 'erc-mode)
- (boundp 'erc-channel-users)
- (hash-table-p erc-channel-users)
- (> (hash-table-size erc-channel-users) 0))
- (number-to-string (hash-table-size erc-channel-users))
+ (if-let ((table (or erc-channel-users erc-server-users))
+ ((hash-table-p table))
+ (count (hash-table-count table))
+ ((> count 0)))
+ (number-to-string count)
""))
(define-ibuffer-column erc-away (:name "A")
@@ -177,8 +180,7 @@
(defvar erc-ibuffer-limit-map nil
"Prefix keymap to use for ERC related limiting.")
(define-prefix-command 'erc-ibuffer-limit-map)
-;; FIXME: Where is `ibuffer-limit-by-erc-server' defined?
-(define-key 'erc-ibuffer-limit-map (kbd "s") 'ibuffer-limit-by-erc-server)
+(define-key 'erc-ibuffer-limit-map (kbd "s") #'ibuffer-filter-by-erc-server)
(define-key ibuffer-mode-map (kbd "/ \C-e") 'erc-ibuffer-limit-map)
(provide 'erc-ibuffer)
diff --git a/lisp/erc/erc-identd.el b/lisp/erc/erc-identd.el
index 5fdac58716c..2c95b16c12e 100644
--- a/lisp/erc/erc-identd.el
+++ b/lisp/erc/erc-identd.el
@@ -1,6 +1,6 @@
;;; erc-identd.el --- RFC1413 (identd authentication protocol) server -*- lexical-binding: t; -*-
-;; Copyright (C) 2003, 2006-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003, 2006-2024 Free Software Foundation, Inc.
;; Author: John Wiegley <johnw@gnu.org>
;; Maintainer: Amin Bandali <bandali@gnu.org>, F. Jason Park <jp@neverwas.me>
diff --git a/lisp/erc/erc-imenu.el b/lisp/erc/erc-imenu.el
index f053c6279b8..4c9cbfc1580 100644
--- a/lisp/erc/erc-imenu.el
+++ b/lisp/erc/erc-imenu.el
@@ -1,6 +1,6 @@
;;; erc-imenu.el --- Imenu support for ERC -*- lexical-binding: t; -*-
-;; Copyright (C) 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2024 Free Software Foundation, Inc.
;; Author: Mario Lang <mlang@delysid.org>
;; Maintainer: Amin Bandali <bandali@gnu.org>, F. Jason Park <jp@neverwas.me>
diff --git a/lisp/erc/erc-join.el b/lisp/erc/erc-join.el
index 2a57e77a622..cb57d8a00a1 100644
--- a/lisp/erc/erc-join.el
+++ b/lisp/erc/erc-join.el
@@ -1,6 +1,6 @@
;;; erc-join.el --- autojoin channels on connect and reconnects -*- lexical-binding: t; -*-
-;; Copyright (C) 2002-2004, 2006-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2004, 2006-2024 Free Software Foundation, Inc.
;; Author: Alex Schroeder <alex@gnu.org>
;; Maintainer: Amin Bandali <bandali@gnu.org>, F. Jason Park <jp@neverwas.me>
diff --git a/lisp/erc/erc-lang.el b/lisp/erc/erc-lang.el
index 9261d659c72..9613a7f2c32 100644
--- a/lisp/erc/erc-lang.el
+++ b/lisp/erc/erc-lang.el
@@ -1,6 +1,6 @@
;;; erc-lang.el --- provide the LANG command to ERC -*- lexical-binding: t; -*-
-;; Copyright (C) 2002, 2004, 2006-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002, 2004, 2006-2024 Free Software Foundation, Inc.
;; Author: Alex Schroeder <alex@gnu.org>
;; Maintainer: Amin Bandali <bandali@gnu.org>, F. Jason Park <jp@neverwas.me>
diff --git a/lisp/erc/erc-list.el b/lisp/erc/erc-list.el
index 099096771ac..3beb9ffe741 100644
--- a/lisp/erc/erc-list.el
+++ b/lisp/erc/erc-list.el
@@ -1,6 +1,6 @@
;;; erc-list.el --- /list support for ERC -*- lexical-binding:t -*-
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
;; Author: Tom Tromey <tromey@redhat.com>
;; Maintainer: Amin Bandali <bandali@gnu.org>, F. Jason Park <jp@neverwas.me>
diff --git a/lisp/erc/erc-log.el b/lisp/erc/erc-log.el
index d3106da4017..d5c56bcc2b3 100644
--- a/lisp/erc/erc-log.el
+++ b/lisp/erc/erc-log.el
@@ -1,6 +1,6 @@
;;; erc-log.el --- Logging facilities for ERC. -*- lexical-binding: t; -*-
-;; Copyright (C) 2003-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003-2024 Free Software Foundation, Inc.
;; Author: Lawrence Mitchell <wence@gmx.li>
;; Maintainer: Amin Bandali <bandali@gnu.org>, F. Jason Park <jp@neverwas.me>
@@ -231,7 +231,7 @@ also be a predicate function. To only log when you are not set away, use:
(add-hook 'erc-part-hook #'erc-conditional-save-buffer)
;; append, so that 'erc-initialize-log-marker runs first
(add-hook 'erc-connect-pre-hook #'erc-log-setup-logging 'append)
- (add-hook 'erc--pre-clear-functions #'erc-save-buffer-in-logs)
+ (add-hook 'erc--pre-clear-functions #'erc-save-buffer-in-logs 50)
(dolist (buffer (erc-buffer-list))
(erc-log-setup-logging buffer))
(erc--modify-local-map t "C-c C-l" #'erc-save-buffer-in-logs))
@@ -276,11 +276,11 @@ The current buffer is given by BUFFER."
(defun erc-log-all-but-server-buffers (buffer)
"Return t if logging should be enabled in BUFFER.
-Returns nil if `erc-server-buffer-p' returns t."
+Return nil if BUFFER is a server buffer."
(save-excursion
(save-window-excursion
(set-buffer buffer)
- (not (erc-server-buffer-p)))))
+ (not (erc--server-buffer-p)))))
(defun erc-save-query-buffers (process)
"Save all buffers of the given PROCESS."
@@ -430,7 +430,8 @@ You can save every individual message by putting this function on
(if (and erc-truncate-buffer-on-save
(called-interactively-p 'interactive))
(let ((erc-log--save-in-progress-p t))
- (erc-cmd-CLEAR)
+ (save-excursion (goto-char erc-insert-marker)
+ (erc-cmd-CLEAR))
(erc-button--display-error-notice-with-keys
(erc-server-buffer) "Option `%s' is deprecated."
" Use /CLEAR instead." 'erc-truncate-buffer-on-save))
@@ -445,6 +446,15 @@ You can save every individual message by putting this function on
(set-buffer-modified-p nil))))))
t)
+;; This is a kludge to avoid littering erc-truncate.el with forward
+;; declarations needed only for a corner-case compatibility check.
+(defun erc-log--call-when-logging-enabled-sans-module (fn)
+ (when (and (erc-logging-enabled)
+ (not (or erc-log-mode (memq 'log erc-modules))))
+ (let ((dirfile (and (stringp erc-log-channels-directory)
+ erc-log-channels-directory)))
+ (funcall fn dirfile))))
+
(provide 'erc-log)
;;; erc-log.el ends here
diff --git a/lisp/erc/erc-match.el b/lisp/erc/erc-match.el
index 50db8a132ec..8497382a733 100644
--- a/lisp/erc/erc-match.el
+++ b/lisp/erc/erc-match.el
@@ -1,6 +1,6 @@
;;; erc-match.el --- Highlight messages matching certain regexps -*- lexical-binding: t; -*-
-;; Copyright (C) 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2024 Free Software Foundation, Inc.
;; Author: Andreas Fuchs <asf@void.at>
;; Maintainer: Amin Bandali <bandali@gnu.org>, F. Jason Park <jp@neverwas.me>
@@ -53,13 +53,14 @@ they are hidden or highlighted. This is controlled via the variables
you can decide whether the entire message or only the sending nick is
highlighted."
((add-hook 'erc-insert-modify-hook #'erc-match-message 50)
- (add-hook 'erc-mode-hook #'erc-match--modify-invisibility-spec)
- (unless erc--updating-modules-p
- (erc-buffer-do #'erc-match--modify-invisibility-spec))
+ (add-hook 'erc-mode-hook #'erc-match--setup)
+ (unless erc--updating-modules-p (erc-buffer-do #'erc-match--setup))
+ (add-hook 'erc-insert-post-hook #'erc-match--on-insert-post 50)
(erc--modify-local-map t "C-c C-k" #'erc-go-to-log-matches-buffer))
((remove-hook 'erc-insert-modify-hook #'erc-match-message)
- (remove-hook 'erc-mode-hook #'erc-match--modify-invisibility-spec)
- (erc-match--modify-invisibility-spec)
+ (remove-hook 'erc-insert-post-hook #'erc-match--on-insert-post)
+ (remove-hook 'erc-mode-hook #'erc-match--setup)
+ (erc-buffer-do #'erc-match--setup)
(erc--modify-local-map nil "C-c C-k" #'erc-go-to-log-matches-buffer)))
;; Remaining customizations
@@ -490,7 +491,9 @@ Use this defun with `erc-insert-modify-hook'."
(message (buffer-substring message-beg (point-max))))
(when (and vector
(not (and erc-match-exclude-server-buffer
- (erc-server-buffer-p))))
+ ;; FIXME replace with `erc--server-buffer-p'
+ ;; or explain why that's unwise.
+ (erc-server-or-unjoined-channel-buffer-p))))
(mapc
(lambda (match-type)
(goto-char (point-min))
@@ -657,7 +660,20 @@ See `erc-log-match-format'."
(defun erc-hide-fools (match-type _nickuserhost _message)
"Hide comments from designated fools."
- (when (eq match-type 'fool)
+ (when (and erc--msg-props (eq match-type 'fool))
+ (puthash 'erc--invisible 'erc-match-fool erc--msg-props)))
+
+;; FIXME remove, make public, or only add locally.
+;;
+;; ERC modules typically don't add internal functions to public hooks
+;; globally. However, ERC 5.6 will likely include a general
+;; (internal) facility for adding invisible props, which will obviate
+;; the need for this function. IOW, leaving this internal for now is
+;; an attempt to avoid the hassle of the deprecation process.
+(defun erc-match--on-insert-post ()
+ "Hide messages marked with the `erc--invisible' prop."
+ (when (erc--check-msg-prop 'erc--invisible 'erc-match-fool)
+ (remhash 'erc--invisible erc--msg-props)
(erc--hide-message 'match-fools)))
(defun erc-beep-on-match (match-type _nickuserhost _message)
@@ -666,33 +682,20 @@ This function is meant to be called from `erc-text-matched-hook'."
(when (member match-type erc-beep-match-types)
(beep)))
-(defun erc-match--modify-invisibility-spec ()
+(defun erc-match--setup ()
"Add an `erc-match' property to the local spec."
;; Hopefully, this will be extended to do the same for other
;; invisible properties managed by this module.
(if erc-match-mode
(erc-match-toggle-hidden-fools +1)
- (erc-with-all-buffers-of-server nil nil
- (erc-match-toggle-hidden-fools -1))))
+ (erc-match-toggle-hidden-fools -1)))
(defun erc-match-toggle-hidden-fools (arg)
"Toggle fool visibility.
Expect the function `erc-hide-fools' or similar to be present in
`erc-text-matched-hook'."
(interactive "P")
- (erc-match--toggle-hidden 'match-fools arg))
-
-(defun erc-match--toggle-hidden (prop arg)
- "Toggle invisibility for spec member PROP.
-Treat ARG in a manner similar to mode toggles defined by
-`define-minor-mode'."
- (when arg
- (setq arg (prefix-numeric-value arg)))
- (if (memq prop (ensure-list buffer-invisibility-spec))
- (unless (natnump arg)
- (remove-from-invisibility-spec prop))
- (when (or (not arg) (natnump arg))
- (add-to-invisibility-spec prop))))
+ (erc--toggle-hidden 'match-fools arg))
(provide 'erc-match)
diff --git a/lisp/erc/erc-menu.el b/lisp/erc/erc-menu.el
index 7f877a34c0a..ee32bd4d29f 100644
--- a/lisp/erc/erc-menu.el
+++ b/lisp/erc/erc-menu.el
@@ -1,6 +1,6 @@
;;; erc-menu.el --- Menu-bar definitions for ERC -*- lexical-binding: t; -*-
-;; Copyright (C) 2001-2002, 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2002, 2004-2024 Free Software Foundation, Inc.
;; Author: Mario Lang <mlang@delysid.org>
;; Maintainer: Amin Bandali <bandali@gnu.org>, F. Jason Park <jp@neverwas.me>
diff --git a/lisp/erc/erc-netsplit.el b/lisp/erc/erc-netsplit.el
index 5dd11ab1869..15798793df8 100644
--- a/lisp/erc/erc-netsplit.el
+++ b/lisp/erc/erc-netsplit.el
@@ -1,6 +1,6 @@
;;; erc-netsplit.el --- Reduce JOIN/QUIT messages on netsplits -*- lexical-binding: t; -*-
-;; Copyright (C) 2002-2004, 2006-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2004, 2006-2024 Free Software Foundation, Inc.
;; Author: Mario Lang <mlang@delysid.org>
;; Maintainer: Amin Bandali <bandali@gnu.org>, F. Jason Park <jp@neverwas.me>
@@ -41,7 +41,7 @@ netsplits, so that it can filter the JOIN messages on a netjoin too."
;;;###autoload(autoload 'erc-netsplit-mode "erc-netsplit")
(define-erc-module netsplit nil
"This mode hides quit/join messages if a netsplit occurs."
- ((erc-netsplit-install-message-catalogs)
+ ( ; FIXME delete newline on next edit
(add-hook 'erc-server-JOIN-functions #'erc-netsplit-JOIN)
(add-hook 'erc-server-MODE-functions #'erc-netsplit-MODE)
(add-hook 'erc-server-QUIT-functions #'erc-netsplit-QUIT)
@@ -85,13 +85,22 @@ where FIRST-JOIN is t or nil, depending on whether or not the first
join from that split has been detected or not.")
(defun erc-netsplit-install-message-catalogs ()
+ (declare (obsolete "defined at top level in erc-netsplit.el" "30.1"))
+ (with-suppressed-warnings ((obsolete erc-define-catalog)) ; indentation
(erc-define-catalog
'english
'((netsplit . "netsplit: %s")
(netjoin . "netjoin: %s, %N were split")
(netjoin-done . "netjoin: All lost souls are back!")
(netsplit-none . "No netsplits in progress")
- (netsplit-wholeft . "split: %s missing: %n %t"))))
+ (netsplit-wholeft . "split: %s missing: %n %t"))))) ; indentation
+
+(erc-define-message-format-catalog english
+ (netsplit . "netsplit: %s")
+ (netjoin . "netjoin: %s, %N were split")
+ (netjoin-done . "netjoin: All lost souls are back!")
+ (netsplit-none . "No netsplits in progress")
+ (netsplit-wholeft . "split: %s missing: %n %t"))
(defun erc-netsplit-JOIN (proc parsed)
"Show/don't show rejoins."
diff --git a/lisp/erc/erc-networks.el b/lisp/erc/erc-networks.el
index bf4ef1d35a9..99c3c0563d0 100644
--- a/lisp/erc/erc-networks.el
+++ b/lisp/erc/erc-networks.el
@@ -1,6 +1,6 @@
;;; erc-networks.el --- IRC networks -*- lexical-binding: t; -*-
-;; Copyright (C) 2002, 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002, 2004-2024 Free Software Foundation, Inc.
;; Author: Mario Lang <mlang@lexx.delysid.org>
;; Maintainer: Amin Bandali <bandali@gnu.org>, F. Jason Park <jp@neverwas.me>
@@ -42,31 +42,24 @@
(defvar erc--target)
(defvar erc-insert-marker)
-(defvar erc-kill-buffer-hook)
-(defvar erc-kill-server-hook)
(defvar erc-modules)
(defvar erc-rename-buffers)
(defvar erc-reuse-buffers)
(defvar erc-server-announced-name)
(defvar erc-server-connected)
-(defvar erc-server-parameters)
(defvar erc-server-process)
-(defvar erc-session-server)
-(declare-function erc--default-target "erc" nil)
(declare-function erc--get-isupport-entry "erc-backend" (key &optional single))
(declare-function erc-buffer-filter "erc" (predicate &optional proc))
(declare-function erc-current-nick "erc" nil)
(declare-function erc-display-error-notice "erc" (parsed string))
(declare-function erc-display-message "erc" (parsed type buffer msg &rest args))
-(declare-function erc-error "erc" (&rest args))
(declare-function erc-get-buffer "erc" (target &optional proc))
-(declare-function erc-server-buffer "erc" nil)
(declare-function erc-server-process-alive "erc-backend" (&optional buffer))
(declare-function erc-set-active-buffer "erc" (buffer))
(declare-function erc-button--display-error-notice-with-keys
- (parsed &rest strings))
+ (maybe-buffer &rest strings))
;; Variables
@@ -479,7 +472,7 @@ NET is a symbol indicating to which network from `erc-networks-alist'
this server corresponds,
HOST is the server's hostname, and (TLS-)PORTS is either a
number, a list of numbers, or a list of port ranges."
- :package-version '(ERC . "5.6") ; FIXME sync on release
+ :package-version '(ERC . "5.6")
:type '(alist :key-type (string :tag "Name")
:value-type
(group symbol (string :tag "Hostname")
@@ -756,9 +749,8 @@ number, a list of numbers, or a list of port ranges."
Each network is a list (NET MATCHER) where
NET is a symbol naming that IRC network and
MATCHER is used to find a corresponding network to a server while
- connected to it. If it is regexp, it's used to match against
- `erc-server-announced-name'. It can also be a function (predicate).
- Then it is executed with the server buffer as current buffer."
+connected to it. If it is a regexp, it's used to match against
+`erc-server-announced-name'."
:type '(repeat
(list :tag "Network"
(symbol :tag "Network name")
@@ -992,12 +984,11 @@ object."
(erc-networks--id-qualifying-len nid))
(erc-networks--rename-server-buffer (or proc erc-server-process) parsed)
(erc-networks--shrink-ids-and-buffer-names-any)
- (erc-with-all-buffers-of-server
- erc-server-process #'erc--default-target
- (when-let* ((new-name (erc-networks--reconcile-buffer-names erc--target
- nid))
- ((not (equal (buffer-name) new-name))))
- (rename-buffer new-name 'unique))))
+ (erc-with-all-buffers-of-server erc-server-process #'erc-target
+ (when-let
+ ((new-name (erc-networks--reconcile-buffer-names erc--target nid))
+ ((not (equal (buffer-name) new-name))))
+ (rename-buffer new-name 'unique))))
(cl-defgeneric erc-networks--id-ensure-comparable (self other)
"Take measures to ensure two net identities are in comparable states.")
@@ -1232,6 +1223,8 @@ Use the server parameter NETWORK if provided, otherwise parse the
server name and search for a match in `erc-networks-alist'."
;; The server made it easy for us and told us the name of the NETWORK
(declare (obsolete "maybe see `erc-networks--determine'" "29.1"))
+ (defvar erc-server-parameters)
+ (defvar erc-session-server)
(let ((network-name (cdr (assoc "NETWORK" erc-server-parameters))))
(if network-name
(intern network-name)
@@ -1295,17 +1288,16 @@ shutting down the connection."
erc-network)))
(erc-display-message parsed 'notice nil m)
nil)
- ((and
- (guard (eq erc-network erc-networks--name-missing-sentinel))
- ;; This can happen theoretically, e.g., when adjusting settings
- ;; on a proxy service that partially impersonates IRC but isn't
- ;; currently conveying anything through to a real network. The
- ;; service may send a 422 but no NETWORK param (or *any* 005s).
- (let m (concat "Failed to determine network. Please set entry for \""
- erc-server-announced-name "\" in `erc-networks-alist'"
- " or consider calling `erc-tls' with the keyword `:id'."
- " See Info:\"(erc) Network Identifier\" for more.")))
- (erc-display-error-notice parsed m)
+ ((guard (eq erc-network erc-networks--name-missing-sentinel))
+ ;; This can happen theoretically, e.g., when adjusting settings
+ ;; on a proxy service that partially impersonates IRC but isn't
+ ;; currently conveying anything through to a real network. The
+ ;; service may send a 422 but no NETWORK param (or *any* 005s).
+ (erc-button--display-error-notice-with-keys
+ "Failed to determine network. Please set entry for \""
+ erc-server-announced-name "\" in `erc-networks-alist' or consider"
+ " calling `erc-tls' with the keyword `:id'."
+ " See Info:\"(erc) Network Identifier\" for more.")
(if erc-networks--allow-unknown-network
(progn
(erc-display-error-notice
@@ -1325,9 +1317,9 @@ Copy source (prefix) from MOTD-ish message as a last resort."
(unless erc-server-announced-name
(require 'erc-button)
(erc-button--display-error-notice-with-keys
- parsed "Failed to determine server name. Using \""
+ "Failed to determine server name. Using \""
(setq erc-server-announced-name (erc-response.sender parsed)) "\" instead"
- ". If this was unexpected, consider reporting it via \\[erc-bug]" "."))
+ ". If this was unexpected, consider reporting it via \\[erc-bug]."))
nil)
(defun erc-unset-network-name (_nick _ip _reason)
@@ -1385,6 +1377,8 @@ already been copied over to the current, replacement buffer.")
(defun erc-networks--copy-over-server-buffer-contents (existing name)
"Kill off existing server buffer after copying its contents.
Must be called from the replacement buffer."
+ (defvar erc-kill-buffer-hook)
+ (defvar erc-kill-server-hook)
;; ERC expects `erc-open' to be idempotent when setting up local
;; vars and other context properties for a new identity. Thus, it's
;; unlikely we'll have to copy anything else over besides text. And
@@ -1508,7 +1502,7 @@ to be a false alarm. If `erc-reuse-buffers' is nil, let
proc)
(require 'erc-button)
(erc-button--display-error-notice-with-keys
- parsed "Unexpected state detected. Please report via \\[erc-bug].")))
+ "Unexpected state detected. Please report via \\[erc-bug].")))
;; For now, retain compatibility with erc-server-NNN-functions.
(or (erc-networks--ensure-announced proc parsed)
@@ -1590,14 +1584,29 @@ return the host alone sans URL formatting (for compatibility)."
'((pals Libera.Chat ("kensanata" "shapr" "anti\\(fuchs\\|gone\\)"))
(format-nick-function (Libera.Chat "#emacs") erc-format-@nick))
"Experimental: Alist of configuration options.
+
+WARNING: this variable is a vestige from a long-abandoned
+experiment. ERC may redefine it using the same name for any
+purpose at any time.
+
The format is (VARNAME SCOPE VALUE) where
VARNAME is a symbol identifying the configuration option,
SCOPE is either a symbol which identifies an entry from
`erc-networks-alist' or a list (NET TARGET) where NET is a network symbol and
TARGET is a string identifying the channel/query target.
VALUE is the options value.")
+(make-obsolete-variable 'erc-settings
+ "temporarily deprecated for later repurposing" "30.1")
(defun erc-get (var &optional net target)
+ "Retrieve configuration values from `erc-settings'.
+
+WARNING: this function is a non-functioning remnant from a
+long-abandoned experiment. ERC may redefine it using the same
+name for any purpose at any time.
+
+\(fn &rest UNKNOWN)"
+ (declare (obsolete "temporarily deprecated for later repurposing" "30.1"))
(let ((items erc-settings)
elt val)
(while items
diff --git a/lisp/erc/erc-nicks.el b/lisp/erc/erc-nicks.el
index a7d0b0769f2..64f9ec42783 100644
--- a/lisp/erc/erc-nicks.el
+++ b/lisp/erc/erc-nicks.el
@@ -1,6 +1,6 @@
;;; erc-nicks.el -- Nick colors for ERC -*- lexical-binding: t; -*-
-;; Copyright (C) 2023 Free Software Foundation, Inc.
+;; Copyright (C) 2023-2024 Free Software Foundation, Inc.
;; Author: David Leatherman <leathekd@gmail.com>
;; Andy Stewart <lazycat.manatee@gmail.com>
@@ -71,7 +71,7 @@
(defgroup erc-nicks nil
"Colorize nicknames in ERC target buffers."
- :package-version '(ERC . "5.6") ; FIXME sync on release
+ :package-version '(ERC . "5.6")
:group 'erc)
(defcustom erc-nicks-ignore-chars ",`'_-"
@@ -102,7 +102,10 @@ should adjust it before connecting."
(frame-parameter (selected-frame) 'background-color)
"Background color for calculating contrast.
Set this explicitly when the background color isn't discoverable,
-which may be the case in terminal Emacs."
+which may be the case in terminal Emacs. Even when automatically
+initialized, this value may need adjustment mid-session, such as
+after loading a new theme. Remember to run \\[erc-nicks-refresh]
+after doing so."
:type 'string)
(defcustom erc-nicks-color-adjustments
@@ -153,9 +156,13 @@ List of colors as strings (hex or named) or, alternatively, a
single symbol representing a set of colors, like that produced by
the function `defined-colors', which ERC associates with the
symbol `defined'. Similarly, `all' tells ERC to use any 24-bit
-color. When specifying a list, users may want to set the option
-`erc-nicks-color-adjustments' to nil to prevent unwanted culling."
- :type '(choice (const all) (const defined) (repeat string)))
+color. To change the value mid-session, try
+\\[erc-nicks-refresh]."
+ :type `(choice (const :tag "All 24-bit colors" all)
+ (const :tag "Defined terminal colors" defined)
+ (const :tag "Font Lock faces" font-lock)
+ (const :tag "ANSI color faces" ansi-color)
+ (repeat :tag "User-provided list" string)))
(defcustom erc-nicks-key-suffix-format "@%n"
"Template for latter portion of keys to generate colors from.
@@ -166,6 +173,20 @@ adding extra characters or padding, for example, with something
like \"@%-012n\"."
:type 'string)
+(defcustom erc-nicks-track-faces 'prioritize
+ "Show nick faces in the `track' module's portion of the mode line.
+A value of nil means don't show nick faces at all. A value of
+`defer' means have `track' consider nick faces only after those
+ranked faces in `erc-track-faces-normal-list'. This has the
+effect of \"alternating\" between a ranked \"normal\" and a nick.
+The value `prioritize' means have `track' consider nick faces to
+be \"normal\" unless the current speaker is the same as the
+previous one, in which case pretend the value is `defer'. Like
+most options in this module, updating the value mid-session is
+not officially supported, although cycling \\[erc-nicks-mode] may
+be worth a shot."
+ :type '(choice (const nil) (const defer) (const prioritize)))
+
(defvar erc-nicks--max-skip-search 3 ; make this an option?
"Max number of faces to visit when testing `erc-nicks-skip-faces'.")
@@ -188,6 +209,7 @@ Keys are nonempty strings but need not be valid nicks.")
(defvar help-xref-stack)
(defvar help-xref-stack-item)
+(defvar erc-track--normal-faces)
;; https://stackoverflow.com/questions/596216#answer-56678483
(defun erc-nicks--get-luminance (color)
@@ -227,6 +249,7 @@ If FG or BG are floats, interpret them as luminance values."
;; https://www.w3.org/TR/UNDERSTANDING-WCAG20/visual-audio-contrast-contrast.html
(defun erc-nicks--adjust-contrast (color target &optional decrease)
+ (cl-assert erc-nicks--fg-rgb)
(let* ((lum-bg (or erc-nicks--bg-luminance
(setq erc-nicks--bg-luminance
(erc-nicks--get-luminance erc-nicks-bg-color))))
@@ -356,7 +379,40 @@ Return a hex string."
erc-nicks-color-adjustments
(if (stringp color) (color-name-to-rgb color) color))))
-(defun erc-nicks--create-pool (adjustments colors)
+(defvar erc-nicks--create-pool-function #'erc-nicks--create-coerced-pool
+ "Filter function for initializing the pool of colors.
+Takes a list of adjustment functions, such as those named in
+`erc-nicks-color-adjustments', and a list of colors. Returns
+another list whose members need not be among the original
+candidates. Users should note that this variable, along with its
+predefined function values, `erc-nicks--create-coerced-pool' and
+`erc-nicks--create-culled-pool', can be made public in a future
+version of this module, perhaps as a single user option, given
+sufficient demand.")
+
+(defun erc-nicks--create-coerced-pool (adjustments colors)
+ "Return COLORS that fall within parameters heeded by ADJUSTMENTS.
+Apply ADJUSTMENTS and dedupe after replacing adjusted values with
+those nearest defined for the terminal. Only perform one pass.
+That is, accept the nearest initially found as \"close enough,\"
+knowing that values may fall outside desired parameters and thus
+yield a larger pool than simple culling might produce. When
+debugging, add candidates to `erc-nicks--colors-rejects' that map
+to the same output color as some prior candidate."
+ (let* ((seen (make-hash-table :test #'equal))
+ (erc-nicks-color-adjustments adjustments)
+ pool)
+ (dolist (color colors)
+ (let ((quantized (car (tty-color-approximate
+ (color-values (erc-nicks--reduce color))))))
+ (if (gethash quantized seen)
+ (when erc-nicks--colors-rejects
+ (push color erc-nicks--colors-rejects))
+ (push quantized pool)
+ (puthash quantized color seen))))
+ (nreverse pool)))
+
+(defun erc-nicks--create-culled-pool (adjustments colors)
"Return COLORS that fall within parameters indicated by ADJUSTMENTS."
(let (addp capp satp pool)
(dolist (adjustment adjustments)
@@ -382,8 +438,12 @@ Return a hex string."
"Initialize colors and optionally display faces or color palette."
(unless (eq erc-nicks-colors 'all)
(let* ((colors (or (and (listp erc-nicks-colors) erc-nicks-colors)
+ (and (memq erc-nicks-colors '(font-lock ansi-color))
+ (erc-nicks--colors-from-faces
+ (format "%s-" erc-nicks-colors)))
(defined-colors)))
- (pool (erc-nicks--create-pool erc-nicks-color-adjustments colors)))
+ (pool (funcall erc-nicks--create-pool-function
+ erc-nicks-color-adjustments colors)))
(setq erc-nicks--colors-pool pool
erc-nicks--colors-len (length pool)))))
@@ -409,7 +469,9 @@ Favor a custom erc-nicks-NICK@NETWORK-face when defined."
(put new-face 'erc-nicks--nick nick)
(put new-face 'erc-nicks--netid erc-networks--id)
(put new-face 'erc-nicks--key key)
- (face-spec-set new-face `((t :foreground ,color)) 'face-defface-spec)
+ (face-spec-set new-face `((t :foreground ,color
+ :inherit ,erc-nicks-backing-face))
+ 'face-defface-spec)
(set-face-documentation
new-face (format "Internal face for %s on %s." nick (erc-network)))
(puthash nick new-face table)))))
@@ -458,12 +520,8 @@ Abandon search after examining LIMIT faces."
((not (and base-face
(erc-nicks--skip-p base-face erc-nicks-skip-faces
erc-nicks--max-skip-search))))
- (key (erc-nicks--gen-key-from-format-spec trimmed))
- (out (erc-nicks--get-face trimmed key)))
- (if (or (null erc-nicks-backing-face)
- (eq base-face erc-nicks-backing-face))
- out
- (cons out (erc-list erc-nicks-backing-face)))))
+ (key (erc-nicks--gen-key-from-format-spec trimmed)))
+ (erc-nicks--get-face trimmed key)))
(defun erc-nicks--highlight-button (nick-object)
"Possibly add face to `erc-button--nick-user' NICK-OBJECT."
@@ -473,7 +531,12 @@ Abandon search after examining LIMIT faces."
'font-lock-face))
(nick (erc-server-user-nickname (erc-button--nick-user nick-object)))
(out (erc-nicks--highlight nick face)))
- (setf (erc-button--nick-nickname-face nick-object) out))
+ (setf (erc-button--nick-nickname-face nick-object) out
+ ;;
+ (erc-button--nick-face-cache nick-object)
+ (and erc-nicks-track-faces
+ (bound-and-true-p erc-track--normal-faces)
+ #'erc-nicks--remember-face-for-track)))
nick-object)
(define-erc-module nicks nil
@@ -487,7 +550,8 @@ Abandon search after examining LIMIT faces."
" Toggling it in individual target buffers is unsupported.")
(erc-nicks-mode +1))) ; but do it anyway
(setq erc-nicks--downcased-skip-nicks
- (mapcar #'erc-downcase erc-nicks-skip-nicks))
+ (mapcar #'erc-downcase erc-nicks-skip-nicks)
+ erc-nicks--fg-rgb (erc-with-server-buffer erc-nicks--fg-rgb))
(add-function :filter-return (local 'erc-button--modify-nick-function)
#'erc-nicks--highlight-button '((depth . 80)))
(erc-button--phantom-users-mode +1))
@@ -505,16 +569,18 @@ Abandon search after examining LIMIT faces."
"Module `nicks' unable to determine background color. Setting to \""
temp "\" globally. Please see `erc-nicks-bg-color'.")
(custom-set-variables (list 'erc-nicks-bg-color temp))))
+ (setq erc-nicks--fg-rgb
+ (or (color-name-to-rgb
+ (face-foreground 'erc-default-face nil 'default))
+ (color-name-to-rgb
+ (readable-foreground-color erc-nicks-bg-color))))
(erc-nicks--init-pool)
(erc--restore-initialize-priors erc-nicks-mode
erc-nicks--face-table (make-hash-table :test #'equal)))
- (setq erc-nicks--fg-rgb
- (or (color-name-to-rgb
- (face-foreground 'erc-default-face nil 'default))
- (color-name-to-rgb
- (readable-foreground-color erc-nicks-bg-color))))
(setf (alist-get "Edit face" erc-button--nick-popup-alist nil nil #'equal)
#'erc-nicks-customize-face)
+ (erc-nicks--setup-track-integration)
+ (add-hook 'erc-track-mode #'erc-nicks--setup-track-integration 50 t)
(advice-add 'widget-create-child-and-convert :filter-args
#'erc-nicks--redirect-face-widget-link))
((kill-local-variable 'erc-nicks--face-table)
@@ -526,8 +592,12 @@ Abandon search after examining LIMIT faces."
(kill-local-variable 'erc-nicks--downcased-skip-nicks)
(when (fboundp 'erc-button--phantom-users-mode)
(erc-button--phantom-users-mode -1))
+ (remove-function (local 'erc-track--face-reject-function)
+ #'erc-nicks--reject-uninterned-faces)
(remove-function (local 'erc-button--modify-nick-function)
#'erc-nicks--highlight-button)
+ (remove-function (local 'erc-track--alt-normals-function)
+ #'erc-nicks--check-normals)
(setf (alist-get "Edit face"
erc-button--nick-popup-alist nil 'remove #'equal)
nil)
@@ -599,8 +669,10 @@ Abandon search after examining LIMIT faces."
(defun erc-nicks-refresh (debug)
"Recompute faces for all nicks on current network.
-With DEBUG, review affected faces or colors. Which one depends
-on the value of `erc-nicks-colors'."
+With DEBUG, review affected faces or colors. Exactly which of
+the two depends on the value of `erc-nicks-colors'. Note that
+the list of rejected faces may include duplicates of accepted
+ones."
(interactive "P")
(unless (derived-mode-p 'erc-mode)
(user-error "Not an ERC buffer"))
@@ -608,6 +680,8 @@ on the value of `erc-nicks-colors'."
(unless erc-nicks-mode (user-error "Module `nicks' disabled"))
(let ((erc-nicks--colors-rejects (and debug (list t))))
(erc-nicks--init-pool)
+ (unless erc-nicks--colors-pool
+ (user-error "Pool empty: all colors rejected"))
(dolist (nick (hash-table-keys erc-nicks--face-table))
;; User-tuned faces do not have an `erc-nicks--key' property.
(when-let ((face (gethash nick erc-nicks--face-table))
@@ -634,6 +708,67 @@ on the value of `erc-nicks-colors'."
(cadr (apply #'color-rgb-to-hsl
(color-name-to-rgb c))))))))))))))
+(defun erc-nicks--colors-from-faces (prefix)
+ "Extract foregrounds from faces with PREFIX
+Expect PREFIX to be something like \"ansi-color-\" or \"font-lock-\"."
+ (let (out)
+ (dolist (face (face-list) (nreverse out))
+ (when-let (((string-prefix-p prefix (symbol-name face)))
+ (color (face-foreground face)))
+ (push color out)))))
+
+(defun erc-nicks--reject-uninterned-faces (candidate)
+ "Remove own faces from CANDIDATE if it's a combination of faces."
+ (while-let ((next (car-safe candidate))
+ ((facep next))
+ ((not (intern-soft next))))
+ (setq candidate (cdr candidate)))
+ (if (and (consp candidate) (not (cdr candidate))) (car candidate) candidate))
+
+(define-inline erc-nicks--oursp (face)
+ (inline-quote
+ (and-let* ((sym (car-safe ,face))
+ ((symbolp sym))
+ ((get sym 'erc-nicks--key)))
+ sym)))
+
+(defun erc-nicks--check-normals (current contender contenders normals)
+ "Return a viable `nicks'-owned face from NORMALS in CONTENDERS.
+But only do so if the CURRENT face is also one of ours and in
+NORMALS and if the highest ranked CONTENDER among new faces is
+`erc-default-face', the lowest ranking default priority face."
+ (and-let* (((eq contender 'erc-default-face))
+ ((or (null current) (gethash current normals)))
+ (spkr (or (null current) (erc-nicks--oursp current))))
+ (catch 'contender
+ (dolist (candidate (cdr contenders) contender)
+ (when-let (((not (equal candidate current)))
+ ((gethash candidate normals))
+ (s (erc-nicks--oursp candidate))
+ ((not (eq s spkr))))
+ (throw 'contender candidate))))))
+
+(defun erc-nicks--setup-track-integration ()
+ "Restore traditional \"alternating normal\" face functionality to mode-line."
+ (when (bound-and-true-p erc-track-mode)
+ (pcase erc-nicks-track-faces
+ ;; Variant `defer' is handled elsewhere.
+ ('prioritize
+ (add-function :override (local 'erc-track--alt-normals-function)
+ #'erc-nicks--check-normals))
+ ('nil
+ (add-function :override (local 'erc-track--face-reject-function)
+ #'erc-nicks--reject-uninterned-faces)))))
+
+(defun erc-nicks--remember-face-for-track (face)
+ "Add FACE to local hash table maintained by `track' module."
+ (or (gethash face erc-track--normal-faces)
+ (if-let ((sym (or (car-safe face) face))
+ ((symbolp sym))
+ ((get sym 'erc-nicks--key)))
+ (puthash face face erc-track--normal-faces)
+ face)))
+
(provide 'erc-nicks)
;;; erc-nicks.el ends here
diff --git a/lisp/erc/erc-notify.el b/lisp/erc/erc-notify.el
index 55be8976ada..45b0fb12c43 100644
--- a/lisp/erc/erc-notify.el
+++ b/lisp/erc/erc-notify.el
@@ -1,6 +1,6 @@
;;; erc-notify.el --- Online status change notification -*- lexical-binding:t -*-
-;; Copyright (C) 2002-2004, 2006-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2004, 2006-2024 Free Software Foundation, Inc.
;; Author: Mario Lang <mlang@lexx.delysid.org>
;; Maintainer: Amin Bandali <bandali@gnu.org>, F. Jason Park <jp@neverwas.me>
@@ -30,7 +30,6 @@
;;; Code:
(require 'erc)
-(require 'erc-networks)
(eval-when-compile (require 'pcomplete))
;;;; Customizable variables
@@ -78,12 +77,14 @@ strings."
;;;; Setup
(defun erc-notify-install-message-catalogs ()
- (erc-define-catalog
- 'english
- '((notify_current . "Notified people online: %l")
- (notify_list . "Current notify list: %l")
- (notify_on . "Detected %n on IRC network %m")
- (notify_off . "%n has left IRC network %m"))))
+ (declare (obsolete "defined at top level in erc-notify.el" "30.1"))
+ (with-suppressed-warnings ((obsolete erc-define-catalog))
+ (erc-define-catalog
+ 'english
+ '((notify-current . "Notified people online: %l")
+ (notify-list . "Current notify list: %l")
+ (notify-on . "Detected %n on IRC network %m")
+ (notify-off . "%n has left IRC network %m")))))
;;;###autoload(autoload 'erc-notify-mode "erc-notify" nil t)
(define-erc-module notify nil
@@ -119,14 +120,14 @@ changes."
(run-hook-with-args 'erc-notify-signon-hook server (car new-list))
(erc-display-message
parsed 'notice proc
- 'notify_on ?n (car new-list) ?m (erc-network-name)))
+ 'notify-on ?n (car new-list) ?m (erc-network-name)))
(setq new-list (cdr new-list)))
(while old-list
(when (not (erc-member-ignore-case (car old-list) ison-list))
(run-hook-with-args 'erc-notify-signoff-hook server (car old-list))
(erc-display-message
parsed 'notice proc
- 'notify_off ?n (car old-list) ?m (erc-network-name)))
+ 'notify-off ?n (car old-list) ?m (erc-network-name)))
(setq old-list (cdr old-list)))
(setq erc-last-ison ison-list)
t)))
@@ -136,8 +137,8 @@ changes."
(defun erc-notify-JOIN (proc parsed)
"Check if channel joiner is on `erc-notify-list' and not on `erc-last-ison'.
-If this condition is satisfied, produce a notify_on message and add the nick
-to `erc-last-ison' to prevent any further notifications."
+When that's the case, produce a `notify-on' message and add the
+nick to `erc-last-ison' to prevent any further notifications."
(let ((nick (erc-extract-nick (erc-response.sender parsed))))
(when (and (erc-member-ignore-case nick erc-notify-list)
(not (erc-member-ignore-case nick erc-last-ison)))
@@ -147,13 +148,13 @@ to `erc-last-ison' to prevent any further notifications."
nick)
(erc-display-message
parsed 'notice proc
- 'notify_on ?n nick ?m (erc-network-name)))
+ 'notify-on ?n nick ?m (erc-network-name)))
nil))
(defun erc-notify-NICK (proc parsed)
"Check if new nick is on `erc-notify-list' and not on `erc-last-ison'.
-If this condition is satisfied, produce a notify_on message and add the nick
-to `erc-last-ison' to prevent any further notifications."
+When that's the case, produce a `notify-on' message and add the
+nick to `erc-last-ison' to prevent any further notifications."
(let ((nick (erc-response.contents parsed)))
(when (and (erc-member-ignore-case nick erc-notify-list)
(not (erc-member-ignore-case nick erc-last-ison)))
@@ -163,13 +164,13 @@ to `erc-last-ison' to prevent any further notifications."
nick)
(erc-display-message
parsed 'notice proc
- 'notify_on ?n nick ?m (erc-network-name)))
+ 'notify-on ?n nick ?m (erc-network-name)))
nil))
(defun erc-notify-QUIT (proc parsed)
"Check if quitter is on `erc-notify-list' and on `erc-last-ison'.
-If this condition is satisfied, produce a notify_off message and remove the
-nick from `erc-last-ison' to prevent any further notifications."
+When that's the case, insert a `notify-off' message and remove
+the nick from `erc-last-ison' to prevent further notifications."
(let ((nick (erc-extract-nick (erc-response.sender parsed))))
(when (and (erc-member-ignore-case nick erc-notify-list)
(erc-member-ignore-case nick erc-last-ison))
@@ -183,7 +184,7 @@ nick from `erc-last-ison' to prevent any further notifications."
nick)
(erc-display-message
parsed 'notice proc
- 'notify_off ?n nick ?m (erc-network-name)))
+ 'notify-off ?n nick ?m (erc-network-name)))
nil))
;;;; User level command
@@ -193,6 +194,12 @@ nick from `erc-last-ison' to prevent any further notifications."
"Change `erc-notify-list' or list current notify-list members online.
Without args, list the current list of notified people online,
with args, toggle notify status of people."
+ (unless erc-notify-mode
+ (erc-notify-mode +1)
+ (erc-button--display-error-notice-with-keys
+ (current-buffer)
+ "Command /NOTIFY requires the `notify' module. Enabling now. Add `notify'"
+ " to `erc-modules' before next starting ERC to silence this message."))
(cond
((null args)
;; Print current notified people (online)
@@ -202,11 +209,12 @@ with args, toggle notify status of people."
nil 'notice 'active "No ison-list yet!")
(erc-display-message
nil 'notice 'active
- 'notify_current ?l ison))))
+ 'notify-current ?l ison))))
((string= (car args) "-l")
- (erc-display-message nil 'notice 'active
- 'notify_list ?l (mapconcat #'identity erc-notify-list
- " ")))
+ (let ((list (if erc-notify-list
+ (mapconcat #'identity erc-notify-list " ")
+ "(empty)")))
+ (erc-display-message nil 'notice 'active 'notify-list ?l list)))
(t
(while args
(if (erc-member-ignore-case (car args) erc-notify-list)
@@ -218,28 +226,41 @@ with args, toggle notify status of people."
;; from your notify list.
(dolist (buf (erc-buffer-list))
(with-current-buffer buf
- (if (erc-server-buffer-p)
+ ;; FIXME replace with `erc--server-buffer-p' or
+ ;; explain why that's unwise.
+ (if (erc-server-or-unjoined-channel-buffer-p)
(setq erc-last-ison (delete (car args) erc-last-ison))))))
(setq erc-notify-list (cons (erc-string-no-properties (car args))
erc-notify-list)))
(setq args (cdr args)))
- (erc-display-message
- nil 'notice 'active
- 'notify_list ?l (mapconcat #'identity erc-notify-list " "))))
+ (erc-cmd-NOTIFY "-l")))
t)
-(autoload 'pcomplete-erc-all-nicks "erc-pcomplete")
-
;; "--" is not a typo.
(declare-function pcomplete--here "pcomplete"
(&optional form stub paring form-only))
+(declare-function pcomplete-erc-all-nicks "erc-pcomplete"
+ (&optional postfix))
;;;###autoload
(defun pcomplete/erc-mode/NOTIFY ()
- (require 'pcomplete)
- (pcomplete-here (pcomplete-erc-all-nicks)))
-
-(erc-notify-install-message-catalogs)
+ (require 'erc-pcomplete)
+ (pcomplete-here (append erc-notify-list (pcomplete-erc-all-nicks))))
+
+(define-obsolete-variable-alias 'erc-message-english-notify_on
+ 'erc-message-english-notify-on "30.1")
+(define-obsolete-variable-alias 'erc-message-english-notify_off
+ 'erc-message-english-notify-off "30.1")
+(define-obsolete-variable-alias 'erc-message-english-notify_list
+ 'erc-message-english-notify-list "30.1")
+(define-obsolete-variable-alias 'erc-message-english-notify_current
+ 'erc-message-english-notify-current "30.1")
+
+(erc-define-message-format-catalog english
+ (notify-current . "Notified people online: %l")
+ (notify-list . "Current notify list: %l")
+ (notify-on . "Detected %n on IRC network %m")
+ (notify-off . "%n has left IRC network %m"))
(provide 'erc-notify)
diff --git a/lisp/erc/erc-page.el b/lisp/erc/erc-page.el
index a94678e5132..7e777adfaf9 100644
--- a/lisp/erc/erc-page.el
+++ b/lisp/erc/erc-page.el
@@ -1,6 +1,6 @@
;;; erc-page.el --- CTCP PAGE support for ERC -*- lexical-binding: t; -*-
-;; Copyright (C) 2002, 2004, 2006-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002, 2004, 2006-2024 Free Software Foundation, Inc.
;; Maintainer: Amin Bandali <bandali@gnu.org>, F. Jason Park <jp@neverwas.me>
@@ -42,7 +42,8 @@
"Process CTCP PAGE requests from IRC."
nil nil)
-(erc-define-catalog-entry 'english 'CTCP-PAGE "Page from %n (%u@%h): %m")
+(defvar erc-message-english-CTCP-PAGE "Page from %n (%u@%h): %m"
+ "English template for a CTCP PAGE message.")
(defcustom erc-page-function nil
"A function to process a \"page\" request.
diff --git a/lisp/erc/erc-pcomplete.el b/lisp/erc/erc-pcomplete.el
index 7eb7431fb91..52ebdc83e5e 100644
--- a/lisp/erc/erc-pcomplete.el
+++ b/lisp/erc/erc-pcomplete.el
@@ -1,6 +1,6 @@
;;; erc-pcomplete.el --- Provides programmable completion for ERC -*- lexical-binding: t; -*-
-;; Copyright (C) 2002-2004, 2006-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2004, 2006-2024 Free Software Foundation, Inc.
;; Author: Sacha Chua <sacha@free.net.ph>
;; Maintainer: Amin Bandali <bandali@gnu.org>, F. Jason Park <jp@neverwas.me>
diff --git a/lisp/erc/erc-replace.el b/lisp/erc/erc-replace.el
index 8c1c35b46d7..6374a8773d3 100644
--- a/lisp/erc/erc-replace.el
+++ b/lisp/erc/erc-replace.el
@@ -1,6 +1,6 @@
;;; erc-replace.el --- wash and massage messages inserted into the buffer -*- lexical-binding: t; -*-
-;; Copyright (C) 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2024 Free Software Foundation, Inc.
;; Author: Andreas Fuchs <asf@void.at>
;; Maintainer: Amin Bandali <bandali@gnu.org>, F. Jason Park <jp@neverwas.me>
diff --git a/lisp/erc/erc-ring.el b/lisp/erc/erc-ring.el
index 4534e913204..d05d44044ea 100644
--- a/lisp/erc/erc-ring.el
+++ b/lisp/erc/erc-ring.el
@@ -1,6 +1,6 @@
;;; erc-ring.el --- Command history handling for erc using ring.el -*- lexical-binding: t; -*-
-;; Copyright (C) 2001-2004, 2006-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2004, 2006-2024 Free Software Foundation, Inc.
;; Author: Alex Schroeder <alex@gnu.org>
;; Maintainer: Amin Bandali <bandali@gnu.org>, F. Jason Park <jp@neverwas.me>
diff --git a/lisp/erc/erc-sasl.el b/lisp/erc/erc-sasl.el
index c6922b1b26b..f1cc68e2620 100644
--- a/lisp/erc/erc-sasl.el
+++ b/lisp/erc/erc-sasl.el
@@ -1,6 +1,6 @@
;;; erc-sasl.el --- SASL for ERC -*- lexical-binding: t -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;;
;; This file is part of GNU Emacs.
;;
@@ -305,9 +305,8 @@ If necessary, pass PROMPT to `read-passwd'."
(| eot ",")))
(downcase offered)))
-(erc-define-catalog
- 'english
- '((s902 . "ERR_NICKLOCKED nick %n unavailable: %s")
+(erc--define-catalog english
+ ((s902 . "ERR_NICKLOCKED nick %n unavailable: %s")
(s904 . "ERR_SASLFAIL (authentication failed) %s")
(s905 . "ERR SASLTOOLONG (credentials too long) %s")
(s906 . "ERR_SASLABORTED (authentication aborted) %s")
@@ -333,8 +332,8 @@ This doesn't solicit or validate a suite of supported mechanisms."
(client (erc-sasl--create-client mech)))
(unless client
(erc-display-error-notice
- nil (format "Unknown or unsupported SASL mechanism: %s" mech))
- (erc-error "Unknown or unsupported SASL mechanism: %s" mech))
+ nil (format "Unknown or unsupported SASL mechanism: `%s'" mech))
+ (error "Unknown or unsupported SASL mechanism: `%s'" mech))
(setf (erc-sasl--state-client erc-sasl--state) client))))
((kill-local-variable 'erc-sasl--state)
(kill-local-variable 'erc-sasl--options))
@@ -371,9 +370,10 @@ This doesn't solicit or validate a suite of supported mechanisms."
(setq data (concat (substring data end) (and (= end 400) "+"))))))))
(defun erc-sasl--destroy (proc)
- (run-hook-with-args 'erc-quit-hook proc)
+ "Destroy process PROC and warn user that their settings are likely faulty."
(delete-process proc)
- (erc-error "Disconnected from %s; please review SASL settings" proc))
+ (erc--lwarn 'erc-sasl :error
+ "Disconnected from %s; please review SASL settings" proc))
(define-erc-response-handler (902)
"Handle an ERR_NICKLOCKED response." nil
diff --git a/lisp/erc/erc-services.el b/lisp/erc/erc-services.el
index 47c59f76b5c..92cb9075b5e 100644
--- a/lisp/erc/erc-services.el
+++ b/lisp/erc/erc-services.el
@@ -1,6 +1,6 @@
;;; erc-services.el --- Identify to NickServ -*- lexical-binding:t -*-
-;; Copyright (C) 2002-2004, 2006-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2004, 2006-2024 Free Software Foundation, Inc.
;; Maintainer: Amin Bandali <bandali@gnu.org>, F. Jason Park <jp@neverwas.me>
;; URL: https://www.emacswiki.org/emacs/ErcNickserv
@@ -169,7 +169,7 @@ You can also use \\[erc-nickserv-identify-mode] to change modes."
:type 'boolean)
(defcustom erc-use-auth-source-for-nickserv-password nil
- "Query auth-source for a password when identifiying to NickServ.
+ "Query auth-source for a password when identifying to NickServ.
Passwords from `erc-nickserv-passwords' take precedence. See
function `erc-nickserv-get-password'."
:version "28.1"
diff --git a/lisp/erc/erc-sound.el b/lisp/erc/erc-sound.el
index 083d72805df..f1c6601427f 100644
--- a/lisp/erc/erc-sound.el
+++ b/lisp/erc/erc-sound.el
@@ -1,6 +1,6 @@
;;; erc-sound.el --- CTCP SOUND support for ERC -*- lexical-binding: t -*-
-;; Copyright (C) 2002-2003, 2006-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2003, 2006-2024 Free Software Foundation, Inc.
;; Maintainer: Amin Bandali <bandali@gnu.org>, F. Jason Park <jp@neverwas.me>
;; URL: https://www.emacswiki.org/emacs/ErcSound
@@ -63,7 +63,8 @@ and play sound files as requested."
((remove-hook 'erc-ctcp-query-SOUND-hook #'erc-ctcp-query-SOUND)
(define-key erc-mode-map "\C-c\C-s" #'undefined)))
-(erc-define-catalog-entry 'english 'CTCP-SOUND "%n (%u@%h) plays %s:%m")
+(defvar erc-message-english-CTCP-SOUND "%n (%u@%h) plays %s:%m"
+ "English template for a CTCP SOUND message.")
(defcustom erc-play-sound t
"Play sounds when you receive CTCP SOUND requests."
diff --git a/lisp/erc/erc-speedbar.el b/lisp/erc/erc-speedbar.el
index f5fbaac767d..5fcea056e3e 100644
--- a/lisp/erc/erc-speedbar.el
+++ b/lisp/erc/erc-speedbar.el
@@ -1,6 +1,6 @@
;;; erc-speedbar.el --- Speedbar support for ERC -*- lexical-binding: t; -*-
-;; Copyright (C) 2001-2004, 2006-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2004, 2006-2024 Free Software Foundation, Inc.
;; Author: Mario Lang <mlang@delysid.org>
;; Contributor: Eric M. Ludlam <zappo@gnu.org>
@@ -54,7 +54,7 @@ node `(speedbar) Top' for more about the underlying integration."
(defcustom erc-speedbar-nicknames-window-width 18
"Default width of the nicknames sidebar (in columns)."
- :package-version '(ERC . "5.6") ; FIXME sync on release
+ :package-version '(ERC . "5.6")
:type 'integer)
(defcustom erc-speedbar-sort-users-type 'activity
@@ -69,7 +69,7 @@ nil - Do not sort users"
(defcustom erc-speedbar-hide-mode-topic 'headerline
"Hide mode and topic lines."
- :package-version '(ERC . "5.6") ; FIXME sync on release
+ :package-version '(ERC . "5.6")
:type '(choice (const :tag "Always show" nil)
(const :tag "Always hide" t)
(const :tag "Omit when headerline visible" headerline)))
@@ -81,7 +81,7 @@ When the value is t, ERC uses `erc-current-nick-face' if
When using the `nicks' module, you can see your nick as it
appears to others by coordinating with the option
`erc-nicks-skip-faces'."
- :package-version '(ERC . "5.6") ; FIXME sync on release
+ :package-version '(ERC . "5.6")
:type '(choice face (const :tag "Current nick or own speaker face" t)))
(defvar erc-speedbar-key-map nil
@@ -135,7 +135,15 @@ This will add a speedbar major display mode."
(erase-buffer)
(let (serverp chanp queryp)
(with-current-buffer buffer
- (setq serverp (erc-server-buffer-p))
+ ;; The function `dframe-help-echo' checks the default value of
+ ;; `dframe-help-echo-function' when deciding whether to visit
+ ;; the buffer and fire the callback. This works in normal
+ ;; speedbar frames because the event handler runs in the
+ ;; `window-buffer' of the active frame. But in our hacked
+ ;; version, where the frame is hidden, `speedbar-item-info'
+ ;; never runs without this workaround.
+ (setq-local dframe-help-echo-function #'ignore)
+ (setq serverp (erc--server-buffer-p))
(setq chanp (erc-channel-p (erc-default-target)))
(setq queryp (erc-query-buffer-p)))
(cond (serverp
@@ -212,6 +220,11 @@ This will add a speedbar major display mode."
(buffer-name buffer) 'erc-speedbar-goto-buffer buffer nil
depth)))
+(defconst erc-speedbar--fmt-sentinel (gensym "erc-speedbar-")
+ "Symbol for identifying a nonstandard `speedbar-token' text property.
+When encountered, ERC assumes the value's tail contains
+`format'-compatible args.")
+
(defun erc-speedbar-expand-channel (text channel indent)
"For the line matching TEXT, in CHANNEL, expand or contract a line.
INDENT is the current indentation level."
@@ -221,35 +234,17 @@ INDENT is the current indentation level."
(speedbar-with-writable
(save-excursion
(end-of-line) (forward-char 1)
- (let ((modes (with-current-buffer channel
- (concat (apply #'concat
- erc-channel-modes)
- (cond
- ((and erc-channel-user-limit
- erc-channel-key)
- (if erc-show-channel-key-p
- (format "lk %.0f %s"
- erc-channel-user-limit
- erc-channel-key)
- (format "kl %.0f" erc-channel-user-limit)))
- (erc-channel-user-limit
- ;; Emacs has no bignums
- (format "l %.0f" erc-channel-user-limit))
- (erc-channel-key
- (if erc-show-channel-key-p
- (format "k %s" erc-channel-key)
- "k"))
- (t "")))))
+ (let ((modes (buffer-local-value 'erc--mode-line-mode-string channel))
(topic (erc-controls-interpret
(with-current-buffer channel erc-channel-topic))))
- (speedbar-make-tag-line
- 'angle ?i nil nil
- (concat "Modes: +" modes) nil nil nil
- (1+ indent))
+ (when modes
+ (speedbar-make-tag-line
+ 'angle ?m nil (list erc-speedbar--fmt-sentinel "Mode: %s" modes)
+ modes nil nil 'erc-notice-face (1+ indent)))
(unless (string= topic "")
(speedbar-make-tag-line
- 'angle ?i nil nil
- (concat "Topic: " topic) nil nil nil
+ 'angle ?t nil (list erc-speedbar--fmt-sentinel "Topic: %s" topic)
+ topic nil nil 'erc-notice-face
(1+ indent)))
(unless (pcase erc-speedbar-hide-mode-topic
('nil 'show)
@@ -324,9 +319,9 @@ a list of four items: the userhost, the GECOS, the current
(info (erc-server-user-info user))
(login (erc-server-user-login user))
(name (erc-server-user-full-name user))
- (voice (and cuser (erc-channel-user-voice cuser)))
- (op (and cuser (erc-channel-user-op cuser)))
- (nick-str (concat (if op "@" "") (if voice "+" "") nick))
+ (nick-str (concat (with-current-buffer (or buffer (current-buffer))
+ (erc-get-channel-membership-prefix cuser))
+ nick))
(finger (concat login (when (or login host) "@") host))
(sbtoken (list finger name info (buffer-name buffer))))
(if (or login host name info) ; we want to be expandable
@@ -428,6 +423,13 @@ The INDENT level is ignored."
(message "%s: %s" txt (car data)))
((bufferp data)
(message "Channel: %s" txt))
+ ;; Print help if line has a non-standard ([-+?=]) button
+ ;; char and a `speedbar-token' property with a known CAR.
+ ((and-let* ((p (text-property-not-all (pos-bol) (pos-eol)
+ 'speedbar-token nil))
+ (v (get-text-property p 'speedbar-token))
+ ((eq erc-speedbar--fmt-sentinel (car v))))
+ (apply #'message (cdr v))))
(t
(message "%s" txt)))))
@@ -439,7 +441,6 @@ The INDENT level is ignored."
(defvar erc-status-sidebar-buffer-name)
(declare-function erc-status-sidebar-set-window-preserve-size
"erc-status-sidebar" nil)
-(declare-function erc-status-sidebar-mode--unhook "erc-status-sidebar" nil)
(defvar erc-speedbar--buffer-options
'((speedbar-update-flag . t)
@@ -454,10 +455,7 @@ The INDENT level is ignored."
`(display-buffer-in-side-window
. ((side . right)
(window-width . ,erc-speedbar-nicknames-window-width)))))
- (erc-status-sidebar-set-window-preserve-size)
- (when-let ((window (get-buffer-window speedbar-buffer)))
- (set-window-parameter window 'no-other-window nil)
- (internal-show-cursor window t))))
+ (erc-status-sidebar-set-window-preserve-size)))
(defun erc-speedbar--status-sidebar-mode--unhook ()
"Remove hooks installed by `erc-status-sidebar-mode'."
@@ -470,6 +468,7 @@ The INDENT level is ignored."
(cl-assert (eq speedbar-buffer (current-buffer)))
(cl-assert (eq speedbar-frame (selected-frame)))
(setq erc-speedbar--hidden-speedbar-frame speedbar-frame
+ ;; In Emacs 27, this is not `local-variable-if-set-p'.
dframe-controlled #'erc-speedbar--dframe-controlled)
(add-hook 'window-configuration-change-hook
#'erc-speedbar--emulate-sidebar-set-window-preserve-size nil t)
@@ -490,36 +489,66 @@ The INDENT level is ignored."
(cl-assert (buffer-live-p speedbar-buffer))
(if (or (and force (< arg 0))
(and (not force) (get-buffer-window speedbar-buffer nil)))
- (erc-speedbar-close-nicknames-window nil)
+ ;; Close associated windows and stop updating but leave timer.
+ (progn
+ (dolist (window (get-buffer-window-list speedbar-buffer nil t))
+ (unless (frame-root-window-p window)
+ (when erc-speedbar--hidden-speedbar-frame
+ (cl-assert
+ (not (eq (window-frame window)
+ erc-speedbar--hidden-speedbar-frame))))
+ (delete-window window)))
+ (with-current-buffer speedbar-buffer
+ (setq speedbar-update-flag nil)
+ (speedbar-set-mode-line-format)))
(when (or (not force) (>= arg 0))
(with-selected-frame speedbar-frame
- (erc-speedbar--emulate-sidebar-set-window-preserve-size)))))
- (when (or (not force) (>= arg 0))
- (let ((speedbar-frame-parameters (backquote-list*
- '(visibility . nil)
- '(no-other-frame . t)
- speedbar-frame-parameters))
- (speedbar-after-create-hook #'erc-speedbar--emulate-sidebar))
- (erc-speedbar-browser)
- ;; If we put the remaining parts in the "create hook" along
- ;; with everything else, the frame with `window-main-window'
- ;; gets raised and steals focus if you've switched away from
- ;; Emacs in the meantime.
- (make-frame-invisible speedbar-frame)
- (select-frame (setq speedbar-frame (previous-frame)))
- (erc-speedbar--emulate-sidebar-set-window-preserve-size))))))
+ (erc-speedbar--emulate-sidebar-set-window-preserve-size)
+ (erc-speedbar-toggle-nicknames-window-lock -1)))))
+ (when-let (((or (not force) (>= arg 0)))
+ (speedbar-frame-parameters (backquote-list*
+ '(visibility . nil)
+ '(no-other-frame . t)
+ speedbar-frame-parameters))
+ (speedbar-after-create-hook #'erc-speedbar--emulate-sidebar))
+ (erc-install-speedbar-variables)
+ ;; Run before toggling mode to prevent timer from being
+ ;; created twice.
+ (speedbar-change-initial-expansion-list "ERC")
+ (speedbar-frame-mode 1)
+ ;; If we put the remaining parts in the "create hook" along
+ ;; with everything else, the frame with `window-main-window'
+ ;; gets raised and steals focus if you've switched away from
+ ;; Emacs in the meantime.
+ (make-frame-invisible speedbar-frame)
+ (select-frame (setq speedbar-frame (previous-frame)))
+ (erc-speedbar--emulate-sidebar-set-window-preserve-size)
+ (erc-speedbar-toggle-nicknames-window-lock -1))))
+ (cl-assert (not (cdr (erc-speedbar--get-timers))) t))
(defun erc-speedbar--ensure (&optional force)
(when (or (erc-server-buffer) force)
(when erc-track-mode
(cl-pushnew '(derived-mode . speedbar-mode)
erc-track--switch-fallback-blockers :test #'equal))
+ (unless speedbar-update-flag
+ (erc-button--display-error-notice-with-keys
+ (erc-server-buffer)
+ "Module `nickbar' needs `speedbar-update-flag' to be non-nil"
+ (and (not (display-graphic-p)) " in text terminals")
+ ". Setting to t for the current Emacs session."
+ " Customize it permanently to avoid this message.")
+ (setq speedbar-update-flag t))
(erc-speedbar--toggle-nicknames-sidebar +1)
- (speedbar-enable-update)))
+ (with-current-buffer speedbar-buffer
+ (setq speedbar-update-flag t)
+ (speedbar-set-mode-line-format))))
+
+(defvar erc-speedbar--shutting-down-p nil)
;;;###autoload(autoload 'erc-nickbar-mode "erc-speedbar" nil t)
(define-erc-module nickbar nil
- "Show nicknames in a side window.
+ "Show nicknames for current target buffer in a side window.
When enabling, create a speedbar session if one doesn't exist and
show its buffer in an `erc-status-sidebar' window instead of a
separate frame. When disabling, close the window or, with a
@@ -527,70 +556,73 @@ negative prefix arg, destroy the session.
WARNING: this module may produce unwanted side effects, like the
raising of frames or the stealing of input focus. If you witness
-such an occurrence, and can reproduce it, please file a bug
-report with \\[erc-bug]."
+such a thing and can reproduce it, please file a bug report with
+\\[erc-bug]."
((add-hook 'erc--setup-buffer-hook #'erc-speedbar--ensure)
(erc-speedbar--ensure)
(unless (or erc--updating-modules-p
(and-let* ((speedbar-buffer)
(win (get-buffer-window speedbar-buffer 'all-frames))
((eq speedbar-frame (window-frame win))))))
- (if speedbar-buffer
- (erc-speedbar--ensure 'force)
- (setq erc-nickbar-mode nil)
- (when (derived-mode-p 'erc-mode)
- (erc-error "Not initializing `erc-nickbar-mode' in %s"
- (current-buffer))))))
+ (when-let ((buf (or (and (derived-mode-p 'erc-mode) (current-buffer))
+ (car (erc-buffer-filter #'erc--server-buffer-p)))))
+ (with-current-buffer buf
+ (erc-speedbar--ensure 'force)))))
((remove-hook 'erc--setup-buffer-hook #'erc-speedbar--ensure)
- (speedbar-disable-update)
(when erc-track-mode
(setq erc-track--switch-fallback-blockers
(remove '(derived-mode . speedbar-mode)
erc-track--switch-fallback-blockers)))
(erc-speedbar--toggle-nicknames-sidebar -1)
- (when-let ((arg erc--module-toggle-prefix-arg)
+ (when-let (((not erc-speedbar--shutting-down-p))
+ (arg erc--module-toggle-prefix-arg)
((numberp arg))
((< arg 0)))
- (erc-speedbar-close-nicknames-window 'kill))))
+ (with-current-buffer speedbar-buffer
+ (dframe-close-frame)
+ (setq erc-speedbar--hidden-speedbar-frame nil)))))
+
+(defun erc-speedbar--get-timers ()
+ (cl-remove #'dframe-timer-fn timer-idle-list
+ :key #'timer--function
+ :test-not #'eq))
(defun erc-speedbar--dframe-controlled (arg)
+ (when speedbar-buffer
+ (cl-assert (eq speedbar-buffer (current-buffer))))
(when (and erc-speedbar--hidden-speedbar-frame (numberp arg) (< arg 0))
(when erc-nickbar-mode
- (erc-nickbar-mode -1))
+ (let ((erc-speedbar--shutting-down-p t))
+ (erc-nickbar-mode -1)))
(setq speedbar-frame erc-speedbar--hidden-speedbar-frame
erc-speedbar--hidden-speedbar-frame nil)
;; It's unknown whether leaving the frame invisible interferes
- ;; with the upstream teardown procedure.
+ ;; with the upstream teardown sequence.
(when (display-graphic-p)
(make-frame-visible speedbar-frame))
- (speedbar-frame-mode arg)
- (when speedbar-buffer
- (kill-buffer speedbar-buffer)
- (setq speedbar-buffer nil))))
-
-(defun erc-speedbar-toggle-nicknames-window-lock ()
- "Toggle whether nicknames window is selectable with \\[other-window]."
- (interactive)
+ (speedbar-frame-mode arg) ; -1
+ ;; As of Emacs 29, `dframe-set-timer' can't remove `dframe-timer'.
+ (cl-assert (= 1 (length (erc-speedbar--get-timers))) t)
+ (cancel-function-timers #'dframe-timer-fn)
+ ;; `dframe-close-frame' kills the buffer but no function in
+ ;; erc-speedbar.el resets this to nil.
+ (setq speedbar-buffer nil)))
+
+(defun erc-speedbar-toggle-nicknames-window-lock (arg)
+ "Toggle whether nicknames window is selectable with \\[other-window].
+When arg is a number, lock the window if non-negative, otherwise
+unlock."
+ (interactive "P")
(unless erc-nickbar-mode
(user-error "`erc-nickbar-mode' inactive"))
(when-let ((window (get-buffer-window speedbar-buffer)))
- (let ((val (window-parameter window 'no-other-window)))
- (set-window-parameter window 'no-other-window (not val))
- (message "nick-window: %s" (if val "selectable" "protected")))))
-
-(defun erc-speedbar-close-nicknames-window (kill)
- (interactive "P")
- (if kill
- (with-current-buffer speedbar-buffer
- (dframe-close-frame)
- (cl-assert (not erc-nickbar-mode))
- (setq erc-speedbar--hidden-speedbar-frame nil))
- (dolist (window (get-buffer-window-list speedbar-buffer nil t))
- (unless (frame-root-window-p window)
- (when erc-speedbar--hidden-speedbar-frame
- (cl-assert (not (eq (window-frame window)
- erc-speedbar--hidden-speedbar-frame))))
- (delete-window window)))))
+ (let ((val (cond ((natnump arg) t)
+ ((integerp arg) nil)
+ (t (not (window-parameter window
+ 'no-other-window))))))
+ (set-window-parameter window 'no-other-window val)
+ (unless (numberp arg)
+ (message "nick-window: %s" (if val "protected" "selectable"))))))
;;;; Nicks integration
diff --git a/lisp/erc/erc-spelling.el b/lisp/erc/erc-spelling.el
index 83eb849f1b4..b2f565d71bf 100644
--- a/lisp/erc/erc-spelling.el
+++ b/lisp/erc/erc-spelling.el
@@ -1,6 +1,6 @@
;;; erc-spelling.el --- use flyspell in ERC -*- lexical-binding: t; -*-
-;; Copyright (C) 2005-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2005-2024 Free Software Foundation, Inc.
;; Author: Jorgen Schaefer <forcer@forcix.cx>
;; Maintainer: Amin Bandali <bandali@gnu.org>, F. Jason Park <jp@neverwas.me>
diff --git a/lisp/erc/erc-stamp.el b/lisp/erc/erc-stamp.el
index a021cd26607..558afd19427 100644
--- a/lisp/erc/erc-stamp.el
+++ b/lisp/erc/erc-stamp.el
@@ -1,6 +1,6 @@
;;; erc-stamp.el --- Timestamping for ERC messages -*- lexical-binding:t -*-
-;; Copyright (C) 2002-2004, 2006-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2004, 2006-2024 Free Software Foundation, Inc.
;; Author: Mario Lang <mlang@delysid.org>
;; Maintainer: Amin Bandali <bandali@gnu.org>, F. Jason Park <jp@neverwas.me>
@@ -55,21 +55,23 @@ If nil, timestamping is turned off."
:type '(choice (const nil)
(string)))
-;; FIXME remove surrounding whitespace from default value and have
-;; `erc-insert-timestamp-left-and-right' add it before insertion.
-
(defcustom erc-timestamp-format-left "\n[%a %b %e %Y]\n"
- "If set to a string, messages will be timestamped.
-This string is processed using `format-time-string'.
-Good examples are \"%T\" and \"%H:%M\".
-
-This timestamp is used for timestamps on the left side of the
-screen when `erc-insert-timestamp-function' is set to
-`erc-insert-timestamp-left-and-right'.
-
-If nil, timestamping is turned off."
- :type '(choice (const nil)
- (string)))
+ "Format recognized by `format-time-string' for date stamps.
+Only considered when `erc-insert-timestamp-function' is set to
+`erc-insert-timestamp-left-and-right'. Used for displaying date
+stamps on their own line, between messages. ERC inserts this
+flavor of stamp as a separate \"pseudo message\", so a final
+newline isn't necessary. For compatibility, only additional
+trailing newlines beyond the first become empty lines. For
+example, the default value results in an empty line after the
+previous message, followed by the timestamp on its own line,
+followed immediately by the next message on the next line. ERC
+expects to display these stamps less frequently, so the
+formatting specifiers should reflect that. To omit these stamps
+entirely, use a different `erc-insert-timestamp-function', such
+as `erc-timestamp-format-right'. Note that changing this value
+during an ERC session requires cycling `erc-stamp-mode'."
+ :type 'string)
(defcustom erc-timestamp-format-right nil
"If set to a string, messages will be timestamped.
@@ -83,7 +85,7 @@ screen when `erc-insert-timestamp-function' is set to
Unlike `erc-timestamp-format' and `erc-timestamp-format-left', if
the value of this option is nil, it falls back to using the value
of `erc-timestamp-format'."
- :package-version '(ERC . "5.6") ; FIXME sync on release
+ :package-version '(ERC . "5.6")
:type '(choice (const nil)
(string)))
(make-obsolete-variable 'erc-timestamp-format-right
@@ -136,14 +138,28 @@ hidden, they will still be present in the logs."
"If non-nil, print timestamp in the minibuffer when point is moved.
Using this variable, you can turn off normal timestamping,
and simply move point to an irc message to see its timestamp
-printed in the minibuffer."
+printed in the minibuffer. When attempting to enable this option
+after `erc-stamp-mode' is already active, you may need to run the
+command `erc-show-timestamps' (or `erc-hide-timestamps') in the
+appropriate ERC buffer before the change will take effect."
:type 'boolean)
(defcustom erc-echo-timestamp-format "Timestamped %A, %H:%M:%S"
"Format string to be used when `erc-echo-timestamps' is non-nil.
This string specifies the format of the timestamp being echoed in
the minibuffer."
- :type 'string)
+ :type '(choice (const :tag "Timestamped Monday, 15:04:05"
+ "Timestamped %A, %H:%M:%S")
+ (const :tag "2006-01-02 15:04:05 MST" "%F %T %Z")
+ string))
+
+(defcustom erc-echo-timestamp-zone nil
+ "Default timezone for the option `erc-echo-timestamps'.
+Also affects the command `erc-echo-timestamp' (singular). See
+the ZONE parameter of `format-time-string' for a description of
+acceptable value types."
+ :type '(choice boolean number (const wall) (list number string))
+ :package-version '(ERC . "5.6"))
(defcustom erc-timestamp-intangible nil
"Whether the timestamps should be intangible, i.e. prevent the point
@@ -162,22 +178,18 @@ from entering them and instead jump over them."
;;;###autoload(autoload 'erc-timestamp-mode "erc-stamp" nil t)
(define-erc-module stamp timestamp
"This mode timestamps messages in the channel buffers."
- ((add-hook 'erc-mode-hook #'erc-munge-invisibility-spec)
- (add-hook 'erc-insert-modify-hook #'erc-add-timestamp 60)
- (add-hook 'erc-send-modify-hook #'erc-add-timestamp 60)
+ ((add-hook 'erc-mode-hook #'erc-stamp--setup)
+ (add-hook 'erc-insert-modify-hook #'erc-add-timestamp 70)
+ (add-hook 'erc-send-modify-hook #'erc-add-timestamp 70)
(add-hook 'erc-mode-hook #'erc-stamp--recover-on-reconnect)
- (add-hook 'erc--pre-clear-functions #'erc-stamp--reset-on-clear)
- (unless erc--updating-modules-p
- (erc-buffer-do #'erc-munge-invisibility-spec)))
+ (add-hook 'erc--pre-clear-functions #'erc-stamp--reset-on-clear 40)
+ (unless erc--updating-modules-p (erc-buffer-do #'erc-stamp--setup)))
((remove-hook 'erc-mode-hook #'erc-munge-invisibility-spec)
(remove-hook 'erc-insert-modify-hook #'erc-add-timestamp)
(remove-hook 'erc-send-modify-hook #'erc-add-timestamp)
(remove-hook 'erc-mode-hook #'erc-stamp--recover-on-reconnect)
(remove-hook 'erc--pre-clear-functions #'erc-stamp--reset-on-clear)
- (erc-with-all-buffers-of-server nil nil
- (kill-local-variable 'erc-timestamp-last-inserted)
- (kill-local-variable 'erc-timestamp-last-inserted-left)
- (kill-local-variable 'erc-timestamp-last-inserted-right))))
+ (erc-buffer-do #'erc-stamp--setup)))
(defvar erc-stamp--invisible-property nil
"Existing `invisible' property value and/or symbol `timestamp'.")
@@ -200,41 +212,65 @@ 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.
-This becomes the message's `erc-timestamp' text property, which
-may not be unique, `equal'-wise."
- (erc-current-time))
+This becomes the message's `erc--ts' text property."
+ (erc-compat--current-lisp-time))
(cl-defmethod erc-stamp--current-time :around ()
(or erc-stamp--current-time (cl-call-next-method)))
+(defvar erc-stamp--skip nil
+ "Non-nil means inhibit `erc-add-timestamp' completely.")
+
+(defvar erc-stamp--allow-unmanaged nil
+ "Non-nil means run `erc-add-timestamp' almost unconditionally.
+This is an unofficial escape hatch for code wanting to use
+lower-level message-insertion functions, like `erc-insert-line',
+directly. Third parties needing such functionality should
+petition for it via \\[erc-bug].")
+
+(defvar erc-stamp--permanent-cursor-sensor-functions nil
+ "Non-nil means add `cursor-sensor-functions' unconditionally.
+This is an unofficial escape hatch for code wanting the text
+property `cursor-sensor-functions' to always be present,
+regardless of the option `erc-echo-timestamps'. Third parties
+needing such pre-5.6 behavior to stick around should make that
+known via \\[erc-bug].")
+
(defun erc-add-timestamp ()
"Add timestamp and text-properties to message.
This function is meant to be called from `erc-insert-modify-hook'
or `erc-send-modify-hook'."
- (progn ; remove this `progn' on next major refactor
+ (unless (or erc-stamp--skip (and (not erc-stamp--allow-unmanaged)
+ (null erc--msg-props)))
(let* ((ct (erc-stamp--current-time))
(invisible (get-text-property (point-min) 'invisible))
(erc-stamp--invisible-property
;; FIXME on major version bump, make this `erc-' prefixed.
(if invisible `(timestamp ,@(ensure-list invisible)) 'timestamp))
+ (skipp (or (and erc-stamp--skip-when-invisible invisible)
+ (erc--check-msg-prop 'erc--ephemeral)))
(erc-stamp--current-time ct))
- (unless (setq invisible (and erc-stamp--skip-when-invisible invisible))
+ (when erc--msg-props
+ (puthash 'erc--ts ct erc--msg-props))
+ (unless skipp
(funcall erc-insert-timestamp-function
(erc-format-timestamp ct erc-timestamp-format)))
- ;; FIXME this will error when advice has been applied.
- (when (and (not invisible) (fboundp erc-insert-away-timestamp-function)
- erc-away-timestamp-format
- (erc-away-time)
- (not erc-timestamp-format))
+ ;; Check `erc-insert-away-timestamp-function' for historical
+ ;; reasons even though its Custom :type only allows functions.
+ (when (and (not (or skipp erc-timestamp-format))
+ erc-away-timestamp-format
+ (functionp erc-insert-away-timestamp-function)
+ (erc-away-time))
(funcall erc-insert-away-timestamp-function
(erc-format-timestamp ct erc-away-timestamp-format)))
- (add-text-properties (point-min) (1- (point-max))
+ (when erc-stamp--permanent-cursor-sensor-functions
+ (add-text-properties (point-min) (max (point-min) (1- (point-max)))
;; It's important for the function to
;; be different on different entries (bug#22700).
(list 'cursor-sensor-functions
;; Regions are no longer contiguous ^
- '(erc--echo-ts-csf) 'erc-timestamp ct)))))
+ '(erc--echo-ts-csf) 'erc--ts ct))))))
(defvar-local erc-timestamp-last-window-width nil
"The width of the last window that showed the current buffer.
@@ -245,9 +281,11 @@ buffer is not shown in any window.")
"Last timestamp inserted into the buffer.")
(defvar-local erc-timestamp-last-inserted-left nil
- "Last timestamp inserted into the left side of the buffer.
-This is used when `erc-insert-timestamp-function' is set to
-`erc-timestamp-left-and-right'")
+ "Last \"date stamp\" inserted into the left side of the buffer.
+Used when `erc-insert-timestamp-function' is set to
+`erc-timestamp-left-and-right'. If the format string specified
+by `erc-timestamp-format-left' includes trailing newlines, this
+value omits the last one.")
(defvar-local erc-timestamp-last-inserted-right nil
"Last timestamp inserted into the right side of the buffer.
@@ -289,7 +327,7 @@ option adds a space after the end of a message if the stamp
doesn't already start with one. And when its value is t, it adds
a single space, unconditionally."
:type '(choice boolean integer)
- :package-version '(ERC . "5.6")) ; FIXME sync on release
+ :package-version '(ERC . "5.6"))
(defvar-local erc-stamp--margin-width nil
"Width in columns of margin for `erc-stamp--display-margin-mode'.
@@ -322,7 +360,18 @@ prompt is wider, use its width instead."
(if resetp
(or (and (not (zerop cols)) cols)
erc-stamp--margin-width
- (max (if leftp (string-width (erc-prompt)) 0)
+ (max (if leftp
+ (cond ((fboundp 'erc-fill--wrap-measure)
+ (let* ((b erc-insert-marker)
+ (e (1- erc-input-marker))
+ (w (erc-fill--wrap-measure b e)))
+ (/ (if (consp w) (car w) w)
+ (frame-char-width))))
+ ((fboundp 'string-pixel-width)
+ (/ (string-pixel-width (erc-prompt))
+ (frame-char-width)))
+ (t (string-width (erc-prompt))))
+ 0)
(1+ (string-width
(or (if leftp
erc-timestamp-last-inserted
@@ -347,19 +396,30 @@ non-nil."
(goto-char (point-min))
(while
(progn
- (when-let* (((< (point) (pos-eol)))
- (end (1- (pos-eol)))
- ((eq 'erc-timestamp (field-at-pos end)))
- (beg (field-beginning end))
- ;; Skip a line that's just a timestamp.
- ((> beg (point))))
+ (when-let (((< (point) (pos-eol)))
+ (end (1- (pos-eol)))
+ ((eq 'erc-timestamp (field-at-pos end)))
+ (beg (field-beginning end))
+ ;; Skip a line that's just a timestamp.
+ ((> beg (point))))
(delete-region beg (1+ end)))
- (when-let (time (get-text-property (point) 'erc-timestamp))
+ (when-let (time (erc--get-inserted-msg-prop 'erc--ts))
(insert (format-time-string "[%H:%M:%S] " time)))
(zerop (forward-line))))
"")
-(defvar erc-stamp--inherited-props '(line-prefix wrap-prefix))
+;; These are currently extended manually, but we could also bind
+;; `text-property-default-nonsticky' and call `insert-and-inherit'
+;; instead of `insert', but we'd have to pair the props with differing
+;; boolean values for left and right stamps. Also, since this hook
+;; runs last, we can't expect overriding sticky props to be absent,
+;; even though, as of 5.6, `front-sticky' is only added by the
+;; `readonly' module after hooks run.
+(defvar erc-stamp--inherited-props '(line-prefix wrap-prefix)
+ "Extant properties at the start of a message inherited by the stamp.")
+
+(defvar-local erc-stamp--skip-left-margin-prompt-p nil
+ "Don't display prompt in left margin.")
(declare-function erc--remove-text-properties "erc" (string))
@@ -391,7 +451,8 @@ and `erc-stamp--margin-left-p', before activating the mode."
#'erc--remove-text-properties)
(add-hook 'erc--setup-buffer-hook
#'erc-stamp--refresh-left-margin-prompt nil t)
- (when erc-stamp--margin-left-p
+ (when (and erc-stamp--margin-left-p
+ (not erc-stamp--skip-left-margin-prompt-p))
(add-hook 'erc--refresh-prompt-hook
#'erc-stamp--display-prompt-in-left-margin nil t)))
(remove-function (local 'filter-buffer-substring-function)
@@ -405,6 +466,7 @@ and `erc-stamp--margin-left-p', before activating the mode."
(kill-local-variable (if erc-stamp--margin-left-p
'left-margin-width
'right-margin-width))
+ (kill-local-variable 'erc-stamp--skip-left-margin-prompt-p)
(kill-local-variable 'fringes-outside-margins)
(kill-local-variable 'erc-stamp--margin-left-p)
(kill-local-variable 'erc-stamp--margin-width)
@@ -439,21 +501,22 @@ and `erc-stamp--margin-left-p', before activating the mode."
(setq erc-stamp--last-prompt nil))
(erc--refresh-prompt)))
-(cl-defmethod erc--reveal-prompt
- (&context (erc-stamp--display-margin-mode (eql t))
- (erc-stamp--margin-left-p (eql t)))
- (put-text-property erc-insert-marker (1- erc-input-marker)
- 'display `((margin left-margin) ,erc-stamp--last-prompt)))
-
(cl-defmethod erc--conceal-prompt
(&context (erc-stamp--display-margin-mode (eql t))
- (erc-stamp--margin-left-p (eql t)))
- (let ((prompt (string-pad erc-prompt-hidden left-margin-width nil 'start)))
- (put-text-property erc-insert-marker (1- erc-input-marker)
- 'display `((margin left-margin) ,prompt))))
-
-(cl-defmethod erc-insert-timestamp-left (string)
+ (erc-stamp--margin-left-p (eql t))
+ (erc-stamp--skip-left-margin-prompt-p null))
+ (when-let (((null erc--hidden-prompt-overlay))
+ (prompt (string-pad erc-prompt-hidden left-margin-width nil 'start))
+ (ov (make-overlay erc-insert-marker (1- erc-input-marker)
+ nil 'front-advance)))
+ (overlay-put ov 'display `((margin left-margin) ,prompt))
+ (setq erc--hidden-prompt-overlay ov)))
+
+(defun erc-insert-timestamp-left (string)
"Insert timestamps at the beginning of the line."
+ (erc--insert-timestamp-left string))
+
+(cl-defmethod erc--insert-timestamp-left (string)
(goto-char (point-min))
(let* ((ignore-p (and erc-timestamp-only-if-changed-flag
(string-equal string erc-timestamp-last-inserted)))
@@ -464,13 +527,12 @@ and `erc-stamp--margin-left-p', before activating the mode."
(erc-put-text-property 0 len 'invisible erc-stamp--invisible-property s)
(insert s)))
-(cl-defmethod erc-insert-timestamp-left
+(cl-defmethod erc--insert-timestamp-left
(string &context (erc-stamp--display-margin-mode (eql t)))
(unless (and erc-timestamp-only-if-changed-flag
(string-equal string erc-timestamp-last-inserted))
(goto-char (point-min))
- (insert-before-markers-and-inherit
- (setq erc-timestamp-last-inserted string))
+ (insert-and-inherit (setq erc-timestamp-last-inserted string))
(dolist (p erc-stamp--inherited-props)
(when-let ((v (get-text-property (point) p)))
(put-text-property (point-min) (point) p v)))
@@ -558,8 +620,11 @@ printed just after each line's text (no alignment)."
;; intervening white space unless a hard break is warranted.
(pcase erc-timestamp-use-align-to
((guard erc-stamp--display-margin-mode)
- (put-text-property 0 (length string)
- 'display `((margin right-margin) ,string) string))
+ (let ((s (propertize (substring-no-properties string)
+ 'invisible erc-stamp--invisible-property)))
+ (put-text-property 0 (length string) 'display
+ `((margin right-margin) ,s)
+ string)))
((and 't (guard (< col pos)))
(insert " ")
(put-text-property from (point) 'display `(space :align-to ,pos)))
@@ -584,30 +649,169 @@ printed just after each line's text (no alignment)."
(when erc-timestamp-intangible
(erc-put-text-property from (1+ (point)) 'cursor-intangible t)))))
-(defvar erc-stamp--insert-date-function #'insert
- "Function to insert left \"left-right date\" stamp.
-A local module might use this to modify text properties,
-`insert-before-markers' or renarrow the region after insertion.")
+(defvar erc-stamp--insert-date-hook nil
+ "Functions appended to send and modify hooks when inserting date stamp.")
+
+(defvar-local erc-stamp--date-format-end nil
+ "Tristate value indicating how and whether date stamps have been set up.
+A non-nil value means the buffer has been initialized to use date
+stamps. An integer marks the `substring' TO parameter for
+truncating `erc-timestamp-format-left' prior to rendering. A
+value of t means the option's value doesn't require trimming.")
+
+(defun erc-stamp--propertize-left-date-stamp ()
+ (add-text-properties (point-min) (1- (point-max)) '(field erc-timestamp))
+ (erc--hide-message 'timestamp)
+ (run-hooks 'erc-stamp--insert-date-hook))
+
+(defun erc-stamp--format-date-stamp (ct)
+ "Format left date stamp with `erc-timestamp-format-left'."
+ (unless erc-stamp--date-format-end
+ ;; Don't add text properties to the trailing newline.
+ (setq erc-stamp--date-format-end
+ (if (string-suffix-p "\n" erc-timestamp-format-left) -1 t)))
+ ;; Ignore existing `invisible' prop value because date stamps should
+ ;; never be hideable except via `timestamp'.
+ (let (erc-stamp--invisible-property)
+ (erc-format-timestamp ct (if (numberp erc-stamp--date-format-end)
+ (substring erc-timestamp-format-left
+ 0 erc-stamp--date-format-end)
+ erc-timestamp-format-left))))
+
+(defun erc-stamp-inserting-date-stamp-p ()
+ "Return non-nil if the narrowed buffer contains a date stamp.
+Expect to be called by members of `erc-insert-modify-hook' and
+`erc-insert-post-hook' to detect whether the message being
+inserted is a date stamp."
+ (erc--check-msg-prop 'erc--msg 'datestamp))
+
+;; Calling `erc-display-message' from within a hook it's currently
+;; running is roundabout, but it's a definite means of ensuring hooks
+;; can act on the date stamp as a standalone message to do things like
+;; adjust invisibility props.
+(defun erc-stamp--insert-date-stamp-as-phony-message (string)
+ (cl-assert (string-empty-p string))
+ (setq string erc-timestamp-last-inserted-left)
+ (let ((erc-stamp--skip t)
+ (erc-insert-modify-hook `(,@erc-insert-modify-hook
+ erc-stamp--propertize-left-date-stamp))
+ (erc--insert-line-function #'insert-before-markers)
+ ;; Don't run hooks that aren't expecting a narrowed buffer.
+ (erc-insert-pre-hook nil)
+ (erc-insert-done-hook nil))
+ (erc-display-message nil nil (current-buffer) string)))
+
+(defun erc-stamp--lr-date-on-pre-modify (_)
+ (when-let (((not erc-stamp--skip))
+ (ct (erc-stamp--current-time))
+ (rendered (erc-stamp--format-date-stamp ct))
+ ((not (string-equal rendered erc-timestamp-last-inserted-left)))
+ (erc-insert-timestamp-function
+ #'erc-stamp--insert-date-stamp-as-phony-message))
+ (save-excursion
+ (save-restriction
+ (narrow-to-region (or erc--insert-marker erc-insert-marker)
+ (or erc--insert-marker erc-insert-marker))
+ ;; Ensure all hooks, like `erc-stamp--insert-date-hook', only
+ ;; see the let-bound value below during `erc-add-timestamp'.
+ (setq erc-timestamp-last-inserted-left nil)
+ (let* ((aligned (erc-stamp--time-as-day ct))
+ (erc-stamp--current-time aligned)
+ ;; Forget current `erc--cmd', etc.
+ (erc--msg-props (map-into `((erc--msg . datestamp))
+ 'hash-table))
+ (erc-timestamp-last-inserted-left rendered)
+ erc-timestamp-format erc-away-timestamp-format)
+ ;; FIXME delete once convinced adjustment correct.
+ (cl-assert (string= rendered
+ (erc-stamp--format-date-stamp aligned)))
+ (erc-add-timestamp))
+ (setq erc-timestamp-last-inserted-left rendered)))))
+
+;; This minor mode is just a placeholder and currently unhelpful for
+;; managing complexity. A useful version would leave a marker during
+;; post-modify hooks and then perform insertions (before markers)
+;; during "done" hooks. This would enable completely decoupling from
+;; and possibly deprecating `erc-insert-timestamp-left-and-right'.
+;; However, doing this would require expanding the internal API to
+;; include insertion and deletion handlers for twiddling and massaging
+;; text properties based on context immediately after modifying text
+;; earlier in a buffer (away from `erc-insert-marker'). Without such
+;; handlers, things like "merged" `fill-wrap' speakers and invisible
+;; messages may be damaged by buffer modifications.
+(define-minor-mode erc-stamp--date-mode
+ "Insert date stamps as standalone messages."
+ :interactive nil
+ (if erc-stamp--date-mode
+ (progn (add-hook 'erc-insert-pre-hook
+ #'erc-stamp--lr-date-on-pre-modify 10 t)
+ (add-hook 'erc-pre-send-functions
+ #'erc-stamp--lr-date-on-pre-modify 10 t))
+ (kill-local-variable 'erc-timestamp-last-inserted-left)
+ (remove-hook 'erc-insert-pre-hook
+ #'erc-stamp--lr-date-on-pre-modify t)
+ (remove-hook 'erc-pre-send-functions
+ #'erc-stamp--lr-date-on-pre-modify t)))
+
+(defvar erc-stamp-prepend-date-stamps-p nil
+ "When non-nil, date stamps are not independent messages.
+This flag restores pre-5.6 behavior in which date stamps formed
+the leading portion of affected messages. Beware that enabling
+this degrades the user experience by causing 5.6+ features, like
+`fill-wrap', dynamic invisibility, etc., to malfunction. When
+non-nil, none of the newline twiddling mentioned in the doc
+string for `erc-timestamp-format-left' occurs. That is, ERC does
+not append or remove trailing newlines.")
+(make-obsolete-variable 'erc-stamp-prepend-date-stamps-p
+ "unsupported legacy behavior" "30.1")
(defun erc-insert-timestamp-left-and-right (string)
"Insert a stamp on either side when it changes.
When the deprecated option `erc-timestamp-format-right' is nil,
use STRING, which originates from `erc-timestamp-format', for the
-right-hand stamp. Use `erc-timestamp-format-left' for the
-left-hand stamp and expect it to change less frequently."
- (let* ((ct (or erc-stamp--current-time (erc-stamp--current-time)))
- (ts-left (erc-format-timestamp ct erc-timestamp-format-left))
+right-hand stamp. Use `erc-timestamp-format-left' for formatting
+the left-sided \"date stamp,\" and expect it to change less
+frequently. Include all but the final trailing newline present
+in the latter (if any) as part of the `erc-timestamp' field.
+Allow the stamp's `invisible' property to span that same interval
+but also cover the previous newline, in order to satisfy folding
+requirements related to `erc-legacy-invisible-bounds-p'.
+Additionally, ensure every date stamp is identifiable as such so
+that internal modules can easily distinguish between other
+left-sided stamps and date stamps inserted by this function."
+ (unless (or erc-stamp--date-format-end erc-stamp-prepend-date-stamps-p
+ (and (or (null erc-timestamp-format-left)
+ (string-empty-p ; compat
+ (string-trim erc-timestamp-format-left "\n")))
+ (always (erc-stamp--date-mode -1))
+ (setq erc-stamp-prepend-date-stamps-p t)))
+ (erc-stamp--date-mode +1)
+ ;; Hooks used by ^ are the preferred means of inserting date
+ ;; stamps. But they'll never see this inaugural message, so it
+ ;; must be handled specially.
+ (let ((erc--insert-marker (point-min-marker))
+ (end-marker (point-max-marker)))
+ (set-marker-insertion-type erc--insert-marker t)
+ (erc-stamp--lr-date-on-pre-modify nil)
+ (narrow-to-region erc--insert-marker end-marker)
+ (set-marker end-marker nil)
+ (set-marker erc--insert-marker nil)))
+ (let* ((ct (erc-stamp--current-time))
(ts-right (with-suppressed-warnings
((obsolete erc-timestamp-format-right))
(if erc-timestamp-format-right
(erc-format-timestamp ct erc-timestamp-format-right)
string))))
- ;; insert left timestamp
- (unless (string-equal ts-left erc-timestamp-last-inserted-left)
+ ;; We should arguably be ensuring a trailing newline on legacy
+ ;; "prepended" date stamps as well. However, since this is a
+ ;; compatibility oriented code path, and pre-5.6 did no such
+ ;; thing, better to punt.
+ (when-let ((erc-stamp-prepend-date-stamps-p)
+ (ts-left (erc-format-timestamp ct erc-timestamp-format-left))
+ ((not (string= ts-left erc-timestamp-last-inserted-left))))
(goto-char (point-min))
(erc-put-text-property 0 (length ts-left) 'field 'erc-timestamp ts-left)
- (funcall erc-stamp--insert-date-function ts-left)
- (setq erc-timestamp-last-inserted-left ts-left))
+ (insert (setq erc-timestamp-last-inserted-left ts-left)))
;; insert right timestamp
(let ((erc-timestamp-only-if-changed-flag t)
(erc-timestamp-last-inserted erc-timestamp-last-inserted-right))
@@ -617,6 +821,19 @@ left-hand stamp and expect it to change less frequently."
;; for testing: (setq erc-timestamp-only-if-changed-flag nil)
(defvar erc-stamp--tz nil)
+;; Unfortunately, cursory measurements show that this function is 10x
+;; slower than `erc-format-timestamp', which is perhaps
+;; counterintuitive. Thus, we use the latter for our cache, and
+;; perform day alignments via this function only when needed.
+(defun erc-stamp--time-as-day (current-time)
+ "Discard hour, minute, and second info from timestamp CURRENT-TIME."
+ (let* ((current-time-list) ; flag
+ (decoded (decode-time current-time erc-stamp--tz)))
+ (setf (decoded-time-second decoded) 0
+ (decoded-time-minute decoded) 0
+ (decoded-time-hour decoded) 0)
+ (encode-time decoded))) ; may return an integer
+
(defun erc-format-timestamp (time format)
"Return TIME formatted as string according to FORMAT.
Return the empty string if FORMAT is nil."
@@ -624,8 +841,9 @@ Return the empty string if FORMAT is nil."
(let ((ts (format-time-string format time erc-stamp--tz)))
(erc-put-text-property 0 (length ts)
'font-lock-face 'erc-timestamp-face ts)
- (erc-put-text-property 0 (length ts) 'invisible
- erc-stamp--invisible-property ts)
+ (when erc-stamp--invisible-property
+ (erc-put-text-property 0 (length ts) 'invisible
+ erc-stamp--invisible-property ts))
;; N.B. Later use categories instead of this harmless, but
;; inelegant, hack. -- BPT
(and erc-timestamp-intangible
@@ -634,20 +852,66 @@ Return the empty string if FORMAT is nil."
ts)
""))
+(defvar-local erc-stamp--csf-props-updated-p nil)
+
;; This function is used to munge `buffer-invisibility-spec' to an
;; appropriate value. Currently, it only handles timestamps, thus its
;; location. If you add other features which affect invisibility,
;; please modify this function and move it to a more appropriate
;; location.
(defun erc-munge-invisibility-spec ()
- (and erc-timestamp-intangible (not (bound-and-true-p cursor-intangible-mode))
- (cursor-intangible-mode 1))
- (and erc-echo-timestamps (not (bound-and-true-p cursor-sensor-mode))
- (cursor-sensor-mode 1))
+ (if erc-timestamp-intangible
+ (cursor-intangible-mode +1) ; idempotent
+ (when (bound-and-true-p cursor-intangible-mode)
+ (cursor-intangible-mode -1)))
+ (if erc-echo-timestamps
+ (progn
+ (unless erc-stamp--permanent-cursor-sensor-functions
+ (dolist (hook '(erc-insert-post-hook erc-send-post-hook))
+ (add-hook hook #'erc-stamp--add-csf-on-post-modify nil t))
+ (erc--restore-initialize-priors erc-stamp-mode
+ erc-stamp--csf-props-updated-p nil)
+ (unless erc-stamp--csf-props-updated-p
+ (setq erc-stamp--csf-props-updated-p t)
+ (let ((erc--msg-props (map-into '((erc--ts . t)) 'hash-table)))
+ (with-silent-modifications
+ (erc--traverse-inserted
+ (point-min) erc-insert-marker
+ #'erc-stamp--add-csf-on-post-modify)))))
+ (cursor-sensor-mode +1) ; idempotent
+ (when (>= emacs-major-version 29)
+ (add-function :before-until (local 'clear-message-function)
+ #'erc-stamp--on-clear-message)))
+ (dolist (hook '(erc-insert-post-hook erc-send-post-hook))
+ (remove-hook hook #'erc-stamp--add-csf-on-post-modify t))
+ (kill-local-variable 'erc-stamp--csf-props-updated-p)
+ (when (bound-and-true-p cursor-sensor-mode)
+ (cursor-sensor-mode -1))
+ (remove-function (local 'clear-message-function)
+ #'erc-stamp--on-clear-message))
(if erc-hide-timestamps
(add-to-invisibility-spec 'timestamp)
(remove-from-invisibility-spec 'timestamp)))
+(defun erc-stamp--add-csf-on-post-modify ()
+ "Add `cursor-sensor-functions' to narrowed buffer."
+ (when (erc--check-msg-prop 'erc--ts)
+ (put-text-property (point-min) (1- (point-max))
+ 'cursor-sensor-functions '(erc--echo-ts-csf))))
+
+(defun erc-stamp--setup ()
+ "Enable or disable buffer-local `erc-stamp-mode' modifications."
+ (if erc-stamp-mode
+ (erc-munge-invisibility-spec)
+ (let (erc-echo-timestamps erc-hide-timestamps erc-timestamp-intangible)
+ (erc-munge-invisibility-spec))
+ ;; Undo local mods from `erc-insert-timestamp-left-and-right'.
+ (erc-stamp--date-mode -1) ; kills `erc-timestamp-last-inserted-left'
+ (kill-local-variable 'erc-stamp--last-stamp)
+ (kill-local-variable 'erc-timestamp-last-inserted)
+ (kill-local-variable 'erc-timestamp-last-inserted-right)
+ (kill-local-variable 'erc-stamp--date-format-end)))
+
(defun erc-hide-timestamps ()
"Hide timestamp information from display."
(interactive)
@@ -677,28 +941,48 @@ enabled when the message was inserted."
(erc-munge-invisibility-spec)))
(erc-buffer-list)))
-(defun erc-echo-timestamp (dir stamp)
- "Print timestamp text-property of an IRC message."
- ;; Could also pass an &optional `zone' arg to `format-time-string'.
- (interactive (list 'entered (get-text-property (point) 'erc-timestamp)))
- (when (eq 'entered dir)
- (when stamp
- (message "%s" (format-time-string erc-echo-timestamp-format
- stamp)))))
+(defvar-local erc-stamp--last-stamp nil)
+
+(defun erc-stamp--on-clear-message (&rest _)
+ "Return `dont-clear-message' when operating inside the same stamp."
+ (and erc-stamp--last-stamp erc-echo-timestamps
+ (eq (erc--get-inserted-msg-prop 'erc--ts) erc-stamp--last-stamp)
+ 'dont-clear-message))
+
+(defun erc-echo-timestamp (dir stamp &optional zone)
+ "Display timestamp of message at point in echo area.
+Interactively, interpret a numeric prefix as a ZONE offset in
+hours (or seconds, if its abs value is larger than 14), and
+interpret a \"raw\" prefix as UTC. To specify a zone for use
+with the option `erc-echo-timestamps', see the companion option
+`erc-echo-timestamp-zone'."
+ (interactive (list nil (erc--get-inserted-msg-prop 'erc--ts)
+ (pcase current-prefix-arg
+ ((and (pred numberp) v)
+ (if (<= (abs v) 14) (* v 3600) v))
+ (`(,_) t))))
+ (if (and stamp (or (null dir) (and erc-echo-timestamps (eq 'entered dir))))
+ (progn
+ (setq erc-stamp--last-stamp stamp)
+ (message (format-time-string erc-echo-timestamp-format
+ stamp (or zone erc-echo-timestamp-zone))))
+ (when (and erc-echo-timestamps (eq 'left dir))
+ (setq erc-stamp--last-stamp nil))))
(defun erc--echo-ts-csf (_window _before dir)
- (erc-echo-timestamp dir (get-text-property (point) 'erc-timestamp)))
+ (erc-echo-timestamp dir (erc--get-inserted-msg-prop 'erc--ts)))
(defun erc-stamp--update-saved-position (&rest _)
- (remove-function (local 'erc-stamp--insert-date-function)
- #'erc-stamp--update-saved-position)
- (move-marker erc-last-saved-position (1- (point))))
+ (remove-hook 'erc-stamp--insert-date-hook
+ #'erc-stamp--update-saved-position t)
+ (move-marker erc-last-saved-position (1- (point-max))))
(defun erc-stamp--reset-on-clear (pos)
"Forget last-inserted stamps when POS is at insert marker."
(when (= pos (1- erc-insert-marker))
- (add-function :after (local 'erc-stamp--insert-date-function)
- #'erc-stamp--update-saved-position)
+ (when erc-stamp--date-mode
+ (add-hook 'erc-stamp--insert-date-hook
+ #'erc-stamp--update-saved-position 0 t))
(setq erc-timestamp-last-inserted nil
erc-timestamp-last-inserted-left nil
erc-timestamp-last-inserted-right nil)))
diff --git a/lisp/erc/erc-status-sidebar.el b/lisp/erc/erc-status-sidebar.el
index cf3d20aeffa..b7695651e4c 100644
--- a/lisp/erc/erc-status-sidebar.el
+++ b/lisp/erc/erc-status-sidebar.el
@@ -1,6 +1,6 @@
;;; erc-status-sidebar.el --- HexChat-like activity overview for ERC -*- lexical-binding: t; -*-
-;; Copyright (C) 2017, 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017, 2020-2024 Free Software Foundation, Inc.
;; Author: Andrew Barbarello
;; Maintainer: Amin Bandali <bandali@gnu.org>, F. Jason Park <jp@neverwas.me>
@@ -102,7 +102,7 @@ Only consulted for certain values of `erc-status-sidebar-style'."
"Whether to highlight the selected window's buffer in the sidebar.
ERC uses the same instance across all frames. May not be
compatible with all values of `erc-status-sidebar-style'."
- :package-version '(ERC . "5.6") ; FIXME sync on release
+ :package-version '(ERC . "5.6")
:type 'boolean)
(defcustom erc-status-sidebar-style 'all-queries-first
@@ -130,12 +130,12 @@ buffers, using the functions
`erc-status-sidebar-pad-hierarchy'
for the above-mentioned purposes. ERC also accepts a list of
-functions to preform these roles a la carte. Since the members
+functions to perform these roles a la carte. Since the members
of the above sets aren't really interoperable, we don't offer
them here as customization choices, but you can still specify
them manually. See doc strings for a description of their
expected arguments and return values."
- :package-version '(ERC . "5.6") ; FIXME sync on release
+ :package-version '(ERC . "5.6")
:type '(choice (const channels-only)
(const all-mixed)
(const all-queries-first)
@@ -150,7 +150,7 @@ expected arguments and return values."
"How to display a buffer when clicked.
Values can be anything recognized by `display-buffer' for its
ACTION parameter."
- :package-version '(ERC . "5.6") ; FIXME sync on release
+ :package-version '(ERC . "5.6")
:type '(choice (const :tag "Always use/create other window" t)
(const :tag "Let `display-buffer' decide" nil)
(const :tag "Same window" (display-buffer-same-window
@@ -257,12 +257,13 @@ current frame only."
" Add `track' to `erc-modules' to silence this message."))
(erc-track-mode +1))
(add-hook 'erc--setup-buffer-hook #'erc-status-sidebar--open)
- (unless erc--updating-modules-p
- (if (erc-with-server-buffer erc-server-connected)
- (erc-status-sidebar--open)
- (when (derived-mode-p 'erc-mode)
- (erc-error "Not initializing `erc-bufbar-mode' in %s"
- (current-buffer))))))
+ ;; Preserve side-window dimensions after `custom-buffer-done'.
+ (when-let (((not erc--updating-modules-p))
+ (buf (or (and (derived-mode-p 'erc-mode) (current-buffer))
+ (car (erc-buffer-filter
+ (lambda () erc-server-connected))))))
+ (with-current-buffer buf
+ (erc-status-sidebar--open))))
((remove-hook 'erc--setup-buffer-hook #'erc-status-sidebar--open)
(erc-status-sidebar-close 'all-frames)
(when-let ((arg erc--module-toggle-prefix-arg)
diff --git a/lisp/erc/erc-track.el b/lisp/erc/erc-track.el
index 64e59a90047..7e5ed165fb9 100644
--- a/lisp/erc/erc-track.el
+++ b/lisp/erc/erc-track.el
@@ -1,6 +1,6 @@
;;; erc-track.el --- Track modified channel buffers -*- lexical-binding:t -*-
-;; Copyright (C) 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2024 Free Software Foundation, Inc.
;; Author: Mario Lang <mlang@delysid.org>
;; Maintainer: Amin Bandali <bandali@gnu.org>, F. Jason Park <jp@neverwas.me>
@@ -161,23 +161,39 @@ The faces used are the same as used for text in the buffers.
\(e.g. `erc-pal-face' is used if a pal sent a message to that channel.)"
:type 'boolean)
+(defun erc-track--massage-nick-button-faces (sym val &optional set-fn)
+ "Transform VAL of face-list option SYM to have new defaults.
+Use `set'-compatible SET-FN when given. If an update was
+performed, set the symbol property `erc-track--obsolete-faces' of
+SYM to t."
+ (let* ((changedp nil)
+ (new (mapcar
+ (lambda (f)
+ (if (and (eq (car-safe f) 'erc-nick-default-face)
+ (equal f '(erc-nick-default-face erc-default-face)))
+ (progn
+ (setq changedp t)
+ (put sym 'erc-track--obsolete-faces t)
+ (cons 'erc-button-nick-default-face (cdr f)))
+ f))
+ val)))
+ (if set-fn
+ (funcall set-fn sym (if changedp new val))
+ (set-default sym (if changedp new val)))))
+
(defcustom erc-track-faces-priority-list
'(erc-error-face
- (erc-nick-default-face erc-current-nick-face)
erc-current-nick-face
erc-keyword-face
- (erc-nick-default-face erc-pal-face)
erc-pal-face
erc-nick-msg-face
erc-direct-msg-face
(erc-button erc-default-face)
- (erc-nick-default-face erc-dangerous-host-face)
erc-dangerous-host-face
erc-nick-default-face
- (erc-nick-default-face erc-default-face)
+ (erc-button-nick-default-face erc-default-face)
erc-default-face
erc-action-face
- (erc-nick-default-face erc-fool-face)
erc-fool-face
erc-notice-face
erc-input-face
@@ -188,6 +204,8 @@ be highlighted using that face. The first matching face is used.
Note that ERC prioritizes certain faces reserved for critical
messages regardless of this option's value."
+ :package-version '(ERC . "5.6")
+ :set #'erc-track--massage-nick-button-faces
:type (erc--with-dependent-type-match
(repeat (choice face (repeat :tag "Combination" face)))
erc-button))
@@ -209,10 +227,9 @@ setting this variable might not be very useful."
(defcustom erc-track-faces-normal-list
'((erc-button erc-default-face)
- (erc-nick-default-face erc-dangerous-host-face)
erc-dangerous-host-face
erc-nick-default-face
- (erc-nick-default-face erc-default-face)
+ (erc-button-nick-default-face erc-default-face)
erc-default-face
erc-action-face)
"A list of faces considered to be part of normal conversations.
@@ -224,9 +241,26 @@ the buffer name will be highlighted using the face from the
message. This gives a rough indication that active conversations
are occurring in these channels.
+Note that ERC makes a copy of this option when initializing the
+module. To see your changes reflected mid-session, cycle
+\\[erc-track-mode].
+
The effect may be disabled by setting this variable to nil."
- :type '(repeat (choice face
- (repeat :tag "Combination" face))))
+ :package-version '(ERC . "5.6")
+ :set #'erc-track--massage-nick-button-faces
+ :type (erc--with-dependent-type-match
+ (repeat (choice face (repeat :tag "Combination" face)))
+ erc-button))
+
+(defvar erc-track-ignore-normal-contenders-p nil
+ "Compatibility flag to promote only exclusively new \"normal\" faces.
+When non-nil, revert to pre-5.6 behavior in which only a current
+mode-line face that both outranks and is absent from the current
+message is eligible for replacement by a fellow face from
+`erc-track-faces-normal-list' that does appear in the message.
+By extension, when enabled, never replace the current, reigning
+mode-line face if it's present in the current message. May be
+incompatible with modules introduced after ERC 5.5.")
(defcustom erc-track-position-in-mode-line 'before-modes
"Where to show modified channel information in the mode-line.
@@ -344,6 +378,37 @@ See `erc-track-position-in-mode-line' for possible values."
;;; Shortening of names
+(defvar erc-track--shortened-names nil
+ "A cons of the last novel name-shortening params and the result.
+The CAR is a hash of environmental inputs such as options and
+parameters passed to `erc-track-shorten-function'. Its effect is
+only really noticeable during batch processing.")
+
+(defvar erc-track--shortened-names-current-hash nil)
+
+(defun erc-track--shortened-names-set (_ shortened)
+ "Remember SHORTENED names with hash of contextual params."
+ (cl-assert erc-track--shortened-names-current-hash)
+ (setq erc-track--shortened-names
+ (cons erc-track--shortened-names-current-hash shortened)))
+
+(defun erc-track--shortened-names-get (channel-names)
+ "Cache CHANNEL-NAMES with various contextual parameters.
+For now, omit relevant options like `erc-track-shorten-start' and
+friends, even though they do affect the outcome, because they
+likely change too infrequently to matter over sub-second
+intervals and are unlikely to be let-bound or set locally."
+ (when-let ((hash (setq erc-track--shortened-names-current-hash
+ (sxhash-equal (list channel-names
+ (buffer-list)
+ erc-track-shorten-function))))
+ (erc-track--shortened-names)
+ ((= hash (car erc-track--shortened-names))))
+ (cdr erc-track--shortened-names)))
+
+(gv-define-simple-setter erc-track--shortened-names-get
+ erc-track--shortened-names-set)
+
(defun erc-track-shorten-names (channel-names)
"Call `erc-unique-channel-names' with the correct parameters.
This function is a good value for `erc-track-shorten-function'.
@@ -518,6 +583,9 @@ keybindings will not do anything useful."
(progn
(add-hook 'window-configuration-change-hook #'erc-user-is-active)
(add-hook 'erc-send-completed-hook #'erc-user-is-active)
+ ;; FIXME find out why this uses `erc-server-001-functions'.
+ ;; `erc-user-is-active' runs when `erc-server-connected' is
+ ;; non-nil. But this hook usually only runs when it's nil.
(add-hook 'erc-server-001-functions #'erc-user-is-active))
(erc-track-add-to-mode-line erc-track-position-in-mode-line)
(erc-update-mode-line)
@@ -528,6 +596,8 @@ keybindings will not do anything useful."
;; enable the tracking keybindings
(add-hook 'erc-connect-pre-hook #'erc-track-minor-mode-maybe)
(erc-track-minor-mode-maybe))
+ (add-hook 'erc-mode-hook #'erc-track--setup)
+ (unless erc--updating-modules-p (erc-buffer-do #'erc-track--setup))
(add-hook 'erc-networks--copy-server-buffer-functions
#'erc-track--replace-killed-buffer))
;; Disable:
@@ -539,6 +609,7 @@ keybindings will not do anything useful."
#'erc-user-is-active)
(remove-hook 'erc-send-completed-hook #'erc-user-is-active)
(remove-hook 'erc-server-001-functions #'erc-user-is-active)
+ ;; FIXME remove this if unused.
(remove-hook 'erc-timer-hook #'erc-user-is-active))
(remove-hook 'window-configuration-change-hook
#'erc-window-configuration-change)
@@ -548,9 +619,12 @@ keybindings will not do anything useful."
(remove-hook 'erc-connect-pre-hook #'erc-track-minor-mode-maybe)
(when erc-track-minor-mode
(erc-track-minor-mode -1)))
+ (remove-hook 'erc-mode-hook #'erc-track--setup)
+ (erc-buffer-do #'erc-track--setup)
(remove-hook 'erc-networks--copy-server-buffer-functions
#'erc-track--replace-killed-buffer)))
+;; FIXME move this above the module definition.
(defcustom erc-track-when-inactive nil
"Enable channel tracking even for visible buffers, if you are inactive."
:type 'boolean
@@ -562,6 +636,51 @@ keybindings will not do anything useful."
(erc-track-enable))
(set sym val))))
+(defvar-local erc-track--normal-faces nil
+ "Local copy of `erc-track-faces-normal-list' as a hash table.")
+
+(defun erc-track--setup ()
+ "Initialize a buffer for use with the `track' module.
+If this is a server buffer or `erc-track-faces-normal-list' is
+locally bound, create a new `erc-track--normal-faces' for the
+current buffer. Otherwise, set the local value to the server
+buffer's."
+ (if erc-track-mode
+ (let ((existing (erc-with-server-buffer erc-track--normal-faces))
+ (localp (and erc--target
+ (local-variable-p 'erc-track-faces-normal-list)))
+ (opts '(erc-track-faces-normal-list erc-track-faces-priority-list))
+ warnp table)
+ ;; Don't bother warning users who've disabled `button'.
+ (unless (or erc--target (not (or (bound-and-true-p erc-button-mode)
+ (memq 'button erc-modules))))
+ (when (or localp (local-variable-p 'erc-track-faces-priority-list))
+ (dolist (opt opts)
+ (erc-track--massage-nick-button-faces opt (symbol-value opt)
+ #'set)))
+ (dolist (opt opts)
+ (when (get opt 'erc-track--obsolete-faces)
+ (push opt warnp)
+ (put opt 'erc-track--obsolete-faces nil)))
+ (when warnp
+ (erc--warn-once-before-connect 'erc-track-mode
+ (if (cdr warnp) "Options " "Option ")
+ (mapconcat (lambda (o) (format "`%S'" o)) warnp " and ")
+ (if (cdr warnp) " contain" " contains")
+ " an obsolete item, %S, intended to match buttonized nicknames."
+ " ERC has changed it to %S for the current session."
+ " Please save the current value to silence this message."
+ '(erc-nick-default-face erc-default-face)
+ '(erc-button-nick-default-face erc-default-face))))
+ (when (or (null existing) localp)
+ (setq table (map-into (mapcar (lambda (f) (cons f f))
+ erc-track-faces-normal-list)
+ '(hash-table :test equal :weakness value))))
+ (setq erc-track--normal-faces (or table existing))
+ (unless (or localp existing)
+ (erc-with-server-buffer (setq erc-track--normal-faces table))))
+ (kill-local-variable 'erc-track--normal-faces)))
+
;;; Visibility
(defvar erc-buffer-activity nil
@@ -705,10 +824,13 @@ Use `erc-make-mode-line-buffer-name' to create buttons."
(or (buffer-name buf)
""))
buffers))
- (short-names (if (functionp erc-track-shorten-function)
- (funcall erc-track-shorten-function
- long-names)
- long-names))
+ (erc-track--shortened-names-current-hash nil)
+ (short-names
+ (if (functionp erc-track-shorten-function)
+ (with-memoization
+ (erc-track--shortened-names-get long-names)
+ (funcall erc-track-shorten-function long-names))
+ long-names))
strings)
(while buffers
(when (car short-names)
@@ -766,7 +888,12 @@ instead. This has the effect of allowing the current mode line
face, if a member of `erc-track-faces-normal-list', to be
replaced with another with lower priority face from NEW-FACES, if
that face with highest priority in NEW-FACES is also a member of
-`erc-track-faces-normal-list'."
+`erc-track-faces-normal-list'.
+
+To put it another way, when CUR-FACE outranks all NEW-FACES and
+doesn't appear among them, it's eligible to be replaced with a
+fellow \"normal\" from NEW-FACES. But if it does appear among
+them, it can't be replaced."
(let ((choice (catch 'face
(dolist (candidate erc-track-faces-priority-list)
(when (or (equal candidate cur-face)
@@ -785,6 +912,56 @@ that face with highest priority in NEW-FACES is also a member of
choice))
choice))))
+(defvar erc-track--alt-normals-function nil
+ "A function to possibly elect a \"normal\" face.
+Called with the current incumbent and the worthiest new contender
+followed by all new contending faces and so-called \"normal\"
+faces. See `erc-track--select-mode-line-face' for their meanings
+and expected types. This function should return a face or nil.")
+
+(defun erc-track--select-mode-line-face (cur-face new-faces ranks normals)
+ "Return CUR-FACE or a replacement for displaying in the mode-line, or nil.
+Expect RANKS to be a list of faces and both NORMALS and the car
+of NEW-FACES to be hash tables mapping faces to non-nil values.
+Assume the latter's makeup and that of RANKS to resemble
+`erc-track-face-normal-list' and `erc-track-faces-priority-list'.
+If NEW-FACES has a cdr, expect it to be its car's contents
+ordered from most recently seen (later in the buffer) to
+earliest. In general, act like `erc-track-select-mode-line-face'
+except appeal to `erc-track--alt-normals-function' if it's
+non-nil, falling back on reconsidering NEW-FACES when CUR-FACE
+outranks all its members. That is, choose the first among RANKS
+in NEW-FACES not equal to CUR-FACE. Failing that, choose the
+first face in NEW-FACES that's also in NORMALS, assuming
+NEW-FACES has a cdr."
+ (cl-check-type erc-track-ignore-normal-contenders-p null)
+ (cl-check-type new-faces cons)
+ (when-let ((choice (catch 'face
+ (dolist (candidate ranks)
+ (when (or (equal candidate cur-face)
+ (gethash candidate (car new-faces)))
+ (throw 'face candidate))))))
+ (or (and erc-track--alt-normals-function
+ (funcall erc-track--alt-normals-function
+ cur-face choice new-faces normals))
+ (and (equal choice cur-face)
+ (gethash choice normals)
+ (catch 'face
+ (progn
+ (dolist (candidate ranks)
+ (when (and (not (equal candidate choice))
+ (gethash candidate (car new-faces))
+ (gethash choice normals))
+ (throw 'face candidate)))
+ (dolist (candidate (cdr new-faces))
+ (when (and (not (equal candidate choice))
+ (gethash candidate normals))
+ (throw 'face candidate))))))
+ choice)))
+
+(defvar erc-track--skipped-msgs '(datestamp)
+ "Values of `erc--msg' text prop to ignore.")
+
(defun erc-track-modified-channels ()
"Hook function for `erc-insert-post-hook'.
Check if the current buffer should be added to the mode line as a
@@ -795,11 +972,16 @@ the current buffer is in `erc-mode'."
(if (and (not (erc-buffer-visible (current-buffer)))
(not (member this-channel erc-track-exclude))
(not (and erc-track-exclude-server-buffer
- (erc-server-buffer-p)))
- (not (erc-message-type-member
- (or (erc-find-parsed-property)
- (point-min))
- erc-track-exclude-types)))
+ ;; FIXME either use `erc--server-buffer-p' or
+ ;; explain why that's unwise.
+ (erc-server-or-unjoined-channel-buffer-p)))
+ (not (let ((parsed (erc-find-parsed-property)))
+ (or (erc-message-type-member (or parsed (point-min))
+ erc-track-exclude-types)
+ ;; Skip certain non-server-sent messages.
+ (and (not parsed)
+ (erc--check-msg-prop 'erc--msg
+ erc-track--skipped-msgs))))))
;; If the active buffer is not visible (not shown in a
;; window), and not to be excluded, determine the kinds of
;; faces used in the current message, and unless the user
@@ -811,31 +993,43 @@ the current buffer is in `erc-mode'."
;; (in the car), change its face attribute (in the cddr) if
;; necessary. See `erc-modified-channels-alist' for the
;; exact data structure used.
- (let ((faces (erc-faces-in (buffer-string)))
- (erc-track-faces-priority-list
- `(,@erc-track--attn-faces ,@erc-track-faces-priority-list)))
- (unless (and
- (or (eq erc-track-priority-faces-only 'all)
- (member this-channel erc-track-priority-faces-only))
- (not (catch 'found
- (dolist (f faces)
- (when (member f erc-track-faces-priority-list)
- (throw 'found t))))))
+ (when-let
+ ((faces (if erc-track-ignore-normal-contenders-p
+ (erc-faces-in (buffer-string))
+ (erc-track--get-faces-in-current-message)))
+ (normals erc-track--normal-faces)
+ (erc-track-faces-priority-list
+ `(,@erc-track--attn-faces ,@erc-track-faces-priority-list))
+ (ranks erc-track-faces-priority-list)
+ ((not (and
+ (or (eq erc-track-priority-faces-only 'all)
+ (member this-channel erc-track-priority-faces-only))
+ (not (catch 'found
+ (dolist (f ranks)
+ (when (gethash f (or (car-safe faces) faces))
+ (throw 'found t)))))))))
+ (progn ; FIXME remove `progn' on next major edit
(if (not (assq (current-buffer) erc-modified-channels-alist))
;; Add buffer, faces and counts
(setq erc-modified-channels-alist
(cons (cons (current-buffer)
(cons
- 1 (erc-track-select-mode-line-face
- nil faces)))
+ 1 (if erc-track-ignore-normal-contenders-p
+ (erc-track-select-mode-line-face
+ nil faces)
+ (erc-track--select-mode-line-face
+ nil faces ranks normals))))
erc-modified-channels-alist))
;; Else modify the face for the buffer, if necessary.
(when faces
(let* ((cell (assq (current-buffer)
erc-modified-channels-alist))
(old-face (cddr cell))
- (new-face (erc-track-select-mode-line-face
- old-face faces)))
+ (new-face (if erc-track-ignore-normal-contenders-p
+ (erc-track-select-mode-line-face
+ old-face faces)
+ (erc-track--select-mode-line-face
+ old-face faces ranks normals))))
(setcdr cell (cons (1+ (cadr cell)) new-face)))))
;; And display it
(erc-modified-channels-display)))
@@ -864,6 +1058,30 @@ the current buffer is in `erc-mode'."
(push cur faces)))
faces))
+(defvar erc-track--face-reject-function nil
+ "Function called with face in current buffer to massage or reject.")
+
+(defun erc-track--get-faces-in-current-message ()
+ "Collect all faces in the narrowed buffer.
+Return a cons of a hash table and a list ordered from most
+recently seen to earliest seen."
+ (let ((i (text-property-not-all (point-min) (point-max) 'font-lock-face nil))
+ (seen (make-hash-table :test #'equal))
+ ;;
+ (rfaces ())
+ (faces (make-hash-table :test #'equal)))
+ (while-let ((i)
+ (cur (get-text-property i 'face)))
+ (unless (gethash cur seen)
+ (puthash cur t seen)
+ (when erc-track--face-reject-function
+ (setq cur (funcall erc-track--face-reject-function cur)))
+ (when cur
+ (push cur rfaces)
+ (puthash cur t faces)))
+ (setq i (next-single-property-change i 'font-lock-face)))
+ (cons faces rfaces)))
+
;;; Buffer switching
(defvar erc-track-last-non-erc-buffer nil
diff --git a/lisp/erc/erc-truncate.el b/lisp/erc/erc-truncate.el
index 8430a68d92b..4b602074ebb 100644
--- a/lisp/erc/erc-truncate.el
+++ b/lisp/erc/erc-truncate.el
@@ -1,6 +1,6 @@
;;; erc-truncate.el --- Functions for truncating ERC buffers -*- lexical-binding: t; -*-
-;; Copyright (C) 2003-2004, 2006-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003-2004, 2006-2024 Free Software Foundation, Inc.
;; Author: Andreas Fuchs <asf@void.at>
;; Maintainer: Amin Bandali <bandali@gnu.org>, F. Jason Park <jp@neverwas.me>
@@ -24,10 +24,8 @@
;;; Commentary:
-;; This implements buffer truncation (and optional log file writing
-;; support for the Emacs IRC client. Use `erc-truncate-mode' to switch
-;; on. Use `erc-enable-logging' to enable logging of the stuff which
-;; is getting truncated.
+;; This file implements buffer truncation through the `truncate'
+;; module, with optional `log' module integration.
;;; Code:
@@ -50,15 +48,41 @@ This prevents the query buffer from getting too large, which can
bring any grown Emacs to its knees after a few days worth of
tracking heavy-traffic channels."
;;enable
- ((add-hook 'erc-insert-done-hook #'erc-truncate-buffer))
+ ((add-hook 'erc-insert-done-hook #'erc-truncate-buffer)
+ (add-hook 'erc-connect-pre-hook #'erc-truncate--warn-about-logging))
;; disable
- ((remove-hook 'erc-insert-done-hook #'erc-truncate-buffer)))
+ ((remove-hook 'erc-insert-done-hook #'erc-truncate-buffer)
+ (remove-hook 'erc-connect-pre-hook #'erc-truncate--warn-about-logging)))
+
+(defun erc-truncate--warn-about-logging (&rest _)
+ (when (and (not erc--target)
+ (fboundp 'erc-log--call-when-logging-enabled-sans-module))
+ ;; We could also enable `erc-log-mode' here, but the risk of
+ ;; lasting damage is nonzero.
+ (erc-log--call-when-logging-enabled-sans-module
+ (lambda (dirfile)
+ ;; Emit a real Emacs warning because the message may be
+ ;; truncated away before it can be read if merely inserted.
+ (erc-button--display-error-notice-with-keys-and-warn
+ "The `truncate' module no longer enables logging implicitly."
+ " If you want ERC to write logs before truncating, add `log' to"
+ " `erc-modules' using something like \\[customize-option]."
+ " To silence this message, don't `require' `erc-log'."
+ (and dirfile " Alternatively, change the value of")
+ (and dirfile " `erc-log-channels-directory', or move ")
+ dirfile (and dirfile " elsewhere."))))))
;;;###autoload
(defun erc-truncate-buffer-to-size (size &optional buffer)
- "Truncates the buffer to the size SIZE.
-If BUFFER is not provided, the current buffer is assumed. The deleted
-region is logged if `erc-logging-enabled' returns non-nil."
+ "Truncate BUFFER or the current buffer to SIZE.
+Log the deleted region when the `log' module is active and
+`erc-logging-enabled' returns non-nil.
+
+Note that prior to ERC 5.6, whenever erc-log.el happened to be
+loaded and the option `erc-enable-logging' was left at its
+default value, this function would cause logging to commence
+regardless of whether `erc-log-mode' was enabled or `log' was
+present in `erc-modules'."
;; If buffer is non-nil, but get-buffer does not return anything,
;; then this is a bug. If buffer is a buffer name, get the buffer
;; object. If buffer is nil, use the current buffer.
@@ -78,7 +102,7 @@ region is logged if `erc-logging-enabled' returns non-nil."
;; Truncate at message boundary (formerly line boundary
;; before 5.6).
(goto-char end)
- (goto-char (or (previous-single-property-change (point) 'erc-command)
+ (goto-char (or (erc--get-inserted-msg-beg end)
(pos-bol)))
(setq end (point))
;; try to save the current buffer using
@@ -93,6 +117,9 @@ region is logged if `erc-logging-enabled' returns non-nil."
;; (not (memq 'erc-save-buffer-in-logs
;; erc-insert-post-hook))
;; Comments?
+ ;; The comments above concern pre-5.6 behavior and reflect
+ ;; an obsolete understanding of how `erc-logging-enabled'
+ ;; behaves in practice.
(run-hook-with-args 'erc--pre-clear-functions end)
;; disable undoing for the truncating
(buffer-disable-undo)
diff --git a/lisp/erc/erc-xdcc.el b/lisp/erc/erc-xdcc.el
index 3dc08de4d10..b592c84e346 100644
--- a/lisp/erc/erc-xdcc.el
+++ b/lisp/erc/erc-xdcc.el
@@ -1,6 +1,6 @@
;;; erc-xdcc.el --- XDCC file-server support for ERC -*- lexical-binding: t; -*-
-;; Copyright (C) 2003-2004, 2006-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003-2004, 2006-2024 Free Software Foundation, Inc.
;; Author: Mario Lang <mlang@delysid.org>
;; Maintainer: Amin Bandali <bandali@gnu.org>, F. Jason Park <jp@neverwas.me>
diff --git a/lisp/erc/erc.el b/lisp/erc/erc.el
index 7375b5308ea..0565440f357 100644
--- a/lisp/erc/erc.el
+++ b/lisp/erc/erc.el
@@ -1,6 +1,6 @@
;;; erc.el --- An Emacs Internet Relay Chat client -*- lexical-binding:t -*-
-;; Copyright (C) 1997-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997-2024 Free Software Foundation, Inc.
;; Author: Alexander L. Belikoff <alexander@belikoff.net>
;; Maintainer: Amin Bandali <bandali@gnu.org>, F. Jason Park <jp@neverwas.me>
@@ -13,10 +13,13 @@
;; Michael Olson (mwolson@gnu.org)
;; Kelvin White (kwhite@gnu.org)
;; Version: 5.6-git
-;; Package-Requires: ((emacs "27.1") (compat "29.1.4.1"))
+;; Package-Requires: ((emacs "27.1") (compat "29.1.4.3"))
;; Keywords: IRC, chat, client, Internet
;; URL: https://www.gnu.org/software/emacs/erc.html
+;; This is a GNU ELPA :core package. Avoid functionality that is not
+;; compatible with the version of Emacs recorded above.
+
;; This file is part of GNU Emacs.
;; GNU Emacs is free software: you can redistribute it and/or modify
@@ -132,13 +135,63 @@ concerning buffers."
"Running scripts at startup and with /LOAD."
:group 'erc)
-;; Forward declarations
-(defvar erc-message-parsed)
-
-(defvar tabbar--local-hlf)
-(defvar motif-version-string)
-(defvar gtk-version-string)
+(defvar erc-message-parsed) ; only known to this file
+
+(defvar erc--msg-props nil
+ "Hash table containing metadata properties for current message.
+Provided by the insertion functions `erc-display-message' and
+`erc-display-msg' while running their modification hooks.
+Initialized when null for each visitation round from function
+parameters and environmental factors, as well as the alist
+`erc--msg-prop-overrides'. Keys are symbols. Values are opaque
+objects, unless otherwise specified. Items present after running
+`erc-insert-post-hook' or `erc-send-post-hook' become text
+properties added to the first character of an inserted message.
+A given message therefore spans the interval extending from one
+set of such properties to the newline before the next (or
+`erc-insert-marker'). As of ERC 5.6, this forms the basis for
+visiting and editing inserted messages. Modules should align
+their markers accordingly. The following properties have meaning
+as of ERC 5.6:
+
+ - `erc--msg': a symbol, guaranteed present; possible values
+ include `unknown', a fallback used by `erc-display-message'; a
+ catalog key, such as `s401' or `finished'; an
+ `erc-display-message' TYPE parameter, like `notice'
+
+ - `erc--cmd': a message's associated IRC command, as read by
+ `erc--get-eq-comparable-cmd'; currently either a symbol, like
+ `PRIVMSG', or a number, like 5, which represents the numeric
+ \"005\"; absent on \"local\" messages, such as simple warnings
+ and help text, and on outgoing messages unless echoed back by
+ the server (assuming future support)
+
+ - `erc--spkr': a string, the nick of the person speaking
+
+ - `erc--ctcp': a CTCP command, like `ACTION'
+
+ - `erc--ts': a timestamp, possibly provided by the server; as of
+ 5.6, a ticks/hertz pair on Emacs 29 and above, and a \"list\"
+ type otherwise; managed by the `stamp' module
+
+ - `erc--ephemeral': a symbol prefixed by or matching a module
+ name; indicates to other modules and members of modification
+ hooks that the current message should not affect stateful
+ operations, such as recording a channel's most recent speaker
+
+This is an internal API, and the selection of related helper
+utilities is fluid and provisional. As of ERC 5.6, see the
+functions `erc--check-msg-prop' and `erc--get-inserted-msg-prop'.")
+
+(defvar erc--msg-prop-overrides nil
+ "Alist of \"message properties\" for populating `erc--msg-props'.
+These override any defaults normally shown to modification hooks
+by `erc-display-msg' and `erc-display-message'. Modules should
+accommodate existing overrides when applicable. Items toward the
+front shadow any that follow. Ignored when `erc--msg-props' is
+already non-nil.")
+;; Forward declarations
(declare-function decoded-time-period "time-date" (time))
(declare-function iso8601-parse-duration "iso8601" (string))
(declare-function word-at-point "thingatpt" (&optional no-properties))
@@ -249,7 +302,14 @@ node `(auth) Top' and Info node `(erc) auth-source'.")
:type 'boolean)
(defcustom erc-warn-about-blank-lines t
- "Warn the user if they attempt to send a blank line."
+ "Warn the user if they attempt to send a blank line.
+When non-nil, ERC signals a `user-error' upon encountering prompt
+input containing empty or whitespace-only lines. When nil, ERC
+still inhibits sending but does so silently. With the companion
+option `erc-send-whitespace-lines' enabled, ERC sends pending
+input and prints a message in the echo area indicating the amount
+of padding and/or stripping applied, if any. Setting this option
+to nil suppresses such reporting."
:group 'erc
:type 'boolean)
@@ -261,8 +321,8 @@ node `(auth) Top' and Info node `(erc) auth-source'.")
(defcustom erc-inhibit-multiline-input nil
"When non-nil, conditionally disallow input consisting of multiple lines.
Issue an error when the number of input lines submitted for
-sending exceeds this value. The value t means disallow more
-than 1 line of input."
+sending meets or exceeds this value. The value t is synonymous
+with a value of 2 and means disallow more than 1 line of input."
:package-version '(ERC . "5.5")
:group 'erc
:type '(choice integer boolean))
@@ -283,8 +343,13 @@ than 1 line of input."
"If non-nil, hide input prompt upon disconnecting.
To unhide, type something in the input area. Once revealed, a
prompt remains unhidden until the next disconnection. Channel
-prompts are unhidden upon rejoining. See
-`erc-unhide-query-prompt' for behavior concerning query prompts."
+prompts are unhidden upon rejoining. For behavior concerning
+query prompts, see `erc-unhide-query-prompt'. Longtime ERC users
+should note that this option was repurposed in ERC 5.5 because it
+had lain dormant for years after being sidelined in 5.3 when its
+only use in the interactive client was removed. Before then, its
+role was controlling whether `erc-command-indicator' would appear
+alongside echoed slash-command lines."
:package-version '(ERC . "5.5")
:group 'erc-display
:type '(choice (const :tag "Always hide prompt" t)
@@ -409,13 +474,14 @@ Functions are passed a buffer as the first argument."
:group 'erc-hooks
:type 'hook)
-
-(defvar-local erc-channel-users nil
+(defvaralias 'erc-channel-users 'erc-channel-members)
+(defvar-local erc-channel-members nil
"Hash table of members in the current channel.
-It associates nicknames with cons cells of the form:
-\(USER . MEMBER-DATA) where USER is a pointer to an
-erc-server-user struct, and MEMBER-DATA is a pointer to an
-erc-channel-user struct.")
+It associates nicknames with cons cells of the form
+\(SERVER-USER . MEMBER-DATA), where SERVER-USER is a
+`erc-server-user' object and MEMBER-DATA is a `erc-channel-user'
+object. Convenient abbreviations for these two components are
+`susr' and `cusr', along with `cmem' for the pair.")
(defvar-local erc-server-users nil
"Hash table of users on the current server.
@@ -522,6 +588,8 @@ See also: `erc-remove-server-user' and
Removes all users in the current channel. This is called by
`erc-server-PART' and `erc-server-QUIT'."
+ (when (erc--target-channel-p erc--target)
+ (setf (erc--target-channel-joined-p erc--target) nil))
(when (and erc-server-connected
(erc-server-process-alive)
(hash-table-p erc-channel-users))
@@ -530,6 +598,29 @@ Removes all users in the current channel. This is called by
erc-channel-users)
(clrhash erc-channel-users)))
+(defmacro erc--define-channel-user-status-compat-getter (name n)
+ "Define a gv getter for historical `erc-channel-user' status slot NAME.
+Expect NAME to be a string and N to be its associated power-of-2
+\"enumerated flag\" integer."
+ `(defun ,(intern (concat "erc-channel-user-" name)) (u)
+ ,(format "Get equivalent of pre-5.6 `%s' slot for `erc-channel-user'."
+ name)
+ (declare (gv-setter (lambda (v)
+ (macroexp-let2 nil v v
+ (,'\`(let ((val (erc-channel-user-status ,',u)))
+ (setf (erc-channel-user-status ,',u)
+ (if ,',v
+ (logior val ,n)
+ (logand val ,(lognot n))))
+ ,',v))))))
+ (= ,n (logand ,n (erc-channel-user-status u)))))
+
+(erc--define-channel-user-status-compat-getter "voice" 1)
+(erc--define-channel-user-status-compat-getter "halfop" 2)
+(erc--define-channel-user-status-compat-getter "op" 4)
+(erc--define-channel-user-status-compat-getter "admin" 8)
+(erc--define-channel-user-status-compat-getter "owner" 16)
+
(defun erc-channel-user-owner-p (nick)
"Return non-nil if NICK is an owner of the current channel."
(and nick
@@ -662,9 +753,9 @@ See also: `erc-get-channel-user-list'."
"A topic string for the channel. Should only be used in channel-buffers.")
(defvar-local erc-channel-modes nil
- "List of strings representing channel modes.
-E.g. (\"i\" \"m\" \"s\" \"b Quake!*@*\")
-\(not sure the ban list will be here, but why not)")
+ "List of letters, as strings, representing channel modes.
+For example, (\"i\" \"m\" \"s\"). Modes that take accompanying
+parameters are not included.")
(defvar-local erc-insert-marker nil
"The place where insertion of new text in erc buffers should happen.")
@@ -681,7 +772,74 @@ E.g. (\"i\" \"m\" \"s\" \"b Quake!*@*\")
(defcustom erc-prompt "ERC>"
"Prompt used by ERC. Trailing whitespace is not required."
:group 'erc-display
- :type '(choice string function))
+ :type '(choice string
+ (function-item :tag "Interpret format specifiers"
+ erc-prompt-format)
+ function))
+
+(defvar erc--prompt-format-face-example
+ #("%p%m%a\u00b7%b>"
+ 0 2 (font-lock-face erc-my-nick-prefix-face)
+ 2 4 (font-lock-face font-lock-keyword-face)
+ 4 6 (font-lock-face erc-error-face)
+ 6 7 (font-lock-face shadow)
+ 7 9 (font-lock-face font-lock-constant-face)
+ 9 10 (font-lock-face shadow))
+ "An example value for option `erc-prompt-format' with faces.")
+
+(defcustom erc-prompt-format erc--prompt-format-face-example
+ "Format string when `erc-prompt' is `erc-prompt-format'.
+ERC recognizes these substitution specifiers:
+
+ %a - away indicator
+ %b - buffer name
+ %t - channel or query target, server domain, or dialed address
+ %S - target@network or buffer name
+ %s - target@server or server
+ %N - current network, like Libera.Chat
+ %p - channel membership prefix, like @ or +
+ %n - current nickname
+ %c - channel modes with args for select modes
+ %C - channel modes with all args
+ %u - user modes
+ %m - channel modes sans args in channels, user modes elsewhere
+ %M - like %m but show nothing in query buffers
+
+To pick your own colors, do something like:
+
+ (setopt erc-prompt-format
+ (concat
+ (propertize \"%b\" \\='font-lock-face \\='erc-input-face)
+ (propertize \"%a\" \\='font-lock-face \\='erc-error-face)))
+
+Please remember that ERC ignores this option completely unless
+the \"parent\" option `erc-prompt' is set to `erc-prompt-format'."
+ :package-version '(ERC . "5.6")
+ :group 'erc-display
+ :type `(choice (const :tag "{Prefix}{Mode}{Away}{MIDDLE DOT}{Buffer}>"
+ ,erc--prompt-format-face-example)
+ string))
+
+(defun erc-prompt-format ()
+ "Make predefined `format-spec' substitutions.
+
+See option `erc-prompt-format' and option `erc-prompt'."
+ (format-spec erc-prompt-format
+ (erc-compat--defer-format-spec-in-buffer
+ (?C erc--channel-modes 3 ",")
+ (?M erc--format-modes 'no-query-p)
+ (?N erc-format-network)
+ (?S erc-format-target-and/or-network)
+ (?a erc--format-away-indicator)
+ (?b buffer-name)
+ (?c erc-format-channel-modes)
+ (?m erc--format-modes)
+ (?n erc-current-nick)
+ (?p erc--format-channel-status-prefix)
+ (?s erc-format-target-and/or-server)
+ (?t erc-format-target)
+ (?u erc--format-user-modes))
+ 'ignore-missing)) ; formerly `only-present'
(defun erc-prompt ()
"Return the input prompt as a string.
@@ -694,28 +852,6 @@ See also the variable `erc-prompt'."
(concat prompt " ")
prompt)))
-(defcustom erc-command-indicator nil
- "Indicator used by ERC for showing commands.
-
-If non-nil, this will be used in the ERC buffer to indicate
-commands (i.e., input starting with a `/').
-
-If nil, the prompt will be constructed from the variable `erc-prompt'."
- :group 'erc-display
- :type '(choice (const nil) string function))
-
-(defun erc-command-indicator ()
- "Return the command indicator prompt as a string.
-
-This only has any meaning if the variable `erc-command-indicator' is non-nil."
- (and erc-command-indicator
- (let ((prompt (if (functionp erc-command-indicator)
- (funcall erc-command-indicator)
- erc-command-indicator)))
- (if (> (length prompt) 0)
- (concat prompt " ")
- prompt))))
-
(defcustom erc-notice-prefix "*** "
"Prefix for all notices."
:group 'erc-display
@@ -1023,7 +1159,13 @@ user after \"/PART\"."
;; Hooks
(defgroup erc-hooks nil
- "Hook variables for fancy customizations of ERC."
+ "Hooks for ERC.
+Users of the interactive client should be aware that many of
+these hooks have names predating the modern convention of
+conveying abnormality via the \"-function\" suffix. Users should
+likewise be aware that built-in and third-party modules use these
+hooks as well, and some of their variables may be buffer-local in
+particular sessions and/or `let'-bound for spells."
:group 'erc)
(defcustom erc-mode-hook nil
@@ -1033,9 +1175,8 @@ user after \"/PART\"."
:options '(erc-add-scroll-to-bottom))
(defcustom erc-timer-hook nil
- "Put functions which should get called more or less periodically here.
-The idea is that servers always play ping pong with the client, and so there
-is no need for any idle-timer games with Emacs."
+ "Abnormal hook run after each response handler.
+Called with a float returned from `erc-current-time'."
:group 'erc-hooks
:type 'hook)
@@ -1079,22 +1220,28 @@ The struct has three slots:
`string': The current input string.
`insertp': Whether the string should be inserted into the erc buffer.
`sendp': Whether the string should be sent to the irc server.
+
+And one \"phony\" slot only accessible by hook members at runtime:
+
`refoldp': Whether the string should be re-split per protocol limits.
This hook runs after protocol line splitting has taken place, so
the value of `string' is originally \"pre-filled\". If you need
-ERC to refill the entire payload before sending it, set the
-`refoldp' slot to a non-nil value. Preformatted text and encoded
-subprotocols should probably be handled manually."
+ERC to refill the entire payload before sending it, set the phony
+`refoldp' slot to a non-nil value. Note that this refilling is
+only a convenience, and modules with special needs, such as
+preserving \"preformatted\" text or encoding for subprotocol
+\"tunneling\", should handle splitting manually."
:group 'erc
:type 'hook
:version "27.1")
(define-obsolete-variable-alias 'erc--pre-send-split-functions
'erc--input-review-functions "30.1")
-(defvar erc--input-review-functions '(erc--discard-trailing-multiline-nulls
- erc--split-lines
- erc--run-input-validation-checks)
+(defvar erc--input-review-functions '(erc--split-lines
+ erc--run-input-validation-checks
+ erc--discard-trailing-multiline-nulls
+ erc--inhibit-slash-cmd-insertion)
"Special hook for reviewing and modifying prompt input.
ERC runs this before clearing the prompt and before running any
send-related hooks, such as `erc-pre-send-functions'. Thus, it's
@@ -1128,9 +1275,13 @@ if they wish to avoid sending of a particular string.")
"Insertion hook for functions that will change the text's appearance.
This hook is called just after `erc-insert-pre-hook' when the value
of `erc-insert-this' is t.
-While this hook is run, narrowing is in effect and `current-buffer' is
-the buffer where the text got inserted. One possible value to add here
-is `erc-fill'."
+
+ERC runs this hook with the buffer narrowed to the bounds of the
+inserted message plus a trailing newline. Built-in modules place
+their hook members at depths between 20 and 80, with those from
+the stamp module always running last. Use the functions
+`erc-find-parsed-property' and `erc-get-parsed-vector' to locate
+and extract the `erc-response' object for the inserted message."
:group 'erc-hooks
:type 'hook)
@@ -1294,12 +1445,6 @@ This will only be used if `erc-header-line-face-method' is non-nil."
"ERC face for the prompt."
:group 'erc-faces)
-(defface erc-command-indicator-face
- '((t :weight bold))
- "ERC face for the command indicator.
-See the variable `erc-command-indicator'."
- :group 'erc-faces)
-
(defface erc-notice-face
'((default :weight bold)
(((class color) (min-colors 88) (supports :weight semi-bold))
@@ -1307,13 +1452,13 @@ See the variable `erc-command-indicator'."
(((class color) (min-colors 88)) :foreground "SlateBlue")
(t :foreground "blue"))
"ERC face for notices."
- :package-version '(ERC . "5.6") ; FIXME sync on release
+ :package-version '(ERC . "5.6")
:group 'erc-faces)
(defface erc-action-face '((((supports :weight semi-bold)) :weight semi-bold)
(t :weight bold))
"ERC face for actions generated by /ME."
- :package-version '(ERC . "5.6") ; FIXME sync on release
+ :package-version '(ERC . "5.6")
:group 'erc-faces)
(defface erc-error-face '((t :foreground "red"))
@@ -1336,9 +1481,8 @@ See also `erc-show-my-nick'."
;; Debugging support
-(defvar erc-log-p nil
- "When set to t, generate debug messages in a separate debug buffer.")
-
+;; FIXME if this variable plays some role, indicate that here.
+;; Otherwise, deprecate.
(defvar erc-debug-log-file (expand-file-name "ERC.debug")
"Debug log file name.")
@@ -1355,16 +1499,15 @@ buffer during local-module setup and `erc-mode-hook' activation.")
(defmacro erc--restore-initialize-priors (mode &rest vars)
"Restore local VARS for MODE from a previous session."
(declare (indent 1))
- (let ((existing (make-symbol "existing"))
+ (let ((priors (make-symbol "priors"))
+ (initp (make-symbol "initp"))
;;
- restore initialize)
- (while-let ((k (pop vars)) (v (pop vars)))
- (push `(,k (alist-get ',k ,existing)) restore)
- (push `(,k ,v) initialize))
- `(if-let* ((,existing (or erc--server-reconnecting erc--target-priors))
- ((alist-get ',mode ,existing)))
- (setq ,@(mapcan #'identity (nreverse restore)))
- (setq ,@(mapcan #'identity (nreverse initialize))))))
+ forms)
+ (while-let ((k (pop vars)))
+ (push `(,k (if ,initp (alist-get ',k ,priors) ,(pop vars))) forms))
+ `(let* ((,priors (or erc--server-reconnecting erc--target-priors))
+ (,initp (and ,priors (alist-get ',mode ,priors))))
+ (setq ,@(mapcan #'identity (nreverse forms))))))
(defun erc--target-from-string (string)
"Construct an `erc--target' variant from STRING."
@@ -1375,16 +1518,6 @@ buffer during local-module setup and `erc-mode-hook' activation.")
#'make-erc--target)
:string string :symbol (intern (erc-downcase string))))
-(defvar-local erc--target nil
- "Info about a buffer's target, if any.")
-
-;; Temporary internal getter to ease transition to `erc--target'
-;; everywhere. Will be replaced by updated `erc-default-target'.
-(defun erc--default-target ()
- "Return target string or nil."
- (when erc--target
- (erc--target-string erc--target)))
-
(defun erc-once-with-server-event (event f)
"Run function F the next time EVENT occurs in the `current-buffer'.
@@ -1401,7 +1534,7 @@ Please be sure to use this function in server-buffers. In
channel-buffers it may not work at all, as it uses the LOCAL
argument of `add-hook' and `remove-hook' to ensure multiserver
capabilities."
- (unless (erc-server-buffer-p)
+ (unless (erc--server-buffer-p)
(error
"You should only run `erc-once-with-server-event' in a server buffer"))
(let ((fun (make-symbol "fun"))
@@ -1458,26 +1591,37 @@ the process buffer."
(and (processp erc-server-process)
(buffer-live-p (process-buffer erc-server-process))))
-(defun erc-server-buffer-p (&optional buffer)
+(define-obsolete-function-alias
+ 'erc-server-buffer-p 'erc-server-or-unjoined-channel-buffer-p "30.1")
+(defun erc-server-or-unjoined-channel-buffer-p (&optional buffer)
"Return non-nil if argument BUFFER is an ERC server buffer.
-
-If BUFFER is nil, the current buffer is used."
+If BUFFER is nil, use the current buffer. For historical
+reasons, also return non-nil for channel buffers the client has
+parted or from which it's been kicked."
(with-current-buffer (or buffer (current-buffer))
(and (eq major-mode 'erc-mode)
(null (erc-default-target)))))
+(defun erc--server-buffer-p (&optional buffer)
+ "Return non-nil if BUFFER is an ERC server buffer.
+Without BUFFER, use the current buffer."
+ (if buffer
+ (with-current-buffer buffer
+ (and (eq major-mode 'erc-mode) (null erc--target)))
+ (and (eq major-mode 'erc-mode) (null erc--target))))
+
(defun erc-open-server-buffer-p (&optional buffer)
"Return non-nil if BUFFER is an ERC server buffer with an open IRC process.
If BUFFER is nil, the current buffer is used."
- (and (erc-server-buffer-p buffer)
+ (and (erc--server-buffer-p buffer)
(erc-server-process-alive buffer)))
(defun erc-query-buffer-p (&optional buffer)
"Return non-nil if BUFFER is an ERC query buffer.
If BUFFER is nil, the current buffer is used."
(with-current-buffer (or buffer (current-buffer))
- (let ((target (erc-default-target)))
+ (let ((target (erc-target)))
(and (eq major-mode 'erc-mode)
target
(not (memq (aref target 0) '(?# ?& ?+ ?!)))))))
@@ -1538,6 +1682,7 @@ Defaults to the server buffer."
(setq-local paragraph-start
(concat "\\(" (regexp-quote (erc-prompt)) "\\)"))
(setq-local completion-ignore-case t)
+ (add-hook 'post-command-hook #'erc-check-text-conversion nil t)
(add-hook 'kill-buffer-hook #'erc-kill-buffer-function nil t)
(add-hook 'completion-at-point-functions #'erc-complete-word-at-point nil t))
@@ -1630,7 +1775,7 @@ All are symbols indicating an inciting user action, such as the
issuance of a slash command, the clicking of a URL hyperlink, or
the invocation of an entry-point command. See Info node `(erc)
display-buffer' for more."
- :package-version '(ERC . "5.6") ; FIXME sync on release
+ :package-version '(ERC . "5.6")
:group 'erc-buffers
:type erc--buffer-display-choices)
@@ -1654,7 +1799,7 @@ of the second, \"action\" argument. The item's key is the symbol
"Duration `erc-auto-reconnect-display' remains active.
The countdown starts on MOTD and is canceled early by any
\"slash\" command."
- :package-version '(ERC . "5.6") ; FIXME sync on release
+ :package-version '(ERC . "5.6")
:type 'integer
:group 'erc-buffers)
@@ -1665,7 +1810,7 @@ for server buffers when automatically reconnecting, nor does it
consider `erc-interactive-display' when users issue a /RECONNECT.
Enabling this tells ERC to always display server buffers
according to those options."
- :package-version '(ERC . "5.6") ; FIXME sync on release
+ :package-version '(ERC . "5.6")
:type 'boolean
:group 'erc-buffers)
@@ -1841,7 +1986,10 @@ All strings are compared according to IRC protocol case rules, see
(defun erc-get-buffer (target &optional proc)
"Return the buffer matching TARGET in the process PROC.
-If PROC is not supplied, all processes are searched."
+Without PROC, search all ERC buffers. For historical reasons,
+skip buffers for channels the client has \"PART\"ed or from which
+it's been \"KICK\"ed. Expect users to use a different function
+for finding targets independent of \"JOIN\"edness."
(let ((downcased-target (erc-downcase target)))
(catch 'buffer
(erc-buffer-filter
@@ -1993,9 +2141,17 @@ buffer rather than a server buffer.")
;; each item is in the format '(old . new)
(delete-dups (mapcar #'erc--normalize-module-symbol mods)))
+(defun erc--sort-modules (modules)
+ "Return a copy of MODULES, deduped and led by sorted built-ins."
+ (let (built-in third-party)
+ (dolist (mod modules)
+ (setq mod (erc--normalize-module-symbol mod))
+ (cl-pushnew mod (if (get mod 'erc--module) built-in third-party)))
+ `(,@(sort built-in #'string-lessp) ,@(nreverse third-party))))
+
(defcustom erc-modules '( autojoin button completion fill imenu irccontrols
list match menu move-to-prompt netsplit
- networks noncommands readonly ring stamp track)
+ networks readonly ring stamp track)
"A list of modules which ERC should enable.
If you set the value of this without using `customize' remember to call
\(erc-update-modules) after you change it. When using `customize', modules
@@ -2022,22 +2178,17 @@ removed from the list will be disabled."
(when (symbol-value f)
(message "Disabling `erc-%s'" module)
(funcall f 0))
+ ;; Disable local module in all ERC buffers.
(unless (or (custom-variable-p f)
(not (fboundp 'erc-buffer-filter)))
(erc-buffer-filter (lambda ()
(when (symbol-value f)
(funcall f 0))
(kill-local-variable f)))))))))
- (let (built-in third-party)
- (dolist (v val)
- (setq v (erc--normalize-module-symbol v))
- (if (get v 'erc--module)
- (push v built-in)
- (push v third-party)))
- ;; Calling `set-default-toplevel-value' complicates testing
- (set sym (append (sort built-in #'string-lessp)
- (nreverse third-party))))
- ;; this test is for the case where erc hasn't been loaded yet
+ ;; Calling `set-default-toplevel-value' complicates testing.
+ (set sym (erc--sort-modules val))
+ ;; Don't initialize modules on load, even though the rare
+ ;; third-party module may need it.
(when (fboundp 'erc-update-modules)
(unless erc--inside-mode-toggle-p
(erc-update-modules))))
@@ -2050,6 +2201,7 @@ removed from the list will be disabled."
(const :tag "button: Buttonize URLs, nicknames, and other text" button)
(const :tag "capab: Mark unidentified users on servers supporting CAPAB"
capab-identify)
+ (const :tag "command-indicator: Echo command lines." command-indicator)
(const :tag "completion: Complete nicknames and commands (programmable)"
completion)
(const :tag "dcc: Provide Direct Client-to-Client support" dcc)
@@ -2067,9 +2219,9 @@ removed from the list will be disabled."
move-to-prompt)
(const :tag "netsplit: Detect netsplits" netsplit)
(const :tag "networks: Provide data about IRC networks" networks)
- (const :tag "nickbar: Show nicknames in a dyamic side window" nickbar)
+ (const :tag "nickbar: Show nicknames in a dynamic side window" nickbar)
(const :tag "nicks: Uniquely colorize nicknames in target buffers" nicks)
- (const :tag "noncommands: Don't display non-IRC commands after evaluation"
+ (const :tag "noncommands: Deprecated. See module `command-indicator'."
noncommands)
(const :tag "notifications: Desktop alerts on PRIVMSG or mentions"
notifications)
@@ -2095,32 +2247,57 @@ removed from the list will be disabled."
(const :tag "unmorse: Translate morse code in messages" unmorse)
(const :tag "xdcc: Act as an XDCC file-server" xdcc)
(repeat :tag "Others" :inline t symbol))
- :package-version '(ERC . "5.6") ; FIXME sync on release
+ :package-version '(ERC . "5.6")
:group 'erc)
(defun erc-update-modules ()
"Enable minor mode for every module in `erc-modules'.
Except ignore all local modules, which were introduced in ERC 5.5."
- (erc--update-modules)
+ (erc--update-modules erc-modules)
nil)
+(defvar erc--aberrant-modules nil
+ "Modules suspected of being improperly loaded.")
+
+(defun erc--warn-about-aberrant-modules ()
+ (when (and erc--aberrant-modules (not erc--target))
+ (erc-button--display-error-notice-with-keys-and-warn
+ "The following modules likely engage in unfavorable loading practices: "
+ (mapconcat (lambda (s) (format "`%s'" s)) erc--aberrant-modules ", ")
+ ". Please contact ERC with \\[erc-bug] if you believe this to be untrue."
+ " See Info:\"(erc) Module Loading\" for more.")
+ (setq erc--aberrant-modules nil)))
+
+(defvar erc--requiring-module-mode-p nil
+ "Non-nil while doing (require \\='erc-mymod) for `mymod' in `erc-modules'.
+Used for inhibiting potentially recursive `erc-update-modules'
+invocations by third-party packages.")
+
(defun erc--find-mode (sym)
(setq sym (erc--normalize-module-symbol sym))
- (if-let* ((mode (intern-soft (concat "erc-" (symbol-name sym) "-mode")))
- ((or (boundp mode)
- (and (fboundp mode)
- (autoload-do-load (symbol-function mode) mode)))))
+ (if-let ((mode (intern-soft (concat "erc-" (symbol-name sym) "-mode")))
+ ((and (fboundp mode)
+ (autoload-do-load (symbol-function mode) mode)))
+ ((or (get sym 'erc--module)
+ (symbol-file mode)
+ (ignore (cl-pushnew sym erc--aberrant-modules)))))
mode
- (and (require (or (get sym 'erc--feature)
- (intern (concat "erc-" (symbol-name sym))))
- nil 'noerror)
- (setq mode (intern-soft (concat "erc-" (symbol-name sym) "-mode")))
+ (and (or (and erc--requiring-module-mode-p
+ ;; Also likely non-nil: (eq sym (car features))
+ (cl-pushnew sym erc--aberrant-modules))
+ (let ((erc--requiring-module-mode-p t))
+ (require (or (get sym 'erc--feature)
+ (intern (concat "erc-" (symbol-name sym))))
+ nil 'noerror))
+ (memq sym erc--aberrant-modules))
+ (or mode (setq mode (intern-soft (concat "erc-" (symbol-name sym)
+ "-mode"))))
(fboundp mode)
mode)))
-(defun erc--update-modules ()
+(defun erc--update-modules (modules)
(let (local-modes)
- (dolist (module erc-modules local-modes)
+ (dolist (module modules local-modes)
(if-let ((mode (erc--find-mode module)))
(if (custom-variable-p mode)
(funcall mode 1)
@@ -2147,7 +2324,7 @@ realizes it's missing some required module \"foo\", it can
confidently call (erc-foo-mode 1) without having to learn
anything about the dependency's implementation.")
-(defvar erc--setup-buffer-hook nil
+(defvar erc--setup-buffer-hook '(erc--warn-about-aberrant-modules)
"Internal hook for module setup involving windows and frames.")
(defvar erc--display-context nil
@@ -2247,7 +2424,9 @@ nil."
(set-marker-insertion-type erc-insert-marker t)
(cl-assert (= (field-end erc-insert-marker) erc-input-marker))
(goto-char old-point)
- (erc--unhide-prompt))
+ (let ((erc--hidden-prompt-overlay
+ (alist-get 'erc--hidden-prompt-overlay continued-session)))
+ (erc--unhide-prompt)))
(cl-assert (not (get-text-property (point) 'erc-prompt)))
;; In the original version from `erc-open', the snippet that
;; handled these newline insertions appeared twice close in
@@ -2304,7 +2483,8 @@ Returns the buffer for the given server or channel."
(setq old-point (point))
(setq delayed-modules
(erc--merge-local-modes (let ((erc--updating-modules-p t))
- (erc--update-modules))
+ (erc--update-modules
+ (erc--sort-modules erc-modules)))
(or erc--server-reconnecting
erc--target-priors)))
@@ -2362,8 +2542,8 @@ Returns the buffer for the given server or channel."
(when erc-log-p
(get-buffer-create (concat "*ERC-DEBUG: " server "*"))))
- (erc-determine-parameters server port nick full-name user passwd)
(erc--initialize-markers old-point continued-session)
+ (erc-determine-parameters server port nick full-name user passwd)
(save-excursion (run-mode-hooks)
(dolist (mod (car delayed-modules)) (funcall mod +1))
(dolist (var (cdr delayed-modules)) (set var nil)))
@@ -2432,10 +2612,12 @@ in here get called with three parameters, SERVER, PORT and NICK."
:type '(repeat function))
(defcustom erc-after-connect nil
- "Functions called after connecting to a server.
-This functions in this variable gets executed when an end of MOTD
-has been received. All functions in here get called with the
-parameters SERVER and NICK."
+ "Abnormal hook run upon establishing a logical IRC connection.
+Runs on MOTD's end when `erc-server-connected' becomes non-nil.
+ERC calls members with `erc-server-announced-name', falling back
+to the 376/422 message's \"sender\", as well as the current nick,
+as given by the 376/422 message's \"target\" parameter, which is
+typically the same as that reported by `erc-current-nick'."
:group 'erc-hooks
:type '(repeat function))
@@ -2460,7 +2642,7 @@ With prefix arg, also prompt for user and full name."
(let* ((input (let ((d (erc-compute-server)))
(if erc--prompt-for-server-function
(funcall erc--prompt-for-server-function)
- (read-string (format "Server or URL (default is %S): " d)
+ (read-string (format-prompt "Server or URL" d)
nil 'erc-server-history-list d))))
;; For legacy reasons, also accept a URL without a scheme.
(url (url-generic-parse-url (erc--ensure-url input)))
@@ -2469,27 +2651,27 @@ With prefix arg, also prompt for user and full name."
(port (or (url-portspec url)
(erc-compute-port
(let ((d (erc-compute-port sp))) ; may be a string
- (read-string (format "Port (default is %s): " d)
+ (read-string (format-prompt "Port" d)
nil nil d)))))
;; Trust the user not to connect twice accidentally. We
;; can't use `erc-already-logged-in' to check for an existing
;; connection without modifying it to consider USER and PASS.
(nick (or (url-user url)
(let ((d (erc-compute-nick)))
- (read-string (format "Nickname (default is %S): " d)
+ (read-string (format-prompt "Nickname" d)
nil 'erc-nick-history-list d))))
(user (and current-prefix-arg
(let ((d (erc-compute-user (url-user url))))
- (read-string (format "User (default is %S): " d)
+ (read-string (format-prompt "User" d)
nil nil d))))
(full (and current-prefix-arg
(let ((d (erc-compute-full-name (url-user url))))
- (read-string (format "Full name (default is %S): " d)
+ (read-string (format-prompt "Full name" d)
nil nil d))))
(passwd (let* ((p (with-suppressed-warnings ((obsolete erc-password))
(or (url-password url) erc-password)))
(m (if p
- (format "Server password (default is %S): " p)
+ (format-prompt "Server password" p)
"Server password (optional): ")))
(if erc-prompt-for-password (read-passwd m nil p) p)))
(opener (and (or sp (eql port erc-default-port-tls)
@@ -2670,12 +2852,15 @@ PARAMETERS should be a sequence of keywords and values, per
(defun erc-open-socks-tls-stream (name buffer host service &rest parameters)
"Connect to an IRC server via SOCKS proxy over TLS.
-Bind `erc-server-connect-function' to this function around calls
-to `erc-tls'. See `erc-open-network-stream' for the meaning of
-NAME and BUFFER. HOST should be a \".onion\" URL, SERVICE a TLS
-port number, and PARAMETERS a sequence of key/value pairs, per
-`open-network-stream'. See Info node `(erc) SOCKS' for more
-info."
+Defer to the `socks' and `gnutls' libraries to make the actual
+connection and perform TLS negotiation. Expect SERVICE to be a
+TLS port number and that the plist PARAMETERS contains a
+`:client-certificate' pair when necessary. Otherwise, assume the
+arguments NAME, BUFFER, and HOST to be acceptable to
+`open-network-stream' and that users know to check out
+`erc-server-connect-function' and Info node `(erc) SOCKS' for
+more info, including an important example of how to \"wrap\" this
+function with SOCKS credentials."
(require 'gnutls)
(require 'socks)
(let ((proc (socks-open-network-stream name buffer host service))
@@ -2695,6 +2880,15 @@ message instead, to make debugging easier."
(apply #'message args)
(beep)))
+(defvar erc--warnings-buffer-name nil
+ "Name of possibly existing alternate warnings buffer for unit tests.")
+
+(defun erc--lwarn (type level format-string &rest args)
+ "Issue a warning of TYPE and LEVEL with FORMAT-STRING and ARGS."
+ (let ((message (substitute-command-keys
+ (apply #'format-message format-string args))))
+ (display-warning type message level erc--warnings-buffer-name)))
+
;;; Debugging the protocol
(defvar erc-debug-irc-protocol-time-format "%FT%T.%6N%z "
@@ -2840,21 +3034,75 @@ If ARG is non-nil, show the *erc-protocol* buffer."
;; send interface
+(defvar erc--send-action-function #'erc--send-action
+ "Function to display and send an outgoing CTCP ACTION message.
+Called with three arguments: the submitted input, the current
+target, and an `erc-server-send' FORCE flag.")
+
(defun erc-send-action (tgt str &optional force)
"Send CTCP ACTION information described by STR to TGT."
- (erc-send-ctcp-message tgt (format "ACTION %s" str) force)
- (let ((erc-insert-pre-hook
- (cons (lambda (s) ; Leave newline be.
- (put-text-property 0 (1- (length s)) 'erc-command 'PRIVMSG s)
- (put-text-property 0 (1- (length s)) 'erc-ctcp 'ACTION s))
- erc-insert-pre-hook))
+ (funcall erc--send-action-function tgt str force))
+
+;; Sending and displaying are provided separately to afford modules
+;; more flexibility, e.g., to forgo displaying on the way out when
+;; expecting the server to echo messages back and/or to associate
+;; outgoing messages with IDs generated for `erc--ephemeral'
+;; placeholders.
+(defun erc--send-action-perform-ctcp (target string force)
+ "Send STRING to TARGET, possibly immediately, with FORCE."
+ (erc-send-ctcp-message target (format "ACTION %s" string) force))
+
+(defvar erc--use-language-catalog-for-ctcp-action-p nil
+ "When non-nil, use `ACTION' entry from language catalog for /ME's.
+Otherwise, use `ctcp-action' or `ctcp-action-input' from the
+internal `-speaker' catalog. This is an escape hatch to restore
+pre-5.6 behavior for the `font-lock-face' property of incoming
+and outgoing \"CTCP ACTION\" messages, whose pre-buttonized state
+was a single interval of `erc-input-face' or `erc-action-face'.
+Newer modules, like `fill-wrap' and `nicks', are incompatible with
+this format style. If you use this, please ask ERC to expose it
+as a public variable via \\[erc-bug] or similar.")
+
+(defun erc--send-action-display (string)
+ "Display STRING as an outgoing \"CTCP ACTION\" message.
+Propertize the message according to the compatibility flag
+`erc--use-language-catalog-for-ctcp-action-p'."
+ ;; Allow hooks acting on inserted PRIVMSG and NOTICES to process us.
+ (let ((erc--msg-prop-overrides `((erc--ctcp . ACTION)
+ ,@erc--msg-prop-overrides))
(nick (erc-current-nick)))
- (setq nick (propertize nick 'erc-speaker nick))
- (erc-display-message nil '(t action input) (current-buffer)
- 'ACTION ?n nick ?a str ?u "" ?h "")))
+ (if erc--use-language-catalog-for-ctcp-action-p
+ (progn (erc--ensure-spkr-prop nick)
+ (erc-display-message nil 'input (current-buffer) 'ACTION
+ ?n (propertize nick 'erc--speaker nick)
+ ?a string ?u "" ?h ""))
+ (let ((erc-current-message-catalog erc--message-speaker-catalog))
+ (erc-display-message nil nil (current-buffer) 'ctcp-action-input
+ ?p (erc-get-channel-membership-prefix nick)
+ ?n (erc--speakerize-nick nick) ?m string)))))
+
+(defun erc--send-action (target string force)
+ "Display STRING, then send to TARGET as a \"CTCP ACTION\" message."
+ (erc--send-action-display string)
+ (erc--send-action-perform-ctcp target string force))
;; Display interface
+(defun erc--ensure-spkr-prop (nick &optional overrides)
+ "Add NICK as `erc--spkr' to the current \"msg props\" environment.
+Prefer `erc--msg-props' over `erc--msg-prop-overrides' when both
+are available. Also include any members of the alist OVERRIDES,
+when present. Assume NICK itself to be free of any text props,
+and return it."
+ (cond (erc--msg-props
+ (puthash 'erc--spkr nick erc--msg-props)
+ (dolist (entry overrides)
+ (puthash (car entry) (cdr entry) erc--msg-props)))
+ (erc--msg-prop-overrides
+ (setq erc--msg-prop-overrides
+ `((erc--spkr . ,nick) ,@overrides ,@erc--msg-prop-overrides))))
+ nick)
+
(defun erc-string-invisible-p (string)
"Check whether STRING is invisible or not.
I.e. any char in it has the `invisible' property set."
@@ -2865,9 +3113,18 @@ I.e. any char in it has the `invisible' property set."
The default is to remove it, since it causes ERC to take up extra
memory. If you have code that relies on this property, then set
-this option to nil."
+this option to nil.
+
+Note that this option is deprecated because a value of nil is
+impractical in prolonged sessions with more than a few channels.
+Use `erc-insert-post-hook' or similar and the helper function
+`erc-find-parsed-property' and friends to stash the current
+`erc-response' object as needed. And instead of using this for
+debugging purposes, try `erc-debug-irc-protocol'."
:type 'boolean
:group 'erc)
+(make-obsolete-variable 'erc-remove-parsed-property
+ "impractical when non-nil" "30.1")
(define-inline erc--assert-input-bounds ()
(inline-quote
@@ -2879,47 +3136,213 @@ this option to nil."
(cl-assert (< erc-insert-marker erc-input-marker))
(cl-assert (= (field-end erc-insert-marker) erc-input-marker)))))
-(defvar erc--refresh-prompt-hook nil)
+(defvar erc--merge-prop-behind-p nil
+ "When non-nil, put merged prop(s) behind existing.")
+
+(defvar erc--refresh-prompt-hook nil
+ "Hook called after refreshing the prompt in the affected buffer.")
+
+(defvar-local erc--inhibit-prompt-display-property-p nil
+ "Tell `erc-prompt' related functions to avoid the `display' text prop.
+Modules can enable this when needing to reserve the prompt's
+display property for some other purpose, such as displaying it
+elsewhere, abbreviating it, etc.")
+
+(defconst erc--prompt-properties '( rear-nonsticky t
+ erc-prompt t ; t or `hidden'
+ field erc-prompt
+ front-sticky t
+ read-only t)
+ "Mandatory text properties added to ERC's prompt.")
+
+(defvar erc--refresh-prompt-continue-request nil
+ "State flag for refreshing prompt in all buffers.
+When the value is zero, functions assigned to the variable
+`erc-prompt' can set this to run `erc--refresh-prompt-hook' (1)
+or `erc--refresh-prompt' (2) in all buffers of the server.")
+
+(defun erc--refresh-prompt-continue (&optional hooks-only-p)
+ "Ask ERC to refresh the prompt in all buffers.
+Functions assigned to `erc-prompt' can call this if needing to
+recreate the prompt in other buffers as well. With HOOKS-ONLY-P,
+run `erc--refresh-prompt-hook' in other buffers instead of doing
+a full refresh."
+ (when (and erc--refresh-prompt-continue-request
+ (zerop erc--refresh-prompt-continue-request))
+ (setq erc--refresh-prompt-continue-request (if hooks-only-p 1 2))))
(defun erc--refresh-prompt ()
"Re-render ERC's prompt when the option `erc-prompt' is a function."
(erc--assert-input-bounds)
(unless (erc--prompt-hidden-p)
- (when (functionp erc-prompt)
- (save-excursion
- (goto-char erc-insert-marker)
- (set-marker-insertion-type erc-insert-marker nil)
- ;; Avoid `erc-prompt' (the named function), which appends a
- ;; space, and `erc-display-prompt', which propertizes all but
- ;; that space.
- (insert-and-inherit (funcall erc-prompt))
- (set-marker-insertion-type erc-insert-marker t)
- (delete-region (point) (1- erc-input-marker))))
- (run-hooks 'erc--refresh-prompt-hook)))
-
-(defun erc-display-line-1 (string buffer)
- "Display STRING in `erc-mode' BUFFER.
-Auxiliary function used in `erc-display-line'. The line gets filtered to
-interpret the control characters. Then, `erc-insert-pre-hook' gets called.
-If `erc-insert-this' is still t, STRING gets inserted into the buffer.
-Afterwards, `erc-insert-modify' and `erc-insert-post-hook' get called.
-If STRING is nil, the function does nothing."
+ (let ((erc--refresh-prompt-continue-request
+ (or erc--refresh-prompt-continue-request 0)))
+ (when (functionp erc-prompt)
+ (save-excursion
+ (goto-char (1- erc-input-marker))
+ ;; Avoid `erc-prompt' (the named function), which appends a
+ ;; space, and `erc-display-prompt', which propertizes all
+ ;; but that space.
+ (let ((s (funcall erc-prompt))
+ (p (point))
+ (erc--merge-prop-behind-p t))
+ (erc--merge-prop 0 (length s) 'font-lock-face 'erc-prompt-face s)
+ (add-text-properties 0 (length s) erc--prompt-properties s)
+ (insert s)
+ (delete-region erc-insert-marker p))))
+ (run-hooks 'erc--refresh-prompt-hook)
+ (when-let (((> erc--refresh-prompt-continue-request 0))
+ (n erc--refresh-prompt-continue-request)
+ (erc--refresh-prompt-continue-request -1)
+ (b (current-buffer)))
+ (erc-with-all-buffers-of-server erc-server-process
+ (lambda () (not (eq b (current-buffer))))
+ (if (= n 1)
+ (run-hooks 'erc--refresh-prompt-hook)
+ (erc--refresh-prompt)))))))
+
+(defun erc--check-msg-prop (prop &optional val)
+ "Return PROP's value in `erc--msg-props' when populated.
+If VAL is a list, return non-nil if PROP appears in VAL. If VAL
+is otherwise non-nil, return non-nil if VAL compares `eq' to the
+stored value. Otherwise, return the stored value."
+ (and-let* ((erc--msg-props)
+ (v (gethash prop erc--msg-props)))
+ (if (consp val) (memq v val) (if val (eq v val) v))))
+
+(defmacro erc--get-inserted-msg-beg-at (point at-start-p)
+ (macroexp-let2* nil ((point point)
+ (at-start-p at-start-p))
+ `(or (and ,at-start-p ,point)
+ (and-let* ((p (previous-single-property-change ,point 'erc--msg)))
+ (if (and (= p (1- ,point)) (get-text-property p 'erc--msg))
+ p
+ (1- p))))))
+
+(defmacro erc--get-inserted-msg-end-at (point at-start-p)
+ (macroexp-let2 nil point point
+ `(1- (next-single-property-change (if ,at-start-p (1+ ,point) ,point)
+ 'erc--msg nil erc-insert-marker))))
+
+(defun erc--get-inserted-msg-beg (&optional point)
+ "Maybe return the start of message in an ERC buffer."
+ (erc--get-inserted-msg-beg-at (or point (setq point (point)))
+ (get-text-property point 'erc--msg)))
+
+(defun erc--get-inserted-msg-end (&optional point)
+ "Return the end of message in an ERC buffer.
+Include any trailing white space before final newline. Expect
+POINT to be less than `erc-insert-marker', and don't bother
+considering `erc--insert-marker', for now."
+ (erc--get-inserted-msg-end-at (or point (setq point (point)))
+ (get-text-property point 'erc--msg)))
+
+(defun erc--get-inserted-msg-bounds (&optional point)
+ "Return bounds of message at POINT in an ERC buffer when found.
+Search from POINT, when non-nil, instead of `point'. Return nil
+if not found."
+ (let ((at-start-p (get-text-property (or point (setq point (point)))
+ 'erc--msg)))
+ (and-let* ((b (erc--get-inserted-msg-beg-at point at-start-p)))
+ (cons b (erc--get-inserted-msg-end-at point at-start-p)))))
+
+(defun erc--get-inserted-msg-prop (prop)
+ "Return the value of text property PROP for some message at point."
+ (and-let* ((stack-pos (erc--get-inserted-msg-beg (point))))
+ (get-text-property stack-pos prop)))
+
+(defmacro erc--with-inserted-msg (&rest body)
+ "Simulate narrowing performed for send and insert hooks, and run BODY.
+Expect callers to know that this doesn't wrap BODY in
+`with-silent-modifications' or bind a temporary `erc--msg-props'."
+ `(when-let ((bounds (erc--get-inserted-msg-bounds)))
+ (save-restriction
+ (narrow-to-region (car bounds) (1+ (cdr bounds)))
+ ,@body)))
+
+(defun erc--traverse-inserted (beg end fn)
+ "Visit messages between BEG and END and run FN in narrowed buffer.
+If END is a marker, possibly update its position."
+ (unless (markerp end)
+ (setq end (set-marker (make-marker) (or end erc-insert-marker))))
+ (unless (eq end erc-insert-marker)
+ (set-marker end (min erc-insert-marker end)))
+ (save-excursion
+ (goto-char beg)
+ (let ((b (if (get-text-property (point) 'erc--msg)
+ (point)
+ (next-single-property-change (point) 'erc--msg nil end))))
+ (while-let ((b)
+ ((< b end))
+ (e (next-single-property-change (1+ b) 'erc--msg nil end)))
+ (save-restriction
+ (narrow-to-region b e)
+ (funcall fn))
+ (setq b e))))
+ (unless (eq end erc-insert-marker)
+ (set-marker end nil)))
+
+(defvar erc--insert-invisible-as-intangible-p nil
+ "When non-nil, ensure certain invisible messages are also intangible.
+That is, single out any message inserted via `erc-insert-line'
+that lacks a trailing newline but has a t-valued `invisible'
+property anywhere along its length, and ensure it's both
+`invisible' t and `intangible' t throughout. Note that this is
+merely an escape hatch for accessing aberrant pre-5.6 behavior
+that ERC considers a bug because it applies a practice described
+as obsolete in the manual, and it does so heavy-handedly. That
+the old behavior only acted when the input lacked a trailing
+newline was likely accidental but is ultimately incidental. See
+info node `(elisp) Special Properties' for specifics. Beware
+that this flag and the behavior it restores may disappear at any
+time, so if you need them, please let ERC know with \\[erc-bug].")
+
+(defvar erc--insert-line-function nil
+ "When non-nil, an alterntive to `insert' for inserting messages.")
+
+(defvar erc--insert-marker nil
+ "Internal override for `erc-insert-marker'.")
+
+(define-obsolete-function-alias 'erc-display-line-1 'erc-insert-line "30.1")
+(defun erc-insert-line (string buffer)
+ "Insert STRING in an `erc-mode' BUFFER.
+When STRING is nil, do nothing. Otherwise, start off by running
+`erc-insert-pre-hook' in BUFFER with `erc-insert-this' bound to
+t. If the latter remains non-nil afterward, insert STRING into
+BUFFER, ensuring a trailing newline. After that, narrow BUFFER
+around STRING, along with its final line ending, and run
+`erc-insert-modify' and `erc-insert-post-hook', respectively. In
+all cases, run `erc-insert-done-hook' unnarrowed before exiting,
+and update positions in `buffer-undo-list'.
+
+In general, expect to be called from a higher-level insertion
+function, like `erc-display-message', especially when modules
+should consider STRING as a candidate for formatting with
+enhancements like indentation, fontification, timestamping, etc.
+Otherwise, when called directly, allow built-in modules to ignore
+STRING, which may make it appear incongruous in situ (unless
+preformatted or anticipated by third-party members of the various
+modification hooks)."
(when string
(with-current-buffer (or buffer (process-buffer erc-server-process))
- (let ((insert-position (marker-position erc-insert-marker)))
- (let ((string string) ;; FIXME! Can this be removed?
- (buffer-undo-list t)
+ (let (insert-position)
+ ;; Initialize ^ below to thwart rogue `erc-insert-pre-hook'
+ ;; members that dare to modify the buffer's length.
+ (let ((buffer-undo-list t)
(inhibit-read-only t))
- (unless (string-match "\n$" string)
+ (unless (string-suffix-p "\n" string)
(setq string (concat string "\n"))
- (when (erc-string-invisible-p string)
+ (when (and erc--insert-invisible-as-intangible-p
+ (erc-string-invisible-p string))
(erc-put-text-properties 0 (length string)
'(invisible intangible) string)))
- (erc-log (concat "erc-display-line: " string
+ (erc-log (concat "erc-display-message: " string
(format "(%S)" string) " in buffer "
(format "%s" buffer)))
(setq erc-insert-this t)
(run-hook-with-args 'erc-insert-pre-hook string)
+ (setq insert-position (marker-position (or erc--insert-marker
+ erc-insert-marker)))
(if (null erc-insert-this)
;; Leave erc-insert-this set to t as much as possible. Fran
;; Litterio <franl> has seen erc-insert-this set to nil while
@@ -2930,7 +3353,9 @@ If STRING is nil, the function does nothing."
(save-restriction
(widen)
(goto-char insert-position)
- (insert string)
+ (if erc--insert-line-function
+ (funcall erc--insert-line-function string)
+ (insert string))
(erc--assert-input-bounds)
;; run insertion hook, with point at restored location
(save-restriction
@@ -2939,10 +3364,17 @@ If STRING is nil, the function does nothing."
(run-hooks 'erc-insert-post-hook)
(when erc-remove-parsed-property
(remove-text-properties (point-min) (point-max)
- '(erc-parsed nil))))
+ '(erc-parsed nil tags nil)))
+ (cl-assert (> (- (point-max) (point-min)) 1))
+ (let ((props (if erc--msg-props
+ (erc--order-text-properties-from-hash
+ erc--msg-props)
+ '(erc--msg unknown))))
+ (add-text-properties (point-min) (1+ (point-min)) props)))
(erc--refresh-prompt)))))
(run-hooks 'erc-insert-done-hook)
- (erc-update-undo-list (- (or (marker-position erc-insert-marker)
+ (erc-update-undo-list (- (or (marker-position (or erc--insert-marker
+ erc-insert-marker))
(point-max))
insert-position))))))
@@ -2976,66 +3408,103 @@ If STRING is nil, the function does nothing."
"Check if NICK is a valid IRC nickname."
(string-match (concat "\\`" erc-valid-nick-regexp "\\'") nick))
-(defun erc-display-line (string &optional buffer)
- "Display STRING in the ERC BUFFER.
-All screen output must be done through this function. If BUFFER is nil
-or omitted, the default ERC buffer for the `erc-session-server' is used.
-The BUFFER can be an actual buffer, a list of buffers, `all' or `active'.
-If BUFFER = `all', the string is displayed in all the ERC buffers for the
-current session. `active' means the current active buffer
-\(`erc-active-buffer'). If the buffer can't be resolved, the current
-buffer is used. `erc-display-line-1' is used to display STRING.
-
-If STRING is nil, the function does nothing."
- (let (new-bufs)
+(defun erc--route-insertion (string buffer)
+ "Insert STRING in BUFFER.
+See `erc-display-message' for acceptable BUFFER types."
+ (let (seen msg-props)
(dolist (buf (cond
((bufferp buffer) (list buffer))
- ((listp buffer) buffer)
+ ((consp buffer)
+ (setq msg-props erc--msg-props)
+ buffer)
((processp buffer) (list (process-buffer buffer)))
((eq 'all buffer)
;; Hmm, or all of the same session server?
(erc-buffer-list nil erc-server-process))
- ((and (eq 'active buffer) (erc-active-buffer))
- (list (erc-active-buffer)))
+ ((and-let* (((eq 'active buffer))
+ (b (erc-active-buffer)))
+ (list b)))
((erc-server-buffer-live-p)
(list (process-buffer erc-server-process)))
(t (list (current-buffer)))))
(when (buffer-live-p buf)
- (erc-display-line-1 string buf)
- (push buf new-bufs)))
- (when (null new-bufs)
- (erc-display-line-1 string (if (erc-server-buffer-live-p)
- (process-buffer erc-server-process)
- (current-buffer))))))
-
-(defvar erc--compose-text-properties nil
+ (when msg-props
+ (setq erc--msg-props (copy-hash-table msg-props)))
+ (erc-insert-line string buf)
+ (setq seen t)))
+ (unless (or seen (null buffer))
+ (erc--route-insertion string nil))))
+
+(defun erc-display-line (string &optional buffer)
+ "Insert STRING in BUFFER as a plain \"local\" message.
+Take pains to ensure modification hooks see messages created by
+the old pattern (erc-display-line (erc-make-notice) my-buffer) as
+being equivalent to a `erc-display-message' TYPE of `notice'."
+ (let ((erc--msg-prop-overrides erc--msg-prop-overrides))
+ (when (eq 'erc-notice-face (get-text-property 0 'font-lock-face string))
+ (unless (assq 'erc--msg erc--msg-prop-overrides)
+ (push '(erc--msg . notice) erc--msg-prop-overrides)))
+ (erc-display-message nil nil buffer string)))
+
+(defvar erc--merge-text-properties-p nil
"Non-nil when `erc-put-text-property' defers to `erc--merge-prop'.")
;; To save space, we could maintain a map of all readable property
;; values and optionally dispense archetypal constants in their place
;; in order to ensure all occurrences of some list (a b) across all
;; text-properties in all ERC buffers are actually the same object.
-(defun erc--merge-prop (from to prop val &optional object)
+(defun erc--merge-prop (from to prop val &optional object cache-fn)
"Combine existing PROP values with VAL between FROM and TO in OBJECT.
For spans where PROP is non-nil, cons VAL onto the existing
value, ensuring a proper list. Otherwise, just set PROP to VAL.
When VAL is itself a list, prepend its members onto an existing
-value. See also `erc-button-add-face'."
+value. Call CACHE-FN, when given, with the new value for prop.
+It must return a suitable replacement or the same value. See
+also `erc-button-add-face'."
(let ((old (get-text-property from prop object))
(pos from)
(end (next-single-property-change from prop object to))
new)
(while (< pos to)
(setq new (if old
- (if (listp val)
- (append val (ensure-list old))
- (cons val (ensure-list old)))
+ ;; Can't `nconc' without more info.
+ (if erc--merge-prop-behind-p
+ `(,@(ensure-list old) ,@(ensure-list val))
+ (if (listp val)
+ (append val (ensure-list old))
+ (cons val (ensure-list old))))
val))
+ (when cache-fn
+ (setq new (funcall cache-fn new)))
(put-text-property pos end prop new object)
(setq pos end
old (get-text-property pos prop object)
end (next-single-property-change pos prop object to)))))
+(defun erc--remove-from-prop-value-list (from to prop val &optional object)
+ "Remove VAL from text prop value between FROM and TO.
+If current value is VAL itself, remove the property entirely.
+When VAL is a list, act as if this function were called
+repeatedly with VAL set to each of VAL's members."
+ (let ((old (get-text-property from prop object))
+ (pos from)
+ (end (next-single-property-change from prop object to))
+ new)
+ (while (< pos to)
+ (when old
+ (if (setq new (and (consp old) (if (consp val)
+ (seq-difference old val)
+ (remq val old))))
+ (put-text-property pos end prop
+ (if (cdr new) new (car new)) object)
+ (when (pcase val
+ ((pred consp) (or (consp old) (memq old val)))
+ (_ (if (consp old) (memq val old) (eq old val))))
+ (remove-text-properties pos end (list prop nil) object))))
+ (setq pos end
+ old (get-text-property pos prop object)
+ end (next-single-property-change pos prop object to)))))
+
(defvar erc-legacy-invisible-bounds-p nil
"Whether to hide trailing rather than preceding newlines.
Beginning in ERC 5.6, invisibility extends from a message's
@@ -3045,7 +3514,11 @@ preceding newline to its last non-newline character.")
(defun erc--hide-message (value)
"Apply `invisible' text-property with VALUE to current message.
-Expect to run in a narrowed buffer during message insertion."
+Expect to run in a narrowed buffer during message insertion.
+Begin the invisible interval at the previous message's trailing
+newline and end before the current message's. If the preceding
+message ends in a double newline or there is no previous message,
+don't bother including the preceding newline."
(if erc-legacy-invisible-bounds-p
;; Before ERC 5.6, this also used to add an `intangible'
;; property, but the docs say it's now obsolete.
@@ -3054,8 +3527,59 @@ Expect to run in a narrowed buffer during message insertion."
(end (point-max)))
(save-restriction
(widen)
+ (when (or (<= beg 4) (= ?\n (char-before (- beg 2))))
+ (cl-incf beg))
(erc--merge-prop (1- beg) (1- end) 'invisible value)))))
+(defun erc--toggle-hidden (prop arg)
+ "Toggle invisibility for spec member PROP.
+Treat ARG in a manner similar to mode toggles defined by
+`define-minor-mode'."
+ (when arg
+ (setq arg (prefix-numeric-value arg)))
+ (if (memq prop (ensure-list buffer-invisibility-spec))
+ (unless (natnump arg)
+ (remove-from-invisibility-spec prop))
+ (when (or (not arg) (natnump arg))
+ (add-to-invisibility-spec prop))))
+
+(defun erc--delete-inserted-message (beg-or-point &optional end)
+ "Remove message between BEG and END.
+Expect BEG and END to match bounds as returned by the macro
+`erc--get-inserted-msg-bounds'. Ensure all markers residing at
+the start of the deleted message end up at the beginning of the
+subsequent message."
+ (let ((beg beg-or-point))
+ (save-restriction
+ (widen)
+ (unless end
+ (setq end (erc--get-inserted-msg-bounds beg-or-point)
+ beg (pop end)))
+ (with-silent-modifications
+ (if erc-legacy-invisible-bounds-p
+ (delete-region beg (1+ end))
+ (save-excursion
+ (goto-char beg)
+ (insert-before-markers
+ (substring (delete-and-extract-region (1- (point)) (1+ end))
+ -1))))))))
+
+(defvar erc--ranked-properties
+ '(erc--msg erc--spkr erc--ts erc--cmd erc--ctcp erc--ephemeral))
+
+(defun erc--order-text-properties-from-hash (table)
+ "Return a plist of text props from items in TABLE.
+Ensure props in `erc--ranked-properties' appear last and in
+reverse order so they end up sorted in buffer interval plists for
+retrieval by `text-properties-at' and friends."
+ (let (out)
+ (dolist (k erc--ranked-properties)
+ (when-let ((v (gethash k table)))
+ (remhash k table)
+ (setq out (nconc (list k v) out))))
+ (maphash (lambda (k v) (setq out (nconc (list k v) out))) table)
+ out))
+
(defun erc-display-message-highlight (type string)
"Highlight STRING according to TYPE, where erc-TYPE-face is an ERC face.
@@ -3269,30 +3793,73 @@ returns non-nil."
(defun erc-display-message (parsed type buffer msg &rest args)
"Display MSG in BUFFER.
-ARGS, PARSED, and TYPE are used to format MSG sensibly.
+Insert MSG or text derived from MSG into an ERC buffer, possibly
+after applying formatting by way of either a `format-spec' known
+to a message-catalog entry or a TYPE known to a specialized
+string handler. Additionally, derive metadata, faces, and other
+text properties from the various overloaded parameters, such as
+PARSED, when it's an `erc-response' object, and MSG, when it's a
+key (symbol) for a \"message catalog\" entry. Expect ARGS, when
+applicable, to be `format-spec' args known to such an entry, and
+TYPE, when non-nil, to be a symbol handled by
+`erc-display-message-highlight' (necessarily accompanied by a
+string MSG). Expect BUFFER to be among the sort accepted by the
+function `erc-display-line'.
+
+Expect BUFFER to be a live `erc-mode' buffer, a list of such
+buffers, or the symbols `all' or `active'. If `all', insert
+STRING in all buffers for the current session. If `active',
+defer to the function `erc-active-buffer', which may return the
+session's server buffer if the previously active buffer has been
+killed. If BUFFER is nil or a network process, pretend it's set
+to the appropriate server buffer. Otherwise, use the current
+buffer.
When TYPE is a list of symbols, call handlers from left to right
without influencing how they behave when encountering existing
faces. As of ERC 5.6, expect a TYPE of (notice error) to insert
MSG with `font-lock-face' as `erc-error-face' throughout.
However, when the list of symbols begins with t, tell compatible
-handlers to compose rather than clobber faces. For example, as
-of ERC 5.6, expect a TYPE of (t notice error) to result in MSG's
-`font-lock-face' being (erc-error-face erc-notice-face)
-throughout when `erc-notice-highlight-type' is set to its default
-`all'.
-
-See also `erc-format-message' and `erc-display-line'."
- (let ((string (if (symbolp msg)
- (apply #'erc-format-message msg args)
- msg))
- (erc-message-parsed parsed))
+handlers to compose rather than clobber faces. For example,
+expect a TYPE of (t notice error) to result in `font-lock-face'
+being (erc-error-face erc-notice-face) throughout MSG when
+`erc-notice-highlight-type' is left at its default, `all'.
+
+As of ERC 5.6, assume third-party code will use this function
+instead of lower-level ones, like `erc-insert-line', when needing
+ERC to process arbitrary informative messages as if they'd been
+sent from a server. That is, guarantee \"local\" messages, for
+which PARSED is typically nil, will be subject to buttonizing,
+filling, and other effects."
+ (let* ((erc--msg-props
+ (or erc--msg-props
+ (let ((table (make-hash-table))
+ (cmd (and parsed (erc--get-eq-comparable-cmd
+ (erc-response.command parsed)))))
+ (puthash 'erc--msg
+ (cond ((and msg (symbolp msg)) msg)
+ (type (pcase type
+ ((pred symbolp) type)
+ ((pred listp)
+ (intern (mapconcat #'prin1-to-string
+ type "-")))
+ (_ 'unknown)))
+ (t 'unknown))
+ table)
+ (when cmd
+ (puthash 'erc--cmd cmd table))
+ (when erc--msg-prop-overrides
+ (pcase-dolist (`(,k . ,v) (reverse erc--msg-prop-overrides))
+ (when v (puthash k v table))))
+ table)))
+ (erc-message-parsed parsed)
+ (string (if (symbolp msg) (apply #'erc-format-message msg args) msg)))
(setq string
(cond
((null type)
string)
((listp type)
- (let ((erc--compose-text-properties
+ (let ((erc--merge-text-properties-p
(and (eq (car type) t) (setq type (cdr type)))))
(dolist (type type)
(setq string (erc-display-message-highlight type string))))
@@ -3301,16 +3868,13 @@ See also `erc-format-message' and `erc-display-line'."
(erc-display-message-highlight type string))))
(if (not (erc-response-p parsed))
- (erc-display-line string buffer)
+ (erc--route-insertion string buffer)
(unless (erc-hide-current-message-p parsed)
(erc-put-text-property 0 (length string) 'erc-parsed parsed string)
- (put-text-property
- 0 (length string) 'erc-command
- (erc--get-eq-comparable-cmd (erc-response.command parsed)) string)
(when (erc-response.tags parsed)
(erc-put-text-property 0 (length string) 'tags (erc-response.tags parsed)
string))
- (erc-display-line string buffer)))))
+ (erc--route-insertion string buffer)))))
(defun erc-message-type-member (position list)
"Return non-nil if the erc-parsed text-property at POSITION is in LIST.
@@ -3324,6 +3888,17 @@ present."
"Non-nil when a user types a \"/slash\" command.
Remains bound until `erc-cmd-SLASH' returns.")
+(defvar erc--current-line-input-split nil
+ "Current `erc--input-split' instance when processing user input.
+This is for special cases in which a \"slash\" command needs
+details about the input it's handling or needs to detect whether
+it's been dispatched by `erc-send-current-line'.")
+
+(defvar erc--allow-empty-outgoing-lines-p nil
+ "Flag to opt out of last-minute padding of empty lines.
+Useful to extensions, like `multiline', and for interop with
+IRC-adjacent protocols.")
+
(defvar-local erc-send-input-line-function #'erc-send-input-line
"Function for sending lines lacking a leading \"slash\" command.
When prompt input starts with a \"slash\" command, like \"/MSG\",
@@ -3337,7 +3912,7 @@ for other purposes.")
(defun erc-send-input-line (target line &optional force)
"Send LINE to TARGET."
- (when (string= line "\n")
+ (when (and (not erc--allow-empty-outgoing-lines-p) (string= line "\n"))
(setq line " \n"))
(erc-message "PRIVMSG" (concat target " " line) force))
@@ -3398,7 +3973,7 @@ this function from interpreting the line as a command."
(let ((r (erc-default-target)))
(if r
(funcall erc-send-input-line-function r line force)
- (erc-display-message nil 'error (current-buffer) 'no-target)
+ (erc-display-message nil '(notice error) (current-buffer) 'no-target)
nil)))))
(defconst erc--shell-parse-regexp
@@ -3460,9 +4035,7 @@ need this when pasting multiple lines of text."
(if (string-match "^\\s-*$" line)
nil
(string-match "^ ?\\(.*\\)" line)
- (let ((msg (match-string 1 line)))
- (erc-display-msg msg)
- (erc-process-input-line msg nil t))))
+ (erc-send-message (match-string 1 line) nil)))
(put 'erc-cmd-SAY 'do-not-parse-args t)
(defun erc-cmd-SET (line)
@@ -3575,16 +4148,14 @@ If no USER argument is specified, list the contents of `erc-ignore-list'."
(run-at-time timeout nil
(lambda ()
(erc--unignore-user user buffer))))
- (erc-display-line
- (erc-make-notice (format "Now ignoring %s" user))
- 'active)
+ (erc-display-message nil 'notice 'active
+ (format "Now ignoring %s" user))
(erc-with-server-buffer (add-to-list 'erc-ignore-list user))))
(if (null (erc-with-server-buffer erc-ignore-list))
- (erc-display-line (erc-make-notice "Ignore list is empty") 'active)
- (erc-display-line (erc-make-notice "Ignore list:") 'active)
+ (erc-display-message nil 'notice 'active "Ignore list is empty")
+ (erc-display-message nil 'notice 'active "Ignore list:")
(mapc (lambda (item)
- (erc-display-line (erc-make-notice item)
- 'active))
+ (erc-display-message nil 'notice 'active item))
(erc-with-server-buffer erc-ignore-list))))
t)
@@ -3598,9 +4169,8 @@ If no USER argument is specified, list the contents of `erc-ignore-list'."
(unless (y-or-n-p (format "Remove this regexp (%s)? "
ignored-nick))
(setq ignored-nick nil))
- (erc-display-line
- (erc-make-notice (format "%s is not currently ignored!" user))
- 'active)))
+ (erc-display-message nil 'notice 'active
+ (format "%s is not currently ignored!" user))))
(when ignored-nick
(erc--unignore-user user (current-buffer))))
t)
@@ -3608,9 +4178,8 @@ If no USER argument is specified, list the contents of `erc-ignore-list'."
(defun erc--unignore-user (user buffer)
(when (buffer-live-p buffer)
(with-current-buffer buffer
- (erc-display-line
- (erc-make-notice (format "No longer ignoring %s" user))
- 'active)
+ (erc-display-message nil 'notice 'active
+ (format "No longer ignoring %s" user))
(erc-with-server-buffer
(setq erc-ignore-list (delete user erc-ignore-list))))))
@@ -3619,12 +4188,16 @@ If no USER argument is specified, list the contents of `erc-ignore-list'."
Called with position indicating boundary of interval to be excised.")
(defun erc-cmd-CLEAR ()
- "Clear the window content."
- (let ((inhibit-read-only t))
- (run-hook-with-args 'erc--pre-clear-functions (1- erc-insert-marker))
- ;; Ostensibly, `line-beginning-position' is for use in lisp code.
- (delete-region (point-min) (min (line-beginning-position)
- (1- erc-insert-marker))))
+ "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
+to but not including the one occupying the current line."
+ (with-silent-modifications
+ (let ((max (if (>= (point) erc-insert-marker)
+ (1- erc-insert-marker)
+ (or (erc--get-inserted-msg-beg (point)) (pos-bol)))))
+ (run-hook-with-args 'erc--pre-clear-functions max)
+ (delete-region (point-min) max)))
t)
(put 'erc-cmd-CLEAR 'process-not-needed t)
@@ -3855,11 +4428,22 @@ the one with host foo would win."
(plist-get (car sorted) :secret))))
(defun erc-auth-source-search (&rest plist)
- "Call `auth-source-search', possibly with keyword params in PLIST."
+ "Call `auth-source-search', possibly with keyword params in PLIST.
+If the search signals an error before returning, `warn' the user
+and ask whether to continue connecting anyway."
;; These exist as separate helpers in case folks should find them
;; useful. If that's you, please request that they be exported.
- (apply #'erc--auth-source-search
- (apply #'erc--auth-source-determine-params-merge plist)))
+ (condition-case err
+ (apply #'erc--auth-source-search
+ (apply #'erc--auth-source-determine-params-merge plist))
+ (error
+ (erc--lwarn '(erc auth-source) :error
+ "Problem querying `auth-source': %S. See %S for more."
+ (error-message-string err)
+ '(info "(erc) auth-source Troubleshooting"))
+ (when (or noninteractive
+ (not (y-or-n-p "Ignore auth-source error and continue? ")))
+ (signal (car err) (cdr err))))))
(defun erc-server-join-channel (server channel &optional secret)
"Join CHANNEL, optionally with SECRET.
@@ -4095,12 +4679,10 @@ See `erc-cmd-WHOIS' for more details."
(string-to-number
(cl-third
(erc-response.command-args parsed)))))
- (erc-display-line
- (erc-make-notice
+ (erc-display-message nil 'notice origbuf
(format "%s has been idle for %s."
(erc-string-no-properties nick)
(erc-seconds-to-string idleseconds)))
- origbuf)
t)))
'erc-server-317-functions)
symlist)
@@ -4164,17 +4746,68 @@ the matching is case-sensitive."
(put 'erc-cmd-LASTLOG 'do-not-parse-args t)
(put 'erc-cmd-LASTLOG 'process-not-needed t)
+(defvar erc--send-message-nested-function #'erc--send-message-nested
+ "Function for inserting and sending slash-command generated text.
+When a command like /SV or /SAY modifies or replaces command-line
+input originally submitted at the prompt, `erc-send-message'
+performs additional processing to ensure said input is fit for
+inserting and sending given this \"nested\" meta context. This
+interface variable exists because modules extending fundamental
+insertion and sending operations need a say in this processing as
+well.")
+
(defun erc-send-message (line &optional force)
"Send LINE to the current channel or user and display it.
See also `erc-message' and `erc-display-line'."
- (erc-message "PRIVMSG" (concat (erc-default-target) " " line) force)
- (erc-display-line
- (concat (erc-format-my-nick) line)
- (current-buffer))
+ (if (erc--input-split-p erc--current-line-input-split)
+ (funcall erc--send-message-nested-function line force)
+ (erc--send-message-external line force)))
+
+(defun erc--send-message-external (line force)
+ "Send a \"PRIVMSG\" to the default target with optional FORCE.
+Expect caller to bind `erc-default-recipients' if needing to
+specify a status-prefixed target."
+ ;; Almost like an echoed message, but without the `erc--cmd'.
+ (let* ((erc-current-message-catalog erc--message-speaker-catalog)
+ (target (erc-default-target))
+ (erc--msg-prop-overrides `((erc--tmp) ,@erc--msg-prop-overrides))
+ ;; This util sets the `erc--spkr' property in ^.
+ (trimmed (erc--statusmsg-target target))
+ (stmsgindc (and trimmed (substring target 0 1)))
+ (queryp (and erc--target (not (erc--target-channel-p erc--target))))
+ (args (erc--determine-speaker-message-format-args
+ (erc-current-nick) line queryp 'privmsgp 'inputp
+ stmsgindc 'prefix)))
+ (erc-message "PRIVMSG" (concat target " " line) force)
+ (push (cons 'erc--msg (car args)) erc--msg-prop-overrides)
+ (apply #'erc-display-message nil nil (current-buffer) args))
;; FIXME - treat multiline, run hooks, or remove me?
+ ;; FIXME explain this ^ in more detail or remove.
+ t)
+
+(defun erc--send-message-nested (input-line force)
+ "Process string INPUT-LINE almost as if it's normal chat input.
+Expect INPUT-LINE to differ from the `string' slot of the calling
+context's `erc--current-line-input-split' object because the
+latter is likely a slash command invocation whose handler
+generated INPUT-LINE. Before inserting INPUT-LINE, split it and
+run `erc-send-modify-hook' and `erc-send-post-hook' on each
+actual outgoing line. Forgo input validation because this isn't
+interactive input, and skip `erc-send-completed-hook' because it
+will run just before the outer `erc-send-current-line' call
+returns."
+ (let* ((erc-flood-protect (not force))
+ (lines-obj (erc--make-input-split input-line)))
+ (setf (erc--input-split-refoldp lines-obj) t
+ (erc--input-split-cmdp lines-obj) nil)
+ (erc--send-input-lines (erc--run-send-hooks lines-obj)))
t)
+;; FIXME if the user types /MODE<RET>, LINE becomes "\n", which
+;; matches the pattern, so "\n" is sent to the server. Perhaps
+;; instead of `do-not-parse-args', this should just join &rest
+;; arguments.
(defun erc-cmd-MODE (line)
"Change or display the mode value of a channel or user.
The first word specifies the target. The rest is the mode string
@@ -4189,7 +4822,7 @@ A list of valid mode strings for Libera.Chat may be found at
((string-match "^\\s-\\(.*\\)$" line)
(let ((s (match-string 1 line)))
(erc-log (format "cmd: MODE: %s" s))
- (erc-server-send (concat "MODE " line)))
+ (erc-server-send (concat "MODE " s)))
t)
(t nil)))
(put 'erc-cmd-MODE 'do-not-parse-args t)
@@ -4214,6 +4847,7 @@ The rest of LINE is the message to send."
The rest of LINE is the message to send."
(erc-message "SQUERY" line))
+(put 'erc-cmd-SQUERY 'do-not-parse-args t)
(defun erc-cmd-NICK (nick)
"Change current nickname to NICK."
@@ -4256,7 +4890,7 @@ Otherwise leave the channel indicated by LINE."
(format "PART %s" ch)
(format "PART %s :%s" ch reason))
nil ch))
- (erc-display-message nil 'error (current-buffer) 'no-target)))
+ (erc-display-message nil '(notice error) (current-buffer) 'no-target)))
t)
(t nil)))
(put 'erc-cmd-PART 'do-not-parse-args t)
@@ -4404,10 +5038,7 @@ the message given by REASON."
;; kill them
(run-at-time
4 nil
- (lambda ()
- (dolist (buffer (erc-buffer-list (lambda (buf)
- (not (erc-server-buffer-p buf)))))
- (kill-buffer buffer)))))
+ #'erc-buffer-do (lambda () (when erc--target (kill-buffer)))))
t)
(defalias 'erc-cmd-GQ #'erc-cmd-GQUIT)
@@ -4453,6 +5084,8 @@ connection or, with -A, all applicable connections.
(put 'erc-cmd-RECONNECT 'process-not-needed t)
+;; FIXME use less speculative error message or lose `condition-case',
+;; since most connection failures don't signal anything.
(defun erc-cmd-SERVER (server)
"Connect to SERVER, leaving existing connection intact."
(erc-log (format "cmd: SERVER: %s" server))
@@ -4471,9 +5104,11 @@ connection or, with -A, all applicable connections.
system-configuration
(concat
(cond ((featurep 'motif)
+ (defvar motif-version-string)
(concat ", " (substring
motif-version-string 4)))
((featurep 'gtk)
+ (defvar gtk-version-string)
(concat ", GTK+ Version "
gtk-version-string))
((featurep 'x-toolkit) ", X toolkit")
@@ -4599,7 +5234,7 @@ be displayed."
(progn
(erc-log (format "cmd: TOPIC [%s]: %s" ch topic))
(erc-server-send (format "TOPIC %s :%s" ch topic) nil ch))
- (erc-display-message nil 'error (current-buffer) 'no-target)))
+ (erc-display-message nil '(notice error) (current-buffer) 'no-target)))
t)
(t nil)))
(defalias 'erc-cmd-T #'erc-cmd-TOPIC)
@@ -4649,8 +5284,7 @@ The ban list is fetched from the server if necessary."
(cond
((not (erc-channel-p chnl))
- (erc-display-line (erc-make-notice "You're not on a channel\n")
- 'active))
+ (erc-display-message nil 'notice 'active "You're not on a channel\n"))
((not (get 'erc-channel-banlist 'received-from-server))
(let ((old-367-hook erc-server-367-functions))
@@ -4669,9 +5303,8 @@ The ban list is fetched from the server if necessary."
(erc-server-send (format "MODE %s b" chnl)))))
((null erc-channel-banlist)
- (erc-display-line (erc-make-notice
- (format "No bans for channel: %s\n" chnl))
- 'active)
+ (erc-display-message nil 'notice 'active
+ (format "No bans for channel: %s\n" chnl))
(put 'erc-channel-banlist 'received-from-server nil))
(t
@@ -4685,10 +5318,9 @@ The ban list is fetched from the server if necessary."
"%-" (number-to-string (/ erc-fill-column 2)) "s"
"%" (number-to-string (/ erc-fill-column 2)) "s")))
- (erc-display-line
- (erc-make-notice (format "Ban list for channel: %s\n"
- (erc-default-target)))
- 'active)
+ (erc-display-message
+ nil 'notice 'active
+ (format "Ban list for channel: %s\n" (erc-default-target)))
(erc-display-line separator 'active)
(erc-display-line (format fmt "Ban Mask" "Banned By") 'active)
@@ -4705,8 +5337,7 @@ The ban list is fetched from the server if necessary."
'active))
erc-channel-banlist)
- (erc-display-line (erc-make-notice "End of Ban list")
- 'active)
+ (erc-display-message nil 'notice 'active "End of Ban list")
(put 'erc-channel-banlist 'received-from-server nil)))))
t)
@@ -4720,9 +5351,7 @@ Unban all currently banned users in the current channel."
(cond
((not (erc-channel-p chnl))
- (erc-display-line
- (erc-make-notice "You're not on a channel\n")
- 'active))
+ (erc-display-message nil 'notice 'active "You're not on a channel\n"))
((not (get 'erc-channel-banlist 'received-from-server))
(let ((old-367-hook erc-server-367-functions))
@@ -4764,7 +5393,9 @@ Eventually add a # in front of it, if that turns it into a valid channel name."
(concat "#" channel)))
(defvar erc--own-property-names
- '( tags erc-speaker erc-parsed display ; core
+ `( tags erc--speaker erc-parsed display ; core
+ ;; `erc--msg-props'
+ ,@erc--ranked-properties
;; `erc-display-prompt'
rear-nonsticky erc-prompt field front-sticky read-only
;; stamp
@@ -4835,12 +5466,7 @@ If FACE is non-nil, it will be used to propertize the prompt. If it is nil,
;; Do not extend the text properties when typing at the end
;; of the prompt, but stuff typed in front of the prompt
;; shall remain part of the prompt.
- (setq prompt (propertize prompt
- 'rear-nonsticky t
- 'erc-prompt t ; t or `hidden'
- 'field 'erc-prompt
- 'front-sticky t
- 'read-only t))
+ (setq prompt (apply #'propertize prompt erc--prompt-properties))
(erc-put-text-property 0 (1- (length prompt))
'font-lock-face (or face 'erc-prompt-face)
prompt)
@@ -5117,7 +5743,9 @@ manner implied above, which was lost sometime before ERC 5.4."
:package-version '(ERC . "5.6") ; revived
:group 'erc-buffers
:group 'erc-query
- :type 'boolean)
+ :type '(choice boolean
+ (choice :tag "Create pseudo queries for STATUSMSGs"
+ status)))
(defcustom erc-format-query-as-channel-p t
"If non-nil, format text from others in a query buffer like in a channel.
@@ -5251,24 +5879,23 @@ and as second argument the event parsed as a vector."
(and (erc-is-message-ctcp-p message)
(not (string-match "^\C-aACTION.*\C-a$" message))))
-(define-inline erc--get-speaker-bounds ()
- "Return the bounds of `erc-speaker' property when present.
+(defun erc--get-speaker-bounds ()
+ "Return the bounds of `erc--speaker' text property when present.
Assume buffer is narrowed to the confines of an inserted message."
- (inline-quote
- (and-let*
- (((memq (get-text-property (point) 'erc-command) '(PRIVMSG NOTICE)))
- (beg (or (and (get-text-property (point-min) 'erc-speaker) (point-min))
- (next-single-property-change (point-min) 'erc-speaker))))
- (cons beg (next-single-property-change beg 'erc-speaker)))))
-
-(defvar erc--user-from-nick-function #'erc--examine-nick
- "Function to possibly consider unknown user.
-Must return either nil or a cons of an `erc-server-user' and a
-possibly nil `erc-channel-user' for formatting a server user's
-nick. Called in the appropriate buffer with the downcased nick,
-the parsed NUH, and the original `erc-response' object.")
-
-(defun erc--examine-nick (downcased _nuh _parsed)
+ (and-let* (((erc--check-msg-prop 'erc--spkr))
+ (beg (text-property-not-all (point-min) (point-max)
+ 'erc--speaker nil)))
+ (cons beg (next-single-property-change beg 'erc--speaker))))
+
+(defvar erc--cmem-from-nick-function #'erc--cmem-get-existing
+ "Function maybe returning a \"channel member\" cons from a nick.
+Must return either nil or a cons of an `erc-server-user' and an
+`erc-channel-user' (see `erc-channel-users') for use in
+formatting a user's nick prior to insertion. Called in the
+appropriate target buffer with the downcased nick, the parsed
+NUH, and the current `erc-response' object.")
+
+(defun erc--cmem-get-existing (downcased _nuh _parsed)
(and erc-channel-users (gethash downcased erc-channel-users)))
(defun erc-format-privmessage (nick msg privp msgp)
@@ -5283,53 +5910,289 @@ the parsed NUH, and the original `erc-response' object.")
nick-prefix-face nick))
0))
(msg-face (if privp 'erc-direct-msg-face 'erc-default-face)))
+ (erc--ensure-spkr-prop nick)
;; add text properties to text before the nick, the nick and after the nick
(erc-put-text-property 0 (length mark-s) 'font-lock-face msg-face str)
(erc-put-text-properties (+ (length mark-s) prefix-len)
(+ (length mark-s) (length nick))
- '(font-lock-face erc-speaker) str
+ '(font-lock-face erc--speaker) str
(list nick-face
(substring-no-properties nick prefix-len)))
(erc-put-text-property (+ (length mark-s) (length nick)) (length str)
'font-lock-face msg-face str)
str))
-(defcustom erc-format-nick-function 'erc-format-nick
- "Function to format a nickname for message display."
+;; The format strings in the following `-speaker' catalog shouldn't
+;; contain any non-protocol words, so they make sense in any language.
+
+(defvar erc--message-speaker-statusmsg
+ #("(%p%n%s) %m"
+ 0 1 (font-lock-face erc-default-face)
+ 1 3 (font-lock-face erc-nick-prefix-face)
+ 3 5 (font-lock-face erc-nick-default-face)
+ 5 7 (font-lock-face erc-notice-face)
+ 7 11 (font-lock-face erc-default-face))
+ "Message template for in-channel status messages.")
+
+(defvar erc--message-speaker-statusmsg-input
+ #("(%p%n%s) %m"
+ 0 1 (font-lock-face erc-default-face)
+ 1 3 (font-lock-face erc-my-nick-prefix-face)
+ 3 5 (font-lock-face erc-my-nick-face)
+ 5 7 (font-lock-face erc-notice-face)
+ 7 8 (font-lock-face erc-default-face)
+ 8 11 (font-lock-face erc-input-face))
+ "Message template for echoed status messages.")
+
+(defvar erc--message-speaker-input-chan-privmsg
+ #("<%p%n> %m"
+ 0 1 (font-lock-face erc-default-face)
+ 1 3 (font-lock-face erc-my-nick-prefix-face)
+ 3 5 (font-lock-face erc-my-nick-face)
+ 5 7 (font-lock-face erc-default-face)
+ 7 9 (font-lock-face erc-input-face))
+ "Message template for prompt input or echoed PRIVMSG from own nick.")
+
+(defvar erc--message-speaker-input-query-privmsg
+ #("*%n* %m"
+ 0 1 (font-lock-face erc-direct-msg-face)
+ 1 3 (font-lock-face erc-my-nick-face)
+ 3 5 (font-lock-face erc-direct-msg-face)
+ 5 7 (font-lock-face erc-input-face))
+ "Message template for prompt input or echoed PRIVMSG query from own nick.")
+
+(defvar erc--message-speaker-input-query-notice
+ #("-%n- %m"
+ 0 1 (font-lock-face erc-direct-msg-face)
+ 1 3 (font-lock-face erc-my-nick-face)
+ 3 5 (font-lock-face erc-direct-msg-face)
+ 5 7 (font-lock-face erc-input-face))
+ "Message template for echoed or spoofed query NOTICE from own nick.")
+
+(defvar erc--message-speaker-input-chan-notice
+ #("-%p%n- %m"
+ 0 1 (font-lock-face erc-default-face)
+ 1 3 (font-lock-face erc-my-nick-prefix-face)
+ 3 5 (font-lock-face erc-my-nick-face)
+ 5 7 (font-lock-face erc-default-face)
+ 7 9 (font-lock-face erc-input-face))
+ "Message template for prompt input or echoed NOTICE from own nick.")
+
+(defvar erc--message-speaker-chan-privmsg
+ #("<%p%n> %m"
+ 0 1 (font-lock-face erc-default-face)
+ 1 3 (font-lock-face erc-nick-prefix-face)
+ 3 5 (font-lock-face erc-nick-default-face)
+ 5 9 (font-lock-face erc-default-face))
+ "Message template for a PRIVMSG in a channel.")
+
+(defvar erc--message-speaker-query-privmsg
+ #("*%n* %m"
+ 0 1 (font-lock-face erc-direct-msg-face)
+ 1 3 (font-lock-face erc-nick-msg-face)
+ 3 7 (font-lock-face erc-direct-msg-face))
+ "Message template for a PRIVMSG in query buffer.")
+
+(defvar erc--message-speaker-chan-notice
+ #("-%p%n- %m"
+ 0 1 (font-lock-face erc-default-face)
+ 1 3 (font-lock-face erc-nick-prefix-face)
+ 3 5 (font-lock-face erc-nick-default-face)
+ 5 9 (font-lock-face erc-default-face))
+ "Message template for a NOTICE in a channel.")
+
+(defvar erc--message-speaker-query-notice
+ #("-%n- %m"
+ 0 1 (font-lock-face erc-direct-msg-face)
+ 1 3 (font-lock-face erc-nick-msg-face)
+ 3 7 (font-lock-face erc-direct-msg-face))
+ "Message template for a NOTICE in a query buffer.")
+
+(defvar erc--message-speaker-ctcp-action
+ #("* %p%n %m"
+ 0 2 (font-lock-face erc-action-face)
+ 2 4 (font-lock-face (erc-nick-prefix-face erc-action-face))
+ 4 9 (font-lock-face erc-action-face))
+ "Message template for a CTCP ACTION from another user.")
+
+(defvar erc--message-speaker-ctcp-action-input
+ #("* %p%n %m"
+ 0 2 (font-lock-face #1=(erc-input-face erc-action-face))
+ 2 4 (font-lock-face (erc-my-nick-prefix-face . #1#))
+ 4 6 (font-lock-face (erc-my-nick-face . #1#))
+ 6 9 (font-lock-face #1#))
+ "Message template for a CTCP ACTION from current client.")
+
+(defvar erc--message-speaker-ctcp-action-statusmsg
+ #("* (%p%n%s) %m"
+ 0 3 (font-lock-face erc-action-face)
+ 3 5 (font-lock-face (erc-nick-prefix-face erc-action-face))
+ 5 7 (font-lock-face erc-action-face)
+ 7 9 (font-lock-face (erc-notice-face erc-action-face))
+ 9 13 (font-lock-face erc-action-face))
+ "Template for a CTCP ACTION status message from another chan op.")
+
+(defvar erc--message-speaker-ctcp-action-statusmsg-input
+ #("* (%p%n%s) %m"
+ 0 3 (font-lock-face #1=(erc-input-face erc-action-face))
+ 3 5 (font-lock-face (erc-my-nick-prefix-face . #1#))
+ 5 7 (font-lock-face (erc-my-nick-face . #1#))
+ 7 9 (font-lock-face (erc-notice-face . #1#))
+ 9 13 (font-lock-face #1#))
+ "Template for a CTCP ACTION status message from current client.")
+
+(defun erc--speakerize-nick (nick &optional disp)
+ "Propertize NICK with `erc--speaker' if not already present.
+Do so to DISP instead if it's non-nil. In either case, assign
+NICK, sans properties, as the `erc--speaker' value. As a side
+effect, pair the latter string (the same `eq'-able object) with
+the symbol `erc--spkr' in the \"msg prop\" environment for any
+imminent `erc-display-message' invocations. While doing so,
+include any overrides defined in `erc--message-speaker-catalog'."
+ (let ((plain-nick (substring-no-properties nick)))
+ (erc--ensure-spkr-prop plain-nick (get erc--message-speaker-catalog
+ 'erc--msg-prop-overrides))
+ (if (text-property-not-all 0 (length (or disp nick))
+ 'erc--speaker nil (or disp nick))
+ (or disp nick)
+ (propertize (or disp nick) 'erc--speaker plain-nick))))
+
+(defun erc--determine-speaker-message-format-args
+ (nick message queryp privmsgp inputp &optional statusmsg prefix disp-nick)
+ "Return a list consisting of a \"speaker\"-template key and spec args.
+Consider the three flags QUERYP, PRIVMSGP, and INPUTP, as well as
+the possibly null STATUSMSG string. (Combined, these describe
+the context of a newly arrived \"PRIVMSG\" or, when PRIVMSGP is
+nil, a \"NOTICE\"). Interpret QUERYP to mean that MESSAGE is
+directed at the ERC client itself (a direct message), and INPUTP
+to mean MESSAGE is an outgoing or echoed message originating from
+or meant to simulate prompt input. Interpret a non-nil STATUSMSG
+to mean MESSAGE should be formatted as a special channel message
+intended for privileged members of the same or greater status.
+
+After deciding on the template key for the current \"speaker\"
+catalog, use the remaining arguments, possibly along with
+STATUSMSG, to construct the appropriate spec-args plist forming
+the returned list's tail. In this plist, pair the char ?n with
+NICK, the nickname of the speaker and ?m with MESSAGE, the
+message body. When non-nil, assume DISP-NICK to be a possibly
+phony display name to take the place of NICK for ?n. When PREFIX
+is non-nil, look up NICK's channel-membership status, possibly
+using PREFIX itself if it's an `erc-channel-user' object, which
+it must be when called outside of a channel buffer. Pair the
+result with the ?p specifier. When STATUSMSG is non-nil, pair it
+with the ?s specifier. Ensure unused spec values are the empty
+string rather than nil."
+ (when prefix
+ (setq prefix (erc-get-channel-membership-prefix
+ (if (erc-channel-user-p prefix) prefix nick))))
+ (when (and queryp erc--target erc-format-query-as-channel-p
+ (not (erc--target-channel-p erc--target)))
+ (setq queryp nil))
+ (list (cond (statusmsg (if inputp 'statusmsg-input 'statusmsg))
+ (privmsgp (if queryp
+ (if inputp 'input-query-privmsg 'query-privmsg)
+ (if inputp 'input-chan-privmsg 'chan-privmsg)))
+ (t (if queryp
+ (if inputp 'input-query-notice 'query-notice)
+ (if inputp 'input-chan-notice 'chan-notice))))
+ ?p (or prefix "") ?n (erc--speakerize-nick nick disp-nick)
+ ?s (or statusmsg "") ?m message))
+
+(defcustom erc-show-speaker-membership-status nil
+ "Whether to prefix speakers with their channel status.
+For example, when this option is non-nil and some nick \"Alice\"
+has operator status in the current channel, ERC displays their
+leading \"speaker\" label as <@Alice> instead of <Alice>."
+ :package-version '(ERC . "5.6")
:group 'erc-display
- :type 'function)
+ :type 'boolean)
-(defun erc-format-nick (&optional user _channel-data)
- "Return the nickname of USER.
-See also `erc-format-nick-function'."
- (when user (erc-server-user-nickname user)))
+(define-obsolete-variable-alias 'erc-format-nick-function
+ 'erc-speaker-from-channel-member-function "30.1")
+(defcustom erc-speaker-from-channel-member-function
+ #'erc-determine-speaker-from-user
+ "Function to determine a message's displayed \"speaker\" label.
+Called with an `erc-server-user' object and an `erc-channel-user'
+object, both possibly nil. Use this option to do things like
+provide localized display names. To ask ERC to prepend
+channel-membership \"status\" prefixes, like \"@\", to the
+returned name, see `erc-show-speaker-membership-status'."
+ :package-version '(ERC . "5.6")
+ :group 'erc-display
+ :type '(choice (function-item erc-determine-speaker-from-user) function))
-(defun erc-get-user-mode-prefix (user)
- (when user
- (cond ((erc-channel-user-owner-p user)
- (propertize "~" 'help-echo "owner"))
- ((erc-channel-user-admin-p user)
- (propertize "&" 'help-echo "admin"))
- ((erc-channel-user-op-p user)
- (propertize "@" 'help-echo "operator"))
- ((erc-channel-user-halfop-p user)
- (propertize "%" 'help-echo "half-op"))
- ((erc-channel-user-voice-p user)
- (propertize "+" 'help-echo "voice"))
- (t ""))))
+(define-obsolete-function-alias 'erc-format-nick
+ #'erc-determine-speaker-from-user "30.1")
+(defun erc-determine-speaker-from-user (&optional user _channel-data)
+ "Return nickname slot of `erc-server-user' USER, when non-nil."
+ (when user (erc-server-user-nickname user)))
-(defun erc-format-@nick (&optional user _channel-data)
+(define-obsolete-function-alias 'erc-get-user-mode-prefix
+ #'erc-get-channel-membership-prefix "30.1")
+(defun erc-get-channel-membership-prefix (nick-or-cusr)
+ "Return channel membership prefix for NICK-OR-CUSR as a string.
+Ensure returned string has a `help-echo' text property with the
+corresponding verbose membership type, like \"voice\", as its
+value. Expect NICK-OR-CUSR to be an `erc-channel-user' object or
+a string nickname, not necessarily downcased. When called in a
+logically connected ERC buffer, use advertised prefix mappings.
+For compatibility reasons, don't error when NICK-OR-CUSR is null,
+but return nil instead of the empty string. Otherwise, always
+return a possibly empty string."
+ (when nick-or-cusr
+ (when (stringp nick-or-cusr)
+ (setq nick-or-cusr (and erc-channel-members
+ (cdr (erc-get-channel-member nick-or-cusr)))))
+ (cond
+ ((null nick-or-cusr) "")
+ ;; Special-case most common value.
+ ((zerop (erc-channel-user-status nick-or-cusr)) "")
+ ;; For compatibility, first check whether a parsed prefix exists.
+ ((and-let* ((pfx-obj (erc--parsed-prefix)))
+ (catch 'done
+ (pcase-dolist (`(,letter . ,pfx)
+ (erc--parsed-prefix-alist pfx-obj))
+ (pcase letter
+ ((and ?q (guard (erc-channel-user-owner nick-or-cusr)))
+ (throw 'done (propertize (string pfx) 'help-echo "owner")))
+ ((and ?a (guard (erc-channel-user-admin nick-or-cusr)))
+ (throw 'done (propertize (string pfx) 'help-echo "admin")))
+ ((and ?o (guard (erc-channel-user-op nick-or-cusr)))
+ (throw 'done (propertize (string pfx) 'help-echo "operator")))
+ ((and ?h (guard (erc-channel-user-halfop nick-or-cusr)))
+ (throw 'done (propertize (string pfx) 'help-echo "half-op")))
+ ((and ?v (guard (erc-channel-user-voice nick-or-cusr)))
+ (throw 'done (propertize (string pfx) 'help-echo "voice")))))
+ "")))
+ (t
+ (cond ((erc-channel-user-owner nick-or-cusr)
+ (propertize "~" 'help-echo "owner"))
+ ((erc-channel-user-admin nick-or-cusr)
+ (propertize "&" 'help-echo "admin"))
+ ((erc-channel-user-op nick-or-cusr)
+ (propertize "@" 'help-echo "operator"))
+ ((erc-channel-user-halfop nick-or-cusr)
+ (propertize "%" 'help-echo "half-op"))
+ ((erc-channel-user-voice nick-or-cusr)
+ (propertize "+" 'help-echo "voice"))
+ (t ""))))))
+
+(defun erc-format-@nick (&optional user channel-data)
"Format the nickname of USER showing if USER has a voice, is an
operator, half-op, admin or owner. Owners have \"~\", admins have
\"&\", operators have \"@\" and users with voice have \"+\" as a
-prefix. Use CHANNEL-DATA to determine op and voice status. See
-also `erc-format-nick-function'."
+prefix. Use CHANNEL-DATA to determine op and voice status."
+ (declare (obsolete "see option `erc-show-speaker-membership-status'" "30.1"))
(when user
(let ((nick (erc-server-user-nickname user)))
- (concat (propertize
- (erc-get-user-mode-prefix nick)
- 'font-lock-face 'erc-nick-prefix-face)
- nick))))
+ (if (not erc--speaker-status-prefix-wanted-p)
+ (prog1 nick
+ (setq erc--speaker-status-prefix-wanted-p 'erc-format-@nick))
+ (concat (propertize
+ (erc-get-channel-membership-prefix channel-data)
+ 'font-lock-face 'erc-nick-prefix-face)
+ nick)))))
(defun erc-format-my-nick ()
"Return the beginning of this user's message, correctly propertized."
@@ -5337,15 +6200,42 @@ also `erc-format-nick-function'."
(let* ((open "<")
(close "> ")
(nick (erc-current-nick))
- (mode (erc-get-user-mode-prefix nick)))
+ (mode (erc-get-channel-membership-prefix nick)))
+ (erc--ensure-spkr-prop nick)
(concat
(propertize open 'font-lock-face 'erc-default-face)
(propertize mode 'font-lock-face 'erc-my-nick-prefix-face)
- (propertize nick 'font-lock-face 'erc-my-nick-face 'erc-speaker nick)
+ (propertize nick 'erc--speaker nick 'font-lock-face 'erc-my-nick-face)
(propertize close 'font-lock-face 'erc-default-face)))
(let ((prefix "> "))
(propertize prefix 'font-lock-face 'erc-default-face))))
+(defun erc--format-speaker-input-message (message)
+ "Assemble outgoing MESSAGE entered at the prompt for insertion.
+Intend \"input\" to refer to interactive prompt input as well as
+the group of associated message-format templates from the
+\"speaker\" catalog. Format the speaker portion in a manner
+similar to that performed by `erc-format-my-nick', but use either
+`erc--message-speaker-input-chan-privmsg' or
+`erc--message-speaker-input-query-privmsg' as a formatting
+template, with MESSAGE being the actual message body. Return a
+copy with possibly shared text-property values."
+ (if-let ((erc-show-my-nick)
+ (nick (erc-current-nick))
+ (pfx (erc-get-channel-membership-prefix nick))
+ (erc-current-message-catalog erc--message-speaker-catalog)
+ (key (if (or erc-format-query-as-channel-p
+ (erc--target-channel-p erc--target))
+ 'input-chan-privmsg
+ 'input-query-privmsg)))
+ (progn
+ (cond (erc--msg-props (puthash 'erc--msg key erc--msg-props))
+ (erc--msg-prop-overrides (push (cons 'erc--msg key)
+ erc--msg-prop-overrides)))
+ (erc-format-message key ?p pfx ?n (erc--speakerize-nick nick)
+ ?m message))
+ (propertize (concat "> " message) 'font-lock-face 'erc-input-face)))
+
(defun erc-echo-notice-in-default-buffer (s parsed buffer _sender)
"Echo a private notice in the default buffer, namely the
target buffer specified by BUFFER, or there is no target buffer,
@@ -5516,9 +6406,7 @@ See also: `erc-echo-notice-in-user-buffers',
(erc-load-script f)))))
(defun erc-connection-established (proc parsed)
- "Run just after connection.
-
-Set user modes and run `erc-after-connect' hook."
+ "Set user mode and run `erc-after-connect' hook in server buffer."
(with-current-buffer (process-buffer proc)
(unless erc-server-connected ; only once per session
(let ((server (or erc-server-announced-name
@@ -5537,23 +6425,30 @@ Set user modes and run `erc-after-connect' hook."
(erc-update-mode-line)
(erc-set-initial-user-mode nick buffer)
(erc-server-setup-periodical-ping buffer)
- (run-hook-with-args 'erc-after-connect server nick))))
-
- (when erc-unhide-query-prompt
- (erc-with-all-buffers-of-server proc
- nil ; FIXME use `erc--target' after bug#48598
- (when (and (erc-default-target)
- (not (erc-channel-p (car erc-default-recipients))))
- (erc--unhide-prompt)))))
+ (when erc-unhide-query-prompt
+ (erc-with-all-buffers-of-server erc-server-process nil
+ (when (and erc--target (not (erc--target-channel-p erc--target)))
+ (erc--unhide-prompt))))
+ (run-hook-with-args 'erc-after-connect server nick)))))
(defun erc-set-initial-user-mode (nick buffer)
"If `erc-user-mode' is non-nil for NICK, set the user modes.
The server buffer is given by BUFFER."
(with-current-buffer buffer
(when erc-user-mode
- (let ((mode (if (functionp erc-user-mode)
- (funcall erc-user-mode)
- erc-user-mode)))
+ (let* ((mode (if (functionp erc-user-mode)
+ (funcall erc-user-mode)
+ erc-user-mode))
+ (groups (erc--parse-user-modes mode (erc--user-modes) t))
+ (superfluous (last groups 2))
+ (redundant-want (car superfluous))
+ (redundant-drop (cadr superfluous)))
+ (when redundant-want
+ (erc-display-message nil 'notice buffer 'user-mode-redundant-add
+ ?m (apply #'string redundant-want)))
+ (when redundant-drop
+ (erc-display-message nil 'notice buffer 'user-mode-redundant-drop
+ ?m (apply #'string redundant-drop)))
(when (stringp mode)
(erc-log (format "changing mode for %s to %s" nick mode))
(erc-server-send (format "MODE %s %s" nick mode)))))))
@@ -5580,11 +6475,8 @@ See also `erc-display-message'."
(while queries
(let* ((type (upcase (car (split-string (car queries)))))
(hook (intern-soft (concat "erc-ctcp-query-" type "-hook")))
- (erc-insert-pre-hook
- (cons (lambda (s)
- (put-text-property 0 (1- (length s)) 'erc-ctcp
- (intern type) s))
- erc-insert-pre-hook)))
+ (erc--msg-prop-overrides `((erc--ctcp . ,(intern type))
+ ,@erc--msg-prop-overrides)))
(if (and hook (boundp hook))
(if (string-equal type "ACTION")
(run-hook-with-args-until-success
@@ -5618,11 +6510,31 @@ See also `erc-display-message'."
(let ((s (match-string 1 msg))
(buf (or (erc-get-buffer to proc)
(erc-get-buffer nick proc)
- (process-buffer proc))))
- (setq nick (propertize nick 'erc-speaker nick))
- (erc-display-message
- parsed 'action buf
- 'ACTION ?n nick ?u login ?h host ?a s))))
+ (process-buffer proc)))
+ (selfp (erc-current-nick-p nick)))
+ (if erc--use-language-catalog-for-ctcp-action-p
+ (progn
+ (erc--ensure-spkr-prop nick)
+ (setq nick (propertize nick 'erc--speaker nick))
+ (erc-display-message parsed (if selfp 'input 'action) buf
+ 'ACTION ?n nick ?u login ?h host ?a s))
+ (let* ((obj (and (erc--ctcp-response-p parsed) parsed))
+ (buffer (and obj (erc--ctcp-response-buffer obj)))
+ (stsmsg (and obj (erc--ctcp-response-statusmsg obj)))
+ (prefix (and obj (erc--ctcp-response-prefix obj)))
+ (dispnm (and obj (erc--ctcp-response-dispname obj)))
+ (erc-current-message-catalog erc--message-speaker-catalog))
+ (erc-display-message
+ parsed nil (or buffer buf)
+ (if selfp
+ (if stsmsg 'ctcp-action-statusmsg-input 'ctcp-action-input)
+ (if stsmsg 'ctcp-action-statusmsg 'ctcp-action))
+ ?s (or stsmsg to)
+ ?p (or (and (erc-channel-user-p prefix)
+ (erc-get-channel-membership-prefix prefix))
+ "")
+ ?n (erc--speakerize-nick nick dispnm)
+ ?m s))))))
(defvar erc-ctcp-query-CLIENTINFO-hook '(erc-ctcp-query-CLIENTINFO))
@@ -5696,8 +6608,14 @@ See also `erc-display-message'."
(defun erc-process-ctcp-reply (proc parsed nick login host msg)
"Process MSG as a CTCP reply."
(let* ((type (car (split-string msg)))
- (hook (intern (concat "erc-ctcp-reply-" type "-hook"))))
- (if (boundp hook)
+ (hook (intern-soft (concat "erc-ctcp-reply-" type "-hook")))
+ ;; Help `erc-display-message' by ensuring subsequent
+ ;; insertions retain the necessary props.
+ (cmd (erc--get-eq-comparable-cmd (erc-response.command parsed)))
+ (erc--msg-prop-overrides `((erc--ctcp . ,(and hook (intern type)))
+ (erc--cmd . ,cmd)
+ ,@erc--msg-prop-overrides)))
+ (if (and hook (boundp hook))
(run-hook-with-args-until-success
hook proc nick login host
(car (erc-response.command-args parsed)) msg)
@@ -5831,22 +6749,38 @@ See also `erc-channel-begin-receiving-names'."
(defun erc-parse-prefix ()
"Return an alist of valid prefix character types and their representations.
-Example: (operator) o => @, (voiced) v => +."
- (let ((str (or (erc-with-server-buffer (erc--get-isupport-entry 'PREFIX t))
- ;; provide a sane default
- "(qaohv)~&@%+"))
- types chars)
- (when (string-match "^(\\([^)]+\\))\\(.+\\)$" str)
- (setq types (match-string 1 str)
- chars (match-string 2 str))
- (let ((len (min (length types) (length chars)))
- (i 0)
- (alist nil))
- (while (< i len)
- (setq alist (cons (cons (elt types i) (elt chars i))
- alist))
- (setq i (1+ i)))
- alist))))
+For example, if the current ISUPPORT \"PREFIX\" is \"(ov)@+\",
+return an alist `equal' to ((?v . ?+) (?o . ?@)). For historical
+reasons, ensure the ordering of the returned alist is opposite
+that of the advertised parameter."
+ (let* ((str (or (erc--get-isupport-entry 'PREFIX t) "(qaohv)~&@%+"))
+ (i 0)
+ (j (string-search ")" str))
+ collected)
+ (when j
+ (while-let ((u (aref str (cl-incf i)))
+ ((not (= ?\) u))))
+ (push (cons u (aref str (cl-incf j))) collected)))
+ collected))
+
+(defvar-local erc--parsed-prefix nil
+ "Possibly stale `erc--parsed-prefix' struct instance for the server.
+Use the \"getter\" function of the same name to obtain the current
+value.")
+
+(defun erc--parsed-prefix ()
+ "Return possibly cached `erc--parsed-prefix' object for the server.
+Ensure the returned value describes the most recent \"PREFIX\"
+parameter advertised by the current server, with the original
+ordering intact. If no such parameter has yet arrived, return a
+stand-in from the fallback value \"(qaohv)~&@%+\"."
+ (erc--with-isupport-data PREFIX erc--parsed-prefix
+ (let ((alist (nreverse (erc-parse-prefix))))
+ (make-erc--parsed-prefix
+ :key key
+ :letters (apply #'string (map-keys alist))
+ :statuses (apply #'string (map-values alist))
+ :alist alist))))
(defcustom erc-channel-members-changed-hook nil
"This hook is called every time the variable `channel-members' changes.
@@ -5860,7 +6794,7 @@ The buffer where the change happened is current while this hook is called."
Update `erc-channel-users' according to NAMES-STRING.
NAMES-STRING is a string listing some of the names on the
channel."
- (let* ((prefix (erc-parse-prefix))
+ (let* ((prefix (erc--parsed-prefix-alist (erc--parsed-prefix)))
(voice-ch (cdr (assq ?v prefix)))
(op-ch (cdr (assq ?o prefix)))
(hop-ch (cdr (assq ?h prefix)))
@@ -5948,73 +6882,52 @@ which USER is a member, and t is returned."
changed))
(defun erc-update-current-channel-member
- (nick new-nick &optional add voice halfop op admin owner host login full-name info
+ (nick new-nick &optional addp voice halfop op admin owner host login full-name info
update-message-time)
- "Update the stored user information for the user with nickname NICK.
-`erc-update-user' is called to handle changes to nickname,
-HOST, LOGIN, FULL-NAME, and INFO. If VOICE HALFOP OP ADMIN or OWNER
-are non-nil, they must be equal to either `on' or `off', in which
-case the status of the user in the current channel is changed accordingly.
-If UPDATE-MESSAGE-TIME is non-nil, the last-message-time of the user
- in the current channel is set to (current-time).
-
-If ADD is non-nil, the user will be added with the specified
-information if it is not already present in the user or channel
-lists.
-
-If, and only if, changes are made, or the user is added,
-`erc-channel-members-changed-hook' is run, and t is returned.
-
-See also: `erc-update-user' and `erc-update-channel-member'."
- (let* (changed user-changed
- (channel-data (erc-get-channel-user nick))
- (cuser (cdr channel-data))
- (user (if channel-data (car channel-data)
- (erc-get-server-user nick))))
- (if cuser
+ "Update or create entry for NICK in current `erc-channel-members' table.
+With ADDP, ensure an entry exists. If one already does, call
+`erc-update-user' to handle updates to HOST, LOGIN, FULL-NAME,
+INFO, and NEW-NICK. Expect any non-nil membership 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,
+including creation, run `erc-channel-members-changed-hook'.
+Return non-nil when meaningful changes, including creation, have
+occurred.
+
+Without ADDP, do nothing unless a `erc-channel-members' entry
+exists. When it doesn't, assume the sender is a non-joined
+entity, like the server itself or a historical speaker, or assume
+the prior buffer for the channel was killed without parting."
+ (let* (cusr-changed-p
+ user-changed-p
+ (cmem (erc-get-channel-member nick))
+ (cusr (cdr cmem))
+ (down (erc-downcase nick))
+ (user (or (car cmem)
+ (gethash down (erc-with-server-buffer erc-server-users)))))
+ (if cusr
(progn
- (erc-log (format "update-member: user = %S, cuser = %S" user cuser))
- (when (and voice
- (not (eq (erc-channel-user-voice cuser) voice)))
- (setq changed t)
- (setf (erc-channel-user-voice cuser)
- (cond ((eq voice 'on) t)
- ((eq voice 'off) nil)
- (t voice))))
- (when (and halfop
- (not (eq (erc-channel-user-halfop cuser) halfop)))
- (setq changed t)
- (setf (erc-channel-user-halfop cuser)
- (cond ((eq halfop 'on) t)
- ((eq halfop 'off) nil)
- (t halfop))))
- (when (and op
- (not (eq (erc-channel-user-op cuser) op)))
- (setq changed t)
- (setf (erc-channel-user-op cuser)
- (cond ((eq op 'on) t)
- ((eq op 'off) nil)
- (t op))))
- (when (and admin
- (not (eq (erc-channel-user-admin cuser) admin)))
- (setq changed t)
- (setf (erc-channel-user-admin cuser)
- (cond ((eq admin 'on) t)
- ((eq admin 'off) nil)
- (t admin))))
- (when (and owner
- (not (eq (erc-channel-user-owner cuser) owner)))
- (setq changed t)
- (setf (erc-channel-user-owner cuser)
- (cond ((eq owner 'on) t)
- ((eq owner 'off) nil)
- (t owner))))
+ (erc-log (format "update-member: user = %S, cusr = %S" user cusr))
+ (when-let (((or voice halfop op admin owner))
+ (existing (erc-channel-user-status cusr)))
+ (when voice (setf (erc-channel-user-voice cusr) (eq voice 'on)))
+ (when halfop (setf (erc-channel-user-halfop cusr) (eq halfop 'on)))
+ (when op (setf (erc-channel-user-op cusr) (eq op 'on)))
+ (when admin (setf (erc-channel-user-admin cusr) (eq admin 'on)))
+ (when owner (setf (erc-channel-user-owner cusr) (eq owner 'on)))
+ (setq cusr-changed-p (= existing (erc-channel-user-status cusr))))
(when update-message-time
- (setf (erc-channel-user-last-message-time cuser) (current-time)))
- (setq user-changed
+ (setf (erc-channel-user-last-message-time cusr) (current-time)))
+ ;; Assume `user' exists and its `buffers' slot contains the
+ ;; current buffer so that `erc-channel-members-changed-hook'
+ ;; will run if changes are made.
+ (setq user-changed-p
(erc-update-user user new-nick
host login full-name info)))
- (when add
+ (when addp
(if (null user)
(progn
(setq user (make-erc-server-user
@@ -6028,30 +6941,22 @@ See also: `erc-update-user' and `erc-update-channel-member'."
(setf (erc-server-user-buffers user)
(cons (current-buffer)
(erc-server-user-buffers user))))
- (setq cuser (make-erc-channel-user
- :voice (cond ((eq voice 'on) t)
- ((eq voice 'off) nil)
- (t voice))
- :halfop (cond ((eq halfop 'on) t)
- ((eq halfop 'off) nil)
- (t halfop))
- :op (cond ((eq op 'on) t)
- ((eq op 'off) nil)
- (t op))
- :admin (cond ((eq admin 'on) t)
- ((eq admin 'off) nil)
- (t admin))
- :owner (cond ((eq owner 'on) t)
- ((eq owner 'off) nil)
- (t owner))
- :last-message-time
- (if update-message-time (current-time))))
- (puthash (erc-downcase nick) (cons user cuser)
- erc-channel-users)
- (setq changed t)))
- (when (and changed (null user-changed))
+ (setq cusr (make-erc-channel-user
+ :voice (and voice (eq voice 'on))
+ :halfop (and halfop (eq halfop 'on))
+ :op (and op (eq op 'on))
+ :admin (and admin (eq admin 'on))
+ :owner (and owner (eq owner 'on))
+ :last-message-time (if update-message-time
+ (current-time))))
+ (puthash down (cons user cusr) erc-channel-users)
+ (setq cusr-changed-p t)))
+ ;; An existing `cusr' was changed or a new one was added, and
+ ;; `user' was not updated, though possibly just created (since
+ ;; `erc-update-user' runs this same hook in all a user's buffers).
+ (when (and cusr-changed-p (null user-changed-p))
(run-hooks 'erc-channel-members-changed-hook))
- (or changed user-changed add)))
+ (or cusr-changed-p user-changed-p)))
(defun erc-update-channel-member (channel nick new-nick
&optional add voice halfop op admin owner host login
@@ -6096,7 +7001,9 @@ TOPIC string to the current topic."
(defun erc-set-modes (tgt mode-string)
"Set the modes for the TGT provided as MODE-STRING."
- (let* ((modes (erc-parse-modes mode-string))
+ (declare (obsolete "see comment atop `erc--update-modes'" "30.1"))
+ (let* ((modes (with-suppressed-warnings ((obsolete erc-parse-modes))
+ (erc-parse-modes mode-string)))
(add-modes (nth 0 modes))
;; list of triples: (mode-char 'on/'off argument)
(arg-modes (nth 2 modes)))
@@ -6142,6 +7049,7 @@ for modes without parameters to add and remove respectively. The
arg-modes is a list of triples of the form:
(MODE-CHAR ON/OFF ARGUMENT)."
+ (declare (obsolete "see comment atop `erc--update-modes'" "30.1"))
(if (string-match "^\\s-*\\(\\S-+\\)\\(\\s-.*$\\|$\\)" mode-string)
(let ((chars (mapcar #'char-to-string (match-string 1 mode-string)))
;; arguments in channel modes
@@ -6186,8 +7094,10 @@ arg-modes is a list of triples of the form:
"Update the mode information for TGT, provided as MODE-STRING.
Optional arguments: NICK, HOST and LOGIN - the attributes of the
person who changed the modes."
+ (declare (obsolete "see comment atop `erc--update-modes'" "30.1"))
;; FIXME: neither of nick, host, and login are used!
- (let* ((modes (erc-parse-modes mode-string))
+ (let* ((modes (with-suppressed-warnings ((obsolete erc-parse-modes))
+ (erc-parse-modes mode-string)))
(add-modes (nth 0 modes))
(remove-modes (nth 1 modes))
;; list of triples: (mode-char 'on/'off argument)
@@ -6236,9 +7146,265 @@ person who changed the modes."
;; nick modes - ignored at this point
(t nil))))
+(defun erc--update-membership-prefix (nick letter state)
+ "Update status prefixes for NICK in current channel buffer.
+Expect LETTER to be a status char and STATE to be a boolean."
+ (erc-update-current-channel-member nick nil nil
+ (and (= letter ?v) state)
+ (and (= letter ?h) state)
+ (and (= letter ?o) state)
+ (and (= letter ?a) state)
+ (and (= letter ?q) state)))
+
+(defvar-local erc--channel-modes nil
+ "When non-nil, a hash table of current channel modes.
+Keys are characters. Values are either a string, for types A-C,
+or t, for type D.")
+
+(defvar-local erc--channel-mode-types nil
+ "Possibly stale `erc--channel-mode-types' instance for the server.
+Use the getter of the same name to retrieve the current value.")
+
+(defvar-local erc--mode-line-mode-string nil
+ "Computed mode-line or header-line component for user/channel modes.")
+
+(defvar erc--mode-line-chanmodes-arg-len 10
+ "Max length at which to truncate channel-mode args in header line.")
+
+(defun erc--channel-mode-types ()
+ "Return variable `erc--channel-mode-types', possibly initializing it."
+ (erc--with-isupport-data CHANMODES erc--channel-mode-types
+ (let ((types (or key '(nil "Kk" "Ll" nil)))
+ (ct (make-char-table 'erc--channel-mode-types))
+ (type ?a))
+ (dolist (cs types)
+ (erc--doarray (c cs)
+ (aset ct c type))
+ (cl-incf type))
+ (make-erc--channel-mode-types :key key
+ :fallbackp (null key)
+ :table ct))))
+
+(defun erc--process-channel-modes (string args &optional status-letters)
+ "Parse channel \"MODE\" changes and call unary letter handlers.
+Update `erc-channel-modes' and `erc--channel-modes'. With
+STATUS-LETTERS, also update channel membership prefixes. Expect
+STRING to be the second argument from an incoming \"MODE\"
+command and ARGS to be the remaining arguments, which should
+complement relevant letters in STRING."
+ (cl-assert (erc--target-channel-p erc--target))
+ (let* ((obj (erc--channel-mode-types))
+ (table (erc--channel-mode-types-table obj))
+ (fallbackp (erc--channel-mode-types-fallbackp obj))
+ (+p t))
+ (erc--doarray (c string)
+ (cond ((= ?+ c) (setq +p t))
+ ((= ?- c) (setq +p nil))
+ ((and status-letters (string-search (string c) status-letters))
+ (erc--update-membership-prefix (pop args) c (if +p 'on 'off)))
+ ((and-let* ((group (or (aref table c) (and fallbackp ?d))))
+ (erc--handle-channel-mode group c +p
+ (and (/= group ?d)
+ (or (/= group ?c) +p)
+ (pop args)))
+ t))
+ ((not fallbackp)
+ (erc-display-message nil '(notice error) (erc-server-buffer)
+ (format "Unknown channel mode: %S" c)))))
+ (setq erc-channel-modes (sort erc-channel-modes #'string<))
+ (setq erc--mode-line-mode-string
+ (concat "+" (erc--channel-modes erc--mode-line-chanmodes-arg-len)))
+ (erc-update-mode-line (current-buffer))))
+
+(defvar-local erc--user-modes nil
+ "Sorted list of current user \"MODE\" letters.
+Analogous to `erc-channel-modes' but chars rather than strings.")
+
+(defun erc--user-modes (&optional as-type)
+ "Return user \"MODE\" letters in a form described by AS-TYPE.
+When AS-TYPE is the symbol `strings' (plural), return a list of
+strings. When it's `string' (singular), return the same list
+concatenated into a single string. When AS-TYPE is nil, return a
+list of chars."
+ (let ((modes (or erc--user-modes (erc-with-server-buffer erc--user-modes))))
+ (pcase as-type
+ ('strings (mapcar #'char-to-string modes))
+ ('string (apply #'string modes))
+ (_ modes))))
+
+(defun erc--channel-modes (&optional as-type sep)
+ "Return channel \"MODE\" settings in a form described by AS-TYPE.
+When AS-TYPE is the symbol `strings' (plural), return letter keys
+as a list of sorted string. When it's `string' (singular),
+return keys as a single string. When it's a number N, return a
+single string consisting of the concatenated and sorted keys
+followed by a space and then their corresponding args, each
+truncated to N chars max. ERC joins these args together with
+SEP, which defaults to a single space. Otherwise, return a
+sorted alist of letter and arg pairs. In all cases that include
+values, respect `erc-show-channel-key-p' and optionally omit the
+secret key associated with the letter k."
+ (and-let* ((modes erc--channel-modes)
+ (tobj (erc--channel-mode-types))
+ (types (erc--channel-mode-types-table tobj)))
+ (let (out)
+ (maphash (lambda (k v)
+ (unless (eq ?a (aref types k))
+ (push (cons k
+ (and (not (eq t v))
+ (not (and (eq k ?k)
+ (not (bound-and-true-p
+ erc-show-channel-key-p))))
+ v))
+ out)))
+ modes)
+ (setq out (cl-sort out #'< :key #'car))
+ (pcase as-type
+ ('strings (mapcar (lambda (o) (char-to-string (car o))) out))
+ ('string (apply #'string (mapcar #'car out)))
+ ((and (pred natnump) c)
+ (let (keys vals)
+ (pcase-dolist (`(,k . ,v) out)
+ (when v
+ (push (if (> (length v) c)
+ (with-memoization
+ (gethash (list c k v)
+ (erc--channel-mode-types-shortargs tobj))
+ (truncate-string-to-width v c 0 nil t))
+ v)
+ vals))
+ (push k keys))
+ (concat (apply #'string (nreverse keys)) (and vals " ")
+ (string-join (nreverse vals) (or sep " ")))))
+ (_ out)))))
+
+(defun erc--parse-user-modes (string &optional current extrap)
+ "Return lists of chars from STRING to add to and drop from CURRENT.
+Expect STRING to be a so-called \"modestring\", the second
+parameter of a \"MODE\" command, here containing only valid
+user-mode letters. Expect CURRENT to be a list of chars
+resembling those found in `erc--user-modes'. With EXTRAP, return
+two additional lists of chars: those that would be added were
+they not already present in CURRENT and those that would be
+dropped were they not already absent."
+ (let ((addp t)
+ ;;
+ redundant-add redundant-drop adding dropping)
+ (erc--doarray (c string)
+ (pcase c
+ (?+ (setq addp t))
+ (?- (setq addp nil))
+ (_ (push c (let ((hasp (and current (memq c current))))
+ (if addp
+ (if hasp redundant-add adding)
+ (if hasp dropping redundant-drop)))))))
+ (if extrap
+ (list (nreverse adding) (nreverse dropping)
+ (nreverse redundant-add) (nreverse redundant-drop))
+ (list (nreverse adding) (nreverse dropping)))))
+
+(defun erc--update-user-modes (string)
+ "Update `erc--user-modes' from \"MODE\" STRING.
+Return its value, a list of characters sorted by character code."
+ (prog1
+ (setq erc--user-modes
+ (pcase-let ((`(,adding ,dropping)
+ (erc--parse-user-modes string erc--user-modes)))
+ (sort (seq-difference (nconc erc--user-modes adding) dropping)
+ #'<)))
+ (setq erc--mode-line-mode-string
+ (concat "+" (erc--user-modes 'string)))))
+
+(defun erc--update-channel-modes (string &rest args)
+ "Update `erc-channel-modes' and call individual mode handlers.
+Also update membership prefixes, as needed. Expect STRING to be
+a \"modestring\" and ARGS to match mode-specific parameters."
+ (let ((status-letters (or (erc-with-server-buffer
+ (erc--parsed-prefix-letters
+ (erc--parsed-prefix)))
+ "qaovhbQAOVHB")))
+ (erc--process-channel-modes string args status-letters)))
+
+;; XXX this comment is referenced elsewhere (grep before deleting).
+;;
+;; The function `erc-update-modes' was deprecated in ERC 5.6 with no
+;; immediate public replacement. Third parties needing such a thing
+;; are encouraged to write to emacs-erc@gnu.org with ideas for a
+;; mode-handler API, possibly one incorporating letter-specific
+;; handlers, like `erc--handle-channel-mode' (below), which only
+;; handles mode types A-C.
+(defun erc--update-modes (raw-args)
+ "Handle user or channel \"MODE\" update from server.
+Expect RAW-ARGS be a list consisting of a \"modestring\" followed
+by mode-specific arguments."
+ (if (and erc--target (erc--target-channel-p erc--target))
+ (apply #'erc--update-channel-modes raw-args)
+ (erc--update-user-modes (car raw-args))))
+
+(defun erc--init-channel-modes (channel raw-args)
+ "Set CHANNEL modes from RAW-ARGS.
+Expect RAW-ARGS to be a \"modestring\" without any status-prefix
+chars, followed by applicable arguments."
+ (erc-with-buffer (channel)
+ (erc--process-channel-modes (car raw-args) (cdr raw-args))))
+
+(cl-defgeneric erc--handle-channel-mode (type letter state arg)
+ "Handle a STATE change for mode LETTER of TYPE with ARG.
+Expect to be called in the affected target buffer. Expect TYPE
+to be a character, like ?a, representing an advertised
+\"CHANMODES\" group. Expect LETTER to also be a character, and
+expect STATE to be a boolean and ARGUMENT either a string or nil."
+ (erc-log (format "Channel-mode %c (type %s, arg %S) %s"
+ letter type arg (if state 'enabled 'disabled))))
+
+(cl-defmethod erc--handle-channel-mode :before (type c state arg)
+ "Record STATE change for mode letter C.
+When STATE is non-nil, add or update C's mapping in
+`erc--channel-modes', associating it with ARG if C takes a
+parameter and t otherwise. When STATE is nil, forget the
+mapping. For type A, add up update a permanent mapping for C,
+associating it with an integer indicating a running total of
+STATE changes since joining the channel. In most cases, this
+won't match the number known to the server."
+ (unless erc--channel-modes
+ (cl-assert (erc--target-channel-p erc--target))
+ (setq erc--channel-modes (make-hash-table)))
+ (if (= type ?a)
+ (cl-callf (lambda (s) (+ (or s 0) (if state +1 -1)))
+ (gethash c erc--channel-modes))
+ (if state
+ (puthash c (or arg t) erc--channel-modes)
+ (remhash c erc--channel-modes))))
+
+(cl-defmethod erc--handle-channel-mode :before ((_ (eql ?d)) c state _)
+ "Update `erc-channel-modes' for any character C of nullary type D.
+Remember when STATE is non-nil and forget otherwise."
+ (setq erc-channel-modes
+ (if state
+ (cl-pushnew (char-to-string c) erc-channel-modes :test #'equal)
+ (delete (char-to-string c) erc-channel-modes))))
+
+;; We could specialize on type C, but that may be too brittle.
+(cl-defmethod erc--handle-channel-mode (_ (_ (eql ?l)) state arg)
+ "Update channel user limit, remembering ARG when STATE is non-nil."
+ (erc-update-channel-limit (erc--target-string erc--target)
+ (if state 'on 'off)
+ arg))
+
+;; We could specialize on type B, but that may be too brittle.
+(cl-defmethod erc--handle-channel-mode (_ (_ (eql ?k)) state arg)
+ "Update channel key, remembering ARG when state is non-nil."
+ ;; Mimic old parsing behavior in which an ARG of "*" was discarded
+ ;; even though `erc-update-channel-limit' checks STATE first.
+ (erc-update-channel-key (erc--target-string erc--target)
+ (if state 'on 'off)
+ (if (equal arg "*") nil arg)))
+
(defun erc-update-channel-limit (channel onoff n)
- ;; FIXME: what does ONOFF actually do? -- Lawrence 2004-01-08
- "Update CHANNEL's user limit to N."
+ "Update CHANNEL's user limit to N.
+Expect ONOFF to be `on' when the mode is being enabled and `off'
+otherwise. And because this mode is of \"type C\", expect N to
+be non-nil only when enabling."
(if (or (not (eq onoff 'on))
(and (stringp n) (string-match "^[0-9]+$" n)))
(erc-with-buffer
@@ -6310,18 +7476,28 @@ OBJECT is modified without being copied first.
You can redefine or `defadvice' this function in order to add
EmacsSpeak support."
- (if erc--compose-text-properties
+ (if erc--merge-text-properties-p
(erc--merge-prop start end property value object)
(put-text-property start end property value object)))
(defalias 'erc-list 'ensure-list)
+(defconst erc--parse-user-regexp-pedantic
+ (rx bot (? (? (group (+ (not (any "!@\r\n"))))) "!")
+ (? (? (group (+ nonl))) "@")
+ (? (group (+ nonl))) eot))
+
+(defconst erc--parse-user-regexp-legacy
+ "^\\([^!\n]*\\)!\\([^@\n]*\\)@\\(.*\\)$")
+
+(defvar erc--parse-user-regexp erc--parse-user-regexp-legacy)
+
(defun erc-parse-user (string)
"Parse STRING as a user specification (nick!login@host).
Return a list of the three separate tokens."
(cond
- ((string-match "^\\([^!\n]*\\)!\\([^@\n]*\\)@\\(.*\\)$" string)
+ ((string-match erc--parse-user-regexp string)
(list (match-string 1 string)
(match-string 2 string)
(match-string 3 string)))
@@ -6333,6 +7509,20 @@ Return a list of the three separate tokens."
(t
(list string "" ""))))
+(defun erc--parse-nuh (string)
+ "Match STRING against `erc--parse-user-regexp-pedantic'.
+Return nil or matching groups representing nick, login, and host,
+any of which may be nil. Expect STRING not to contain leading
+prefix chars. Return an empty nick component to indicate further
+processing is required based on context. Interpret a lone token
+lacking delimiters or one with only a leading \"!\" as a host.
+
+See associated unit test for precise behavior."
+ (when (string-match erc--parse-user-regexp-pedantic string)
+ (list (match-string 1 string)
+ (match-string 2 string)
+ (match-string 3 string))))
+
(defun erc-extract-nick (string)
"Return the nick corresponding to a user specification STRING.
@@ -6409,20 +7599,6 @@ holds off on submitting it, for obvious reasons."
(defvar erc-command-regexp "^/\\([A-Za-z']+\\)\\(\\s-+.*\\|\\s-*\\)$"
"Regular expression used for matching commands in ERC.")
-(defun erc--blank-in-multiline-input-p (lines)
- "Detect whether LINES contains a blank line.
-When `erc-send-whitespace-lines' is in effect, return nil if
-LINES is multiline or the first line is non-empty. When
-`erc-send-whitespace-lines' is nil, return non-nil when any line
-is empty or consists of one or more spaces, tabs, or form-feeds."
- (catch 'return
- (let ((multilinep (cdr lines)))
- (dolist (line lines)
- (when (if erc-send-whitespace-lines
- (and (string-empty-p line) (not multilinep))
- (string-match (rx bot (* (in " \t\f")) eot) line))
- (throw 'return t))))))
-
(defun erc--check-prompt-input-for-excess-lines (_ lines)
"Return non-nil when trying to send too many LINES."
(when erc-inhibit-multiline-input
@@ -6442,23 +7618,97 @@ is empty or consists of one or more spaces, tabs, or form-feeds."
(y-or-n-p (concat "Send input " msg "?")))
(concat "Too many lines " msg))))))
-(defun erc--check-prompt-input-for-multiline-blanks (_ lines)
- "Return non-nil when multiline prompt input has blank LINES."
- (when (erc--blank-in-multiline-input-p lines)
+(defun erc--check-prompt-input-for-something (string _)
+ (when (string-empty-p string)
(if erc-warn-about-blank-lines
"Blank line - ignoring..."
'invalid)))
+(defun erc--count-blank-lines (lines)
+ "Report on the number of whitespace-only and empty LINES.
+Return a list of (BLANKS TO-PAD TO-STRIP). Expect caller to know
+that BLANKS includes non-empty whitespace-only lines and that no
+padding or stripping has yet occurred."
+ (let ((real 0) (total 0) (pad 0) (strip 0))
+ (dolist (line lines)
+ (if (string-match (rx bot (* (in " \t\f")) eot) line)
+ (progn
+ (cl-incf total)
+ (if (zerop (match-end 0))
+ (cl-incf strip)
+ (cl-incf pad strip)
+ (setq strip 0)))
+ (cl-incf real)
+ (unless (zerop strip)
+ (cl-incf pad strip)
+ (setq strip 0))))
+ (when (and (zerop real) (not (zerop total)) (= total (+ pad strip)))
+ (cl-incf strip (1- pad))
+ (setq pad 1))
+ (list total pad strip)))
+
+(defvar erc--check-prompt-explanation nil
+ "List of strings to print if no validator returns non-nil.")
+
+(defun erc--check-prompt-input-for-multiline-blanks (_ lines)
+ "Return non-nil when multiline prompt input has blank LINES.
+Consider newlines to be intervening delimiters, meaning the empty
+\"logical\" line between a trailing newline and `eob' constitutes
+a separate message."
+ (pcase-let ((`(,total ,pad ,strip)(erc--count-blank-lines lines)))
+ (cond ((zerop total) nil)
+ ((and erc-warn-about-blank-lines erc-send-whitespace-lines)
+ (let (msg args)
+ (unless (zerop strip)
+ (push "stripping (%d)" msg)
+ (push strip args))
+ (unless (zerop pad)
+ (when msg
+ (push "and" msg))
+ (push "padding (%d)" msg)
+ (push pad args))
+ (when msg
+ (push "blank" msg)
+ (push (if (> (apply #'+ args) 1) "lines" "line") msg))
+ (when msg
+ (setf msg (nreverse msg)
+ (car msg) (capitalize (car msg))))
+ (when msg
+ (push (apply #'format (string-join msg " ") (nreverse args))
+ erc--check-prompt-explanation)
+ nil)))
+ (erc-warn-about-blank-lines
+ (concat (if (= total 1)
+ (if (zerop strip) "Blank" "Trailing")
+ (if (= total strip)
+ (format "%d trailing" strip)
+ (format "%d blank" total)))
+ (and (> total 1) (/= total strip) (not (zerop strip))
+ (format " (%d trailing)" strip))
+ (if (= total 1) " line" " lines")
+ " detected (see `erc-send-whitespace-lines')"))
+ (erc-send-whitespace-lines nil)
+ (t 'invalid))))
+
(defun erc--check-prompt-input-for-point-in-bounds (_ _)
"Return non-nil when point is before prompt."
(when (< (point) (erc-beg-of-input-line))
"Point is not in the input area"))
+;; Originally, `erc-send-current-line' inhibited sends whenever a
+;; server buffer was missing. In 2007, this was narrowed to
+;; occurrences involving process-dependent commands. However, the
+;; accompanying error message, which was identical to that emitted by
+;; `erc-server-send', "ERC: No process running", was always inaccurate
+;; because a server buffer can be alive and its process dead.
(defun erc--check-prompt-input-for-running-process (string _)
- "Return non-nil unless in an active ERC server buffer."
- (unless (or (erc-server-buffer-live-p)
- (erc-command-no-process-p string))
- "ERC: No process running"))
+ "Return non-nil if STRING is a slash command missing a process.
+Also do so when the server buffer has been killed."
+ ;; Even if the server buffer has been killed, the user should still
+ ;; be able to /reconnect and recall previous commands.
+ (and (not (erc-command-no-process-p string))
+ (or (and (not (erc-server-buffer-live-p)) "Server buffer missing")
+ (and (not (erc-server-process-alive)) "Process not running"))))
(defun erc--check-prompt-input-for-multiline-command (line lines)
"Return non-nil when non-blank lines follow a command line."
@@ -6469,25 +7719,47 @@ is empty or consists of one or more spaces, tabs, or form-feeds."
(defvar erc--check-prompt-input-functions
'(erc--check-prompt-input-for-point-in-bounds
+ erc--check-prompt-input-for-something
+ erc--check-prompt-input-for-multiline-command
erc--check-prompt-input-for-multiline-blanks
erc--check-prompt-input-for-running-process
- erc--check-prompt-input-for-excess-lines
- erc--check-prompt-input-for-multiline-command)
+ erc--check-prompt-input-for-excess-lines)
"Validators for user input typed at prompt.
-Called with latest input string submitted by user and the list of
-lines produced by splitting it. If any member function returns
-non-nil, processing is abandoned and input is left untouched.
-When the returned value is a string, ERC passes it to `erc-error'.")
+Called with two arguments: the current input submitted by the
+user, as a string, along with the same input as a list of
+strings. If any member function returns non-nil, ERC abandons
+processing and leaves pending input untouched in the prompt area.
+When the returned value is a string, ERC passes it to
+`user-error'. Any other non-nil value tells ERC to abort
+silently. If all members return nil, and the variable
+`erc--check-prompt-explanation' is a nonempty list of strings,
+ERC prints them as a single message joined by newlines.")
(defun erc--run-input-validation-checks (state)
"Run input checkers from STATE, an `erc--input-split' object."
- (when-let ((msg (run-hook-with-args-until-success
- 'erc--check-prompt-input-functions
- (erc--input-split-string state)
- (erc--input-split-lines state))))
- (unless (stringp msg)
- (setq msg (format "Input error: %S" msg)))
- (user-error msg)))
+ (let* ((erc--check-prompt-explanation nil)
+ (msg (run-hook-with-args-until-success
+ 'erc--check-prompt-input-functions
+ (erc--input-split-string state)
+ (erc--input-split-lines state))))
+ (cond ((stringp msg) (user-error msg))
+ (msg (push msg (erc--input-split-abortp state)))
+ (erc--check-prompt-explanation
+ (message "%s" (string-join (nreverse erc--check-prompt-explanation)
+ "\n"))))))
+
+(defun erc--inhibit-slash-cmd-insertion (state)
+ "Don't insert STATE object's message if it's a \"slash\" command."
+ (when (erc--input-split-cmdp state)
+ (setf (erc--input-split-insertp state) nil)))
+
+(defun erc--make-input-split (string)
+ (make-erc--input-split
+ :string string
+ :insertp erc-insert-this
+ :sendp erc-send-this
+ :lines (split-string string erc--input-line-delim-regexp)
+ :cmdp (string-match erc-command-regexp string)))
(defun erc-send-current-line ()
"Parse current line and send it to IRC."
@@ -6503,16 +7775,12 @@ When the returned value is a string, ERC passes it to `erc-error'.")
(expand-abbrev))
(widen)
(let* ((str (erc-user-input))
- (state (make-erc--input-split
- :string str
- :insertp erc-insert-this
- :sendp erc-send-this
- :lines (split-string
- str erc--input-line-delim-regexp)
- :cmdp (string-match erc-command-regexp str))))
+ (state (erc--make-input-split str)))
(run-hook-with-args 'erc--input-review-functions state)
- (let ((inhibit-read-only t)
- (old-buf (current-buffer)))
+ (when-let (((not (erc--input-split-abortp state)))
+ (inhibit-read-only t)
+ (erc--current-line-input-split state)
+ (old-buf (current-buffer)))
(progn ; unprogn this during next major surgery
(erc-set-active-buffer (current-buffer))
;; Kill the input and the prompt
@@ -6541,12 +7809,11 @@ When the returned value is a string, ERC passes it to `erc-error'.")
(erc-end-of-input-line)))
(defun erc--discard-trailing-multiline-nulls (state)
- "Ensure last line of STATE's string is non-null.
-But only when `erc-send-whitespace-lines' is non-nil. STATE is
-an `erc--input-split' object."
- (when (and erc-send-whitespace-lines (erc--input-split-lines state))
+ "Remove trailing empty lines from STATE, an `erc--input-split' object.
+When all lines are empty, remove all but the first."
+ (when (erc--input-split-lines state)
(let ((reversed (nreverse (erc--input-split-lines state))))
- (while (and reversed (string-empty-p (car reversed)))
+ (while (and (cdr reversed) (string-empty-p (car reversed)))
(setq reversed (cdr reversed)))
(setf (erc--input-split-lines state) (nreverse reversed)))))
@@ -6558,6 +7825,22 @@ an `erc--input-split' object."
(setf (erc--input-split-lines state)
(mapcan #'erc--split-line (erc--input-split-lines state)))))
+(defun erc--input-ensure-hook-context ()
+ (unless (erc--input-split-p erc--current-line-input-split)
+ (error "Invoked outside of `erc-pre-send-functions'")))
+
+(defun erc-input-refoldp (_)
+ "Impersonate accessor for phony `erc-input' `refoldp' slot.
+This function only works inside `erc-pre-send-functions' members."
+ (declare (gv-setter (lambda (v)
+ `(progn
+ (erc--input-ensure-hook-context)
+ (setf (erc--input-split-refoldp
+ erc--current-line-input-split)
+ ,v)))))
+ (erc--input-ensure-hook-context)
+ (erc--input-split-refoldp erc--current-line-input-split))
+
(defun erc--run-send-hooks (lines-obj)
"Run send-related hooks that operate on the entire prompt input.
Sequester some of the back and forth involved in honoring old
@@ -6566,7 +7849,7 @@ multiline input. Optionally readjust lines to protocol length
limits and pad empty ones, knowing full well that additional
processing may still corrupt messages before they reach the send
queue. Expect LINES-OBJ to be an `erc--input-split' object."
- (when (or erc-send-pre-hook erc-pre-send-functions)
+ (progn ; FIXME remove `progn' after code review.
(with-suppressed-warnings ((lexical str) (obsolete erc-send-this))
(defvar str) ; see note in string `erc-send-input'.
(let* ((str (string-join (erc--input-split-lines lines-obj) "\n"))
@@ -6583,22 +7866,25 @@ queue. Expect LINES-OBJ to be an `erc--input-split' object."
(erc--input-split-insertp lines-obj) (erc-input-insertp state)
;; See note in test of same name re trailing newlines.
(erc--input-split-lines lines-obj)
- (cl-nsubst " " "" (split-string (erc-input-string state)
- erc--input-line-delim-regexp)
- :test #'equal))
- (when (erc-input-refoldp state)
+ (let ((lines (split-string (erc-input-string state)
+ erc--input-line-delim-regexp)))
+ (if erc--allow-empty-outgoing-lines-p
+ lines
+ (cl-nsubst " " "" lines :test #'equal))))
+ (when (erc--input-split-refoldp lines-obj)
(erc--split-lines lines-obj)))))
(when (and (erc--input-split-cmdp lines-obj)
(cdr (erc--input-split-lines lines-obj)))
(user-error "Multiline command detected" ))
lines-obj)
-(defun erc--send-input-lines (lines-obj)
+(cl-defmethod erc--send-input-lines (lines-obj)
"Send lines in `erc--input-split-lines' object LINES-OBJ."
(when (erc--input-split-sendp lines-obj)
(dolist (line (erc--input-split-lines lines-obj))
- (unless (erc--input-split-cmdp lines-obj)
- (when (erc--input-split-insertp lines-obj)
+ (when (erc--input-split-insertp lines-obj)
+ (if (functionp (erc--input-split-insertp lines-obj))
+ (funcall (erc--input-split-insertp lines-obj) line)
(erc-display-msg line)))
(erc-process-input-line (concat line "\n")
(null erc-flood-protect)
@@ -6657,22 +7943,27 @@ Return non-nil only if we actually send anything."
t)))))
(defun erc-display-msg (line)
- "Display LINE as a message of the user to the current target at point."
+ "Insert LINE into current buffer and run \"send\" hooks.
+Treat LINE as input submitted interactively at the prompt, such
+as outgoing chat messages and echoed slash commands."
(when erc-insert-this
(save-excursion
(erc--assert-input-bounds)
(let ((insert-position (marker-position (goto-char erc-insert-marker)))
- beg)
- (insert (erc-format-my-nick))
- (setq beg (point))
- (insert line)
- (erc-put-text-property beg (point) 'font-lock-face 'erc-input-face)
- (erc-put-text-property insert-position (point) 'erc-command 'PRIVMSG)
- (insert "\n")
+ (erc--msg-props (or erc--msg-props
+ (let ((ovs (seq-filter
+ #'cdr erc--msg-prop-overrides)))
+ (map-into `((erc--msg . msg) ,@(reverse ovs))
+ 'hash-table)))))
+ (insert (erc--format-speaker-input-message line) "\n")
(save-restriction
(narrow-to-region insert-position (point))
(run-hooks 'erc-send-modify-hook)
- (run-hooks 'erc-send-post-hook))
+ (run-hooks 'erc-send-post-hook)
+ (cl-assert (> (- (point-max) (point-min)) 1))
+ (add-text-properties (point-min) (1+ (point-min))
+ (erc--order-text-properties-from-hash
+ erc--msg-props)))
(erc--refresh-prompt)))))
(defun erc-command-symbol (command)
@@ -6753,28 +8044,16 @@ See also `erc-downcase'."
;; default target handling
(defun erc--current-buffer-joined-p ()
- "Return whether the current target buffer is joined."
- ;; This may be a reliable means of detecting subscription status,
- ;; but it's also roundabout and awkward. Perhaps it's worth
- ;; discussing adding a joined slot to `erc--target' for this.
+ "Return non-nil if the current buffer is a channel and is joined."
(cl-assert erc--target)
(and (erc--target-channel-p erc--target)
- (erc-get-channel-user (erc-current-nick)) t))
-
-;; While `erc-default-target' happens to return nil in channel buffers
-;; you've parted or from which you've been kicked, using it to detect
-;; whether a channel is currently joined may become unreliable in the
-;; future. For now, third-party code can use
-;;
-;; (erc-get-channel-user (erc-current-nick))
-;;
-;; A predicate may be provided eventually. For retrieving a target's
-;; name regardless of subscription or connection status, new library
-;; code should use `erc--default-target'. Third-party code should
-;; continue to use `erc-default-target'.
+ (erc--target-channel-joined-p erc--target)
+ t))
(defun erc-default-target ()
- "Return the current default target (as a character string) or nil if none."
+ "Return the current channel or query target, if any.
+For historical reasons, return nil in channel buffers if not
+currently joined."
(let ((tgt (car erc-default-recipients)))
(cond
((not tgt) nil)
@@ -6821,6 +8100,8 @@ The previous default target of QUERY type gets removed."
(setq erc-default-recipients d2)
(error "Current target is not a QUERY"))))
+;; FIXME move all ignore-related functionality to its own module,
+;; required and enabled by default (until some major version change).
(defun erc-ignored-user-p (spec)
"Return non-nil if SPEC matches something in `erc-ignore-list'.
@@ -7108,7 +8389,10 @@ sequences, process the lines verbatim. Use this for multiline
user input."
(let* ((cb (current-buffer))
(s "")
- (sp (or (erc-command-indicator) (erc-prompt)))
+ (sp (or (and (bound-and-true-p erc-command-indicator-mode)
+ (fboundp 'erc-command-indicator)
+ (erc-command-indicator))
+ (erc-prompt)))
(args (and (boundp 'erc-script-args) erc-script-args)))
(if (and args (string-match "^ " args))
(setq args (substring args 1)))
@@ -7336,15 +8620,14 @@ If it doesn't exist, create it."
(unless (file-attributes dir) (make-directory dir))
(or (file-accessible-directory-p dir) (error "Cannot access %s" dir)))
+;; FIXME make function obsolete or alias to something less confusing.
(defun erc-kill-query-buffers (process)
- "Kill all buffers of PROCESS.
-Does nothing if PROCESS is not a process object."
+ "Kill all target buffers of PROCESS, including channel buffers.
+Do nothing if PROCESS is not a process object."
;; here, we only want to match the channel buffers, to avoid
;; "selecting killed buffers" b0rkage.
(when (processp process)
- (erc-with-all-buffers-of-server process
- (lambda ()
- (not (erc-server-buffer-p)))
+ (erc-with-all-buffers-of-server process (lambda () erc--target)
(kill-buffer (current-buffer)))))
(defun erc-nick-at-point ()
@@ -7436,8 +8719,13 @@ See `erc-mode-line-format' for which characters are can be used."
:type '(choice (const :tag "Disabled" nil)
string))
+;; This should optionally support the built-in `tab-bar'.
(defcustom erc-header-line-uses-tabbar-p nil
- "Use tabbar mode instead of the header line to display the header."
+ "Use `tabbar-mode' integration instead of the header line.
+This concerns a historical integration with the external library
+`tabbar' <https://www.emacswiki.org/emacs/tabbar.el>, which
+shouldn't be confused with the built-in `tab-bar' described in
+Info node `(emacs) Tab Bars'."
:group 'erc-mode-line-and-header
:type 'boolean)
@@ -7528,6 +8816,62 @@ shortened server name instead."
(format-time-string erc-mode-line-away-status-format a)
"")))
+(defvar-local erc--away-indicator nil
+ "Cons containing an away indicator for the connection.")
+
+(defvar erc-away-status-indicator "A"
+ "String shown by various formatting facilities to indicate away status.
+Currently only used by the option `erc-prompt-format'.")
+
+(defun erc--format-away-indicator ()
+ "Return char with `display' property of `erc--away-indicator'."
+ (and-let* ((indicator (erc-with-server-buffer
+ (or erc--away-indicator
+ (setq erc--away-indicator (list "")))))
+ (newcar (if (erc-away-time) erc-away-status-indicator "")))
+ ;; Inform other buffers of the change when necessary.
+ (let ((dispp (not erc--inhibit-prompt-display-property-p)))
+ (unless (eq newcar (car indicator))
+ (erc--refresh-prompt-continue (and dispp 'hooks-only-p))
+ (setcar indicator newcar))
+ (if dispp
+ (propertize "(away?)" 'display indicator)
+ newcar))))
+
+(defvar-local erc--user-modes-indicator nil
+ "Cons containing connection-wide indicator for user modes.")
+
+;; If adding more of these functions, should factor out commonalities.
+;; 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"
+ (and-let* ((indicator (erc-with-server-buffer
+ (or erc--user-modes-indicator
+ (setq erc--user-modes-indicator (list "")))))
+ (newcar (erc--user-modes 'string)))
+ (let ((dispp (not erc--inhibit-prompt-display-property-p)))
+ (unless (string= newcar (car indicator))
+ (erc--refresh-prompt-continue (and dispp 'hooks-only-p))
+ (setcar indicator newcar))
+ (if dispp
+ (propertize "(user-modes?)" 'display indicator)
+ newcar))))
+
+(defun erc--format-channel-status-prefix ()
+ "Return the current channel membership prefix."
+ (and (erc--target-channel-p erc--target)
+ (erc-get-channel-membership-prefix (erc-current-nick))))
+
+(defun erc--format-modes (&optional no-query-p)
+ "Return a string of channel modes in channels and user modes elsewhere.
+With NO-QUERY-P, return nil instead of user modes in query
+buffers. Also return nil when mode information is unavailable."
+ (cond ((erc--target-channel-p erc--target)
+ (erc--channel-modes 'string))
+ ((not (and erc--target no-query-p))
+ (erc--format-user-modes))))
+
(defun erc-format-channel-modes ()
"Return the current channel's modes."
(concat (apply #'concat
@@ -7559,7 +8903,7 @@ shortened server name instead."
(with-current-buffer buffer
(let ((spec `((?a . ,(erc-format-away-status))
(?l . ,(erc-format-lag-time))
- (?m . ,(erc-format-channel-modes))
+ (?m . ,(or erc--mode-line-mode-string ""))
(?n . ,(or (erc-current-nick) ""))
(?N . ,(erc-format-network))
(?o . ,(or (erc-controls-strip erc-channel-topic) ""))
@@ -7588,7 +8932,8 @@ shortened server name instead."
(format-spec erc-header-line-format spec)
nil)))
(cond (erc-header-line-uses-tabbar-p
- (setq-local tabbar--local-hlf header-line-format)
+ (when (boundp 'tabbar--local-hlf)
+ (setq-local tabbar--local-hlf header-line-format))
(kill-local-variable 'header-line-format))
((null header)
(setq header-line-format nil))
@@ -7722,10 +9067,11 @@ If optional argument HERE is non-nil, insert version number at point."
(let (modes (case-fold-search nil))
(dolist (var (apropos-internal "^erc-.*mode$"))
(when (and (boundp var)
+ (get var 'erc-module)
(symbol-value var))
- (setq modes (cons (symbol-name var)
+ (setq modes (cons (concat "`" (symbol-name var) "'")
modes))))
- modes)
+ (sort modes #'string<))
", ")))
(if here
(insert string)
@@ -7781,24 +9127,38 @@ All windows are opened in the current frame."
;;; Message catalog
+(define-inline erc--make-message-variable-name (catalog key softp)
+ "Return variable name conforming to ERC's message-catalog interface.
+Given a CATALOG symbol `mycat' and format-string KEY `mykey',
+also a symbol, return the symbol `erc-message-mycat-mykey'. With
+SOFTP, only do so when defined as a variable."
+ (inline-quote
+ (let* ((catname (symbol-name ,catalog))
+ (prefix (if (eq ?- (aref catname 0)) "erc--message" "erc-message-"))
+ (name (concat prefix catname "-" (symbol-name ,key))))
+ (if ,softp
+ (and-let* ((s (intern-soft name)) ((boundp s))) s)
+ (intern name)))))
+
(defun erc-make-message-variable-name (catalog entry)
"Create a variable name corresponding to CATALOG's ENTRY."
- (intern (concat "erc-message-"
- (symbol-name catalog) "-" (symbol-name entry))))
+ (erc--make-message-variable-name catalog entry nil))
(defun erc-define-catalog-entry (catalog entry format-spec)
"Set CATALOG's ENTRY to FORMAT-SPEC."
+ (declare (obsolete "define manually using `defvar' instead" "30.1"))
(set (erc-make-message-variable-name catalog entry)
format-spec))
(defun erc-define-catalog (catalog entries)
"Define a CATALOG according to ENTRIES."
- (dolist (entry entries)
- (erc-define-catalog-entry catalog (car entry) (cdr entry))))
+ (declare (obsolete erc-define-message-format-catalog "30.1"))
+ (with-suppressed-warnings ((obsolete erc-define-catalog-entry))
+ (dolist (entry entries)
+ (erc-define-catalog-entry catalog (car entry) (cdr entry)))))
-(erc-define-catalog
- 'english
- '((bad-ping-response . "Unexpected PING response from %n (time %t)")
+(erc--define-catalog english
+ ((bad-ping-response . "Unexpected PING response from %n (time %t)")
(bad-syntax . "Error occurred - incorrect usage?\n%c %u\n%d")
(incorrect-args . "Incorrect arguments. Usage:\n%c %u\n%d")
(cannot-find-file . "Cannot find file %f")
@@ -7813,9 +9173,10 @@ All windows are opened in the current frame."
(flood-ctcp-off . "FLOOD PROTECTION: Automatic CTCP responses turned off.")
(flood-strict-mode
. "FLOOD PROTECTION: Switched to Strict Flood Control mode.")
- (disconnected . "\n\nConnection failed! Re-establishing connection...\n")
+ (disconnected
+ . "\n\n*** Connection failed! Re-establishing connection...\n")
(disconnected-noreconnect
- . "\n\nConnection failed! Not re-establishing connection.\n")
+ . "\n\n*** Connection failed! Not re-establishing connection.\n")
(reconnecting . "Reconnecting in %ms: attempt %i/%n ...")
(reconnect-canceled . "Canceled %u reconnect timer with %cs to go...")
(finished . "\n\n*** ERC finished ***\n")
@@ -7830,6 +9191,10 @@ All windows are opened in the current frame."
(ops . "%i operator%s: %o")
(ops-none . "No operators in this channel.")
(undefined-ctcp . "Undefined CTCP query received. Silently ignored")
+ (user-mode-redundant-add
+ . "Already have user mode(s): %m. Requesting again anyway.")
+ (user-mode-redundant-drop
+ . "Already without user mode(s): %m. Requesting removal anyway.")
(variable-not-bound . "Variable not bound!")
(ACTION . "* %n %a")
(CTCP-CLIENTINFO . "Client info for %n: %m")
@@ -7850,7 +9215,7 @@ All windows are opened in the current frame."
(MODE-nick . "%n has changed mode for %t to %m")
(NICK . "%n (%u@%h) is now known as %N")
(NICK-you . "Your new nickname is %N")
- (PART . erc-message-english-PART)
+ (PART . #'erc-message-english-PART)
(PING . "PING from server (last: %s sec. ago)")
(PONG . "PONG from %h (%i second%s)")
(QUIT . "%n (%u@%h) has quit: %r")
@@ -7892,6 +9257,7 @@ All windows are opened in the current frame."
(s368 . "Banlist of %c ends.")
(s379 . "%c: Forwarded to %f")
(s391 . "The time at %s is %t")
+ (s396 . "Your visible host has changed to %s")
(s401 . "%n: No such nick/channel")
(s402 . "%c: No such server")
(s403 . "%c: No such channel")
@@ -7944,22 +9310,20 @@ functions."
(string-replace "%" "%%" reason))
"")))))
-
-(defvar-local erc-current-message-catalog 'english)
-
-(defun erc-retrieve-catalog-entry (entry &optional catalog)
- "Retrieve ENTRY from CATALOG.
-
-If CATALOG is nil, `erc-current-message-catalog' is used.
-
-If ENTRY is nil in CATALOG, it is retrieved from the fallback,
-english, catalog."
+(defun erc-retrieve-catalog-entry (key &optional catalog)
+ "Retrieve `format-spec' entry for symbol KEY in CATALOG.
+Without symbol CATALOG, use `erc-current-message-catalog'. If
+lookup fails, try the latter's `default-toplevel-value' if it's
+not the same as CATALOG. Failing that, try the `english' catalog
+if yet untried."
(unless catalog (setq catalog erc-current-message-catalog))
- (let ((var (erc-make-message-variable-name catalog entry)))
- (if (boundp var)
- (symbol-value var)
- (when (boundp (erc-make-message-variable-name 'english entry))
- (symbol-value (erc-make-message-variable-name 'english entry))))))
+ (symbol-value
+ (or (erc--make-message-variable-name catalog key 'softp)
+ (let ((default (default-toplevel-value 'erc-current-message-catalog)))
+ (or (and (not (eq default catalog))
+ (erc--make-message-variable-name default key 'softp))
+ (and (not (memq 'english (list default catalog)))
+ (erc--make-message-variable-name 'english key 'softp)))))))
(defun erc-format-message (msg &rest args)
"Format MSG according to ARGS.
@@ -8002,6 +9366,7 @@ See also `kill-buffer'."
:group 'erc-hooks
:type 'hook)
+;; FIXME alias and deprecate current *-function suffixed name.
(defun erc-kill-buffer-function ()
"Function to call when an ERC buffer is killed.
This function should be on `kill-buffer-hook'.
@@ -8015,11 +9380,27 @@ or `erc-kill-buffer-hook' if any other buffer."
(cond
((eq (erc-server-buffer) (current-buffer))
(run-hooks 'erc-kill-server-hook))
- ((erc-channel-p (or (erc-default-target) (buffer-name)))
+ ((erc--target-channel-p erc--target)
(run-hooks 'erc-kill-channel-hook))
(t
(run-hooks 'erc-kill-buffer-hook)))))
+(declare-function set-text-conversion-style "textconv.c")
+
+(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
+guarantee that the input method functions properly for the
+purpose of typing within the ERC prompt."
+ (when (and (eq major-mode 'erc-mode)
+ (fboundp 'set-text-conversion-style))
+ (if (>= (point) (erc-beg-of-input-line))
+ (unless (eq text-conversion-style 'action)
+ (set-text-conversion-style 'action))
+ (unless (not text-conversion-style)
+ (set-text-conversion-style nil)))))
+
(defun erc-kill-server ()
"Sends a QUIT command to the server when the server buffer is killed.
This function should be on `erc-kill-server-hook'."
@@ -8044,8 +9425,8 @@ This function should be on `erc-kill-channel-hook'."
(text-property-not-all (point-min) (point-max) 'erc-parsed nil))
(defun erc-restore-text-properties ()
- "Restore the property `erc-parsed' for the region."
- (when-let* ((parsed-posn (erc-find-parsed-property))
+ "Ensure the `erc-parsed' and `tags' props cover the entire message."
+ (when-let ((parsed-posn (erc-find-parsed-property))
(found (erc-get-parsed-vector parsed-posn)))
(put-text-property (point-min) (point-max) 'erc-parsed found)
(when-let ((tags (get-text-property parsed-posn 'tags)))
@@ -8074,7 +9455,7 @@ This function should be on `erc-kill-channel-hook'."
See also `erc-message-type'."
;; IRC numerics are three-digit numbers, possibly with leading 0s.
;; To invert: (if (numberp o) (format "%03d" o) (symbol-name o))
- (if-let* ((n (string-to-number command)) ((zerop n))) (intern command) n))
+ (if-let ((n (string-to-number command)) ((zerop n))) (intern command) n))
;; Teach url.el how to open irc:// URLs with ERC.
;; To activate, customize `url-irc-function' to `url-irc-erc'.
diff --git a/lisp/eshell/em-alias.el b/lisp/eshell/em-alias.el
index 841982c3425..832e14418d0 100644
--- a/lisp/eshell/em-alias.el
+++ b/lisp/eshell/em-alias.el
@@ -1,6 +1,6 @@
;;; em-alias.el --- creation and management of command aliases -*- lexical-binding:t -*-
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
;; Author: John Wiegley <johnw@gnu.org>
diff --git a/lisp/eshell/em-banner.el b/lisp/eshell/em-banner.el
index 2bee50b80a4..e6dcbb24475 100644
--- a/lisp/eshell/em-banner.el
+++ b/lisp/eshell/em-banner.el
@@ -1,6 +1,6 @@
;;; em-banner.el --- sample module that displays a login banner -*- lexical-binding:t -*-
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
;; Author: John Wiegley <johnw@gnu.org>
diff --git a/lisp/eshell/em-basic.el b/lisp/eshell/em-basic.el
index 016afe811b2..8f68a750bd7 100644
--- a/lisp/eshell/em-basic.el
+++ b/lisp/eshell/em-basic.el
@@ -1,6 +1,6 @@
;;; em-basic.el --- basic shell builtin commands -*- lexical-binding:t -*-
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
;; Author: John Wiegley <johnw@gnu.org>
@@ -188,6 +188,38 @@ or `eshell-printn' for display."
(put 'eshell/umask 'eshell-no-numeric-conversions t)
+(defun eshell/eshell-debug (&rest args)
+ "A command for toggling certain debug variables."
+ (eshell-eval-using-options
+ "eshell-debug" args
+ '((?h "help" nil nil "display this usage message")
+ :usage "[KIND]...
+This command is used to aid in debugging problems related to Eshell
+itself. It is not useful for anything else. The recognized `kinds'
+are:
+
+ error stops Eshell from trapping errors
+ form shows command form manipulation in `*eshell last cmd*'
+ process shows process events in `*eshell last cmd*'")
+ (if args
+ (dolist (kind args)
+ (if (equal kind "error")
+ (setq eshell-handle-errors (not eshell-handle-errors))
+ (let ((kind-sym (intern kind)))
+ (if (memq kind-sym eshell-debug-command)
+ (setq eshell-debug-command
+ (delq kind-sym eshell-debug-command))
+ (push kind-sym eshell-debug-command)))))
+ ;; Output the currently-enabled debug kinds.
+ (unless eshell-handle-errors
+ (eshell-print "errors\n"))
+ (dolist (kind eshell-debug-command)
+ (eshell-printn (symbol-name kind))))))
+
+(defun pcomplete/eshell-mode/eshell-debug ()
+ "Completion for the `debug' command."
+ (while (pcomplete-here '("error" "form" "process"))))
+
(provide 'em-basic)
;; Local Variables:
diff --git a/lisp/eshell/em-cmpl.el b/lisp/eshell/em-cmpl.el
index 732bbb3f1fa..201beb5071d 100644
--- a/lisp/eshell/em-cmpl.el
+++ b/lisp/eshell/em-cmpl.el
@@ -1,6 +1,6 @@
;;; em-cmpl.el --- completion using the TAB key -*- lexical-binding:t -*-
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
;; Author: John Wiegley <johnw@gnu.org>
@@ -148,6 +148,10 @@ to writing a completion function."
(eshell-cmpl--custom-variable-docstring 'pcomplete-dir-ignore)
:type (get 'pcomplete-dir-ignore 'custom-type))
+(defcustom eshell-cmpl-remote-file-ignore nil
+ (eshell-cmpl--custom-variable-docstring 'pcomplete-remote-file-ignore)
+ :type (get 'pcomplete-remote-file-ignore 'custom-type))
+
(defcustom eshell-cmpl-ignore-case (eshell-under-windows-p)
(eshell-cmpl--custom-variable-docstring 'completion-ignore-case)
:type (get 'completion-ignore-case 'custom-type))
@@ -248,6 +252,8 @@ to writing a completion function."
eshell-cmpl-file-ignore)
(setq-local pcomplete-dir-ignore
eshell-cmpl-dir-ignore)
+ (setq-local pcomplete-remote-file-ignore
+ eshell-cmpl-remote-file-ignore)
(setq-local completion-ignore-case
eshell-cmpl-ignore-case)
(setq-local pcomplete-autolist
@@ -325,10 +331,19 @@ to writing a completion function."
"Failed to evaluate argument form during completion: %S" arg)
(propertize "\0" 'eshell-argument-stub 'error))))
+;; Code stolen from `eshell-plain-command'.
+(defun eshell-external-command-p (command)
+ "Whether an external command shall be called."
+ (let* ((esym (eshell-find-alias-function command))
+ (sym (or esym (intern-soft command))))
+ (not (and sym (fboundp sym)
+ (or esym eshell-prefer-lisp-functions
+ (not (eshell-search-path command)))))))
+
(defun eshell-complete-parse-arguments ()
"Parse the command line arguments for `pcomplete-argument'."
(when (and eshell-no-completion-during-jobs
- (eshell-interactive-process-p))
+ eshell-foreground-command)
(eshell--pcomplete-insert-tab))
(let ((end (point-marker))
(begin (save-excursion (beginning-of-line) (point)))
@@ -362,7 +377,8 @@ to writing a completion function."
(throw 'pcompleted (elisp-completion-at-point)))
(t
(eshell--pcomplete-insert-tab)))))
- (when (get-text-property (1- end) 'comment)
+ (when (and (< begin end)
+ (get-text-property (1- end) 'comment))
(eshell--pcomplete-insert-tab))
(let ((pos (1- end)))
(while (>= pos begin)
@@ -406,6 +422,14 @@ to writing a completion function."
args posns)
(setq args (nreverse evaled-args)
posns (nreverse evaled-posns)))
+ ;; Determine, whether remote file names shall be completed. They
+ ;; shouldn't for external commands, or when in a pipe. Respect
+ ;; also `eshell-cmpl-remote-file-ignore', which could be set by
+ ;; the user.
+ (setq-local pcomplete-remote-file-ignore
+ (or eshell-cmpl-remote-file-ignore
+ eshell-in-pipeline-p ; does not work
+ (eshell-external-command-p (car args))))
;; Convert arguments to forms that Pcomplete can understand.
(cons (mapcar
(lambda (arg)
diff --git a/lisp/eshell/em-dirs.el b/lisp/eshell/em-dirs.el
index 640d3676750..cf90a8bb230 100644
--- a/lisp/eshell/em-dirs.el
+++ b/lisp/eshell/em-dirs.el
@@ -1,6 +1,6 @@
;;; em-dirs.el --- directory navigation commands -*- lexical-binding:t -*-
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
;; Author: John Wiegley <johnw@gnu.org>
@@ -253,26 +253,19 @@ Thus, this does not include the current directory.")
(throw 'eshell-replace-command
(eshell-parse-command "cd" (flatten-tree args)))))
-(defun eshell-expand-user-reference-1 (file)
+(defun eshell-expand-user-reference (file)
"Expand a user reference in FILE to its real directory name."
(replace-regexp-in-string
(rx bos (group "~" (*? anychar)) (or "/" eos))
#'expand-file-name file))
-(defun eshell-expand-user-reference (file)
- "Expand a user reference in FILE to its real directory name.
-FILE can be either a string or a list of strings to expand."
- ;; If the argument was a glob pattern, then FILE is a list, so
- ;; expand each element of the glob's resulting list.
- (if (listp file)
- (mapcar #'eshell-expand-user-reference-1 file)
- (eshell-expand-user-reference-1 file)))
-
(defun eshell-parse-user-reference ()
"An argument beginning with ~ is a filename to be expanded."
(when (and (not eshell-current-argument)
(eq (char-after) ?~))
- (add-to-list 'eshell-current-modifiers #'eshell-expand-user-reference)
+ ;; Apply this modifier fairly early so it happens before things
+ ;; like glob expansion.
+ (add-hook 'eshell-current-modifiers #'eshell-expand-user-reference -50)
(forward-char)
(char-to-string (char-before))))
diff --git a/lisp/eshell/em-elecslash.el b/lisp/eshell/em-elecslash.el
index 2b003f58dc7..93eadcfe1ff 100644
--- a/lisp/eshell/em-elecslash.el
+++ b/lisp/eshell/em-elecslash.el
@@ -1,6 +1,6 @@
;;; em-elecslash.el --- electric forward slashes -*- lexical-binding:t -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;; Author: Sean Whitton <spwhitton@spwhitton.name>
diff --git a/lisp/eshell/em-extpipe.el b/lisp/eshell/em-extpipe.el
index 5c9a0a85934..057eead9297 100644
--- a/lisp/eshell/em-extpipe.el
+++ b/lisp/eshell/em-extpipe.el
@@ -1,6 +1,6 @@
;;; em-extpipe.el --- external shell pipelines -*- lexical-binding:t -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;; Author: Sean Whitton <spwhitton@spwhitton.name>
@@ -118,86 +118,87 @@ as though it were Eshell syntax."
;; other members of `eshell-parse-argument-hook'. We must avoid
;; misinterpreting a quoted `*|', `*<' or `*>' as indicating an
;; external pipeline, hence the structure of the loop in `findbeg1'.
- (cl-flet
- ((findbeg1 (pat &optional go (bound (point-max)))
- (let* ((start (point))
- (result
- (catch 'found
- (while (> bound (point))
- (let* ((found
- (save-excursion
- (re-search-forward
- "\\(?:#?'\\|\"\\|\\\\\\)" bound t)))
- (next (or (and found (match-beginning 0))
- bound)))
- (if (re-search-forward pat next t)
- (throw 'found (match-beginning 1))
- (goto-char next)
- (while (eshell-extpipe--or-with-catch
- (eshell-parse-lisp-argument)
- (eshell-parse-backslash)
- (eshell-parse-double-quote)
- (eshell-parse-literal-quote)))
- ;; Guard against an infinite loop if none of
- ;; the parsers moved us forward.
- (unless (or (> (point) next) (eobp))
- (forward-char 1))))))))
- (goto-char (if (and result go) (match-end 0) start))
- result)))
- (unless (or eshell-current-argument eshell-current-quoted)
- (let ((beg (point)) end
- (next-marked (findbeg1 "\\(?:\\=\\|\\s-\\)\\(\\*[|<>]\\)"))
- (next-unmarked
- (or (findbeg1 "\\(?:\\=\\|[^*]\\|\\S-\\*\\)\\(|\\)")
- (point-max))))
- (when (and next-marked (> next-unmarked next-marked)
- (or (> next-marked (point))
- (looking-back "\\`\\|\\s-" nil)))
- ;; Skip to the final segment of the external pipeline.
- (while (findbeg1 "\\(?:\\=\\|\\s-\\)\\(\\*|\\)" t))
- ;; Find output redirections.
- (while (findbeg1
- "\\([0-9]?>+&?[0-9]?\\s-*\\S-\\)" t next-unmarked)
- ;; Is the output redirection Eshell-specific? We have our
- ;; own logic, rather than calling `eshell-parse-argument',
- ;; to avoid specifying here all the possible cars of
- ;; parsed special references -- `get-buffer-create' etc.
- (forward-char -1)
- (let ((this-end
- (save-match-data
- (cond ((looking-at "#<")
- (forward-char 1)
- (1+ (eshell-find-delimiter ?\< ?\>)))
- ((and (looking-at "/\\S-+")
- (assoc (match-string 0)
- eshell-virtual-targets))
- (match-end 0))))))
- (cond ((and this-end end)
- (goto-char this-end))
- (this-end
- (goto-char this-end)
- (setq end (match-beginning 0)))
- (t
- (setq end nil)))))
- ;; We've moved past all Eshell-specific output redirections
- ;; we could find. If there is only whitespace left, then
- ;; `end' is right before redirections we should exclude;
- ;; otherwise, we must include everything.
- (unless (and end (skip-syntax-forward "\s" next-unmarked)
- (= next-unmarked (point)))
- (setq end next-unmarked))
- (let ((cmd (string-trim
- (buffer-substring-no-properties beg end))))
- (goto-char end)
- ;; We must now drop the asterisks, unless quoted/escaped.
- (with-temp-buffer
- (insert cmd)
- (goto-char (point-min))
- (cl-loop
- for next = (findbeg1 "\\(?:\\=\\|\\s-\\)\\(\\*[|<>]\\)" t)
- while next do (forward-char -2) (delete-char 1))
- (eshell-finish-arg
- `(eshell-external-pipeline ,(buffer-string))))))))))
+ (unless eshell-current-argument-plain
+ (cl-flet
+ ((findbeg1 (pat &optional go (bound (point-max)))
+ (let* ((start (point))
+ (result
+ (catch 'found
+ (while (> bound (point))
+ (let* ((found
+ (save-excursion
+ (re-search-forward
+ "\\(?:#?'\\|\"\\|\\\\\\)" bound t)))
+ (next (or (and found (match-beginning 0))
+ bound)))
+ (if (re-search-forward pat next t)
+ (throw 'found (match-beginning 1))
+ (goto-char next)
+ (while (eshell-extpipe--or-with-catch
+ (eshell-parse-lisp-argument)
+ (eshell-parse-backslash)
+ (eshell-parse-double-quote)
+ (eshell-parse-literal-quote)))
+ ;; Guard against an infinite loop if none of
+ ;; the parsers moved us forward.
+ (unless (or (> (point) next) (eobp))
+ (forward-char 1))))))))
+ (goto-char (if (and result go) (match-end 0) start))
+ result)))
+ (unless (or eshell-current-argument eshell-current-quoted)
+ (let ((beg (point)) end
+ (next-marked (findbeg1 "\\(?:\\=\\|\\s-\\)\\(\\*[|<>]\\)"))
+ (next-unmarked
+ (or (findbeg1 "\\(?:\\=\\|[^*]\\|\\S-\\*\\)\\(|\\)")
+ (point-max))))
+ (when (and next-marked (> next-unmarked next-marked)
+ (or (> next-marked (point))
+ (looking-back "\\`\\|\\s-" nil)))
+ ;; Skip to the final segment of the external pipeline.
+ (while (findbeg1 "\\(?:\\=\\|\\s-\\)\\(\\*|\\)" t))
+ ;; Find output redirections.
+ (while (findbeg1
+ "\\([0-9]?>+&?[0-9]?\\s-*\\S-\\)" t next-unmarked)
+ ;; Is the output redirection Eshell-specific? We have our
+ ;; own logic, rather than calling `eshell-parse-argument',
+ ;; to avoid specifying here all the possible cars of
+ ;; parsed special references -- `get-buffer-create' etc.
+ (forward-char -1)
+ (let ((this-end
+ (save-match-data
+ (cond ((looking-at "#<")
+ (forward-char 1)
+ (1+ (eshell-find-delimiter ?\< ?\>)))
+ ((and (looking-at "/\\S-+")
+ (assoc (match-string 0)
+ eshell-virtual-targets))
+ (match-end 0))))))
+ (cond ((and this-end end)
+ (goto-char this-end))
+ (this-end
+ (goto-char this-end)
+ (setq end (match-beginning 0)))
+ (t
+ (setq end nil)))))
+ ;; We've moved past all Eshell-specific output redirections
+ ;; we could find. If there is only whitespace left, then
+ ;; `end' is right before redirections we should exclude;
+ ;; otherwise, we must include everything.
+ (unless (and end (skip-syntax-forward "\s" next-unmarked)
+ (= next-unmarked (point)))
+ (setq end next-unmarked))
+ (let ((cmd (string-trim
+ (buffer-substring-no-properties beg end))))
+ (goto-char end)
+ ;; We must now drop the asterisks, unless quoted/escaped.
+ (with-temp-buffer
+ (insert cmd)
+ (goto-char (point-min))
+ (cl-loop
+ for next = (findbeg1 "\\(?:\\=\\|\\s-\\)\\(\\*[|<>]\\)" t)
+ while next do (forward-char -2) (delete-char 1))
+ (eshell-finish-arg
+ `(eshell-external-pipeline ,(buffer-string)))))))))))
(defun eshell-rewrite-external-pipeline (terms)
"Rewrite an external pipeline in TERMS as parsed by
diff --git a/lisp/eshell/em-glob.el b/lisp/eshell/em-glob.el
index 1141b673e97..b0c3e6e7a11 100644
--- a/lisp/eshell/em-glob.el
+++ b/lisp/eshell/em-glob.el
@@ -1,6 +1,6 @@
;;; em-glob.el --- extended file name globbing -*- lexical-binding:t -*-
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
;; Author: John Wiegley <johnw@gnu.org>
@@ -156,8 +156,8 @@ This mimics the behavior of zsh if non-nil, but bash if nil."
(defun eshell-add-glob-modifier ()
"Add `eshell-extended-glob' to the argument modifier list."
(when eshell-glob-splice-results
- (add-to-list 'eshell-current-modifiers 'eshell-splice-args t))
- (add-to-list 'eshell-current-modifiers 'eshell-extended-glob))
+ (add-hook 'eshell-current-modifiers #'eshell-splice-args 99))
+ (add-hook 'eshell-current-modifiers #'eshell-extended-glob))
(defun eshell-parse-glob-chars ()
"Parse a globbing delimiter.
diff --git a/lisp/eshell/em-hist.el b/lisp/eshell/em-hist.el
index 79232d8e9b5..21029eae1bc 100644
--- a/lisp/eshell/em-hist.el
+++ b/lisp/eshell/em-hist.el
@@ -1,6 +1,6 @@
;;; em-hist.el --- history list management -*- lexical-binding:t -*-
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
;; Author: John Wiegley <johnw@gnu.org>
@@ -116,6 +116,12 @@ If set to t, history will always be saved, silently."
(const :tag "Ask" ask)
(const :tag "Always save" t)))
+(defcustom eshell-history-append nil
+ "If non-nil, append new entries to the history file when saving history."
+ :type '(choice (const :tag "Overwrite history file" nil)
+ (const :tag "Append new entries to file" t))
+ :version "30.1")
+
(defcustom eshell-input-filter 'eshell-input-filter-default
"Predicate for filtering additions to input history.
Takes one argument, the input. If non-nil, the input may be saved on
@@ -195,6 +201,9 @@ element, regardless of any text on the command line. In that case,
(defvar eshell-history-index nil)
(defvar eshell-matching-input-from-input-string "")
(defvar eshell-save-history-index nil)
+(defvar eshell-hist--new-items nil
+ "The number of new history items that have not been written to
+file. This variable is local in each eshell buffer.")
(defvar-keymap eshell-isearch-map
:doc "Keymap used in isearch in Eshell."
@@ -283,6 +292,7 @@ Returns nil if INPUT is prepended by blank space, otherwise non-nil."
(make-local-variable 'eshell-history-index)
(make-local-variable 'eshell-save-history-index)
+ (setq-local eshell-hist--new-items 0)
(if (minibuffer-window-active-p (selected-window))
(setq-local eshell-save-history-on-exit nil)
@@ -290,17 +300,21 @@ Returns nil if INPUT is prepended by blank space, otherwise non-nil."
(if eshell-history-file-name
(eshell-read-history nil t))
- (add-hook 'eshell-exit-hook #'eshell-write-history nil t))
+ (add-hook 'eshell-exit-hook #'eshell--save-history nil t))
(unless eshell-history-ring
(setq eshell-history-ring (make-ring eshell-history-size)))
- (add-hook 'eshell-exit-hook #'eshell-write-history nil t)
+ (add-hook 'eshell-exit-hook #'eshell--save-history nil t)
(add-hook 'kill-emacs-query-functions #'eshell-save-some-history)
(add-hook 'eshell-input-filter-functions #'eshell-add-to-history nil t))
+(defun eshell--save-history ()
+ "Save the history for current Eshell buffer."
+ (eshell-write-history nil eshell-history-append))
+
(defun eshell-save-some-history ()
"Save the history for any open Eshell buffers."
(dolist (buf (buffer-list))
@@ -314,7 +328,7 @@ Returns nil if INPUT is prepended by blank space, otherwise non-nil."
(format-message
"Save input history for Eshell buffer `%s'? "
(buffer-name buf)))))
- (eshell-write-history)))))
+ (eshell--save-history)))))
t)
(defun eshell/history (&rest args)
@@ -323,11 +337,11 @@ Returns nil if INPUT is prepended by blank space, otherwise non-nil."
(eshell-eval-using-options
"history" args
'((?r "read" nil read-history
- "read from history file to current history list")
+ "clear current history list and read from history file to it")
(?w "write" nil write-history
"write current history list to history file")
(?a "append" nil append-history
- "append current history list to history file")
+ "append new history in current buffer to history file")
(?h "help" nil nil "display this usage message")
:usage "[n] [-rwa [filename]]"
:post-usage
@@ -381,20 +395,21 @@ Input is entered into the input history ring, if the value of
variable `eshell-input-filter' returns non-nil when called on the
input."
(when (and (funcall eshell-input-filter input)
- (if (eq eshell-hist-ignoredups 'erase)
- ;; Remove any old occurrences of the input, and put
- ;; the new one at the end.
- (unless (ring-empty-p eshell-history-ring)
- (ring-remove eshell-history-ring
- (ring-member eshell-history-ring input))
- t)
- ;; Always add...
- (or (null eshell-hist-ignoredups)
- ;; ... or add if it's not already present at the
- ;; end.
- (not (ring-p eshell-history-ring))
- (ring-empty-p eshell-history-ring)
- (not (string-equal (eshell-get-history 0) input)))))
+ (pcase eshell-hist-ignoredups
+ ('nil t) ; Always add to history
+ ('erase ; Add, removing any old occurrences
+ (when-let ((old-index (ring-member eshell-history-ring input)))
+ ;; Remove the old occurrence of this input so we can
+ ;; add it to the end. FIXME: Should we try to
+ ;; remove multiple old occurrences, e.g. if the user
+ ;; recently changed to using `erase'?
+ (ring-remove eshell-history-ring old-index))
+ t)
+ (_ ; Add if not already the latest entry
+ (or (ring-empty-p eshell-history-ring)
+ (not (string-equal (eshell-get-history 0) input))))))
+ (setq eshell-hist--new-items
+ (min eshell-history-size (1+ eshell-hist--new-items)))
(eshell-put-history input))
(setq eshell-save-history-index eshell-history-index)
(setq eshell-history-index nil))
@@ -456,21 +471,30 @@ line, with the most recent command last. See also
(re-search-backward "^[ \t]*\\([^#\n].*\\)[ \t]*$"
nil t))
(let ((history (match-string 1)))
- (if (or (null ignore-dups)
- (ring-empty-p ring)
- (not (string-equal (ring-ref ring 0) history)))
- (ring-insert-at-beginning
- ring (subst-char-in-string ?\177 ?\n history))))
- (setq count (1+ count))))
+ (when (or (ring-empty-p ring)
+ (null ignore-dups)
+ (and (not (string-equal
+ (ring-ref ring (1- (ring-length ring)))
+ history))
+ (not (and (eq ignore-dups 'erase)
+ (ring-member ring history)))))
+ (ring-insert-at-beginning
+ ring (subst-char-in-string ?\177 ?\n history))
+ (setq count (1+ count))))))
(setq eshell-history-ring ring
- eshell-history-index nil))))))
+ eshell-history-index nil
+ eshell-hist--new-items 0))))))
(defun eshell-write-history (&optional filename append)
"Writes the buffer's `eshell-history-ring' to a history file.
-The name of the file is given by the variable
-`eshell-history-file-name'. The original contents of the file are
-lost if `eshell-history-ring' is not empty. If
-`eshell-history-file-name' is nil this function does nothing.
+If the optional argument FILENAME is nil, the value of
+`eshell-history-file-name' is used. This function does nothing
+if the value resolves to nil.
+
+If the optional argument APPEND is non-nil, then append new
+history items to the history file. Otherwise, overwrite the
+contents of the file with `eshell-history-ring' (so long as it is
+not empty).
Useful within process sentinels.
@@ -481,13 +505,14 @@ See also `eshell-read-history'."
((or (null file)
(equal file "")
(null eshell-history-ring)
- (ring-empty-p eshell-history-ring))
+ (ring-empty-p eshell-history-ring)
+ (and append (= eshell-hist--new-items 0)))
nil)
((not (file-writable-p resolved-file))
(message "Cannot write history file %s" resolved-file))
(t
(let* ((ring eshell-history-ring)
- (index (ring-length ring)))
+ (index (if append eshell-hist--new-items (ring-length ring))))
;; Write it all out into a buffer first. Much faster, but
;; messier, than writing it one line at a time.
(with-temp-buffer
@@ -500,7 +525,8 @@ See also `eshell-read-history'."
(subst-char-in-region start (1- (point)) ?\n ?\177)))
(eshell-with-private-file-modes
(write-region (point-min) (point-max) resolved-file append
- 'no-message))))))))
+ 'no-message)))
+ (setq eshell-hist--new-items 0))))))
(defun eshell-list-history ()
"List in help buffer the buffer's input history."
diff --git a/lisp/eshell/em-ls.el b/lisp/eshell/em-ls.el
index 9b53bf29559..fd89a9f778e 100644
--- a/lisp/eshell/em-ls.el
+++ b/lisp/eshell/em-ls.el
@@ -1,6 +1,6 @@
;;; em-ls.el --- implementation of ls in Lisp -*- lexical-binding:t -*-
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
;; Author: John Wiegley <johnw@gnu.org>
@@ -274,11 +274,7 @@ instead."
;; use the fancy highlighting in `eshell-ls' rather than font-lock
(when eshell-ls-use-colors
(font-lock-mode -1)
- (setq font-lock-defaults nil)
- (if (boundp 'font-lock-buffers)
- (setq font-lock-buffers
- (delq (current-buffer)
- (symbol-value 'font-lock-buffers)))))
+ (setq font-lock-defaults nil))
(require 'em-glob)
(let* ((insert-func 'insert)
(error-func 'insert)
diff --git a/lisp/eshell/em-pred.el b/lisp/eshell/em-pred.el
index 1d67f1af990..c3997dc72c3 100644
--- a/lisp/eshell/em-pred.el
+++ b/lisp/eshell/em-pred.el
@@ -1,6 +1,6 @@
;;; em-pred.el --- argument predicates and modifiers (ala zsh) -*- lexical-binding:t -*-
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
;; Author: John Wiegley <johnw@gnu.org>
@@ -302,24 +302,14 @@ This function is specially for adding onto `eshell-parse-argument-hook'."
(preds (car modifiers))
(mods (cdr modifiers)))
(when (or preds mods)
- ;; Has to go at the end, which is only natural since
+ ;; Has to go near the end (but before
+ ;; `eshell-splice-args'), which is only natural since
;; syntactically it can only occur at the end.
- (setq eshell-current-modifiers
- (append
- eshell-current-modifiers
- (list
- (lambda (lst)
- (eshell-apply-modifiers
- lst preds mods modifier-string)))))
- (when (memq 'eshell-splice-args eshell-current-modifiers)
- ;; If splicing results, ensure that
- ;; `eshell-splice-args' is the last modifier.
- ;; Eshell's command parsing can't handle it anywhere
- ;; else.
- (setq eshell-current-modifiers
- (append (delq 'eshell-splice-args
- eshell-current-modifiers)
- (list 'eshell-splice-args)))))))
+ (add-hook 'eshell-current-modifiers
+ (lambda (lst)
+ (eshell-apply-modifiers
+ lst preds mods modifier-string))
+ 90))))
(goto-char (1+ end))
(eshell-finish-arg))))))
diff --git a/lisp/eshell/em-prompt.el b/lisp/eshell/em-prompt.el
index 42f8f273b52..3662c1fa895 100644
--- a/lisp/eshell/em-prompt.el
+++ b/lisp/eshell/em-prompt.el
@@ -1,6 +1,6 @@
;;; em-prompt.el --- command prompts -*- lexical-binding:t -*-
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
;; Author: John Wiegley <johnw@gnu.org>
@@ -50,22 +50,18 @@ as is common with most shells."
(defcustom eshell-prompt-function
(lambda ()
(concat (abbreviate-file-name (eshell/pwd))
+ (unless (eshell-exit-success-p)
+ (format " [%d]" eshell-last-command-status))
(if (= (file-user-uid) 0) " # " " $ ")))
- "A function that returns the Eshell prompt string.
-Make sure to update `eshell-prompt-regexp' so that it will match your
-prompt."
+ "A function that returns the Eshell prompt string."
:type 'function
:group 'eshell-prompt)
(defcustom eshell-prompt-regexp "^[^#$\n]* [#$] "
- "A regexp which fully matches your Eshell prompt.
-This is useful for navigating by paragraph using \
-\\[forward-paragraph] and \\[backward-paragraph].
-
-If this variable is changed, all Eshell buffers must be exited
-and re-entered for it to take effect."
+ "A regexp which fully matches your Eshell prompt."
:type 'regexp
:group 'eshell-prompt)
+(make-obsolete-variable 'eshell-prompt-regexp nil "30.1")
(defcustom eshell-highlight-prompt t
"If non-nil, Eshell should highlight the prompt."
@@ -98,8 +94,10 @@ arriving, or after."
:group 'eshell-prompt)
(defvar-keymap eshell-prompt-mode-map
- "C-c C-n" #'eshell-next-prompt
- "C-c C-p" #'eshell-previous-prompt)
+ "C-c C-n" #'eshell-next-prompt
+ "C-c C-p" #'eshell-previous-prompt
+ "<remap> <forward-paragraph>" #'eshell-forward-paragraph
+ "<remap> <backward-paragraph>" #'eshell-backward-paragraph)
(defvar-keymap eshell-prompt-repeat-map
:doc "Keymap to repeat eshell-prompt key sequences. Used in `repeat-mode'."
@@ -119,11 +117,6 @@ arriving, or after."
"Initialize the prompting code."
(unless eshell-non-interactive-p
(add-hook 'eshell-post-command-hook 'eshell-emit-prompt nil t)
-
- (make-local-variable 'eshell-prompt-regexp)
- (if eshell-prompt-regexp
- (setq-local paragraph-start eshell-prompt-regexp))
-
(eshell-prompt-mode)))
(defun eshell-emit-prompt ()
@@ -172,16 +165,41 @@ negative, find the Nth next match."
(interactive (eshell-regexp-arg "Backward input matching (regexp): "))
(eshell-forward-matching-input regexp (- arg)))
-(defun eshell-next-prompt (n)
+(defun eshell-forward-paragraph (&optional n)
+ "Move to the beginning of the Nth next prompt in the buffer.
+Like `forward-paragraph', but navigates using fields."
+ (interactive "p")
+ (eshell-next-prompt n)
+ (goto-char (field-beginning (point) t)))
+
+(defun eshell-backward-paragraph (&optional n)
+ "Move to the beginning of the Nth previous prompt in the buffer.
+Like `backward-paragraph', but navigates using fields."
+ (interactive "p")
+ (eshell-previous-prompt n)
+ (goto-char (field-beginning (point) t)))
+
+(defun eshell-next-prompt (&optional n)
"Move to end of Nth next prompt in the buffer."
(interactive "p")
+ (unless n (setq n 1))
+ ;; First, move point to our starting position: the end of the
+ ;; current prompt (aka the beginning of the input), if any. (The
+ ;; welcome message and output from commands don't count as having a
+ ;; current prompt.)
+ (pcase (get-text-property (point) 'field)
+ ('command-output)
+ ('prompt (goto-char (field-end)))
+ (_ (when-let ((match (text-property-search-backward 'field 'prompt t)))
+ (goto-char (prop-match-end match)))))
+ ;; Now, move forward/backward to our destination prompt.
(if (natnump n)
(while (and (> n 0)
(text-property-search-forward 'field 'prompt t))
(setq n (1- n)))
(let (match this-match)
- ;; Don't count the current prompt.
- (text-property-search-backward 'field 'prompt t)
+ ;; Go to the beginning of the current prompt.
+ (goto-char (field-beginning (point) t))
(while (and (< n 0)
(setq this-match (text-property-search-backward
'field 'prompt t)))
@@ -190,10 +208,10 @@ negative, find the Nth next match."
(when match
(goto-char (prop-match-end match))))))
-(defun eshell-previous-prompt (n)
+(defun eshell-previous-prompt (&optional n)
"Move to end of Nth previous prompt in the buffer."
(interactive "p")
- (eshell-next-prompt (- n)))
+ (eshell-next-prompt (- (or n 1))))
(defun eshell-skip-prompt ()
"Skip past the text matching regexp `eshell-prompt-regexp'.
diff --git a/lisp/eshell/em-rebind.el b/lisp/eshell/em-rebind.el
index e4579497edc..c6ee1a329b6 100644
--- a/lisp/eshell/em-rebind.el
+++ b/lisp/eshell/em-rebind.el
@@ -1,6 +1,6 @@
;;; em-rebind.el --- rebind keys when point is at current input -*- lexical-binding:t -*-
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
;; Author: John Wiegley <johnw@gnu.org>
diff --git a/lisp/eshell/em-script.el b/lisp/eshell/em-script.el
index 55a05076342..066063c4cc2 100644
--- a/lisp/eshell/em-script.el
+++ b/lisp/eshell/em-script.el
@@ -1,6 +1,6 @@
;;; em-script.el --- Eshell script files -*- lexical-binding:t -*-
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
;; Author: John Wiegley <johnw@gnu.org>
@@ -89,26 +89,18 @@ This includes when running `eshell-command'."
(defun eshell-source-file (file &optional args subcommand-p)
"Execute a series of Eshell commands in FILE, passing ARGS.
Comments begin with `#'."
- (let ((orig (point))
- (here (point-max)))
- (goto-char (point-max))
- (with-silent-modifications
- ;; FIXME: Why not use a temporary buffer and avoid this
- ;; "insert&delete" business? --Stef
- (insert-file-contents file)
- (goto-char (point-max))
- (throw 'eshell-replace-command
- (prog1
- (list 'let
- (list (list 'eshell-command-name (list 'quote file))
- (list 'eshell-command-arguments
- (list 'quote args)))
- (let ((cmd (eshell-parse-command (cons here (point)))))
- (if subcommand-p
- (setq cmd (list 'eshell-as-subcommand cmd)))
- cmd))
- (delete-region here (point))
- (goto-char orig))))))
+ (let ((cmd (eshell-parse-command `(:file . ,file))))
+ (when subcommand-p
+ (setq cmd `(eshell-as-subcommand ,cmd)))
+ (throw 'eshell-replace-command
+ `(let ((eshell-command-name ',file)
+ (eshell-command-arguments ',args)
+ ;; Don't print subjob messages by default.
+ ;; Otherwise, if this function was called as a
+ ;; subjob, then *all* commands in the script would
+ ;; print start/stop messages.
+ (eshell-subjob-messages nil))
+ ,cmd))))
(defun eshell/source (&rest args)
"Source a file in a subshell environment."
diff --git a/lisp/eshell/em-smart.el b/lisp/eshell/em-smart.el
index d5002a59d14..91fe02e5545 100644
--- a/lisp/eshell/em-smart.el
+++ b/lisp/eshell/em-smart.el
@@ -1,6 +1,6 @@
;;; em-smart.el --- smart display of output -*- lexical-binding:t -*-
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
;; Author: John Wiegley <johnw@gnu.org>
@@ -95,7 +95,7 @@ it to get a real sense of how it works."
(list
(lambda ()
(remove-hook 'window-configuration-change-hook
- 'eshell-refresh-windows)))
+ 'eshell-smart-scroll)))
"A hook that gets run when `eshell-smart' is unloaded."
:type 'hook
:group 'eshell-smart)
@@ -159,9 +159,7 @@ The options are `begin', `after' or `end'."
;;; Internal Variables:
-(defvar eshell-smart-displayed nil)
(defvar eshell-smart-command-done nil)
-(defvar eshell-currently-handling-window nil)
;;; Functions:
@@ -174,10 +172,9 @@ The options are `begin', `after' or `end'."
(setq-local eshell-scroll-to-bottom-on-input nil)
(setq-local eshell-scroll-show-maximum-output t)
- (add-hook 'window-scroll-functions 'eshell-smart-scroll-window nil t)
- (add-hook 'window-configuration-change-hook 'eshell-refresh-windows)
+ (add-hook 'window-configuration-change-hook 'eshell-smart-scroll nil t)
- (add-hook 'eshell-output-filter-functions 'eshell-refresh-windows t t)
+ (add-hook 'eshell-output-filter-functions 'eshell-smart-scroll-windows 90 t)
(add-hook 'after-change-functions 'eshell-disable-after-change nil t)
@@ -193,28 +190,15 @@ The options are `begin', `after' or `end'."
(add-hook 'eshell-post-command-hook
'eshell-smart-maybe-jump-to-end nil t))))
-;; This is called by window-scroll-functions with two arguments.
-(defun eshell-smart-scroll-window (wind _start)
- "Scroll the given Eshell window WIND accordingly."
- (unless eshell-currently-handling-window
- (let ((eshell-currently-handling-window t))
- (with-selected-window wind
- (eshell-smart-redisplay)))))
-
-(defun eshell-refresh-windows (&optional frame)
- "Refresh all visible Eshell buffers."
- (let (affected)
- (walk-windows
- (lambda (wind)
- (with-current-buffer (window-buffer wind)
- (if eshell-mode
- (let (window-scroll-functions) ;;FIXME: Why?
- (eshell-smart-scroll-window wind (window-start))
- (setq affected t)))))
- 0 frame)
- (if affected
- (let (window-scroll-functions) ;;FIXME: Why?
- (redisplay)))))
+(defun eshell-smart-scroll-windows ()
+ "Scroll all eshell windows to display as much output as possible, smartly."
+ (walk-windows
+ (lambda (wind)
+ (with-current-buffer (window-buffer wind)
+ (if eshell-mode
+ (with-selected-window wind
+ (eshell-smart-scroll)))))
+ 0 t))
(defun eshell-smart-display-setup ()
"Set the point to somewhere in the beginning of the last command."
@@ -231,8 +215,7 @@ The options are `begin', `after' or `end'."
(t
(error "Invalid value for `eshell-where-to-jump'")))
(setq eshell-smart-command-done nil)
- (add-hook 'pre-command-hook 'eshell-smart-display-move nil t)
- (eshell-refresh-windows))
+ (add-hook 'pre-command-hook 'eshell-smart-display-move nil t))
;; Called from after-change-functions with 3 arguments.
(defun eshell-disable-after-change (_b _e _l)
@@ -254,28 +237,22 @@ and the end of the buffer are still visible."
(goto-char (point-max))
(remove-hook 'pre-command-hook 'eshell-smart-display-move t)))
-(defun eshell-smart-redisplay ()
- "Display as much output as possible, smartly."
- (if (eobp)
+(defun eshell-smart-scroll ()
+ "Scroll WINDOW to display as much output as possible, smartly."
+ (let ((top-point (point)))
+ (and (memq 'eshell-smart-display-move pre-command-hook)
+ (>= (point) eshell-last-input-start)
+ (< (point) eshell-last-input-end)
+ (set-window-start (selected-window)
+ (pos-bol) t))
+ (when (pos-visible-in-window-p (point-max) (selected-window))
(save-excursion
- (recenter -1)
- ;; trigger the redisplay now, so that we catch any attempted
- ;; point motion; this is to cover for a redisplay bug
- (redisplay))
- (let ((top-point (point)))
- (and (memq 'eshell-smart-display-move pre-command-hook)
- (>= (point) eshell-last-input-start)
- (< (point) eshell-last-input-end)
- (set-window-start (selected-window)
- (line-beginning-position) t))
- (if (pos-visible-in-window-p (point-max))
- (save-excursion
- (goto-char (point-max))
- (recenter -1)
- (unless (pos-visible-in-window-p top-point)
- (goto-char top-point)
- (set-window-start (selected-window)
- (line-beginning-position) t)))))))
+ (goto-char (point-max))
+ (recenter -1)
+ (unless (pos-visible-in-window-p top-point (selected-window))
+ (goto-char top-point)
+ (set-window-start (selected-window)
+ (pos-bol) t))))))
(defun eshell-smart-goto-end ()
"Like `end-of-buffer', but do not push a mark."
@@ -294,7 +271,7 @@ and the end of the buffer are still visible."
((eq this-command 'self-insert-command)
(if (eq last-command-event ? )
(if (and eshell-smart-space-goes-to-end
- eshell-current-command)
+ eshell-foreground-command)
(if (not (pos-visible-in-window-p (point-max)))
(setq this-command 'scroll-up)
(setq this-command 'eshell-smart-goto-end))
@@ -323,7 +300,7 @@ and the end of the buffer are still visible."
(remove-hook 'pre-command-hook 'eshell-smart-display-move t))))
(defun em-smart-unload-hook ()
- (remove-hook 'window-configuration-change-hook #'eshell-refresh-windows))
+ (remove-hook 'window-configuration-change-hook #'eshell-smart-scroll))
(provide 'em-smart)
diff --git a/lisp/eshell/em-term.el b/lisp/eshell/em-term.el
index 3f76c349a7e..8f29e2d8509 100644
--- a/lisp/eshell/em-term.el
+++ b/lisp/eshell/em-term.el
@@ -1,6 +1,6 @@
;;; em-term.el --- running visual commands -*- lexical-binding:t -*-
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
;; Author: John Wiegley <johnw@gnu.org>
diff --git a/lisp/eshell/em-tramp.el b/lisp/eshell/em-tramp.el
index 94eb9797033..90f9c6cf78d 100644
--- a/lisp/eshell/em-tramp.el
+++ b/lisp/eshell/em-tramp.el
@@ -1,6 +1,6 @@
;;; em-tramp.el --- Eshell features that require Tramp -*- lexical-binding:t -*-
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
;; Author: Aidan Gauland <aidalgol@no8wireless.co.nz>
diff --git a/lisp/eshell/em-unix.el b/lisp/eshell/em-unix.el
index 509b2d31819..75afaf1c104 100644
--- a/lisp/eshell/em-unix.el
+++ b/lisp/eshell/em-unix.el
@@ -1,6 +1,6 @@
;;; em-unix.el --- UNIX command aliases -*- lexical-binding:t -*-
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
;; Author: John Wiegley <johnw@gnu.org>
@@ -92,7 +92,7 @@ Otherwise, `rmdir' is required."
:group 'eshell-unix)
(define-widget 'eshell-interactive-query 'radio
- "When to interatively query the user about a particular operation.
+ "When to interactively query the user about a particular operation.
If t, always query. If nil, never query. If `root', query when
the user is logged in as root (including when `default-directory'
is remote with a root user)."
diff --git a/lisp/eshell/em-xtra.el b/lisp/eshell/em-xtra.el
index 45c3ea3c0fc..a62073e2183 100644
--- a/lisp/eshell/em-xtra.el
+++ b/lisp/eshell/em-xtra.el
@@ -1,6 +1,6 @@
;;; em-xtra.el --- extra alias functions -*- lexical-binding:t -*-
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
;; Author: John Wiegley <johnw@gnu.org>
diff --git a/lisp/eshell/esh-arg.el b/lisp/eshell/esh-arg.el
index 26be1127880..1880cc03885 100644
--- a/lisp/eshell/esh-arg.el
+++ b/lisp/eshell/esh-arg.el
@@ -1,6 +1,6 @@
;;; esh-arg.el --- argument processing -*- lexical-binding:t -*-
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
;; Author: John Wiegley <johnw@gnu.org>
@@ -49,6 +49,8 @@ yield the values intended."
(defvar eshell-arg-listified nil)
(defvar eshell-nested-argument nil)
(defvar eshell-current-quoted nil)
+(defvar eshell-current-argument-plain nil
+ "If non-nil, the current argument is \"plain\", and not part of a command.")
(defvar eshell-inside-quote-regexp nil)
(defvar eshell-outside-quote-regexp nil)
@@ -163,6 +165,43 @@ treated as a literal character."
:type 'hook
:group 'eshell-arg)
+(defvar eshell-special-ref-alist
+ '(("buffer"
+ (creation-function eshell-get-buffer)
+ (insertion-function eshell-insert-buffer-name)
+ (completion-function eshell-complete-buffer-ref))
+ ("marker"
+ (creation-function eshell-get-marker)
+ (insertion-function eshell-insert-marker)
+ (completion-function eshell-complete-marker-ref)))
+ "Alist of special reference types for Eshell.
+Each entry is a list of the form (TYPE (KEY VALUE)...). TYPE is
+the name of the special reference type, and each KEY/VALUE pair
+represents a parameter for the type. Eshell defines the
+following KEYs:
+
+* `creation-function'
+ A function taking any number of arguments that returns the Lisp
+ object for this special ref type.
+
+* `insertion-function'
+ An interactive function that returns the special reference in
+ string form. This string should look like \"#<TYPE ARG...>\";
+ Eshell will pass the ARGs to `creation-function'.
+
+* `completion-function'
+ A function using Pcomplete to perform completion on any
+ arguments necessary for creating this special reference type.")
+
+(defcustom eshell-special-ref-default "buffer"
+ "The default type for special references when the type keyword is omitted.
+This should be a key in `eshell-special-ref-alist' (which see).
+Eshell will expand special refs like \"#<ARG...>\" into
+\"#<`eshell-special-ref-default' ARG...>\"."
+ :version "30.1"
+ :type 'string
+ :group 'eshell-arg)
+
(defvar-keymap eshell-arg-mode-map
"C-c M-b" #'eshell-insert-buffer-name)
@@ -184,11 +223,6 @@ treated as a literal character."
(add-hook 'pcomplete-try-first-hook
#'eshell-complete-special-reference nil t)))
-(defun eshell-insert-buffer-name (buffer-name)
- "Insert BUFFER-NAME into the current buffer at point."
- (interactive "BName of buffer: ")
- (insert-and-inherit "#<buffer " buffer-name ">"))
-
(defsubst eshell-escape-arg (string)
"Return STRING with the `escaped' property on it."
(if (stringp string)
@@ -293,10 +327,13 @@ then the result will be:
(append (list 'eshell-concat eshell-current-quoted)
eshell-current-argument)))
(setq eshell-arg-listified nil))
- (while eshell-current-modifiers
+ (when eshell-current-modifiers
+ (eshell-debug-command 'form
+ "applying modifiers %S\n\n%s" eshell-current-modifiers
+ (eshell-stringify eshell-current-argument)))
+ (dolist (modifier eshell-current-modifiers)
(setq eshell-current-argument
- (list (car eshell-current-modifiers) eshell-current-argument)
- eshell-current-modifiers (cdr eshell-current-modifiers))))
+ (list modifier eshell-current-argument))))
(setq eshell-current-modifiers nil))
(defun eshell-finish-arg (&rest arguments)
@@ -502,42 +539,6 @@ leaves point where it was."
(goto-char bound)
(apply #'concat (nreverse strings))))))
-(defun eshell-parse-special-reference ()
- "Parse a special syntax reference, of the form `#<args>'.
-
-args := `type' `whitespace' `arbitrary-args' | `arbitrary-args'
-type := \"buffer\" or \"process\"
-arbitrary-args := any string of characters.
-
-If the form has no `type', the syntax is parsed as if `type' were
-\"buffer\"."
- (when (and (not eshell-current-argument)
- (not eshell-current-quoted)
- (looking-at (rx "#<" (? (group (or "buffer" "process"))
- space))))
- (let ((here (point)))
- (goto-char (match-end 0)) ;; Go to the end of the match.
- (let ((buffer-p (if (match-beginning 1)
- (equal (match-string 1) "buffer")
- t)) ; With no type keyword, assume we want a buffer.
- (end (eshell-find-delimiter ?\< ?\>)))
- (when (not end)
- (when (match-beginning 1)
- (goto-char (match-beginning 1)))
- (throw 'eshell-incomplete "#<"))
- (if (eshell-arg-delimiter (1+ end))
- (prog1
- (list (if buffer-p #'get-buffer-create #'get-process)
- ;; FIXME: We should probably parse this as a
- ;; real Eshell argument so that we get the
- ;; benefits of quoting, variable-expansion, etc.
- (string-trim-right
- (replace-regexp-in-string
- (rx "\\" (group anychar)) "\\1"
- (buffer-substring-no-properties (point) end))))
- (goto-char (1+ end)))
- (ignore (goto-char here)))))))
-
(defun eshell-parse-delimiter ()
"Parse an argument delimiter, which is essentially a command operator."
;; this `eshell-operator' keyword gets parsed out by
@@ -588,41 +589,158 @@ If no argument requested a splice, return nil."
(when splicep
grouped-args)))
-;;;_* Special ref completion
+;;; Special references
+
+(defsubst eshell--special-ref-function (type function)
+ "Get the specified FUNCTION for a particular special ref TYPE.
+If TYPE is nil, get the FUNCTION for the `eshell-special-ref-default'."
+ (cadr (assq function (assoc (or type eshell-special-ref-default)
+ eshell-special-ref-alist))))
+
+(defun eshell-parse-special-reference ()
+ "Parse a special syntax reference, of the form `#<args>'.
+
+args := `type' `whitespace' `arbitrary-args' | `arbitrary-args'
+type := one of the keys in `eshell-special-ref-alist'
+arbitrary-args := any number of Eshell arguments
+
+If the form has no `type', the syntax is parsed as if `type' were
+`eshell-special-ref-default'."
+ (let ((here (point))
+ (special-ref-types (mapcar #'car eshell-special-ref-alist)))
+ (when (and (not eshell-current-argument)
+ (not eshell-current-quoted)
+ (looking-at (rx-to-string
+ `(seq "#<" (? (group (or ,@special-ref-types))
+ (+ space)))
+ t)))
+ (goto-char (match-end 0)) ; Go to the end of the match.
+ (let ((end (eshell-find-delimiter ?\< ?\>))
+ (creation-fun (eshell--special-ref-function
+ (match-string 1) 'creation-function)))
+ (unless end
+ (when (match-beginning 1)
+ (goto-char (match-beginning 1)))
+ (throw 'eshell-incomplete "#<"))
+ (if (eshell-arg-delimiter (1+ end))
+ (prog1
+ (cons creation-fun
+ (let ((eshell-current-argument-plain t))
+ (eshell-parse-arguments (point) end)))
+ (goto-char (1+ end)))
+ (ignore (goto-char here)))))))
+
+(defun eshell-insert-special-reference (type &rest args)
+ "Insert a special reference of the specified TYPE.
+ARGS is a list of arguments to pass to the insertion function for
+TYPE (see `eshell-special-ref-alist')."
+ (interactive
+ (let* ((type (completing-read
+ (format-prompt "Type" eshell-special-ref-default)
+ (mapcar #'car eshell-special-ref-alist)
+ nil 'require-match nil nil eshell-special-ref-default))
+ (insertion-fun (eshell--special-ref-function
+ type 'insertion-function)))
+ (list :interactive (call-interactively insertion-fun))))
+ (if (eq type :interactive)
+ (car args)
+ (apply (eshell--special-ref-function type 'insertion-function) args)))
(defun eshell-complete-special-reference ()
"If there is a special reference, complete it."
- (let ((arg (pcomplete-actual-arg)))
- (when (string-match
- (rx string-start
- "#<" (? (group (or "buffer" "process")) space)
- (group (* anychar))
- string-end)
- arg)
- (let ((all-results (if (equal (match-string 1 arg) "process")
- (mapcar #'process-name (process-list))
- (mapcar #'buffer-name (buffer-list))))
- (saw-type (match-beginning 1)))
- (unless saw-type
- ;; Include the special reference types as completion options.
- (setq all-results (append '("buffer" "process") all-results)))
- (setq pcomplete-stub (replace-regexp-in-string
- (rx "\\" (group anychar)) "\\1"
- (substring arg (match-beginning 2))))
- ;; When finished with completion, add a trailing ">" (unless
- ;; we just completed the initial "buffer" or "process"
- ;; keyword).
- (add-function
- :before (var pcomplete-exit-function)
- (lambda (value status)
- (when (and (eq status 'finished)
- (or saw-type
- (not (member value '("buffer" "process")))))
- (if (looking-at ">")
- (goto-char (match-end 0))
- (insert ">")))))
- (throw 'pcomplete-completions
- (all-completions pcomplete-stub all-results))))))
+ (when (string-prefix-p "#<" (pcomplete-actual-arg))
+ (let ((special-ref-types (mapcar #'car eshell-special-ref-alist))
+ num-args explicit-type)
+ ;; When finished with completion, add a trailing ">" when
+ ;; appropriate.
+ (add-function
+ :around (var pcomplete-exit-function)
+ (lambda (oldfun value status)
+ (when (eq status 'finished)
+ ;; Don't count the special reference type (e.g. "buffer").
+ (when (or explicit-type
+ (and (= num-args 1)
+ (member value special-ref-types)))
+ (setq num-args (1- num-args)))
+ (let ((creation-fun (eshell--special-ref-function
+ explicit-type 'creation-function)))
+ ;; Check if we already have the maximum number of
+ ;; arguments for this special ref type. If so, finish
+ ;; the ref with ">". Otherwise, insert a space and set
+ ;; the completion status to `sole'.
+ (if (eq (cdr (func-arity creation-fun)) num-args)
+ (if (looking-at ">")
+ (goto-char (match-end 0))
+ (insert ">"))
+ (pcomplete-default-exit-function value status)
+ (setq status 'sole))
+ (funcall oldfun value status)))))
+ ;; Parse the arguments to this special reference and call the
+ ;; appropriate completion function.
+ (save-excursion
+ (eshell-with-temp-command (cons (+ 2 (pcomplete-begin)) (point))
+ (goto-char (point-max))
+ (let (pcomplete-args pcomplete-last pcomplete-index pcomplete-begins)
+ (when (let ((eshell-current-argument-plain t))
+ (pcomplete-parse-arguments
+ pcomplete-expand-before-complete))
+ (setq num-args (length pcomplete-args))
+ (if (= pcomplete-index pcomplete-last)
+ ;; Call the default special ref completion function,
+ ;; and also add the known special ref types as
+ ;; possible completions.
+ (throw 'pcomplete-completions
+ (nconc
+ (mapcar #'car eshell-special-ref-alist)
+ (catch 'pcomplete-completions
+ (funcall (eshell--special-ref-function
+ nil 'completion-function)))))
+ ;; Get the special ref type and call its completion
+ ;; function.
+ (let ((first (pcomplete-arg 'first)))
+ (when (member first special-ref-types)
+ ;; "Complete" the ref type (which we already
+ ;; completed above).
+ (pcomplete-here)
+ (setq explicit-type first)))
+ (funcall (eshell--special-ref-function
+ explicit-type 'completion-function))))))))))
+
+(defun eshell-get-buffer (buffer-or-name)
+ "Return the buffer specified by BUFFER-OR-NAME, creating a new one if needed.
+This is equivalent to `get-buffer-create', but only accepts a
+single argument."
+ (get-buffer-create buffer-or-name))
+
+(defun eshell-insert-buffer-name (buffer-name)
+ "Insert BUFFER-NAME into the current buffer at point."
+ (interactive "BName of buffer: ")
+ (insert-and-inherit "#<buffer " (eshell-quote-argument buffer-name) ">"))
+
+(defun eshell-complete-buffer-ref ()
+ "Perform completion for buffer references."
+ (pcomplete-here (mapcar #'buffer-name (buffer-list))))
+
+(defun eshell-get-marker (position buffer-or-name)
+ "Return the marker for character number POSITION in BUFFER-OR-NAME.
+BUFFER-OR-NAME can be a buffer or a string. If a string and a
+live buffer with that name exists, use that buffer. If no such
+buffer exists, create a new buffer with that name and use it."
+ (let ((marker (make-marker)))
+ (set-marker marker (string-to-number position)
+ (get-buffer-create buffer-or-name))))
+
+(defun eshell-insert-marker (position buffer-name)
+ "Insert a marker into the current buffer at point.
+This marker will point to POSITION in BUFFER-NAME."
+ (interactive "nPosition: \nBName of buffer: ")
+ (insert-and-inherit "#<marker " (number-to-string position) " "
+ (eshell-quote-argument buffer-name) ">"))
+
+(defun eshell-complete-marker-ref ()
+ "Perform completion for marker references."
+ (pcomplete-here)
+ (pcomplete-here (mapcar #'buffer-name (buffer-list))))
(provide 'esh-arg)
;;; esh-arg.el ends here
diff --git a/lisp/eshell/esh-cmd.el b/lisp/eshell/esh-cmd.el
index 80066263396..2746800ea78 100644
--- a/lisp/eshell/esh-cmd.el
+++ b/lisp/eshell/esh-cmd.el
@@ -1,6 +1,6 @@
;;; esh-cmd.el --- command invocation -*- lexical-binding:t -*-
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
;; Author: John Wiegley <johnw@gnu.org>
@@ -237,17 +237,6 @@ return non-nil if the command is complex."
:version "24.1" ; removed eshell-cmd-initialize
:type 'hook)
-(defcustom eshell-debug-command nil
- "If non-nil, enable Eshell debugging code.
-This is slow, and only useful for debugging problems with Eshell.
-If you change this without using customize after Eshell has loaded,
-you must re-load `esh-cmd.el'."
- :initialize 'custom-initialize-default
- :set (lambda (symbol value)
- (set symbol value)
- (load "esh-cmd"))
- :type 'boolean)
-
(defcustom eshell-deferrable-commands
'(eshell-named-command
eshell-lisp-command
@@ -274,7 +263,24 @@ command line.")
;;; Internal Variables:
-(defvar eshell-current-command nil)
+;; These variables have been merged into `eshell-foreground-command'.
+;; Outside of this file, the most-common use for them is to check
+;; whether they're nil.
+(define-obsolete-variable-alias 'eshell-last-async-procs
+ 'eshell-foreground-command "30.1")
+(define-obsolete-variable-alias 'eshell-current-command
+ 'eshell-foreground-command "30.1")
+
+(defvar eshell-foreground-command nil
+ "The currently-running foreground command, if any.
+This is a list of the form (FORM PROCESSES). FORM is the Eshell
+command form. PROCESSES is a list of processes that deferred the
+command.")
+(defvar eshell-background-commands nil
+ "A list of currently-running deferred commands.
+Each element is of the form (FORM PROCESSES), as with
+`eshell-foreground-command' (which see).")
+
(defvar eshell-command-name nil)
(defvar eshell-command-arguments nil)
(defvar eshell-in-pipeline-p nil
@@ -284,14 +290,6 @@ otherwise t.")
(defvar eshell-in-subcommand-p nil)
(defvar eshell-last-arguments nil)
(defvar eshell-last-command-name nil)
-(defvar eshell-last-async-procs nil
- "The currently-running foreground process(es).
-When executing a pipeline, this is a cons cell whose CAR is the
-first process (usually reading from stdin) and whose CDR is the
-last process (usually writing to stdout). Otherwise, the CAR and
-CDR are the same process.
-
-When the process in the CDR completes, resume command evaluation.")
(defvar eshell-allow-commands t
"If non-nil, allow evaluating command forms (including Lisp forms).
@@ -308,42 +306,32 @@ also `eshell-complete-parse-arguments'.")
(defsubst eshell-interactive-process-p ()
"Return non-nil if there is a currently running command process."
- eshell-last-async-procs)
+ (declare (obsolete 'eshell-foreground-command "30.1"))
+ eshell-foreground-command)
(defsubst eshell-head-process ()
"Return the currently running process at the head of any pipeline.
This only returns external (non-Lisp) processes."
- (car-safe eshell-last-async-procs))
+ (caadr eshell-foreground-command))
(defsubst eshell-tail-process ()
"Return the currently running process at the tail of any pipeline.
This only returns external (non-Lisp) processes."
- (cdr-safe eshell-last-async-procs))
+ (car (last (cadr eshell-foreground-command))))
(define-obsolete-function-alias 'eshell-interactive-process
'eshell-tail-process "29.1")
(defun eshell-cmd-initialize () ;Called from `eshell-mode' via intern-soft!
"Initialize the Eshell command processing module."
- (setq-local eshell-current-command nil)
+ (setq-local eshell-foreground-command nil)
+ (setq-local eshell-background-commands nil)
(setq-local eshell-command-name nil)
(setq-local eshell-command-arguments nil)
(setq-local eshell-last-arguments nil)
(setq-local eshell-last-command-name nil)
- (setq-local eshell-last-async-procs nil)
(add-hook 'eshell-kill-hook #'eshell-resume-command nil t)
-
- ;; make sure that if a command is over, and no process is being
- ;; waited for, that `eshell-current-command' is set to nil. This
- ;; situation can occur, for example, if a Lisp function results in
- ;; `debug' being called, and the user then types \\[top-level]
- (add-hook 'eshell-post-command-hook
- (lambda ()
- (setq eshell-current-command nil
- eshell-last-async-procs nil))
- nil t)
-
(add-hook 'eshell-parse-argument-hook
#'eshell-parse-subcommand-argument nil t)
(add-hook 'eshell-parse-argument-hook
@@ -362,50 +350,62 @@ This only returns external (non-Lisp) processes."
(throw 'pcomplete-completions
(all-completions pcomplete-stub obarray 'boundp)))))
-;; Command parsing
+;; Current command management
+
+(defun eshell-add-command (form &optional background)
+ "Add a command FORM to our list of known commands and return the new entry.
+If non-nil, BACKGROUND indicates that this is a command running
+in the background. The result is a command entry in the
+form (BACKGROUND FORM PROCESSES), where PROCESSES is initially
+nil."
+ (cons (when background 'background)
+ (if background
+ (car (push (list form nil) eshell-background-commands))
+ (cl-assert (null eshell-foreground-command))
+ (setq eshell-foreground-command (list form nil)))))
+
+(defun eshell-remove-command (command)
+ "Remove COMMAND from our list of known commands.
+COMMAND should be a list of the form (BACKGROUND FORM PROCESSES),
+as returned by `eshell-add-command' (which see)."
+ (let ((background (car command))
+ (entry (cdr command)))
+ (if background
+ (setq eshell-background-commands
+ (delq entry eshell-background-commands))
+ (cl-assert (eq eshell-foreground-command entry))
+ (setq eshell-foreground-command nil))))
+
+(defun eshell-commands-for-process (process)
+ "Return all commands associated with a PROCESS.
+Each element will have the form (BACKGROUND FORM PROCESSES), as
+returned by `eshell-add-command' (which see).
+
+Usually, there should only be one element in this list, but it's
+theoretically possible to have more than one associated command
+for a given process."
+ (nconc (when (memq process (cadr eshell-foreground-command))
+ (list (cons nil eshell-foreground-command)))
+ (seq-keep (lambda (cmd)
+ (when (memq process (cadr cmd))
+ (cons 'background cmd)))
+ eshell-background-commands)))
-(defmacro eshell-with-temp-command (region &rest body)
- "Narrow the buffer to REGION and execute the forms in BODY.
-
-REGION is a cons cell (START . END) that specifies the region to
-which to narrow the buffer. REGION can also be a string, in
-which case the macro temporarily inserts it into the buffer at
-point, and narrows the buffer to the inserted string. Before
-executing BODY, point is set to the beginning of the narrowed
-REGION.
-
-The value returned is the last form in BODY."
- (declare (indent 1))
- `(let ((reg ,region))
- (if (stringp reg)
- ;; Since parsing relies partly on buffer-local state
- ;; (e.g. that of `eshell-parse-argument-hook'), we need to
- ;; perform the parsing in the Eshell buffer.
- (let ((begin (point)) end)
- (with-silent-modifications
- (insert reg)
- (setq end (point))
- (unwind-protect
- (save-restriction
- (narrow-to-region begin end)
- (goto-char begin)
- ,@body)
- (delete-region begin end))))
- (save-restriction
- (narrow-to-region (car reg) (cdr reg))
- (goto-char (car reg))
- ,@body))))
+;; Command parsing
(defun eshell-parse-command (command &optional args toplevel)
"Parse the COMMAND, adding ARGS if given.
-COMMAND can either be a string, or a cons cell demarcating a buffer
-region. TOPLEVEL, if non-nil, means that the outermost command (the
-user's input command) is being parsed, and that pre and post command
-hooks should be run before and after the command."
+COMMAND can be a string, a cons cell (START . END) demarcating a
+buffer region, or (:file . FILENAME) to parse the contents of
+FILENAME.
+
+TOPLEVEL, if non-nil, means that the outermost command (the
+user's input command) is being parsed, and that pre and post
+command hooks should be run before and after the command."
(pcase-let*
((terms
(append
- (if (consp command)
+ (if (eshell--region-p command)
(eshell-parse-arguments (car command) (cdr command))
(eshell-with-temp-command command
(goto-char (point-max))
@@ -418,8 +418,6 @@ hooks should be run before and after the command."
(lambda (cmd)
(let ((sep (pop sep-terms)))
(setq cmd (eshell-parse-pipeline cmd))
- (when (equal sep "&")
- (setq cmd `(eshell-do-subjob (cons :eshell-background ,cmd))))
(unless eshell-in-pipeline-p
(setq cmd `(eshell-trap-errors ,cmd)))
;; Copy I/O handles so each full statement can manipulate
@@ -427,31 +425,22 @@ hooks should be run before and after the command."
;; command in the list; we won't use the originals again
;; anyway.
(setq cmd `(eshell-with-copied-handles ,cmd ,(not sep)))
+ (when (equal sep "&")
+ (setq cmd `(eshell-do-subjob ,cmd)))
cmd))
sub-chains)))
(if toplevel
`(eshell-commands (progn
(run-hooks 'eshell-pre-command-hook)
- (catch 'top-level (progn ,@commands))
- (run-hooks 'eshell-post-command-hook)))
+ (unwind-protect
+ (progn ,@commands)
+ (run-hooks 'eshell-post-command-hook))))
(macroexp-progn commands))))
-(defun eshell-debug-command (tag subform)
- "Output a debugging message to `*eshell last cmd*'."
- (let ((buf (get-buffer-create "*eshell last cmd*"))
- (text (eshell-stringify eshell-current-command)))
- (with-current-buffer buf
- (if (not tag)
- (erase-buffer)
- (insert "\n\C-l\n" tag "\n\n" text
- (if subform
- (concat "\n\n" (eshell-stringify subform)) ""))))))
-
(defun eshell-debug-show-parsed-args (terms)
"Display parsed arguments in the debug buffer."
- (ignore
- (if eshell-debug-command
- (eshell-debug-command "parsed arguments" terms))))
+ (ignore (eshell-debug-command 'form
+ "parsed arguments\n\n%s" (eshell-stringify terms))))
(defun eshell-no-command-conversion (terms)
"Don't convert the command argument."
@@ -762,10 +751,13 @@ if none)."
(defmacro eshell-do-subjob (object)
"Evaluate a command OBJECT as a subjob.
-We indicate that the process was run in the background by returning it
-ensconced in a list."
- `(let ((eshell-current-subjob-p t))
- ,object))
+We indicate that the process was run in the background by
+returning it as (:eshell-background . PROCESSES)."
+ `(let ((eshell-current-subjob-p t)
+ ;; Print subjob messages. This could have been cleared
+ ;; (e.g. by `eshell-source-file', which see).
+ (eshell-subjob-messages t))
+ (eshell-resume-eval (eshell-add-command ',object 'background))))
(defmacro eshell-commands (object &optional silent)
"Place a valid set of handles, and context, around command OBJECT."
@@ -784,15 +776,14 @@ to this hook using `nconc', and *not* `add-hook'.
Someday, when Scheme will become the dominant Emacs language, all of
this grossness will be made to disappear by using `call/cc'..."
- `(let ((eshell-this-command-hook '(ignore)))
- (eshell-condition-case err
- (prog1
- ,object
- (mapc #'funcall eshell-this-command-hook))
- (error
- (mapc #'funcall eshell-this-command-hook)
- (eshell-errorn (error-message-string err))
- (eshell-close-handles 1)))))
+ `(eshell-condition-case err
+ (let ((eshell-this-command-hook '(ignore)))
+ (unwind-protect
+ ,object
+ (mapc #'funcall eshell-this-command-hook)))
+ (error
+ (eshell-errorn (error-message-string err))
+ (eshell-close-handles 1))))
(defvar eshell-output-handle) ;Defined in esh-io.el.
(defvar eshell-error-handle) ;Defined in esh-io.el.
@@ -814,89 +805,83 @@ current ones (see `eshell-duplicate-handles')."
(eshell-protect-handles eshell-current-handles)
,object))
+(defun eshell--unmark-deferrable (command)
+ "If COMMAND is (or ends with) a deferrable command, unmark it as such.
+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*', "
+ (let ((cmd command))
+ (when (memq (car cmd) '(let progn))
+ (setq cmd (car (last cmd))))
+ (when (memq (car cmd) eshell-deferrable-commands)
+ (setcar cmd (intern-soft
+ (concat (symbol-name (car cmd)) "*"))))
+ command))
+
(defmacro eshell-do-pipelines (pipeline &optional notfirst)
"Execute the commands in PIPELINE, connecting each to one another.
+Returns a list of the processes in the pipeline.
+
This macro calls itself recursively, with NOTFIRST non-nil."
(when (setq pipeline (cadr pipeline))
+ (eshell--unmark-deferrable (car pipeline))
`(eshell-with-copied-handles
- (progn
- ,(when (cdr pipeline)
- `(let ((nextproc
- (eshell-do-pipelines (quote ,(cdr pipeline)) t)))
- (eshell-set-output-handle ,eshell-output-handle
- 'append nextproc)))
- ,(let ((head (car pipeline)))
- (if (memq (car head) '(let progn))
- (setq head (car (last head))))
- (when (memq (car head) eshell-deferrable-commands)
- (ignore
- (setcar head
- (intern-soft
- (concat (symbol-name (car head)) "*"))))))
- ;; First and last elements in a pipeline may need special treatment.
- ;; (Currently only eshell-ls-files uses 'last.)
- ;; Affects process-connection-type in eshell-gather-process-output.
- (let ((eshell-in-pipeline-p
- ,(cond ((not notfirst) (quote 'first))
- ((cdr pipeline) t)
- (t (quote 'last)))))
- (let ((proc ,(car pipeline)))
- (set headproc (or proc (symbol-value headproc)))
- (set tailproc (or (symbol-value tailproc) proc))
- proc)))
+ (let ((next-procs
+ ,(when (cdr pipeline)
+ `(eshell-do-pipelines (quote ,(cdr pipeline)) t)))
+ ;; First and last elements in a pipeline may need special
+ ;; treatment (currently only `eshell-ls-files' uses
+ ;; `last'). Affects `process-connection-type' in
+ ;; `eshell-gather-process-output'.
+ (eshell-in-pipeline-p
+ ,(cond ((not notfirst) (quote 'first))
+ ((cdr pipeline) t)
+ (t (quote 'last)))))
+ ,(when (cdr pipeline)
+ `(eshell-set-output-handle ,eshell-output-handle
+ 'append (car next-procs)))
+ (let ((proc ,(car pipeline)))
+ (cons proc next-procs)))
;; Steal handles if this is the last item in the pipeline.
,(null (cdr pipeline)))))
(defmacro eshell-do-pipelines-synchronously (pipeline)
"Execute the commands in PIPELINE in sequence synchronously.
-Output of each command is passed as input to the next one in the pipeline.
-This is used on systems where async subprocesses are not supported."
+This collects the output of each command in turn, passing it as
+input to the next one in the pipeline. Returns the result of the
+first command invocation in the pipeline (usually t or nil).
+
+This is used on systems where async subprocesses are not
+supported."
(when (setq pipeline (cadr pipeline))
- `(progn
+ ;; FIXME: is deferrable significant here?
+ (eshell--unmark-deferrable (car pipeline))
+ `(prog1
+ (eshell-with-copied-handles
+ (progn
+ ,(when (cdr pipeline)
+ `(let ((output-marker ,(point-marker)))
+ (eshell-set-output-handle ,eshell-output-handle
+ 'append output-marker)))
+ (let (;; XXX: `eshell-in-pipeline-p' has a different
+ ;; meaning for synchronous processes: it's non-nil
+ ;; only when piping *to* a process.
+ (eshell-in-pipeline-p ,(and (cdr pipeline) t)))
+ ,(car pipeline)))
+ ;; Steal handles if this is the last item in the pipeline.
+ ,(null (cdr pipeline)))
,(when (cdr pipeline)
- `(let ((output-marker ,(point-marker)))
- (eshell-set-output-handle ,eshell-output-handle
- 'append output-marker)))
- ,(let ((head (car pipeline)))
- (if (memq (car head) '(let progn))
- (setq head (car (last head))))
- ;; FIXME: is deferrable significant here?
- (when (memq (car head) eshell-deferrable-commands)
- (ignore
- (setcar head
- (intern-soft
- (concat (symbol-name (car head)) "*"))))))
- ;; The last process in the pipe should get its handles
- ;; redirected as we found them before running the pipe.
- ,(if (null (cdr pipeline))
- '(progn
- (setq eshell-current-handles tail-handles)
- (setq eshell-in-pipeline-p nil)))
- (let ((result ,(car pipeline)))
- ;; tailproc gets the result of the last successful process in
- ;; the pipeline.
- (set tailproc (or result (symbol-value tailproc)))
- ,(if (cdr pipeline)
- `(eshell-do-pipelines-synchronously (quote ,(cdr pipeline))))
- result))))
+ `(eshell-do-pipelines-synchronously (quote ,(cdr pipeline)))))))
(defalias 'eshell-process-identity 'identity)
(defmacro eshell-execute-pipeline (pipeline)
"Execute the commands in PIPELINE, connecting each to one another."
- `(let ((eshell-in-pipeline-p t)
- (headproc (make-symbol "headproc"))
- (tailproc (make-symbol "tailproc")))
- (set headproc nil)
- (set tailproc nil)
- (progn
- ,(if eshell-supports-asynchronous-processes
- `(eshell-do-pipelines ,pipeline)
- `(let ((tail-handles (eshell-duplicate-handles
- eshell-current-handles)))
- (eshell-do-pipelines-synchronously ,pipeline)))
- (eshell-process-identity (cons (symbol-value headproc)
- (symbol-value tailproc))))))
+ `(eshell-process-identity
+ ,(if eshell-supports-asynchronous-processes
+ `(remove nil (eshell-do-pipelines ,pipeline))
+ `(eshell-do-pipelines-synchronously ,pipeline))))
(defmacro eshell-as-subcommand (command)
"Execute COMMAND as a subcommand.
@@ -942,38 +927,6 @@ This avoids the need to use `let*'."
;; finishes, it will resume the evaluation using the remainder of the
;; command tree.
-(defun eshell/eshell-debug (&rest args)
- "A command for toggling certain debug variables."
- (ignore
- (cond
- ((not args)
- (if eshell-handle-errors
- (eshell-print "errors\n"))
- (if eshell-debug-command
- (eshell-print "commands\n")))
- ((member (car args) '("-h" "--help"))
- (eshell-print "usage: eshell-debug [kinds]
-
-This command is used to aid in debugging problems related to Eshell
-itself. It is not useful for anything else. The recognized `kinds'
-at the moment are:
-
- errors stops Eshell from trapping errors
- commands shows command execution progress in `*eshell last cmd*'
-"))
- (t
- (while args
- (cond
- ((string= (car args) "errors")
- (setq eshell-handle-errors (not eshell-handle-errors)))
- ((string= (car args) "commands")
- (setq eshell-debug-command (not eshell-debug-command))))
- (setq args (cdr args)))))))
-
-(defun pcomplete/eshell-mode/eshell-debug ()
- "Completion for the `debug' command."
- (while (pcomplete-here '("errors" "commands"))))
-
(iter-defun eshell--find-subcommands (haystack)
"Recursively search for subcommand forms in HAYSTACK.
This yields the SUBCOMMANDs when found in forms like
@@ -1038,67 +991,89 @@ Return the process (or head and tail processes) created by
COMMAND, if any. If COMMAND is a background command, return the
process(es) in a cons cell like:
- (:eshell-background . PROCESS)"
- (if eshell-current-command
- ;; We can just stick the new command at the end of the current
- ;; one, and everything will happen as it should.
- (setcdr (last (cdr eshell-current-command))
- (list `(let ((here (and (eobp) (point))))
- ,(and input
- `(insert-and-inherit ,(concat input "\n")))
- (if here
- (eshell-update-markers here))
- (eshell-do-eval ',command))))
- (and eshell-debug-command
- (with-current-buffer (get-buffer-create "*eshell last cmd*")
- (erase-buffer)
- (insert "command: \"" input "\"\n")))
- (setq eshell-current-command command)
+ (:eshell-background . PROCESSES)"
+ (if eshell-foreground-command
+ (progn
+ ;; We can just stick the new command at the end of the current
+ ;; one, and everything will happen as it should.
+ (setcdr (last (cdar eshell-foreground-command))
+ (list `(let ((here (and (eobp) (point))))
+ ,(and input
+ `(insert-and-inherit ,(concat input "\n")))
+ (if here
+ (eshell-update-markers here))
+ (eshell-do-eval ',command))))
+ (eshell-debug-command 'form
+ "enqueued command form for %S\n\n%s"
+ (or input "<no string>")
+ (eshell-stringify (car eshell-foreground-command))))
+ (eshell-debug-command-start input)
(let* (result
(delim (catch 'eshell-incomplete
- (ignore (setq result (eshell-resume-eval))))))
+ (ignore (setq result (eshell-resume-eval
+ (eshell-add-command command)))))))
(when delim
(error "Unmatched delimiter: %S" delim))
result)))
(defun eshell-resume-command (proc status)
- "Resume the current command when a process ends."
+ "Resume the current command when a pipeline ends.
+PROC is the process that invoked this from its sentinel, and
+STATUS is its status."
(when proc
- (unless (or (not (stringp status))
- (string= "stopped" status)
- (string-match eshell-reset-signals status))
- (if (eq proc (eshell-tail-process))
- (eshell-resume-eval)))))
-
-(defun eshell-resume-eval ()
- "Destructively evaluate a form which may need to be deferred."
+ (dolist (command (eshell-commands-for-process proc))
+ (unless (seq-some #'eshell-process-active-p (nth 2 command))
+ (setf (nth 2 command) nil) ; Clear processes from command.
+ (if (and ;; Check STATUS to determine whether we want to resume or
+ ;; abort the command.
+ (stringp status)
+ (not (string= "stopped" status))
+ (not (string-match eshell-reset-signals status)))
+ (eshell-resume-eval command)
+ (eshell-remove-command command)
+ (declare-function eshell-reset "esh-mode" (&optional no-hooks))
+ (eshell-reset))))))
+
+(defun eshell-resume-eval (command)
+ "Destructively evaluate a COMMAND which may need to be deferred.
+COMMAND is a command entry of the form (BACKGROUND FORM
+PROCESSES) (see `eshell-add-command').
+
+Return the result of COMMAND's FORM if it wasn't deferred. If
+BACKGROUND is non-nil and Eshell defers COMMAND, return a list of
+the form (:eshell-background . PROCESSES)."
(eshell-condition-case err
- (progn
- (setq eshell-last-async-procs nil)
- (when eshell-current-command
- (let* (retval
- (procs (catch 'eshell-defer
- (ignore
- (setq retval
- (eshell-do-eval
- eshell-current-command))))))
- (if (eshell-process-pair-p procs)
- (ignore (setq eshell-last-async-procs procs))
- (cadr retval)))))
+ (let (retval procs)
+ (unwind-protect
+ (progn
+ (setq procs
+ (catch 'eshell-defer
+ (ignore (setq retval (eshell-do-eval (cadr command))))))
+ (cond
+ (retval (cadr retval))
+ ((car command) (cons :eshell-background procs))))
+ (if procs
+ (setf (nth 2 command) procs)
+ ;; If we didn't defer this command, clear it out. This
+ ;; applies both when the command has finished normally,
+ ;; and when a signal or thrown value causes us to unwind.
+ (eshell-remove-command command))))
(error
(error (error-message-string err)))))
-(defmacro eshell-manipulate (tag &rest commands)
- "Manipulate a COMMAND form, with TAG as a debug identifier."
- (declare (indent 1))
- ;; Check `bound'ness since at compile time the code until here has not
- ;; executed yet.
- (if (not (and (boundp 'eshell-debug-command) eshell-debug-command))
- `(progn ,@commands)
- `(progn
- (eshell-debug-command ,(eval tag) form)
- ,@commands
- (eshell-debug-command ,(concat "done " (eval tag)) form))))
+(defmacro eshell-manipulate (form tag &rest body)
+ "Manipulate a command FORM with BODY, using TAG as a debug identifier."
+ (declare (indent 2))
+ (let ((tag-symbol (make-symbol "tag")))
+ `(if (not (memq 'form eshell-debug-command))
+ (progn ,@body)
+ (let ((,tag-symbol ,tag))
+ (eshell-always-debug-command 'form
+ "%s\n\n%s" ,tag-symbol (eshell-stringify ,form))
+ (unwind-protect
+ (progn ,@body)
+ (eshell-always-debug-command 'form
+ "done %s\n\n%s" ,tag-symbol (eshell-stringify ,form)))))))
(defun eshell-do-eval (form &optional synchronous-p)
"Evaluate FORM, simplifying it as we go.
@@ -1125,8 +1100,8 @@ have been replaced by constants."
;; we can modify any `let' forms to evaluate only once.
(if (macrop (car form))
(let ((exp (copy-tree (macroexpand form))))
- (eshell-manipulate (format-message "expanding macro `%s'"
- (symbol-name (car form)))
+ (eshell-manipulate form
+ (format-message "expanding macro `%s'" (symbol-name (car form)))
(setcar form (car exp))
(setcdr form (cdr exp)))))
(let ((args (cdr form)))
@@ -1138,7 +1113,7 @@ have been replaced by constants."
(let ((new-form (copy-tree `(let ((eshell--command-body nil)
(eshell--test-body nil))
(eshell--wrapped-while ,@args)))))
- (eshell-manipulate "modifying while form"
+ (eshell-manipulate form "modifying while form"
(setcar form (car new-form))
(setcdr form (cdr new-form)))
(eshell-do-eval form synchronous-p)))
@@ -1161,17 +1136,22 @@ have been replaced by constants."
(setq eshell--command-body nil
eshell--test-body (copy-tree (car args)))))
((eq (car form) 'if)
- (eshell-manipulate "evaluating if condition"
- (setcar args (eshell-do-eval (car args) synchronous-p)))
- (eshell-do-eval
- (cond
- ((eval (car args)) ; COND is non-nil
- (cadr args))
- ((cdddr args) ; Multiple ELSE forms
- `(progn ,@(cddr args)))
- (t ; Zero or one ELSE forms
- (caddr args)))
- synchronous-p))
+ (eshell-manipulate form "evaluating if condition"
+ ;; Evaluate the condition and replace our `if' form with
+ ;; THEN or ELSE as appropriate.
+ (let ((new-form
+ (cond
+ ((cadr (eshell-do-eval (car args) synchronous-p))
+ (cadr args)) ; COND is non-nil
+ ((cdddr args)
+ `(progn ,@(cddr args))) ; Multiple ELSE forms
+ (t
+ (caddr args))))) ; Zero or one ELSE forms
+ (unless (consp new-form)
+ (setq new-form (cons 'progn new-form)))
+ (setcar form (car new-form))
+ (setcdr form (cdr new-form))))
+ (eshell-do-eval form synchronous-p))
((eq (car form) 'setcar)
(setcar (cdr args) (eshell-do-eval (cadr args) synchronous-p))
(eval form))
@@ -1180,7 +1160,7 @@ have been replaced by constants."
(eval form))
((eq (car form) 'let)
(unless (eq (car-safe (cadr args)) 'eshell-do-eval)
- (eshell-manipulate "evaluating let args"
+ (eshell-manipulate form "evaluating let args"
(dolist (letarg (car args))
(when (and (listp letarg)
(not (eq (cadr letarg) 'quote)))
@@ -1207,7 +1187,7 @@ have been replaced by constants."
;; the let-bindings' values so that those values are
;; correct when we resume evaluation of this form.
(when deferred
- (eshell-manipulate "rebinding let args after `eshell-defer'"
+ (eshell-manipulate form "rebinding let args after `eshell-defer'"
(let ((bindings (car args)))
(while bindings
(let ((binding (if (consp (car bindings))
@@ -1221,30 +1201,50 @@ have been replaced by constants."
;; If we get here, there was no `eshell-defer' thrown, so
;; just return the `let' body's result.
result)))
- ((memq (car form) '(catch condition-case unwind-protect))
- ;; `condition-case' and `unwind-protect' have to be
- ;; handled specially, because we only want to call
- ;; `eshell-do-eval' on their first form.
+ ((memq (car form) '(catch condition-case))
+ ;; `catch' and `condition-case' have to be handled specially,
+ ;; because we only want to call `eshell-do-eval' on their
+ ;; second forms.
;;
;; NOTE: This requires obedience by all forms which this
;; function might encounter, that they do not contain
;; other special forms.
- (unless (eq (car form) 'unwind-protect)
- (setq args (cdr args)))
+ (setq args (cdr args))
(unless (eq (caar args) 'eshell-do-eval)
- (eshell-manipulate "handling special form"
+ (eshell-manipulate form "handling special form"
(setcar args `(eshell-do-eval ',(car args) ,synchronous-p))))
(eval form))
+ ((eq (car form) 'unwind-protect)
+ ;; `unwind-protect' has to be handled specially, because we
+ ;; only want to call `eshell-do-eval' on its first form, and
+ ;; we need to ensure we let `eshell-defer' through without
+ ;; evaluating the unwind forms.
+ (let (deferred)
+ (unwind-protect
+ (eshell-manipulate form "handling `unwind-protect' body form"
+ (setq deferred
+ (catch 'eshell-defer
+ (ignore
+ (setcar args (eshell-do-eval
+ (car args) synchronous-p)))))
+ (car args))
+ (if deferred
+ (throw 'eshell-defer deferred)
+ (eshell-manipulate form "handling `unwind-protect' unwind forms"
+ (pop args)
+ (while args
+ (setcar args (eshell-do-eval (car args) synchronous-p))
+ (pop args)))))))
((eq (car form) 'setq)
(if (cddr args) (error "Unsupported form (setq X1 E1 X2 E2..)"))
- (eshell-manipulate "evaluating arguments to setq"
+ (eshell-manipulate form "evaluating arguments to setq"
(setcar (cdr args) (eshell-do-eval (cadr args) synchronous-p)))
(list 'quote (eval form)))
(t
(if (and args (not (memq (car form) '(run-hooks))))
- (eshell-manipulate
+ (eshell-manipulate form
(format-message "evaluating arguments to `%s'"
- (symbol-name (car form)))
+ (car form))
(while args
(setcar args (eshell-do-eval (car args) synchronous-p))
(setq args (cdr args)))))
@@ -1283,16 +1283,15 @@ have been replaced by constants."
(setq result (eval form))))))
(if new-form
(progn
- (eshell-manipulate "substituting replacement form"
+ (eshell-manipulate form "substituting replacement form"
(setcar form (car new-form))
(setcdr form (cdr new-form)))
(eshell-do-eval form synchronous-p))
(if-let (((memq (car form) eshell-deferrable-commands))
- ((not eshell-current-subjob-p))
- (procs (eshell-make-process-pair result)))
+ (procs (eshell-make-process-list result)))
(if synchronous-p
- (eshell/wait (cdr procs))
- (eshell-manipulate "inserting ignore form"
+ (apply #'eshell/wait procs)
+ (eshell-manipulate form "inserting ignore form"
(setcar form 'ignore)
(setcdr form nil))
(throw 'eshell-defer procs))
@@ -1341,16 +1340,24 @@ have been replaced by constants."
COMMAND may result in an alias being executed, or a plain command."
(unless eshell-allow-commands
(signal 'eshell-commands-forbidden '(named)))
+ ;; Strip off any leading nil values. This can only happen if a
+ ;; variable evaluates to nil, such as "$var x", where `var' is nil.
+ ;; In that case, the command name becomes `x', for compatibility
+ ;; with most regular shells (the difference is that they do an
+ ;; interpolation pass before the argument parsing pass, but Eshell
+ ;; does both at the same time).
+ (while (and (not command) args)
+ (setq command (pop args)))
(setq eshell-last-arguments args
- eshell-last-command-name (eshell-stringify command))
+ eshell-last-command-name (eshell-stringify command))
(run-hook-with-args 'eshell-prepare-command-hook)
(cl-assert (stringp eshell-last-command-name))
- (if eshell-last-command-name
- (or (run-hook-with-args-until-success
- 'eshell-named-command-hook eshell-last-command-name
- eshell-last-arguments)
- (eshell-plain-command eshell-last-command-name
- eshell-last-arguments))))
+ (when eshell-last-command-name
+ (or (run-hook-with-args-until-success
+ 'eshell-named-command-hook eshell-last-command-name
+ eshell-last-arguments)
+ (eshell-plain-command eshell-last-command-name
+ eshell-last-arguments))))
(defalias 'eshell-named-command* 'eshell-named-command)
diff --git a/lisp/eshell/esh-ext.el b/lisp/eshell/esh-ext.el
index 38579d7ef1c..dc2b93e574b 100644
--- a/lisp/eshell/esh-ext.el
+++ b/lisp/eshell/esh-ext.el
@@ -1,6 +1,6 @@
;;; esh-ext.el --- commands external to Eshell -*- lexical-binding:t -*-
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
;; Author: John Wiegley <johnw@gnu.org>
diff --git a/lisp/eshell/esh-io.el b/lisp/eshell/esh-io.el
index c9d87c650d5..4487389bf26 100644
--- a/lisp/eshell/esh-io.el
+++ b/lisp/eshell/esh-io.el
@@ -1,6 +1,6 @@
;;; esh-io.el --- I/O management -*- lexical-binding:t -*-
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
;; Author: John Wiegley <johnw@gnu.org>
@@ -170,7 +170,7 @@ describing the mode, e.g. for using with `eshell-get-target'.")
(defvar eshell-current-handles nil)
-(defvar eshell-last-command-status 0
+(defvar-local eshell-last-command-status 0
"The exit code from the last command. 0 if successful.")
(defvar eshell-last-command-result nil
@@ -196,7 +196,8 @@ describing the mode, e.g. for using with `eshell-get-target'.")
(defun eshell-parse-redirection ()
"Parse an output redirection, such as `2>' or `>&'."
- (when (not eshell-current-quoted)
+ (unless (or eshell-current-quoted
+ eshell-current-argument-plain)
(cond
;; Copying a handle (e.g. `2>&1').
((looking-at (rx (? (group digit))
@@ -597,7 +598,7 @@ If status is nil, prompt before killing."
;; details.
(catch 'done
(dotimes (_ (if (process-tty-name target 'stdin) 3 1))
- (unless (eq (process-status target) 'run)
+ (unless (process-live-p target)
(throw 'done nil))
(process-send-eof target))))
@@ -648,10 +649,12 @@ Returns what was actually sent, or nil if nothing was sent.")
(process-send-string target object)
(error
;; If `process-send-string' raises an error and the process has
- ;; finished, treat it as a broken pipe. Otherwise, just
- ;; re-throw the signal.
- (if (memq (process-status target)
- '(run stop open closed))
+ ;; finished, treat it as a broken pipe. Otherwise, just re-raise
+ ;; the signal. NOTE: When running Emacs in batch mode
+ ;; (e.g. during regression tests), Emacs can abort due to SIGPIPE
+ ;; here. Maybe `process-send-string' should handle SIGPIPE even
+ ;; in batch mode (bug#66186).
+ (if (process-live-p target)
(signal (car err) (cdr err))
(signal 'eshell-pipe-broken (list target)))))
object)
diff --git a/lisp/eshell/esh-mode.el b/lisp/eshell/esh-mode.el
index 0c381dbb86a..21e3f00086f 100644
--- a/lisp/eshell/esh-mode.el
+++ b/lisp/eshell/esh-mode.el
@@ -1,6 +1,6 @@
;;; esh-mode.el --- user interface -*- lexical-binding:t -*-
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
;; Author: John Wiegley <johnw@gnu.org>
@@ -361,6 +361,9 @@ and the hook `eshell-exit-hook'."
(setq-local eshell-last-output-end (point-marker))
(setq-local eshell-last-output-block-begin (point))
+ (add-function :filter-return (local 'filter-buffer-substring-function)
+ #'eshell--unmark-string-as-output)
+
(let ((modules-list (copy-sequence eshell-modules-list)))
(setq-local eshell-modules-list modules-list))
@@ -453,7 +456,7 @@ and the hook `eshell-exit-hook'."
last-command-event))))
(defun eshell-intercept-commands ()
- (when (and (eshell-interactive-process-p)
+ (when (and eshell-foreground-command
(not (and (integerp last-input-event)
(memq last-input-event '(?\C-x ?\C-c)))))
(let ((possible-events (where-is-internal this-command))
@@ -967,7 +970,7 @@ buffer's process if STRING contains a password prompt defined by
`eshell-password-prompt-regexp'.
This function could be in the list `eshell-output-filter-functions'."
- (when (eshell-interactive-process-p)
+ (when eshell-foreground-command
(save-excursion
(let ((case-fold-search t))
(goto-char eshell-last-output-block-begin)
diff --git a/lisp/eshell/esh-module.el b/lisp/eshell/esh-module.el
index 7fc74d38796..fbd5ae4b9b8 100644
--- a/lisp/eshell/esh-module.el
+++ b/lisp/eshell/esh-module.el
@@ -1,6 +1,6 @@
;;; esh-module.el --- Eshell modules -*- lexical-binding:t -*-
-;; Copyright (C) 1999-2000, 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2000, 2002-2024 Free Software Foundation, Inc.
;; Author: John Wiegley <johnw@gnu.org>
;; Keywords: processes
diff --git a/lisp/eshell/esh-opt.el b/lisp/eshell/esh-opt.el
index 09c19767a19..d01e3569d57 100644
--- a/lisp/eshell/esh-opt.el
+++ b/lisp/eshell/esh-opt.el
@@ -1,6 +1,6 @@
;;; esh-opt.el --- command options processing -*- lexical-binding:t -*-
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
;; Author: John Wiegley <johnw@gnu.org>
diff --git a/lisp/eshell/esh-proc.el b/lisp/eshell/esh-proc.el
index 00e0c8014e1..2bb0043bddb 100644
--- a/lisp/eshell/esh-proc.el
+++ b/lisp/eshell/esh-proc.el
@@ -1,6 +1,6 @@
;;; esh-proc.el --- process management -*- lexical-binding:t -*-
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
;; Author: John Wiegley <johnw@gnu.org>
@@ -23,6 +23,7 @@
;;; Code:
+(require 'esh-arg)
(require 'esh-io)
(require 'esh-util)
@@ -40,13 +41,22 @@ finish."
:version "24.1" ; removed eshell-proc-initialize
:type 'hook)
+(defcustom eshell-process-wait-time 0.05
+ "The number of seconds to delay waiting for a synchronous process."
+ :version "30.1"
+ :type 'number)
+
(defcustom eshell-process-wait-seconds 0
"The number of seconds to delay waiting for a synchronous process."
:type 'integer)
+(make-obsolete-variable 'eshell-process-wait-seconds
+ 'eshell-process-wait-time "30.1")
(defcustom eshell-process-wait-milliseconds 50
"The number of milliseconds to delay waiting for a synchronous process."
:type 'integer)
+(make-obsolete-variable 'eshell-process-wait-milliseconds
+ 'eshell-process-wait-time "30.1")
(defcustom eshell-done-messages-in-minibuffer t
"If non-nil, subjob \"Done\" messages will display in minibuffer."
@@ -100,6 +110,8 @@ information, for example."
(defvar eshell-supports-asynchronous-processes (fboundp 'make-process)
"Non-nil if Eshell can create asynchronous processes.")
+(defvar eshell-subjob-messages t
+ "Non-nil if we should print process start/end messages for subjobs.")
(defvar eshell-current-subjob-p nil)
(defvar eshell-process-list nil
@@ -111,7 +123,9 @@ subjob.
To add or remove elements of this list, see
`eshell-record-process-object' and `eshell-remove-process-entry'.")
+(declare-function eshell-reset "esh-mode" (&optional no-hooks))
(declare-function eshell-send-eof-to-process "esh-mode")
+(declare-function eshell-interactive-filter "esh-mode" (buffer string))
(declare-function eshell-tail-process "esh-cmd")
(defvar-keymap eshell-proc-mode-map
@@ -128,6 +142,7 @@ To add or remove elements of this list, see
"Function run when killing a process.
Runs `eshell-reset-after-proc' and `eshell-kill-hook', passing arguments
PROC and STATUS to functions on the latter."
+ (declare (obsolete nil "30.1"))
;; Was there till 24.1, but it is not optional.
(remove-hook 'eshell-kill-hook #'eshell-reset-after-proc)
;; Only reset the prompt if this process is running interactively.
@@ -144,30 +159,37 @@ PROC and STATUS to functions on the latter."
(defun eshell-proc-initialize () ;Called from `eshell-mode' via intern-soft!
"Initialize the process handling code."
(make-local-variable 'eshell-process-list)
+ (setq-local eshell-special-ref-alist
+ (cons
+ `("process"
+ (creation-function get-process)
+ (insertion-function eshell-insert-process)
+ (completion-function eshell-complete-process-ref))
+ eshell-special-ref-alist))
+
(eshell-proc-mode))
-(defun eshell-reset-after-proc (status)
- "Reset the command input location after a process terminates.
-The signals which will cause this to happen are matched by
-`eshell-reset-signals'."
- (when (and (stringp status)
- (string-match eshell-reset-signals status))
- (require 'esh-mode)
- (declare-function eshell-reset "esh-mode" (&optional no-hooks))
- (eshell-reset)))
+(define-obsolete-function-alias 'eshell-reset-after-proc
+ 'eshell--reset-after-signal "30.1")
+
+(defun eshell-process-active-p (process)
+ "Return non-nil if PROCESS is active.
+This is like `process-live-p', but additionally checks whether
+`eshell-sentinel' has finished all of its work yet."
+ (or (process-live-p process)
+ ;; If we have handles, this is an Eshell-managed
+ ;; process. Wait until we're 100% done and have
+ ;; cleared out the handles (see `eshell-sentinel').
+ (process-get process :eshell-handles)))
(defun eshell-wait-for-process (&rest procs)
- "Wait until PROC has successfully completed."
- (while procs
- (let ((proc (car procs)))
- (when (eshell-processp proc)
- ;; NYI: If the process gets stopped here, that's bad.
- (while (assq proc eshell-process-list)
- (if (input-pending-p)
- (discard-input))
- (sit-for eshell-process-wait-seconds
- eshell-process-wait-milliseconds))))
- (setq procs (cdr 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)))))
(defalias 'eshell/wait #'eshell-wait-for-process)
@@ -214,27 +236,11 @@ and signal names."
(put 'eshell/kill 'eshell-no-numeric-conversions t)
-(defun eshell-read-process-name (prompt)
- "Read the name of a process from the minibuffer, using completion.
-The prompt will be set to PROMPT."
- (completing-read prompt
- (mapcar
- (lambda (proc)
- (cons (process-name proc) t))
- (process-list))
- nil t))
-
-(defun eshell-insert-process (process)
- "Insert the name of PROCESS into the current buffer at point."
- (interactive
- (list (get-process
- (eshell-read-process-name "Name of process: "))))
- (insert-and-inherit "#<process " (process-name process) ">"))
-
(defsubst eshell-record-process-object (object)
"Record OBJECT as now running."
- (when (and (eshell-processp object)
- eshell-current-subjob-p)
+ (when (and eshell-subjob-messages
+ eshell-current-subjob-p
+ (eshell-processp object))
(require 'esh-mode)
(declare-function eshell-interactive-print "esh-mode" (string))
(eshell-interactive-print
@@ -243,11 +249,12 @@ The prompt will be set to PROMPT."
(defun eshell-remove-process-entry (entry)
"Record the process ENTRY as fully completed."
- (if (and (eshell-processp (car entry))
- (cdr entry)
- eshell-done-messages-in-minibuffer)
- (message "[%s]+ Done %s" (process-name (car entry))
- (process-command (car entry))))
+ (when (and eshell-subjob-messages
+ eshell-done-messages-in-minibuffer
+ (eshell-processp (car entry))
+ (cdr entry))
+ (message "[%s]+ Done %s" (process-name (car entry))
+ (process-command (car entry))))
(setq eshell-process-list
(delq entry eshell-process-list)))
@@ -269,6 +276,8 @@ nil, write to `eshell-output-handle'."
"A marker that tracks the beginning of output of the last subprocess.
Used only on systems which do not support async subprocesses.")
+(defvar tramp-remote-path)
+
(defun eshell-gather-process-output (command args)
"Gather the output from COMMAND + ARGS."
(require 'esh-var)
@@ -276,7 +285,9 @@ Used only on systems which do not support async subprocesses.")
(unless (and (file-executable-p command)
(file-regular-p (file-truename command)))
(error "%s: not an executable file" command))
- (let* ((delete-exited-processes
+ (let* ((real-path (getenv "PATH"))
+ (tramp-remote-path (bound-and-true-p tramp-remote-path))
+ (delete-exited-processes
(if eshell-current-subjob-p
eshell-delete-exited-processes
delete-exited-processes))
@@ -284,6 +295,16 @@ Used only on systems which do not support async subprocesses.")
(coding-system-for-read coding-system-for-read)
(coding-system-for-write coding-system-for-write)
proc stderr-proc decoding encoding changed)
+ ;; HACK: We want to supply our subprocess with the all the
+ ;; environment variables we've set in Eshell. However, supplying
+ ;; a remote PATH this way can break Tramp, which needs the *local*
+ ;; PATH for calling "ssh", etc. Instead, set the local path in
+ ;; our `process-environment' and pass the remote PATH via
+ ;; `tramp-remote-path'. (If we handle this some better way in the
+ ;; future, remember to remove `tramp-remote-path' above, too.)
+ (when (file-remote-p default-directory)
+ (push (concat "PATH=" real-path) process-environment)
+ (setq tramp-remote-path (eshell-get-path t)))
;; MS-Windows needs special setting of encoding/decoding, because
;; (a) non-ASCII text in command-line arguments needs to be
;; encoded in the system's codepage; and (b) because many Windows
@@ -335,8 +356,19 @@ Used only on systems which do not support async subprocesses.")
:connection-type conn-type
:stderr stderr-proc
:file-handler t)))
+ (eshell-debug-command 'process
+ "started external process `%s'\n\n%s" proc
+ (mapconcat (lambda (i) (shell-quote-argument i 'posix))
+ (process-command proc) " "))
(eshell-record-process-object proc)
(eshell-record-process-properties proc)
+ (when stderr-proc
+ ;; Provide a shared flag between the primary and stderr
+ ;; processes. This lets the primary process wait to clean up
+ ;; until stderr is totally finished (see `eshell-sentinel').
+ (let ((stderr-live (list t)))
+ (process-put proc :eshell-stderr-live stderr-live)
+ (process-put stderr-proc :eshell-stderr-live stderr-live)))
(run-hook-with-args 'eshell-exec-hook proc)
(when (fboundp 'process-coding-system)
(let ((coding-systems (process-coding-system proc)))
@@ -401,7 +433,7 @@ Used only on systems which do not support async subprocesses.")
(eshell-close-handles
(if (numberp exit-status) exit-status -1)
(list 'quote (and (numberp exit-status) (= exit-status 0))))
- (eshell-kill-process-function command exit-status)
+ (run-hook-with-args 'eshell-kill-hook command exit-status)
(or (bound-and-true-p eshell-in-pipeline-p)
(setq eshell-last-sync-output-start nil))
(if (not (numberp exit-status))
@@ -413,9 +445,9 @@ Used only on systems which do not support async subprocesses.")
"Send the output from PROCESS (STRING) to the interactive display.
This is done after all necessary filtering has been done."
(when string
+ (eshell-debug-command 'process
+ "received output from process `%s'\n\n%s" process string)
(eshell--mark-as-output 0 (length string) string)
- (require 'esh-mode)
- (declare-function eshell-interactive-filter "esh-mode" (buffer string))
(eshell-interactive-filter (if process (process-buffer process)
(current-buffer))
string)))
@@ -427,19 +459,23 @@ This is done after all necessary filtering has been done."
"Insert a string into the eshell buffer, or a process/file/buffer.
PROC is the process for which we're inserting output. STRING is the
output."
+ (eshell-debug-command 'process
+ "received output from process `%s'\n\n%s" proc string)
(when (buffer-live-p (process-buffer proc))
(with-current-buffer (process-buffer proc)
(process-put proc :eshell-pending
(concat (process-get proc :eshell-pending)
string))
- (unless (process-get proc :eshell-busy) ; Already being handled?
- (while (process-get proc :eshell-pending)
- (let ((handles (process-get proc :eshell-handles))
- (index (process-get proc :eshell-handle-index))
- (data (process-get proc :eshell-pending)))
- (process-put proc :eshell-pending nil)
- (process-put proc :eshell-busy t)
- (unwind-protect
+ (if (process-get proc :eshell-busy)
+ (eshell-debug-command 'process "i/o busy for process `%s'" proc)
+ (unwind-protect
+ (let ((handles (process-get proc :eshell-handles))
+ (index (process-get proc :eshell-handle-index))
+ data)
+ (while (setq data (process-get proc :eshell-pending))
+ (process-put proc :eshell-pending nil)
+ (eshell-debug-command 'process
+ "forwarding output from process `%s'\n\n%s" proc data)
(condition-case nil
(eshell-output-object data index handles)
;; FIXME: We want to send SIGPIPE to the process
@@ -457,48 +493,67 @@ output."
(if (or (process-get proc 'remote-pid)
(eq system-type 'windows-nt))
(delete-process proc)
- (signal-process proc 'SIGPIPE))))
- (process-put proc :eshell-busy nil))))))))
+ (signal-process proc 'SIGPIPE))))))
+ (process-put proc :eshell-busy nil))))))
(defun eshell-sentinel (proc string)
"Generic sentinel for command processes. Reports only signals.
PROC is the process that's exiting. STRING is the exit message."
- (when (buffer-live-p (process-buffer proc))
+ (eshell-debug-command 'process
+ "sentinel for external process `%s': %S" proc string)
+ (when (and (buffer-live-p (process-buffer proc))
+ (not (string= string "run")))
(with-current-buffer (process-buffer proc)
(unwind-protect
- (unless (string= string "run")
- ;; Write the exit message if the status is abnormal and
- ;; the process is already writing to the terminal.
+ (let* ((handles (process-get proc :eshell-handles))
+ (index (process-get proc :eshell-handle-index))
+ (primary (= index eshell-output-handle))
+ (data (process-get proc :eshell-pending))
+ ;; Only get the status for the primary subprocess,
+ ;; not the pipe process (if any).
+ (status (when primary (process-exit-status proc)))
+ (stderr-live (process-get proc :eshell-stderr-live)))
+ ;; Write the exit message for the last process in the
+ ;; foreground pipeline if its status is abnormal and
+ ;; stderr is already writing to the terminal.
(when (and (eq proc (eshell-tail-process))
+ (eshell-interactive-output-p eshell-error-handle handles)
(not (string-match "^\\(finished\\|exited\\)"
string)))
- (funcall (process-filter proc) proc string))
- (let* ((handles (process-get proc :eshell-handles))
- (index (process-get proc :eshell-handle-index))
- (data (process-get proc :eshell-pending))
- ;; Only get the status for the primary subprocess,
- ;; not the pipe process (if any).
- (status (when (= index eshell-output-handle)
- (process-exit-status proc))))
- (process-put proc :eshell-pending nil)
- ;; If we're in the middle of handling output from this
- ;; process then schedule the EOF for later.
- (letrec ((finish-io
- (lambda ()
- (if (process-get proc :eshell-busy)
- (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)))))
- (funcall finish-io))))
+ (eshell--mark-as-output 0 (length string) string)
+ (eshell-interactive-filter (process-buffer proc) string))
+ (process-put proc :eshell-pending nil)
+ ;; If we're in the middle of handling output from this
+ ;; process then schedule the EOF for later.
+ (letrec ((wait-for-stderr (and primary
+ (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)
+ (eshell-debug-command 'process
+ "finished external process `%s'" proc)
+ (if primary
+ (run-hook-with-args 'eshell-kill-hook proc string)
+ (setcar stderr-live nil))))))
+ (funcall finish-io)))
(when-let ((entry (assq proc eshell-process-list)))
- (eshell-remove-process-entry entry))
- (eshell-kill-process-function proc string)))))
+ (eshell-remove-process-entry entry))))))
(defun eshell-process-interact (func &optional all query)
"Interact with a process, using PROMPT if more than one, via FUNC.
@@ -506,16 +561,14 @@ If ALL is non-nil, background processes will be interacted with as well.
If QUERY is non-nil, query the user with QUERY before calling FUNC."
(let (defunct result)
(dolist (entry eshell-process-list)
- (if (and (memq (process-status (car entry))
- '(run stop open closed))
+ (if (and (process-live-p (car entry))
(or all
(not (cdr entry)))
(or (not query)
(y-or-n-p (format-message query
(process-name (car entry))))))
(setq result (funcall func (car entry))))
- (unless (memq (process-status (car entry))
- '(run stop open closed))
+ (unless (process-live-p (car entry))
(setq defunct (cons entry defunct))))
;; clean up the process list; this can get dirty if an error
;; occurred that brought the user into the debugger, and then they
@@ -526,7 +579,7 @@ If QUERY is non-nil, query the user with QUERY before calling FUNC."
(defcustom eshell-kill-process-wait-time 5
"Seconds to wait between sending termination signals to a subprocess."
- :type 'integer)
+ :type 'number)
(defcustom eshell-kill-process-signals '(SIGINT SIGQUIT SIGKILL)
"Signals used to kill processes when an Eshell buffer exits.
@@ -589,29 +642,41 @@ See the variable `eshell-kill-processes-on-exit'."
(kill-buffer buf)))
(message nil))))
+(defun eshell--reset-after-signal (status)
+ "Reset the prompt after a signal when necessary.
+STATUS is the status associated with the signal; if
+`eshell-reset-signals' matches status, reset the prompt.
+
+This is really only useful when \"signaling\" while there's no
+foreground process. Otherwise, `eshell-resume-command' handles
+everything."
+ (when (and (stringp status)
+ (string-match eshell-reset-signals status))
+ (eshell-reset)))
+
(defun eshell-interrupt-process ()
"Interrupt a process."
(interactive)
(unless (eshell-process-interact 'interrupt-process)
- (eshell-kill-process-function nil "interrupt")))
+ (eshell--reset-after-signal "interrupt\n")))
(defun eshell-kill-process ()
"Kill a process."
(interactive)
(unless (eshell-process-interact 'kill-process)
- (eshell-kill-process-function nil "killed")))
+ (eshell--reset-after-signal "killed\n")))
(defun eshell-quit-process ()
"Send quit signal to process."
(interactive)
(unless (eshell-process-interact 'quit-process)
- (eshell-kill-process-function nil "quit")))
+ (eshell--reset-after-signal "quit\n")))
;(defun eshell-stop-process ()
; "Send STOP signal to process."
; (interactive)
; (unless (eshell-process-interact 'stop-process)
-; (eshell-kill-process-function nil "stopped")))
+; (eshell--reset-after-signal "stopped\n")))
;(defun eshell-continue-process ()
; "Send CONTINUE signal to process."
@@ -620,7 +685,32 @@ See the variable `eshell-kill-processes-on-exit'."
; ;; jww (1999-09-17): this signal is not dealt with yet. For
; ;; example, `eshell-reset' will be called, and so will
; ;; `eshell-resume-eval'.
-; (eshell-kill-process-function nil "continue")))
+; (eshell--reset-after-signal "continue\n")))
+
+;;; Special references
+
+(defun eshell-read-process-name (prompt)
+ "Read the name of a process from the minibuffer, using completion.
+The prompt will be set to PROMPT."
+ (completing-read prompt
+ (mapcar
+ (lambda (proc)
+ (cons (process-name proc) t))
+ (process-list))
+ nil t))
+
+(defun eshell-insert-process (process)
+ "Insert the name of PROCESS into the current buffer at point."
+ (interactive
+ (list (get-process
+ (eshell-read-process-name "Name of process: "))))
+ (insert-and-inherit "#<process "
+ (eshell-quote-argument (process-name process))
+ ">"))
+
+(defun eshell-complete-process-ref ()
+ "Perform completion for process references."
+ (pcomplete-here (mapcar #'process-name (process-list))))
(provide 'esh-proc)
;;; esh-proc.el ends here
diff --git a/lisp/eshell/esh-util.el b/lisp/eshell/esh-util.el
index 87cd1f5dcb2..f0acfecb701 100644
--- a/lisp/eshell/esh-util.el
+++ b/lisp/eshell/esh-util.el
@@ -1,6 +1,6 @@
;;; esh-util.el --- general utilities -*- lexical-binding:t -*-
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
;; Author: John Wiegley <johnw@gnu.org>
@@ -102,6 +102,16 @@ argument matches `eshell-number-regexp'."
(string :tag "Username")
(repeat :tag "UIDs" string))))))
+(defcustom eshell-debug-command nil
+ "A list of debug features to enable when running Eshell commands.
+Possible entries are `form', to log the manipulation of Eshell
+command forms, and `process', to log external process operations.
+
+If nil, don't debug commands at all."
+ :version "30.1"
+ :type '(set (const :tag "Form manipulation" form)
+ (const :tag "Process operations" process)))
+
;;; Internal Variables:
(defvar eshell-number-regexp
@@ -145,6 +155,9 @@ function `string-to-number'.")
,#'eshell--mark-yanked-as-output))
"A list of text properties to apply to command output.")
+(defvar eshell-debug-command-buffer "*eshell last cmd*"
+ "The name of the buffer to log debug messages about command invocation.")
+
;;; Obsolete variables:
(define-obsolete-variable-alias 'eshell-host-names
@@ -164,11 +177,41 @@ function `string-to-number'.")
"If `eshell-handle-errors' is non-nil, this is `condition-case'.
Otherwise, evaluates FORM with no error handling."
(declare (indent 2) (debug (sexp form &rest form)))
- (if eshell-handle-errors
- `(condition-case-unless-debug ,tag
- ,form
- ,@handlers)
- form))
+ `(if eshell-handle-errors
+ (condition-case-unless-debug ,tag
+ ,form
+ ,@handlers)
+ ,form))
+
+(defun eshell-debug-command-start (command)
+ "Start debugging output for the command string COMMAND.
+If debugging is enabled (see `eshell-debug-command'), this will
+start logging to `*eshell last cmd*'."
+ (when eshell-debug-command
+ (with-current-buffer (get-buffer-create eshell-debug-command-buffer)
+ (erase-buffer)
+ (insert "command: \"" command "\"\n"))))
+
+(defun eshell-always-debug-command (kind string &rest objects)
+ "Output a debugging message to `*eshell last cmd*'.
+KIND is the kind of message to log. STRING and OBJECTS are as
+`format-message' (which see)."
+ (declare (indent 1))
+ (with-current-buffer (get-buffer-create eshell-debug-command-buffer)
+ (insert "\n\C-l\n[" (symbol-name kind) "] "
+ (apply #'format-message string objects))))
+
+(defmacro eshell-debug-command (kind string &rest objects)
+ "Output a debugging message to `*eshell last cmd*' if debugging is enabled.
+KIND is the kind of message to log (either `form' or `process'). If
+present in `eshell-debug-command', output this message; otherwise, ignore it.
+
+STRING and OBJECTS are as `format-message' (which see)."
+ (declare (indent 1))
+ (let ((kind-sym (make-symbol "kind")))
+ `(let ((,kind-sym ,kind))
+ (when (memq ,kind-sym eshell-debug-command)
+ (eshell-always-debug-command ,kind-sym ,string ,@objects)))))
(defun eshell--mark-as-output (start end &optional object)
"Mark the text from START to END as Eshell output.
@@ -191,6 +234,57 @@ current buffer."
(eshell--mark-as-output start1 end1)))))
(add-hook 'after-change-functions hook nil t)))
+(defun eshell--unmark-string-as-output (string)
+ "Unmark STRING as Eshell output."
+ (remove-list-of-text-properties
+ 0 (length string)
+ '(rear-nonsticky front-sticky field insert-in-front-hooks)
+ string)
+ string)
+
+(defsubst eshell--region-p (object)
+ "Return non-nil if OBJECT is a pair of numbers or markers."
+ (and (consp object)
+ (number-or-marker-p (car object))
+ (number-or-marker-p (cdr object))))
+
+(defmacro eshell-with-temp-command (command &rest body)
+ "Temporarily insert COMMAND into the buffer and execute the forms in BODY.
+
+COMMAND can be a string to insert, a cons cell (START . END)
+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.
+
+The value returned is the last form in BODY."
+ (declare (indent 1))
+ (let ((command-sym (make-symbol "command"))
+ (begin-sym (make-symbol "begin"))
+ (end-sym (make-symbol "end")))
+ `(let ((,command-sym ,command))
+ (if (eshell--region-p ,command-sym)
+ (save-restriction
+ (narrow-to-region (car ,command-sym) (cdr ,command-sym))
+ (goto-char (car ,command-sym))
+ ,@body)
+ ;; Since parsing relies partly on buffer-local state
+ ;; (e.g. that of `eshell-parse-argument-hook'), we need to
+ ;; perform the parsing in the Eshell buffer.
+ (let ((,begin-sym (point)) ,end-sym)
+ (with-silent-modifications
+ (if (stringp ,command-sym)
+ (insert ,command-sym)
+ (forward-char (cadr (insert-file-contents (cdr ,command-sym)))))
+ (setq ,end-sym (point))
+ (unwind-protect
+ (save-restriction
+ (narrow-to-region ,begin-sym ,end-sym)
+ (goto-char ,begin-sym)
+ ,@body)
+ (delete-region ,begin-sym ,end-sym))))))))
+
(defun eshell-find-delimiter
(open close &optional bound reverse-p backslash-p)
"From point, find the CLOSE delimiter corresponding to OPEN.
@@ -326,7 +420,7 @@ as the $PATH was actually specified."
(eshell-under-windows-p))
(push "." path))
(if (and remote (not literal-p))
- (mapcar (lambda (x) (file-name-concat remote x)) path)
+ (mapcar (lambda (x) (concat remote x)) path)
path))))
(defun eshell-set-path (path)
@@ -695,19 +789,18 @@ gid format. Valid values are `string' and `integer', defaulting to
"If the `processp' function does not exist, PROC is not a process."
(and (fboundp 'processp) (processp proc)))
-(defun eshell-process-pair-p (procs)
- "Return non-nil if PROCS is a pair of process objects."
- (and (consp procs)
- (eshell-processp (car procs))
- (eshell-processp (cdr procs))))
+(defun eshell-process-list-p (procs)
+ "Return non-nil if PROCS is a list of process objects."
+ (and (listp procs)
+ (seq-every-p #'eshell-processp procs)))
-(defun eshell-make-process-pair (procs)
- "Make a pair of process objects from PROCS if possible.
-This represents the head and tail of a pipeline of processes,
-where the head and tail may be the same process."
+(defun eshell-make-process-list (procs)
+ "Make a list of process objects from PROCS if possible.
+PROCS can be a single process or a list thereof. If PROCS is
+anything else, return nil instead."
(pcase procs
- ((pred eshell-processp) (cons procs procs))
- ((pred eshell-process-pair-p) procs)))
+ ((pred eshell-processp) (list procs))
+ ((pred eshell-process-list-p) procs)))
;; (defun eshell-copy-file
;; (file newname &optional ok-if-already-exists keep-date)
diff --git a/lisp/eshell/esh-var.el b/lisp/eshell/esh-var.el
index c7c0a21d2a9..ae0b18cd13a 100644
--- a/lisp/eshell/esh-var.el
+++ b/lisp/eshell/esh-var.el
@@ -1,6 +1,6 @@
;;; esh-var.el --- handling of variables -*- lexical-binding:t -*-
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
;; Author: John Wiegley <johnw@gnu.org>
@@ -162,6 +162,13 @@ if they are quoted with a backslash."
("COLUMNS" ,(lambda () (window-body-width nil 'remap)) t t)
("LINES" ,(lambda () (window-body-height nil 'remap)) t t)
("INSIDE_EMACS" eshell-inside-emacs t)
+ ("PAGER" (,(lambda () (or comint-pager (getenv "PAGER")))
+ . ,(lambda (_ value)
+ ;; When unsetting PAGER, be sure to clear its value
+ ;; from `process-environment' too.
+ (unless value (setenv "PAGER"))
+ (setq comint-pager value)))
+ t t)
("UID" ,(lambda () (file-user-uid)) nil t)
("GID" ,(lambda () (file-group-gid)) nil t)
@@ -262,11 +269,13 @@ copied (a.k.a. \"exported\") to the environment of created subprocesses."
;; changing a variable will affect all of Emacs.
(unless eshell-modify-global-environment
(setq-local process-environment (eshell-copy-environment)))
+ (make-local-variable 'comint-pager)
(setq-local eshell-subcommand-bindings
(append
'((process-environment (eshell-copy-environment))
(eshell-variable-aliases-list eshell-variable-aliases-list)
- (eshell-path-env-list eshell-path-env-list))
+ (eshell-path-env-list eshell-path-env-list)
+ (comint-pager comint-pager))
eshell-subcommand-bindings))
(setq-local eshell-special-chars-inside-quoting
@@ -287,43 +296,30 @@ copied (a.k.a. \"exported\") to the environment of created subprocesses."
(defun eshell-handle-local-variables ()
"Allow for the syntax `VAR=val <command> <args>'."
- ;; strip off any null commands, which can only happen if a variable
- ;; evaluates to nil, such as "$var x", where `var' is nil. The
- ;; command name in that case becomes `x', for compatibility with
- ;; most regular shells (the difference is that they do an
- ;; interpolation pass before the argument parsing pass, but Eshell
- ;; does both at the same time).
- (while (and (not eshell-last-command-name)
- eshell-last-arguments)
- (setq eshell-last-command-name (car eshell-last-arguments)
- eshell-last-arguments (cdr eshell-last-arguments)))
+ ;; Eshell handles local variable settings (e.g. 'CFLAGS=-O2 make')
+ ;; by making the whole command into a subcommand, and calling
+ ;; `eshell-set-variable' immediately before the command is invoked.
+ ;; This means that 'FOO=x cd bar' won't work exactly as expected,
+ ;; but that is by no means a typical use of local environment
+ ;; variables.
(let ((setvar "\\`\\([A-Za-z_][A-Za-z0-9_]*\\)=\\(.*\\)\\'")
- (command (eshell-stringify eshell-last-command-name))
- (args eshell-last-arguments))
- ;; local variable settings (such as 'CFLAGS=-O2 make') are handled
- ;; by making the whole command into a subcommand, and calling
- ;; setenv immediately before the command is invoked. This means
- ;; that 'BLAH=x cd blah' won't work exactly as expected, but that
- ;; is by no means a typical use of local environment variables.
- (if (and command (string-match setvar command))
- (throw
- 'eshell-replace-command
- (list
- 'eshell-as-subcommand
- (append
- (list 'progn)
- (let ((l (list t)))
- (while (string-match setvar command)
- (nconc
- l (list
- (list 'eshell-set-variable
- (match-string 1 command)
- (match-string 2 command))))
- (setq command (eshell-stringify (car args))
- args (cdr args)))
- (cdr l))
- (list (list 'eshell-named-command
- command (list 'quote args)))))))))
+ (command eshell-last-command-name)
+ (args eshell-last-arguments))
+ (when (and (stringp command) (string-match setvar command))
+ (throw 'eshell-replace-command
+ `(eshell-as-subcommand
+ (progn
+ ,@(let (locals)
+ (while (and (stringp command)
+ (string-match setvar command))
+ (push `(eshell-set-variable
+ ,(match-string 1 command)
+ ,(match-string 2 command))
+ locals)
+ (setq command (pop args)))
+ (nreverse locals))
+ (eshell-named-command ,command ,(list 'quote args)))
+ )))))
(defun eshell-interpolate-variable ()
"Parse a variable interpolation.
diff --git a/lisp/eshell/eshell.el b/lisp/eshell/eshell.el
index 15fc2ae6310..7d374587dc4 100644
--- a/lisp/eshell/eshell.el
+++ b/lisp/eshell/eshell.el
@@ -1,6 +1,6 @@
;;; eshell.el --- the Emacs command shell -*- lexical-binding:t -*-
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
;; Author: John Wiegley <johnw@gnu.org>
;; Version: 2.4.2
@@ -301,7 +301,8 @@ argument), then insert output into the current buffer at point."
`(let ((eshell-current-handles
(eshell-create-handles ,stdout 'insert))
(eshell-current-subjob-p))
- ,(eshell-parse-command command))))
+ ,(eshell-parse-command command))
+ command))
intr
(bufname (if (eq (car-safe proc) :eshell-background)
"*Eshell Async Command Output*"
@@ -314,9 +315,8 @@ argument), then insert output into the current buffer at point."
;; make the output as attractive as possible, with no
;; extraneous newlines
(when intr
- (if (eshell-interactive-process-p)
- (eshell-wait-for-process (eshell-tail-process)))
- (cl-assert (not (eshell-interactive-process-p)))
+ (apply #'eshell-wait-for-process (cadr eshell-foreground-command))
+ (cl-assert (not eshell-foreground-command))
(goto-char (point-max))
(while (and (bolp) (not (bobp)))
(delete-char -1)))
@@ -356,6 +356,7 @@ corresponding to a successful execution."
(with-temp-buffer
(let ((eshell-non-interactive-p t))
(eshell-mode)
+ (eshell-debug-command-start command)
(let ((result (eshell-do-eval
(list 'eshell-commands
(list 'eshell-command-to-value
diff --git a/lisp/expand.el b/lisp/expand.el
index 7e0b0b56010..f32ab101224 100644
--- a/lisp/expand.el
+++ b/lisp/expand.el
@@ -1,6 +1,6 @@
;;; expand.el --- make abbreviations more usable -*- lexical-binding: t -*-
-;; Copyright (C) 1995-1996, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1995-1996, 2001-2024 Free Software Foundation, Inc.
;; Author: Frederic Lepied <Frederic.Lepied@sugix.frmug.org>
;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/external-completion.el b/lisp/external-completion.el
index 3f80be1c0a4..b171e27014c 100644
--- a/lisp/external-completion.el
+++ b/lisp/external-completion.el
@@ -1,12 +1,15 @@
;;; external-completion.el --- Let external tools control completion style -*- lexical-binding: t; -*-
-;; Copyright (C) 2018-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2018-2024 Free Software Foundation, Inc.
;; Version: 0.1
;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
;; Maintainer: João Távora <joaotavora@gmail.com>
;; Keywords:
+;; This is a GNU ELPA :core package. Avoid functionality that is not
+;; compatible with the version of Emacs recorded above.
+
;; This file is part of GNU Emacs.
;; GNU Emacs is free software: you can redistribute it and/or modify
diff --git a/lisp/ezimage.el b/lisp/ezimage.el
index ba3e5b1d369..8d5815c2f18 100644
--- a/lisp/ezimage.el
+++ b/lisp/ezimage.el
@@ -1,6 +1,6 @@
;;; ezimage.el --- Generalized Image management -*- lexical-binding: t -*-
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
;; Keywords: file, tags, tools
diff --git a/lisp/face-remap.el b/lisp/face-remap.el
index c5f7af37406..d269d85301c 100644
--- a/lisp/face-remap.el
+++ b/lisp/face-remap.el
@@ -1,6 +1,6 @@
;;; face-remap.el --- Functions for managing `face-remapping-alist' -*- lexical-binding: t -*-
;;
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
;;
;; Author: Miles Bader <miles@gnu.org>
;; Keywords: faces, face remapping, display, user commands
diff --git a/lisp/facemenu.el b/lisp/facemenu.el
index 5066bf25c9d..50c2c91fcdb 100644
--- a/lisp/facemenu.el
+++ b/lisp/facemenu.el
@@ -1,6 +1,6 @@
;;; facemenu.el --- create a face menu for interactively adding fonts to text -*- lexical-binding: t; -*-
-;; Copyright (C) 1994-1996, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1994-1996, 2001-2024 Free Software Foundation, Inc.
;; Author: Boris Goldowsky <boris@gnu.org>
;; Keywords: faces
diff --git a/lisp/faces.el b/lisp/faces.el
index 1a446aacacd..d5120f42b92 100644
--- a/lisp/faces.el
+++ b/lisp/faces.el
@@ -1,6 +1,6 @@
;;; faces.el --- Lisp faces -*- lexical-binding: t -*-
-;; Copyright (C) 1992-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1992-2024 Free Software Foundation, Inc.
;; Maintainer: emacs-devel@gnu.org
;; Keywords: internal
@@ -1118,8 +1118,7 @@ element of DEFAULT is returned. If DEFAULT isn't a list, but
MULTIPLE is non-nil, a one-element list containing DEFAULT is
returned. Otherwise, DEFAULT is returned verbatim."
(let (defaults)
- (unless (listp default)
- (setq default (list default)))
+ (setq default (ensure-list default))
(when default
(setq default
(if multiple
@@ -1146,16 +1145,16 @@ returned. Otherwise, DEFAULT is returned verbatim."
(format-prompt prompt default)
(format "%s: " prompt)))
(completion-extra-properties
- '(:affixation-function
- (lambda (faces)
- (mapcar
- (lambda (face)
- (list face
- (concat (propertize read-face-name-sample-text
- 'face face)
- "\t")
- ""))
- faces))))
+ `(:affixation-function
+ ,(lambda (faces)
+ (mapcar
+ (lambda (face)
+ (list face
+ (concat (propertize read-face-name-sample-text
+ 'face face)
+ "\t")
+ ""))
+ faces))))
aliasfaces nonaliasfaces faces)
;; Build up the completion tables.
(mapatoms (lambda (s)
@@ -2441,7 +2440,10 @@ If you set `term-file-prefix' to nil, this function does nothing."
'((((supports :slant italic))
:slant italic)
(((supports :underline t))
- :underline t)
+ ;; Include italic, even if it isn't supported by the default
+ ;; font, because this face could be merged with another face
+ ;; which uses font that does have an italic variant.
+ :underline t :slant italic)
(t
;; Default to italic, even if it doesn't appear to be supported,
;; because in some cases the display engine will do its own
@@ -2458,7 +2460,9 @@ If you set `term-file-prefix' to nil, this function does nothing."
(defface underline
'((((supports :underline t))
:underline t)
- (((supports :weight bold))
+ ;; Include underline, for when this face is merged with another
+ ;; whose font does support underline.
+ (((supports :weight bold :underline t))
:weight bold)
(t :underline t))
"Basic underlined face."
diff --git a/lisp/ffap.el b/lisp/ffap.el
index 907f56763ff..3492dcbf17a 100644
--- a/lisp/ffap.el
+++ b/lisp/ffap.el
@@ -1,6 +1,6 @@
;;; ffap.el --- find file (or url) at point -*- lexical-binding: t -*-
-;; Copyright (C) 1995-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1995-2024 Free Software Foundation, Inc.
;; Author: Michelangelo Grigni <mic@mathcs.emory.edu>
;; Maintainer: emacs-devel@gnu.org
@@ -152,15 +152,15 @@ schemes (e.g. \"ftp\"); in that case, only convert those URLs."
:group 'ffap
:version "24.3")
-(defcustom ffap-lax-url t
+(defcustom ffap-lax-url nil
"If non-nil, allow lax URL matching.
The default non-nil value might produce false URLs in C++ code
with symbols like \"std::find\". On the other hand, setting
this to nil will disable recognition of URLs that are not
-well-formed, such as \"user@host\" or \"<user@host>\"."
+well-formed."
:type 'boolean
:group 'ffap
- :version "25.2") ; nil -> t
+ :version "30.1")
(defcustom ffap-ftp-default-user "anonymous"
"User name in FTP file names generated by `ffap-host-to-filename'.
@@ -174,7 +174,8 @@ Note this name may be omitted if it equals the default
"\\`/\\(afs\\|net\\)/."
;; afs only: (and (file-exists-p "/afs") "\\`/afs/.")
"Matching file names are treated as remote. Use nil to disable."
- :type 'regexp
+ :type '(choice (const :tag "Disable" nil)
+ regexp)
:group 'ffap)
(defvar ffap-url-regexp
@@ -553,7 +554,7 @@ Looks at `ffap-ftp-default-user', returns \"\" for \"localhost\"."
(concat "gopher://" mach "/"))
;; www.ncsa.uiuc.edu
((and (string-match "\\`w\\(ww\\|eb\\)[-.]" mach))
- (concat "http://" mach "/"))
+ (concat "https://" mach "/"))
;; More cases?
(ffap-ftp-regexp (ffap-host-to-filename mach))
))
@@ -608,6 +609,13 @@ Looks at `ffap-ftp-default-user', returns \"\" for \"localhost\"."
((and ffap-url-unwrap-remote (ffap-url-unwrap-remote url)))
(url)))
+(defun ffap-fixup-email (email)
+ "Clean up EMAIL and return it as a mailto: URL."
+ (when (stringp email)
+ (if (string-prefix-p "mailto:" email)
+ email
+ (concat "mailto:" email))))
+
;;; File Name Handling:
@@ -729,6 +737,7 @@ This uses `ffap-file-exists-string', which may try adding suffixes from
(defvar ffap-alist
'(
("" . ffap-completable) ; completion, slow on some systems
+ ("" . ffap-in-project) ; maybe in the root of the project
("\\.info\\'" . ffap-info) ; gzip.info
("\\`info/" . ffap-info-2) ; info/emacs
("\\`[-[:lower:]]+\\'" . ffap-info-3) ; (emacs)Top [only in the parentheses]
@@ -792,6 +801,11 @@ to extract substrings.")
(cmp (file-name-completion (file-name-nondirectory name) dir)))
(and cmp (concat dir cmp))))
+(declare-function project-root "project" (project))
+(defun ffap-in-project (name)
+ (when-let (project (project-current))
+ (file-name-concat (project-root project) name)))
+
(defun ffap-home (name) (ffap-locate-file name t '("~")))
(defun ffap-info (name)
@@ -1564,6 +1578,7 @@ Uses the face `ffap' if it is defined, or else `highlight'."
(ffap-fixup-url (or (ffap-url-at-point)
(ffap-gopher-at-point))))
(ffap-file-at-point) ; may yield url!
+ (ffap-fixup-email (thing-at-point 'email))
(ffap-fixup-machine (ffap-machine-at-point))))
(defun ffap-prompter (&optional guess suffix)
diff --git a/lisp/filecache.el b/lisp/filecache.el
index 42225509eca..86d5e65df06 100644
--- a/lisp/filecache.el
+++ b/lisp/filecache.el
@@ -1,6 +1,6 @@
;;; filecache.el --- find files using a pre-loaded cache -*- lexical-binding:t -*-
-;; Copyright (C) 1996, 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996, 2000-2024 Free Software Foundation, Inc.
;; Author: Peter Breton <pbreton@cs.umb.edu>
;; Created: Sun Nov 10 1996
diff --git a/lisp/fileloop.el b/lisp/fileloop.el
index f58d00d9aa9..1fe40387096 100644
--- a/lisp/fileloop.el
+++ b/lisp/fileloop.el
@@ -1,6 +1,6 @@
;;; fileloop.el --- Operations on multiple files -*- lexical-binding: t; -*-
-;; Copyright (C) 2018-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2018-2024 Free Software Foundation, Inc.
;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
diff --git a/lisp/filenotify.el b/lisp/filenotify.el
index e9f8d4e515d..4e289d564c9 100644
--- a/lisp/filenotify.el
+++ b/lisp/filenotify.el
@@ -1,6 +1,6 @@
;;; filenotify.el --- watch files for changes on disk -*- lexical-binding:t -*-
-;; Copyright (C) 2013-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2024 Free Software Foundation, Inc.
;; Author: Michael Albinus <michael.albinus@gmx.de>
@@ -138,7 +138,7 @@ It is nil or a `file-notify--rename' defstruct where the cookie can be nil.")
((memq action '(delete delete-self move-self)) 'deleted)
((eq action 'moved-from) 'renamed-from)
((eq action 'moved-to) 'renamed-to)
- ((eq action 'ignored) 'stopped)))
+ ((memq action '(ignored unmount)) 'stopped)))
actions))
file file1-or-cookie))
@@ -153,7 +153,8 @@ It is nil or a `file-notify--rename' defstruct where the cookie can be nil.")
((eq action 'write) 'changed)
((memq action '(attrib link)) 'attribute-changed)
((eq action 'delete) 'deleted)
- ((eq action 'rename) 'renamed)))
+ ((eq action 'rename) 'renamed)
+ ((eq action 'revoke) 'stopped)))
actions))
file file1-or-cookie))
@@ -179,7 +180,8 @@ It is nil or a `file-notify--rename' defstruct where the cookie can be nil.")
((memq action
'(created changed attribute-changed deleted))
action)
- ((eq action 'moved) 'renamed)))
+ ((eq action 'moved) 'renamed)
+ ((eq action 'unmounted) 'stopped)))
(if (consp actions) actions (list actions))))
file file1-or-cookie))
@@ -195,6 +197,7 @@ It is nil or a `file-notify--rename' defstruct where the cookie can be nil.")
((memq action '(created changed attribute-changed deleted))
action)
((eq action 'moved) 'renamed)
+ ((eq action 'unmounted) 'stopped)
;; inotify actions:
((eq action 'create) 'created)
((eq action 'modify) 'changed)
@@ -202,7 +205,7 @@ It is nil or a `file-notify--rename' defstruct where the cookie can be nil.")
((memq action '(delete delete-self move-self)) 'deleted)
((eq action 'moved-from) 'renamed-from)
((eq action 'moved-to) 'renamed-to)
- ((eq action 'ignored) 'stopped)))
+ ((memq action '(ignored unmount)) 'stopped)))
(if (consp actions) actions (list actions))))
file file1-or-cookie))
@@ -339,7 +342,7 @@ DESC is the back-end descriptor. ACTIONS is a list of:
"Add a watch for FILE in DIR with FLAGS, using inotify."
(inotify-add-watch dir
(append
- '(dont-follow)
+ '(dont-follow ignored unmount)
(and (memq 'change flags)
'(create delete delete-self modify move-self move))
(and (memq 'attribute-change flags)
@@ -352,6 +355,7 @@ DESC is the back-end descriptor. ACTIONS is a list of:
;; directories, so we watch each file directly.
(kqueue-add-watch file
(append
+ '(revoke)
(and (memq 'change flags)
'(create delete write extend rename))
(and (memq 'attribute-change flags)
diff --git a/lisp/files-x.el b/lisp/files-x.el
index 3ba7632d253..fccb2fa4a9f 100644
--- a/lisp/files-x.el
+++ b/lisp/files-x.el
@@ -1,6 +1,6 @@
;;; files-x.el --- extended file handling commands -*- lexical-binding: t; -*-
-;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
;; Author: Juri Linkov <juri@jurta.org>
;; Maintainer: emacs-devel@gnu.org
@@ -31,6 +31,8 @@
;;; Code:
(eval-when-compile (require 'subr-x)) ; for string-trim-right
+(declare-function dosified-file-name "dos-fns" (file-name))
+(declare-function project-root "project" (project))
;;; Commands to add/delete file-local/directory-local variables.
@@ -410,7 +412,7 @@ then this function adds it."
(defvar auto-insert) ; from autoinsert.el
-(defun modify-dir-local-variable (mode variable value op)
+(defun modify-dir-local-variable (mode variable value op &optional file)
"Modify directory-local VARIABLE in .dir-locals.el depending on operation OP.
If OP is `add-or-replace' then delete all existing settings of
@@ -422,28 +424,37 @@ If .dir-locals.el was not found and OP is not `delete' then create
this file in the current directory.
If OP is `delete' then delete all existing settings of VARIABLE
-from the MODE alist ignoring the input argument VALUE."
+from the MODE alist ignoring the input argument VALUE.
+
+Optional argument FILE, when non-nil, specifies what file to modify. It
+should be an expanded filename."
(catch 'exit
(unless enable-local-variables
(throw 'exit (message "Directory-local variables are disabled")))
- (let* ((dir-or-cache (and (buffer-file-name)
- (not (file-remote-p (buffer-file-name)))
- (dir-locals-find-file (buffer-file-name))))
- (variables-file
- ;; If there are several .dir-locals, the user probably
- ;; wants to edit the last one (the highest priority).
- (cond ((stringp dir-or-cache)
- (car (last (dir-locals--all-files dir-or-cache))))
- ((consp dir-or-cache) ; result from cache
- ;; If cache element has an mtime, assume it came
- ;; from a file. Otherwise, assume it was set
- ;; directly.
- (if (nth 2 dir-or-cache)
- (car (last (dir-locals--all-files (car dir-or-cache))))
- (cadr dir-or-cache)))
- ;; Try to make a proper file-name.
- (t (expand-file-name dir-locals-file))))
- variables)
+ (let ((variables-file
+ (if (stringp file)
+ file
+ (let ((dir-or-cache
+ (and (buffer-file-name)
+ (not (file-remote-p (buffer-file-name)))
+ (dir-locals-find-file (buffer-file-name)))))
+ ;; If there are several .dir-locals, the user probably
+ ;; wants to edit the last one (the highest priority).
+ (cond
+ ((stringp dir-or-cache)
+ (car (last (dir-locals--all-files dir-or-cache))))
+ ((consp dir-or-cache) ; result from cache
+ ;; If cache element has an mtime, assume it came
+ ;; from a file. Otherwise, assume it was set
+ ;; directly.
+ (if (nth 2 dir-or-cache)
+ (car (last (dir-locals--all-files (car dir-or-cache))))
+ (cadr dir-or-cache)))
+ ;; Try to make a proper file-name.
+ (t (expand-file-name (if (eq system-type 'ms-dos)
+ (dosified-file-name dir-locals-file)
+ dir-locals-file)))))))
+ variables)
;; I can't be bothered to handle this case right now.
;; Dir locals were set directly from a class. You need to
;; directly modify the class in dir-locals-class-alist.
@@ -527,33 +538,75 @@ from the MODE alist ignoring the input argument VALUE."
(cdr mode-variables) "\n"))))
variables "\n")))
+(defun read-dir-locals-file ()
+ "Read a dir-locals filename using completion.
+Intended to be used in the `interactive' spec of `add-dir-local-variable',
+`delete-dir-local-variable' and `copy-file-locals-to-dir-locals'.
+
+Returns the filename, expanded."
+ (let* ((pri dir-locals-file)
+ (sec (replace-regexp-in-string ".el$" "-2.el" dir-locals-file))
+ (dir (or (locate-dominating-file default-directory pri)
+ (locate-dominating-file default-directory sec))))
+ (expand-file-name
+ (read-file-name
+ "File: "
+ (cond (dir)
+ ((when-let ((proj (and (featurep 'project) (project-current))))
+ (project-root proj))))
+ nil
+ (lambda (fname)
+ (member (file-name-nondirectory fname) (list pri sec)))
+ dir-locals-file))))
+
;;;###autoload
-(defun add-dir-local-variable (mode variable value)
- "Add directory-local VARIABLE with its VALUE and MODE to .dir-locals.el."
+(defun add-dir-local-variable (mode variable value &optional file)
+ "Add directory-local VARIABLE with its VALUE and MODE to .dir-locals.el.
+
+With a prefix argument, prompt for the file to modify.
+
+When called from Lisp, FILE may be the expanded name of the dir-locals file
+where to add VARIABLE."
(interactive
(let (variable)
(list
(read-file-local-variable-mode)
(setq variable (read-file-local-variable "Add directory-local variable"))
- (read-file-local-variable-value variable))))
- (modify-dir-local-variable mode variable value 'add-or-replace))
+ (read-file-local-variable-value variable)
+ (when current-prefix-arg
+ (read-dir-locals-file)))))
+ (modify-dir-local-variable mode variable value 'add-or-replace file))
;;;###autoload
-(defun delete-dir-local-variable (mode variable)
- "Delete all MODE settings of file-local VARIABLE from .dir-locals.el."
+(defun delete-dir-local-variable (mode variable &optional file)
+ "Delete all MODE settings of dir-local VARIABLE from .dir-locals.el.
+
+With a prefix argument, prompt for the file to modify.
+
+When called from Lisp, FILE may be the expanded name of the dir-locals file
+from where to delete VARIABLE."
(interactive
(list
(read-file-local-variable-mode)
- (read-file-local-variable "Delete directory-local variable")))
- (modify-dir-local-variable mode variable nil 'delete))
+ (read-file-local-variable "Delete directory-local variable")
+ (when current-prefix-arg
+ (read-dir-locals-file))))
+ (modify-dir-local-variable mode variable nil 'delete file))
;;;###autoload
-(defun copy-file-locals-to-dir-locals ()
- "Copy file-local variables to .dir-locals.el."
- (interactive)
+(defun copy-file-locals-to-dir-locals (&optional file)
+ "Copy file-local variables to .dir-locals.el.
+
+With a prefix argument, prompt for the file to modify.
+
+When called from Lisp, FILE may be the expanded name of the dir-locals file
+where to copy the file-local variables."
+ (interactive
+ (list (when current-prefix-arg
+ (read-dir-locals-file))))
(dolist (elt file-local-variables-alist)
(unless (assq (car elt) dir-local-variables-alist)
- (add-dir-local-variable major-mode (car elt) (cdr elt)))))
+ (add-dir-local-variable major-mode (car elt) (cdr elt) file))))
;;;###autoload
(defun copy-dir-locals-to-file-locals ()
@@ -647,7 +700,8 @@ Return a reordered plist."
"Return the connection profiles list for CRITERIA.
CRITERIA is a plist identifying a connection and the application
using this connection, see `connection-local-criteria-alist'."
- (let (profiles)
+ (let ((criteria (connection-local-normalize-criteria criteria))
+ profiles)
(dolist (crit-alist connection-local-criteria-alist)
(let ((crit criteria)
(match t))
@@ -737,6 +791,7 @@ definitions that aren't listed in VARIABLES."
(setq variables (nreverse existing-variables)))
(connection-local-set-profile-variables profile variables))
+;;;###autoload
(defun hack-connection-local-variables (criteria)
"Read connection-local variables according to CRITERIA.
Store the connection-local variables in buffer local
@@ -872,17 +927,46 @@ earlier in the `setq-connection-local'. The return value of the
connection-local-profile-name-for-setq)))))
;;;###autoload
+(defmacro connection-local-p (variable &optional application)
+ "Non-nil if VARIABLE has a connection-local binding in `default-directory'.
+If APPLICATION is nil, the value of
+`connection-local-default-application' is used."
+ (declare (debug (symbolp &optional form)))
+ (unless (symbolp variable)
+ (signal 'wrong-type-argument (list 'symbolp variable)))
+ `(let (connection-local-variables-alist file-local-variables-alist)
+ (hack-connection-local-variables
+ (connection-local-criteria-for-default-directory ,application))
+ (and (assq ',variable connection-local-variables-alist) t)))
+
+;;;###autoload
+(defmacro connection-local-value (variable &optional application)
+ "Return connection-local VARIABLE for APPLICATION in `default-directory'.
+If APPLICATION is nil, the value of
+`connection-local-default-application' is used.
+If VARIABLE does not have a connection-local binding, the return
+value is the default binding of the variable."
+ (declare (debug (symbolp &optional form)))
+ (unless (symbolp variable)
+ (signal 'wrong-type-argument (list 'symbolp variable)))
+ `(let (connection-local-variables-alist file-local-variables-alist)
+ (hack-connection-local-variables
+ (connection-local-criteria-for-default-directory ,application))
+ (if-let ((result (assq ',variable connection-local-variables-alist)))
+ (cdr result)
+ ,variable)))
+
+;;;###autoload
(defun path-separator ()
"The connection-local value of `path-separator'."
- (with-connection-local-variables path-separator))
+ (connection-local-value path-separator))
;;;###autoload
(defun null-device ()
"The connection-local value of `null-device'."
- (with-connection-local-variables null-device))
+ (connection-local-value null-device))
-
(provide 'files-x)
;;; files-x.el ends here
diff --git a/lisp/files.el b/lisp/files.el
index 3466a53d165..8b4e4394e5a 100644
--- a/lisp/files.el
+++ b/lisp/files.el
@@ -1,6 +1,6 @@
;;; files.el --- file input and output commands for Emacs -*- lexical-binding:t -*-
-;; Copyright (C) 1985-1987, 1992-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1985-1987, 1992-2024 Free Software Foundation, Inc.
;; Maintainer: emacs-devel@gnu.org
;; Package: emacs
@@ -228,7 +228,7 @@ If non-nil, this directory is used instead of `temporary-file-directory'
by programs that create small temporary files. This is for systems that
have fast storage with limited space, such as a RAM disk."
:group 'files
- :initialize 'custom-initialize-delay
+ :initialize #'custom-initialize-delay
:type '(choice (const nil) directory))
;; The system null device. (Should reference NULL_DEVICE from C.)
@@ -434,7 +434,7 @@ ignored."
,@(mapcar (lambda (algo)
(list 'const algo))
(secure-hash-algorithms)))))
- :initialize 'custom-initialize-delay
+ :initialize #'custom-initialize-delay
:version "21.1")
(defvar auto-save--timer nil "Timer for `auto-save-visited-mode'.")
@@ -1135,9 +1135,11 @@ the function needs to examine, starting with FILE."
(while (not (or root
(null file)
(string-match locate-dominating-stop-dir-regexp file)))
- (setq try (if (stringp name)
- (and (file-directory-p file)
- (file-exists-p (expand-file-name name file)))
+ (setq file (if (file-directory-p file)
+ file
+ (file-name-directory file))
+ try (if (stringp name)
+ (file-exists-p (expand-file-name name file))
(funcall name file)))
(cond (try (setq root file))
((equal file (setq file (file-name-directory
@@ -1244,6 +1246,29 @@ See `load-file' for a different interface to `load'."
(interactive (list (read-library-name)))
(load library))
+(defun require-with-check (feature &optional filename noerror)
+ "If FEATURE is not already loaded, load it from FILENAME.
+This is like `require' except if FEATURE is already a member of the list
+`features’, then we check if this was provided by a different file than the
+one that we would load now (presumably because `load-path' has been
+changed since the file was loaded).
+If it's the case, we either signal an error (the default), or forcibly reload
+the new file (if NOERROR is equal to `reload'), or otherwise emit a warning."
+ (let ((lh load-history)
+ (res (require feature filename (if (eq noerror 'reload) nil noerror))))
+ ;; If the `feature' was not yet provided, `require' just loaded the right
+ ;; file, so we're done.
+ (when (eq lh load-history)
+ ;; If `require' did nothing, we need to make sure that was warranted.
+ (let ((fn (locate-file (or filename (symbol-name feature))
+ load-path (get-load-suffixes))))
+ (cond
+ ((assoc fn load-history) nil) ;We loaded the right file.
+ ((eq noerror 'reload) (load fn nil 'nomessage))
+ (t (funcall (if noerror #'warn #'error)
+ "Feature provided by other file: %S" feature)))))
+ res))
+
(defun file-remote-p (file &optional identification connected)
"Test whether FILE specifies a location on a remote system.
A file is considered remote if accessing it is likely to
@@ -1283,10 +1308,8 @@ Tip: You can use this expansion of remote identifier components
returns a remote file name for file \"/bin/sh\" that has the
same remote identifier as FILE but expanded; a name such as
\"/sudo:root@myhost:/bin/sh\"."
- (let ((handler (find-file-name-handler file 'file-remote-p)))
- (if handler
- (funcall handler 'file-remote-p file identification connected)
- nil)))
+ (when-let ((handler (find-file-name-handler file 'file-remote-p)))
+ (funcall handler 'file-remote-p file identification connected)))
;; Probably this entire variable should be obsolete now, in favor of
;; something Tramp-related (?). It is not used in many places.
@@ -1296,7 +1319,7 @@ Tip: You can use this expansion of remote identifier components
(defcustom remote-shell-program (or (executable-find "ssh") "ssh")
"Program to use to execute commands on a remote host (i.e. ssh)."
:version "29.1"
- :initialize 'custom-initialize-delay
+ :initialize #'custom-initialize-delay
:group 'environment
:type 'file)
@@ -1324,10 +1347,10 @@ consecutive checks. For example:
:group 'tramp
:version "24.1"
:type '(choice
- (const :tag "Do not inhibit file name cache" nil)
- (const :tag "Do not use file name cache" t)
- (integer :tag "Do not use file name cache"
- :format "Do not use file name cache older then %v seconds"
+ (const :tag "Do not cache remote file attributes" t)
+ (const :tag "Cache remote file attributes" nil)
+ (integer :tag "Cache remote file attributes with expiration"
+ :format "Cache expiry in seconds: %v"
:value 10)))
(defcustom remote-file-name-access-timeout nil
@@ -2185,37 +2208,33 @@ and others are ignored. PREDICATE is called with the buffer as
the only argument, but not with the buffer as the current buffer.
If there is no such live buffer, return nil."
- (let ((predicate (or predicate #'identity))
- (truename (abbreviate-file-name (file-truename filename))))
- (or (let ((buf (get-file-buffer filename)))
- (when (and buf (funcall predicate buf)) buf))
- (let ((list (buffer-list)) found)
- (while (and (not found) list)
- (with-current-buffer (car list)
- (if (and buffer-file-name
- (string= buffer-file-truename truename)
- (funcall predicate (current-buffer)))
- (setq found (car list))))
- (setq list (cdr list)))
- found)
- (let* ((attributes (file-attributes truename))
- (number (file-attribute-file-identifier attributes))
- (list (buffer-list)) found)
- (and buffer-file-numbers-unique
- (car-safe number) ;Make sure the inode is not just nil.
- (while (and (not found) list)
- (with-current-buffer (car list)
- (if (and buffer-file-name
- (equal buffer-file-number number)
- ;; Verify this buffer's file number
- ;; still belongs to its file.
- (file-exists-p buffer-file-name)
- (equal (file-attributes buffer-file-truename)
- attributes)
- (funcall predicate (current-buffer)))
- (setq found (car list))))
- (setq list (cdr list))))
- found))))
+ (or (let ((buf (get-file-buffer filename)))
+ (when (and buf (or (not predicate) (funcall predicate buf))) buf))
+ (let ((truename (abbreviate-file-name (file-truename filename))))
+ (or
+ (let ((buf (get-truename-buffer truename)))
+ (when (and buf (buffer-local-value 'buffer-file-name buf)
+ (or (not predicate) (funcall predicate buf)))
+ buf))
+ (let* ((attributes (file-attributes truename))
+ (number (file-attribute-file-identifier attributes)))
+ (and buffer-file-numbers-unique
+ (car-safe number) ;Make sure the inode is not just nil.
+ (let* ((buf (find-buffer 'buffer-file-number number))
+ (buf-file-name
+ (and buf (buffer-local-value 'buffer-file-name buf))))
+ (when (and buf-file-name
+ ;; Verify this buffer's file number
+ ;; still belongs to its file.
+ (file-exists-p buf-file-name)
+ (equal (file-attributes
+ (buffer-local-value
+ 'buffer-file-truename buf))
+ attributes)
+ (or (not predicate)
+ (funcall predicate buf)))
+ buf))))))))
+
(defcustom find-file-wildcards t
"Non-nil means file-visiting commands should handle wildcards.
@@ -3245,8 +3264,16 @@ and `inhibit-local-variables-suffixes'. If
temp))
(defvar auto-mode-interpreter-regexp
- (purecopy "#![ \t]?\\([^ \t\n]*\
-/bin/env[ \t]\\)?\\([^ \t\n]+\\)")
+ (purecopy
+ (concat
+ "#![ \t]*"
+ ;; Optional group 1: env(1) invocation.
+ "\\("
+ "[^ \t\n]*/bin/env[ \t]*"
+ "\\(?:-S[ \t]*\\|--split-string\\(?:=\\|[ \t]*\\)\\)?"
+ "\\)?"
+ ;; Group 2: interpreter.
+ "\\([^ \t\n]+\\)"))
"Regexp matching interpreters, for file mode determination.
This regular expression is matched against the first line of a file
to determine the file's mode in `set-auto-mode'. If it matches, the file
@@ -4585,12 +4612,7 @@ applied in order then that means the more specific modes will
variables will override modes."
(let ((key (car node)))
(cond ((null key) -1)
- ((symbolp key)
- (let ((mode key)
- (depth 0))
- (while (setq mode (get mode 'derived-mode-parent))
- (setq depth (1+ depth)))
- depth))
+ ((symbolp key) (length (derived-mode-all-parents key)))
((stringp key)
(+ 1000 (length key)))
(t -2))))
@@ -5935,9 +5957,11 @@ Before and after saving the buffer, this function runs
buffer-file-name)
t))
;; If file not writable, see if we can make it writable
- ;; temporarily while we write it.
- ;; But no need to do so if we have just backed it up
- ;; (setmodes is set) because that says we're superseding.
+ ;; temporarily while we write it (its original modes will be
+ ;; restored in 'basic-save-buffer' or, in case of an error, in
+ ;; the `unwind-protect' below). But no need to do so if we
+ ;; have just backed it up (setmodes is set) because that says
+ ;; we're superseding.
(cond ((and tempsetmodes (not setmodes))
;; Change the mode back, after writing.
(setq setmodes
@@ -5946,12 +5970,17 @@ Before and after saving the buffer, this function runs
"Error getting extended attributes: %s"
(file-extended-attributes buffer-file-name))
buffer-file-name))
- ;; If set-file-extended-attributes fails, fall back on
- ;; set-file-modes.
- (unless
- (with-demoted-errors "Error setting attributes: %s"
- (set-file-extended-attributes buffer-file-name
- (nth 1 setmodes)))
+ ;; If set-file-extended-attributes fails to make the
+ ;; file writable, fall back on set-file-modes. Calling
+ ;; set-file-extended-attributes here may or may not be
+ ;; actually necessary. However, since its exact
+ ;; behavior is highly port-specific, since calling it
+ ;; does not do any harm, and since the call has a long
+ ;; history, we decided to leave it in (bug#66546).
+ (with-demoted-errors "Error setting attributes: %s"
+ (set-file-extended-attributes buffer-file-name
+ (nth 1 setmodes)))
+ (unless (file-writable-p buffer-file-name)
(set-file-modes buffer-file-name
(logior (car setmodes) 128)))))
(let (success)
@@ -5964,12 +5993,22 @@ Before and after saving the buffer, this function runs
buffer-file-name nil t buffer-file-truename)
(when save-silently (message nil))
(setq success t))
- ;; If we get an error writing the new file, and we made
- ;; the backup by renaming, undo the backing-up.
- (and setmodes (not success)
- (progn
- (rename-file (nth 2 setmodes) buffer-file-name t)
- (setq buffer-backed-up nil)))))))
+ (cond
+ ;; If we get an error writing the file, and there is no
+ ;; backup file, then we (most likely) made that file
+ ;; writable above. Attempt to undo the write-access.
+ ((and setmodes (not success)
+ (equal (nth 2 setmodes) buffer-file-name))
+ (with-demoted-errors "Error setting file modes: %S"
+ (set-file-modes buffer-file-name (car setmodes)))
+ (with-demoted-errors "Error setting attributes: %s"
+ (set-file-extended-attributes buffer-file-name
+ (nth 1 setmodes))))
+ ;; If we get an error writing the new file, and we made
+ ;; the backup by renaming, undo the backing-up.
+ ((and setmodes (not success))
+ (rename-file (nth 2 setmodes) buffer-file-name t)
+ (setq buffer-backed-up nil)))))))
setmodes))
(declare-function diff-no-select "diff"
@@ -6070,14 +6109,18 @@ See `save-some-buffers' for PRED values."
(defvar save-some-buffers-functions nil
"Functions to be run by `save-some-buffers' after saving the buffers.
-The functions can be called in two \"modes\", depending on the
-first argument. If the first argument is `query', then the
+These functions should accept one mandatory and one optional
+argument, and they can be called in two \"modes\", depending on
+the first argument. If the first argument is `query', then the
function should return non-nil if there is something to be
saved (but it should not actually save anything).
If the first argument is something else, then the function should
save according to the value of the second argument, which is the
-ARG argument from `save-some-buffers'.")
+ARG argument with which `save-some-buffers' was called.
+
+The main purpose of these functions is to save stuff that is kept
+in variables (rather than in buffers).")
(defun save-some-buffers (&optional arg pred)
"Save some modified file-visiting buffers. Asks user about each one.
@@ -6624,7 +6667,15 @@ into NEWNAME instead."
(file-attributes directory))))
(follow-flag (unless follow 'nofollow)))
(if modes (set-file-modes newname modes follow-flag))
- (if times (set-file-times newname times follow-flag)))))))
+ (when times
+ ;; When built for an Android GUI build, don't attempt to
+ ;; set file times for a file within /content, as the
+ ;; Android VFS layer does not provide means to change file
+ ;; timestamps.
+ (when (or (not (and (eq system-type 'android)
+ (featurep 'android)))
+ (not (string-prefix-p "/content/" newname)))
+ (set-file-times newname times follow-flag))))))))
;; At time of writing, only info uses this.
@@ -7051,11 +7102,19 @@ auto-save file, if that is more recent than the visited file."
#'(lambda (window _value)
(with-selected-window window
(unwind-protect
- (yes-or-no-p (format "Recover auto save file %s? " file-name))
+ (let ((prompt (format "Recover auto save file %s? " file-name))
+ (choices
+ '(("yes" ?y "recover auto save file")
+ ("no" ?n "don't recover auto save file")
+ ("diff" ?= "show changes between auto save file and current file")))
+ ans)
+ (while (equal "diff" (setq ans (read-answer prompt choices)))
+ (diff file file-name))
+ (equal ans "yes"))
(when (window-live-p window)
(quit-restore-window window 'kill)))))
(with-current-buffer standard-output
- (let ((switches dired-listing-switches))
+ (let ((switches (connection-local-value dired-listing-switches)))
(if (file-symlink-p file)
(setq switches (concat switches " -L")))
;; Use insert-directory-safely, not insert-directory,
@@ -7107,7 +7166,7 @@ Then you'll be asked about a number of files to recover."
;; hook.
(dired-mode-hook (delete 'dired-omit-mode dired-mode-hook)))
(dired (concat auto-save-list-file-prefix "*")
- (concat dired-listing-switches " -t")))
+ (concat (connection-local-value dired-listing-switches) " -t")))
(use-local-map (nconc (make-sparse-keymap) (current-local-map)))
(define-key (current-local-map) "\C-c\C-c" 'recover-session-finish)
(save-excursion
@@ -7507,35 +7566,42 @@ default directory. However, if FULL is non-nil, they are absolute."
;; if DIRPART contains wildcards.
(dirs (if (and dirpart
(string-match "[[*?]" (file-local-name dirpart)))
- (mapcar 'file-name-as-directory
+ (mapcar #'file-name-as-directory
(file-expand-wildcards
(directory-file-name dirpart) nil regexp))
(list dirpart)))
contents)
- (dolist (dir dirs)
+ (dolist (dir (nreverse dirs))
(when (or (null dir) ; Possible if DIRPART is not wild.
(file-accessible-directory-p dir))
- (let ((this-dir-contents
- ;; Filter out "." and ".."
- (delq nil
- (mapcar (lambda (name)
- (unless (string-match "\\`\\.\\.?\\'"
- (file-name-nondirectory name))
- name))
- (directory-files
- (or dir ".") full
- (if regexp
- ;; We're matching each file name
- ;; element separately.
- (concat "\\`" nondir "\\'")
- (wildcard-to-regexp nondir)))))))
- (setq contents
- (nconc
- (if (and dir (not full))
- (mapcar (lambda (name) (concat dir name))
- this-dir-contents)
- this-dir-contents)
- contents)))))
+ (if (equal "" nondir)
+ ;; `nondir' is "" when the pattern ends in "/". Basically ""
+ ;; refers to the directory itself, like ".", but it's not
+ ;; among the names returned by `directory-files', so we have
+ ;; to special-case it.
+ (push (or dir nondir) contents)
+ (let ((this-dir-contents
+ ;; Filter out "." and ".."
+ (delq nil
+ (mapcar (lambda (name)
+ (unless (string-match "\\`\\.\\.?\\'"
+ (file-name-nondirectory
+ name))
+ name))
+ (directory-files
+ (or dir ".") full
+ (if regexp
+ ;; We're matching each file name
+ ;; element separately.
+ (concat "\\`" nondir "\\'")
+ (wildcard-to-regexp nondir)))))))
+ (setq contents
+ (nconc
+ (if (and dir (not full))
+ (mapcar (lambda (name) (concat dir name))
+ this-dir-contents)
+ this-dir-contents)
+ contents))))))
contents)))
(defcustom find-sibling-rules nil
@@ -7562,7 +7628,8 @@ files, you could say something like:
In this example, if you're in \"src/emacs/emacs-27/lisp/abbrev.el\",
and a \"src/emacs/emacs-28/lisp/abbrev.el\" file exists, it's now
defined as a sibling."
- :type 'sexp
+ :type '(alist :key-type (regexp :tag "Match")
+ :value-type (repeat (string :tag "Expansion")))
:version "29.1")
(defun find-sibling-file (file)
@@ -7717,10 +7784,38 @@ need to be passed verbatim to shell commands."
pattern))))
-(defvar insert-directory-program (purecopy "ls")
+(defcustom insert-directory-program
+ (if (and (memq system-type '(berkeley-unix darwin))
+ (executable-find "gls"))
+ (purecopy "gls")
+ (purecopy "ls"))
"Absolute or relative name of the `ls'-like program.
This is used by `insert-directory' and `dired-insert-directory'
-\(thus, also by `dired').")
+\(thus, also by `dired'). For Dired, this should ideally point to
+GNU ls, or another version of ls that supports the \"--dired\"
+flag. See `dired-use-ls-dired'.
+
+On GNU/Linux and other capable systems, the default is \"ls\".
+
+On *BSD and macOS systems, the default \"ls\" does not support
+the \"--dired\" flag. Therefore, the default is to use the
+\"gls\" executable on such machines, if it exists. This means
+that there should normally be no need to customize this when
+installing GNU coreutils using something like ports or Homebrew."
+ :group 'dired
+ :type 'string
+ :initialize #'custom-initialize-delay
+ :version "30.1")
+
+(defun files--use-insert-directory-program-p ()
+ "Return non-nil if we should use `insert-directory-program'.
+Return nil if we should prefer `ls-lisp' instead."
+ ;; FIXME: Should we also check `file-accessible-directory-p' so we
+ ;; automatically redirect to ls-lisp when operating on magic file names?
+ (and (if (boundp 'ls-lisp-use-insert-directory-program)
+ ls-lisp-use-insert-directory-program
+ t)
+ insert-directory-program))
(defcustom directory-free-space-program (purecopy "df")
"Program to get the amount of free space on a file system.
@@ -7914,9 +8009,11 @@ Optional third arg WILDCARD means treat FILE as shell wildcard.
Optional fourth arg FULL-DIRECTORY-P means file is a directory and
switches do not contain `d', so that a full listing is expected.
-This works by running a directory listing program
-whose name is in the variable `insert-directory-program'.
-If WILDCARD, it also runs the shell specified by `shell-file-name'.
+Depending on the value of `ls-lisp-use-insert-directory-program'
+this works either using a Lisp emulation of the \"ls\" program
+or by running a directory listing program
+whose name is in the variable `insert-directory-program'
+\(and if WILDCARD, it also runs the shell specified by `shell-file-name').
When SWITCHES contains the long `--dired' option, this function
treats it specially, for the sake of dired. However, the
@@ -7925,184 +8022,191 @@ normally equivalent short `-D' option is just passed on to
;; We need the directory in order to find the right handler.
(let ((handler (find-file-name-handler (expand-file-name file)
'insert-directory)))
- (if handler
- (funcall handler 'insert-directory file switches
- wildcard full-directory-p)
- (let (result (beg (point)))
-
- ;; Read the actual directory using `insert-directory-program'.
- ;; RESULT gets the status code.
- (let* (;; We at first read by no-conversion, then after
- ;; putting text property `dired-filename, decode one
- ;; bunch by one to preserve that property.
- (coding-system-for-read 'no-conversion)
- ;; This is to control encoding the arguments in call-process.
- (coding-system-for-write
- (and enable-multibyte-characters
- (or file-name-coding-system
- default-file-name-coding-system))))
- (setq result
- (if wildcard
- ;; If the wildcard is just in the file part, then run ls in
- ;; the directory part of the file pattern using the last
- ;; component as argument. Otherwise, run ls in the longest
- ;; subdirectory of the directory part free of wildcards; use
- ;; the remaining of the file pattern as argument.
- (let* ((dir-wildcard (insert-directory-wildcard-in-dir-p file))
- (default-directory
- (cond (dir-wildcard (car dir-wildcard))
- (t
- (if (file-name-absolute-p file)
- (file-name-directory file)
- (file-name-directory (expand-file-name file))))))
- (pattern (if dir-wildcard (cdr dir-wildcard) (file-name-nondirectory file))))
- ;; NB since switches is passed to the shell, be
- ;; careful of malicious values, eg "-l;reboot".
- ;; See eg dired-safe-switches-p.
- (call-process
- shell-file-name nil t nil
- shell-command-switch
- (concat (if (memq system-type '(ms-dos windows-nt))
- ""
- "\\") ; Disregard Unix shell aliases!
- insert-directory-program
- " -d "
- (if (stringp switches)
- switches
- (mapconcat 'identity switches " "))
- " -- "
- ;; Quote some characters that have
- ;; special meanings in shells; but
- ;; don't quote the wildcards--we want
- ;; them to be special. We also
- ;; currently don't quote the quoting
- ;; characters in case people want to
- ;; use them explicitly to quote
- ;; wildcard characters.
- (shell-quote-wildcard-pattern pattern))))
- ;; SunOS 4.1.3, SVr4 and others need the "." to list the
- ;; directory if FILE is a symbolic link.
- (unless full-directory-p
- (setq switches
- (cond
- ((stringp switches) (concat switches " -d"))
- ((member "-d" switches) switches)
- (t (append switches '("-d"))))))
- (if (string-match "\\`~" file)
- (setq file (expand-file-name file)))
- (apply 'call-process
- insert-directory-program nil t nil
- (append
- (if (listp switches) switches
- (unless (equal switches "")
- ;; Split the switches at any spaces so we can
- ;; pass separate options as separate args.
- (split-string-and-unquote switches)))
- ;; Avoid lossage if FILE starts with `-'.
- '("--")
- (list file))))))
-
- ;; If we got "//DIRED//" in the output, it means we got a real
- ;; directory listing, even if `ls' returned nonzero.
- ;; So ignore any errors.
- (when (if (stringp switches)
- (string-match "--dired\\>" switches)
- (member "--dired" switches))
- (save-excursion
- (forward-line -2)
- (when (looking-at "//SUBDIRED//")
- (forward-line -1))
- (if (looking-at "//DIRED//")
- (setq result 0))))
-
- (when (and (not (eq 0 result))
- (eq insert-directory-ls-version 'unknown))
- ;; The first time ls returns an error,
- ;; find the version numbers of ls,
- ;; and set insert-directory-ls-version
- ;; to > if it is more than 5.2.1, < if it is less, nil if it
- ;; is equal or if the info cannot be obtained.
- ;; (That can mean it isn't GNU ls.)
- (let ((version-out
- (with-temp-buffer
- (call-process "ls" nil t nil "--version")
- (buffer-string))))
- (if (string-match "ls (.*utils) \\([0-9.]*\\)$" version-out)
- (let* ((version (match-string 1 version-out))
- (split (split-string version "[.]"))
- (numbers (mapcar 'string-to-number split))
- (min '(5 2 1))
- comparison)
- (while (and (not comparison) (or numbers min))
- (cond ((null min)
- (setq comparison '>))
- ((null numbers)
- (setq comparison '<))
- ((> (car numbers) (car min))
- (setq comparison '>))
- ((< (car numbers) (car min))
- (setq comparison '<))
- (t
- (setq numbers (cdr numbers)
- min (cdr min)))))
- (setq insert-directory-ls-version (or comparison '=)))
- (setq insert-directory-ls-version nil))))
-
- ;; For GNU ls versions 5.2.2 and up, ignore minor errors.
- (when (and (eq 1 result) (eq insert-directory-ls-version '>))
- (setq result 0))
-
- ;; If `insert-directory-program' failed, signal an error.
- (unless (eq 0 result)
- ;; Delete the error message it may have output.
- (delete-region beg (point))
- ;; On non-Posix systems, we cannot open a directory, so
- ;; don't even try, because that will always result in
- ;; the ubiquitous "Access denied". Instead, show the
- ;; command line so the user can try to guess what went wrong.
- (if (and (file-directory-p file)
- (memq system-type '(ms-dos windows-nt)))
- (error
- "Reading directory: \"%s %s -- %s\" exited with status %s"
- insert-directory-program
- (if (listp switches) (concat switches) switches)
- file result)
- ;; Unix. Access the file to get a suitable error.
- (access-file file "Reading directory")
- (error "Listing directory failed but `access-file' worked")))
- (insert-directory-clean beg switches)
- ;; Now decode what read if necessary.
- (let ((coding (or coding-system-for-read
- file-name-coding-system
- default-file-name-coding-system
- 'undecided))
- coding-no-eol
- val pos)
- (when (and enable-multibyte-characters
- (not (memq (coding-system-base coding)
- '(raw-text no-conversion))))
- ;; If no coding system is specified or detection is
- ;; requested, detect the coding.
- (if (eq (coding-system-base coding) 'undecided)
- (setq coding (detect-coding-region beg (point) t)))
- (if (not (eq (coding-system-base coding) 'undecided))
- (save-restriction
- (setq coding-no-eol
- (coding-system-change-eol-conversion coding 'unix))
- (narrow-to-region beg (point))
- (goto-char (point-min))
- (while (not (eobp))
- (setq pos (point)
- val (get-text-property (point) 'dired-filename))
- (goto-char (next-single-property-change
- (point) 'dired-filename nil (point-max)))
- ;; Force no eol conversion on a file name, so
- ;; that CR is preserved.
- (decode-coding-region pos (point)
- (if val coding-no-eol coding))
- (if val
- (put-text-property pos (point)
- 'dired-filename t)))))))))))
+ (cond
+ (handler
+ (funcall handler 'insert-directory file switches
+ wildcard full-directory-p))
+ ((not (files--use-insert-directory-program-p))
+ (require 'ls-lisp)
+ (declare-function ls-lisp--insert-directory "ls-lisp")
+ (ls-lisp--insert-directory file switches wildcard full-directory-p))
+ (t
+ (let (result (beg (point)))
+
+ ;; Read the actual directory using `insert-directory-program'.
+ ;; RESULT gets the status code.
+ (let* (;; We at first read by no-conversion, then after
+ ;; putting text property `dired-filename, decode one
+ ;; bunch by one to preserve that property.
+ (coding-system-for-read 'no-conversion)
+ ;; This is to control encoding the arguments in call-process.
+ (coding-system-for-write
+ (and enable-multibyte-characters
+ (or file-name-coding-system
+ default-file-name-coding-system))))
+ (setq result
+ (if wildcard
+ ;; If the wildcard is just in the file part, then run ls in
+ ;; the directory part of the file pattern using the last
+ ;; component as argument. Otherwise, run ls in the longest
+ ;; subdirectory of the directory part free of wildcards; use
+ ;; the remaining of the file pattern as argument.
+ (let* ((dir-wildcard (insert-directory-wildcard-in-dir-p file))
+ (default-directory
+ (cond (dir-wildcard (car dir-wildcard))
+ (t
+ (if (file-name-absolute-p file)
+ (file-name-directory file)
+ (file-name-directory (expand-file-name file))))))
+ (pattern (if dir-wildcard (cdr dir-wildcard) (file-name-nondirectory file))))
+ ;; NB since switches is passed to the shell, be
+ ;; careful of malicious values, eg "-l;reboot".
+ ;; See eg dired-safe-switches-p.
+ (call-process
+ shell-file-name nil t nil
+ shell-command-switch
+ (concat (if (memq system-type '(ms-dos windows-nt))
+ ""
+ "\\") ; Disregard Unix shell aliases!
+ insert-directory-program
+ " -d "
+ (if (stringp switches)
+ switches
+ (mapconcat #'identity switches " "))
+ " -- "
+ ;; Quote some characters that have
+ ;; special meanings in shells; but
+ ;; don't quote the wildcards--we want
+ ;; them to be special. We also
+ ;; currently don't quote the quoting
+ ;; characters in case people want to
+ ;; use them explicitly to quote
+ ;; wildcard characters.
+ (shell-quote-wildcard-pattern pattern))))
+ ;; SunOS 4.1.3, SVr4 and others need the "." to list the
+ ;; directory if FILE is a symbolic link.
+ (unless full-directory-p
+ (setq switches
+ (cond
+ ((stringp switches) (concat switches " -d"))
+ ((member "-d" switches) switches)
+ (t (append switches '("-d"))))))
+ (if (string-match "\\`~" file)
+ (setq file (expand-file-name file)))
+ (apply #'call-process
+ insert-directory-program nil t nil
+ (append
+ (if (listp switches) switches
+ (unless (equal switches "")
+ ;; Split the switches at any spaces so we can
+ ;; pass separate options as separate args.
+ (split-string-and-unquote switches)))
+ ;; Avoid lossage if FILE starts with `-'.
+ '("--")
+ (list file))))))
+
+ ;; If we got "//DIRED//" in the output, it means we got a real
+ ;; directory listing, even if `ls' returned nonzero.
+ ;; So ignore any errors.
+ (when (if (stringp switches)
+ (string-match "--dired\\>" switches)
+ (member "--dired" switches))
+ (save-excursion
+ (forward-line -2)
+ (when (looking-at "//SUBDIRED//")
+ (forward-line -1))
+ (if (looking-at "//DIRED//")
+ (setq result 0))))
+
+ (when (and (not (eq 0 result))
+ (eq insert-directory-ls-version 'unknown))
+ ;; The first time ls returns an error,
+ ;; find the version numbers of ls,
+ ;; and set insert-directory-ls-version
+ ;; to > if it is more than 5.2.1, < if it is less, nil if it
+ ;; is equal or if the info cannot be obtained.
+ ;; (That can mean it isn't GNU ls.)
+ (let ((version-out
+ (with-temp-buffer
+ (call-process "ls" nil t nil "--version")
+ (buffer-string))))
+ (setq insert-directory-ls-version
+ (if (string-match "ls (.*utils) \\([0-9.]*\\)$" version-out)
+ (let* ((version (match-string 1 version-out))
+ (split (split-string version "[.]"))
+ (numbers (mapcar #'string-to-number split))
+ (min '(5 2 1))
+ comparison)
+ (while (and (not comparison) (or numbers min))
+ (cond ((null min)
+ (setq comparison #'>))
+ ((null numbers)
+ (setq comparison #'<))
+ ((> (car numbers) (car min))
+ (setq comparison #'>))
+ ((< (car numbers) (car min))
+ (setq comparison #'<))
+ (t
+ (setq numbers (cdr numbers)
+ min (cdr min)))))
+ (or comparison #'=))
+ nil))))
+
+ ;; For GNU ls versions 5.2.2 and up, ignore minor errors.
+ (when (and (eq 1 result) (eq insert-directory-ls-version #'>))
+ (setq result 0))
+
+ ;; If `insert-directory-program' failed, signal an error.
+ (unless (eq 0 result)
+ ;; Delete the error message it may have output.
+ (delete-region beg (point))
+ ;; On non-Posix systems, we cannot open a directory, so
+ ;; don't even try, because that will always result in
+ ;; the ubiquitous "Access denied". Instead, show the
+ ;; command line so the user can try to guess what went wrong.
+ (if (and (file-directory-p file)
+ (memq system-type '(ms-dos windows-nt)))
+ (error
+ "Reading directory: \"%s %s -- %s\" exited with status %s"
+ insert-directory-program
+ (if (listp switches) (concat switches) switches)
+ file result)
+ ;; Unix. Access the file to get a suitable error.
+ (access-file file "Reading directory")
+ (error "Listing directory failed but `access-file' worked")))
+ (insert-directory-clean beg switches)
+ ;; Now decode what read if necessary.
+ (let ((coding (or coding-system-for-read
+ file-name-coding-system
+ default-file-name-coding-system
+ 'undecided))
+ coding-no-eol
+ val pos)
+ (when (and enable-multibyte-characters
+ (not (memq (coding-system-base coding)
+ '(raw-text no-conversion))))
+ ;; If no coding system is specified or detection is
+ ;; requested, detect the coding.
+ (if (eq (coding-system-base coding) 'undecided)
+ (setq coding (detect-coding-region beg (point) t)))
+ (if (not (eq (coding-system-base coding) 'undecided))
+ (save-restriction
+ (setq coding-no-eol
+ (coding-system-change-eol-conversion coding 'unix))
+ (narrow-to-region beg (point))
+ (goto-char (point-min))
+ (while (not (eobp))
+ (setq pos (point)
+ val (get-text-property (point) 'dired-filename))
+ (goto-char (next-single-property-change
+ (point) 'dired-filename nil (point-max)))
+ ;; Force no eol conversion on a file name, so
+ ;; that CR is preserved.
+ (decode-coding-region pos (point)
+ (if val coding-no-eol coding))
+ (if val
+ (put-text-property pos (point)
+ 'dired-filename t))))))))))))
(defun insert-directory-adj-pos (pos error-lines)
"Convert `ls --dired' file name position value POS to a buffer position.
@@ -8289,13 +8393,12 @@ arguments as the running Emacs)."
;; Get a list of the indices of the args that are file names.
(file-arg-indices
(cdr (or (assq operation
- '(;; The first eight are special because they
+ '(;; The first seven are special because they
;; return a file name. We want to include
;; the /: in the return value. So just
;; avoid stripping it in the first place.
(abbreviate-file-name)
(directory-file-name)
- (expand-file-name)
(file-name-as-directory)
(file-name-directory)
(file-name-sans-versions)
@@ -8304,6 +8407,10 @@ arguments as the running Emacs)."
;; `identity' means just return the first
;; arg not stripped of its quoting.
(substitute-in-file-name identity)
+ ;; `expand-file-name' shall do special case
+ ;; for the first argument starting with
+ ;; "/:~". (Bug#65685)
+ (expand-file-name expand-file-name)
;; `add' means add "/:" to the result.
(file-truename add 0)
;;`insert-file-contents' needs special handling.
@@ -8359,6 +8466,10 @@ arguments as the running Emacs)."
(let ((tramp-mode (and tramp-mode (eq method 'local-copy))))
(pcase method
('identity (car arguments))
+ ('expand-file-name
+ (when (string-prefix-p "/:~" (car arguments))
+ (setcar arguments (file-name-unquote (car arguments) t)))
+ (apply operation arguments))
('add (file-name-quote (apply operation arguments) t))
('buffer-file-name
(let ((buffer-file-name (file-name-unquote buffer-file-name t)))
diff --git a/lisp/filesets.el b/lisp/filesets.el
index 81a194a45e6..7332687d46d 100644
--- a/lisp/filesets.el
+++ b/lisp/filesets.el
@@ -1,6 +1,6 @@
;;; filesets.el --- handle group of files -*- lexical-binding: t; -*-
-;; Copyright (C) 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2024 Free Software Foundation, Inc.
;; Author: Thomas Link <sanobast-emacs@yahoo.de>
;; Maintainer: emacs-devel@gnu.org
@@ -413,15 +413,14 @@ directory's name.
Note: You have to manually rebuild the menu if you change this value."
:set #'filesets-set-default
- :type '(choice :tag "Function:"
+ :type '(choice :tag "Function"
(const :tag "dired"
:value dired)
(list :tag "Command"
:value ("" "%s")
(string :tag "Name")
(string :tag "Arguments"))
- (function :tag "Function"
- :value nil)))
+ (function :tag "Function")))
(defcustom filesets-open-file-function #'filesets-find-or-display-file
"The function used for opening files.
@@ -437,23 +436,21 @@ readable, will not be opened.
Caveat: Changes will take effect only after rebuilding the menu."
:set #'filesets-set-default
- :type '(choice :tag "Function:"
+ :type '(choice :tag "Function"
(const :tag "filesets-find-or-display-file"
:value filesets-find-or-display-file)
(const :tag "filesets-find-file"
:value filesets-find-file)
- (function :tag "Function"
- :value nil)))
+ (function :tag "Function")))
(defcustom filesets-save-buffer-function #'save-buffer
"The function used to save a buffer.
Caveat: Changes will take effect after rebuilding the menu."
:set #'filesets-set-default
- :type '(choice :tag "Function:"
+ :type '(choice :tag "Function"
(const :tag "save-buffer"
:value save-buffer)
- (function :tag "Function"
- :value nil)))
+ (function :tag "Function")))
(defcustom filesets-find-file-delay
(if (and (featurep 'xemacs) gutter-buffers-tab-visible-p)
@@ -535,7 +532,7 @@ the filename."
:type '(repeat :tag "Commands"
(list :tag "Definition" :value ("")
(string "Name")
- (choice :tag "Command"
+ (choice :tag "Command" :value ""
(string :tag "String")
(function :tag "Function"))
(repeat :tag "Argument List"
@@ -546,8 +543,7 @@ the filename."
:value "<file-name>")
(string :tag "Quoted File Name"
:value "<<file-name>>")
- (function :tag "Function"
- :value nil))))))
+ (function :tag "Function"))))))
(defcustom filesets-external-viewers
(let
@@ -647,12 +643,12 @@ In order to view pdf or rtf files in an Emacs buffer, you could use these:
(repeat :tag "Properties"
(choice
(list :tag ":constraintp"
- :value (:constraintp)
+ :value (:constraintp ignore)
(const :format ""
:value :constraintp)
(function :tag "Function"))
(list :tag ":constraint-flag (obsolete)"
- :value (:constraint-flag)
+ :value (:constraint-flag nil)
(const :format ""
:value :constraint-flag)
(sexp :tag "Symbol"))
@@ -667,7 +663,7 @@ In order to view pdf or rtf files in an Emacs buffer, you could use these:
:value :ignore-on-read-text)
(boolean :tag "Boolean"))
(list :tag ":args"
- :value (:args)
+ :value (:args nil)
(const :format ""
:value :args)
(repeat :tag "List"
@@ -676,10 +672,9 @@ In order to view pdf or rtf files in an Emacs buffer, you could use these:
:value "")
(symbol :tag "Symbol"
:value nil)
- (function :tag "Function"
- :value nil))))
+ (function :tag "Function"))))
(list :tag ":open-hook"
- :value (:open-hook)
+ :value (:open-hook nil)
(const :format ""
:value :open-hook)
(hook :tag "Hook"))
@@ -1653,7 +1648,17 @@ Assume MODE (see `filesets-entry-mode'), if provided."
(filesets-entry-get-master entry)))))
(cons entry (filesets-ingroup-cache-get entry))))
(:tree
- (let* ((dirpatt (filesets-entry-get-tree entry))
+ ;; Warning: ENTRY here could be of at least two
+ ;; differente forms, either
+ ;; (NAME (:tree DIRECTORY PATTERN))
+ ;; or
+ ;; (DIRECTORY PATTERN)
+ ;; The latter happens when opening a tree fileset
+ ;; from the Filesets menu. We need to support both
+ ;; of these forms!
+ (let* ((dirpatt (if (consp (nth 1 entry))
+ (filesets-entry-get-tree entry)
+ entry))
(dir (nth 0 dirpatt))
(patt (nth 1 dirpatt))
(depth (or (filesets-entry-get-tree-max-level entry)
diff --git a/lisp/find-cmd.el b/lisp/find-cmd.el
index 6e18113f69f..a148e59bd5c 100644
--- a/lisp/find-cmd.el
+++ b/lisp/find-cmd.el
@@ -1,6 +1,6 @@
;;; find-cmd.el --- Build a valid find(1) command with sexps -*- lexical-binding: t -*-
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
;; Author: Philip Jackson <phil@shellarchive.co.uk>
;; Version: 0.6
diff --git a/lisp/find-dired.el b/lisp/find-dired.el
index 48408d35499..41581cc7900 100644
--- a/lisp/find-dired.el
+++ b/lisp/find-dired.el
@@ -1,6 +1,6 @@
;;; find-dired.el --- run a `find' command and dired the output -*- lexical-binding: t -*-
-;; Copyright (C) 1992-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1992-2024 Free Software Foundation, Inc.
;; Author: Roland McGrath <roland@gnu.org>,
;; Sebastian Kremer <sk@thp.uni-koeln.de>
diff --git a/lisp/find-file.el b/lisp/find-file.el
index 05459c3643d..c4c61e6abe6 100644
--- a/lisp/find-file.el
+++ b/lisp/find-file.el
@@ -4,7 +4,7 @@
;; Maintainer: emacs-devel@gnu.org
;; Keywords: c, matching, tools
-;; Copyright (C) 1994-1995, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1994-1995, 2001-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/lisp/find-lisp.el b/lisp/find-lisp.el
index dd91d963c3a..0b6f9d35ad8 100644
--- a/lisp/find-lisp.el
+++ b/lisp/find-lisp.el
@@ -4,7 +4,7 @@
;; Created: Fri Mar 26 1999
;; Keywords: unix
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/lisp/finder.el b/lisp/finder.el
index f5bf2641537..1cf607c03c0 100644
--- a/lisp/finder.el
+++ b/lisp/finder.el
@@ -1,6 +1,6 @@
;;; finder.el --- topic & keyword-based code finder -*- lexical-binding: t -*-
-;; Copyright (C) 1992-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1992-2024 Free Software Foundation, Inc.
;; Author: Eric S. Raymond <esr@thyrsus.com>
;; Created: 16 Jun 1992
@@ -68,10 +68,11 @@
(processes . "processes, subshells, and compilation")
(terminals . "text terminals (ttys)")
(tex . "the TeX document formatter")
+ (text . "editing text files")
(tools . "programming tools")
(unix . "UNIX feature interfaces and emulators")
(vc . "version control")
- (wp . "word processing"))
+ (wp . "use keyword `text' instead; this keyword is obsolete"))
"Association list of the standard \"Keywords:\" headers.
Each element has the form (KEYWORD . DESCRIPTION).")
@@ -147,7 +148,11 @@ would otherwise be.")
("gnus" . gnus)
("international" . emacs)
("language" . emacs)
+ ("leim" . emacs)
+ ("ja-dic" . emacs)
+ ("quail" . emacs)
("mh-e" . mh-e)
+ ("obsolete" . emacs)
("semantic" . semantic)
("analyze" . semantic)
("bovine" . semantic)
@@ -162,6 +167,7 @@ would otherwise be.")
("org" . org)
("srecode" . srecode)
("term" . emacs)
+ ("use-package" . use-package)
("url" . url))
"Alist of built-in package directories.
Each element should have the form (DIR . PACKAGE), where DIR is a
diff --git a/lisp/flow-ctrl.el b/lisp/flow-ctrl.el
index 31209e48acf..55ffe1cf14f 100644
--- a/lisp/flow-ctrl.el
+++ b/lisp/flow-ctrl.el
@@ -1,6 +1,6 @@
;;; flow-ctrl.el --- help for lusers on cu(1) or ttys with wired-in ^S/^Q flow control -*- lexical-binding: t -*-
-;; Copyright (C) 1990-1991, 1994, 2001-2023 Free Software Foundation,
+;; Copyright (C) 1990-1991, 1994, 2001-2024 Free Software Foundation,
;; Inc.
;; Author: Kevin Gallagher
diff --git a/lisp/foldout.el b/lisp/foldout.el
index ace242ffbc7..495ce4339f7 100644
--- a/lisp/foldout.el
+++ b/lisp/foldout.el
@@ -1,6 +1,6 @@
;;; foldout.el --- folding extensions for outline-mode and outline-minor-mode -*- lexical-binding: t -*-
-;; Copyright (C) 1994, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1994, 2001-2024 Free Software Foundation, Inc.
;; Author: Kevin Broadey <KevinB@bartley.demon.co.uk>
;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/follow.el b/lisp/follow.el
index 7d64161ca33..316c85b1629 100644
--- a/lisp/follow.el
+++ b/lisp/follow.el
@@ -1,6 +1,6 @@
;;; follow.el --- synchronize windows showing the same buffer -*- lexical-binding: t -*-
-;; Copyright (C) 1995-1997, 1999, 2001-2023 Free Software Foundation,
+;; Copyright (C) 1995-1997, 1999, 2001-2024 Free Software Foundation,
;; Inc.
;; Author: Anders Lindgren
diff --git a/lisp/font-core.el b/lisp/font-core.el
index 4056fbdc954..7ef0fae60c0 100644
--- a/lisp/font-core.el
+++ b/lisp/font-core.el
@@ -1,6 +1,6 @@
;;; font-core.el --- Core interface to font-lock -*- lexical-binding: t; -*-
-;; Copyright (C) 1992-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1992-2024 Free Software Foundation, Inc.
;; Maintainer: emacs-devel@gnu.org
;; Keywords: languages, faces
diff --git a/lisp/font-lock.el b/lisp/font-lock.el
index f8815c1698a..7b077a826bf 100644
--- a/lisp/font-lock.el
+++ b/lisp/font-lock.el
@@ -1,6 +1,6 @@
;;; font-lock.el --- Electric font lock mode -*- lexical-binding:t -*-
-;; Copyright (C) 1992-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1992-2024 Free Software Foundation, Inc.
;; Author: Jamie Zawinski
;; Richard Stallman
@@ -299,8 +299,8 @@ that match at least one applicable CONDITION are disabled."
"If non-nil, means show status messages for buffer fontification.
If a number, only buffers greater than this size have fontification messages."
:type '(choice (const :tag "never" nil)
- (other :tag "always" t)
- (integer :tag "size"))
+ (integer :tag "size")
+ (other :tag "always" t))
:group 'font-lock
:version "24.1")
diff --git a/lisp/format-spec.el b/lisp/format-spec.el
index 2e76ecc0f8f..cf34017b994 100644
--- a/lisp/format-spec.el
+++ b/lisp/format-spec.el
@@ -1,6 +1,6 @@
;;; format-spec.el --- format arbitrary formatting strings -*- lexical-binding: t -*-
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
;; Keywords: tools
diff --git a/lisp/format.el b/lisp/format.el
index 5c72a78f325..34bd30e83a5 100644
--- a/lisp/format.el
+++ b/lisp/format.el
@@ -1,6 +1,6 @@
;;; format.el --- read and save files in multiple formats -*- lexical-binding: t; -*-
-;; Copyright (C) 1994-1995, 1997, 1999, 2001-2023 Free Software
+;; Copyright (C) 1994-1995, 1997, 1999, 2001-2024 Free Software
;; Foundation, Inc.
;; Author: Boris Goldowsky <boris@gnu.org>
@@ -295,7 +295,7 @@ For most purposes, consider using `format-decode-region' instead."
(setq try format-alist))
(setq try (cdr try))))))
;; Deal with given format(s)
- (or (listp format) (setq format (list format)))
+ (setq format (ensure-list format))
(let ((do format) f)
(while do
(or (setq f (assq (car do) format-alist))
diff --git a/lisp/forms.el b/lisp/forms.el
index 73b95989e5c..e38fa7ae873 100644
--- a/lisp/forms.el
+++ b/lisp/forms.el
@@ -1,6 +1,6 @@
;;; forms.el --- Forms mode: edit a file as a form to fill in -*- lexical-binding: t; -*-
-;; Copyright (C) 1991-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1991-2024 Free Software Foundation, Inc.
;; Author: Johan Vromans <jvromans@squirrel.nl>
diff --git a/lisp/frame.el b/lisp/frame.el
index ba5d1caafa2..d2376f1e339 100644
--- a/lisp/frame.el
+++ b/lisp/frame.el
@@ -1,6 +1,6 @@
;;; frame.el --- multi-frame management independent of window systems -*- lexical-binding:t -*-
-;; Copyright (C) 1993-1994, 1996-1997, 2000-2023 Free Software
+;; Copyright (C) 1993-1994, 1996-1997, 2000-2024 Free Software
;; Foundation, Inc.
;; Maintainer: emacs-devel@gnu.org
@@ -2906,7 +2906,7 @@ Values smaller than 0.2 sec are treated as 0.2 sec."
"How many times to blink before using a solid cursor on NS, X, and MS-Windows.
Use 0 or negative value to blink forever."
:version "24.4"
- :type 'natnum
+ :type 'integer
:group 'cursor)
(defvar blink-cursor-blinks-done 1
diff --git a/lisp/frameset.el b/lisp/frameset.el
index 224746bbfe3..436e51905fb 100644
--- a/lisp/frameset.el
+++ b/lisp/frameset.el
@@ -1,6 +1,6 @@
;;; frameset.el --- save and restore frame and window setup -*- lexical-binding: t -*-
-;; Copyright (C) 2013-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2024 Free Software Foundation, Inc.
;; Author: Juanma Barranquero <lekktu@gmail.com>
;; Keywords: convenience
diff --git a/lisp/fringe.el b/lisp/fringe.el
index b5ab4f9f605..a64ea4294ad 100644
--- a/lisp/fringe.el
+++ b/lisp/fringe.el
@@ -1,6 +1,6 @@
;;; fringe.el --- fringe setup and control -*- lexical-binding:t -*-
-;; Copyright (C) 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2024 Free Software Foundation, Inc.
;; Author: Simon Josefsson <simon@josefsson.org>
;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/generic-x.el b/lisp/generic-x.el
index 7e5ae90ff9a..b4ae0225943 100644
--- a/lisp/generic-x.el
+++ b/lisp/generic-x.el
@@ -1,6 +1,6 @@
;;; generic-x.el --- A collection of generic modes -*- lexical-binding: t -*-
-;; Copyright (C) 1997-1998, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997-1998, 2001-2024 Free Software Foundation, Inc.
;; Author: Peter Breton <pbreton@cs.umb.edu>
;; Created: Tue Oct 08 1996
diff --git a/lisp/gnus/ChangeLog.1 b/lisp/gnus/ChangeLog.1
index 2ce954cca99..ee00e57b0fa 100644
--- a/lisp/gnus/ChangeLog.1
+++ b/lisp/gnus/ChangeLog.1
@@ -663,7 +663,7 @@
1998-08-07 Gareth Jones <gdj1@gdjones.demon.co.uk>
* gnus-score.el (gnus-summary-increase-score): Don't downcase
- before lookin in char-to-header.
+ before looking in char-to-header.
1998-08-07 Lars Magne Ingebrigtsen <larsi@gnus.org>
@@ -2745,7 +2745,7 @@
1997-12-05 Dave Love <d.love@dl.ac.uk>
- * gnus-nocem.el (gnus-nocem-message-wanted-p): Fix paren typpo.
+ * gnus-nocem.el (gnus-nocem-message-wanted-p): Fix paren typo.
(gnus-nocem-issuers): Allow sexp alternative in :type for alists.
1997-12-05 Dave Love <d.love@dl.ac.uk>
@@ -3702,7 +3702,7 @@
* gnus.el: Quassia Gnus v0.1 is released.
- Copyright (C) 1997-2023 Free Software Foundation, Inc.
+ Copyright (C) 1997-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/lisp/gnus/ChangeLog.2 b/lisp/gnus/ChangeLog.2
index 2d7aeabd8cf..53f81862ddf 100644
--- a/lisp/gnus/ChangeLog.2
+++ b/lisp/gnus/ChangeLog.2
@@ -6215,7 +6215,7 @@
* pop3.el (pop3-retr): Wait 500 msecs.
(pop3-read-response): Ditto.
- * gnus-msg.el (gnus-setup-message): Get the evaliation order
+ * gnus-msg.el (gnus-setup-message): Get the evaluation order
right.
(gnus-inews-make-draft): New function.
(gnus-setup-message): Use it.
@@ -9474,7 +9474,7 @@
2002-03-01 Paul Jarc <prj@po.cwru.edu>
* message.el (message-get-reply-headers): Downcase email addresses
- for comaparisons for duplicate removal.
+ for comparisons for duplicate removal.
2002-03-01 ShengHuo ZHU <zsh@cs.rochester.edu>
@@ -18538,7 +18538,7 @@
See ChangeLog.1 for earlier changes.
- Copyright (C) 2000-2002, 2004-2023 Free Software Foundation, Inc.
+ Copyright (C) 2000-2002, 2004-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/lisp/gnus/ChangeLog.3 b/lisp/gnus/ChangeLog.3
index d0b195e5f13..1633b8835eb 100644
--- a/lisp/gnus/ChangeLog.3
+++ b/lisp/gnus/ChangeLog.3
@@ -13,7 +13,7 @@
2015-04-01 Eric Abrahamsen <eric@ericabrahamsen.net>
- * registry.el (registry-prune): Re-use `registry-full' in
+ * registry.el (registry-prune): Reuse `registry-full' in
`registry-prune'. It's a bit of redundant work, but safer.
Also ensure that target-size is an integer.
@@ -78,7 +78,7 @@
* gnus-notifications.el (gnus-notifications-action): Raise window
frame.
(gnus-notifications-action): Allow mark as read.
- (gnus-notifications-notify): Show uption to mark as read.
+ (gnus-notifications-notify): Show option to mark as read.
2015-03-08 Adam Sjøgren <asjo@koldfront.dk>
@@ -578,7 +578,7 @@
* gnus-start.el (gnus-dribble-read-file): Don't stop the auto-saving of
the dribble buffer even when it is shrunk a lot.
- <http://thread.gmane.org/gmane.emacs.gnus.user/16923>
+ <http://thread.gmane.org/gmane.emacs.gnus.user/16923> [dead link]
2014-06-26 Glenn Morris <rgm@gnu.org>
@@ -26326,7 +26326,7 @@
See ChangeLog.2 for earlier changes.
- Copyright (C) 2004-2023 Free Software Foundation, Inc.
+ Copyright (C) 2004-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/lisp/gnus/canlock.el b/lisp/gnus/canlock.el
index 2eb5e13df9a..02744a7f0a5 100644
--- a/lisp/gnus/canlock.el
+++ b/lisp/gnus/canlock.el
@@ -1,6 +1,6 @@
;;; canlock.el --- functions for Cancel-Lock feature -*- lexical-binding: t; -*-
-;; Copyright (C) 1998-1999, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-1999, 2001-2024 Free Software Foundation, Inc.
;; Author: Katsumi Yamaoka <yamaoka@jpl.org>
;; Keywords: news, cancel-lock, hmac, sha1, rfc2104
diff --git a/lisp/gnus/deuglify.el b/lisp/gnus/deuglify.el
index 2c75d5b7873..80205012696 100644
--- a/lisp/gnus/deuglify.el
+++ b/lisp/gnus/deuglify.el
@@ -1,6 +1,6 @@
;;; deuglify.el --- deuglify broken Outlook (Express) articles -*- lexical-binding: t; -*-
-;; Copyright (C) 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2024 Free Software Foundation, Inc.
;; Author: Raymond Scholz <rscholz@zonix.de>
;; Thomas Steffen
diff --git a/lisp/gnus/gmm-utils.el b/lisp/gnus/gmm-utils.el
index c0651e3dbfc..516758c0082 100644
--- a/lisp/gnus/gmm-utils.el
+++ b/lisp/gnus/gmm-utils.el
@@ -1,6 +1,6 @@
;;; gmm-utils.el --- Utility functions for Gnus, Message and MML -*- lexical-binding: t; -*-
-;; Copyright (C) 2006-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2006-2024 Free Software Foundation, Inc.
;; Author: Reiner Steib <reiner.steib@gmx.de>
;; Keywords: news
diff --git a/lisp/gnus/gnus-agent.el b/lisp/gnus/gnus-agent.el
index db205c5b657..3ee93031119 100644
--- a/lisp/gnus/gnus-agent.el
+++ b/lisp/gnus/gnus-agent.el
@@ -1,6 +1,6 @@
;;; gnus-agent.el --- unplugged support for Gnus -*- lexical-binding: t; -*-
-;; Copyright (C) 1997-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997-2024 Free Software Foundation, Inc.
;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
;; This file is part of GNU Emacs.
diff --git a/lisp/gnus/gnus-art.el b/lisp/gnus/gnus-art.el
index 6f201f9c3df..c3c5eab7d89 100644
--- a/lisp/gnus/gnus-art.el
+++ b/lisp/gnus/gnus-art.el
@@ -1,6 +1,6 @@
;;; gnus-art.el --- article mode commands for Gnus -*- lexical-binding: t; -*-
-;; Copyright (C) 1996-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-2024 Free Software Foundation, Inc.
;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
;; Keywords: news
@@ -1622,7 +1622,8 @@ predicate. See Info node `(gnus)Customizing Articles'."
"The protocol used for encrypt articles.
It is a string, such as \"PGP\". If nil, ask user."
:version "22.1"
- :type 'string
+ :type '(choice (const :tag "Ask me" nil)
+ string)
:group 'mime-security)
(defcustom gnus-use-idna t
@@ -2870,12 +2871,15 @@ Return file name relative to the parent of DIRECTORY."
cid handle directory))
(throw 'found file)))
((equal (concat "<" cid ">") (mm-handle-id handle))
- (setq file (or (mm-handle-filename handle)
- (concat
- (make-temp-name "cid")
- (car (rassoc (car (mm-handle-type handle))
- mailcap-mime-extensions))))
- afile (expand-file-name file directory))
+ ;; Randomize filenames: declared filenames may not be unique.
+ (setq file (format "cid-%d-%s"
+ (random 99)
+ (or (mm-handle-filename handle)
+ (concat
+ (make-temp-name "cid")
+ (car (rassoc (car (mm-handle-type handle))
+ mailcap-mime-extensions)))))
+ afile (expand-file-name file directory))
(mm-save-part-to-file handle afile)
(throw 'found (concat (file-name-nondirectory
(directory-file-name directory))
@@ -7560,10 +7564,11 @@ must return `mid', `mail', `invalid' or `ask'."
:version "22.1"
:group 'gnus-article-buttons
:type '(choice (function-item :tag "Heuristic function"
- gnus-button-mid-or-mail-heuristic)
- (const ask)
- (const mid)
- (const mail)))
+ gnus-button-mid-or-mail-heuristic)
+ (const :tag "Query me" ask)
+ (const :tag "Assume it's a message ID" mid)
+ (const :tag "Assume it's a mail address" mail)
+ function))
(defcustom gnus-button-mid-or-mail-heuristic-alist
'((-10.0 . ".+\\$.+@")
diff --git a/lisp/gnus/gnus-async.el b/lisp/gnus/gnus-async.el
index 14295f09be9..fbcc05c4a1d 100644
--- a/lisp/gnus/gnus-async.el
+++ b/lisp/gnus/gnus-async.el
@@ -1,6 +1,6 @@
;;; gnus-async.el --- asynchronous support for Gnus -*- lexical-binding:t -*-
-;; Copyright (C) 1996-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-2024 Free Software Foundation, Inc.
;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
;; Keywords: news
diff --git a/lisp/gnus/gnus-bcklg.el b/lisp/gnus/gnus-bcklg.el
index 2c338ccd145..4fb73f9cbfa 100644
--- a/lisp/gnus/gnus-bcklg.el
+++ b/lisp/gnus/gnus-bcklg.el
@@ -1,6 +1,6 @@
;;; gnus-bcklg.el --- backlog functions for Gnus -*- lexical-binding: t; -*-
-;; Copyright (C) 1996-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-2024 Free Software Foundation, Inc.
;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
;; Keywords: news
diff --git a/lisp/gnus/gnus-bookmark.el b/lisp/gnus/gnus-bookmark.el
index 1a926619e14..ccb9490d73b 100644
--- a/lisp/gnus/gnus-bookmark.el
+++ b/lisp/gnus/gnus-bookmark.el
@@ -1,6 +1,6 @@
;;; gnus-bookmark.el --- Bookmarks in Gnus -*- lexical-binding: t; -*-
-;; Copyright (C) 2006-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2006-2024 Free Software Foundation, Inc.
;; Author: Bastien Guerry <bzg AT altern DOT org>
;; Keywords: news
@@ -61,12 +61,12 @@
;; (define-key global-map "\C-crl" 'gnus-bookmark-bmenu-list)
;; FIXME: Add keybindings, see
-;; http://thread.gmane.org/gmane.emacs.gnus.general/63101/focus=63379
-;; http://thread.gmane.org/v9fxx9fkm4.fsf@marauder.physik.uni-ulm.de
+;; http://thread.gmane.org/gmane.emacs.gnus.general/63101/focus=63379 [dead link]
+;; http://thread.gmane.org/v9fxx9fkm4.fsf@marauder.physik.uni-ulm.de [dead link]
;; FIXME: Check if `gnus-bookmark.el' should use
;; `bookmark-make-record-function'.
-;; Cf. http://article.gmane.org/gmane.emacs.gnus.general/66076
+;; Cf. http://article.gmane.org/gmane.emacs.gnus.general/66076 [dead link]
(defgroup gnus-bookmark nil
"Setting, annotation and jumping to Gnus bookmarks."
@@ -112,7 +112,7 @@ You can toggle whether details are shown with \\<gnus-bookmark-bmenu-mode-map>\\
(defcustom gnus-bookmark-bookmark-inline-details '(author)
"Details to be shown with `gnus-bookmark-bmenu-toggle-infos'.
-The default value is \(subject)."
+The default value is (author)."
:type '(list :tag "Gnus bookmark details"
(set :inline t
(const :tag "Author" author)
diff --git a/lisp/gnus/gnus-cache.el b/lisp/gnus/gnus-cache.el
index 13be21630ec..961219eee8f 100644
--- a/lisp/gnus/gnus-cache.el
+++ b/lisp/gnus/gnus-cache.el
@@ -1,6 +1,6 @@
;;; gnus-cache.el --- cache interface for Gnus -*- lexical-binding: t; -*-
-;; Copyright (C) 1995-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1995-2024 Free Software Foundation, Inc.
;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
;; Keywords: news
diff --git a/lisp/gnus/gnus-cite.el b/lisp/gnus/gnus-cite.el
index d9071491ed4..04abdfc0d1b 100644
--- a/lisp/gnus/gnus-cite.el
+++ b/lisp/gnus/gnus-cite.el
@@ -1,6 +1,6 @@
;;; gnus-cite.el --- parse citations in articles for Gnus -*- lexical-binding: t; -*-
-;; Copyright (C) 1995-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1995-2024 Free Software Foundation, Inc.
;; Author: Per Abrahamsen <abraham@dina.kvl.dk>
@@ -1117,12 +1117,6 @@ Returns nil if there is no such line before LIMIT, t otherwise."
(setq count (1+ count)))))) ;;
"Keywords for highlighting different levels of message citations.")
-(defvar font-lock-defaults-computed)
-(defvar font-lock-keywords)
-(defvar font-lock-set-defaults)
-
-(autoload 'font-lock-set-defaults "font-lock")
-
(define-minor-mode gnus-message-citation-mode
"Minor mode providing more font-lock support for nested citations.
When enabled, it automatically turns on `font-lock-mode'."
diff --git a/lisp/gnus/gnus-cloud.el b/lisp/gnus/gnus-cloud.el
index ae4c4cc0d71..af5f42b1c3b 100644
--- a/lisp/gnus/gnus-cloud.el
+++ b/lisp/gnus/gnus-cloud.el
@@ -1,6 +1,6 @@
;;; gnus-cloud.el --- storing and retrieving data via IMAP -*- lexical-binding: t; -*-
-;; Copyright (C) 2014-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2014-2024 Free Software Foundation, Inc.
;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
;; Keywords: mail
@@ -148,6 +148,7 @@ easy interactive way to set this from the Server buffer."
(defun gnus-cloud-decode-data ()
(cond
+ ;; FIXME: Duplicated value in ‘cond’: base64-gzip.
((memq gnus-cloud-storage-method '(base64 base64-gzip))
(base64-decode-region (point-min) (point-max)))
diff --git a/lisp/gnus/gnus-cus.el b/lisp/gnus/gnus-cus.el
index 9225f15b7e1..4da9979adac 100644
--- a/lisp/gnus/gnus-cus.el
+++ b/lisp/gnus/gnus-cus.el
@@ -1,6 +1,6 @@
;;; gnus-cus.el --- customization commands for Gnus -*- lexical-binding: t; -*-
-;; Copyright (C) 1996, 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996, 1999-2024 Free Software Foundation, Inc.
;; Author: Per Abrahamsen <abraham@dina.kvl.dk>
;; Keywords: news
diff --git a/lisp/gnus/gnus-dbus.el b/lisp/gnus/gnus-dbus.el
index f6ad48f9069..19d564548f2 100644
--- a/lisp/gnus/gnus-dbus.el
+++ b/lisp/gnus/gnus-dbus.el
@@ -1,6 +1,6 @@
;;; gnus-dbus.el --- DBUS integration for Gnus -*- lexical-binding: t; -*-
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
;; Author: Eric Abrahamsen <eric@ericabrahamsen.net>
diff --git a/lisp/gnus/gnus-delay.el b/lisp/gnus/gnus-delay.el
index 07bed67ae0e..4de9588423c 100644
--- a/lisp/gnus/gnus-delay.el
+++ b/lisp/gnus/gnus-delay.el
@@ -1,6 +1,6 @@
;;; gnus-delay.el --- Delayed posting of articles -*- lexical-binding: t; -*-
-;; Copyright (C) 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2024 Free Software Foundation, Inc.
;; Author: Kai Großjohann <Kai.Grossjohann@CS.Uni-Dortmund.DE>
;; Keywords: mail, news, extensions
diff --git a/lisp/gnus/gnus-demon.el b/lisp/gnus/gnus-demon.el
index de6c167a1fc..93bce94ea3d 100644
--- a/lisp/gnus/gnus-demon.el
+++ b/lisp/gnus/gnus-demon.el
@@ -1,6 +1,6 @@
;;; gnus-demon.el --- daemonic Gnus behavior -*- lexical-binding: t; -*-
-;; Copyright (C) 1995-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1995-2024 Free Software Foundation, Inc.
;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
;; Keywords: news
diff --git a/lisp/gnus/gnus-diary.el b/lisp/gnus/gnus-diary.el
index 4cb1182117d..60b94dff1fa 100644
--- a/lisp/gnus/gnus-diary.el
+++ b/lisp/gnus/gnus-diary.el
@@ -1,6 +1,6 @@
;;; gnus-diary.el --- Wrapper around the NNDiary Gnus back end -*- lexical-binding: t; -*-
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
;; Author: Didier Verna <didier@didierverna.net>
;; Created: Tue Jul 20 10:42:55 1999
diff --git a/lisp/gnus/gnus-dired.el b/lisp/gnus/gnus-dired.el
index b146b51430a..48c1aef968b 100644
--- a/lisp/gnus/gnus-dired.el
+++ b/lisp/gnus/gnus-dired.el
@@ -1,6 +1,6 @@
;;; gnus-dired.el --- utility functions where gnus and dired meet -*- lexical-binding: t; -*-
-;; Copyright (C) 1996-1999, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-1999, 2001-2024 Free Software Foundation, Inc.
;; Authors: Benjamin Rutt <brutt@bloomington.in.us>,
;; Shenghuo Zhu <zsh@cs.rochester.edu>
diff --git a/lisp/gnus/gnus-draft.el b/lisp/gnus/gnus-draft.el
index 76aa5647a3d..1fc2b33fffb 100644
--- a/lisp/gnus/gnus-draft.el
+++ b/lisp/gnus/gnus-draft.el
@@ -1,6 +1,6 @@
;;; gnus-draft.el --- draft message support for Gnus -*- lexical-binding: t; -*-
-;; Copyright (C) 1997-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997-2024 Free Software Foundation, Inc.
;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
;; Keywords: news
diff --git a/lisp/gnus/gnus-dup.el b/lisp/gnus/gnus-dup.el
index 8e31a1762b0..fb752cff67f 100644
--- a/lisp/gnus/gnus-dup.el
+++ b/lisp/gnus/gnus-dup.el
@@ -1,6 +1,6 @@
;;; gnus-dup.el --- suppression of duplicate articles in Gnus -*- lexical-binding: t -*-
-;; Copyright (C) 1996-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-2024 Free Software Foundation, Inc.
;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
;; Keywords: news
diff --git a/lisp/gnus/gnus-eform.el b/lisp/gnus/gnus-eform.el
index cc5beb16a34..ca76c714caa 100644
--- a/lisp/gnus/gnus-eform.el
+++ b/lisp/gnus/gnus-eform.el
@@ -1,6 +1,6 @@
;;; gnus-eform.el --- a mode for editing forms for Gnus -*- lexical-binding: t; -*-
-;; Copyright (C) 1996-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-2024 Free Software Foundation, Inc.
;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
;; Keywords: news
diff --git a/lisp/gnus/gnus-fun.el b/lisp/gnus/gnus-fun.el
index fc934ab142e..677903f461e 100644
--- a/lisp/gnus/gnus-fun.el
+++ b/lisp/gnus/gnus-fun.el
@@ -1,6 +1,6 @@
;;; gnus-fun.el --- various frivolous extension functions to Gnus -*- lexical-binding: t; -*-
-;; Copyright (C) 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2024 Free Software Foundation, Inc.
;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
;; Keywords: news
diff --git a/lisp/gnus/gnus-gravatar.el b/lisp/gnus/gnus-gravatar.el
index cdfd85e9831..67c828bf775 100644
--- a/lisp/gnus/gnus-gravatar.el
+++ b/lisp/gnus/gnus-gravatar.el
@@ -1,6 +1,6 @@
;;; gnus-gravatar.el --- Gnus Gravatar support -*- lexical-binding: t -*-
-;; Copyright (C) 2010-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2010-2024 Free Software Foundation, Inc.
;; Author: Julien Danjou <julien@danjou.info>
;; Keywords: multimedia, news
diff --git a/lisp/gnus/gnus-group.el b/lisp/gnus/gnus-group.el
index 8c1d7e3c86a..9664d603019 100644
--- a/lisp/gnus/gnus-group.el
+++ b/lisp/gnus/gnus-group.el
@@ -1,6 +1,6 @@
;;; gnus-group.el --- group mode commands for Gnus -*- lexical-binding: t; -*-
-;; Copyright (C) 1996-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-2024 Free Software Foundation, Inc.
;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
;; Keywords: news
@@ -286,10 +286,10 @@ If you want to modify the group buffer, you can use this hook."
:type 'hook)
(defcustom gnus-useful-groups
- '(("(ding) mailing list mirrored at gmane.org"
+ '(("(ding) mailing list mirrored at gmane.io"
"gmane.emacs.gnus.general"
(nntp "Gmane"
- (nntp-address "news.gmane.org")))
+ (nntp-address "news.gmane.io")))
("Gnus bug archive"
"gnus.gnus-bug"
(nntp "news.gnus.org"
@@ -1436,14 +1436,8 @@ if it is a string, only list groups matching REGEXP."
;; Moving through the Group buffer (in topic mode) e.g. with C-n doesn't
;; update the state (enabled/disabled) of the icon `gnus-group-describe-group'
-;; automatically. After `C-l' the state is correct. See the following report
-;; on emacs-devel
-;; <http://thread.gmane.org/v9acdmrcse.fsf@marauder.physik.uni-ulm.de>:
-;; From: Reiner Steib
-;; Subject: tool bar icons not updated according to :active condition
-;; Newsgroups: gmane.emacs.devel
-;; Date: Mon, 23 Jan 2006 19:59:13 +0100
-;; Message-ID: <v9acdmrcse.fsf@marauder.physik.uni-ulm.de>
+;; automatically. After `C-l' the state is correct.
+;; See: https://lists.gnu.org/r/emacs-devel/2006-01/msg00853.html
;; Using `redraw-frame' (see `gnus-tool-bar-update') in Emacs might
;; be confusing, so maybe we shouldn't call it by default.
@@ -1751,17 +1745,17 @@ already. If INFO-UNCHANGED is non-nil, dribble buffer is not updated."
gnus-level-killed))
(defun gnus-group-search-forward (&optional backward all level first-too)
- "Find the next newsgroup with unread articles.
-If BACKWARD is non-nil, find the previous newsgroup instead.
-If ALL is non-nil, just find any newsgroup.
-If LEVEL is non-nil, find group with level LEVEL, or higher if no such
-group exists.
-If FIRST-TOO, the current line is also eligible as a target."
+ "Move point to the next newsgroup with unread articles.
+If BACKWARD is non-nil, move to the previous newsgroup instead.
+If ALL is non-nil, consider any newsgroup, not only those with
+unread articles. If LEVEL is non-nil, find group with level
+LEVEL, or higher if no such group exists. If FIRST-TOO, the
+current line is also eligible as a target."
(let ((way (if backward -1 1))
(low gnus-level-killed)
(beg (point))
pos found lev)
- (if (and backward (progn (beginning-of-line)) (bobp))
+ (if (and backward (progn (beginning-of-line) (bobp)))
nil
(unless first-too
(forward-line way))
@@ -2336,7 +2330,7 @@ Valid input formats include:
(cond
;; URLs providing `group', `start' and `range':
((string-match
- ;; http://thread.gmane.org/gmane.emacs.devel/86326/focus=86525
+ ;; http://thread.gmane.org/gmane.emacs.devel/86326/focus=86525 [dead link]
"^http://thread\\.gmane\\.org/\\([^/]+\\)/\\([0-9]+\\)/focus=\\([0-9]+\\)$"
url)
(setq group (match-string 1 url)
@@ -2347,7 +2341,7 @@ Valid input formats include:
start -1)))
;; URLs providing `group' and `start':
((or (string-match
- ;; http://article.gmane.org/gmane.comp.gnu.make.bugs/3584
+ ;; http://article.gmane.org/gmane.comp.gnu.make.bugs/3584 [dead link]
"^http://\\(?:thread\\|article\\|permalink\\)\\.gmane\\.org/\\([^/]+\\)/\\([0-9]+\\)"
url)
(string-match
@@ -2355,7 +2349,7 @@ Valid input formats include:
"^\\(?:nntp\\|news\\)://news\\.gmane\\.org/\\([^/]+\\)/\\([0-9]+\\)"
url)
(string-match
- ;; http://news.gmane.org/group/gmane.emacs.gnus.general/thread=65099/force_load=t
+ ;; http://news.gmane.org/group/gmane.emacs.gnus.general/thread=65099/force_load=t [dead link]
"^http://news\\.gmane\\.org/group/\\([^/]+\\)/thread=\\([0-9]+\\)"
url))
(setq group (match-string 1 url)
diff --git a/lisp/gnus/gnus-html.el b/lisp/gnus/gnus-html.el
index 829e4cf0099..2d8d6db24bf 100644
--- a/lisp/gnus/gnus-html.el
+++ b/lisp/gnus/gnus-html.el
@@ -1,6 +1,6 @@
;;; gnus-html.el --- Render HTML in a buffer. -*- lexical-binding: t; -*-
-;; Copyright (C) 2010-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2010-2024 Free Software Foundation, Inc.
;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
;; Keywords: html, web
diff --git a/lisp/gnus/gnus-icalendar.el b/lisp/gnus/gnus-icalendar.el
index b0efe689636..af7284b88e8 100644
--- a/lisp/gnus/gnus-icalendar.el
+++ b/lisp/gnus/gnus-icalendar.el
@@ -1,6 +1,6 @@
;;; gnus-icalendar.el --- reply to iCalendar meeting requests -*- lexical-binding:t -*-
-;; Copyright (C) 2013-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2024 Free Software Foundation, Inc.
;; Author: Jan Tatarik <Jan.Tatarik@gmail.com>
;; Keywords: mail, icalendar, org
diff --git a/lisp/gnus/gnus-int.el b/lisp/gnus/gnus-int.el
index 49238e62bea..558ad8648ca 100644
--- a/lisp/gnus/gnus-int.el
+++ b/lisp/gnus/gnus-int.el
@@ -1,6 +1,6 @@
;;; gnus-int.el --- backend interface functions for Gnus -*- lexical-binding: t; -*-
-;; Copyright (C) 1996-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-2024 Free Software Foundation, Inc.
;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
;; Keywords: news
diff --git a/lisp/gnus/gnus-kill.el b/lisp/gnus/gnus-kill.el
index 5f96f002a77..8b74cd2e476 100644
--- a/lisp/gnus/gnus-kill.el
+++ b/lisp/gnus/gnus-kill.el
@@ -1,6 +1,6 @@
;;; gnus-kill.el --- kill commands for Gnus -*- lexical-binding: t; -*-
-;; Copyright (C) 1995-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1995-2024 Free Software Foundation, Inc.
;; Author: Masanobu UMEDA <umerin@flab.flab.fujitsu.junet>
;; Lars Magne Ingebrigtsen <larsi@gnus.org>
diff --git a/lisp/gnus/gnus-logic.el b/lisp/gnus/gnus-logic.el
index 628d2bd0958..3652b02672b 100644
--- a/lisp/gnus/gnus-logic.el
+++ b/lisp/gnus/gnus-logic.el
@@ -1,6 +1,6 @@
;;; gnus-logic.el --- advanced scoring code for Gnus -*- lexical-binding: t; -*-
-;; Copyright (C) 1996-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-2024 Free Software Foundation, Inc.
;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
;; Keywords: news
@@ -71,11 +71,11 @@
(+ (cdr score) new-score))
(push (cons (mail-header-number gnus-advanced-headers)
new-score)
- gnus-newsgroup-scored)
- (when trace
- (push (cons "A file" rule)
- ;; Must be synced with `gnus-score-edit-file-at-point'.
- gnus-score-trace)))))))
+ gnus-newsgroup-scored))
+ (when trace
+ (push (cons "A file" rule)
+ ;; Must be synced with `gnus-score-edit-file-at-point'.
+ gnus-score-trace))))))
(defun gnus-advanced-score-rule (rule)
"Apply RULE to `gnus-advanced-headers'."
diff --git a/lisp/gnus/gnus-mh.el b/lisp/gnus/gnus-mh.el
index 59e8947928f..0035ff26a25 100644
--- a/lisp/gnus/gnus-mh.el
+++ b/lisp/gnus/gnus-mh.el
@@ -1,6 +1,6 @@
;;; gnus-mh.el --- mh-e interface for Gnus -*- lexical-binding: t; -*-
-;; Copyright (C) 1994-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1994-2024 Free Software Foundation, Inc.
;; Author: Masanobu UMEDA <umerin@flab.flab.fujitsu.junet>
;; Lars Magne Ingebrigtsen <larsi@gnus.org>
diff --git a/lisp/gnus/gnus-ml.el b/lisp/gnus/gnus-ml.el
index 59c3e60c6e3..fb0f5d830ad 100644
--- a/lisp/gnus/gnus-ml.el
+++ b/lisp/gnus/gnus-ml.el
@@ -1,6 +1,6 @@
;;; gnus-ml.el --- Mailing list minor mode for Gnus -*- lexical-binding: t; -*-
-;; Copyright (C) 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2000-2024 Free Software Foundation, Inc.
;; Author: Julien Gilles <jgilles@free.fr>
;; Keywords: news, mail
diff --git a/lisp/gnus/gnus-mlspl.el b/lisp/gnus/gnus-mlspl.el
index 9fc065fe756..6985a40e305 100644
--- a/lisp/gnus/gnus-mlspl.el
+++ b/lisp/gnus/gnus-mlspl.el
@@ -1,6 +1,6 @@
;;; gnus-mlspl.el --- a group params-based mail splitting mechanism -*- lexical-binding: t; -*-
-;; Copyright (C) 1998-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-2024 Free Software Foundation, Inc.
;; Author: Alexandre Oliva <oliva@lsd.ic.unicamp.br>
;; Keywords: news, mail
diff --git a/lisp/gnus/gnus-msg.el b/lisp/gnus/gnus-msg.el
index 0439bf0d59b..fdf97e1aabd 100644
--- a/lisp/gnus/gnus-msg.el
+++ b/lisp/gnus/gnus-msg.el
@@ -1,6 +1,6 @@
;;; gnus-msg.el --- mail and post interface for Gnus -*- lexical-binding: t; -*-
-;; Copyright (C) 1995-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1995-2024 Free Software Foundation, Inc.
;; Author: Masanobu UMEDA <umerin@flab.flab.fujitsu.junet>
;; Lars Magne Ingebrigtsen <larsi@gnus.org>
@@ -1104,12 +1104,12 @@ If VERY-WIDE, make a very wide reply."
(setq headers (concat headers (buffer-string)))))))
(set-buffer (gnus-copy-article-buffer))
(gnus-msg-treat-broken-reply-to gnus-msg-force-broken-reply-to)
- (save-restriction
- (message-narrow-to-head)
- (when very-wide
- (erase-buffer)
- (insert headers))
- (goto-char (point-max)))
+ (when very-wide
+ (save-restriction
+ (message-narrow-to-head)
+ (delete-region (point-min) (point-max))
+ (insert headers)
+ (goto-char (point-max))))
(mml-quote-region (point) (point-max))
(message-reply nil wide)
(when yank
@@ -1209,7 +1209,7 @@ The original article(s) will be yanked."
(gnus-summary-reply
(gnus-summary-work-articles n) t (gnus-summary-work-articles n)))
-(defun gnus-summary-mail-forward (&optional arg post)
+(defun gnus-summary-mail-forward (&optional arg all-headers post)
"Forward the current message(s) to another user.
If process marks exist, forward all marked messages;
if ARG is nil, see `message-forward-as-mime' and `message-forward-show-mml';
@@ -1217,17 +1217,25 @@ if ARG is 1, decode the message and forward directly inline;
if ARG is 2, forward message as an rfc822 MIME section;
if ARG is 3, decode message and forward as an rfc822 MIME section;
if ARG is 4, forward message directly inline;
-otherwise, use flipped `message-forward-as-mime'.
+otherwise, use negated `message-forward-as-mime'.
If POST, post instead of mail.
-For the \"inline\" alternatives, also see the variable
-`message-forward-ignored-headers'."
- (interactive "P" gnus-summary-mode)
+If symbolic prefix ALL-HEADERS is the symbol `a', include all
+original headers in the forwarded message, except those matching
+`message-forward-ignored-headers'. Otherwise, include headers
+based on the options `message-forward-included-headers',
+`message-forward-ignored-headers', and potentially
+`message-forward-included-mime-headers'."
+ (interactive (gnus-interactive "P\ny") gnus-summary-mode)
(if (cdr (gnus-summary-work-articles nil))
;; Process marks are given.
(gnus-uu-digest-mail-forward nil post)
;; No process marks.
(let ((message-forward-as-mime message-forward-as-mime)
- (message-forward-show-mml message-forward-show-mml))
+ (message-forward-show-mml message-forward-show-mml)
+ (message-forward-included-headers
+ (if (eq all-headers 'a)
+ nil
+ message-forward-included-headers)))
(cond
((null arg))
((eq arg 1)
@@ -1380,11 +1388,11 @@ composing a new message."
(forward-char 1))
(widen)))))
-(defun gnus-summary-post-forward (&optional arg)
+(defun gnus-summary-post-forward (&optional arg all-headers)
"Forward the current article to a newsgroup.
See `gnus-summary-mail-forward' for ARG."
- (interactive "P" gnus-summary-mode)
- (gnus-summary-mail-forward arg t))
+ (interactive (gnus-interactive "P\ny") gnus-summary-mode)
+ (gnus-summary-mail-forward arg all-headers t))
(defun gnus-summary-mail-crosspost-complaint (n)
"Send a complaint about crossposting to the current article(s)."
diff --git a/lisp/gnus/gnus-notifications.el b/lisp/gnus/gnus-notifications.el
index 5e5b4a31e9e..f34f5ea0e26 100644
--- a/lisp/gnus/gnus-notifications.el
+++ b/lisp/gnus/gnus-notifications.el
@@ -1,6 +1,6 @@
;;; gnus-notifications.el --- Send notification on new message in Gnus -*- lexical-binding: t; -*-
-;; Copyright (C) 2012-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2012-2024 Free Software Foundation, Inc.
;; Author: Julien Danjou <julien@danjou.info>
;; Keywords: news
diff --git a/lisp/gnus/gnus-picon.el b/lisp/gnus/gnus-picon.el
index 562c2b7423f..48c70045a37 100644
--- a/lisp/gnus/gnus-picon.el
+++ b/lisp/gnus/gnus-picon.el
@@ -1,6 +1,6 @@
;;; gnus-picon.el --- displaying pretty icons in Gnus -*- lexical-binding: t; -*-
-;; Copyright (C) 1996-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-2024 Free Software Foundation, Inc.
;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
;; Keywords: news xpm annotation glyph faces
diff --git a/lisp/gnus/gnus-range.el b/lisp/gnus/gnus-range.el
index 285018bc642..dbb24571e55 100644
--- a/lisp/gnus/gnus-range.el
+++ b/lisp/gnus/gnus-range.el
@@ -1,6 +1,6 @@
;;; gnus-range.el --- range and sequence functions for Gnus -*- lexical-binding: t; -*-
-;; Copyright (C) 1996-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-2024 Free Software Foundation, Inc.
;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
;; Keywords: news
diff --git a/lisp/gnus/gnus-registry.el b/lisp/gnus/gnus-registry.el
index d9834031b80..0881bfce03c 100644
--- a/lisp/gnus/gnus-registry.el
+++ b/lisp/gnus/gnus-registry.el
@@ -1,6 +1,6 @@
;;; gnus-registry.el --- article registry for Gnus -*- lexical-binding: t; -*-
-;; Copyright (C) 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2024 Free Software Foundation, Inc.
;; Author: Ted Zlatanov <tzz@lifelogs.com>
;; Keywords: news registry
diff --git a/lisp/gnus/gnus-rfc1843.el b/lisp/gnus/gnus-rfc1843.el
index e50f735dcb7..c814f55411f 100644
--- a/lisp/gnus/gnus-rfc1843.el
+++ b/lisp/gnus/gnus-rfc1843.el
@@ -1,6 +1,6 @@
;;; gnus-rfc1843.el --- HZ (rfc1843) decoding interface functions for Gnus -*- lexical-binding: t; -*-
-;; Copyright (C) 1998-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-2024 Free Software Foundation, Inc.
;; Author: Shenghuo Zhu <zsh@cs.rochester.edu>
;; Keywords: news HZ HZ+ mail i18n
diff --git a/lisp/gnus/gnus-rmail.el b/lisp/gnus/gnus-rmail.el
index 55706e80565..26cae246b67 100644
--- a/lisp/gnus/gnus-rmail.el
+++ b/lisp/gnus/gnus-rmail.el
@@ -1,6 +1,6 @@
;;; gnus-rmail.el --- Saving to rmail/babyl files -*- lexical-binding: t; -*-
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/lisp/gnus/gnus-salt.el b/lisp/gnus/gnus-salt.el
index 853c3f6d8ac..358a301da90 100644
--- a/lisp/gnus/gnus-salt.el
+++ b/lisp/gnus/gnus-salt.el
@@ -1,6 +1,6 @@
;;; gnus-salt.el --- alternate summary mode interfaces for Gnus -*- lexical-binding: t; -*-
-;; Copyright (C) 1996-1999, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-1999, 2001-2024 Free Software Foundation, Inc.
;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
;; Keywords: news
diff --git a/lisp/gnus/gnus-score.el b/lisp/gnus/gnus-score.el
index 8bdfccf7eb8..bd19e7d7cd7 100644
--- a/lisp/gnus/gnus-score.el
+++ b/lisp/gnus/gnus-score.el
@@ -1,6 +1,6 @@
;;; gnus-score.el --- scoring code for Gnus -*- lexical-binding: t; -*-
-;; Copyright (C) 1995-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1995-2024 Free Software Foundation, Inc.
;; Author: Per Abrahamsen <amanda@iesd.auc.dk>
;; Lars Magne Ingebrigtsen <larsi@gnus.org>
@@ -2994,10 +2994,7 @@ The list is determined from the variable `gnus-score-file-alist'."
(group (or group gnus-newsgroup-name))
score-files)
(when group
- ;; Make sure funcs is a list.
- (and funcs
- (not (listp funcs))
- (setq funcs (list funcs)))
+ (setq funcs (ensure-list funcs))
(when gnus-score-use-all-scores
;; Get the initial score files for this group.
(when funcs
@@ -3104,12 +3101,8 @@ The list is determined from the variable `gnus-score-file-alist'."
(defun gnus-home-score-file (group &optional adapt)
"Return the home score file for GROUP.
If ADAPT, return the home adaptive file instead."
- (let ((list (if adapt gnus-home-adapt-file gnus-home-score-file))
+ (let ((list (ensure-list (if adapt gnus-home-adapt-file gnus-home-score-file)))
elem found)
- ;; Make sure we have a list.
- (unless (listp list)
- (setq list (list list)))
- ;; Go through the list and look for matches.
(while (and (not found)
(setq elem (pop list)))
(setq found
diff --git a/lisp/gnus/gnus-search.el b/lisp/gnus/gnus-search.el
index 98a7e23428b..a967d6d71da 100644
--- a/lisp/gnus/gnus-search.el
+++ b/lisp/gnus/gnus-search.el
@@ -1,6 +1,6 @@
;;; gnus-search.el --- Search facilities for Gnus -*- lexical-binding: t; -*-
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
;; Author: Eric Abrahamsen <eric@ericabrahamsen.net>
@@ -1434,6 +1434,9 @@ Returns a list of [group article score] vectors."
""))
(groups (mapcar #'gnus-group-short-name groups))
artlist article group)
+ (when (>= gnus-verbose 7)
+ (gnus-message 7 "Search engine returned %d results"
+ (car (buffer-line-statistics))))
(goto-char (point-min))
;; Prep prefix, we want to at least be removing the root
;; filesystem separator.
@@ -1447,7 +1450,7 @@ Returns a list of [group article score] vectors."
(when (and f-name
(file-readable-p f-name)
(null (file-directory-p f-name)))
- ;; `expand-file-name' canoncalizes the file name,
+ ;; `expand-file-name' canonicalizes the file name,
;; specifically collapsing multiple consecutive directory
;; separators.
(setq f-name (expand-file-name f-name)
@@ -1485,6 +1488,10 @@ Returns a list of [group article score] vectors."
;; Are we running an additional grep query?
(when-let ((grep-reg (alist-get 'grep query)))
(setq artlist (gnus-search-grep-search engine artlist grep-reg)))
+
+ (when (>= gnus-verbose 7)
+ (gnus-message 7 "Gnus search returning %d results"
+ (length artlist)))
;; Munge into the list of vectors expected by nnselect.
(mapcar (pcase-lambda (`(,_ ,article ,group ,score))
(vector
diff --git a/lisp/gnus/gnus-sieve.el b/lisp/gnus/gnus-sieve.el
index c7182859282..04af180a9d2 100644
--- a/lisp/gnus/gnus-sieve.el
+++ b/lisp/gnus/gnus-sieve.el
@@ -1,6 +1,6 @@
;;; gnus-sieve.el --- Utilities to manage sieve scripts for Gnus -*- lexical-binding: t; -*-
-;; Copyright (C) 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2024 Free Software Foundation, Inc.
;; Author: NAGY Andras <nagya@inf.elte.hu>,
;; Simon Josefsson <simon@josefsson.org>
diff --git a/lisp/gnus/gnus-spec.el b/lisp/gnus/gnus-spec.el
index a58ad1fc128..a7c79c5c653 100644
--- a/lisp/gnus/gnus-spec.el
+++ b/lisp/gnus/gnus-spec.el
@@ -1,6 +1,6 @@
;;; gnus-spec.el --- format spec functions for Gnus -*- lexical-binding: t; -*-
-;; Copyright (C) 1996-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-2024 Free Software Foundation, Inc.
;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
;; Keywords: news
diff --git a/lisp/gnus/gnus-srvr.el b/lisp/gnus/gnus-srvr.el
index 7dd237bce4d..63956222fa1 100644
--- a/lisp/gnus/gnus-srvr.el
+++ b/lisp/gnus/gnus-srvr.el
@@ -1,6 +1,6 @@
;;; gnus-srvr.el --- virtual server support for Gnus -*- lexical-binding: t; -*-
-;; Copyright (C) 1995-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1995-2024 Free Software Foundation, Inc.
;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
;; Keywords: news
diff --git a/lisp/gnus/gnus-start.el b/lisp/gnus/gnus-start.el
index 19b8b09de03..f337278994c 100644
--- a/lisp/gnus/gnus-start.el
+++ b/lisp/gnus/gnus-start.el
@@ -1,6 +1,6 @@
;;; gnus-start.el --- startup functions for Gnus -*- lexical-binding:t -*-
-;; Copyright (C) 1996-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-2024 Free Software Foundation, Inc.
;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
;; Keywords: news
diff --git a/lisp/gnus/gnus-sum.el b/lisp/gnus/gnus-sum.el
index a3be5577f7a..fd67e46a401 100644
--- a/lisp/gnus/gnus-sum.el
+++ b/lisp/gnus/gnus-sum.el
@@ -1,6 +1,6 @@
;;; gnus-sum.el --- summary mode commands for Gnus -*- lexical-binding:t -*-
-;; Copyright (C) 1996-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-2024 Free Software Foundation, Inc.
;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
;; Keywords: news
@@ -122,7 +122,7 @@ The server has to support NOV for any of this to work.
This feature can seriously impact performance it ignores all
locally cached header entries. Setting it to t for groups for a
-server that doesn't expire articles (such as news.gmane.org),
+server that doesn't expire articles (such as news.gmane.io),
leads to very slow summary generation."
:group 'gnus-thread
:type '(choice (const :tag "off" nil)
@@ -322,7 +322,8 @@ This can either be a regular expression or list of regular expressions
that will be removed from subject strings if fuzzy subject
simplification is selected."
:group 'gnus-thread
- :type '(repeat regexp))
+ :type '(choice regexp
+ (repeat regexp)))
(defcustom gnus-show-threads t
"If non-nil, display threads in summary mode."
@@ -8331,39 +8332,29 @@ articles."
(defun gnus-summary-limit-to-age (age &optional younger-p)
"Limit the summary buffer to articles that are older than (or equal) AGE days.
-If YOUNGER-P (the prefix) is non-nil, limit the summary buffer to
-articles that are younger than AGE days."
+Days are counted from midnight to midnight, and now to the
+previous midnight counts as day one. If YOUNGER-P (the prefix)
+is non-nil, limit the summary buffer to articles that are younger
+than AGE days."
(interactive
- (let ((younger current-prefix-arg)
- (days-got nil)
- days)
- (while (not days-got)
- (setq days (if younger
- (read-string "Limit to articles younger than (in days, older when negative): ")
- (read-string
- "Limit to articles older than (in days, younger when negative): ")))
- (when (> (length days) 0)
- (setq days (read days)))
- (if (numberp days)
- (progn
- (setq days-got t)
- (when (< days 0)
- (setq younger (not younger))
- (setq days (* days -1))))
- (message "Please enter a number.")
- (sleep-for 1)))
+ (let* ((younger current-prefix-arg)
+ (days (read-number
+ (if younger "Limit to articles younger than days: "
+ "Limit to articles older than days: "))))
(list days younger))
gnus-summary-mode)
(prog1
- (let ((data gnus-newsgroup-data)
- (cutoff (days-to-time age))
- articles d date is-younger)
+ (let* ((data gnus-newsgroup-data)
+ (now (append '(0 0 0) (cdddr (decode-time))))
+ (delta (make-decoded-time :day (* -1 (- age 1))))
+ (cutoff (encode-time (decoded-time-add now delta)))
+ articles d date is-younger)
(while (setq d (pop data))
(when (and (mail-header-p (gnus-data-header d))
(setq date (mail-header-date (gnus-data-header d))))
(setq is-younger (time-less-p
- (time-since (gnus-date-get-time date))
- cutoff))
+ cutoff
+ (gnus-date-get-time date)))
(when (if younger-p
is-younger
(not is-younger))
diff --git a/lisp/gnus/gnus-topic.el b/lisp/gnus/gnus-topic.el
index f41c457ecbc..7a1053bd6f0 100644
--- a/lisp/gnus/gnus-topic.el
+++ b/lisp/gnus/gnus-topic.el
@@ -1,6 +1,6 @@
;;; gnus-topic.el --- a folding minor mode for Gnus group buffers -*- lexical-binding: t; -*-
-;; Copyright (C) 1995-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1995-2024 Free Software Foundation, Inc.
;; Author: Ilja Weis <kult@uni-paderborn.de>
;; Lars Magne Ingebrigtsen <larsi@gnus.org>
diff --git a/lisp/gnus/gnus-undo.el b/lisp/gnus/gnus-undo.el
index e19a7b78363..c29659db237 100644
--- a/lisp/gnus/gnus-undo.el
+++ b/lisp/gnus/gnus-undo.el
@@ -1,6 +1,6 @@
;;; gnus-undo.el --- minor mode for undoing in Gnus -*- lexical-binding: t; -*-
-;; Copyright (C) 1996-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-2024 Free Software Foundation, Inc.
;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
;; Keywords: news
diff --git a/lisp/gnus/gnus-util.el b/lisp/gnus/gnus-util.el
index 4b5bc69894b..b5aa0b02d34 100644
--- a/lisp/gnus/gnus-util.el
+++ b/lisp/gnus/gnus-util.el
@@ -1,6 +1,6 @@
;;; gnus-util.el --- utility functions for Gnus -*- lexical-binding: t; -*-
-;; Copyright (C) 1996-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-2024 Free Software Foundation, Inc.
;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
;; Keywords: news
@@ -343,10 +343,10 @@ Symbols are also allowed; their print names are used instead."
(yes-or-no-p prompt)
(message "")))
-;; By Frank Schmitt <ich@Frank-Schmitt.net>. Allows to have
-;; age-depending date representations. (e.g. just the time if it's
-;; from today, the day of the week if it's within the last 7 days and
-;; the full date if it's older)
+;; By Frank Schmitt <ich@Frank-Schmitt.net>. Enables age-dependent
+;; date representations. (e.g. just the time if it's from today, the
+;; day of the week if it's within the last 7 days and the full date if
+;; it's older)
(defun gnus-seconds-today ()
"Return the integer number of seconds passed today."
diff --git a/lisp/gnus/gnus-uu.el b/lisp/gnus/gnus-uu.el
index 1846f05af2d..95236a167fc 100644
--- a/lisp/gnus/gnus-uu.el
+++ b/lisp/gnus/gnus-uu.el
@@ -1,6 +1,6 @@
;;; gnus-uu.el --- extract (uu)encoded files in Gnus -*- lexical-binding: t; -*-
-;; Copyright (C) 1985-1987, 1993-1998, 2000-2023 Free Software
+;; Copyright (C) 1985-1987, 1993-1998, 2000-2024 Free Software
;; Foundation, Inc.
;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
@@ -1371,8 +1371,7 @@ When called interactively, prompt for REGEXP."
;; Allow user-defined functions to be run on this file.
(when gnus-uu-grabbed-file-functions
(let ((funcs gnus-uu-grabbed-file-functions))
- (unless (listp funcs)
- (setq funcs (list funcs)))
+ (setq funcs (ensure-list funcs))
(while funcs
(funcall (pop funcs) result-file))))
(setq result-file nil)
diff --git a/lisp/gnus/gnus-vm.el b/lisp/gnus/gnus-vm.el
index 9d83b974719..9e7b5d86662 100644
--- a/lisp/gnus/gnus-vm.el
+++ b/lisp/gnus/gnus-vm.el
@@ -1,6 +1,6 @@
;;; gnus-vm.el --- vm interface for Gnus -*- lexical-binding: t; -*-
-;; Copyright (C) 1994-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1994-2024 Free Software Foundation, Inc.
;; Author: Per Persson <pp@gnu.ai.mit.edu>
;; Keywords: news, mail
diff --git a/lisp/gnus/gnus-win.el b/lisp/gnus/gnus-win.el
index 9d8b34aef29..885d20823b7 100644
--- a/lisp/gnus/gnus-win.el
+++ b/lisp/gnus/gnus-win.el
@@ -1,6 +1,6 @@
;;; gnus-win.el --- window configuration functions for Gnus -*- lexical-binding: t; -*-
-;; Copyright (C) 1996-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-2024 Free Software Foundation, Inc.
;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
;; Keywords: news
diff --git a/lisp/gnus/gnus.el b/lisp/gnus/gnus.el
index fc8518512ee..99833e4eeca 100644
--- a/lisp/gnus/gnus.el
+++ b/lisp/gnus/gnus.el
@@ -1,6 +1,6 @@
;;; gnus.el --- a newsreader for GNU Emacs -*- lexical-binding:t -*-
-;; Copyright (C) 1987-1990, 1993-1998, 2000-2023 Free Software
+;; Copyright (C) 1987-1990, 1993-1998, 2000-2024 Free Software
;; Foundation, Inc.
;; Author: Masanobu UMEDA <umerin@flab.flab.fujitsu.junet>
@@ -319,20 +319,25 @@ be set in `.emacs' instead."
(not (stringp str))
(not (string-match "^Gnus:" str)))
(list str)
- (let ((load-path (append (mm-image-load-path) load-path)))
+ (let ((load-path (append (mm-image-load-path) load-path))
+ (gnus-emacs-version (gnus-emacs-version)))
;; Add the Gnus logo.
(add-text-properties
0 5
(list 'display
(find-image
- '((:type xpm :file "gnus-pointer.xpm"
+ '((:type svg :file "gnus-pointer.svg"
+ :ascent center)
+ (:type xpm :file "gnus-pointer.xpm"
:ascent center)
(:type xbm :file "gnus-pointer.xbm"
:ascent center))
t)
- 'help-echo (format
- "This is %s, %s."
- gnus-version (gnus-emacs-version)))
+ 'help-echo (if gnus-emacs-version
+ (format
+ "This is %s, %s."
+ gnus-version gnus-emacs-version)
+ (format "This is %s." gnus-version)))
str)
(list str)))))
diff --git a/lisp/gnus/gssapi.el b/lisp/gnus/gssapi.el
index beb9ba41e11..58c26c4e47c 100644
--- a/lisp/gnus/gssapi.el
+++ b/lisp/gnus/gssapi.el
@@ -1,6 +1,6 @@
;;; gssapi.el --- GSSAPI/Kerberos 5 interface for Emacs -*- lexical-binding: t; -*-
-;; Copyright (C) 2011-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2011-2024 Free Software Foundation, Inc.
;; Author: Simon Josefsson <simon@josefsson.org>
;; Lars Magne Ingebrigtsen <larsi@gnus.org>
diff --git a/lisp/gnus/legacy-gnus-agent.el b/lisp/gnus/legacy-gnus-agent.el
index bd95c5137f5..d4f08c72de8 100644
--- a/lisp/gnus/legacy-gnus-agent.el
+++ b/lisp/gnus/legacy-gnus-agent.el
@@ -1,6 +1,6 @@
;;; legacy-gnus-agent.el --- Legacy unplugged support for Gnus -*- lexical-binding: t; -*-
-;; Copyright (C) 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2004-2024 Free Software Foundation, Inc.
;; Author: Kevin Greiner <kgreiner@xpediantsolutions.com>
;; Keywords: news
diff --git a/lisp/gnus/mail-source.el b/lisp/gnus/mail-source.el
index f870c0b8274..fdafc29f7e8 100644
--- a/lisp/gnus/mail-source.el
+++ b/lisp/gnus/mail-source.el
@@ -1,6 +1,6 @@
;;; mail-source.el --- functions for fetching mail -*- lexical-binding: t; -*-
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
;; Keywords: news, mail
diff --git a/lisp/gnus/message.el b/lisp/gnus/message.el
index 45cc21701b3..979d2fecf56 100644
--- a/lisp/gnus/message.el
+++ b/lisp/gnus/message.el
@@ -1,6 +1,6 @@
;;; message.el --- composing mail and news messages -*- lexical-binding: t -*-
-;; Copyright (C) 1996-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-2024 Free Software Foundation, Inc.
;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
;; Keywords: mail, news
@@ -154,7 +154,7 @@ If this variable is nil, no such courtesy message will be added."
:type '(radio string (const nil)))
(defcustom message-ignored-bounced-headers
- "^\\(Received\\|Return-Path\\|Delivered-To\\):"
+ "^\\(Received\\|Return-Path\\|Delivered-To\\|DKIM-Signature\\|X-Hashcash\\):"
"Regexp that matches headers to be removed in resent bounced mail."
:group 'message-interface
:type 'regexp)
@@ -747,16 +747,14 @@ default is system dependent and determined by the function
`message-send-mail-function'.
See also `send-mail-function'."
- :type '(radio (function-item message--default-send-mail-function
- :tag "Use send-mail-function")
+ :type '(radio (function-item message--default-send-mail-function)
(function-item message-send-mail-with-sendmail)
(function-item message-send-mail-with-mh)
(function-item message-send-mail-with-qmail)
(function-item message-smtpmail-send-it)
- (function-item smtpmail-send-it)
+ (function-item :doc "Use SMTPmail package." smtpmail-send-it)
(function-item feedmail-send-it)
- (function-item message-send-mail-with-mailclient
- :tag "Use Mailclient package")
+ (function-item message-send-mail-with-mailclient)
(function :tag "Other"))
:group 'message-sending
:version "27.1"
@@ -911,8 +909,10 @@ installations, which are rare these days."
(defcustom message-sendmail-envelope-from
'obey-mail-envelope-from
"Envelope-from when sending mail with sendmail.
-If this is nil, use `user-mail-address'. If it is the symbol
-`header', use the From: header of the message."
+If this is `obey-mail-envelope-from', then use
+`mail-envelope-from' to decide what to do. If it is nil, use
+`user-mail-address'. If it is the symbol `header', use the
+\"From:\" header of the message."
:version "27.1"
:type '(choice (string :tag "From name")
(const :tag "Use From: header from message" header)
@@ -1145,7 +1145,8 @@ Note that these functions use `mail-citation-hook' if that is non-nil."
This can also be a list of functions. Each function can find the
citation between (point) and (mark t). And each function should leave
point and mark around the citation text as modified."
- :type 'function
+ :type '(choice function
+ (repeat function))
:link '(custom-manual "(message)Insertion Variables")
:group 'message-insertion)
@@ -1406,8 +1407,9 @@ This can also be a list of values."
:group 'message
:link '(custom-manual "(message)Mail Aliases")
:type '(choice (const :tag "Use Mailabbrev" abbrev)
- (const :tag "Use ecomplete" ecomplete)
- (const :tag "No expansion" nil)))
+ (const :tag "Use ecomplete" ecomplete)
+ (set (const :tag "Use Mailabbrev" abbrev)
+ (const :tag "Use ecomplete" ecomplete))))
(defcustom message-self-insert-commands '(self-insert-command)
"List of `self-insert-command's used to trigger ecomplete.
@@ -1451,8 +1453,9 @@ If a function email is passed as the argument."
:group 'message
:link '(custom-manual "(message)Wide Reply")
:type '(choice (const :tag "Yourself" nil)
- regexp
- (repeat :tag "Regexp List" regexp)))
+ regexp
+ (repeat :tag "Regexp List" regexp)
+ function))
(defsubst message-dont-reply-to-names ()
(if (functionp message-dont-reply-to-names)
@@ -1873,9 +1876,13 @@ downcased."
:type '(repeat (repeat string)))
(defcustom message-mail-user-agent nil
- "Like `mail-user-agent'.
-Except if it is nil, use Gnus native MUA; if it is t, use
-`mail-user-agent'."
+ "Your preferred package for composing and sending email when using message.el.
+Like `mail-user-agent' (which see), this specifies the package you prefer
+to use for composing and sending email messages.
+The value can be anything accepted by `mail-user-agent', and in addition
+it can be nil or t. If the value is nil, use the Gnus native Mail User
+Agent (MUA); if it is t, use the value of `mail-user-agent'.
+For more about mail user agents, see Info node `(emacs)Mail Methods'"
:version "22.1"
:type '(radio (const :tag "Gnus native"
:format "%t\n"
@@ -2838,11 +2845,11 @@ will not be inserted."
(const :tag "No ID" nil))
(choice (string :tag "Key")
(const :tag "No Key" nil))
- (choice (other :tag "None" nil)
- (const :tag "Unprotected" "unprotected")
+ (choice (const :tag "Unprotected" "unprotected")
(const :tag "Sign" "sign")
(const :tag "Encrypt" "encrypt")
- (const :tag "Sign and Encrypt" "signencrypt"))))
+ (const :tag "Sign and Encrypt" "signencrypt")
+ (other :tag "None" nil))))
:version "28.1")
(defun message-add-openpgp-header ()
@@ -6593,8 +6600,8 @@ they are."
(widen)
(forward-line 1)
(unless (looking-at "$")
- (forward-line 2)))
- (sit-for 0)))
+ (forward-line 2))))
+ (sit-for 0))
(defcustom message-beginning-of-line t
"Whether \\<message-mode-map>\\[message-beginning-of-line]\
@@ -7707,10 +7714,7 @@ the message."
""))
(when message-wash-forwarded-subjects
(setq subject (message-wash-subject subject)))
- ;; Make sure funcs is a list.
- (and funcs
- (not (listp funcs))
- (setq funcs (list funcs)))
+ (setq funcs (ensure-list funcs))
;; Apply funcs in order, passing subject generated by previous
;; func to the next one.
(dolist (func funcs)
@@ -8211,7 +8215,6 @@ which specify the range to operate on."
It can be either a list or a symbol referring to a list. See
`gmm-tool-bar-from-list' for the format of the list. The
default key map is `message-mode-map'."
- :type '(repeat gmm-tool-bar-list-item)
:type '(choice (repeat :tag "User defined list" gmm-tool-bar-item)
(symbol))
:version "29.1"
@@ -8975,32 +8978,61 @@ used to take the screenshot."
retval))
;;;###autoload
-(defun message-mailto (&optional url)
+(defun message-mailto (&optional url subject body file-attachments)
"Command to parse command line mailto: links.
This is meant to be used for MIME handlers: Setting the handler
for \"x-scheme-handler/mailto;\" to \"emacs -f message-mailto %u\"
will then start up Emacs ready to compose mail. For emacsclient use
- emacsclient -e \\='(message-mailto \"%u\")'"
+ emacsclient -e \\='(message-mailto \"%u\")'
+
+To facilitate the use of this function within window systems that
+provide message subject, body and attachments independent of URL
+itself, the arguments SUBJECT, BODY and FILE-ATTACHMENTS may also
+provide alternative message subject and body text, which is
+inserted in lieu of nothing if URL does not incorporate such
+information itself, and a list of files to insert as attachments
+to the E-mail."
(interactive)
;; <a href="mailto:someone@example.com?subject=This%20is%20the%20subject&cc=someone_else@example.com&body=This%20is%20the%20body">Send email</a>
(message-mail)
- (message-mailto-1 (or url (pop command-line-args-left))))
+ (message-mailto-1 (or url (pop command-line-args-left))
+ subject body file-attachments))
-(defun message-mailto-1 (url)
- (let ((args (message-parse-mailto-url url)))
+(defun message-mailto-1 (url &optional subject body file-attachments)
+ (let ((args (message-parse-mailto-url url))
+ (need-body nil) (need-subject nil))
(dolist (arg args)
(unless (equal (car arg) "body")
(message-position-on-field (capitalize (car arg)))
(insert (string-replace
"\r\n" "\n"
(mapconcat #'identity (reverse (cdr arg)) ", ")))))
- (when (assoc "body" args)
- (message-goto-body)
- (dolist (body (cdr (assoc "body" args)))
- (insert body "\n")))
+ (if (assoc "body" args)
+ (progn
+ (message-goto-body)
+ (dolist (body (cdr (assoc "body" args)))
+ (insert body "\n")))
+
+ (setq need-body t))
(if (assoc "subject" args)
(message-goto-body)
- (message-goto-subject))))
+ (setq need-subject t)
+ (message-goto-subject))
+ ;; If either one of need-subject and need-body is non-nil then
+ ;; attempt to insert the absent information from an external
+ ;; SUBJECT or BODY.
+ (when (or need-body need-subject)
+ (when (and need-body body)
+ (message-goto-body)
+ (insert body))
+ (when (and need-subject subject)
+ (message-goto-subject)
+ (insert subject)
+ (message-goto-body)))
+ ;; Subsequently insert each attachment enumerated within
+ ;; FILE-ATTACHMENTS.
+ (dolist (file file-attachments)
+ (mml-attach-file file nil 'attachment))))
(provide 'message)
diff --git a/lisp/gnus/mm-archive.el b/lisp/gnus/mm-archive.el
index 50f6012148e..9add3e1c8ea 100644
--- a/lisp/gnus/mm-archive.el
+++ b/lisp/gnus/mm-archive.el
@@ -1,6 +1,6 @@
;;; mm-archive.el --- Functions for parsing archive files as MIME -*- lexical-binding: t; -*-
-;; Copyright (C) 2012-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2012-2024 Free Software Foundation, Inc.
;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
;; This file is part of GNU Emacs.
diff --git a/lisp/gnus/mm-bodies.el b/lisp/gnus/mm-bodies.el
index 2290b667abe..912bbc1fe8c 100644
--- a/lisp/gnus/mm-bodies.el
+++ b/lisp/gnus/mm-bodies.el
@@ -1,6 +1,6 @@
;;; mm-bodies.el --- Functions for decoding MIME things -*- lexical-binding: t; -*-
-;; Copyright (C) 1998-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-2024 Free Software Foundation, Inc.
;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
;; MORIOKA Tomohiko <morioka@jaist.ac.jp>
diff --git a/lisp/gnus/mm-decode.el b/lisp/gnus/mm-decode.el
index b9beedf6c5c..f91755e967b 100644
--- a/lisp/gnus/mm-decode.el
+++ b/lisp/gnus/mm-decode.el
@@ -1,6 +1,6 @@
;;; mm-decode.el --- Functions for decoding MIME things -*- lexical-binding:t -*-
-;; Copyright (C) 1998-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-2024 Free Software Foundation, Inc.
;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
;; MORIOKA Tomohiko <morioka@jaist.ac.jp>
@@ -119,7 +119,7 @@
((executable-find "links") 'links)
((executable-find "lynx") 'lynx)
(t 'shr))
- "Render of HTML contents.
+ "Renderer of HTML contents.
It is one of defined renderer types, or a rendering function.
The defined renderer types are:
`shr': use the built-in Gnus HTML renderer;
@@ -131,8 +131,8 @@ The defined renderer types are:
:version "29.1"
:type '(choice (const shr)
(const gnus-w3m)
- (const w3m :tag "emacs-w3m")
- (const w3m-standalone :tag "standalone w3m" )
+ (const :tag "emacs-w3m" w3m)
+ (const :tag "standalone w3m" w3m-standalone)
(const links)
(const lynx)
(function))
diff --git a/lisp/gnus/mm-encode.el b/lisp/gnus/mm-encode.el
index 14b7da299b8..560d7bd30a9 100644
--- a/lisp/gnus/mm-encode.el
+++ b/lisp/gnus/mm-encode.el
@@ -1,6 +1,6 @@
;;; mm-encode.el --- Functions for encoding MIME things -*- lexical-binding: t; -*-
-;; Copyright (C) 1998-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-2024 Free Software Foundation, Inc.
;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
;; MORIOKA Tomohiko <morioka@jaist.ac.jp>
diff --git a/lisp/gnus/mm-extern.el b/lisp/gnus/mm-extern.el
index 1d628c3d6b5..c23e176d60d 100644
--- a/lisp/gnus/mm-extern.el
+++ b/lisp/gnus/mm-extern.el
@@ -1,6 +1,6 @@
;;; mm-extern.el --- showing message/external-body -*- lexical-binding:t -*-
-;; Copyright (C) 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2000-2024 Free Software Foundation, Inc.
;; Author: Shenghuo Zhu <zsh@cs.rochester.edu>
;; Keywords: message external-body
diff --git a/lisp/gnus/mm-partial.el b/lisp/gnus/mm-partial.el
index 35b1ff197f8..56781527aca 100644
--- a/lisp/gnus/mm-partial.el
+++ b/lisp/gnus/mm-partial.el
@@ -1,6 +1,6 @@
;;; mm-partial.el --- showing message/partial -*- lexical-binding: t; -*-
-;; Copyright (C) 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2000-2024 Free Software Foundation, Inc.
;; Author: Shenghuo Zhu <zsh@cs.rochester.edu>
;; Keywords: message partial
diff --git a/lisp/gnus/mm-url.el b/lisp/gnus/mm-url.el
index 11847a79f17..be6c9bb7977 100644
--- a/lisp/gnus/mm-url.el
+++ b/lisp/gnus/mm-url.el
@@ -1,6 +1,6 @@
;;; mm-url.el --- a wrapper of url functions/commands for Gnus -*- lexical-binding: t; -*-
-;; Copyright (C) 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2024 Free Software Foundation, Inc.
;; Author: Shenghuo Zhu <zsh@cs.rochester.edu>
diff --git a/lisp/gnus/mm-util.el b/lisp/gnus/mm-util.el
index 2065747b859..0e4bbbe650f 100644
--- a/lisp/gnus/mm-util.el
+++ b/lisp/gnus/mm-util.el
@@ -1,6 +1,6 @@
;;; mm-util.el --- Utility functions for Mule and low level things -*- lexical-binding:t -*-
-;; Copyright (C) 1998-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-2024 Free Software Foundation, Inc.
;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
;; MORIOKA Tomohiko <morioka@jaist.ac.jp>
diff --git a/lisp/gnus/mm-uu.el b/lisp/gnus/mm-uu.el
index 72c39aae83c..3c7e3cbdf1a 100644
--- a/lisp/gnus/mm-uu.el
+++ b/lisp/gnus/mm-uu.el
@@ -1,6 +1,6 @@
;;; mm-uu.el --- Return uu stuff as mm handles -*- lexical-binding:t -*-
-;; Copyright (C) 1998-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-2024 Free Software Foundation, Inc.
;; Author: Shenghuo Zhu <zsh@cs.rochester.edu>
;; Keywords: postscript uudecode binhex shar forward gnatsweb pgp
diff --git a/lisp/gnus/mm-view.el b/lisp/gnus/mm-view.el
index 2c407353559..3a7192092af 100644
--- a/lisp/gnus/mm-view.el
+++ b/lisp/gnus/mm-view.el
@@ -1,6 +1,6 @@
;;; mm-view.el --- functions for viewing MIME objects -*- lexical-binding: t; -*-
-;; Copyright (C) 1998-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-2024 Free Software Foundation, Inc.
;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
;; This file is part of GNU Emacs.
@@ -487,8 +487,6 @@ after inserting the part."
(let ((inhibit-read-only t))
(delete-region beg end)))))))))
-;; Shut up byte-compiler.
-(defvar font-lock-mode-hook)
(defun mm-display-inline-fontify (handle &optional mode)
"Insert HANDLE inline fontifying with MODE.
If MODE is not set, try to find mode automatically."
diff --git a/lisp/gnus/mml-sec.el b/lisp/gnus/mml-sec.el
index 44ffaf9f229..98f8ebbcbcd 100644
--- a/lisp/gnus/mml-sec.el
+++ b/lisp/gnus/mml-sec.el
@@ -1,6 +1,6 @@
;;; mml-sec.el --- A package with security functions for MML documents -*- lexical-binding: t; -*-
-;; Copyright (C) 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2000-2024 Free Software Foundation, Inc.
;; Author: Simon Josefsson <simon@josefsson.org>
diff --git a/lisp/gnus/mml-smime.el b/lisp/gnus/mml-smime.el
index 896c95f8d3e..3064c46d2a3 100644
--- a/lisp/gnus/mml-smime.el
+++ b/lisp/gnus/mml-smime.el
@@ -1,6 +1,6 @@
;;; mml-smime.el --- S/MIME support for MML -*- lexical-binding: t; -*-
-;; Copyright (C) 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2000-2024 Free Software Foundation, Inc.
;; Author: Simon Josefsson <simon@josefsson.org>
;; Keywords: Gnus, MIME, S/MIME, MML
diff --git a/lisp/gnus/mml.el b/lisp/gnus/mml.el
index 6025ca7e72a..edb3c286242 100644
--- a/lisp/gnus/mml.el
+++ b/lisp/gnus/mml.el
@@ -1,6 +1,6 @@
;;; mml.el --- A package for parsing and validating MML documents -*- lexical-binding: t; -*-
-;; Copyright (C) 1998-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-2024 Free Software Foundation, Inc.
;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
;; This file is part of GNU Emacs.
@@ -1369,9 +1369,9 @@ If not set, `default-directory' will be used."
;;; Attachment functions.
(defcustom mml-dnd-protocol-alist
- '(("^file:///" . mml-dnd-attach-file)
- ("^file://" . dnd-open-file)
- ("^file:" . mml-dnd-attach-file))
+ '(("^file:///" . mml-dnd-attach-file) ; GNOME, KDE, and suchlike.
+ ("^file:/[^/]" . mml-dnd-attach-file) ; Motif, other systems.
+ ("^file:[^/]" . mml-dnd-attach-file)) ; MS-Windows.
"The functions to call when a drop in `mml-mode' is made.
See `dnd-protocol-alist' for more information. When nil, behave
as in other buffers."
@@ -1460,29 +1460,36 @@ will be computed and used."
(file-name-nondirectory file)))
(goto-char at-end))))
-(defun mml-dnd-attach-file (uri _action)
- "Attach a drag and drop file.
-
-Ask for type, description or disposition according to
-`mml-dnd-attach-options'."
- (let ((file (dnd-get-local-file-name uri t)))
- (when (and file (file-regular-p file))
- (let ((mml-dnd-attach-options mml-dnd-attach-options)
- type description disposition)
- (setq mml-dnd-attach-options
- (when (and (eq mml-dnd-attach-options t)
- (not
- (y-or-n-p
- "Use default type, disposition and description? ")))
- '(type description disposition)))
- (when (or (memq 'type mml-dnd-attach-options)
- (memq 'disposition mml-dnd-attach-options))
- (setq type (mml-minibuffer-read-type file)))
- (when (memq 'description mml-dnd-attach-options)
- (setq description (mml-minibuffer-read-description)))
- (when (memq 'disposition mml-dnd-attach-options)
- (setq disposition (mml-minibuffer-read-disposition type nil file)))
- (mml-attach-file file type description disposition)))))
+(defun mml-dnd-attach-file (uris _action)
+ "Attach a drag and drop URIS, a list of local file URIs.
+
+Query whether to use the types, dispositions and descriptions
+default for each URL, subject to `mml-dnd-attach-options'.
+
+Return the action `private', communicating to the drop source
+that the file has been attached."
+ (let (file (mml-dnd-attach-options mml-dnd-attach-options))
+ (setq mml-dnd-attach-options
+ (when (and (eq mml-dnd-attach-options t)
+ (not
+ (y-or-n-p
+ "Use default type, disposition and description? ")))
+ '(type description disposition)))
+ (dolist (uri uris)
+ (setq file (dnd-get-local-file-name uri t))
+ (when (and file (file-regular-p file))
+ (let (type description disposition)
+ (when (or (memq 'type mml-dnd-attach-options)
+ (memq 'disposition mml-dnd-attach-options))
+ (setq type (mml-minibuffer-read-type file)))
+ (when (memq 'description mml-dnd-attach-options)
+ (setq description (mml-minibuffer-read-description)))
+ (when (memq 'disposition mml-dnd-attach-options)
+ (setq disposition (mml-minibuffer-read-disposition type nil file)))
+ (mml-attach-file file type description disposition)))))
+ 'private)
+
+(put 'mml-dnd-attach-file 'dnd-multiple-handler t)
(defun mml-attach-buffer (buffer &optional type description disposition filename)
"Attach a buffer to the outgoing MIME message.
diff --git a/lisp/gnus/mml1991.el b/lisp/gnus/mml1991.el
index 33b1f3a4c78..b44d50b5f77 100644
--- a/lisp/gnus/mml1991.el
+++ b/lisp/gnus/mml1991.el
@@ -1,6 +1,6 @@
;;; mml1991.el --- Old PGP message format (RFC 1991) support for MML -*- lexical-binding: t; -*-
-;; Copyright (C) 1998-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-2024 Free Software Foundation, Inc.
;; Author: Sascha Lüdecke <sascha@meta-x.de>,
;; Simon Josefsson <simon@josefsson.org> (Mailcrypt interface, Gnus glue)
diff --git a/lisp/gnus/mml2015.el b/lisp/gnus/mml2015.el
index 21bb46b8fa7..602a4baa73d 100644
--- a/lisp/gnus/mml2015.el
+++ b/lisp/gnus/mml2015.el
@@ -1,6 +1,6 @@
;;; mml2015.el --- MIME Security with Pretty Good Privacy (PGP) -*- lexical-binding: t; -*-
-;; Copyright (C) 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2000-2024 Free Software Foundation, Inc.
;; Author: Shenghuo Zhu <zsh@cs.rochester.edu>
;; Keywords: PGP MIME MML
@@ -148,8 +148,8 @@ If set, it overrides the setting of `mml2015-sign-with-sender'."
;;
;; This function doesn't handle NotDashEscaped correctly. EasyPG handles it
;; correctly.
- ;; http://thread.gmane.org/gmane.emacs.gnus.general/66062/focus=66082
- ;; http://thread.gmane.org/gmane.emacs.gnus.general/65087/focus=65109
+ ;; http://thread.gmane.org/gmane.emacs.gnus.general/66062/focus=66082 [dead link]
+ ;; http://thread.gmane.org/gmane.emacs.gnus.general/65087/focus=65109 [dead link]
(goto-char (point-min))
(forward-line)
;; We need to be careful not to strip beyond the armor headers.
diff --git a/lisp/gnus/nnagent.el b/lisp/gnus/nnagent.el
index 30d5514a8b7..7ccb02a45d0 100644
--- a/lisp/gnus/nnagent.el
+++ b/lisp/gnus/nnagent.el
@@ -1,6 +1,6 @@
;;; nnagent.el --- offline backend for Gnus -*- lexical-binding: t; -*-
-;; Copyright (C) 1997-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997-2024 Free Software Foundation, Inc.
;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
;; Keywords: news, mail
diff --git a/lisp/gnus/nnbabyl.el b/lisp/gnus/nnbabyl.el
index 4ad994b12f1..b002b3c0114 100644
--- a/lisp/gnus/nnbabyl.el
+++ b/lisp/gnus/nnbabyl.el
@@ -1,6 +1,6 @@
;;; nnbabyl.el --- rmail mbox access for Gnus -*- lexical-binding: t; -*-
-;; Copyright (C) 1995-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1995-2024 Free Software Foundation, Inc.
;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
;; Masanobu UMEDA <umerin@flab.flab.fujitsu.junet>
diff --git a/lisp/gnus/nndiary.el b/lisp/gnus/nndiary.el
index 8728aab1def..b6f423ee2f8 100644
--- a/lisp/gnus/nndiary.el
+++ b/lisp/gnus/nndiary.el
@@ -1,6 +1,6 @@
;;; nndiary.el --- A diary back end for Gnus -*- lexical-binding: t; -*-
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
;; Author: Didier Verna <didier@didierverna.net>
;; Created: Fri Jul 16 18:55:42 1999
@@ -1030,7 +1030,7 @@ all. This may very well take some time.")
(defun nndiary-generate-nov-databases (&optional server)
"Generate NOV databases in all nndiary directories."
(interactive (list (or (nnoo-current-server 'nndiary) "")))
- ;; Read the active file to make sure we don't re-use articles
+ ;; Read the active file to make sure we don't reuse articles
;; numbers in empty groups.
(nnmail-activate 'nndiary)
(unless (nndiary-server-opened server)
diff --git a/lisp/gnus/nndir.el b/lisp/gnus/nndir.el
index 3b21a933409..039925331d1 100644
--- a/lisp/gnus/nndir.el
+++ b/lisp/gnus/nndir.el
@@ -1,6 +1,6 @@
;;; nndir.el --- single directory newsgroup access for Gnus -*- lexical-binding: t; -*-
-;; Copyright (C) 1995-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1995-2024 Free Software Foundation, Inc.
;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
;; Keywords: news
diff --git a/lisp/gnus/nndoc.el b/lisp/gnus/nndoc.el
index 0d499a15c3d..06a5e6808dd 100644
--- a/lisp/gnus/nndoc.el
+++ b/lisp/gnus/nndoc.el
@@ -1,6 +1,6 @@
;;; nndoc.el --- single file access for Gnus -*- lexical-binding: t; -*-
-;; Copyright (C) 1995-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1995-2024 Free Software Foundation, Inc.
;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
;; Masanobu UMEDA <umerin@flab.flab.fujitsu.junet>
diff --git a/lisp/gnus/nndraft.el b/lisp/gnus/nndraft.el
index bf90cfaa207..3ad495966f4 100644
--- a/lisp/gnus/nndraft.el
+++ b/lisp/gnus/nndraft.el
@@ -1,6 +1,6 @@
;;; nndraft.el --- draft article access for Gnus -*- lexical-binding: t; -*-
-;; Copyright (C) 1995-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1995-2024 Free Software Foundation, Inc.
;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
;; Keywords: news
diff --git a/lisp/gnus/nneething.el b/lisp/gnus/nneething.el
index a6b5870ca98..9d1c676b912 100644
--- a/lisp/gnus/nneething.el
+++ b/lisp/gnus/nneething.el
@@ -1,6 +1,6 @@
;;; nneething.el --- arbitrary file access for Gnus -*- lexical-binding: t; -*-
-;; Copyright (C) 1995-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1995-2024 Free Software Foundation, Inc.
;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
;; Masanobu UMEDA <umerin@flab.flab.fujitsu.junet>
diff --git a/lisp/gnus/nnfolder.el b/lisp/gnus/nnfolder.el
index 3516a75e927..66683f77433 100644
--- a/lisp/gnus/nnfolder.el
+++ b/lisp/gnus/nnfolder.el
@@ -1,6 +1,6 @@
;;; nnfolder.el --- mail folder access for Gnus -*- lexical-binding: t; -*-
-;; Copyright (C) 1995-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1995-2024 Free Software Foundation, Inc.
;; Author: Simon Josefsson <simon@josefsson.org>
;; ShengHuo Zhu <zsh@cs.rochester.edu> (adding NOV)
diff --git a/lisp/gnus/nngateway.el b/lisp/gnus/nngateway.el
index 152ef08f0f7..d7e772e8bf5 100644
--- a/lisp/gnus/nngateway.el
+++ b/lisp/gnus/nngateway.el
@@ -1,6 +1,6 @@
;;; nngateway.el --- posting news via mail gateways -*- lexical-binding: t; -*-
-;; Copyright (C) 1996-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-2024 Free Software Foundation, Inc.
;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
;; Keywords: news, mail
diff --git a/lisp/gnus/nnheader.el b/lisp/gnus/nnheader.el
index cdba6e663bf..97821894b48 100644
--- a/lisp/gnus/nnheader.el
+++ b/lisp/gnus/nnheader.el
@@ -1,6 +1,6 @@
;;; nnheader.el --- header access macros for Gnus and its backends -*- lexical-binding: t; -*-
-;; Copyright (C) 1987-1990, 1993-1998, 2000-2023 Free Software
+;; Copyright (C) 1987-1990, 1993-1998, 2000-2024 Free Software
;; Foundation, Inc.
;; Author: Masanobu UMEDA <umerin@flab.flab.fujitsu.junet>
@@ -85,7 +85,7 @@ Integer values will in effect be rounded up to the nearest multiple of
(defvar nnheader-read-timeout
(if (memq system-type '(windows-nt cygwin))
- ;; http://thread.gmane.org/v9655t3pjo.fsf@marauder.physik.uni-ulm.de
+ ;; http://thread.gmane.org/v9655t3pjo.fsf@marauder.physik.uni-ulm.de [dead link]
;;
;; IIRC, values lower than 1.0 didn't/don't work on Windows/DOS.
;;
diff --git a/lisp/gnus/nnimap.el b/lisp/gnus/nnimap.el
index 81449cb58b2..17a55f988c9 100644
--- a/lisp/gnus/nnimap.el
+++ b/lisp/gnus/nnimap.el
@@ -1,6 +1,6 @@
;;; nnimap.el --- IMAP interface for Gnus -*- lexical-binding: t; -*-
-;; Copyright (C) 2010-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2010-2024 Free Software Foundation, Inc.
;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
;; Simon Josefsson <simon@josefsson.org>
diff --git a/lisp/gnus/nnmail.el b/lisp/gnus/nnmail.el
index e8f157392d4..fef12eebe09 100644
--- a/lisp/gnus/nnmail.el
+++ b/lisp/gnus/nnmail.el
@@ -1,6 +1,6 @@
;;; nnmail.el --- mail support functions for the Gnus mail backends -*- lexical-binding: t; -*-
-;; Copyright (C) 1995-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1995-2024 Free Software Foundation, Inc.
;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
;; Keywords: news, mail
@@ -667,7 +667,9 @@ nn*-request-list should have been called before calling this function."
(cond ((symbolp group)
(symbol-name group))
((numberp group)
- (number-to-string group))))
+ (number-to-string group))
+ ((stringp group)
+ group)))
(if (and (numberp (setq max (read buffer)))
(numberp (setq min (read buffer))))
(push (list group (cons min max))
diff --git a/lisp/gnus/nnmairix.el b/lisp/gnus/nnmairix.el
index 72833d7bc33..c517f85db9b 100644
--- a/lisp/gnus/nnmairix.el
+++ b/lisp/gnus/nnmairix.el
@@ -1,6 +1,6 @@
;;; nnmairix.el --- Mairix back end for Gnus, the Emacs newsreader -*- lexical-binding: t; -*-
-;; Copyright (C) 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2024 Free Software Foundation, Inc.
;; Author: David Engster <deng@randomsample.de>
;; Keywords: mail searching
@@ -741,8 +741,7 @@ called interactively, user will be asked for parameters."
(when (and (stringp query)
(string-match "\\s-" query))
(setq query (split-string query)))
- (when (not (listp query))
- (setq query (list query)))
+ (setq query (ensure-list query))
(when (and server group query)
(let ((groupname (gnus-group-prefixed-name group server))
) ;; info
diff --git a/lisp/gnus/nnmbox.el b/lisp/gnus/nnmbox.el
index c1a064c27f3..ac6846dda05 100644
--- a/lisp/gnus/nnmbox.el
+++ b/lisp/gnus/nnmbox.el
@@ -1,6 +1,6 @@
;;; nnmbox.el --- mail mbox access for Gnus -*- lexical-binding: t; -*-
-;; Copyright (C) 1995-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1995-2024 Free Software Foundation, Inc.
;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
;; Masanobu UMEDA <umerin@flab.flab.fujitsu.junet>
diff --git a/lisp/gnus/nnmh.el b/lisp/gnus/nnmh.el
index bb5ea3fa1bb..e11d063f6ee 100644
--- a/lisp/gnus/nnmh.el
+++ b/lisp/gnus/nnmh.el
@@ -1,6 +1,6 @@
;;; nnmh.el --- mhspool access for Gnus -*- lexical-binding: t; -*-
-;; Copyright (C) 1995-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1995-2024 Free Software Foundation, Inc.
;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
;; Masanobu UMEDA <umerin@flab.flab.fujitsu.junet>
diff --git a/lisp/gnus/nnml.el b/lisp/gnus/nnml.el
index d969716f020..7a37cb6090b 100644
--- a/lisp/gnus/nnml.el
+++ b/lisp/gnus/nnml.el
@@ -1,6 +1,6 @@
;;; nnml.el --- mail spool access for Gnus -*- lexical-binding: t; -*-
-;; Copyright (C) 1995-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1995-2024 Free Software Foundation, Inc.
;; Authors: Didier Verna <didier@didierverna.net> (adding compaction)
;; Simon Josefsson <simon@josefsson.org>
@@ -830,7 +830,7 @@ article number. This function is called narrowed to an article."
(defun nnml-generate-nov-databases (&optional server)
"Generate NOV databases in all nnml directories."
(interactive (list (or (nnoo-current-server 'nnml) "")))
- ;; Read the active file to make sure we don't re-use articles
+ ;; Read the active file to make sure we don't reuse articles
;; numbers in empty groups.
(nnmail-activate 'nnml)
(unless (nnml-server-opened server)
diff --git a/lisp/gnus/nnoo.el b/lisp/gnus/nnoo.el
index 4392a464f7b..0fe70ef67b5 100644
--- a/lisp/gnus/nnoo.el
+++ b/lisp/gnus/nnoo.el
@@ -1,6 +1,6 @@
;;; nnoo.el --- OO Gnus Backends -*- lexical-binding: t; -*-
-;; Copyright (C) 1996-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-2024 Free Software Foundation, Inc.
;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
;; Keywords: news
diff --git a/lisp/gnus/nnregistry.el b/lisp/gnus/nnregistry.el
index 0702418a91a..55d77ea1fe4 100644
--- a/lisp/gnus/nnregistry.el
+++ b/lisp/gnus/nnregistry.el
@@ -1,6 +1,6 @@
;;; nnregistry.el --- access to articles via Gnus' message-id registry -*- lexical-binding: t; -*-
-;; Copyright (C) 2010-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2010-2024 Free Software Foundation, Inc.
;; Author: Ludovic Courtès <ludo@gnu.org>
;; Keywords: news, mail
diff --git a/lisp/gnus/nnrss.el b/lisp/gnus/nnrss.el
index c5f2cb672d7..fe2d0df5f3f 100644
--- a/lisp/gnus/nnrss.el
+++ b/lisp/gnus/nnrss.el
@@ -1,6 +1,6 @@
;;; nnrss.el --- interfacing with RSS -*- lexical-binding: t; -*-
-;; Copyright (C) 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2024 Free Software Foundation, Inc.
;; Author: Shenghuo Zhu <zsh@cs.rochester.edu>
;; Keywords: RSS
@@ -629,7 +629,7 @@ which RSS 2.0 allows."
(assoc 'href
(nnrss-discover-feed
(read-string
- (format "URL to search for %s: " group) "http://")))))
+ (format "URL to search for %s: " group) "https://")))))
(let ((pair (assoc-string group nnrss-server-data)))
(if pair
(setcdr (cdr pair) (list url))
diff --git a/lisp/gnus/nnselect.el b/lisp/gnus/nnselect.el
index c4fbe3a5bd2..c6a1c0a9342 100644
--- a/lisp/gnus/nnselect.el
+++ b/lisp/gnus/nnselect.el
@@ -1,6 +1,6 @@
;;; nnselect.el --- a virtual group backend -*- lexical-binding:t -*-
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
;; Author: Andrew Cohen <cohen@andy.bu.edu>
;; Keywords: news mail
diff --git a/lisp/gnus/nnspool.el b/lisp/gnus/nnspool.el
index ca97afcb7f1..ce0aea8dd57 100644
--- a/lisp/gnus/nnspool.el
+++ b/lisp/gnus/nnspool.el
@@ -1,6 +1,6 @@
;;; nnspool.el --- spool access for GNU Emacs -*- lexical-binding: t; -*-
-;; Copyright (C) 1988-1990, 1993-1998, 2000-2023 Free Software
+;; Copyright (C) 1988-1990, 1993-1998, 2000-2024 Free Software
;; Foundation, Inc.
;; Author: Masanobu UMEDA <umerin@flab.flab.fujitsu.junet>
diff --git a/lisp/gnus/nntp.el b/lisp/gnus/nntp.el
index fb9d8fa53bf..fe165662988 100644
--- a/lisp/gnus/nntp.el
+++ b/lisp/gnus/nntp.el
@@ -1,6 +1,6 @@
;;; nntp.el --- nntp access for Gnus -*- lexical-binding:t -*-
-;; Copyright (C) 1987-1990, 1992-1998, 2000-2023 Free Software
+;; Copyright (C) 1987-1990, 1992-1998, 2000-2024 Free Software
;; Foundation, Inc.
;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
diff --git a/lisp/gnus/nnvirtual.el b/lisp/gnus/nnvirtual.el
index c43abe57ee0..9eea0f89996 100644
--- a/lisp/gnus/nnvirtual.el
+++ b/lisp/gnus/nnvirtual.el
@@ -1,6 +1,6 @@
;;; nnvirtual.el --- virtual newsgroups access for Gnus -*- lexical-binding: t; -*-
-;; Copyright (C) 1994-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1994-2024 Free Software Foundation, Inc.
;; Author: David Moore <dmoore@ucsd.edu>
;; Lars Magne Ingebrigtsen <larsi@gnus.org>
diff --git a/lisp/gnus/nnweb.el b/lisp/gnus/nnweb.el
index d3bf138edeb..c8a21792662 100644
--- a/lisp/gnus/nnweb.el
+++ b/lisp/gnus/nnweb.el
@@ -1,6 +1,6 @@
;;; nnweb.el --- retrieving articles via web search engines -*- lexical-binding: t; -*-
-;; Copyright (C) 1996-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-2024 Free Software Foundation, Inc.
;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
;; Keywords: news
@@ -42,37 +42,30 @@
(defvoo nnweb-type 'google
"What search engine type is being used.
-Valid types include `google', `dejanews', and `gmane'.")
+Valid types include `google' and `dejanews'.")
(defvar nnweb-type-definition
'((google
- (id . "http://www.google.com/groups?as_umsgid=%s&hl=en&dmode=source")
- (result . "http://groups.google.com/group/%s/msg/%s?dmode=source")
+ (id . "https://www.google.com/groups?as_umsgid=%s&hl=en&dmode=source")
+ (result . "https://groups.google.com/group/%s/msg/%s?dmode=source")
(article . nnweb-google-wash-article)
(reference . identity)
(map . nnweb-google-create-mapping)
(search . nnweb-google-search)
- (address . "http://groups.google.com/groups")
- (base . "http://groups.google.com")
+ (address . "https://groups.google.com/groups")
+ (base . "https://groups.google.com")
(identifier . nnweb-google-identity))
+ ;; FIXME: Make obsolete?
(dejanews ;; alias of google
- (id . "http://www.google.com/groups?as_umsgid=%s&hl=en&dmode=source")
- (result . "http://groups.google.com/group/%s/msg/%s?dmode=source")
+ (id . "https://www.google.com/groups?as_umsgid=%s&hl=en&dmode=source")
+ (result . "https://groups.google.com/group/%s/msg/%s?dmode=source")
(article . nnweb-google-wash-article)
(reference . identity)
(map . nnweb-google-create-mapping)
(search . nnweb-google-search)
- (address . "http://groups.google.com/groups")
- (base . "http://groups.google.com")
- (identifier . nnweb-google-identity))
- (gmane
- (article . nnweb-gmane-wash-article)
- (id . "http://gmane.org/view.php?group=%s")
- (reference . identity)
- (map . nnweb-gmane-create-mapping)
- (search . nnweb-gmane-search)
- (address . "http://search.gmane.org/nov.php")
- (identifier . nnweb-gmane-identity)))
+ (address . "https://groups.google.com/groups")
+ (base . "https://groups.google.com")
+ (identifier . nnweb-google-identity)))
"Type-definition alist.")
(defvoo nnweb-search nil
@@ -254,6 +247,8 @@ Valid types include `google', `dejanews', and `gmane'.")
(defun nnweb-definition (type &optional noerror)
"Return the definition of TYPE."
+ (when (eq nnweb-type 'gmane)
+ (user-error "`gmane' is no longer a valid value for `nnweb-type'"))
(let ((def (cdr (assq type (assq nnweb-type nnweb-type-definition)))))
(when (and (not def)
(not noerror))
@@ -277,6 +272,8 @@ Valid types include `google', `dejanews', and `gmane'.")
(unless (gnus-buffer-live-p nnweb-buffer)
(setq nnweb-buffer
(save-current-buffer
+ (when (eq nnweb-type 'gmane)
+ (user-error "`gmane' is no longer a valid value for `nnweb-type'"))
(nnheader-set-temp-buffer
(format " *nnweb %s %s %s*"
nnweb-type nnweb-search server))
@@ -437,10 +434,11 @@ Valid types include `google', `dejanews', and `gmane'.")
url))
;;;
-;;; gmane.org
+;;; gmane.org -- now obsolete as the gmane.org web interface is gone
;;;
(defun nnweb-gmane-create-mapping ()
"Perform the search and create a number-to-url alist."
+ (declare (obsolete nil "30.1"))
(with-current-buffer nnweb-buffer
(let ((case-fold-search t)
(active (or (cadr (assoc nnweb-group nnweb-group-alist))
@@ -484,6 +482,7 @@ Valid types include `google', `dejanews', and `gmane'.")
(sort (nconc nnweb-articles map) #'car-less-than-car)))))
(defun nnweb-gmane-wash-article ()
+ (declare (obsolete nil "30.1"))
(let ((case-fold-search t))
(goto-char (point-min))
(when (search-forward "<!--X-Head-of-Message-->" nil t)
@@ -495,6 +494,7 @@ Valid types include `google', `dejanews', and `gmane'.")
(mm-url-remove-markup))))
(defun nnweb-gmane-search (search)
+ (declare (obsolete nil "30.1"))
(mm-url-insert
(concat
(nnweb-definition 'address)
@@ -511,6 +511,7 @@ Valid types include `google', `dejanews', and `gmane'.")
(defun nnweb-gmane-identity (url)
"Return a unique identifier based on URL."
+ (declare (obsolete nil "30.1"))
(if (string-match "group=\\(.+\\)" url)
(match-string 1 url)
url))
diff --git a/lisp/gnus/score-mode.el b/lisp/gnus/score-mode.el
index e2c89ef8964..6906872c75d 100644
--- a/lisp/gnus/score-mode.el
+++ b/lisp/gnus/score-mode.el
@@ -1,6 +1,6 @@
;;; score-mode.el --- mode for editing Gnus score files -*- lexical-binding: t; -*-
-;; Copyright (C) 1996, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996, 2001-2024 Free Software Foundation, Inc.
;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
;; Keywords: news, mail
diff --git a/lisp/gnus/smiley.el b/lisp/gnus/smiley.el
index 3c17f9bf511..c39a5806951 100644
--- a/lisp/gnus/smiley.el
+++ b/lisp/gnus/smiley.el
@@ -1,6 +1,6 @@
;;; smiley.el --- displaying smiley faces -*- lexical-binding: t; -*-
-;; Copyright (C) 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2000-2024 Free Software Foundation, Inc.
;; Author: Dave Love <fx@gnu.org>
;; Keywords: news mail multimedia
diff --git a/lisp/gnus/smime.el b/lisp/gnus/smime.el
index ddebfec078a..b61579912dd 100644
--- a/lisp/gnus/smime.el
+++ b/lisp/gnus/smime.el
@@ -1,6 +1,6 @@
;;; smime.el --- S/MIME support library -*- lexical-binding:t -*-
-;; Copyright (C) 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2000-2024 Free Software Foundation, Inc.
;; Author: Simon Josefsson <simon@josefsson.org>
;; Keywords: SMIME X.509 PEM OpenSSL
diff --git a/lisp/gnus/spam-report.el b/lisp/gnus/spam-report.el
index 7e0392797f9..c0158c2e795 100644
--- a/lisp/gnus/spam-report.el
+++ b/lisp/gnus/spam-report.el
@@ -1,6 +1,6 @@
;;; spam-report.el --- Reporting spam -*- lexical-binding: t; -*-
-;; Copyright (C) 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2024 Free Software Foundation, Inc.
;; Author: Ted Zlatanov <tzz@lifelogs.com>
;; Keywords: network, spam, mail, gmane, report
@@ -49,7 +49,7 @@ instead."
"Whether the article number (faster!) or the header should be used.
You must set this to nil if you don't read Gmane groups directly
-from news.gmane.org, e.g. when using local newsserver such as
+from news.gmane.io, e.g. when using local newsserver such as
leafnode."
:type 'boolean)
@@ -64,7 +64,7 @@ The function must accept the arguments `host' and `report'."
spam-report-url-ping-mm-url)
(const :tag "Store request URLs in `spam-report-requests-file'"
spam-report-url-to-file)
- (function :tag "User defined function" nil)))
+ (function :tag "User defined function")))
(defcustom spam-report-requests-file
(nnheader-concat gnus-directory "spam/" "spam-report-requests.url")
@@ -149,6 +149,8 @@ submitted at once. Internal variable.")
(when (and gnus-newsgroup-name
(or (null spam-report-gmane-regex)
(string-match spam-report-gmane-regex gnus-newsgroup-name)))
+ ;; FIXME: These addresses are down. There is also no
+ ;; unspam.gmane.io or spam.gmane.io.
(let ((rpt-host (if unspam "unspam.gmane.org" "spam.gmane.org")))
(gnus-message 6 "Reporting article %d to %s..." article rpt-host)
(cond
diff --git a/lisp/gnus/spam-stat.el b/lisp/gnus/spam-stat.el
index ee6da6ecb44..f4ad9e48f6f 100644
--- a/lisp/gnus/spam-stat.el
+++ b/lisp/gnus/spam-stat.el
@@ -1,6 +1,6 @@
;;; spam-stat.el --- detecting spam based on statistics -*- lexical-binding: t; -*-
-;; Copyright (C) 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2024 Free Software Foundation, Inc.
;; Author: Alex Schroeder <alex@gnu.org>
;; Keywords: network
diff --git a/lisp/gnus/spam-wash.el b/lisp/gnus/spam-wash.el
index 685cb7e92d0..94feaa27796 100644
--- a/lisp/gnus/spam-wash.el
+++ b/lisp/gnus/spam-wash.el
@@ -1,6 +1,6 @@
;;; spam-wash.el --- wash spam before analysis -*- lexical-binding: t; -*-
-;; Copyright (C) 2004, 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2004, 2007-2024 Free Software Foundation, Inc.
;; Author: Andrew Cohen <cohen@andy.bu.edu>
;; Keywords: mail
diff --git a/lisp/gnus/spam.el b/lisp/gnus/spam.el
index 3178d9f59e6..1ae214ea4fa 100644
--- a/lisp/gnus/spam.el
+++ b/lisp/gnus/spam.el
@@ -1,6 +1,6 @@
;;; spam.el --- Identifying spam -*- lexical-binding: t; -*-
-;; Copyright (C) 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2024 Free Software Foundation, Inc.
;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
;; Maintainer: Ted Zlatanov <tzz@lifelogs.com>
@@ -1375,8 +1375,7 @@ In the case of mover backends, checks the setting of
(when (and (car-safe groups) (listp (car-safe groups)))
(setq groups (pop groups)))
- (unless (listp groups)
- (setq groups (list groups)))
+ (setq groups (ensure-list groups))
;; remove the current process mark
(gnus-summary-kill-process-mark)
diff --git a/lisp/help-at-pt.el b/lisp/help-at-pt.el
index 6c18a85ddfd..95d0fafc544 100644
--- a/lisp/help-at-pt.el
+++ b/lisp/help-at-pt.el
@@ -1,6 +1,6 @@
;;; help-at-pt.el --- local help through the keyboard -*- lexical-binding: t -*-
-;; Copyright (C) 2003-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003-2024 Free Software Foundation, Inc.
;; Author: Luc Teirlinck <teirllm@auburn.edu>
;; Keywords: help
diff --git a/lisp/help-fns.el b/lisp/help-fns.el
index 22cfbbc39cd..ca21408f6c3 100644
--- a/lisp/help-fns.el
+++ b/lisp/help-fns.el
@@ -1,6 +1,6 @@
;;; help-fns.el --- Complex help functions -*- lexical-binding: t -*-
-;; Copyright (C) 1985-1986, 1993-1994, 1998-2023 Free Software
+;; Copyright (C) 1985-1986, 1993-1994, 1998-2024 Free Software
;; Foundation, Inc.
;; Maintainer: emacs-devel@gnu.org
@@ -369,7 +369,8 @@ if the variable `help-downcase-arguments' is non-nil."
(setq doc (replace-regexp-in-string
;; This is heuristic, but covers all common cases
;; except ARG1-ARG2
- (concat "\\<" ; beginning of word
+ (concat "([^ ]+ .*" ; skip function name
+ "\\<" ; beginning of word
"\\(?:[a-z-]*-\\)?" ; for xxx-ARG
"\\("
(regexp-quote arg)
@@ -741,6 +742,7 @@ the C sources, too."
(defun help-fns--parent-mode (function)
;; If this is a derived mode, link to the parent.
(let ((parent-mode (and (symbolp function)
+ ;; FIXME: Should we mention other parent modes?
(get function
'derived-mode-parent))))
(when parent-mode
@@ -766,7 +768,7 @@ the C sources, too."
" is obsolete")
(when (nth 2 obsolete)
(insert (format " since %s" (nth 2 obsolete))))
- (insert (cond ((stringp use) (concat "; " use))
+ (insert (cond ((stringp use) (concat "; " (substitute-quotes use)))
(use (format-message "; use `%s' instead." use))
(t "."))
"\n")
@@ -1749,8 +1751,7 @@ If FRAME is omitted or nil, use the selected frame."
(called-interactively-p 'interactive))
(unless face
(setq face 'default))
- (if (not (listp face))
- (setq face (list face)))
+ (setq face (ensure-list face))
(with-help-window (help-buffer)
(with-current-buffer standard-output
(dolist (f face (buffer-string))
@@ -2239,7 +2240,7 @@ documentation for the major and minor modes of that buffer."
(not (get sym 'byte-obsolete-info))
;; Ignore everything bound.
(not (where-is-internal sym nil t))
- (apply #'derived-mode-p (command-modes sym)))
+ (derived-mode-p (command-modes sym)))
(push sym functions))))
(with-temp-buffer
(when functions
diff --git a/lisp/help-macro.el b/lisp/help-macro.el
index fac3419f184..cea8b379ec0 100644
--- a/lisp/help-macro.el
+++ b/lisp/help-macro.el
@@ -1,6 +1,6 @@
;;; help-macro.el --- makes command line help such as help-for-help -*- lexical-binding: t -*-
-;; Copyright (C) 1993-1994, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1993-1994, 2001-2024 Free Software Foundation, Inc.
;; Author: Lynn Slater <lrs@indetech.com>
;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/help-mode.el b/lisp/help-mode.el
index b51276d5e06..9c405efeee5 100644
--- a/lisp/help-mode.el
+++ b/lisp/help-mode.el
@@ -1,6 +1,6 @@
;;; help-mode.el --- `help-mode' used by *Help* buffers -*- lexical-binding: t; -*-
-;; Copyright (C) 1985-1986, 1993-1994, 1998-2023 Free Software
+;; Copyright (C) 1985-1986, 1993-1994, 1998-2024 Free Software
;; Foundation, Inc.
;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/help.el b/lisp/help.el
index f522cfac2a1..a551dba5fe5 100644
--- a/lisp/help.el
+++ b/lisp/help.el
@@ -1,6 +1,6 @@
;;; help.el --- help commands for Emacs -*- lexical-binding:t -*-
-;; Copyright (C) 1985-1986, 1993-1994, 1998-2023 Free Software
+;; Copyright (C) 1985-1986, 1993-1994, 1998-2024 Free Software
;; Foundation, Inc.
;; Maintainer: emacs-devel@gnu.org
@@ -192,7 +192,7 @@ buffer.")
max-key-len (max (length key) max-key-len))
(push (list key (cdr ent) (car ent)) keys))))
(when keys
- (let ((fmt (format "%%-%ds %%-%ds%s" max-key-len max-cmd-len
+ (let ((fmt (format "%%s %%-%ds%s" max-cmd-len
(make-string padding ?\s)))
(width (+ max-key-len 1 max-cmd-len padding)))
(push `(,width
@@ -203,10 +203,12 @@ buffer.")
'face 'bold)
,@(mapcar (lambda (ent)
(format fmt
- (propertize
- (car ent)
- 'quick-help-cmd
- (caddr ent))
+ (concat
+ (propertize
+ (car ent)
+ 'quick-help-cmd
+ (caddr ent))
+ (make-string (- max-key-len (length (car ent))) ?\s))
(cadr ent)))
keys))
blocks)))))
@@ -1230,15 +1232,60 @@ appeared on the mode-line."
i))))
minor-mode-alist)))
-(defun describe-minor-mode-from-indicator (indicator)
+(defun describe-minor-mode-from-indicator (indicator &optional event)
"Display documentation of a minor mode specified by INDICATOR.
If you call this function interactively, you can give indicator which
-is currently activated with completion."
+is currently activated with completion.
+
+If non-nil, EVENT is a mouse event used to establish which minor
+mode lighter was clicked."
(interactive (list
(completing-read
"Minor mode indicator: "
(describe-minor-mode-completion-table-for-indicator))))
- (let ((minor-mode (lookup-minor-mode-from-indicator indicator)))
+ (when (and event mode-line-compact)
+ (let* ((event-start (event-start event))
+ (window (posn-window event-start)))
+ ;; If INDICATOR is a string object, WINDOW is set, and
+ ;; `mode-line-compact' might be enabled, find a string in
+ ;; `minor-mode-alist' that is present within the INDICATOR and
+ ;; whose extents within INDICATOR contain the position of the
+ ;; object within the string.
+ (when (windowp window)
+ (setq indicator (posn-object event-start))
+ (catch 'found
+ (with-selected-window window
+ (let ((alist minor-mode-alist) string position)
+ (when (consp indicator)
+ (with-temp-buffer
+ (insert (car indicator))
+ (dolist (menu alist)
+ ;; If this is a valid minor mode menu entry,
+ (when (and (consp menu)
+ (setq string (format-mode-line (cadr menu)
+ nil window))
+ (> (length string) 0))
+ ;; Start searching for an appearance of (cdr
+ ;; menu).
+ (goto-char (point-min))
+ (while (search-forward string nil 0)
+ ;; If the position of the string object is
+ ;; contained within, set indicator to the
+ ;; minor mode in question.
+ (setq position (1+ (cdr indicator)))
+ (and (>= position (match-beginning 0))
+ (<= position (match-end 0))
+ (setq indicator (car menu))
+ (throw 'found nil)))))))))))))
+ ;; If INDICATOR is still a cons, use its car.
+ (when (consp indicator)
+ (setq indicator (car indicator)))
+ (let ((minor-mode (if (symbolp indicator)
+ ;; indicator being set to a symbol means that
+ ;; the loop above has already found a
+ ;; matching minor mode.
+ indicator
+ (lookup-minor-mode-from-indicator indicator))))
(if minor-mode
(describe-minor-mode-from-symbol minor-mode)
(error "Cannot find minor mode for `%s'" indicator))))
@@ -1423,7 +1470,7 @@ Otherwise, return a new string."
;; in case it is a local variable.
(with-current-buffer orig-buf
;; This is for computing the SHADOWS arg for
- ;; describe-map-tree.
+ ;; help--describe-map-tree.
(setq active-maps (current-active-maps))
(when (boundp name)
(setq this-keymap (and (keymapp (symbol-value name))
@@ -1444,9 +1491,10 @@ Otherwise, return a new string."
;; If this one's not active, get nil.
(let ((earlier-maps
(cdr (memq this-keymap (reverse active-maps)))))
- (describe-map-tree this-keymap t (nreverse earlier-maps)
- nil nil (not include-menus)
- nil nil t))))))))
+ (help--describe-map-tree this-keymap t
+ (nreverse earlier-maps)
+ nil nil (not include-menus)
+ nil nil t))))))))
;; 2. Handle quotes.
((and (eq (text-quoting-style) 'curve)
(or (and (= (following-char) ?\`)
@@ -1463,10 +1511,11 @@ Otherwise, return a new string."
(buffer-string)))))
(defun substitute-quotes (string)
- "Substitute quote characters for display.
+ "Substitute quote characters in STRING for display.
Each grave accent \\=` is replaced by left quote, and each
-apostrophe \\=' is replaced by right quote. Left and right quote
-characters are specified by `text-quoting-style'."
+apostrophe \\=' is replaced by right quote. Which left and right
+quote characters to use is determined by the variable
+`text-quoting-style'."
(cond ((eq (text-quoting-style) 'curve)
(string-replace "`" "‘"
(string-replace "'" "’" string)))
@@ -1475,9 +1524,9 @@ characters are specified by `text-quoting-style'."
(t string)))
(defvar help--keymaps-seen nil)
-(defun describe-map-tree (startmap &optional partial shadow prefix title
- no-menu transl always-title mention-shadow
- buffer)
+(defun help--describe-map-tree (startmap &optional partial shadow prefix title
+ no-menu transl always-title mention-shadow
+ buffer)
"Insert a description of the key bindings in STARTMAP.
This is followed by the key bindings of all maps reachable
through STARTMAP.
@@ -1631,7 +1680,7 @@ Assume that this keymap itself is reached by the sequence of
prefix keys PREFIX (a string or vector).
TRANSL, PARTIAL, SHADOW, NOMENU, MENTION-SHADOW and BUFFER are as
-in `describe-map-tree'."
+in `help--describe-map-tree'."
;; Converted from describe_map in keymap.c.
(let* ((map (keymap-canonicalize map))
(tail map)
@@ -2406,6 +2455,7 @@ the suggested string to use instead. See
#'help-command-error-confusable-suggestions))
(define-obsolete-function-alias 'help-for-help-internal #'help-for-help "28.1")
+(define-obsolete-function-alias 'describe-map-tree #'help--describe-map-tree "30.1")
(provide 'help)
diff --git a/lisp/hex-util.el b/lisp/hex-util.el
index 9b40c1d2799..9a9564c7095 100644
--- a/lisp/hex-util.el
+++ b/lisp/hex-util.el
@@ -1,6 +1,6 @@
;;; hex-util.el --- Functions to encode/decode hexadecimal string -*- lexical-binding: t -*-
-;; Copyright (C) 1999, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999, 2001-2024 Free Software Foundation, Inc.
;; Author: Shuhei KOBAYASHI <shuhei@aqua.ocn.ne.jp>
;; Keywords: data
diff --git a/lisp/hexl.el b/lisp/hexl.el
index 5fa09459a46..1288cf4d7fb 100644
--- a/lisp/hexl.el
+++ b/lisp/hexl.el
@@ -1,6 +1,6 @@
;;; hexl.el --- edit a file in a hex dump format using the hexl filter -*- lexical-binding: t -*-
-;; Copyright (C) 1989, 1994, 1998, 2001-2023 Free Software Foundation,
+;; Copyright (C) 1989, 1994, 1998, 2001-2024 Free Software Foundation,
;; Inc.
;; Author: Keith Gabryelski <ag@wheaties.ai.mit.edu>
diff --git a/lisp/hfy-cmap.el b/lisp/hfy-cmap.el
index 95f82a1f68c..ee8eac6732a 100644
--- a/lisp/hfy-cmap.el
+++ b/lisp/hfy-cmap.el
@@ -1,6 +1,6 @@
;;; hfy-cmap.el --- Fallback color name -> rgb mapping for `htmlfontify' -*- lexical-binding:t -*-
-;; Copyright (C) 2002-2003, 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2003, 2009-2024 Free Software Foundation, Inc.
;; Emacs Lisp Archive Entry
;; Package: htmlfontify
diff --git a/lisp/hi-lock.el b/lisp/hi-lock.el
index 5c536b190fb..516bee67dd0 100644
--- a/lisp/hi-lock.el
+++ b/lisp/hi-lock.el
@@ -1,6 +1,6 @@
;;; hi-lock.el --- minor mode for interactive automatic highlighting -*- lexical-binding: t -*-
-;; Copyright (C) 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2000-2024 Free Software Foundation, Inc.
;; Author: David M. Koppelman <koppel@ece.lsu.edu>
;; Keywords: faces, minor-mode, matching, display
diff --git a/lisp/hilit-chg.el b/lisp/hilit-chg.el
index d5899175616..41bd4026b8e 100644
--- a/lisp/hilit-chg.el
+++ b/lisp/hilit-chg.el
@@ -1,6 +1,6 @@
;;; hilit-chg.el --- minor mode displaying buffer changes with special face -*- lexical-binding: t -*-
-;; Copyright (C) 1998, 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998, 2000-2024 Free Software Foundation, Inc.
;; Author: Richard Sharman <rsharman@pobox.com>
;; Keywords: faces
diff --git a/lisp/hippie-exp.el b/lisp/hippie-exp.el
index 573366dd0a1..298634c2b7e 100644
--- a/lisp/hippie-exp.el
+++ b/lisp/hippie-exp.el
@@ -1,6 +1,6 @@
;;; hippie-exp.el --- expand text trying various ways to find its expansion -*- lexical-binding: t; -*-
-;; Copyright (C) 1992, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1992, 2001-2024 Free Software Foundation, Inc.
;; Author: Anders Holst <aho@sans.kth.se>
;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/hl-line.el b/lisp/hl-line.el
index 11631418c76..2826477c7ca 100644
--- a/lisp/hl-line.el
+++ b/lisp/hl-line.el
@@ -1,6 +1,6 @@
;;; hl-line.el --- highlight the current line -*- lexical-binding:t -*-
-;; Copyright (C) 1998, 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998, 2000-2024 Free Software Foundation, Inc.
;; Author: Dave Love <fx@gnu.org>
;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/htmlfontify.el b/lisp/htmlfontify.el
index 6c303226e54..6b9c623f31f 100644
--- a/lisp/htmlfontify.el
+++ b/lisp/htmlfontify.el
@@ -1,6 +1,6 @@
;;; htmlfontify.el --- htmlize a buffer/source tree with optional hyperlinks -*- lexical-binding: t -*-
-;; Copyright (C) 2002-2003, 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2003, 2009-2024 Free Software Foundation, Inc.
;; Emacs Lisp Archive Entry
;; Package: htmlfontify
diff --git a/lisp/ibuf-ext.el b/lisp/ibuf-ext.el
index 37065f5d41a..95ff014aa5b 100644
--- a/lisp/ibuf-ext.el
+++ b/lisp/ibuf-ext.el
@@ -1,6 +1,6 @@
;;; ibuf-ext.el --- extensions for ibuffer -*- lexical-binding:t -*-
-;; Copyright (C) 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2000-2024 Free Software Foundation, Inc.
;; Author: Colin Walters <walters@verbum.org>
;; Maintainer: John Paul Wallington <jpw@gnu.org>
@@ -400,9 +400,9 @@ format. See `ibuffer-update-saved-filters-format' and
(error "This buffer is not in Ibuffer mode"))
(cond (ibuffer-auto-mode
(frame-or-buffer-changed-p 'ibuffer-auto-buffers-changed) ; Initialize state vector
- (add-hook 'post-command-hook 'ibuffer-auto-update-changed))
+ (add-hook 'post-command-hook #'ibuffer-auto-update-changed))
(t
- (remove-hook 'post-command-hook 'ibuffer-auto-update-changed))))
+ (remove-hook 'post-command-hook #'ibuffer-auto-update-changed))))
(defun ibuffer-auto-update-changed ()
(when (frame-or-buffer-changed-p 'ibuffer-auto-buffers-changed)
@@ -557,7 +557,7 @@ See `ibuffer-do-view-and-eval' for that."
(list (read--expression "Eval in buffers (form): "))
:opstring "evaluated in"
:modifier-p :maybe)
- (eval form))
+ (eval form t))
;;;###autoload (autoload 'ibuffer-do-view-and-eval "ibuf-ext")
(define-ibuffer-op view-and-eval (form)
@@ -575,7 +575,7 @@ To evaluate a form without viewing the buffer, see `ibuffer-do-eval'."
(unwind-protect
(progn
(switch-to-buffer buf)
- (eval form))
+ (eval form t))
(switch-to-buffer ibuffer-buf))))
;;;###autoload (autoload 'ibuffer-do-rename-uniquely "ibuf-ext")
@@ -1185,10 +1185,12 @@ Interactively, prompt for NAME, and use the current filters."
(concat " [filter: " (cdr qualifier) "]"))
('or
(concat " [OR" (mapconcat #'ibuffer-format-qualifier
- (cdr qualifier) "") "]"))
+ (cdr qualifier))
+ "]"))
('and
(concat " [AND" (mapconcat #'ibuffer-format-qualifier
- (cdr qualifier) "") "]"))
+ (cdr qualifier))
+ "]"))
(_
(let ((type (assq (car qualifier) ibuffer-filtering-alist)))
(unless qualifier
@@ -1202,11 +1204,12 @@ Interactively, prompt for NAME, and use the current filters."
If INCLUDE-PARENTS is non-nil then include parent modes."
(let ((modes))
(dolist (buf (buffer-list))
- (let ((this-mode (buffer-local-value 'major-mode buf)))
- (while (and this-mode (not (memq this-mode modes)))
- (push this-mode modes)
- (setq this-mode (and include-parents
- (get this-mode 'derived-mode-parent))))))
+ (let ((this-modes (derived-mode-all-parents
+ (buffer-local-value 'major-mode buf))))
+ (while (and this-modes (not (memq (car this-modes) modes)))
+ (push (car this-modes) modes)
+ (setq this-modes (and include-parents
+ (cdr this-modes))))))
(mapcar #'symbol-name modes)))
@@ -1391,7 +1394,7 @@ matches against the value of `default-directory' in that buffer."
(:description "predicate"
:reader (read-minibuffer "Filter by predicate (form): "))
(with-current-buffer buf
- (eval qualifier)))
+ (eval qualifier t)))
;;;###autoload (autoload 'ibuffer-filter-chosen-by-completion "ibuf-ext")
(defun ibuffer-filter-chosen-by-completion ()
@@ -1508,7 +1511,7 @@ Ordering is lexicographic."
"Emulate `bs-show' from the bs.el package."
(interactive)
(ibuffer t "*Ibuffer-bs*" '((filename . ".*")) nil t)
- (define-key (current-local-map) "a" 'ibuffer-bs-toggle-all))
+ (define-key (current-local-map) "a" #'ibuffer-bs-toggle-all))
(defun ibuffer-bs-toggle-all ()
"Emulate `bs-toggle-show-all' from the bs.el package."
@@ -1746,7 +1749,7 @@ You can then feed the file name(s) to other commands with \\[yank]."
(t (file-name-nondirectory name))))))
buffers))
(string
- (mapconcat 'identity (delete "" file-names) " ")))
+ (mapconcat #'identity (delete "" file-names) " ")))
(unless (string= string "")
(if (eq last-command 'kill-region)
(kill-append string nil)
diff --git a/lisp/ibuf-macs.el b/lisp/ibuf-macs.el
index 2c9e9ea8bcd..1fd94967836 100644
--- a/lisp/ibuf-macs.el
+++ b/lisp/ibuf-macs.el
@@ -1,6 +1,6 @@
;;; ibuf-macs.el --- macros for ibuffer -*- lexical-binding:t -*-
-;; Copyright (C) 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2000-2024 Free Software Foundation, Inc.
;; Author: Colin Walters <walters@verbum.org>
;; Maintainer: John Paul Wallington <jpw@gnu.org>
@@ -230,6 +230,9 @@ buffer object.
(_
'ibuffer-marked-buffer-names)))))
(when (null marked-names)
+ (cl-assert (get-text-property (line-beginning-position)
+ 'ibuffer-properties)
+ nil "No buffer on this line")
(setq marked-names (list (buffer-name (ibuffer-current-buffer))))
(ibuffer-set-mark ,(pcase mark
(:deletion
@@ -243,7 +246,9 @@ buffer object.
())
(and after `(,after)) ; post-operation form.
`((ibuffer-redisplay t)
- (message ,(concat "Operation finished; " opstring " %s buffers") count))))
+ (message ,(concat "Operation finished; " opstring
+ " %s %s")
+ count (ngettext "buffer" "buffers" count)))))
(inner-body (if complex
`(progn ,@body)
`(progn
@@ -310,7 +315,7 @@ bound to the current value of the filter.
(,qualifier-str qualifier))
,(when accept-list
`(progn
- (unless (listp qualifier) (setq qualifier (list qualifier)))
+ (setq qualifier (ensure-list qualifier))
;; Reject equivalent filters: (or f1 f2) is same as (or f2 f1).
(setq qualifier (sort (delete-dups qualifier) #'string-lessp))
(setq ,filter (cons ',name (car qualifier)))
diff --git a/lisp/ibuffer.el b/lisp/ibuffer.el
index a26bb1811ec..602f06338e2 100644
--- a/lisp/ibuffer.el
+++ b/lisp/ibuffer.el
@@ -1,6 +1,6 @@
;;; ibuffer.el --- operate on buffers like dired -*- lexical-binding:t -*-
-;; Copyright (C) 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2000-2024 Free Software Foundation, Inc.
;; Author: Colin Walters <walters@verbum.org>
;; Maintainer: John Paul Wallington <jpw@gnu.org>
@@ -1872,7 +1872,8 @@ the buffer object itself and the current mark symbol."
(let ((result
(if (buffer-live-p (ibuffer-current-buffer))
(when (or (null group)
- (when-let ((it (get-text-property (point) 'ibuffer-filter-group)))
+ (when-let ((it (get-text-property
+ (point) 'ibuffer-filter-group)))
(equal group it)))
(save-excursion
(funcall function
@@ -1897,7 +1898,19 @@ the buffer object itself and the current mark symbol."
(t
(cl-incf ibuffer-map-lines-count)
(forward-line 1)))))
- ibuffer-map-lines-count)
+ ;; With `ibuffer-auto-mode' enabled, `ibuffer-expert' nil
+ ;; and more than one marked buffer lines, the preceding loop
+ ;; counts the automatically popped up (and hence not
+ ;; user-marked) buffer "*Ibuffer confirmation*". Since
+ ;; Ibuffer reports how many marked buffers lines were acted
+ ;; upon, and in this case the reported count would be too
+ ;; high by one, we decrement the count to avoid the
+ ;; confusing message (see bug#64230).
+ (if (and (featurep 'ibuf-ext) ibuffer-auto-mode
+ (> ibuffer-map-lines-count 1)
+ (not ibuffer-expert))
+ (1- ibuffer-map-lines-count)
+ ibuffer-map-lines-count))
(progn
(setq buffer-read-only t)
(unless nomodify
diff --git a/lisp/icomplete.el b/lisp/icomplete.el
index e6fdd1f1836..d49714f3204 100644
--- a/lisp/icomplete.el
+++ b/lisp/icomplete.el
@@ -1,6 +1,6 @@
;;; icomplete.el --- minibuffer completion incremental feedback -*- lexical-binding: t -*-
-;; Copyright (C) 1992-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1992-2024 Free Software Foundation, Inc.
;; Author: Ken Manheimer <ken dot manheimer at gmail...>
;; Created: Mar 1993 Ken Manheimer, klm@nist.gov - first release to usenet
@@ -722,7 +722,8 @@ See `icomplete-mode' and `minibuffer-setup-hook'."
;; Check if still in the right buffer (bug#61308)
(or (window-minibuffer-p) completion-in-region--data)
(icomplete-simple-completing-p)) ;Shouldn't be necessary.
- (let ((saved-point (point)))
+ (let ((saved-point (point))
+ (completion-lazy-hilit t))
(save-excursion
(goto-char (icomplete--field-end))
;; Insert the match-status information:
@@ -901,7 +902,7 @@ by `group-function''s second \"transformation\" protocol."
'icomplete-selected-match 'append comp)
collect (concat prefix
(make-string (- max-prefix-len (length prefix)) ? )
- comp
+ (completion-lazy-hilit comp)
(make-string (- max-comp-len (length comp)) ? )
suffix)
into lines-aux
@@ -1067,7 +1068,8 @@ matches exist."
(if (< prospects-len prospects-max)
(push comp prospects)
(setq limit t)))
- (setq prospects (nreverse prospects))
+ (setq prospects
+ (nreverse (mapcar #'completion-lazy-hilit prospects)))
;; Decorate first of the prospects.
(when prospects
(let ((first (copy-sequence (pop prospects))))
diff --git a/lisp/ido.el b/lisp/ido.el
index 00a2e57f7ba..6e51dc67196 100644
--- a/lisp/ido.el
+++ b/lisp/ido.el
@@ -1,6 +1,6 @@
;;; ido.el --- interactively do things with buffers and files -*- lexical-binding: t -*-
-;; Copyright (C) 1996-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-2024 Free Software Foundation, Inc.
;; Author: Kim F. Storm <storm@cua.dk>
;; Based on: iswitchb by Stephen Eglen <stephen@cns.ed.ac.uk>
@@ -864,7 +864,8 @@ also modify the dynamic variables described for the variable
(defcustom ido-completion-buffer "*Ido Completions*"
"Name of completion buffer used by Ido.
Set to nil to disable completion buffers popping up."
- :type 'string)
+ :type '(choice (const :tag "Disable popping up completion buffer" nil)
+ string))
(defcustom ido-completion-buffer-all-completions nil
"Non-nil means to show all completions in completion buffer.
@@ -1508,8 +1509,8 @@ Removes badly formatted data and ignored directories."
(add-hook 'minibuffer-setup-hook #'ido-minibuffer-setup)
(add-hook 'choose-completion-string-functions #'ido-choose-completion-string))
-(defun ido--ffap-find-file (file)
- (find-file file))
+(defun ido--ffap-find-file (file &optional wildcard)
+ (find-file file wildcard))
(define-minor-mode ido-everywhere
"Toggle use of Ido for all buffer/file reading."
@@ -2325,7 +2326,7 @@ If cursor is not at the end of the user input, move to end of input."
(if (eq ido-use-filename-at-point 'guess)
(ffap-guesser)
(ffap-string-at-point))))
- (not (string-match "\\`http:/" fn)))
+ (not (string-match (rx bos "http" (? "s") ":/") fn)))
(let ((absolute-fn (expand-file-name fn)))
(cond
((file-directory-p absolute-fn)
diff --git a/lisp/ielm.el b/lisp/ielm.el
index f7d025b8c01..777aebb70cf 100644
--- a/lisp/ielm.el
+++ b/lisp/ielm.el
@@ -1,6 +1,6 @@
;;; ielm.el --- interaction mode for Emacs Lisp -*- lexical-binding: t -*-
-;; Copyright (C) 1994, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1994, 2001-2024 Free Software Foundation, Inc.
;; Author: David Smith <maa036@lancaster.ac.uk>
;; Maintainer: emacs-devel@gnu.org
@@ -491,8 +491,7 @@ addition to `comint-indirect-setup-hook', run this hook with the
indirect buffer as the current buffer after its setup is done.
This can be used to further customize fontification and other
behavior of the indirect buffer."
- :type 'boolean
- :safe 'booleanp
+ :type 'hook
:version "29.1")
(defun ielm-indirect-setup-hook ()
diff --git a/lisp/iimage.el b/lisp/iimage.el
index b4c175a7b63..205141577c9 100644
--- a/lisp/iimage.el
+++ b/lisp/iimage.el
@@ -1,6 +1,6 @@
;;; iimage.el --- Inline image minor mode. -*- lexical-binding: t -*-
-;; Copyright (C) 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2004-2024 Free Software Foundation, Inc.
;; Author: KOSEKI Yoshinori <kose@meadowy.org>
;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/image-file.el b/lisp/image-file.el
index a28da2f05ba..57e9799dc34 100644
--- a/lisp/image-file.el
+++ b/lisp/image-file.el
@@ -1,6 +1,6 @@
;;; image-file.el --- support for visiting image files -*- lexical-binding:t -*-
;;
-;; Copyright (C) 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2000-2024 Free Software Foundation, Inc.
;;
;; Author: Miles Bader <miles@gnu.org>
;; Keywords: multimedia
diff --git a/lisp/image-mode.el b/lisp/image-mode.el
index 713125d4e58..355685e70fd 100644
--- a/lisp/image-mode.el
+++ b/lisp/image-mode.el
@@ -1,6 +1,6 @@
;;; image-mode.el --- support for visiting image files -*- lexical-binding: t -*-
;;
-;; Copyright (C) 2005-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2005-2024 Free Software Foundation, Inc.
;;
;; Author: Richard Stallman <rms@gnu.org>
;; Keywords: multimedia
@@ -69,8 +69,8 @@ Its value should be one of the following:
Resizing will always preserve the aspect ratio of the image."
:type '(choice (const :tag "No resizing" nil)
(const :tag "Fit to window" fit-window)
- (other :tag "Scale down to fit window" t)
- (number :tag "Scale factor" 1))
+ (number :tag "Scale factor" 1)
+ (other :tag "Scale down to fit window" t))
:version "29.1"
:group 'image)
@@ -89,7 +89,7 @@ This will always keep the image fit to the window.
When non-nil, the value should be a number of seconds to wait before
resizing according to the value specified in `image-auto-resize'."
:type '(choice (const :tag "No auto-resize on window size change" nil)
- (integer :tag "Wait for number of seconds before resize" 1))
+ (number :tag "Wait for number of seconds before resize" 1))
:version "27.1"
:group 'image)
@@ -772,9 +772,8 @@ to switch back to
;;;###autoload
(defun image-mode-to-text ()
- "Set a non-image mode as major mode in combination with image minor mode.
-A non-mage major mode found from `auto-mode-alist' or fundamental mode
-displays an image file as text."
+ "Set current buffer's modes be a non-image major mode, plus `image-minor-mode'.
+A non-image major mode displays an image file as text."
;; image-mode-as-text = normal-mode + image-minor-mode
(let ((previous-image-type image-type)) ; preserve `image-type'
(major-mode-restore '(image-mode image-mode-as-text))
@@ -785,15 +784,14 @@ displays an image file as text."
(image-toggle-display-text))))
(defun image-mode-as-hex ()
- "Set `hexl-mode' as major mode in combination with image minor mode.
-A non-mage major mode found from `auto-mode-alist' or fundamental mode
-displays an image file as hex. `image-minor-mode' provides the key
-\\<image-mode-map>\\[image-toggle-hex-display] to switch back to `image-mode' \
-to display an image file as
-the actual image.
+ "Set current buffer's modes be `hexl-mode' major mode, plus `image-minor-mode'.
+This will by default display an image file as hex. `image-minor-mode'
+provides the key sequence \\<image-mode-map>\\[image-toggle-hex-display] to \
+switch back to `image-mode' to display
+an image file's buffer as an image.
You can use `image-mode-as-hex' in `auto-mode-alist' when you want to
-display an image file as hex initially.
+display image files as hex by default.
See commands `image-mode' and `image-minor-mode' for more information
on these modes."
diff --git a/lisp/image.el b/lisp/image.el
index 08190cf86bc..73801f88d1e 100644
--- a/lisp/image.el
+++ b/lisp/image.el
@@ -1,6 +1,6 @@
;;; image.el --- image API -*- lexical-binding:t -*-
-;; Copyright (C) 1998-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-2024 Free Software Foundation, Inc.
;; Maintainer: emacs-devel@gnu.org
;; Keywords: multimedia
@@ -38,7 +38,7 @@
(defconst image-type-header-regexps
`(("\\`/[\t\n\r ]*\\*.*XPM.\\*/" . xpm)
("\\`P[1-6]\\(?:\
-\\(?:\\(?:#[^\r\n]*[\r\n]\\)*[[:space:]]\\)+\
+\\(?:\\(?:#[^\r\n]*[\r\n]\\)*[ \t\r\n]\\)+\
\\(?:\\(?:#[^\r\n]*[\r\n]\\)*[0-9]\\)+\
\\)\\{2\\}" . pbm)
("\\`GIF8[79]a" . gif)
diff --git a/lisp/image/compface.el b/lisp/image/compface.el
index 25204147906..9fb139ad830 100644
--- a/lisp/image/compface.el
+++ b/lisp/image/compface.el
@@ -1,6 +1,6 @@
;;; compface.el --- functions for converting X-Face headers -*- lexical-binding: t -*-
-;; Copyright (C) 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2024 Free Software Foundation, Inc.
;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
;; Keywords: multimedia, news
diff --git a/lisp/image/exif.el b/lisp/image/exif.el
index 4807df0fbbb..2c1c4850bef 100644
--- a/lisp/image/exif.el
+++ b/lisp/image/exif.el
@@ -1,6 +1,6 @@
;;; exif.el --- parsing Exif data in JPEG images -*- lexical-binding: t -*-
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
;; Keywords: images
diff --git a/lisp/image/gravatar.el b/lisp/image/gravatar.el
index b2f0d453761..9e1cb7d50ad 100644
--- a/lisp/image/gravatar.el
+++ b/lisp/image/gravatar.el
@@ -1,6 +1,6 @@
;;; gravatar.el --- Get Gravatars -*- lexical-binding: t -*-
-;; Copyright (C) 2010-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2010-2024 Free Software Foundation, Inc.
;; Author: Julien Danjou <julien@danjou.info>
;; Keywords: comm, multimedia
diff --git a/lisp/image/image-converter.el b/lisp/image/image-converter.el
index ff9d4ad0d82..2e2010e06f0 100644
--- a/lisp/image/image-converter.el
+++ b/lisp/image/image-converter.el
@@ -1,6 +1,6 @@
;;; image-converter.el --- Converting images from exotic formats -*- lexical-binding: t -*-
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
;; Keywords: images
diff --git a/lisp/image/image-crop.el b/lisp/image/image-crop.el
index 9ef848c5bc8..0f0701dc2fd 100644
--- a/lisp/image/image-crop.el
+++ b/lisp/image/image-crop.el
@@ -1,6 +1,6 @@
;;; image-crop.el --- Image Cropping -*- lexical-binding: t -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;; Keywords: multimedia
diff --git a/lisp/image/image-dired-dired.el b/lisp/image/image-dired-dired.el
index 6b932601df0..f4778d8e121 100644
--- a/lisp/image/image-dired-dired.el
+++ b/lisp/image/image-dired-dired.el
@@ -1,10 +1,11 @@
;;; image-dired-dired.el --- Dired specific commands for Image-Dired -*- lexical-binding: t -*-
-;; Copyright (C) 2005-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2005-2024 Free Software Foundation, Inc.
;; Author: Mathias Dahl <mathias.rem0veth1s.dahl@gmail.com>
;; Maintainer: Stefan Kangas <stefankangas@gmail.com>
;; Keywords: multimedia
+;; Package: image-dired
;; This file is part of GNU Emacs.
diff --git a/lisp/image/image-dired-external.el b/lisp/image/image-dired-external.el
index 77352c25a3b..8a73f518e6b 100644
--- a/lisp/image/image-dired-external.el
+++ b/lisp/image/image-dired-external.el
@@ -1,10 +1,11 @@
;;; image-dired-external.el --- External process support for Image-Dired -*- lexical-binding: t -*-
-;; Copyright (C) 2005-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2005-2024 Free Software Foundation, Inc.
;; Author: Mathias Dahl <mathias.rem0veth1s.dahl@gmail.com>
;; Maintainer: Stefan Kangas <stefankangas@gmail.com>
;; Keywords: multimedia
+;; Package: image-dired
;; This file is part of GNU Emacs.
diff --git a/lisp/image/image-dired-tags.el b/lisp/image/image-dired-tags.el
index b9c1a811850..7b4ca35a15e 100644
--- a/lisp/image/image-dired-tags.el
+++ b/lisp/image/image-dired-tags.el
@@ -1,10 +1,11 @@
;;; image-dired-tags.el --- Tag support for Image-Dired -*- lexical-binding: t -*-
-;; Copyright (C) 2005-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2005-2024 Free Software Foundation, Inc.
;; Author: Mathias Dahl <mathias.rem0veth1s.dahl@gmail.com>
;; Maintainer: Stefan Kangas <stefankangas@gmail.com>
;; Keywords: multimedia
+;; Package: image-dired
;; This file is part of GNU Emacs.
diff --git a/lisp/image/image-dired-util.el b/lisp/image/image-dired-util.el
index 53a5e274175..c3860cb0b0a 100644
--- a/lisp/image/image-dired-util.el
+++ b/lisp/image/image-dired-util.el
@@ -1,9 +1,10 @@
;;; image-dired-util.el --- util functions for Image-Dired -*- lexical-binding: t -*-
-;; Copyright (C) 2005-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2005-2024 Free Software Foundation, Inc.
;; Author: Mathias Dahl <mathias.rem0veth1s.dahl@gmail.com>
;; Maintainer: Stefan Kangas <stefankangas@gmail.com>
+;; Package: image-dired
;; This file is part of GNU Emacs.
diff --git a/lisp/image/image-dired.el b/lisp/image/image-dired.el
index 8e2e4c6f644..9eb68e240fe 100644
--- a/lisp/image/image-dired.el
+++ b/lisp/image/image-dired.el
@@ -1,6 +1,6 @@
;;; image-dired.el --- use dired to browse and manipulate your images -*- lexical-binding: t -*-
-;; Copyright (C) 2005-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2005-2024 Free Software Foundation, Inc.
;; Author: Mathias Dahl <mathias.rem0veth1s.dahl@gmail.com>
;; Maintainer: Stefan Kangas <stefankangas@gmail.com>
@@ -724,21 +724,22 @@ On reaching end or beginning of buffer, stop and show a message."
(not (if reverse (bobp) (eobp))))
(forward-char (if reverse -1 1))))
-(defmacro image-dired--movement-command (to &optional reverse)
- `(progn
- (goto-char ,to)
- (image-dired--movement-ensure-point-pos ,reverse)
- (when image-dired-track-movement
- (image-dired-track-original-file))
- (image-dired--update-header-line)))
-
-(defmacro image-dired--movement-command-line (&optional reverse)
- `(image-dired--movement-command
- (let ((goal-column (current-column)))
- (forward-line ,(if reverse -1 1))
- (move-to-column goal-column)
- (point))
- ,reverse))
+(defun image-dired--update-after-move (reverse)
+ "Book-keeping after move."
+ (image-dired--movement-ensure-point-pos reverse)
+ (when image-dired-track-movement
+ (image-dired-track-original-file))
+ (image-dired--update-header-line))
+
+(defun image-dired--movement-command (to &optional reverse)
+ (goto-char to)
+ (image-dired--update-after-move reverse))
+
+(defun image-dired--movement-command-line (&optional reverse)
+ (let ((goal-column (current-column)))
+ (forward-line (if reverse -1 1))
+ (move-to-column goal-column)
+ (image-dired--update-after-move reverse)))
(defun image-dired-next-line ()
"Move to next line in the thumbnail buffer."
@@ -775,10 +776,7 @@ On reaching end or beginning of buffer, stop and show a message."
(let ((goal-column (current-column)))
(if down (scroll-down) (scroll-up))
(move-to-column goal-column)
- (image-dired--movement-ensure-point-pos down)
- (when image-dired-track-movement
- (image-dired-track-original-file))
- (image-dired--update-header-line)))
+ (image-dired--update-after-move down)))
(defun image-dired-scroll-up ()
(interactive nil image-dired-thumbnail-mode)
diff --git a/lisp/image/wallpaper.el b/lisp/image/wallpaper.el
index c778264d3ef..79682e921b0 100644
--- a/lisp/image/wallpaper.el
+++ b/lisp/image/wallpaper.el
@@ -1,6 +1,6 @@
;;; wallpaper.el --- Change the desktop background -*- lexical-binding: t; -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;; Author: Stefan Kangas <stefankangas@gmail.com>
;; Keywords: images
diff --git a/lisp/imenu.el b/lisp/imenu.el
index c51824b7ef3..f628936cedc 100644
--- a/lisp/imenu.el
+++ b/lisp/imenu.el
@@ -1,6 +1,6 @@
;;; imenu.el --- framework for mode-specific buffer indexes -*- lexical-binding: t -*-
-;; Copyright (C) 1994-1998, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1994-1998, 2001-2024 Free Software Foundation, Inc.
;; Author: Ake Stenhoff <etxaksf@aom.ericsson.se>
;; Lars Lindberg <lli@sypro.cap.se>
diff --git a/lisp/indent-aux.el b/lisp/indent-aux.el
index ed41d4926f7..edcc6ffc22d 100644
--- a/lisp/indent-aux.el
+++ b/lisp/indent-aux.el
@@ -1,6 +1,6 @@
;;; indent-aux.el --- Autoloaded indentation commands for Emacs -*- lexical-binding:t -*-
-;; Copyright (C) 2023 Free Software Foundation, Inc.
+;; Copyright (C) 2023-2024 Free Software Foundation, Inc.
;; Maintainer: emacs-devel@gnu.org
;; Package: emacs
diff --git a/lisp/indent.el b/lisp/indent.el
index 89de0a1d7d1..74ef9183d95 100644
--- a/lisp/indent.el
+++ b/lisp/indent.el
@@ -1,6 +1,6 @@
;;; indent.el --- indentation commands for Emacs -*- lexical-binding:t -*-
-;; Copyright (C) 1985, 1995, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1985, 1995, 2001-2024 Free Software Foundation, Inc.
;; Maintainer: emacs-devel@gnu.org
;; Package: emacs
@@ -170,8 +170,7 @@ prefix argument is ignored."
(t
(let ((old-tick (buffer-chars-modified-tick))
(old-point (point))
- (old-indent (current-indentation))
- (syn (syntax-after (point))))
+ (old-indent (current-indentation)))
;; Indent the line.
(or (not (eq (indent--funcall-widened indent-line-function) 'noindent))
@@ -185,19 +184,14 @@ prefix argument is ignored."
((and (eq tab-always-indent 'complete)
(eql old-point (point))
(eql old-tick (buffer-chars-modified-tick))
- (or (null tab-first-completion)
- (eq last-command this-command)
- (and (eq tab-first-completion 'eol)
- (eolp))
- (and (memq tab-first-completion
- '(word word-or-paren word-or-paren-or-punct))
- (not (eql 2 syn)))
- (and (memq tab-first-completion
- '(word-or-paren word-or-paren-or-punct))
- (not (or (eql 4 syn)
- (eql 5 syn))))
- (and (eq tab-first-completion 'word-or-paren-or-punct)
- (not (eql 1 syn)))))
+ (or (eq last-command this-command)
+ (let ((syn (syntax-class (syntax-after (point)))))
+ (pcase tab-first-completion
+ ('nil t)
+ ('eol (eolp))
+ ('word (not (eql 2 syn)))
+ ('word-or-paren (not (memq syn '(2 4 5))))
+ ('word-or-paren-or-punct (not (memq syn '(2 4 5 1))))))))
(completion-at-point))
;; If a prefix argument was given, rigidly indent the following
@@ -271,7 +265,7 @@ indentation by specifying a large negative ARG."
(interactive "r\nP\np")
(if (and (not arg) interactive)
(set-transient-map indent-rigidly-map t #'deactivate-mark
- "Indent region with %k")
+ "Type %k to indent region interactively")
(save-excursion
(goto-char end)
(setq end (point-marker))
diff --git a/lisp/info-look.el b/lisp/info-look.el
index da45e30cd36..da7beafe500 100644
--- a/lisp/info-look.el
+++ b/lisp/info-look.el
@@ -1,7 +1,6 @@
;;; info-look.el --- major-mode-sensitive Info index lookup facility -*- lexical-binding: t -*-
-;; An older version of this was known as libc.el.
-;; Copyright (C) 1995-1999, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1995-1999, 2001-2024 Free Software Foundation, Inc.
;; Author: Ralph Schleicher <rs@ralph-schleicher.de>
;; Keywords: help languages
@@ -28,11 +27,9 @@
;; Some additional sources of (Tex)info files for non-GNU packages:
;;
-;; Scheme: <URL:http://groups.csail.mit.edu/mac/ftpdir/scm/r5rs.info.tar.gz>
-;; LaTeX:
-;; <URL:http://ctan.tug.org/tex-archive/info/latex2e-help-texinfo/latex2e.texi>
+;; Scheme: https://groups.csail.mit.edu/mac/ftpdir/scm/r5rs.info.tar.gz
+;; LaTeX: https://mirrors.ctan.org/info/latex2e-help-texinfo/latex2e.texi
;; (or CTAN mirrors)
-;; Perl: <URL:http://ftp.cpan.org/pub/CPAN/doc/manual/texinfo/> (or CPAN mirrors)
;; Traditionally, makeinfo quoted `like this', but version 5 and later
;; quotes 'like this' or ‘like this’. Doc specs with patterns
@@ -56,13 +53,13 @@ Automatically becomes buffer local when set in any fashion.")
(make-variable-buffer-local 'info-lookup-mode)
(defcustom info-lookup-other-window-flag t
- "Non-nil means pop up the Info buffer in another window."
- :group 'info-lookup :type 'boolean)
+ "Non-nil means pop up the Info buffer in another window."
+ :type 'boolean)
(defcustom info-lookup-highlight-face 'match
"Face for highlighting looked up help items.
Setting this variable to nil disables highlighting."
- :group 'info-lookup :type 'face)
+ :type 'face)
(defvar info-lookup-highlight-overlay nil
"Overlay object used for highlighting.")
@@ -76,7 +73,7 @@ List elements are cons cells of the form
If a file name matches REGEXP, then use help mode MODE instead of the
buffer's major mode."
- :group 'info-lookup :type '(repeat (cons (regexp :tag "Regexp")
+ :type '(repeat (cons (regexp :tag "Regexp")
(symbol :tag "Mode"))))
(defvar info-lookup-history nil
@@ -170,13 +167,13 @@ the value of `:mode' as HELP-MODE, etc..
If no topic or mode option has been specified, then the help topic defaults
to `symbol', and the help mode defaults to the current major mode."
- (apply 'info-lookup-add-help* nil arg))
+ (apply #'info-lookup-add-help* nil arg))
(defun info-lookup-maybe-add-help (&rest arg)
"Add a help specification if none is defined.
See the documentation of the function `info-lookup-add-help'
for more details."
- (apply 'info-lookup-add-help* t arg))
+ (apply #'info-lookup-add-help* t arg))
(defun info-lookup-add-help* (maybe &rest arg)
(let (topic mode regexp ignore-case doc-spec
@@ -352,18 +349,18 @@ If optional argument QUERY is non-nil, query for the help mode."
(setq file-name-alist (cdr file-name-alist)))))
;; If major-mode has no setups in info-lookup-alist, under any topic, then
- ;; search up through derived-mode-parent to find a parent mode which does
- ;; have some setups. This means that a `define-derived-mode' with no
+ ;; search up through `derived-mode-all-parents' to find a parent mode which
+ ;; does have some setups. This means that a `define-derived-mode' with no
;; setups of its own will select its parent mode for lookups, if one of
;; its parents has some setups. Good for example on `makefile-gmake-mode'
;; and similar derivatives of `makefile-mode'.
;;
- (let ((mode major-mode)) ;; Look for `mode' with some setups.
- (while (and mode (not info-lookup-mode))
+ (let ((modes (derived-mode-all-parents major-mode))) ;; Look for `mode' with some setups.
+ (while (and modes (not info-lookup-mode))
(dolist (topic-cell info-lookup-alist) ;; Usually only two topics here.
- (if (info-lookup->mode-value (car topic-cell) mode)
- (setq info-lookup-mode mode)))
- (setq mode (get mode 'derived-mode-parent))))
+ (if (info-lookup->mode-value (car topic-cell) (car modes))
+ (setq info-lookup-mode (car modes))))
+ (setq modes (cdr modes))))
(or info-lookup-mode (setq info-lookup-mode major-mode)))
@@ -529,7 +526,7 @@ different window."
(nconc (condition-case nil
(info-lookup-make-completions topic mode)
(error nil))
- (apply 'append
+ (apply #'append
(mapcar (lambda (arg)
(info-lookup->completions topic arg))
refer-modes))))
diff --git a/lisp/info-xref.el b/lisp/info-xref.el
index a910f38af84..7887909037b 100644
--- a/lisp/info-xref.el
+++ b/lisp/info-xref.el
@@ -1,6 +1,6 @@
;;; info-xref.el --- check external references in an Info document -*- lexical-binding: t -*-
-;; Copyright (C) 2003-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003-2024 Free Software Foundation, Inc.
;; Author: Kevin Ryde <user42@zip.com.au>
;; Keywords: docs
diff --git a/lisp/info.el b/lisp/info.el
index 463aea93376..39ca88c358c 100644
--- a/lisp/info.el
+++ b/lisp/info.el
@@ -1,6 +1,6 @@
;;; info.el --- Info package for Emacs -*- lexical-binding:t -*-
-;; Copyright (C) 1985-1986, 1992-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1985-1986, 1992-2024 Free Software Foundation, Inc.
;; Maintainer: emacs-devel@gnu.org
;; Keywords: help
@@ -1787,11 +1787,24 @@ By default, go to the current Info node."
(interactive (list (Info-read-node-name
"Go to node (default current page): " Info-current-node))
Info-mode)
- (browse-url-button-open-url
- (Info-url-for-node (format "(%s)%s" (file-name-sans-extension
- (file-name-nondirectory
- Info-current-file))
- node))))
+ (let (filename)
+ (string-match "\\s *\\((\\s *\\([^\t)]*\\)\\s *)\\s *\\|\\)\\(.*\\)"
+ node)
+ (setq filename (if (= (match-beginning 1) (match-end 1))
+ ""
+ (match-string 2 node))
+ node (match-string 3 node))
+ (let ((trim (string-match "\\s +\\'" filename)))
+ (if trim (setq filename (substring filename 0 trim))))
+ (let ((trim (string-match "\\s +\\'" node)))
+ (if trim (setq node (substring node 0 trim))))
+ (if (equal filename "")
+ (setq filename (file-name-sans-extension (file-name-nondirectory
+ Info-current-file))))
+ (if (equal node "")
+ (setq node "Top"))
+ (browse-url-button-open-url
+ (Info-url-for-node (format "(%s)%s" filename node)))))
(defun Info-url-for-node (node)
"Return a URL for NODE, a node in the GNU Emacs or Elisp manual.
@@ -1817,8 +1830,10 @@ and elisp manuals are supported."
""))
(concat "https://www.gnu.org/software/emacs/manual/html_node/"
manual "/"
- (url-hexify-string (string-replace " " "-" node))
- ".html")))
+ (and (not (equal node "Top"))
+ (concat
+ (url-hexify-string (string-replace " " "-" node))
+ ".html")))))
(defvar Info-read-node-completion-table)
diff --git a/lisp/informat.el b/lisp/informat.el
index 6ef26d326a4..79ffad57302 100644
--- a/lisp/informat.el
+++ b/lisp/informat.el
@@ -1,6 +1,6 @@
;;; informat.el --- info support functions package for Emacs -*- lexical-binding: t; -*-
-;; Copyright (C) 1986, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1986, 2001-2024 Free Software Foundation, Inc.
;; Maintainer: emacs-devel@gnu.org
;; Keywords: help
diff --git a/lisp/international/ccl.el b/lisp/international/ccl.el
index 7e58621a67f..b093df36a0f 100644
--- a/lisp/international/ccl.el
+++ b/lisp/international/ccl.el
@@ -1,6 +1,6 @@
;;; ccl.el --- CCL (Code Conversion Language) compiler -*- lexical-binding:t -*-
-;; Copyright (C) 1997-1998, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997-1998, 2001-2024 Free Software Foundation, Inc.
;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
;; 2005, 2006, 2007, 2008, 2009, 2010, 2011
;; National Institute of Advanced Industrial Science and Technology (AIST)
diff --git a/lisp/international/characters.el b/lisp/international/characters.el
index 1aa570ca59a..1e5963f89f3 100644
--- a/lisp/international/characters.el
+++ b/lisp/international/characters.el
@@ -1,6 +1,6 @@
;;; characters.el --- set syntax and category for multibyte characters -*- lexical-binding: t; -*-
-;; Copyright (C) 1997, 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997, 2000-2024 Free Software Foundation, Inc.
;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
;; 2005, 2006, 2007, 2008, 2009, 2010, 2011
;; National Institute of Advanced Industrial Science and Technology (AIST)
@@ -141,10 +141,10 @@ with L, LRE, or LRO Unicode bidi character type.")
;; Chinese characters (Unicode)
(modify-category-entry '(#x2E80 . #x312F) ?|)
(modify-category-entry '(#x3190 . #x33FF) ?|)
-(modify-category-entry '(#x3400 . #x4DB5) ?C)
-(modify-category-entry '(#x4E00 . #x9FD5) ?C)
-(modify-category-entry '(#x3400 . #x9FD5) ?c)
-(modify-category-entry '(#x3400 . #x9FD5) ?|)
+(modify-category-entry '(#x3400 . #x4DBF) ?C)
+(modify-category-entry '(#x4E00 . #x9FFF) ?C)
+(modify-category-entry '(#x3400 . #x9FFF) ?c)
+(modify-category-entry '(#x3400 . #x9FFF) ?|)
(modify-category-entry '(#xF900 . #xFAFF) ?C)
(modify-category-entry '(#xF900 . #xFAFF) ?c)
(modify-category-entry '(#xF900 . #xFAFF) ?|)
@@ -1303,12 +1303,13 @@ with L, LRE, or LRO Unicode bidi character type.")
(#x2E80 . #x2E99)
(#x2E9B . #x2EF3)
(#x2F00 . #x2FD5)
- (#x2FF0 . #x2FFB)
+ (#x2FF0 . #x2FFF)
(#x3000 . #x303E)
(#x3041 . #x3096)
(#x3099 . #x30FF)
(#x3105 . #x312F)
(#x3131 . #x31E3)
+ (#x31EF . #x31EF)
(#x31F0 . #x3247)
(#x3250 . #x4DBF)
(#x4E00 . #xA48C)
@@ -1695,6 +1696,9 @@ Setup `char-width-table' appropriate for non-CJK language environment."
;; Fix some exceptions that blocks.awk/Blocks.txt couldn't get right.
(set-char-table-range char-script-table '(#x2ea . #x2eb) 'bopomofo)
(set-char-table-range char-script-table #xab65 'greek)
+(set-char-table-range char-script-table #x16fe0 'tangut)
+(set-char-table-range char-script-table #x16fe1 'nushu)
+
;;; Setting unicode-category-table.
diff --git a/lisp/international/emoji.el b/lisp/international/emoji.el
index 856c405b545..3a191c5ecd3 100644
--- a/lisp/international/emoji.el
+++ b/lisp/international/emoji.el
@@ -1,6 +1,6 @@
;;; emoji.el --- Inserting emojis -*- lexical-binding:t -*-
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
;; Author: Lars Ingebrigtsen <larsi@gnus.org>
;; Keywords: fun
@@ -97,7 +97,7 @@ representing names. For instance:
(multisession-value emoji--recent)))
;;;###autoload (autoload 'emoji-search "emoji" nil t)
-(transient-define-prefix emoji-search ()
+(transient-define-prefix emoji-search (glyph derived)
"Choose and insert an emoji glyph by typing its Unicode name.
This command prompts for an emoji name, with completion, and
inserts it. It recognizes the Unicode Standard names of emoji,
@@ -106,15 +106,17 @@ and also consults the `emoji-alternate-names' alist."
[:class transient-columns
:setup-children emoji--setup-suffixes
:description emoji--group-description]
- (interactive "*")
- (emoji--init)
- (pcase-let ((`(,glyph . ,derived) (emoji--read-emoji)))
- (if derived
- (emoji--setup-prefix 'emoji-search "Choose Emoji"
- (list glyph)
- (cons glyph derived))
- (emoji--add-recent glyph)
- (insert glyph))))
+ (interactive
+ (progn (barf-if-buffer-read-only)
+ (emoji--init)
+ (let ((cons (emoji--read-emoji)))
+ (list (car cons) (cdr cons)))))
+ (if derived
+ (emoji--setup-prefix 'emoji-search "Choose Emoji"
+ (list glyph)
+ (cons glyph derived))
+ (emoji--add-recent glyph)
+ (insert glyph)))
(defclass emoji--narrow (transient-suffix)
((title :initarg :title)
@@ -142,20 +144,23 @@ and also consults the `emoji-alternate-names' alist."
(defun emoji--group-description ()
(car (oref transient--prefix scope)))
-(transient-define-suffix emoji-insert-glyph ()
+(transient-define-suffix emoji-insert-glyph (glyph)
"Insert the emoji you selected."
- (interactive nil not-a-mode)
- (let ((glyph (oref (transient-suffix-object) description)))
- (emoji--add-recent glyph)
- (insert glyph)))
+ (interactive
+ (list (if (string-prefix-p "emoji-" (symbol-name transient-current-command))
+ (oref (transient-suffix-object) description)
+ (car (multisession-value emoji--recent))))
+ not-a-mode)
+ (emoji--add-recent glyph)
+ (insert glyph))
;;;###autoload
(defun emoji-list ()
- "List emojis and insert the one that's selected.
+ "List emojis and allow selecting and inserting one of them.
Select the emoji by typing \\<emoji-list-mode-map>\\[emoji-list-select] on its picture.
The glyph will be inserted into the buffer that was current
when the command was invoked."
- (interactive "*")
+ (interactive)
(let ((buf (current-buffer)))
(emoji--init)
(switch-to-buffer (get-buffer-create "*Emoji*"))
@@ -268,7 +273,9 @@ the name is not known."
(let ((buf emoji--insert-buffer))
(quit-window)
(if (buffer-live-p buf)
- (switch-to-buffer buf)
+ (progn
+ (switch-to-buffer buf)
+ (barf-if-buffer-read-only))
(error "Buffer disappeared")))
(let ((derived (gethash glyph emoji--derived)))
(if derived
@@ -710,10 +717,14 @@ FACTOR is the multiplication factor for the size."
(add-text-properties
(point) (1+ (point))
(list 'face
- (if (eq (car old) :height)
- (plist-put (copy-sequence old) :height newheight)
+ (cond
+ ((eq (car old) :height)
+ (plist-put (copy-sequence old) :height newheight))
+ ((plistp (car old))
(cons (plist-put (car old) :height newheight)
(cdr old)))
+ (t
+ (append (list (list :height newheight)) old)))
'rear-nonsticky t))
(add-face-text-property (point) (1+ (point))
(list :height newheight))
diff --git a/lisp/international/fontset.el b/lisp/international/fontset.el
index d879920b1d0..2c461a7f7ab 100644
--- a/lisp/international/fontset.el
+++ b/lisp/international/fontset.el
@@ -1,6 +1,6 @@
;;; fontset.el --- commands for handling fontset -*- lexical-binding: t; -*-
-;; Copyright (C) 1997-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997-2024 Free Software Foundation, Inc.
;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
;; 2005, 2006, 2007, 2008, 2009, 2010, 2011
;; National Institute of Advanced Industrial Science and Technology (AIST)
diff --git a/lisp/international/isearch-x.el b/lisp/international/isearch-x.el
index 448e633d0c2..2112ab921e2 100644
--- a/lisp/international/isearch-x.el
+++ b/lisp/international/isearch-x.el
@@ -1,6 +1,6 @@
;;; isearch-x.el --- extended isearch handling commands -*- lexical-binding: t; -*-
-;; Copyright (C) 1997, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997, 2001-2024 Free Software Foundation, Inc.
;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
;; 2005, 2006, 2007, 2008, 2009, 2010, 2011
;; National Institute of Advanced Industrial Science and Technology (AIST)
diff --git a/lisp/international/iso-ascii.el b/lisp/international/iso-ascii.el
index 749118ea20f..a8129db9504 100644
--- a/lisp/international/iso-ascii.el
+++ b/lisp/international/iso-ascii.el
@@ -1,6 +1,6 @@
;;; iso-ascii.el --- set up char tables for ISO 8859/1 on ASCII terminals -*- lexical-binding: t -*-
-;; Copyright (C) 1987, 1995, 1998, 2001-2023 Free Software Foundation,
+;; Copyright (C) 1987, 1995, 1998, 2001-2024 Free Software Foundation,
;; Inc.
;; Author: Howard Gayle
diff --git a/lisp/international/iso-cvt.el b/lisp/international/iso-cvt.el
index 0adf8a24092..7f052e3fe66 100644
--- a/lisp/international/iso-cvt.el
+++ b/lisp/international/iso-cvt.el
@@ -1,7 +1,7 @@
;;; iso-cvt.el --- translate ISO 8859-1 from/to various encodings -*- lexical-binding: t; -*-
;; This file was formerly called gm-lingo.el.
-;; Copyright (C) 1993-1998, 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1993-1998, 2000-2024 Free Software Foundation, Inc.
;; Author: Michael Gschwind <mike@vlsivie.tuwien.ac.at>
;; Keywords: tex, iso, latin, i18n
diff --git a/lisp/international/iso-transl.el b/lisp/international/iso-transl.el
index 459d1ff7f97..67659f7c265 100644
--- a/lisp/international/iso-transl.el
+++ b/lisp/international/iso-transl.el
@@ -1,6 +1,6 @@
;;; iso-transl.el --- keyboard input for ISO 10646 chars -*- coding: utf-8; lexical-binding: t; -*-
-;; Copyright (C) 1987, 1993-1999, 2001-2023 Free Software Foundation,
+;; Copyright (C) 1987, 1993-1999, 2001-2024 Free Software Foundation,
;; Inc.
;; Author: Howard Gayle
@@ -293,6 +293,8 @@
("a<" . [?←])
("a>" . [?→])
("a=" . [?↔])
+ ("ae" . [?æ])
+ ("AE" . [?Æ])
("_-" . [?−])
("~=" . [?≈])
("/=" . [?≠])
diff --git a/lisp/international/ja-dic-cnv.el b/lisp/international/ja-dic-cnv.el
index 5477473ae8c..6f3a0c929c5 100644
--- a/lisp/international/ja-dic-cnv.el
+++ b/lisp/international/ja-dic-cnv.el
@@ -1,6 +1,6 @@
;;; ja-dic-cnv.el --- convert a Japanese dictionary (SKK-JISYO.L) to Emacs Lisp -*- lexical-binding: t; -*-
-;; Copyright (C) 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2024 Free Software Foundation, Inc.
;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
;; 2005, 2006, 2007, 2008, 2009, 2010, 2011
@@ -346,6 +346,8 @@ If NO-REDUCTION is non-nil, do not reduce the dictionary vocabulary."
(erase-buffer)
(buffer-disable-undo)
(generate-lisp-file-heading ja-dic-filename 'skkdic-convert :code nil)
+ (insert (format ";; Generated with small ja-dic option: %s\n\n"
+ (if no-reduction "no" "yes")))
(insert ";; Original SKK dictionary file: "
(file-relative-name (expand-file-name filename) dirname)
"\n\n"
diff --git a/lisp/international/kinsoku.el b/lisp/international/kinsoku.el
index 93719768bac..7c2ad1abf29 100644
--- a/lisp/international/kinsoku.el
+++ b/lisp/international/kinsoku.el
@@ -1,6 +1,6 @@
;;; kinsoku.el --- `Kinsoku' processing funcs -*- lexical-binding: t; -*-
-;; Copyright (C) 1997, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997, 2001-2024 Free Software Foundation, Inc.
;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
;; 2005, 2006, 2007, 2008, 2009, 2010, 2011
;; National Institute of Advanced Industrial Science and Technology (AIST)
diff --git a/lisp/international/kkc.el b/lisp/international/kkc.el
index b10d3e76075..193c9c6147f 100644
--- a/lisp/international/kkc.el
+++ b/lisp/international/kkc.el
@@ -1,6 +1,6 @@
;;; kkc.el --- Kana Kanji converter -*- lexical-binding: t; -*-
-;; Copyright (C) 1997-1998, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997-1998, 2001-2024 Free Software Foundation, Inc.
;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
;; 2005, 2006, 2007, 2008, 2009, 2010, 2011
;; National Institute of Advanced Industrial Science and Technology (AIST)
diff --git a/lisp/international/latexenc.el b/lisp/international/latexenc.el
index e245a099742..6e2306449bc 100644
--- a/lisp/international/latexenc.el
+++ b/lisp/international/latexenc.el
@@ -1,6 +1,6 @@
;;; latexenc.el --- guess correct coding system in LaTeX files -*- lexical-binding: t; -*-
-;; Copyright (C) 2005-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2005-2024 Free Software Foundation, Inc.
;; Author: Arne Jørgensen <arne@arnested.dk>
;; Keywords: mule, coding system, latex
diff --git a/lisp/international/latin1-disp.el b/lisp/international/latin1-disp.el
index d3a458ac516..69b9f81658b 100644
--- a/lisp/international/latin1-disp.el
+++ b/lisp/international/latin1-disp.el
@@ -1,6 +1,6 @@
;;; latin1-disp.el --- display tables for non-ASCII on Latin-1 terminals -*- lexical-binding: t; -*-
-;; Copyright (C) 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2000-2024 Free Software Foundation, Inc.
;; Author: Dave Love <fx@gnu.org>
;; Keywords: i18n
diff --git a/lisp/international/mule-cmds.el b/lisp/international/mule-cmds.el
index e3811d81ec2..07f11a62594 100644
--- a/lisp/international/mule-cmds.el
+++ b/lisp/international/mule-cmds.el
@@ -1,6 +1,6 @@
;;; mule-cmds.el --- commands for multilingual environment -*- lexical-binding:t -*-
-;; Copyright (C) 1997-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997-2024 Free Software Foundation, Inc.
;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
;; 2005, 2006, 2007, 2008, 2009, 2010, 2011
;; National Institute of Advanced Industrial Science and Technology (AIST)
@@ -868,8 +868,7 @@ overrides ACCEPT-DEFAULT-P.
Kludgy feature: if FROM is a string, the string is the target text,
and TO is ignored."
- (if (not (listp default-coding-system))
- (setq default-coding-system (list default-coding-system)))
+ (setq default-coding-system (ensure-list default-coding-system))
(let ((no-other-defaults nil)
auto-cs)
@@ -3095,6 +3094,10 @@ on encoding."
(defun ucs-names ()
"Return table of CHAR-NAME keys and CHAR-CODE values cached in `ucs-names'."
(or ucs-names
+ ;; Sometimes these ranges will need adjusting as codepoints are
+ ;; added to unicode. The test case
+ ;; 'mule-cmds-tests--ucs-names-missing-names' will tell you
+ ;; which are missing (Bug#65997).
(let ((ranges
'((#x0000 . #x33FF)
;; (#x3400 . #x4DBF) CJK Ideographs Extension A
@@ -3107,14 +3110,16 @@ on encoding."
(#x14400 . #x14646)
;; (#x14647 . #x167FF) unused
(#x16800 . #x16F9F)
- (#x16FE0 . #x16FE3)
+ (#x16FE0 . #x16FF1)
;; (#x17000 . #x187FF) Tangut Ideographs
;; (#x18800 . #x18AFF) Tangut Components
;; (#x18B00 . #x18CFF) Khitan Small Script
;; (#x18D00 . #x18D0F) Tangut Ideograph Supplement
;; (#x18D10 . #x1AFEF) unused
- (#x1AFF0 . #x1B12F)
- ;; (#x1B130 . #x1B14F) unused
+ (#x1AFF0 . #x1B122)
+ ;; (#x1B123 . #x1B131) unused
+ (#x1B132 . #x1B132)
+ ;; (#x1B133 . #x1B14F) unused
(#x1B150 . #x1B16F)
(#x1B170 . #x1B2FF)
;; (#x1B300 . #x1BBFF) unused
@@ -3131,12 +3136,16 @@ on encoding."
(while (<= c end)
(let ((new-name (get-char-code-property c 'name))
(old-name (get-char-code-property c 'old-name)))
- ;; In theory this code could end up pushing an "old-name" that
- ;; shadows a "new-name" but in practice every time an
- ;; `old-name' conflicts with a `new-name', the newer one has a
- ;; higher code, so it gets pushed later!
+ ;; This code used to push both old-name and new-name
+ ;; on the assumption that the new-name codepoint would
+ ;; always be higher, which was true for a long time.
+ ;; As of at latest 2023-09-15, this is no longer true,
+ ;; so we now skip the old-name if it conflicts with an
+ ;; existing new-name (Bug#65997).
(if new-name (puthash new-name c names))
- (if old-name (puthash old-name c names))
+ (when (and old-name
+ (not (gethash old-name names)))
+ (puthash old-name c names))
;; Unicode uses the spelling "lamda" in character
;; names, instead of "lambda", due to "preferences
;; expressed by the Greek National Body" (Bug#30513).
diff --git a/lisp/international/mule-conf.el b/lisp/international/mule-conf.el
index f65f124b633..1a58e9b7068 100644
--- a/lisp/international/mule-conf.el
+++ b/lisp/international/mule-conf.el
@@ -1,6 +1,6 @@
;;; mule-conf.el --- configure multilingual environment -*- lexical-binding: t; -*-
-;; Copyright (C) 1997-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997-2024 Free Software Foundation, Inc.
;; Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
;; National Institute of Advanced Industrial Science and Technology (AIST)
;; Registration Number H14PRO021
diff --git a/lisp/international/mule-diag.el b/lisp/international/mule-diag.el
index 6a533f0418e..e8556119995 100644
--- a/lisp/international/mule-diag.el
+++ b/lisp/international/mule-diag.el
@@ -1,6 +1,6 @@
;;; mule-diag.el --- show diagnosis of multilingual environment (Mule) -*- lexical-binding: t; -*-
-;; Copyright (C) 1997-1998, 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997-1998, 2000-2024 Free Software Foundation, Inc.
;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
;; 2005, 2006, 2007, 2008, 2009, 2010, 2011
;; National Institute of Advanced Industrial Science and Technology (AIST)
diff --git a/lisp/international/mule-util.el b/lisp/international/mule-util.el
index c87a4a0ea95..504c15e749b 100644
--- a/lisp/international/mule-util.el
+++ b/lisp/international/mule-util.el
@@ -1,6 +1,6 @@
;;; mule-util.el --- utility functions for multilingual environment (mule) -*- lexical-binding:t -*-
-;; Copyright (C) 1997-1998, 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997-1998, 2000-2024 Free Software Foundation, Inc.
;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
;; 2005, 2006, 2007, 2008, 2009, 2010, 2011
;; National Institute of Advanced Industrial Science and Technology (AIST)
diff --git a/lisp/international/mule.el b/lisp/international/mule.el
index 2b44a2e0645..a17221e6d21 100644
--- a/lisp/international/mule.el
+++ b/lisp/international/mule.el
@@ -1,6 +1,6 @@
;;; mule.el --- basic commands for multilingual environment -*- lexical-binding: t; -*-
-;; Copyright (C) 1997-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997-2024 Free Software Foundation, Inc.
;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
;; 2005, 2006, 2007, 2008, 2009, 2010, 2011
;; National Institute of Advanced Industrial Science and Technology (AIST)
diff --git a/lisp/international/ogonek.el b/lisp/international/ogonek.el
index e2229be288e..13feaee405a 100644
--- a/lisp/international/ogonek.el
+++ b/lisp/international/ogonek.el
@@ -1,6 +1,6 @@
;;; ogonek.el --- change the encoding of Polish diacritics -*- lexical-binding: t; -*-
-;; Copyright (C) 1997-1998, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997-1998, 2001-2024 Free Software Foundation, Inc.
;; Author: Włodek Bzyl
;; Ryszard Kubiak
diff --git a/lisp/international/quail.el b/lisp/international/quail.el
index 894378bda8b..56f049aedf5 100644
--- a/lisp/international/quail.el
+++ b/lisp/international/quail.el
@@ -1,6 +1,6 @@
;;; quail.el --- provides simple input method for multilingual text -*- lexical-binding: t; -*-
-;; Copyright (C) 1997-1998, 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997-1998, 2000-2024 Free Software Foundation, Inc.
;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
;; 2005, 2006, 2007, 2008, 2009, 2010, 2011
;; National Institute of Advanced Industrial Science and Technology (AIST)
diff --git a/lisp/international/rfc1843.el b/lisp/international/rfc1843.el
index 287096ad352..10000cb24a3 100644
--- a/lisp/international/rfc1843.el
+++ b/lisp/international/rfc1843.el
@@ -1,6 +1,6 @@
;;; rfc1843.el --- HZ (RFC 1843) decoding -*- lexical-binding:t -*-
-;; Copyright (C) 1998-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-2024 Free Software Foundation, Inc.
;; Author: Shenghuo Zhu <zsh@cs.rochester.edu>
;; Keywords: news HZ HZ+ mail i18n
diff --git a/lisp/international/textsec-check.el b/lisp/international/textsec-check.el
index 6739f7b9a9d..3a0841c1b5a 100644
--- a/lisp/international/textsec-check.el
+++ b/lisp/international/textsec-check.el
@@ -1,6 +1,6 @@
;;; textsec-check.el --- Check for suspicious texts -*- lexical-binding: t; -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/lisp/international/textsec.el b/lisp/international/textsec.el
index e69e7c19842..86429f15f7c 100644
--- a/lisp/international/textsec.el
+++ b/lisp/international/textsec.el
@@ -1,6 +1,6 @@
;;; textsec.el --- Functions for handling homoglyphs and the like -*- lexical-binding: t; -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/lisp/international/titdic-cnv.el b/lisp/international/titdic-cnv.el
index abd4d3fd40b..c4706e061e3 100644
--- a/lisp/international/titdic-cnv.el
+++ b/lisp/international/titdic-cnv.el
@@ -1,6 +1,6 @@
;;; titdic-cnv.el --- convert cxterm dictionary (TIT format) to Quail package -*- coding: utf-8-emacs; lexical-binding:t -*-
-;; Copyright (C) 1997-1998, 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997-1998, 2000-2024 Free Software Foundation, Inc.
;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
;; 2005, 2006, 2007, 2008, 2009, 2010, 2011
;; National Institute of Advanced Industrial Science and Technology (AIST)
diff --git a/lisp/international/ucs-normalize.el b/lisp/international/ucs-normalize.el
index aed7a6a1392..ccb2022375c 100644
--- a/lisp/international/ucs-normalize.el
+++ b/lisp/international/ucs-normalize.el
@@ -1,6 +1,6 @@
;;; ucs-normalize.el --- Unicode normalization NFC/NFD/NFKD/NFKC -*- lexical-binding: t; -*-
-;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
;; Author: Taichi Kawabata <kawabata.taichi@gmail.com>
;; Keywords: unicode, normalization
@@ -131,11 +131,19 @@
#x1D1BF #x1D1C0)
"Composition Exclusion List.
This list is taken from
- https://www.unicode.org/Public/UNIDATA/5.2/CompositionExclusions.txt")
+ https://www.unicode.org/Public/UNIDATA/15.0/CompositionExclusions.txt")
+
+ ;; Unicode ranges where decompositions & combining characters are
+ ;; defined. Find them by running the following Awk program on
+ ;; UnicodeData.txt:
+ ;;
+ ;; gawk -F";" "$6 != \"\" {print $0}"
- ;; Unicode ranges that decompositions & combining characters are defined.
(defvar check-range nil)
- (setq check-range '((#x00a0 . #x3400) (#xA600 . #xAC00) (#xF900 . #x110ff) (#x1d000 . #x1dfff) (#x1f100 . #x1f2ff) (#x2f800 . #x2faff)))
+ (setq check-range
+ '((#x00A0 . #x3400) (#xA600 . #xAC00) (#xF900 . #x11100)
+ (#x11100 . #x11A00) (#x1D000 . #x1E100) (#x1EE00 . #x1F300)
+ (#x1FBF0 . #x1FC00) (#x2F800 . #x2FB00)))
;; Basic normalization functions
(defun nfd (char)
diff --git a/lisp/international/utf-7.el b/lisp/international/utf-7.el
index 335866f65ff..25f5e8367d8 100644
--- a/lisp/international/utf-7.el
+++ b/lisp/international/utf-7.el
@@ -1,6 +1,6 @@
;;; utf-7.el --- utf-7 coding system -*- lexical-binding: t; -*-
-;; Copyright (C) 2003-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003-2024 Free Software Foundation, Inc.
;; Author: Dave Love <fx@gnu.org>
;; Keywords: i18n, mail
diff --git a/lisp/international/utf7.el b/lisp/international/utf7.el
index af66a7c2e01..63009b0744a 100644
--- a/lisp/international/utf7.el
+++ b/lisp/international/utf7.el
@@ -1,6 +1,6 @@
;;; utf7.el --- UTF-7 encoding/decoding for Emacs -*- lexical-binding:t -*-
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
;; Author: Jon K Hellan <hellan@acm.org>
;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/isearch.el b/lisp/isearch.el
index 4d231fba469..6b39054b512 100644
--- a/lisp/isearch.el
+++ b/lisp/isearch.el
@@ -1,6 +1,6 @@
;;; isearch.el --- incremental search minor mode -*- lexical-binding: t -*-
-;; Copyright (C) 1992-1997, 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1992-1997, 1999-2024 Free Software Foundation, Inc.
;; Author: Daniel LaLiberte <liberte@cs.uiuc.edu>
;; Maintainer: emacs-devel@gnu.org
@@ -4054,6 +4054,7 @@ since they have special meaning in a regexp."
(defvar isearch-lazy-highlight-point-max nil)
(defvar isearch-lazy-highlight-buffer nil)
(defvar isearch-lazy-highlight-case-fold-search nil)
+(defvar isearch-lazy-highlight-invisible nil)
(defvar isearch-lazy-highlight-regexp nil)
(defvar isearch-lazy-highlight-lax-whitespace nil)
(defvar isearch-lazy-highlight-regexp-lax-whitespace nil)
@@ -4099,6 +4100,8 @@ by other Emacs features."
isearch-lazy-highlight-window-group))
(not (eq isearch-lazy-highlight-case-fold-search
isearch-case-fold-search))
+ (not (eq isearch-lazy-highlight-invisible
+ isearch-invisible))
(not (eq isearch-lazy-highlight-regexp
isearch-regexp))
(not (eq isearch-lazy-highlight-regexp-function
@@ -4177,6 +4180,7 @@ by other Emacs features."
isearch-lazy-highlight-wrapped nil
isearch-lazy-highlight-last-string isearch-string
isearch-lazy-highlight-case-fold-search isearch-case-fold-search
+ isearch-lazy-highlight-invisible isearch-invisible
isearch-lazy-highlight-regexp isearch-regexp
isearch-lazy-highlight-lax-whitespace isearch-lax-whitespace
isearch-lazy-highlight-regexp-lax-whitespace isearch-regexp-lax-whitespace
@@ -4226,8 +4230,10 @@ Attempt to do the search exactly the way the pending Isearch would."
(isearch-forward isearch-lazy-highlight-forward)
;; Count all invisible matches, but highlight only
;; matches that can be opened by visiting them later
- (search-invisible (or (not (null isearch-lazy-count))
- 'can-be-opened))
+ (search-invisible
+ (or (not (null isearch-lazy-count))
+ (and (eq isearch-lazy-highlight-invisible 'open)
+ 'can-be-opened)))
(retry t)
(success nil))
;; Use a loop like in `isearch-search'.
@@ -4247,7 +4253,9 @@ Attempt to do the search exactly the way the pending Isearch would."
(when (or (not isearch-lazy-count)
;; Recheck the match that possibly was intended
;; for counting only, but not for highlighting
- (let ((search-invisible 'can-be-opened))
+ (let ((search-invisible
+ (and (eq isearch-lazy-highlight-invisible 'open)
+ 'can-be-opened)))
(funcall isearch-filter-predicate mb me)))
(let ((ov (make-overlay mb me)))
(push ov isearch-lazy-highlight-overlays)
@@ -4396,9 +4404,9 @@ Attempt to do the search exactly the way the pending Isearch would."
;; value `open' since then lazy-highlight
;; will open all overlays with matches.
(if (not (let ((search-invisible
- (if (eq search-invisible 'open)
+ (if (eq isearch-lazy-highlight-invisible 'open)
'can-be-opened
- search-invisible)))
+ isearch-lazy-highlight-invisible)))
(funcall isearch-filter-predicate mb me)))
(setq isearch-lazy-count-invisible
(1+ (or isearch-lazy-count-invisible 0)))
diff --git a/lisp/isearchb.el b/lisp/isearchb.el
index 85b0b636c6c..8cde93ed846 100644
--- a/lisp/isearchb.el
+++ b/lisp/isearchb.el
@@ -1,6 +1,6 @@
;;; isearchb.el --- a marriage between iswitchb and isearch -*- lexical-binding: t -*-
-;; Copyright (C) 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2004-2024 Free Software Foundation, Inc.
;; Author: John Wiegley <johnw@gnu.org>
;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/jit-lock.el b/lisp/jit-lock.el
index 452cbd1ca51..05c0bd847b3 100644
--- a/lisp/jit-lock.el
+++ b/lisp/jit-lock.el
@@ -1,6 +1,6 @@
;;; jit-lock.el --- just-in-time fontification -*- lexical-binding: t -*-
-;; Copyright (C) 1998, 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998, 2000-2024 Free Software Foundation, Inc.
;; Author: Gerd Moellmann <gerd@gnu.org>
;; Keywords: faces files
@@ -90,7 +90,8 @@ See also `jit-lock-stealth-nice'."
:type 'boolean)
-(defvaralias 'jit-lock-defer-contextually 'jit-lock-contextually)
+(define-obsolete-variable-alias 'jit-lock-defer-contextually
+ 'jit-lock-contextually "30.1")
(defcustom jit-lock-contextually 'syntax-driven
"If non-nil, fontification should be syntactically true.
If nil, refontification occurs only on lines that were modified. This
@@ -499,6 +500,7 @@ This applies to the buffer associated with marker START."
(setq start (point-min) end (max start end)))
;; Don't cause refontification (it's already been done), but just do
;; some random buffer change, so as to force redisplay.
+ (put-text-property start end 'fontified nil)
(put-text-property start end 'fontified t)))))
;;; Stealth fontification.
diff --git a/lisp/jka-cmpr-hook.el b/lisp/jka-cmpr-hook.el
index ad55475be25..ced998fafb6 100644
--- a/lisp/jka-cmpr-hook.el
+++ b/lisp/jka-cmpr-hook.el
@@ -1,6 +1,6 @@
;;; jka-cmpr-hook.el --- preloaded code to enable jka-compr.el -*- lexical-binding: t; -*-
-;; Copyright (C) 1993-1995, 1997, 1999-2000, 2002-2023 Free Software
+;; Copyright (C) 1993-1995, 1997, 1999-2000, 2002-2024 Free Software
;; Foundation, Inc.
;; Author: Jay K. Adams <jka@ece.cmu.edu>
diff --git a/lisp/jka-compr.el b/lisp/jka-compr.el
index 265df109669..8e6d14cc290 100644
--- a/lisp/jka-compr.el
+++ b/lisp/jka-compr.el
@@ -1,6 +1,6 @@
;;; jka-compr.el --- reading/writing/loading compressed files -*- lexical-binding: t; -*-
-;; Copyright (C) 1993-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1993-2024 Free Software Foundation, Inc.
;; Author: Jay K. Adams <jka@ece.cmu.edu>
;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/json.el b/lisp/json.el
index 5c2b46cdb4e..524a048f1d8 100644
--- a/lisp/json.el
+++ b/lisp/json.el
@@ -1,6 +1,6 @@
;;; json.el --- JavaScript Object Notation parser / generator -*- lexical-binding: t -*-
-;; Copyright (C) 2006-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2006-2024 Free Software Foundation, Inc.
;; Author: Theresa O'Connor <ted@oconnor.cx>
;; Version: 1.5
diff --git a/lisp/jsonrpc.el b/lisp/jsonrpc.el
index 52ffb220d8b..3f33443f321 100644
--- a/lisp/jsonrpc.el
+++ b/lisp/jsonrpc.el
@@ -1,10 +1,10 @@
;;; jsonrpc.el --- JSON-RPC library -*- lexical-binding: t; -*-
-;; Copyright (C) 2018-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2018-2024 Free Software Foundation, Inc.
;; Author: João Távora <joaotavora@gmail.com>
;; Keywords: processes, languages, extensions
-;; Version: 1.0.17
+;; Version: 1.0.23
;; Package-Requires: ((emacs "25.2"))
;; This is a GNU ELPA :core package. Avoid functionality that is not
@@ -51,6 +51,7 @@
(defclass jsonrpc-connection ()
((name
:accessor jsonrpc-name
+ :initform "anonymous"
:initarg :name
:documentation "A name for the connection")
(-request-dispatcher
@@ -64,31 +65,39 @@
:initarg :notification-dispatcher
:documentation "Dispatcher for remotely invoked notifications.")
(last-error
+ :initform nil
:accessor jsonrpc-last-error
:documentation "Last JSONRPC error message received from endpoint.")
- (-request-continuations
- :initform (make-hash-table)
- :accessor jsonrpc--request-continuations
- :documentation "A hash table of request ID to continuation lambdas.")
+ (-continuations
+ :initform nil
+ :accessor jsonrpc--continuations
+ :documentation "An alist of request IDs to continuation specs.")
(-events-buffer
+ :initform nil
:accessor jsonrpc--events-buffer
:documentation "A buffer pretty-printing the JSONRPC events")
- (-events-buffer-scrollback-size
- :initarg :events-buffer-scrollback-size
- :accessor jsonrpc--events-buffer-scrollback-size
- :documentation "Max size of events buffer. 0 disables, nil means infinite.")
+ (-events-buffer-config
+ :initform '(:size nil :format full)
+ :initarg :events-buffer-config
+ :documentation "Plist configuring the events buffer functions.")
(-deferred-actions
:initform (make-hash-table :test #'equal)
:accessor jsonrpc--deferred-actions
:documentation "Map (DEFERRED BUF) to (FN TIMER ID). FN is\
a saved DEFERRED `async-request' from BUF, to be sent not later\
than TIMER as ID.")
+ (-sync-request-alist ; bug#67945
+ :initform nil
+ :accessor jsonrpc--sync-request-alist
+ :documentation "List of ((ID [ANXIOUS...])) where ID refers \
+to a sync `jsonrpc-request' and each ANXIOUS to another completed\
+request that is higher up in the stack but couldn't run.")
(-next-request-id
:initform 0
:accessor jsonrpc--next-request-id
:documentation "Next number used for a request"))
:documentation "Base class representing a JSONRPC connection.
-The following initargs are accepted:
+The following keyword argument initargs are accepted:
:NAME (mandatory), a string naming the connection
@@ -102,7 +111,33 @@ RESULT) or signal an error of type `jsonrpc-error'.
:NOTIFICATION-DISPATCHER (optional), a function of three
arguments (CONN METHOD PARAMS) for handling JSONRPC
notifications. CONN, METHOD and PARAMS are the same as in
-:REQUEST-DISPATCHER.")
+:REQUEST-DISPATCHER.
+
+:EVENTS-BUFFER-CONFIG is a plist. Its `:size' stipulates the
+size of the log buffer (0 disables, nil means infinite). The
+`:format' property is a symbol for choosing the log entry format.")
+
+(cl-defmethod initialize-instance :after
+ ((c jsonrpc-connection) ((&key (events-buffer-scrollback-size
+ nil
+ e-b-s-s-supplied-p)
+ &allow-other-keys)
+ t))
+ (when e-b-s-s-supplied-p
+ (warn
+ "`:events-buffer-scrollback-size' deprecated. Use `events-buffer-config'.")
+ (with-slots ((plist -events-buffer-config)) c
+ (setf plist (copy-sequence plist)
+ plist (plist-put plist :size events-buffer-scrollback-size)))))
+
+(cl-defmethod slot-missing ((_c jsonrpc-connection)
+ (_n (eql :events-buffer-scrollback-size))
+ (_op (eql oset))
+ _)
+ ;; Yuck! But this just coerces EIEIO to backward-compatibly accept
+ ;; the :e-b-s-s initarg that is no longer associated with a slot
+ ;; #pineForCLOS..
+ )
;;; API mandatory
(cl-defgeneric jsonrpc-connection-send (conn &key id method params result error)
@@ -129,6 +164,41 @@ immediately."
(:method (_s _what) ;; by default all connections are ready
t))
+;;; API optional
+(cl-defgeneric jsonrpc-convert-to-endpoint (connection message subtype)
+ "Convert MESSAGE to JSONRPCesque message accepted by endpoint.
+MESSAGE is a plist, jsonrpc.el's internal representation of a
+JSONRPC message. SUBTYPE is one of `request', `reply' or
+`notification'.
+
+Return a plist to be serialized to JSON with `json-serialize' and
+transmitted to endpoint."
+ ;; TODO: describe representations and serialization in manual and
+ ;; link here.
+ (:method (_s message subtype)
+ `(:jsonrpc "2.0"
+ ,@(if (eq subtype 'reply)
+ ;; true JSONRPC doesn't have `method'
+ ;; fields in responses.
+ (cl-loop for (k v) on message by #'cddr
+ unless (eq k :method)
+ collect k and collect v)
+ message))))
+
+;;; API optional
+(cl-defgeneric jsonrpc-convert-from-endpoint (connection remote-message)
+ "Convert JSONRPC-esque REMOTE-MESSAGE to a plist.
+REMOTE-MESSAGE is a plist read with `json-parse'.
+
+Return a plist of jsonrpc.el's internal representation of a
+JSONRPC message."
+ ;; TODO: describe representations and serialization in manual and
+ ;; link here.
+ (:method (_s remote-message)
+ (cl-loop for (k v) on remote-message by #'cddr
+ unless (eq k :jsonrpc-json)
+ collect k and collect v)))
+
;;; Convenience
;;;
@@ -151,58 +221,107 @@ immediately."
(defun jsonrpc-forget-pending-continuations (connection)
"Stop waiting for responses from the current JSONRPC CONNECTION."
- (clrhash (jsonrpc--request-continuations connection)))
+ (setf (jsonrpc--continuations connection) nil))
(defvar jsonrpc-inhibit-debug-on-error nil
"Inhibit `debug-on-error' when answering requests.
Some extensions, notably ert.el, set `debug-on-error' to non-nil,
-which makes it hard to test the behaviour of catching the Elisp
+which makes it hard to test the behavior of catching the Elisp
error and replying to the endpoint with an JSONRPC-error. This
variable can be set around calls like `jsonrpc-request' to
circumvent that.")
-(defun jsonrpc-connection-receive (connection message)
- "Process MESSAGE just received from CONNECTION.
+(defun jsonrpc-connection-receive (conn foreign-message)
+ "Process FOREIGN-MESSAGE just received from CONN.
This function will destructure MESSAGE and call the appropriate
-dispatcher in CONNECTION."
- (cl-destructuring-bind (&key method id error params result _jsonrpc)
- message
- (let (continuations)
- (jsonrpc--log-event connection message 'server)
- (setf (jsonrpc-last-error connection) error)
- (cond
- (;; A remote request
- (and method id)
- (let* ((debug-on-error (and debug-on-error
- (not jsonrpc-inhibit-debug-on-error)))
- (reply
- (condition-case-unless-debug _ignore
- (condition-case oops
- `(:result ,(funcall (jsonrpc--request-dispatcher connection)
- connection (intern method) params))
- (jsonrpc-error
- `(:error
- (:code
- ,(or (alist-get 'jsonrpc-error-code (cdr oops)) -32603)
- :message ,(or (alist-get 'jsonrpc-error-message
- (cdr oops))
- "Internal error")))))
- (error
- '(:error (:code -32603 :message "Internal error"))))))
- (apply #'jsonrpc--reply connection id reply)))
- (;; A remote notification
- method
- (funcall (jsonrpc--notification-dispatcher connection)
- connection (intern method) params))
- (;; A remote response
- (setq continuations
- (and id (gethash id (jsonrpc--request-continuations connection))))
- (let ((timer (nth 2 continuations)))
- (when timer (cancel-timer timer)))
- (remhash id (jsonrpc--request-continuations connection))
- (if error (funcall (nth 1 continuations) error)
- (funcall (nth 0 continuations) result))))
- (jsonrpc--call-deferred connection))))
+dispatcher in CONN."
+ (cl-destructuring-bind (&rest whole &key method id error params result _jsonrpc)
+ (jsonrpc-convert-from-endpoint conn foreign-message)
+ (unwind-protect
+ (let* ((log-plist (list :json (plist-get foreign-message :jsonrpc-json)
+ :kind (cond ((and method id) 'request)
+ (method 'notification)
+ (id 'reply))
+ :message whole
+ :foreign-message foreign-message))
+ (response-p (and (null method) id))
+ (cont (and response-p (jsonrpc--remove conn id))))
+ (cl-remf foreign-message :jsonrpc-json)
+ ;; Do this pre-processing of the response so we can always
+ ;; log richer information _before_ any non-local calls
+ ;; further ahead. Putting the `jsonrpc--event' as
+ ;; an unwind-form would make us log after the fact.
+ (when cont
+ (pcase-let ((`(,_ ,method ,_ ,_ ,_) cont))
+ (if (keywordp method)
+ (setq method (substring (symbol-name method) 1)))
+ ;; TODO: also set the depth
+ (setq whole (plist-put whole :method method))))
+
+ ;; Do the logging
+ (apply #'jsonrpc--event conn 'server log-plist)
+ (with-slots (last-error
+ (rdispatcher -request-dispatcher)
+ (ndispatcher -notification-dispatcher)
+ (sr-alist -sync-request-alist))
+ conn
+ (setf last-error error)
+ (cond
+ (;; A remote response whose request has been canceled
+ ;; (i.e. timeout or C-g)
+ ;;
+ (and response-p (null cont))
+ (jsonrpc--event
+ conn 'internal
+ :log-text
+ (format "Response to request %s which has been canceled"
+ id)
+ :id id)
+ ;; TODO: food for thought: this seems to be also where
+ ;; notifying the server of the cancellation would come
+ ;; in.
+ )
+ (;; A remote response that can't run yet (bug#67945)
+ (and response-p
+ (and sr-alist (not (eq id (caar sr-alist)))))
+ (jsonrpc--event
+ conn 'internal
+ :log-text
+ (format "anxious continuation to %s can't run, held up by %s"
+ id
+ (mapcar #'car sr-alist)))
+ (push (cons cont (list result error))
+ (cdr (car sr-alist))))
+ (;; A remote response that can continue now
+ response-p
+ (jsonrpc--continue conn id cont result error))
+ (;; A remote request
+ (and method id)
+ (let* ((debug-on-error (and debug-on-error
+ (not jsonrpc-inhibit-debug-on-error)))
+ (reply
+ (condition-case-unless-debug _ignore
+ (condition-case oops
+ `(:result ,(funcall rdispatcher conn (intern method)
+ params))
+ (jsonrpc-error
+ `(:error
+ (:code
+ ,(or (alist-get 'jsonrpc-error-code (cdr oops))
+ -32603)
+ :message ,(or (alist-get 'jsonrpc-error-message
+ (cdr oops))
+ "Internal error")))))
+ (error
+ '(:error (:code -32603 :message "Internal error"))))))
+ (apply #'jsonrpc--reply conn id method reply)))
+ (;; A remote notification
+ method
+ (funcall ndispatcher conn (intern method) params))
+ (t
+ (jsonrpc--event conn 'internal
+ :log-text "Malformed message" )))))
+ (jsonrpc--call-deferred conn))))
;;; Contacting the remote endpoint
@@ -286,6 +405,7 @@ CANCEL-ON-INPUT-RETVAL. Any future replies (normal or error) are
ignored."
(let* ((tag (cl-gensym "jsonrpc-request-catch-tag")) id-and-timer
canceled
+ (throw-on-input nil)
(retval
(unwind-protect
(catch tag
@@ -294,6 +414,7 @@ ignored."
(apply
#'jsonrpc--async-request-1
connection method params
+ :sync-request t
:success-fn (lambda (result)
(unless canceled
(throw tag `(done ,result))))
@@ -316,15 +437,19 @@ ignored."
(setq canceled t))
`(canceled ,cancel-on-input-retval))
(t (while t (accept-process-output nil 30)))))
- ;; In normal operation, cancellation is handled by the
- ;; timeout function and response filter, but we still have
- ;; to protect against user-quit (C-g) or the
- ;; `cancel-on-input' case.
- (pcase-let* ((`(,id ,timer) id-and-timer))
- (remhash id (jsonrpc--request-continuations connection))
- (remhash (list deferred (current-buffer))
- (jsonrpc--deferred-actions connection))
- (when timer (cancel-timer timer))))))
+ ;; In normal operation, continuations for error/success is
+ ;; handled by `jsonrpc-continue'. Timeouts also remove
+ ;; the continuation...
+ (pcase-let* ((`(,id ,_) id-and-timer))
+ ;; ...but we still have to guard against exist explicit
+ ;; user-quit (C-g) or the `cancel-on-input' case, so
+ ;; discard the continuation.
+ (jsonrpc--remove connection id (list deferred (current-buffer)))
+ ;; ...finally, whatever may have happened to this sync
+ ;; request, it might have been holding up any outer
+ ;; "anxious" continuations. The following ensures we
+ ;; cll them.
+ (jsonrpc--continue connection id)))))
(when (eq 'error (car retval))
(signal 'jsonrpc-error
(cons
@@ -353,28 +478,32 @@ ignored."
:initarg :process :accessor jsonrpc--process
:documentation "Process object wrapped by the this connection.")
(-expected-bytes
+ :initform nil
:accessor jsonrpc--expected-bytes
:documentation "How many bytes declared by server.")
(-on-shutdown
:accessor jsonrpc--on-shutdown
:initform #'ignore
:initarg :on-shutdown
- :documentation "Function run when the process dies."))
+ :documentation "Function run when the process dies.")
+ (-autoport-inferior
+ :initform nil
+ :documentation "Used by `jsonrpc-autoport-bootstrap'."))
:documentation "A JSONRPC connection over an Emacs process.
The following initargs are accepted:
:PROCESS (mandatory), a live running Emacs process object or a
-function of no arguments producing one such object. The process
-represents either a pipe connection to locally running process or
-a stream connection to a network host. The remote endpoint is
-expected to understand JSONRPC messages with basic HTTP-style
-enveloping headers such as \"Content-Length:\".
+function producing one such object. If a function, it is passed
+the `jsonrpc-process-connection' object. The process represents
+either a pipe connection to locally running process or a stream
+connection to a network host. The remote endpoint is expected to
+understand JSONRPC messages with basic HTTP-style enveloping
+headers such as \"Content-Length:\".
:ON-SHUTDOWN (optional), a function of one argument, the
connection object, called when the process dies.")
-(cl-defmethod initialize-instance ((conn jsonrpc-process-connection) slots)
- (cl-call-next-method)
+(cl-defmethod initialize-instance :after ((conn jsonrpc-process-connection) slots)
(cl-destructuring-bind (&key ((:process proc)) name &allow-other-keys) slots
;; FIXME: notice the undocumented bad coupling in the stderr
;; buffer name, it must be named exactly like this we expect when
@@ -383,37 +512,22 @@ connection object, called when the process dies.")
;; could use a pipe with a process filter instead of
;; `after-change-functions'. Alternatively, we need a new initarg
;; (but maybe not a slot).
- (let ((calling-buffer (current-buffer)))
- (with-current-buffer (get-buffer-create (format "*%s stderr*" name))
- (let ((inhibit-read-only t)
- (hidden-name (concat " " (buffer-name))))
- (erase-buffer)
- (buffer-disable-undo)
- (add-hook
- 'after-change-functions
- (lambda (beg _end _pre-change-len)
- (cl-loop initially (goto-char beg)
- do (forward-line)
- when (bolp)
- for line = (buffer-substring
- (line-beginning-position 0)
- (line-end-position 0))
- do (with-current-buffer (jsonrpc-events-buffer conn)
- (goto-char (point-max))
- (let ((inhibit-read-only t))
- (insert (format "[stderr] %s\n" line))))
- until (eobp)))
- nil t)
- ;; If we are correctly coupled to the client, the process
- ;; now created should pick up the current stderr buffer,
- ;; which we immediately rename
- (setq proc (if (functionp proc)
- (with-current-buffer calling-buffer (funcall proc))
- proc))
- (ignore-errors (kill-buffer hidden-name))
- (rename-buffer hidden-name)
- (process-put proc 'jsonrpc-stderr (current-buffer))
- (setq buffer-read-only t))))
+ (let* ((stderr-buffer-name (format "*%s stderr*" name))
+ (stderr-buffer (jsonrpc--forwarding-buffer stderr-buffer-name "[stderr] " conn))
+ (hidden-name (concat " " stderr-buffer-name)))
+ ;; If we are correctly coupled to the client, the process now
+ ;; created should pick up the `stderr-buffer' just created, which
+ ;; we immediately rename
+ (setq proc (if (functionp proc)
+ (if (zerop (cdr (func-arity proc)))
+ (funcall proc)
+ (funcall proc conn))
+ proc))
+ (with-current-buffer stderr-buffer
+ (ignore-errors (kill-buffer hidden-name))
+ (rename-buffer hidden-name)
+ (setq buffer-read-only t))
+ (process-put proc 'jsonrpc-stderr stderr-buffer))
(setf (jsonrpc--process conn) proc)
(set-process-buffer proc (get-buffer-create (format " *%s output*" name)))
(set-process-filter proc #'jsonrpc--process-filter)
@@ -429,29 +543,42 @@ connection object, called when the process dies.")
(cl-defmethod jsonrpc-connection-send ((connection jsonrpc-process-connection)
&rest args
&key
- _id
+ id
method
_params
- _result
- _error
+ (_result nil result-supplied-p)
+ error
_partial)
"Send MESSAGE, a JSON object, to CONNECTION."
(when method
- (plist-put args :method
- (cond ((keywordp method) (substring (symbol-name method) 1))
- ((and method (symbolp method)) (symbol-name method)))))
- (let* ( (message `(:jsonrpc "2.0" ,@args))
- (json (jsonrpc--json-encode message))
- (headers
- `(("Content-Length" . ,(format "%d" (string-bytes json)))
- ;; ("Content-Type" . "application/vscode-jsonrpc; charset=utf-8")
- )))
+ ;; sanitize method into a string
+ (setq args
+ (plist-put args :method
+ (cond ((keywordp method) (substring (symbol-name method) 1))
+ ((symbolp method) (symbol-name method))
+ ((stringp method) method)
+ (t (error "[jsonrpc] invalid method %s" method))))))
+ (let* ((kind (cond ((or result-supplied-p error) 'reply)
+ (id 'request)
+ (method 'notification)))
+ (converted (jsonrpc-convert-to-endpoint connection args kind))
+ (json (jsonrpc--json-encode converted))
+ (headers
+ `(("Content-Length" . ,(format "%d" (string-bytes json)))
+ ;; ("Content-Type" . "application/vscode-jsonrpc; charset=utf-8")
+ )))
(process-send-string
(jsonrpc--process connection)
(cl-loop for (header . value) in headers
concat (concat header ": " value "\r\n") into header-section
finally return (format "%s\r\n%s" header-section json)))
- (jsonrpc--log-event connection message 'client)))
+ (jsonrpc--event
+ connection
+ 'client
+ :json json
+ :kind kind
+ :message args
+ :foreign-message converted)))
(defun jsonrpc-process-type (conn)
"Return the `process-type' of JSONRPC connection CONN."
@@ -518,65 +645,56 @@ With optional CLEANUP, kill any associated buffers."
"Encode OBJECT into a JSON string.")
(cl-defun jsonrpc--reply
- (connection id &key (result nil result-supplied-p) (error nil error-supplied-p))
+ (connection id method &key (result nil result-supplied-p) (error nil error-supplied-p))
"Reply to CONNECTION's request ID with RESULT or ERROR."
(apply #'jsonrpc-connection-send connection
`(:id ,id
,@(and result-supplied-p `(:result ,result))
- ,@(and error-supplied-p `(:error ,error)))))
+ ,@(and error-supplied-p `(:error ,error))
+ :method ,method)))
(defun jsonrpc--call-deferred (connection)
"Call CONNECTION's deferred actions, who may again defer themselves."
(when-let ((actions (hash-table-values (jsonrpc--deferred-actions connection))))
- (jsonrpc--debug connection `(:maybe-run-deferred
- ,(mapcar (apply-partially #'nth 2) actions)))
+ (jsonrpc--event
+ connection 'internal
+ :log-text (format "re-attempting deferred requests %s"
+ (mapcar (apply-partially #'nth 2) actions)))
(mapc #'funcall (mapcar #'car actions))))
(defun jsonrpc--process-sentinel (proc change)
"Called when PROC undergoes CHANGE."
(let ((connection (process-get proc 'jsonrpc-connection)))
- (jsonrpc--debug connection `(:message "Connection state changed" :change ,change))
+ (jsonrpc--debug connection "Connection state change: `%s'" change)
(when (not (process-live-p proc))
(with-current-buffer (jsonrpc-events-buffer connection)
(let ((inhibit-read-only t))
(insert "\n----------b---y---e---b---y---e----------\n")))
;; Cancel outstanding timers
- (maphash (lambda (_id triplet)
- (pcase-let ((`(,_success ,_error ,timeout) triplet))
- (when timeout (cancel-timer timeout))))
- (jsonrpc--request-continuations connection))
+ (mapc (jsonrpc-lambda (_id _method _success-fn _error-fn timer)
+ (when timer (cancel-timer timer)))
+ (jsonrpc--continuations connection))
+ (maphash (lambda (_ triplet)
+ (pcase-let ((`(,_ ,timer ,_) triplet))
+ (when timer (cancel-timer timer))))
+ (jsonrpc--deferred-actions connection))
(process-put proc 'jsonrpc-sentinel-cleanup-started t)
(unwind-protect
;; Call all outstanding error handlers
- (maphash (lambda (_id triplet)
- (pcase-let ((`(,_success ,error ,_timeout) triplet))
- (funcall error '(:code -1 :message "Server died"))))
- (jsonrpc--request-continuations connection))
+ (mapc (jsonrpc-lambda (_id _method _success-fn error-fn _timer)
+ (funcall error-fn '(:code -1 :message "Server died")))
+ (jsonrpc--continuations connection))
(jsonrpc--message "Server exited with status %s" (process-exit-status proc))
(delete-process proc)
+ (when-let (p (slot-value connection '-autoport-inferior)) (delete-process p))
(funcall (jsonrpc--on-shutdown connection) connection)))))
-(defvar jsonrpc--in-process-filter nil
- "Non-nil if inside `jsonrpc--process-filter'.")
-
(cl-defun jsonrpc--process-filter (proc string)
"Called when new data STRING has arrived for PROC."
- (when jsonrpc--in-process-filter
- ;; Problematic recursive process filters may happen if
- ;; `jsonrpc--connection-receive', called by us, eventually calls
- ;; client code which calls `process-send-string' (which see) to,
- ;; say send a follow-up message. If that happens to writes enough
- ;; bytes for pending output to be received, we will lose JSONRPC
- ;; messages. In that case, remove recursiveness by re-scheduling
- ;; ourselves to run from within a timer as soon as possible
- ;; (bug#60088)
- (run-at-time 0 nil #'jsonrpc--process-filter proc string)
- (cl-return-from jsonrpc--process-filter))
(when (buffer-live-p (process-buffer proc))
(with-current-buffer (process-buffer proc)
- (let* ((jsonrpc--in-process-filter t)
- (connection (process-get proc 'jsonrpc-connection))
- (expected-bytes (jsonrpc--expected-bytes connection)))
+ (let* ((conn (process-get proc 'jsonrpc-connection))
+ (expected-bytes (jsonrpc--expected-bytes conn)))
;; Insert the text, advancing the process marker.
;;
(save-excursion
@@ -611,24 +729,27 @@ With optional CLEANUP, kill any associated buffers."
expected-bytes)
(let* ((message-end (byte-to-position
(+ (position-bytes (point))
- expected-bytes))))
+ expected-bytes)))
+ message
+ )
(unwind-protect
(save-restriction
(narrow-to-region (point) message-end)
- (let* ((json-message
- (condition-case-unless-debug oops
- (jsonrpc--json-read)
- (error
- (jsonrpc--warn "Invalid JSON: %s %s"
- (cdr oops) (buffer-string))
- nil))))
- (when json-message
- ;; Process content in another
- ;; buffer, shielding proc buffer from
- ;; tamper
- (with-temp-buffer
- (jsonrpc-connection-receive connection
- json-message)))))
+ (setq message
+ (condition-case-unless-debug oops
+ (jsonrpc--json-read)
+ (error
+ (jsonrpc--warn "Invalid JSON: %s %s"
+ (cdr oops) (buffer-string))
+ nil)))
+ (when message
+ (setq message
+ (plist-put message :jsonrpc-json
+ (buffer-string)))
+ (process-put proc 'jsonrpc-mqueue
+ (nconc (process-get proc
+ 'jsonrpc-mqueue)
+ (list message)))))
(goto-char message-end)
(let ((inhibit-read-only t))
(delete-region (point-min) (point)))
@@ -637,9 +758,73 @@ With optional CLEANUP, kill any associated buffers."
;; Message is still incomplete
;;
(setq done :waiting-for-more-bytes-in-this-message))))))))
- ;; Saved parsing state for next visit to this filter
+ ;; Saved parsing state for next visit to this filter, which
+ ;; may well be a recursive one stemming from the tail call
+ ;; to `jsonrpc-connection-receive' below (bug#60088).
;;
- (setf (jsonrpc--expected-bytes connection) expected-bytes))))))
+ (setf (jsonrpc--expected-bytes conn) expected-bytes)
+ ;; Now, time to notify user code of one or more messages in
+ ;; order. Very often `jsonrpc-connection-receive' will exit
+ ;; non-locally (typically the reply to a request), so do
+ ;; this all this processing in top-level loops timer.
+ (cl-loop
+ for msg = (pop (process-get proc 'jsonrpc-mqueue)) while msg
+ do (run-at-time 0 nil
+ (lambda (m) (with-temp-buffer
+ (jsonrpc-connection-receive conn m)))
+ msg)))))))
+
+(defun jsonrpc--remove (conn id &optional deferred-spec)
+ "Cancel CONN's continuations for ID, including its timer, if it exists.
+Also cancel \"deferred actions\" if DEFERRED-SPEC.
+Return the full continuation (ID SUCCESS-FN ERROR-FN TIMER)"
+ (with-slots ((conts -continuations) (defs -deferred-actions)) conn
+ (if deferred-spec (remhash deferred-spec defs))
+ (when-let ((ass (assq id conts)))
+ (cl-destructuring-bind (_ _ _ _ timer) ass
+ (cancel-timer timer))
+ (setf conts (delete ass conts))
+ ass)))
+
+(defun jsonrpc--schedule (conn id method success-fn error-fn timer)
+ (push (list id method success-fn error-fn timer)
+ (jsonrpc--continuations conn)))
+
+(defun jsonrpc--continue (conn id &optional cont result error)
+ (pcase-let* ((`(,cont-id ,_method ,success-fn ,error-fn ,_timer)
+ cont)
+ (head (pop (jsonrpc--sync-request-alist conn)))
+ (anxious (cdr head)))
+ (cond
+ (anxious
+ (when (not (= (car head) id)) ; sanity check
+ (error "internal error: please report this bug"))
+ ;; If there are "anxious" `jsonrpc-request' continuations
+ ;; that should already have been run, they should run now.
+ ;; The main continuation -- if it exists -- should run
+ ;; before them. This order is important to preserve the
+ ;; throw to the catch tags in `jsonrpc-request' in
+ ;; order (bug#67945).
+ (cl-flet ((later (f arg) (run-at-time 0 nil f arg)))
+ (when cont-id
+ (if error (later error-fn error)
+ (later success-fn result)))
+ (cl-loop
+ for (acont ares aerr) in anxious
+ for (anx-id _method success-fn error-fn) = acont
+ do (jsonrpc--event
+ conn 'internal
+ :log-text (format "anxious continuation to %s running now" anx-id))
+ if aerr do (later error-fn aerr)
+ else do (later success-fn ares))))
+ (cont-id
+ ;; Else, just run the normal one, with plain funcall.
+ (if error (funcall error-fn error)
+ (funcall success-fn result)))
+ (t
+ ;; For clarity. This happens if the `jsonrpc-request' was
+ ;; canceled
+ ))))
(cl-defun jsonrpc--async-request-1 (connection
method
@@ -647,8 +832,9 @@ With optional CLEANUP, kill any associated buffers."
&rest args
&key success-fn error-fn timeout-fn
(timeout jsonrpc-default-request-timeout)
- (deferred nil))
- "Does actual work for `jsonrpc-async-request'.
+ (deferred nil)
+ (sync-request nil))
+ "Helper for `jsonrpc-request' and `jsonrpc-async-request'.
Return a list (ID TIMER). ID is the new request's ID, or nil if
the request was deferred. TIMER is a timer object set (or nil, if
@@ -658,60 +844,69 @@ TIMEOUT is nil)."
(and deferred (gethash (list deferred buf)
(jsonrpc--deferred-actions connection))))
(id (or old-id (cl-incf (jsonrpc--next-request-id connection))))
- (make-timer
- (lambda ( )
+ (maybe-timer
+ (lambda ()
(when timeout
- (run-with-timer
- timeout nil
- (lambda ()
- (remhash id (jsonrpc--request-continuations connection))
- (remhash (list deferred buf)
- (jsonrpc--deferred-actions connection))
- (if timeout-fn (funcall timeout-fn)
- (jsonrpc--debug
- connection `(:timed-out ,method :id ,id
- :params ,params)))))))))
+ (or timer
+ (setq
+ timer
+ (run-with-timer
+ timeout nil
+ (lambda ()
+ (jsonrpc--remove connection id (list deferred buf))
+ (jsonrpc--event
+ connection 'internal
+ :log-text (format "timed-out request '%s'" method)
+ :id id)
+ (when timeout-fn (funcall timeout-fn))))))))))
(when deferred
(if (jsonrpc-connection-ready-p connection deferred)
;; Server is ready, we jump below and send it immediately.
(remhash (list deferred buf) (jsonrpc--deferred-actions connection))
;; Otherwise, save in `jsonrpc--deferred-actions' and exit non-locally
(unless old-id
- (jsonrpc--debug connection `(:deferring ,method :id ,id :params
- ,params)))
+ (jsonrpc--event
+ connection 'internal
+ :log-text (format "deferring request '%s'" method)
+ :id id))
(puthash (list deferred buf)
(list (lambda ()
(when (buffer-live-p buf)
(with-current-buffer buf
(save-excursion (goto-char point)
- (apply #'jsonrpc-async-request
+ (apply #'jsonrpc--async-request-1
connection
method params args)))))
- (or timer (setq timer (funcall make-timer))) id)
+ (funcall maybe-timer) id)
(jsonrpc--deferred-actions connection))
(cl-return-from jsonrpc--async-request-1 (list id timer))))
- ;; Really send it
+ ;; Really send it thru the wire
;;
(jsonrpc-connection-send connection
:id id
:method method
:params params)
- (puthash id
- (list (or success-fn
- (lambda (&rest _ignored)
- (jsonrpc--debug
- connection (list :message "success ignored"
- :id id))))
- (or error-fn
- (jsonrpc-lambda (&key code message &allow-other-keys)
- (jsonrpc--debug
- connection (list
- :message
- (format "error ignored, status set (%s)"
- message)
- :id id :error code))))
- (setq timer (funcall make-timer)))
- (jsonrpc--request-continuations connection))
+ ;; Setup some control structures
+ ;;
+ (when sync-request
+ (push (list id) (jsonrpc--sync-request-alist connection)))
+
+ (jsonrpc--schedule
+ connection id method
+ (or success-fn
+ (lambda (&rest _ignored)
+ (jsonrpc--event
+ connection 'internal
+ :log-text (format "success ignored")
+ :id id)))
+ (or error-fn
+ (jsonrpc-lambda (&key code message &allow-other-keys)
+ (jsonrpc--event
+ connection 'internal
+ :log-text (format "error %s ignored: %s ignored"
+ code message)
+ :id id)))
+ (funcall maybe-timer))
(list id timer)))
(defun jsonrpc--message (format &rest args)
@@ -720,10 +915,11 @@ TIMEOUT is nil)."
(defun jsonrpc--debug (server format &rest args)
"Debug message for SERVER with FORMAT and ARGS."
- (jsonrpc--log-event
- server (if (stringp format)
- `(:message ,(apply #'format format args))
- format)))
+ (with-current-buffer (jsonrpc-events-buffer server)
+ (jsonrpc--log-event
+ server 'internal
+ :log-text (apply #'format format args)
+ :type 'debug)))
(defun jsonrpc--warn (format &rest args)
"Warning message with FORMAT and ARGS."
@@ -733,44 +929,215 @@ TIMEOUT is nil)."
(apply #'format format args)
:warning)))
-(defun jsonrpc--log-event (connection message &optional type)
- "Log a JSONRPC-related event.
-CONNECTION is the current connection. MESSAGE is a JSON-like
-plist. TYPE is a symbol saying if this is a client or server
-originated."
- (let ((max (jsonrpc--events-buffer-scrollback-size connection)))
+(cl-defun jsonrpc--event (connection
+ origin
+ &rest plist
+ &key _kind _json _message _foreign-message _log-text
+ &allow-other-keys)
+ (with-current-buffer (jsonrpc-events-buffer connection)
+ (run-hook-wrapped 'jsonrpc-event-hook
+ (lambda (fn)
+ (condition-case oops
+ (apply fn connection origin plist)
+ (error
+ (jsonrpc--message "event hook '%s' errored (%s). Removing it"
+ fn oops)
+ (remove-hook 'jsonrpc-event-hook fn)))))))
+
+(defvar jsonrpc-event-hook (list #'jsonrpc--log-event)
+ "Hook run when JSON-RPC events are emitted.
+This hooks runs in the events buffer of every `jsonrpc-connection'
+when an event is originated by either endpoint. Each hook function
+is passed the arguments described by the lambda list:
+
+ (CONNECTION ORIGIN &key JSON KIND MESSAGE FOREIGN-MESSAGE LOG-TEXT
+ &allow-other-keys)
+
+ CONNECTION the `jsonrpc-connection' instance.
+ ORIGIN one of the symbols `client' ,`server'.
+ JSON the raw JSON string content.
+ KIND one of the symbols `request' ,`notification',
+ `reply'.
+ MESSAGE a plist representing the exchanged message in
+ jsonrpc.el's internal format
+ FOREIGN-MESSAGE a plist representing the exchanged message in
+ the remote endpoint's format.
+ LOG-TEXT text used for events of `internal' origin.
+ ID id of a message that this event refers to.
+ TYPE `error', `debug' or the default `info'.
+
+Except for CONNECTION and ORIGIN all other keys are optional.
+Unlisted keys may appear in the plist.
+
+Do not use this hook to write JSON-RPC protocols, use other parts
+of the API instead.")
+
+(cl-defun jsonrpc--log-event (connection origin
+ &key _kind message
+ foreign-message log-text json
+ type ((:id ref-id))
+ &allow-other-keys)
+ "Log a JSONRPC-related event. Installed in `jsonrpc-event-hook'."
+ (let* ((props (slot-value connection '-events-buffer-config))
+ (max (plist-get props :size))
+ (format (plist-get props :format)))
(when (or (null max) (cl-plusp max))
- (with-current-buffer (jsonrpc-events-buffer connection)
- (cl-destructuring-bind (&key method id error &allow-other-keys) message
- (let* ((inhibit-read-only t)
- (subtype (cond ((and method id) 'request)
- (method 'notification)
- (id 'reply)
- (t 'message)))
- (type
- (concat (format "%s" (or type 'internal))
- (if type
- (format "-%s" subtype)))))
- (goto-char (point-max))
- (prog1
- (let ((msg (format "[%s]%s%s %s:\n%s"
- type
- (if id (format " (id:%s)" id) "")
- (if error " ERROR" "")
- (current-time-string)
- (pp-to-string message))))
- (when error
- (setq msg (propertize msg 'face 'error)))
- (insert-before-markers msg))
- ;; Trim the buffer if it's too large
- (when max
- (save-excursion
- (goto-char (point-min))
- (while (> (buffer-size) max)
- (delete-region (point) (progn (forward-line 1)
- (forward-sexp 1)
- (forward-line 2)
- (point)))))))))))))
+ (cl-destructuring-bind (&key method id error &allow-other-keys) message
+ (let* ((inhibit-read-only t)
+ (depth (length
+ (jsonrpc--sync-request-alist connection)))
+ (preamble (format "[jsonrpc] %s[%s]%s "
+ (pcase type ('error "E") ('debug "D")
+ (_ (pcase origin
+ ('internal "i")
+ (_ "e"))))
+ (format-time-string "%H:%M:%S.%3N")
+ (if (eq origin 'internal)
+ (if ref-id (format " [%s]" ref-id) "")
+ (format " %s%s %s%s"
+ (make-string (* 2 depth) ? )
+ (pcase origin
+ ('client "-->")
+ ('server "<--")
+ (_ ""))
+ (or method "")
+ (if id (format "[%s]" id) "")))))
+ (msg
+ (cond ((eq format 'full)
+ (format "%s%s\n" preamble (or json log-text)))
+ ((eq format 'short)
+ (format "%s%s\n" preamble (or log-text "")))
+ (t
+ (format "%s%s" preamble
+ (or (and foreign-message
+ (concat "\n" (pp-to-string
+ foreign-message)))
+ (concat log-text "\n")))))))
+ (goto-char (point-max))
+ ;; XXX: could use `run-at-time' to delay server logs
+ ;; slightly to play nice with verbose servers' stderr.
+ (when error
+ (setq msg (propertize msg 'face 'error)))
+ (insert-before-markers msg)
+ ;; Trim the buffer if it's too large
+ (when max
+ (save-excursion
+ (goto-char (point-min))
+ (while (> (buffer-size) max)
+ (delete-region (point) (progn (forward-line 1)
+ (forward-sexp 1)
+ (forward-line 2)
+ (point)))))))))))
+
+(defun jsonrpc--forwarding-buffer (name prefix conn)
+ "Helper for `jsonrpc-process-connection' helpers.
+Make a stderr buffer named NAME, forwarding lines prefixed by
+PREFIX to CONN's events buffer."
+ (with-current-buffer (get-buffer-create name)
+ (let ((inhibit-read-only t))
+ (fundamental-mode)
+ (erase-buffer)
+ (buffer-disable-undo)
+ (add-hook
+ 'after-change-functions
+ (lambda (beg _end _pre-change-len)
+ (cl-loop initially (goto-char beg)
+ do (forward-line)
+ when (bolp)
+ for line = (buffer-substring
+ (line-beginning-position 0)
+ (line-end-position 0))
+ do (with-current-buffer (jsonrpc-events-buffer conn)
+ (goto-char (point-max))
+ (let ((inhibit-read-only t))
+ (insert
+ (propertize (format "%s %s\n" prefix line)
+ 'face 'shadow))))
+ until (eobp)))
+ nil t))
+ (current-buffer)))
+
+
+;;;; More convenience utils
+(cl-defun jsonrpc-autoport-bootstrap (name contact
+ &key connect-args)
+ "Use CONTACT to start network server, then connect to it.
+
+Return function suitable for the :PROCESS initarg of
+`jsonrpc-process-connection' (which see).
+
+CONTACT is a list where all the elements are strings except for
+one, which is usuallky the keyword `:autoport'.
+
+When the returned function is called it will start a program
+using a command based on CONTACT, where `:autoport' is
+substituted by a locally free network port. Thereafter, a
+network is made to this port.
+
+Instead of the keyword `:autoport', a cons cell (:autoport
+FORMAT-FN) is also accepted. In that case FORMAT-FN is passed
+the port number and should return a string used for the
+substitution.
+
+The internal processes and control buffers are named after NAME.
+
+CONNECT-ARGS are passed as additional arguments to
+`open-network-stream'."
+ (lambda (conn)
+ (let* ((port-probe (make-network-process :name "jsonrpc-port-probe-dummy"
+ :server t
+ :host "localhost"
+ :service 0))
+ (port-number (unwind-protect
+ (process-contact port-probe :service)
+ (delete-process port-probe)))
+ (inferior-buffer (jsonrpc--forwarding-buffer
+ (format " *%s inferior output*" name)
+ "[inferior]"
+ conn))
+ (cmd (cl-loop for e in contact
+ if (eq e :autoport) collect (format "%s" port-number)
+ else if (eq (car-safe e) :autoport)
+ collect (funcall (cdr e) port-number)
+ else collect e))
+ inferior np)
+ (unwind-protect
+ (progn
+ (message "[jsonrpc] Attempting to start `%s'"
+ (string-join cmd " "))
+ (setq inferior
+ (make-process
+ :name (format "inferior (%s)" name)
+ :buffer inferior-buffer
+ :noquery t
+ :command cmd))
+ (setq np
+ (cl-loop
+ repeat 10 for i from 0
+ do (accept-process-output nil 0.5)
+ while (process-live-p inferior)
+ do (message
+ "[jsonrpc] %sTrying to connect to localhost:%s (attempt %s)"
+ (if (zerop i) "Started. " "")
+ port-number (1+ i))
+ thereis (ignore-errors
+ (apply #'open-network-stream
+ (format "autostart (%s)" name)
+ nil
+ "localhost" port-number connect-args))))
+ (setf (slot-value conn '-autoport-inferior) inferior)
+ np)
+ (cond ((and (process-live-p np)
+ (process-live-p inferior))
+ (message "[jsonrpc] Done, connected to %s!" port-number))
+ (t
+ (when inferior (delete-process inferior))
+ (when np (delete-process np))
+ (error "[jsonrpc] Could not start and/or connect")))))))
+
+(defun jsonrpc-continuation-count (conn)
+ "Number of outstanding continuations for CONN."
+ (length (jsonrpc--continuations conn)))
(provide 'jsonrpc)
;;; jsonrpc.el ends here
diff --git a/lisp/kermit.el b/lisp/kermit.el
index 7ee75141f6c..f632e784204 100644
--- a/lisp/kermit.el
+++ b/lisp/kermit.el
@@ -1,6 +1,6 @@
;;; kermit.el --- additions to shell mode for use with kermit -*- lexical-binding: t -*-
-;; Copyright (C) 1988, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1988, 2001-2024 Free Software Foundation, Inc.
;; Author: Jeff Norden <jeff@colgate.csnet>
;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/keymap.el b/lisp/keymap.el
index 017b2d6ead0..065c59da74c 100644
--- a/lisp/keymap.el
+++ b/lisp/keymap.el
@@ -1,6 +1,10 @@
;;; keymap.el --- Keymap functions -*- lexical-binding: t; -*-
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
+
+;; Maintainer: emacs-devel@gnu.org
+;; Keywords: internal
+;; Package: emacs
;; This file is part of GNU Emacs.
@@ -378,15 +382,17 @@ which is
This function creates a `keyboard-translate-table' if necessary
and then modifies one entry in it.
-Both KEY and TO should be specified by strings that satisfy `key-valid-p'."
+Both FROM and TO should be specified by strings that satisfy `key-valid-p'."
(declare (compiler-macro
(lambda (form) (keymap--compile-check from to) form)))
(keymap--check from)
(keymap--check to)
(or (char-table-p keyboard-translate-table)
(setq keyboard-translate-table
- (make-char-table 'keyboard-translate-table nil)))
- (aset keyboard-translate-table (key-parse from) (key-parse to)))
+ (make-char-table 'keyboard-translate-table nil)))
+ (aset keyboard-translate-table
+ (aref (key-parse from) 0)
+ (aref (key-parse to) 0)))
(defun keymap-lookup (keymap key &optional accept-default no-remap position)
"Return the binding for command KEY in KEYMAP.
diff --git a/lisp/kmacro.el b/lisp/kmacro.el
index 588b2d14943..897ebf14330 100644
--- a/lisp/kmacro.el
+++ b/lisp/kmacro.el
@@ -1,6 +1,6 @@
;;; kmacro.el --- enhanced keyboard macros -*- lexical-binding: t -*-
-;; Copyright (C) 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2024 Free Software Foundation, Inc.
;; Author: Kim F. Storm <storm@cua.dk>
;; Keywords: keyboard convenience
diff --git a/lisp/language/china-util.el b/lisp/language/china-util.el
index 97301576ab8..f9533d7d480 100644
--- a/lisp/language/china-util.el
+++ b/lisp/language/china-util.el
@@ -1,6 +1,6 @@
;;; china-util.el --- utilities for Chinese -*- lexical-binding: t; -*-
-;; Copyright (C) 1995, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1995, 2001-2024 Free Software Foundation, Inc.
;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
;; 2005, 2006, 2007, 2008, 2009, 2010, 2011
;; National Institute of Advanced Industrial Science and Technology (AIST)
diff --git a/lisp/language/chinese.el b/lisp/language/chinese.el
index e35f3f179ad..97a8257db7e 100644
--- a/lisp/language/chinese.el
+++ b/lisp/language/chinese.el
@@ -1,6 +1,6 @@
;;; chinese.el --- support for Chinese -*- coding: utf-8; lexical-binding: t; -*-
-;; Copyright (C) 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2024 Free Software Foundation, Inc.
;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
;; 2005, 2006, 2007, 2008, 2009, 2010, 2011
;; National Institute of Advanced Industrial Science and Technology (AIST)
diff --git a/lisp/language/cyril-util.el b/lisp/language/cyril-util.el
index 0095338af45..ba3df9af02f 100644
--- a/lisp/language/cyril-util.el
+++ b/lisp/language/cyril-util.el
@@ -1,6 +1,6 @@
;;; cyril-util.el --- utilities for Cyrillic scripts -*- lexical-binding: t; -*-
-;; Copyright (C) 1997-1998, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997-1998, 2001-2024 Free Software Foundation, Inc.
;; Keywords: mule, multilingual, Cyrillic
diff --git a/lisp/language/cyrillic.el b/lisp/language/cyrillic.el
index 2b32304c829..87a67915878 100644
--- a/lisp/language/cyrillic.el
+++ b/lisp/language/cyrillic.el
@@ -1,6 +1,6 @@
;;; cyrillic.el --- support for Cyrillic -*- coding: utf-8; lexical-binding: t; -*-
-;; Copyright (C) 1997-1998, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997-1998, 2001-2024 Free Software Foundation, Inc.
;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
;; 2005, 2006, 2007, 2008, 2009, 2010, 2011
;; National Institute of Advanced Industrial Science and Technology (AIST)
diff --git a/lisp/language/czech.el b/lisp/language/czech.el
index e3fe42026a5..838d024851e 100644
--- a/lisp/language/czech.el
+++ b/lisp/language/czech.el
@@ -1,6 +1,6 @@
;;; czech.el --- support for Czech -*- coding: utf-8; lexical-binding: t -*-
-;; Copyright (C) 1998, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998, 2001-2024 Free Software Foundation, Inc.
;; Author: Milan Zamazal <pdm@zamazal.org>
;; Maintainer: Pavel Janík <Pavel@Janik.cz>
diff --git a/lisp/language/english.el b/lisp/language/english.el
index b8334d90863..e223c4aa0cb 100644
--- a/lisp/language/english.el
+++ b/lisp/language/english.el
@@ -1,6 +1,6 @@
;;; english.el --- support for English -*- lexical-binding: t; -*-
-;; Copyright (C) 1997, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997, 2001-2024 Free Software Foundation, Inc.
;; Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
;; 2006, 2007, 2008, 2009, 2010, 2011
;; National Institute of Advanced Industrial Science and Technology (AIST)
diff --git a/lisp/language/ethio-util.el b/lisp/language/ethio-util.el
index fe61a4e8560..50701f830ed 100644
--- a/lisp/language/ethio-util.el
+++ b/lisp/language/ethio-util.el
@@ -1,6 +1,6 @@
;;; ethio-util.el --- utilities for Ethiopic -*- coding: utf-8-emacs; lexical-binding: t; -*-
-;; Copyright (C) 1997-1998, 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997-1998, 2002-2024 Free Software Foundation, Inc.
;; Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
;; 2006, 2007, 2008, 2009, 2010, 2011
;; National Institute of Advanced Industrial Science and Technology (AIST)
diff --git a/lisp/language/ethiopic.el b/lisp/language/ethiopic.el
index 475d569d56d..7490f5351c8 100644
--- a/lisp/language/ethiopic.el
+++ b/lisp/language/ethiopic.el
@@ -1,6 +1,6 @@
;;; ethiopic.el --- support for Ethiopic -*- coding: utf-8-emacs; lexical-binding: t; -*-
-;; Copyright (C) 1997, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997, 2001-2024 Free Software Foundation, Inc.
;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
;; 2005, 2006, 2007, 2008, 2009, 2010, 2011
;; National Institute of Advanced Industrial Science and Technology (AIST)
diff --git a/lisp/language/european.el b/lisp/language/european.el
index d65acb95979..ced070410b4 100644
--- a/lisp/language/european.el
+++ b/lisp/language/european.el
@@ -1,6 +1,6 @@
;;; european.el --- support for European languages -*- coding: utf-8; lexical-binding: t; -*-
-;; Copyright (C) 1997-1998, 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997-1998, 2000-2024 Free Software Foundation, Inc.
;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
;; 2005, 2006, 2007, 2008, 2009, 2010, 2011
;; National Institute of Advanced Industrial Science and Technology (AIST)
diff --git a/lisp/language/georgian.el b/lisp/language/georgian.el
index 32d9425c09a..1308b0a8efc 100644
--- a/lisp/language/georgian.el
+++ b/lisp/language/georgian.el
@@ -1,6 +1,6 @@
;;; georgian.el --- language support for Georgian -*- lexical-binding: t -*-
-;; Copyright (C) 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2024 Free Software Foundation, Inc.
;; Author: Dave Love <fx@gnu.org>
;; Keywords: i18n
diff --git a/lisp/language/greek.el b/lisp/language/greek.el
index 0c3e5e0633f..849c45e5af8 100644
--- a/lisp/language/greek.el
+++ b/lisp/language/greek.el
@@ -1,6 +1,6 @@
;;; greek.el --- support for Greek -*- lexical-binding: t -*-
-;; Copyright (C) 2002, 2013-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002, 2013-2024 Free Software Foundation, Inc.
;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
;; 2005, 2006, 2007, 2008, 2009, 2010, 2011
;; National Institute of Advanced Industrial Science and Technology (AIST)
diff --git a/lisp/language/hanja-util.el b/lisp/language/hanja-util.el
index be0364b1c23..c47ceb5fc88 100644
--- a/lisp/language/hanja-util.el
+++ b/lisp/language/hanja-util.el
@@ -1,6 +1,6 @@
;;; hanja-util.el --- Korean Hanja util module -*- lexical-binding: t; -*-
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
;; Author: Jihyun Cho <jihyun.jo@gmail.com>
;; Keywords: multilingual, input method, Korean, Hanja
@@ -6437,7 +6437,7 @@ character. This variable is initialized by `hanja-init-load'.")
(message "")))
;; List of current conversion status.
-;; The first element is the strating position of shown list.
+;; The first element is the starting position of shown list.
;; It is a group number each split by `hanja-list-width'.
;; The second element is the position of selected element.
;; The third element is a list of suitable Hanja candidate.
@@ -6479,11 +6479,7 @@ character. This variable is initialized by `hanja-init-load'.")
map)
"Keymap for Hanja (Korean Hanja Converter).")
-(defun hanja-filter (condp lst)
- "Construct a list from the elements of LST for which CONDP returns true."
- (delq
- nil
- (mapcar (lambda (x) (and (funcall condp x) x)) lst)))
+(define-obsolete-function-alias 'hanja-filter #'seq-filter "30.1")
(defun hanja-list-prev-group ()
"Select the previous group of hangul->hanja conversions."
@@ -6570,12 +6566,12 @@ The value is a hanja character that is selected interactively."
0 0
;; Filter characters that can not be decoded.
;; Maybe it can not represent characters in current terminal coding.
- (hanja-filter (lambda (x) (car x))
- (mapcar (lambda (c)
- (if (listp c)
- (cons (car c) (cdr c))
- (list c)))
- (aref hanja-table char)))))
+ (seq-filter #'car
+ (mapcar (lambda (c)
+ (if (listp c)
+ (cons (car c) (cdr c))
+ (list c)))
+ (aref hanja-table char)))))
(unwind-protect
(when (aref hanja-conversions 2)
(catch 'exit-input-loop
diff --git a/lisp/language/hebrew.el b/lisp/language/hebrew.el
index 2c0398888b2..d824901a1cb 100644
--- a/lisp/language/hebrew.el
+++ b/lisp/language/hebrew.el
@@ -1,6 +1,6 @@
;;; hebrew.el --- support for Hebrew -*- coding: utf-8; lexical-binding: t; -*-
-;; Copyright (C) 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2024 Free Software Foundation, Inc.
;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
;; 2005, 2006, 2007, 2008, 2009, 2010, 2011
;; National Institute of Advanced Industrial Science and Technology (AIST)
diff --git a/lisp/language/ind-util.el b/lisp/language/ind-util.el
index 71117deef56..b4bdf8f430b 100644
--- a/lisp/language/ind-util.el
+++ b/lisp/language/ind-util.el
@@ -1,6 +1,6 @@
;;; ind-util.el --- Transliteration and Misc. Tools for Indian Languages -*- coding: utf-8-emacs; lexical-binding: t; -*-
-;; Copyright (C) 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2024 Free Software Foundation, Inc.
;; Keywords: multilingual, Indian, Devanagari
diff --git a/lisp/language/indian.el b/lisp/language/indian.el
index d5964823501..9b3e0e0584f 100644
--- a/lisp/language/indian.el
+++ b/lisp/language/indian.el
@@ -1,6 +1,6 @@
;;; indian.el --- Indian languages support -*- coding: utf-8; lexical-binding: t; -*-
-;; Copyright (C) 1997, 1999, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997, 1999, 2001-2024 Free Software Foundation, Inc.
;; Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
;; National Institute of Advanced Industrial Science and Technology (AIST)
;; Registration Number H14PRO021
diff --git a/lisp/language/indonesian.el b/lisp/language/indonesian.el
index e0990c8320a..b8a18930f5c 100644
--- a/lisp/language/indonesian.el
+++ b/lisp/language/indonesian.el
@@ -1,6 +1,6 @@
;;; indonesian.el --- Indonesian languages support -*- coding: utf-8; lexical-binding: t; -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;; Author: समीर सिंह Sameer Singh <lumarzeli30@gmail.com>
;; Keywords: multilingual, input method, i18n, Indonesia
diff --git a/lisp/language/japan-util.el b/lisp/language/japan-util.el
index d60b163ae94..93e8ab24971 100644
--- a/lisp/language/japan-util.el
+++ b/lisp/language/japan-util.el
@@ -1,6 +1,6 @@
;;; japan-util.el --- utilities for Japanese -*- lexical-binding: t; -*-
-;; Copyright (C) 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2024 Free Software Foundation, Inc.
;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
;; 2005, 2006, 2007, 2008, 2009, 2010, 2011
;; National Institute of Advanced Industrial Science and Technology (AIST)
diff --git a/lisp/language/japanese.el b/lisp/language/japanese.el
index 6042ebf4511..dd65409c839 100644
--- a/lisp/language/japanese.el
+++ b/lisp/language/japanese.el
@@ -1,6 +1,6 @@
;;; japanese.el --- support for Japanese -*- lexical-binding: t; -*-
-;; Copyright (C) 1997, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997, 2001-2024 Free Software Foundation, Inc.
;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
;; 2005, 2006, 2007, 2008, 2009, 2010, 2011
;; National Institute of Advanced Industrial Science and Technology (AIST)
diff --git a/lisp/language/korea-util.el b/lisp/language/korea-util.el
index 764a58bd7d2..665745c1eb0 100644
--- a/lisp/language/korea-util.el
+++ b/lisp/language/korea-util.el
@@ -1,6 +1,6 @@
;;; korea-util.el --- utilities for Korean -*- lexical-binding: t; -*-
-;; Copyright (C) 1997, 1999, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997, 1999, 2001-2024 Free Software Foundation, Inc.
;; Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
;; 2007, 2008, 2009, 2010, 2011
;; National Institute of Advanced Industrial Science and Technology (AIST)
diff --git a/lisp/language/korean.el b/lisp/language/korean.el
index ede37d5d07c..9b04de3c6ca 100644
--- a/lisp/language/korean.el
+++ b/lisp/language/korean.el
@@ -1,6 +1,6 @@
;;; korean.el --- support for Korean -*- coding: utf-8; lexical-binding: t; -*-
-;; Copyright (C) 1998, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998, 2001-2024 Free Software Foundation, Inc.
;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
;; 2005, 2006, 2007, 2008, 2009, 2010, 2011
;; National Institute of Advanced Industrial Science and Technology (AIST)
diff --git a/lisp/language/lao-util.el b/lisp/language/lao-util.el
index 33e98a60d63..8bb767ba78f 100644
--- a/lisp/language/lao-util.el
+++ b/lisp/language/lao-util.el
@@ -1,6 +1,6 @@
;;; lao-util.el --- utilities for Lao -*- lexical-binding: t; -*-
-;; Copyright (C) 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2024 Free Software Foundation, Inc.
;; Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
;; 2007, 2008, 2009, 2010, 2011
;; National Institute of Advanced Industrial Science and Technology (AIST)
diff --git a/lisp/language/lao.el b/lisp/language/lao.el
index 875d5b49d52..2992e00b35b 100644
--- a/lisp/language/lao.el
+++ b/lisp/language/lao.el
@@ -1,6 +1,6 @@
;;; lao.el --- support for Lao -*- coding: utf-8; lexical-binding: t; -*-
-;; Copyright (C) 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2024 Free Software Foundation, Inc.
;; Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
;; 2007, 2008, 2009, 2010, 2011
;; National Institute of Advanced Industrial Science and Technology (AIST)
diff --git a/lisp/language/misc-lang.el b/lisp/language/misc-lang.el
index 792155f1de5..1de424252e8 100644
--- a/lisp/language/misc-lang.el
+++ b/lisp/language/misc-lang.el
@@ -1,6 +1,6 @@
;;; misc-lang.el --- support for miscellaneous languages (characters) -*- lexical-binding: t; -*-
-;; Copyright (C) 2012-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2012-2024 Free Software Foundation, Inc.
;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
;; 2005, 2006, 2007, 2008, 2009, 2010, 2011
;; National Institute of Advanced Industrial Science and Technology (AIST)
diff --git a/lisp/language/philippine.el b/lisp/language/philippine.el
index e4a79b02a44..68e0e599fac 100644
--- a/lisp/language/philippine.el
+++ b/lisp/language/philippine.el
@@ -1,6 +1,6 @@
;;; philippine.el --- Philippine languages support -*- coding: utf-8; lexical-binding: t; -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;; Author: समीर सिंह Sameer Singh <lumarzeli30@gmail.com>
;; Keywords: multilingual, input method, i18n, Philippines
diff --git a/lisp/language/romanian.el b/lisp/language/romanian.el
index a18b7d0cda2..a76f162f445 100644
--- a/lisp/language/romanian.el
+++ b/lisp/language/romanian.el
@@ -1,6 +1,6 @@
;;; romanian.el --- support for Romanian -*- coding: utf-8; lexical-binding: t -*-
-;; Copyright (C) 1998, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998, 2001-2024 Free Software Foundation, Inc.
;; Author: Dan Nicolaescu <done@ece.arizona.edu>
;; Keywords: multilingual, Romanian, i18n
diff --git a/lisp/language/sinhala.el b/lisp/language/sinhala.el
index bf320506001..a5c379b3aae 100644
--- a/lisp/language/sinhala.el
+++ b/lisp/language/sinhala.el
@@ -36,11 +36,11 @@
composition-function-table
'(#xD80 . #xDFF)
(list (vector
- ;; C:consonant, H:HALANT, J:ZWJ, v:vowel sign,
+ ;; C:consonant, H:HALANTA, J:ZWJ, v:vowel sign,
;; V:independent vowel, a:ANUSVARA .. VISARGA
(concat
- ;; C(HJC)*v*H?a?, or
- "[\u0D9A-\u0DC6]\\(?:\u0DCA\u200D[\u0D9A-\u0DC6]\\)*[\u0DCF-\u0DDF\u0DF2-\u0DF3]*\u0DCA?[\u0D82-\u0D83]?\\|"
+ ;; C(HJ|JH)C)*v*H?a?, or
+ "[\u0D9A-\u0DC6]\\(?:\\(\u0DCA\u200D\\|\u200D\u0DCA\\)[\u0D9A-\u0DC6]\\)*[\u0DCF-\u0DDF\u0DF2-\u0DF3]*\u0DCA?[\u0D82-\u0D83]?\\|"
;; Va?, or
"[\u0D85-\u0D96][\u0D82-\u0D83]?\\|"
;; any other singleton characters
diff --git a/lisp/language/slovak.el b/lisp/language/slovak.el
index eb49e6d598a..62cd0ecfdce 100644
--- a/lisp/language/slovak.el
+++ b/lisp/language/slovak.el
@@ -1,6 +1,6 @@
;;; slovak.el --- support for Slovak -*- coding: utf-8; lexical-binding: t -*-
-;; Copyright (C) 1998, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998, 2001-2024 Free Software Foundation, Inc.
;; Authors: Tibor Šimko <tibor.simko@fmph.uniba.sk>,
;; Milan Zamazal <pdm@zamazal.org>
diff --git a/lisp/language/tai-viet.el b/lisp/language/tai-viet.el
index 266de0600fe..e0e0d49a06a 100644
--- a/lisp/language/tai-viet.el
+++ b/lisp/language/tai-viet.el
@@ -1,6 +1,6 @@
;;; tai-viet.el --- support for Tai Viet -*- coding: utf-8; lexical-binding: t -*-
-;; Copyright (C) 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2024 Free Software Foundation, Inc.
;; Copyright (C) 2007, 2008, 2009, 2010, 2011
;; National Institute of Advanced Industrial Science and Technology (AIST)
;; Registration Number H13PRO009
diff --git a/lisp/language/thai-util.el b/lisp/language/thai-util.el
index e539e8e3c9d..ab18a752cad 100644
--- a/lisp/language/thai-util.el
+++ b/lisp/language/thai-util.el
@@ -1,6 +1,6 @@
;;; thai-util.el --- utilities for Thai -*- lexical-binding: t; -*-
-;; Copyright (C) 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2000-2024 Free Software Foundation, Inc.
;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
;; 2005, 2006, 2007, 2008, 2009, 2010, 2011
;; National Institute of Advanced Industrial Science and Technology (AIST)
diff --git a/lisp/language/thai.el b/lisp/language/thai.el
index 2e05e9b5db2..2326b983a2b 100644
--- a/lisp/language/thai.el
+++ b/lisp/language/thai.el
@@ -1,6 +1,6 @@
;;; thai.el --- support for Thai -*- coding: utf-8; lexical-binding: t; -*-
-;; Copyright (C) 1997-1998, 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997-1998, 2000-2024 Free Software Foundation, Inc.
;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
;; 2005, 2006, 2007, 2008, 2009, 2010, 2011
;; National Institute of Advanced Industrial Science and Technology (AIST)
diff --git a/lisp/language/tibet-util.el b/lisp/language/tibet-util.el
index b38d5230f93..1f1c52e3fbd 100644
--- a/lisp/language/tibet-util.el
+++ b/lisp/language/tibet-util.el
@@ -1,6 +1,6 @@
;;; tibet-util.el --- utilities for Tibetan -*- coding: utf-8-emacs; lexical-binding: t; -*-
-;; Copyright (C) 1997, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997, 2001-2024 Free Software Foundation, Inc.
;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
;; 2005, 2006, 2007, 2008, 2009, 2010, 2011
;; National Institute of Advanced Industrial Science and Technology (AIST)
diff --git a/lisp/language/tibetan.el b/lisp/language/tibetan.el
index 21b3fc03417..28f8c229d3d 100644
--- a/lisp/language/tibetan.el
+++ b/lisp/language/tibetan.el
@@ -1,6 +1,6 @@
;;; tibetan.el --- support for Tibetan language -*- coding: utf-8-emacs; lexical-binding: t; -*-
-;; Copyright (C) 1997, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997, 2001-2024 Free Software Foundation, Inc.
;; Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
;; 2006, 2007, 2008, 2009, 2010, 2011
;; National Institute of Advanced Industrial Science and Technology (AIST)
diff --git a/lisp/language/utf-8-lang.el b/lisp/language/utf-8-lang.el
index 4ecf8b8f50b..1fbd5427df2 100644
--- a/lisp/language/utf-8-lang.el
+++ b/lisp/language/utf-8-lang.el
@@ -1,6 +1,6 @@
;;; utf-8-lang.el --- generic UTF-8 language environment -*- lexical-binding: t -*-
-;; Copyright (C) 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2024 Free Software Foundation, Inc.
;; Author: Dave Love <fx@gnu.org>
;; Keywords: i18n
diff --git a/lisp/language/viet-util.el b/lisp/language/viet-util.el
index 40b4426399f..068a97dc492 100644
--- a/lisp/language/viet-util.el
+++ b/lisp/language/viet-util.el
@@ -1,6 +1,6 @@
;;; viet-util.el --- utilities for Vietnamese -*- lexical-binding: t; -*-
-;; Copyright (C) 1998, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998, 2001-2024 Free Software Foundation, Inc.
;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
;; 2005, 2006, 2007, 2008, 2009, 2010, 2011
;; National Institute of Advanced Industrial Science and Technology (AIST)
diff --git a/lisp/language/vietnamese.el b/lisp/language/vietnamese.el
index e439a2c3851..460a4d18246 100644
--- a/lisp/language/vietnamese.el
+++ b/lisp/language/vietnamese.el
@@ -1,6 +1,6 @@
;;; vietnamese.el --- support for Vietnamese -*- coding: utf-8; lexical-binding: t -*-
-;; Copyright (C) 1998, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998, 2001-2024 Free Software Foundation, Inc.
;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
;; 2005, 2006, 2007, 2008, 2009, 2010, 2011
;; National Institute of Advanced Industrial Science and Technology (AIST)
diff --git a/lisp/ldefs-boot.el b/lisp/ldefs-boot.el
index f062f3bf8de..ef672d6c2e5 100644
--- a/lisp/ldefs-boot.el
+++ b/lisp/ldefs-boot.el
@@ -302,7 +302,7 @@ usage: (defadvice FUNCTION (CLASS NAME [POSITION] [ARGLIST] FLAG...)
(fn FUNCTION ARGS &rest BODY)" nil t)
(function-put 'defadvice 'doc-string-elt 3)
(function-put 'defadvice 'lisp-indent-function 2)
-(make-obsolete 'defadvice '"use advice-add or define-advice" "30.1")
+(make-obsolete 'defadvice '"use `advice-add' or `define-advice'" "30.1")
(register-definition-prefixes "advice" '("ad-"))
@@ -1946,7 +1946,7 @@ Major mode for editing BibTeX style files.
(register-definition-prefixes "bibtex-style" '("bibtex-style-"))
-;;; Generated autoloads from use-package/bind-key.el
+;;; Generated autoloads from bind-key.el
(push (purecopy '(bind-key 2 4 1)) package--builtin-versions)
(autoload 'bind-key "bind-key" "\
@@ -2608,7 +2608,7 @@ used instead of `browse-url-new-window-flag'.
(fn URL &optional NEW-WINDOW)" t)
(make-obsolete 'browse-url-w3 'nil "29.1")
(autoload 'browse-url-w3-gnudoit "browse-url" "\
-Ask another Emacs running gnuserv to load the URL using the W3 browser.
+Ask another Emacs running emacsclient to load the URL using the W3 browser.
The `browse-url-gnudoit-program' program is used with options given by
`browse-url-gnudoit-args'. Default to the URL around or before point.
@@ -4668,14 +4668,14 @@ Return a string containing the `cl-prin1'-printed representation of OBJECT.
(autoload 'cl-print-to-string-with-limit "cl-print" "\
Return a string containing a printed representation of VALUE.
Attempt to get the length of the returned string under LIMIT
-characters with appropriate settings of `print-level' and
-`print-length.' Use PRINT-FUNCTION to print, which should take
-the arguments VALUE and STREAM and which should respect
-`print-length' and `print-level'. LIMIT may be nil or zero in
-which case PRINT-FUNCTION will be called with `print-level' and
-`print-length' bound to nil, and it can also be t in which case
-PRINT-FUNCTION will be called with the current values of `print-level'
-and `print-length'.
+characters with appropriate settings of `print-level',
+`print-length', and `cl-print-string-length'. Use
+PRINT-FUNCTION to print, which should take the arguments VALUE
+and STREAM and which should respect `print-length',
+`print-level', and `cl-print-string-length'. LIMIT may be nil or
+zero in which case PRINT-FUNCTION will be called with these
+settings bound to nil, and it can also be t in which case
+PRINT-FUNCTION will be called with their current values.
Use this function with `cl-prin1' to print an object,
abbreviating it with ellipses to fit within a size limit.
@@ -4857,10 +4857,6 @@ REGEXP-GROUP is the regular expression group in REGEXP to use.
;;; Generated autoloads from emacs-lisp/comp.el
(put 'no-native-compile 'safe-local-variable 'booleanp)
-(autoload 'comp-subr-trampoline-install "comp" "\
-Make SUBR-NAME effectively advice-able when called from native code.
-
-(fn SUBR-NAME)")
(autoload 'comp-c-func-name "comp" "\
Given NAME, return a name suitable for the native code.
Add PREFIX in front of it. If FIRST is not nil, pick the first
@@ -4868,42 +4864,16 @@ available name ignoring compilation context and potential name
clashes.
(fn NAME PREFIX &optional FIRST)")
+(autoload 'comp-trampoline-compile "comp" "\
+Synthesize compile and return a trampoline for SUBR-NAME.
+
+(fn SUBR-NAME)")
(autoload 'comp-clean-up-stale-eln "comp" "\
Remove all FILE*.eln* files found in `native-comp-eln-load-path'.
The files to be removed are those produced from the original source
filename (including FILE).
(fn FILE)")
-(autoload 'native--compile-async "comp" "\
-Compile FILES asynchronously.
-FILES is one filename or a list of filenames or directories.
-
-If optional argument RECURSIVELY is non-nil, recurse into
-subdirectories of given directories.
-
-If optional argument LOAD is non-nil, request to load the file
-after compiling.
-
-The optional argument SELECTOR has the following valid values:
-
-nil -- Select all files.
-a string -- A regular expression selecting files with matching names.
-a function -- A function selecting files with matching names.
-
-The variable `native-comp-async-jobs-number' specifies the number
-of (commands) to run simultaneously.
-
-LOAD can also be the symbol `late'. This is used internally if
-the byte code has already been loaded when this function is
-called. It means that we request the special kind of load
-necessary in that situation, called \"late\" loading.
-
-During a \"late\" load, instead of executing all top-level forms
-of the original files, only function definitions are
-loaded (paying attention to have these effective only if the
-bytecode definition was not changed in the meantime).
-
-(fn FILES &optional RECURSIVELY LOAD SELECTOR)")
(autoload 'comp-lookup-eln "comp" "\
Given a Lisp source FILENAME return the corresponding .eln file if found.
Search happens in `native-comp-eln-load-path'.
@@ -4940,9 +4910,43 @@ Force the produced .eln to be outputted in the eln system
directory (the last entry in `native-comp-eln-load-path') unless
`native-compile-target-directory' is non-nil. If the environment
variable \"NATIVE_DISABLED\" is set, only byte compile.")
-(autoload 'native-compile-async "comp" "\
+(register-definition-prefixes "comp" '("comp-" "native-comp" "no-native-compile"))
+
+
+;;; Generated autoloads from cedet/semantic/wisent/comp.el
+
+(register-definition-prefixes "semantic/wisent/comp" '("wisent-"))
+
+
+;;; Generated autoloads from emacs-lisp/comp-common.el
+
+(autoload 'comp-function-type-spec "comp-common" "\
+Return the type specifier of FUNCTION.
+
+This function returns a cons cell whose car is the function
+specifier, and cdr is a symbol, either `inferred' or `know'.
+If the symbol is `inferred', the type specifier is automatically
+inferred from the code itself by the native compiler; if it is
+`know', the type specifier comes from `comp-known-type-specifiers'.
+
+(fn FUNCTION)")
+(register-definition-prefixes "comp-common" '("comp-" "native-comp-"))
+
+
+;;; Generated autoloads from emacs-lisp/comp-cstr.el
+
+(register-definition-prefixes "comp-cstr" '("comp-" "with-comp-cstr-accessors"))
+
+
+;;; Generated autoloads from emacs-lisp/comp-run.el
+
+(autoload 'comp-subr-trampoline-install "comp-run" "\
+Make SUBR-NAME effectively advice-able when called from native code.
+
+(fn SUBR-NAME)")
+(autoload 'native--compile-async "comp-run" "\
Compile FILES asynchronously.
-FILES is one file or a list of filenames or directories.
+FILES is one filename or a list of filenames or directories.
If optional argument RECURSIVELY is non-nil, recurse into
subdirectories of given directories.
@@ -4959,28 +4963,38 @@ a function -- A function selecting files with matching names.
The variable `native-comp-async-jobs-number' specifies the number
of (commands) to run simultaneously.
+LOAD can also be the symbol `late'. This is used internally if
+the byte code has already been loaded when this function is
+called. It means that we request the special kind of load
+necessary in that situation, called \"late\" loading.
+
+During a \"late\" load, instead of executing all top-level forms
+of the original files, only function definitions are
+loaded (paying attention to have these effective only if the
+bytecode definition was not changed in the meantime).
+
(fn FILES &optional RECURSIVELY LOAD SELECTOR)")
-(autoload 'comp-function-type-spec "comp" "\
-Return the type specifier of FUNCTION.
+(autoload 'native-compile-async "comp-run" "\
+Compile FILES asynchronously.
+FILES is one file or a list of filenames or directories.
-This function returns a cons cell whose car is the function
-specifier, and cdr is a symbol, either `inferred' or `know'.
-If the symbol is `inferred', the type specifier is automatically
-inferred from the code itself by the native compiler; if it is
-`know', the type specifier comes from `comp-known-type-specifiers'.
+If optional argument RECURSIVELY is non-nil, recurse into
+subdirectories of given directories.
-(fn FUNCTION)")
-(register-definition-prefixes "comp" '("comp-" "make-comp-edge" "native-comp" "no-native-compile"))
+If optional argument LOAD is non-nil, request to load the file
+after compiling.
-
-;;; Generated autoloads from cedet/semantic/wisent/comp.el
+The optional argument SELECTOR has the following valid values:
-(register-definition-prefixes "semantic/wisent/comp" '("wisent-"))
+nil -- Select all files.
+a string -- A regular expression selecting files with matching names.
+a function -- A function selecting files with matching names.
-
-;;; Generated autoloads from emacs-lisp/comp-cstr.el
+The variable `native-comp-async-jobs-number' specifies the number
+of (commands) to run simultaneously.
-(register-definition-prefixes "comp-cstr" '("comp-" "with-comp-cstr-accessors"))
+(fn FILES &optional RECURSIVELY LOAD SELECTOR)")
+(register-definition-prefixes "comp-run" '("comp-" "native-comp"))
;;; Generated autoloads from vc/compare-w.el
@@ -5239,6 +5253,24 @@ or call the function `dynamic-completion-mode'.")
(autoload 'dynamic-completion-mode "completion" "\
Toggle dynamic word-completion on or off.
+When this minor mode is turned on, typing \\`M-RET' or \\`C-RET'
+invokes the command `complete', which completes the word or
+symbol at point using the record of words/symbols you used
+previously and the previously-inserted completions. Typing
+a word or moving point across it constitutes \"using\" the
+word.
+
+By default, the database of all the dynamic completions that
+were inserted by \\[complete] is saved on the file specified
+by `save-completions-file-name' when you exit Emacs, and will
+be loaded from that file when this mode is enabled in a future
+Emacs session.
+
+The following important options control the various aspects of
+this mode: `enable-completion', `save-completions-flag', and
+`save-completions-retention-time'. Few other less important
+options can be found in the `completion' group.
+
This is a global minor mode. If called interactively, toggle the
`Dynamic-Completion mode' mode. If the prefix argument is
positive, enable the mode, and if it is zero or negative, disable
@@ -5258,6 +5290,38 @@ it is disabled.
(register-definition-prefixes "completion" '("*c-def-regexp*" "*lisp-def-regexp*" "accept-completion" "add-" "cdabbrev-" "check-completion-length" "clear-all-completions" "cmpl-" "complet" "current-completion-source" "delete-completion" "enable-completion" "find-" "inside-locate-completion-entry" "interactive-completion-string-reader" "kill-" "list-all-completions" "load-completions-from-file" "make-c" "next-cdabbrev" "num-cmpl-sources" "reset-cdabbrev" "save" "set-c" "symbol-" "use-completion-"))
+;;; Generated autoloads from completion-preview.el
+
+(autoload 'completion-preview-mode "completion-preview" "\
+Show in-buffer completion suggestions in a preview as you type.
+
+This mode automatically shows and updates the completion preview
+according to the text around point.
+\\<completion-preview-active-mode-map>When the preview is visible, \\[completion-preview-insert]
+accepts the completion suggestion,
+\\[completion-preview-next-candidate] cycles forward to the next
+completion suggestion, and \\[completion-preview-prev-candidate]
+cycles backward.
+
+This is a minor mode. If called interactively, toggle the
+`Completion-Preview mode' mode. If the prefix argument is
+positive, enable the mode, and if it is zero or negative, disable
+the mode.
+
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
+
+To check whether the minor mode is enabled in the current buffer,
+evaluate `completion-preview-mode'.
+
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+
+(fn &optional ARG)" t)
+(register-definition-prefixes "completion-preview" '("completion-preview-"))
+
+
;;; Generated autoloads from textmodes/conf-mode.el
(autoload 'conf-mode "conf-mode" "\
@@ -5555,30 +5619,21 @@ into
\\{cperl-mode-map}
-Setting the variable `cperl-font-lock' to t switches on `font-lock-mode'
-(even with older Emacsen), `cperl-electric-lbrace-space' to t switches
-on electric space between $ and {, `cperl-electric-parens-string' is
-the string that contains parentheses that should be electric in CPerl
-(see also `cperl-electric-parens-mark' and `cperl-electric-parens'),
-setting `cperl-electric-keywords' enables electric expansion of
-control structures in CPerl. `cperl-electric-linefeed' governs which
-one of two linefeed behavior is preferable. You can enable all these
-options simultaneously (recommended mode of use) by setting
-`cperl-hairy' to t. In this case you can switch separate options off
-by setting them to `null'. Note that one may undo the extra
-whitespace inserted by semis and braces in `auto-newline'-mode by
-consequent \\[cperl-electric-backspace].
-
-If your site has perl5 documentation in info format, you can use commands
-\\[cperl-info-on-current-command] and \\[cperl-info-on-command] to access it.
-These keys run commands `cperl-info-on-current-command' and
-`cperl-info-on-command', which one is which is controlled by variable
-`cperl-info-on-command-no-prompt' and `cperl-clobber-lisp-bindings'
-(in turn affected by `cperl-hairy').
-
-Even if you have no info-format documentation, short one-liner-style
-help is available on \\[cperl-get-help], and one can run perldoc or
-man via menu.
+Setting the variable `cperl-font-lock' to t switches on `font-lock-mode',
+`cperl-electric-lbrace-space' to t switches on electric space between $
+and {, `cperl-electric-parens-string' is the string that contains
+parentheses that should be electric in CPerl (see also
+`cperl-electric-parens-mark' and `cperl-electric-parens'), setting
+`cperl-electric-keywords' enables electric expansion of control
+structures in CPerl. `cperl-electric-linefeed' governs which one of two
+linefeed behavior is preferable. You can enable all these options
+simultaneously by setting `cperl-hairy' to t. In this case you can
+switch separate options off by setting them to `null'. Note that one may
+undo the extra whitespace inserted by semis and braces in
+`auto-newline'-mode by consequent \\[cperl-electric-backspace].
+
+Short one-liner-style help is available on \\[cperl-get-help],
+and one can run perldoc or man via menu.
It is possible to show this help automatically after some idle time.
This is regulated by variable `cperl-lazy-help-time'. Default with
@@ -5669,7 +5724,7 @@ Run `perldoc' on WORD.
(fn WORD)" t)
(autoload 'cperl-perldoc-at-point "cperl-mode" "\
Run a `perldoc' on the word around point." t)
-(register-definition-prefixes "cperl-mode" '("cperl-" "imenu-max-items"))
+(register-definition-prefixes "cperl-mode" '("cperl-"))
;;; Generated autoloads from progmodes/cpp.el
@@ -6249,6 +6304,13 @@ This stores EXP (without evaluating it) as the saved spec for SYMBOL.
(fn &rest ARGS)")
(autoload 'custom-save-icons "cus-edit" "\
Save all customized icons in `custom-file'.")
+(autoload 'customize-dirlocals "cus-edit" "\
+Customize Directory Local Variables in the current directory.
+
+With optional argument FILENAME non-nil, customize the `.dir-locals.el' file
+that FILENAME specifies.
+
+(fn &optional FILENAME)" t)
(register-definition-prefixes "cus-edit" '("Custom-" "cus" "widget-"))
@@ -6278,7 +6340,7 @@ When called from Lisp, BUFFER should be the buffer to use; if
omitted, a buffer named *Custom Themes* is used.
(fn &optional BUFFER)" t)
-(register-definition-prefixes "cus-theme" '("custom-" "describe-theme-1"))
+(register-definition-prefixes "cus-theme" '("custom-" "describe-theme-"))
;;; Generated autoloads from cedet/ede/custom.el
@@ -6632,6 +6694,13 @@ There is some minimal font-lock support (see vars
(setq debugger 'debug)
(autoload 'debug "debug" "\
Enter debugger. \\<debugger-mode-map>`\\[debugger-continue]' returns from the debugger.
+
+In interactive sessions, this switches to a backtrace buffer and shows
+the Lisp backtrace of function calls there. In batch mode (more accurately,
+when `noninteractive' is non-nil), it shows the Lisp backtrace on the
+standard error stream (unless `backtrace-on-error-noninteractive' is nil),
+and then kills Emacs, causing it to exit with a negative exit code.
+
Arguments are mainly for use when this is called from the internals
of the evaluator.
@@ -7261,29 +7330,36 @@ Major mode for editing the diary file.
(autoload 'dictionary-mode "dictionary" "\
Mode for searching a dictionary.
+
This is a mode for searching a dictionary server implementing the
protocol defined in RFC 2229.
This is a quick reference to this mode describing the default key bindings:
\\<dictionary-mode-map>
-* \\[dictionary-close] close the dictionary buffer
-* \\[describe-mode] display this help information
-* \\[dictionary-search] ask for a new word to search
-* \\[dictionary-lookup-definition] search the word at point
-* \\[forward-button] or TAB place point to the next link
-* \\[backward-button] or S-TAB place point to the prev link
-
-* \\[dictionary-match-words] ask for a pattern and list all matching words.
-* \\[dictionary-select-dictionary] select the default dictionary
-* \\[dictionary-select-strategy] select the default search strategy
-
-* \\`RET' or \\`<mouse-2>' visit that link")
+ \\[dictionary-close] close the dictionary buffer
+ \\[describe-mode] display this help
+ \\[dictionary-search] ask for a new word to search
+ \\[dictionary-lookup-definition] search for word at point
+ \\[forward-button] or \\`TAB' move point to the next link
+ \\[backward-button] or \\`S-TAB' move point to the previous link
+
+ \\[dictionary-match-words] ask for a pattern and list all matching words
+ \\[dictionary-select-dictionary] select the default dictionary
+ \\[dictionary-select-strategy] select the default search strategy
+
+ \\`RET' visit link at point
+ \\`<mouse-2>' visit clicked link
+
+(fn)" t)
(autoload 'dictionary "dictionary" "\
Create a new dictionary buffer and install `dictionary-mode'." t)
(autoload 'dictionary-search "dictionary" "\
-Search the WORD in DICTIONARY if given or in all if nil.
-It presents the selection or word at point as default input and
-allows editing it.
+Search for WORD in all the known dictionaries.
+Interactively, prompt for WORD, and offer the word at point as default.
+
+Optional argument DICTIONARY means restrict the search to only
+that one dictionary. Interactively, with prefix argument,
+prompt for DICTIONARY.
(fn WORD &optional DICTIONARY)" t)
(autoload 'dictionary-lookup-definition "dictionary" "\
@@ -7491,7 +7567,9 @@ each option.
On systems such as MS-DOS and MS-Windows, which use `ls' emulation in Lisp,
some of the `ls' switches are not supported; see the doc string of
-`insert-directory' in `ls-lisp.el' for more details.")
+`insert-directory' in `ls-lisp.el' for more details.
+
+For remote Dired buffers, this option supports connection-local values.")
(custom-autoload 'dired-listing-switches "dired" t)
(defvar-local dired-directory nil "\
The directory name or wildcard spec that this Dired directory lists.
@@ -7620,7 +7698,7 @@ Like \\[dired-jump] (`dired-jump') but in other window.
;;; Generated autoloads from dired-aux.el
-(register-definition-prefixes "dired-aux" '("dired-"))
+(register-definition-prefixes "dired-aux" '("dired-" "shell-command-guess"))
;;; Generated autoloads from dired-x.el
@@ -7677,7 +7755,7 @@ If OBJECT is not already compiled, we compile it, but do not
redefine OBJECT if it is a symbol.
(fn OBJECT &optional BUFFER INDENT INTERACTIVE-P)" t)
-(register-definition-prefixes "disass" '("disassemble-"))
+(register-definition-prefixes "disass" '("disassemble-" "re-disassemble"))
;;; Generated autoloads from disp-table.el
@@ -8022,13 +8100,15 @@ Default is 2.
;;; Generated autoloads from dnd.el
-(defvar dnd-protocol-alist `((,(purecopy "^file:///") . dnd-open-local-file) (,(purecopy "^file://") . dnd-open-file) (,(purecopy "^file:") . dnd-open-local-file) (,(purecopy "^\\(https?\\|ftp\\|file\\|nfs\\)://") . dnd-open-file)) "\
+(defvar dnd-protocol-alist `((,(purecopy "^file:///") . dnd-open-local-file) (,(purecopy "^file://[^/]") . dnd-open-file) (,(purecopy "^file:/[^/]") . dnd-open-local-file) (,(purecopy "^file:[^/]") . dnd-open-local-file) (,(purecopy "^\\(https?\\|ftp\\|nfs\\)://") . dnd-open-file)) "\
The functions to call for different protocols when a drop is made.
-This variable is used by `dnd-handle-one-url' and `dnd-handle-file-name'.
+This variable is used by `dnd-handle-multiple-urls'.
The list contains of (REGEXP . FUNCTION) pairs.
The functions shall take two arguments, URL, which is the URL dropped and
ACTION which is the action to be performed for the drop (move, copy, link,
private or ask).
+If a function's `dnd-multiple-handler' property is set, it is provided
+a list of each URI dropped instead.
If no match is found here, and the value of `browse-url-browser-function'
is a pair of (REGEXP . FUNCTION), those regexps are tried for a match.
If no match is found, the URL is inserted as text by calling `dnd-insert-text'.
@@ -8667,7 +8747,7 @@ A second call of this function without changing point inserts the next match.
A call with prefix PREFIX reads the symbol to insert from the minibuffer with
completion.
-(fn PREFIX)" t)
+(fn PREFIX)" '("P"))
(autoload 'ebrowse-tags-loop-continue "ebrowse" "\
Repeat last operation on files in tree.
FIRST-TIME non-nil means this is not a repetition, but the first time.
@@ -8977,7 +9057,7 @@ MERGE-AUTOSTORE-DIR is the directory in which to store merged files.
(autoload 'ediff-windows-wordwise "ediff" "\
Compare WIND-A and WIND-B, which are selected by clicking, wordwise.
This compares the portions of text visible in each of the two windows.
-With prefix argument, DUMB-MODE, or on a non-windowing display, works as
+With prefix argument, DUMB-MODE, or on a non-graphical display, works as
follows:
If WIND-A is nil, use selected window.
If WIND-B is nil, use window next to WIND-A.
@@ -8988,7 +9068,7 @@ arguments after setting up the Ediff buffers.
(autoload 'ediff-windows-linewise "ediff" "\
Compare WIND-A and WIND-B, which are selected by clicking, linewise.
This compares the portions of text visible in each of the two windows.
-With prefix argument, DUMB-MODE, or on a non-windowing display, works as
+With prefix argument, DUMB-MODE, or on a non-graphical display, works as
follows:
If WIND-A is nil, use selected window.
If WIND-B is nil, use window next to WIND-A.
@@ -9222,14 +9302,14 @@ Edit a keyboard macro which has been given a name by `name-last-kbd-macro'.
(fn &optional PREFIX)" t)
(autoload 'read-kbd-macro "edmacro" "\
Read the region as a keyboard macro definition.
-The region is interpreted as spelled-out keystrokes, e.g., \"M-x abc RET\".
-See documentation for `edmacro-mode' for details.
+The region between START and END is interpreted as spelled-out keystrokes,
+e.g., \"M-x abc RET\". See documentation for `edmacro-mode' for details.
Leading/trailing \"C-x (\" and \"C-x )\" in the text are allowed and ignored.
The resulting macro is installed as the \"current\" keyboard macro.
In Lisp, may also be called with a single STRING argument in which case
the result is returned rather than being installed as the current macro.
-The result will be a string if possible, otherwise an event vector.
+The result is a vector of input events.
Second argument NEED-VECTOR means to return an event vector always.
(fn START &optional END)" t)
@@ -9279,7 +9359,8 @@ Turn on EDT Emulation." t)
;;; Generated autoloads from progmodes/eglot.el
-(push (purecopy '(eglot 1 15)) package--builtin-versions)
+(push (purecopy '(eglot 1 16)) package--builtin-versions)
+(define-obsolete-function-alias 'eglot-update #'eglot-upgrade-eglot "29.1")
(autoload 'eglot "eglot" "\
Start LSP server for PROJECT's buffers under MANAGED-MAJOR-MODES.
@@ -9322,13 +9403,23 @@ INTERACTIVE is ignored and provided for backward compatibility.
(fn MANAGED-MAJOR-MODES PROJECT CLASS CONTACT LANGUAGE-IDS &optional INTERACTIVE)" t)
(autoload 'eglot-ensure "eglot" "\
-Start Eglot session for current buffer if there isn't one.")
+Start Eglot session for current buffer if there isn't one.
+
+Only use this function (in major mode hooks, etc) if you are
+confident that Eglot can be started safely and efficiently for
+*every* buffer visited where these hooks may execute.
+
+Since it is difficult to establish this confidence fully, it's
+often wise to use the interactive command `eglot' instead. This
+command only needs to be invoked once per project, as all other
+files of a given major mode visited within the same project will
+automatically become managed with no further user intervention
+needed.")
(autoload 'eglot-upgrade-eglot "eglot" "\
Update Eglot to latest version.
(fn &rest _)" t)
-(define-obsolete-function-alias 'eglot-update 'eglot-upgrade-eglot "29.1")
-(put 'eglot-workspace-configuration 'safe-local-variable 'listp)
+(put 'eglot-workspace-configuration 'safe-local-variable #'listp)
(put 'eglot--debbugs-or-github-bug-uri 'bug-reference-url-format t)
(defun eglot--debbugs-or-github-bug-uri nil (format (if (string= (match-string 2) "github") "https://github.com/joaotavora/eglot/issues/%s" "https://debbugs.gnu.org/%s") (match-string 3)))
(register-definition-prefixes "eglot" '("eglot-"))
@@ -9455,7 +9546,7 @@ Describe CTR if it is a class constructor.
;;; Generated autoloads from emacs-lisp/eldoc.el
-(push (purecopy '(eldoc 1 14 0)) package--builtin-versions)
+(push (purecopy '(eldoc 1 15 0)) package--builtin-versions)
;;; Generated autoloads from elec-pair.el
@@ -9637,7 +9728,7 @@ displayed." t)
;;; Generated autoloads from eshell/em-basic.el
-(register-definition-prefixes "em-basic" '("eshell"))
+(register-definition-prefixes "em-basic" '("eshell" "pcomplete/eshell-mode/eshell-debug"))
;;; Generated autoloads from eshell/em-cmpl.el
@@ -9859,7 +9950,7 @@ Emerge two RCS revisions of a file, with another revision as ancestor.
(autoload 'emoji-recent "emoji" nil t)
(autoload 'emoji-search "emoji" nil t)
(autoload 'emoji-list "emoji" "\
-List emojis and insert the one that's selected.
+List emojis and allow selecting and inserting one of them.
Select the emoji by typing \\<emoji-list-mode-map>\\[emoji-list-select] on its picture.
The glyph will be inserted into the buffer that was current
when the command was invoked." t)
@@ -10296,7 +10387,7 @@ for the values of the other parameters.
See `erc-tls' for the meaning of ID.
-(fn &key SERVER PORT NICK USER PASSWORD FULL-NAME ID)" t)
+(fn &key SERVER PORT NICK USER PASSWORD FULL-NAME ID)" '((let ((erc--display-context `((erc-interactive-display . erc) ,@erc--display-context))) (erc-select-read-args))))
(defalias 'erc-select #'erc)
(autoload 'erc-tls "erc" "\
ERC is a powerful, modular, and extensible IRC client.
@@ -10344,7 +10435,7 @@ See Info node `(erc) Network Identifier' for details. Like
CLIENT-CERTIFICATE, this parameter cannot be specified
interactively.
-(fn &key SERVER PORT NICK USER PASSWORD FULL-NAME CLIENT-CERTIFICATE ID)" t)
+(fn &key SERVER PORT NICK USER PASSWORD FULL-NAME CLIENT-CERTIFICATE ID)" '((let ((erc-default-port erc-default-port-tls) (erc--display-context `((erc-interactive-display . erc-tls) ,@erc--display-context))) (erc-select-read-args))))
(autoload 'erc-handle-irc-url "erc" "\
Use ERC to IRC on HOST:PORT in CHANNEL.
If ERC is already connected to HOST:PORT, simply /join CHANNEL.
@@ -10544,7 +10635,7 @@ server name and search for a match in `erc-networks-alist'.")
;;; Generated autoloads from erc/erc-truncate.el
-(register-definition-prefixes "erc-truncate" '("erc-max-buffer-size"))
+(register-definition-prefixes "erc-truncate" '("erc-"))
;;; Generated autoloads from erc/erc-xdcc.el
@@ -10560,8 +10651,8 @@ Define NAME (a symbol) as a test.
BODY is evaluated as a `progn' when the test is run. It should
signal a condition on failure or just return if the test passes.
-`should', `should-not', `should-error' and `skip-unless' are
-useful for assertions in BODY.
+`should', `should-not', `should-error', `skip-when', and
+`skip-unless' are useful for assertions in BODY.
Use `ert' to run tests interactively.
@@ -10576,9 +10667,7 @@ it has to be wrapped in `(eval (quote ...))'.
If NAME is already defined as a test and Emacs is running
in batch mode, an error is signaled.
-(fn NAME () [DOCSTRING] [:expected-result RESULT-TYPE] [:tags \\='(TAG...)] BODY...)" nil t)
-(function-put 'ert-deftest 'doc-string-elt 3)
-(function-put 'ert-deftest 'lisp-indent-function 2)
+(fn NAME () [DOCSTRING] [:expected-result RESULT-TYPE] [:tags \\='(TAG...)] BODY...)" nil 'macro)
(autoload 'ert-run-tests-batch "ert" "\
Run the tests specified by SELECTOR, printing results to the terminal.
@@ -10639,7 +10728,7 @@ This mode mainly provides some font locking.
;;; Generated autoloads from eshell/esh-cmd.el
-(register-definition-prefixes "esh-cmd" '("eshell" "pcomplete/eshell-mode/eshell-debug"))
+(register-definition-prefixes "esh-cmd" '("eshell"))
;;; Generated autoloads from eshell/esh-ext.el
@@ -10803,6 +10892,8 @@ which is important if that buffer has a local value of `tags-file-name'.
Returns t if it visits a tags table, or nil if there are no more in the list.
(fn &optional CONT CBUF)")
+(autoload 'tags-reset-tags-tables "etags" "\
+Reset tags state to cancel effect of any previous \\[visit-tags-table] or \\[find-tag]." t)
(autoload 'tags-table-files "etags" "\
Return a list of files in the current tags table.
Assumes the tags table is the current buffer. The file names are returned
@@ -12165,13 +12256,30 @@ Delete all settings of file-local VARIABLE from the -*- line.
(autoload 'add-dir-local-variable "files-x" "\
Add directory-local VARIABLE with its VALUE and MODE to .dir-locals.el.
-(fn MODE VARIABLE VALUE)" t)
+With a prefix argument, prompt for the file to modify.
+
+When called from Lisp, FILE may be the expanded name of the dir-locals file
+where to add VARIABLE.
+
+(fn MODE VARIABLE VALUE &optional FILE)" t)
(autoload 'delete-dir-local-variable "files-x" "\
-Delete all MODE settings of file-local VARIABLE from .dir-locals.el.
+Delete all MODE settings of dir-local VARIABLE from .dir-locals.el.
+
+With a prefix argument, prompt for the file to modify.
-(fn MODE VARIABLE)" t)
+When called from Lisp, FILE may be the expanded name of the dir-locals file
+from where to delete VARIABLE.
+
+(fn MODE VARIABLE &optional FILE)" t)
(autoload 'copy-file-locals-to-dir-locals "files-x" "\
-Copy file-local variables to .dir-locals.el." t)
+Copy file-local variables to .dir-locals.el.
+
+With a prefix argument, prompt for the file to modify.
+
+When called from Lisp, FILE may be the expanded name of the dir-locals file
+where to copy the file-local variables.
+
+(fn &optional FILE)" t)
(autoload 'copy-dir-locals-to-file-locals "files-x" "\
Copy directory-local variables to the Local Variables list." t)
(autoload 'copy-dir-locals-to-file-locals-prop-line "files-x" "\
@@ -12216,6 +12324,14 @@ function preserves the values of any existing variable
definitions that aren't listed in VARIABLES.
(fn PROFILE VARIABLES)")
+(autoload 'hack-connection-local-variables "files-x" "\
+Read connection-local variables according to CRITERIA.
+Store the connection-local variables in buffer local
+variable `connection-local-variables-alist'.
+
+This does nothing if `enable-connection-local-variables' is nil.
+
+(fn CRITERIA)")
(autoload 'hack-connection-local-variables-apply "files-x" "\
Apply connection-local variables identified by CRITERIA.
Other local variables, like file-local and dir-local variables,
@@ -12259,11 +12375,25 @@ earlier in the `setq-connection-local'. The return value of the
`setq-connection-local' form is the value of the last VALUE.
(fn [VARIABLE VALUE]...)" nil t)
+(autoload 'connection-local-p "files-x" "\
+Non-nil if VARIABLE has a connection-local binding in `default-directory'.
+If APPLICATION is nil, the value of
+`connection-local-default-application' is used.
+
+(fn VARIABLE &optional APPLICATION)" nil t)
+(autoload 'connection-local-value "files-x" "\
+Return connection-local VARIABLE for APPLICATION in `default-directory'.
+If APPLICATION is nil, the value of
+`connection-local-default-application' is used.
+If VARIABLE does not have a connection-local binding, the return
+value is the default binding of the variable.
+
+(fn VARIABLE &optional APPLICATION)" nil t)
(autoload 'path-separator "files-x" "\
The connection-local value of `path-separator'.")
(autoload 'null-device "files-x" "\
The connection-local value of `null-device'.")
-(register-definition-prefixes "files-x" '("connection-local-" "dir-locals-to-string" "hack-connection-local-variables" "modify-" "read-file-local-variable"))
+(register-definition-prefixes "files-x" '("connection-local-" "dir-locals-to-string" "modify-" "read-"))
;;; Generated autoloads from filesets.el
@@ -12685,7 +12815,7 @@ lines.
;;; Generated autoloads from progmodes/flymake.el
-(push (purecopy '(flymake 1 3 4)) package--builtin-versions)
+(push (purecopy '(flymake 1 3 7)) package--builtin-versions)
(autoload 'flymake-log "flymake" "\
Log, at level LEVEL, the message MSG formatted with ARGS.
LEVEL is passed to `display-warning', which is used to display
@@ -12866,7 +12996,7 @@ it is disabled.
Unconditionally turn on Flyspell mode.")
(autoload 'turn-off-flyspell "flyspell" "\
Unconditionally turn off Flyspell mode.")
-(autoload 'flyspell-mode-off "flyspell" "\
+(autoload 'flyspell--mode-off "flyspell" "\
Turn Flyspell mode off.")
(autoload 'flyspell-region "flyspell" "\
Flyspell text between BEG and END.
@@ -15013,6 +15143,29 @@ The mode's hook is called both when the mode is enabled and when
it is disabled.
(fn &optional ARG)" t)
+(autoload 'lldb "gud" "\
+Run LLDB passing it COMMAND-LINE as arguments.
+If COMMAND-LINE names a program FILE to debug, LLDB will run in
+a buffer named *gud-FILE*, and the directory containing FILE
+becomes the initial working directory and source-file directory
+for the debug session. If you don't want `default-directory' to
+change to the directory of FILE, specify FILE without leading
+directories, in which case FILE should reside either in the
+directory of the buffer from which this command is invoked, or
+it can be found by searching PATH.
+
+If COMMAND-LINE requests that LLDB attaches to a process PID, LLDB
+will run in *gud-PID*, otherwise it will run in *gud*; in these
+cases the initial working directory is the `default-directory' of
+the buffer in which this command was invoked.
+
+Please note that completion framework that complete while you
+type, like Corfu, do not work well with this mode. You should
+consider to turn them off in this mode.
+
+This command runs functions from `lldb-mode-hook'.
+
+(fn COMMAND-LINE)" t)
(register-definition-prefixes "gud" '("gdb-" "gud-"))
@@ -15950,7 +16103,7 @@ it is disabled.
;;; Generated autoloads from progmodes/hideshow.el
-(defvar hs-special-modes-alist (mapcar #'purecopy '((c-mode "{" "}" "/[*/]" nil nil) (c-ts-mode "{" "}" "/[*/]" nil nil) (c++-mode "{" "}" "/[*/]" nil nil) (c++-ts-mode "{" "}" "/[*/]" nil nil) (bibtex-mode ("@\\S(*\\(\\s(\\)" 1)) (java-mode "{" "}" "/[*/]" nil nil) (java-ts-mode "{" "}" "/[*/]" nil nil) (js-mode "{" "}" "/[*/]" nil) (js-ts-mode "{" "}" "/[*/]" nil) (mhtml-mode "{\\|<[^/>]*?" "}\\|</[^/>]*[^/]>" "<!--" mhtml-forward nil))) "\
+(defvar hs-special-modes-alist (mapcar #'purecopy '((c-mode "{" "}" "/[*/]" nil nil) (c-ts-mode "{" "}" "/[*/]" nil nil) (c++-mode "{" "}" "/[*/]" nil nil) (c++-ts-mode "{" "}" "/[*/]" nil nil) (bibtex-mode ("@\\S(*\\(\\s(\\)" 1)) (java-mode "{" "}" "/[*/]" nil nil) (java-ts-mode "{" "}" "/[*/]" nil nil) (js-mode "{" "}" "/[*/]" nil) (js-ts-mode "{" "}" "/[*/]" nil) (lua-ts-mode "{\\|\\[\\[" "}\\|\\]\\]" "--" nil) (mhtml-mode "{\\|<[^/>]*?" "}\\|</[^/>]*[^/]>" "<!--" mhtml-forward nil))) "\
Alist for initializing the hideshow variables for different modes.
Each element has the form
(MODE START END COMMENT-START FORWARD-SEXP-FUNC ADJUST-BEG-FUNC
@@ -16450,8 +16603,7 @@ inlined into the compiled format versions. This means that if you
change its definition, you should explicitly call
`ibuffer-recompile-formats'.
-(fn SYMBOL (&key NAME INLINE PROPS SUMMARIZER) &rest BODY)" nil t)
-(function-put 'define-ibuffer-column 'lisp-indent-function 'defun)
+(fn SYMBOL (&key NAME INLINE PROPS SUMMARIZER) &rest BODY)" nil 'macro)
(autoload 'define-ibuffer-sorter "ibuf-macs" "\
Define a method of sorting named NAME.
DOCUMENTATION is the documentation of the function, which will be called
@@ -16462,9 +16614,7 @@ For sorting, the forms in BODY will be evaluated with `a' bound to one
buffer object, and `b' bound to another. BODY should return a non-nil
value if and only if `a' is \"less than\" `b'.
-(fn NAME DOCUMENTATION (&key DESCRIPTION) &rest BODY)" nil t)
-(function-put 'define-ibuffer-sorter 'lisp-indent-function 1)
-(function-put 'define-ibuffer-sorter 'doc-string-elt 2)
+(fn NAME DOCUMENTATION (&key DESCRIPTION) &rest BODY)" nil 'macro)
(autoload 'define-ibuffer-op "ibuf-macs" "\
Generate a function which operates on a buffer.
OP becomes the name of the function; if it doesn't begin with
@@ -16503,9 +16653,7 @@ BODY define the operation; they are forms to evaluate per each
marked buffer. BODY is evaluated with `buf' bound to the
buffer object.
-(fn OP ARGS DOCUMENTATION (&key INTERACTIVE MARK MODIFIER-P DANGEROUS OPSTRING ACTIVE-OPSTRING BEFORE AFTER COMPLEX) &rest BODY)" nil t)
-(function-put 'define-ibuffer-op 'lisp-indent-function 2)
-(function-put 'define-ibuffer-op 'doc-string-elt 3)
+(fn OP ARGS DOCUMENTATION (&key INTERACTIVE MARK MODIFIER-P DANGEROUS OPSTRING ACTIVE-OPSTRING BEFORE AFTER COMPLEX) &rest BODY)" nil 'macro)
(autoload 'define-ibuffer-filter "ibuf-macs" "\
Define a filter named NAME.
DOCUMENTATION is the documentation of the function.
@@ -16520,9 +16668,7 @@ not a particular buffer should be displayed or not. The forms in BODY
will be evaluated with BUF bound to the buffer object, and QUALIFIER
bound to the current value of the filter.
-(fn NAME DOCUMENTATION (&key READER DESCRIPTION) &rest BODY)" nil t)
-(function-put 'define-ibuffer-filter 'lisp-indent-function 2)
-(function-put 'define-ibuffer-filter 'doc-string-elt 2)
+(fn NAME DOCUMENTATION (&key READER DESCRIPTION) &rest BODY)" nil 'macro)
(register-definition-prefixes "ibuf-macs" '("ibuffer-"))
@@ -17783,9 +17929,8 @@ it is disabled.
(fn &optional ARG)" t)
(autoload 'image-mode-to-text "image-mode" "\
-Set a non-image mode as major mode in combination with image minor mode.
-A non-mage major mode found from `auto-mode-alist' or fundamental mode
-displays an image file as text.")
+Set current buffer's modes be a non-image major mode, plus `image-minor-mode'.
+A non-image major mode displays an image file as text.")
(autoload 'image-bookmark-jump "image-mode" "\
@@ -17963,6 +18108,42 @@ Convert old Emacs Devanagari characters to UCS.
(register-definition-prefixes "ind-util" '("combinatorial" "indian-" "is13194-"))
+;;; Generated autoloads from indent-aux.el
+
+(defvar kill-ring-deindent-mode nil "\
+Non-nil if Kill-Ring-Deindent mode is enabled.
+See the `kill-ring-deindent-mode' command
+for a description of this minor mode.
+Setting this variable directly does not take effect;
+either customize it (see the info node `Easy Customization')
+or call the function `kill-ring-deindent-mode'.")
+(custom-autoload 'kill-ring-deindent-mode "indent-aux" nil)
+(autoload 'kill-ring-deindent-mode "indent-aux" "\
+Toggle removal of indentation from text saved to the kill ring.
+
+When this minor mode is enabled, text saved into the kill ring is
+indented towards the left by the column number at the start of
+that text.
+
+This is a global minor mode. If called interactively, toggle the
+`Kill-Ring-Deindent mode' mode. If the prefix argument is
+positive, enable the mode, and if it is zero or negative, disable
+the mode.
+
+If called from Lisp, toggle the mode if ARG is `toggle'. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
+
+To check whether the minor mode is enabled in the current buffer,
+evaluate `(default-value \\='kill-ring-deindent-mode)'.
+
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+
+(fn &optional ARG)" t)
+(register-definition-prefixes "indent-aux" '("kill-ring-deindent-buffer-substring-function"))
+
+
;;; Generated autoloads from leim/quail/indian.el
(register-definition-prefixes "quail/indian" '("indian-mlm-mozhi-u" "inscript-" "quail-" "tamil"))
@@ -18610,6 +18791,8 @@ If APPEND is non-nil, don't erase previous debugging output.
(fn &optional APPEND)" t)
(autoload 'ispell-continue "ispell" "\
Continue a halted spelling session beginning with the current word." t)
+(autoload 'ispell-completion-at-point "ispell" "\
+Word completion function for use in `completion-at-point-functions'.")
(autoload 'ispell-complete-word "ispell" "\
Try to complete the word before or at point.
If optional INTERIOR-FRAG is non-nil, then the word may be a character
@@ -18866,7 +19049,7 @@ Major mode for editing JSON, powered by tree-sitter.
;;; Generated autoloads from jsonrpc.el
-(push (purecopy '(jsonrpc 1 0 17)) package--builtin-versions)
+(push (purecopy '(jsonrpc 1 0 23)) package--builtin-versions)
(register-definition-prefixes "jsonrpc" '("jsonrpc-"))
@@ -19267,6 +19450,13 @@ the variables of the outer one. You can, however, access alists
inside the original alist by using dots inside the symbol, as
displayed in the example above.
+Note that there is no way to differentiate the case where a key
+is missing from when it is present, but its value is nil. Thus,
+the following form evaluates to nil:
+
+ (let-alist \\='((some-key . nil))
+ .some-key)
+
(fn ALIST &rest BODY)" nil t)
(function-put 'let-alist 'lisp-indent-function 1)
(register-definition-prefixes "let-alist" '("let-alist--"))
@@ -19315,6 +19505,7 @@ sleep in seconds.
;;; Generated autoloads from emacs-lisp/loaddefs-gen.el
+(put 'autoload-compute-prefixes 'safe-local-variable #'booleanp)
(put 'generated-autoload-file 'safe-local-variable 'stringp)
(put 'generated-autoload-load-name 'safe-local-variable 'stringp)
(autoload 'loaddefs-generate "loaddefs-gen" "\
@@ -19380,7 +19571,7 @@ remove symbols from it in the event that the package has done
something strange, such as redefining an Emacs function.
(fn FEATURE &optional FORCE)" t)
-(register-definition-prefixes "loadhist" '("feature-" "file-" "loadhist-" "read-feature" "unload-"))
+(register-definition-prefixes "loadhist" '("feature-" "file-" "loadhist-unload-filename" "read-feature" "unload-"))
;;; Generated autoloads from cedet/ede/locate.el
@@ -19570,6 +19761,19 @@ Otherwise they are treated as Emacs regexps (for backward compatibility).")
(register-definition-prefixes "ls-lisp" '("ls-lisp-"))
+;;; Generated autoloads from progmodes/lua-ts-mode.el
+
+(autoload 'lua-ts-inferior-lua "lua-ts-mode" "\
+Run a Lua interpreter in an inferior process." t)
+(autoload 'lua-ts-mode "lua-ts-mode" "\
+Major mode for editing Lua files, powered by tree-sitter.
+
+\\{lua-ts-mode-map}
+
+(fn)" t)
+(register-definition-prefixes "lua-ts-mode" '("lua-ts-"))
+
+
;;; Generated autoloads from calendar/lunar.el
(autoload 'lunar-phases "lunar" "\
@@ -19993,15 +20197,8 @@ dependency, despite the colon.
\\{makefile-mode-map}
-In the browser, use the following keys:
-
-\\{makefile-browser-map}
-
Makefile mode can be configured by modifying the following variables:
-`makefile-browser-buffer-name':
- Name of the macro- and target browser buffer.
-
`makefile-target-colon':
The string that gets appended to all target names
inserted by `makefile-insert-target'.
@@ -20019,24 +20216,6 @@ Makefile mode can be configured by modifying the following variables:
If you want a TAB (instead of a space) to be appended after the
target colon, then set this to a non-nil value.
-`makefile-browser-leftmost-column':
- Number of blanks to the left of the browser selection mark.
-
-`makefile-browser-cursor-column':
- Column in which the cursor is positioned when it moves
- up or down in the browser.
-
-`makefile-browser-selected-mark':
- String used to mark selected entries in the browser.
-
-`makefile-browser-unselected-mark':
- String used to mark unselected entries in the browser.
-
-`makefile-browser-auto-advance-after-selection-p':
- If this variable is set to a non-nil value the cursor
- will automagically advance to the next line after an item
- has been selected in the browser.
-
`makefile-pickup-everything-picks-up-filenames-p':
If this variable is set to a non-nil value then
`makefile-pickup-everything' also picks up filenames as targets
@@ -20052,10 +20231,6 @@ Makefile mode can be configured by modifying the following variables:
IMPORTANT: Please note that enabling this option causes Makefile mode
to MODIFY A FILE WITHOUT YOUR CONFIRMATION when \"it seems necessary\".
-`makefile-browser-hook':
- A function or list of functions to be called just before the
- browser is entered. This is executed in the makefile buffer.
-
`makefile-special-targets-list':
List of special targets. You will be offered to complete
on one of those in the minibuffer whenever you enter a `.'.
@@ -20139,6 +20314,11 @@ Note that in some cases you will need to use \\[quoted-insert] to quote the
SPC character in the above examples, because this command attempts
to auto-complete your input based on the installed manual pages.
+If `default-directory' is remote, and `Man-support-remote-systems'
+is non-nil, this command formats the man page on the remote system.
+A prefix argument reverses the value of `Man-support-remote-systems'
+for the current invocation.
+
(fn MAN-ARGS)" t)
(autoload 'man-follow "man" "\
Get a Un*x manual page of the item under point and put it in a buffer.
@@ -20357,7 +20537,15 @@ for \"x-scheme-handler/mailto;\" to \"emacs -f message-mailto %u\"
will then start up Emacs ready to compose mail. For emacsclient use
emacsclient -e \\='(message-mailto \"%u\")'
-(fn &optional URL)" t)
+To facilitate the use of this function within window systems that
+provide message subject, body and attachments independent of URL
+itself, the arguments SUBJECT, BODY and FILE-ATTACHMENTS may also
+provide alternative message subject and body text, which is
+inserted in lieu of nothing if URL does not incorporate such
+information itself, and a list of files to insert as attachments
+to the E-mail.
+
+(fn &optional URL SUBJECT BODY FILE-ATTACHMENTS)" t)
(register-definition-prefixes "message" '("message-"))
@@ -20897,7 +21085,21 @@ With a prefix argument, ask for a wildcard, and search in file buffers
whose file names match the specified wildcard.
(fn FILES)" t)
-(register-definition-prefixes "misearch" '("misearch-unload-function" "multi-isearch-"))
+(autoload 'multi-file-replace-regexp-as-diff "misearch" "\
+Show as diffs replacements of REGEXP with TO-STRING in FILES.
+DELIMITED has the same meaning as in `replace-regexp'.
+The replacements are displayed in the buffer *replace-diff* that
+you can later apply as a patch after reviewing the changes.
+
+(fn FILES REGEXP TO-STRING &optional DELIMITED)" t)
+(autoload 'replace-regexp-as-diff "misearch" "\
+Show as diffs replacements of REGEXP with TO-STRING in the current buffer.
+DELIMITED has the same meaning as in `replace-regexp'.
+The replacements are displayed in the buffer *replace-diff* that
+you can later apply as a patch after reviewing the changes.
+
+(fn REGEXP TO-STRING &optional DELIMITED)" t)
+(register-definition-prefixes "misearch" '("misearch-unload-function" "multi-"))
;;; Generated autoloads from progmodes/mixal-mode.el
@@ -22561,7 +22763,7 @@ Coloring:
;;; Generated autoloads from org/org.el
-(push (purecopy '(org 9 6 7)) package--builtin-versions)
+(push (purecopy '(org 9 6 13)) package--builtin-versions)
(autoload 'org-babel-do-load-languages "org" "\
Load the languages defined in `org-babel-load-languages'.
@@ -23527,8 +23729,7 @@ that code in the early init-file.
(fn &optional NO-ACTIVATE)" t)
(defun package-activate-all nil "\
Activate all installed packages.
-The variable `package-load-list' controls which packages to load." (setq package--activated t) (let* ((elc (concat package-quickstart-file "c")) (qs (if (file-readable-p elc) elc (if (file-readable-p package-quickstart-file) package-quickstart-file)))) (if (and qs (not (bound-and-true-p package-activated-list))) (let ((load-source-file-function nil)) (unless (boundp 'package-activated-list) (setq package-activated-list nil)) (load qs nil 'nomessage)) (require 'package) (package--activate-all))))
-(autoload 'package--activate-all "package")
+The variable `package-load-list' controls which packages to load." (setq package--activated t) (let* ((elc (concat package-quickstart-file "c")) (qs (if (file-readable-p elc) elc (if (file-readable-p package-quickstart-file) package-quickstart-file)))) (or (and qs (not (bound-and-true-p package-activated-list)) (with-demoted-errors "Error during quickstart: %S" (let ((load-source-file-function nil)) (unless (boundp 'package-activated-list) (setq package-activated-list nil)) (load qs nil 'nomessage) t))) (progn (require 'package) (with-no-warnings (package--activate-all))))))
(autoload 'package-import-keyring "package" "\
Import keys from FILE.
@@ -23670,40 +23871,59 @@ DESC must be a `package-desc' object.
(autoload 'package-vc-install-selected-packages "package-vc" "\
Ensure packages specified in `package-vc-selected-packages' are installed." t)
(autoload 'package-vc-upgrade-all "package-vc" "\
-Attempt to upgrade all installed VC packages." t)
+Upgrade all installed VC packages.
+
+This may fail if the local VCS state of one of the packages
+conflicts with its remote repository state." t)
(autoload 'package-vc-upgrade "package-vc" "\
-Attempt to upgrade the package PKG-DESC.
+Upgrade the package described by PKG-DESC from package's VC repository.
+
+This may fail if the local VCS state of the package conflicts
+with the remote repository state.
(fn PKG-DESC)" t)
(autoload 'package-vc-install "package-vc" "\
-Fetch a PACKAGE and set it up for using with Emacs.
-
-If PACKAGE is a string containing an URL, download the package
-from the repository at that URL; the function will try to guess
-the name of the package from the URL. This can be overridden by
-passing the optional argument NAME. If PACKAGE is a cons-cell,
-it should have the form (NAME . SPEC), where NAME is a symbol
-indicating the package name and SPEC is a plist as described in
-`package-vc-selected-packages'. Otherwise PACKAGE should be a
-symbol whose name is the package name, and the URL for the
-package will be taken from the package's metadata.
+Fetch a package described by PACKAGE and set it up for use with Emacs.
+
+PACKAGE specifies which package to install, where to find its
+source repository and how to build it.
+
+If PACKAGE is a symbol, install the package with that name
+according to metadata that package archives provide for it. This
+is the simplest way to call this function, but it only works if
+the package you want to install is listed in a package archive
+you have configured.
+
+If PACKAGE is a string, it specifies the URL of the package
+repository. In this case, optional argument BACKEND specifies
+the VC backend to use for cloning the repository; if it's nil,
+this function tries to infer which backend to use according to
+the value of `package-vc-heuristic-alist' and if that fails it
+uses `package-vc-default-backend'. Optional argument NAME
+specifies the package name in this case; if it's nil, this
+package uses `file-name-base' on the URL to obtain the package
+name, otherwise NAME is the package name as a symbol.
+
+PACKAGE can also be a cons cell (PNAME . SPEC) where PNAME is the
+package name as a symbol, and SPEC is a plist that specifies how
+to fetch and build the package. For possible values, see the
+subsection \"Specifying Package Sources\" in the Info
+node `(emacs)Fetching Package Sources'.
By default, this function installs the last revision of the
package available from its repository. If REV is a string, it
-describes the revision to install, as interpreted by the VC
-backend. The special value `:last-release' (interactively, the
-prefix argument), will use the commit of the latest release, if
-it exists. The last release is the latest revision which changed
-the \"Version:\" header of the package's main Lisp file.
-
-Optional argument BACKEND specifies the VC backend to use for cloning
-the package's repository; this is only possible if NAME-OR-URL is a URL,
-a string. If BACKEND is omitted or nil, the function
-uses `package-vc-heuristic-alist' to guess the backend.
-Note that by default, a VC package will be prioritized over a
-regular package, but it will not remove a VC package.
-
-(fn PACKAGE &optional REV BACKEND)" t)
+describes the revision to install, as interpreted by the relevant
+VC backend. The special value `:last-release' (interactively,
+the prefix argument), says to use the commit of the latest
+release, if it exists. The last release is the latest revision
+which changed the \"Version:\" header of the package's main Lisp
+file.
+
+If you use this function to install a package that you also have
+installed from a package archive, the version this function
+installs takes precedence.
+
+(fn PACKAGE &optional REV BACKEND NAME)" t)
(autoload 'package-vc-checkout "package-vc" "\
Clone the sources for PKG-DESC into DIRECTORY and visit that directory.
Unlike `package-vc-install', this does not yet set up the package
@@ -23717,14 +23937,14 @@ for the last released version of the package.
(fn PKG-DESC DIRECTORY &optional REV)" t)
(autoload 'package-vc-install-from-checkout "package-vc" "\
-Set up the package NAME in DIR by linking it into the ELPA directory.
+Install the package NAME from its source directory DIR.
+NAME defaults to the base name of DIR.
Interactively, prompt the user for DIR, which should be a directory
under version control, typically one created by `package-vc-checkout'.
If invoked interactively with a prefix argument, prompt the user
-for the NAME of the package to set up. Otherwise infer the package
-name from the base name of DIR.
+for the NAME of the package to set up.
-(fn DIR NAME)" t)
+(fn DIR &optional NAME)" t)
(autoload 'package-vc-rebuild "package-vc" "\
Rebuild the installation for package given by PKG-DESC.
Rebuilding an installation means scraping for new autoload
@@ -23736,14 +23956,18 @@ prompt for the name of the package to rebuild.
(fn PKG-DESC)" t)
(autoload 'package-vc-prepare-patch "package-vc" "\
-Send patch for REVISIONS to maintainer of the package PKG using SUBJECT.
-The function uses `vc-prepare-patch', passing SUBJECT and
-REVISIONS directly. PKG-DESC must be a package description.
+Email patches for REVISIONS to maintainer of package PKG-DESC using SUBJECT.
+
+PKG-DESC is a package descriptor and SUBJECT is the subject of
+the message.
+
Interactively, prompt for PKG-DESC, SUBJECT, and REVISIONS. When
invoked with a numerical prefix argument, use the last N
revisions. When invoked interactively in a Log View buffer with
marked revisions, use those.
+See also `vc-prepare-patch'.
+
(fn PKG-DESC SUBJECT REVISIONS)" t)
(register-definition-prefixes "package-vc" '("package-vc-"))
@@ -23772,6 +23996,11 @@ archive).
(register-definition-prefixes "page-ext" '("pages-"))
+;;; Generated autoloads from leim/quail/pakistan.el
+
+(register-definition-prefixes "quail/pakistan" '("pakistan-"))
+
+
;;; Generated autoloads from calendar/parse-time.el
(put 'parse-time-rules 'risky-local-variable t)
@@ -24105,7 +24334,7 @@ Completion for checksum commands.")
(defalias 'pcomplete/sha224sum 'pcomplete/md5sum)
(defalias 'pcomplete/sha256sum 'pcomplete/md5sum)
(defalias 'pcomplete/sha384sum 'pcomplete/md5sum)
-(defalias 'pcomplete/sha521sum 'pcomplete/md5sum)
+(defalias 'pcomplete/sha512sum 'pcomplete/md5sum)
(autoload 'pcomplete/sort "pcmpl-unix" "\
Completion for the `sort' command.")
(autoload 'pcomplete/shuf "pcmpl-unix" "\
@@ -24234,6 +24463,8 @@ Includes files as well as host names followed by a colon.")
(autoload 'pcomplete/telnet "pcmpl-unix")
(autoload 'pcomplete/sudo "pcmpl-unix" "\
Completion for the `sudo' command.")
+(autoload 'pcomplete/doas "pcmpl-unix" "\
+Completion for the `doas' command.")
(register-definition-prefixes "pcmpl-unix" '("pcmpl-" "pcomplete/"))
@@ -24542,6 +24773,11 @@ they are not by default assigned to keys." t)
(register-definition-prefixes "picture" '("picture-"))
+;;; Generated autoloads from language/pinyin.el
+
+(register-definition-prefixes "pinyin" '("pinyin-character-map"))
+
+
;;; Generated autoloads from textmodes/pixel-fill.el
(register-definition-prefixes "pixel-fill" '("pixel-fill-"))
@@ -24598,7 +24834,7 @@ or call the function `pixel-scroll-precision-mode'.")
(autoload 'pixel-scroll-precision-mode "pixel-scroll" "\
Toggle pixel scrolling.
-When enabled, this minor mode allows to scroll the display
+When enabled, this minor mode allows you to scroll the display
precisely, according to the turning of the mouse wheel.
This is a global minor mode. If called interactively, toggle the
@@ -25314,7 +25550,7 @@ Open profile FILENAME.
;;; Generated autoloads from progmodes/project.el
-(push (purecopy '(project 0 9 8)) package--builtin-versions)
+(push (purecopy '(project 0 10 0)) package--builtin-versions)
(autoload 'project-current "project" "\
Return the project instance in DIRECTORY, defaulting to `default-directory'.
@@ -25335,12 +25571,12 @@ See the doc string of `project-find-functions' for the general form
of the project instance object.
(fn &optional MAYBE-PROMPT DIRECTORY)")
-(put 'project-vc-ignores 'safe-local-variable #'listp)
+(put 'project-vc-ignores 'safe-local-variable (lambda (val) (and (listp val) (not (memq nil (mapcar #'stringp val))))))
(put 'project-vc-merge-submodules 'safe-local-variable #'booleanp)
(put 'project-vc-include-untracked 'safe-local-variable #'booleanp)
(put 'project-vc-name 'safe-local-variable #'stringp)
(put 'project-vc-extra-root-markers 'safe-local-variable (lambda (val) (and (listp val) (not (memq nil (mapcar #'stringp val))))))
-(defvar project-prefix-map (let ((map (make-sparse-keymap))) (define-key map "!" 'project-shell-command) (define-key map "&" 'project-async-shell-command) (define-key map "f" 'project-find-file) (define-key map "F" 'project-or-external-find-file) (define-key map "b" 'project-switch-to-buffer) (define-key map "s" 'project-shell) (define-key map "d" 'project-find-dir) (define-key map "D" 'project-dired) (define-key map "v" 'project-vc-dir) (define-key map "c" 'project-compile) (define-key map "e" 'project-eshell) (define-key map "k" 'project-kill-buffers) (define-key map "p" 'project-switch-project) (define-key map "g" 'project-find-regexp) (define-key map "G" 'project-or-external-find-regexp) (define-key map "r" 'project-query-replace-regexp) (define-key map "x" 'project-execute-extended-command) (define-key map "\2" 'project-list-buffers) map) "\
+(defvar project-prefix-map (let ((map (make-sparse-keymap))) (define-key map "!" 'project-shell-command) (define-key map "&" 'project-async-shell-command) (define-key map "f" 'project-find-file) (define-key map "F" 'project-or-external-find-file) (define-key map "b" 'project-switch-to-buffer) (define-key map "s" 'project-shell) (define-key map "d" 'project-find-dir) (define-key map "D" 'project-dired) (define-key map "v" 'project-vc-dir) (define-key map "c" 'project-compile) (define-key map "e" 'project-eshell) (define-key map "k" 'project-kill-buffers) (define-key map "p" 'project-switch-project) (define-key map "g" 'project-find-regexp) (define-key map "G" 'project-or-external-find-regexp) (define-key map "r" 'project-query-replace-regexp) (define-key map "x" 'project-execute-extended-command) (define-key map "o" 'project-any-command) (define-key map "\2" 'project-list-buffers) map) "\
Keymap for project commands.")
(define-key ctl-x-map "p" project-prefix-map)
(autoload 'project-other-window-command "project" "\
@@ -25386,7 +25622,8 @@ pattern to search for.
Visit a file (with completion) in the current project.
The filename at point (determined by `thing-at-point'), if any,
-is available as part of \"future history\".
+is available as part of \"future history\". If none, the current
+buffer's file name is used.
If INCLUDE-ALL is non-nil, or with prefix argument when called
interactively, include all files under the project root, except
@@ -25397,7 +25634,8 @@ for VCS directories listed in `vc-directory-exclusion-list'.
Visit a file (with completion) in the current project or external roots.
The filename at point (determined by `thing-at-point'), if any,
-is available as part of \"future history\".
+is available as part of \"future history\". If none, the current
+buffer's file name is used.
If INCLUDE-ALL is non-nil, or with prefix argument when called
interactively, include all files under the project root, except
@@ -25405,7 +25643,10 @@ for VCS directories listed in `vc-directory-exclusion-list'.
(fn &optional INCLUDE-ALL)" t)
(autoload 'project-find-dir "project" "\
-Start Dired in a directory inside the current project." t)
+Start Dired in a directory inside the current project.
+
+The current buffer's `default-directory' is available as part of
+\"future history\"." t)
(autoload 'project-dired "project" "\
Start Dired in the current project's root." t)
(autoload 'project-vc-dir "project" "\
@@ -25520,6 +25761,24 @@ Return the list of root directories of all known projects.")
(autoload 'project-execute-extended-command "project" "\
Execute an extended command in project root." t)
(function-put 'project-execute-extended-command 'interactive-only 'command-execute)
+(autoload 'project-any-command "project" "\
+Run the next command in the current project.
+
+If the command name starts with `project-', or its symbol has
+property `project-aware', it gets passed the project to use
+with the variable `project-current-directory-override'.
+Otherwise, `default-directory' is temporarily set to the current
+project's root.
+
+If OVERRIDING-MAP is non-nil, it will be used as
+`overriding-local-map' to provide shorter bindings from that map
+which will take priority over the global ones.
+
+(fn &optional OVERRIDING-MAP PROMPT-FORMAT)" t)
+(autoload 'project-prefix-or-any-command "project" "\
+Run the next command in the current project.
+Works like `project-any-command', but also mixes in the shorter
+bindings from `project-prefix-map'." t)
(autoload 'project-switch-project "project" "\
\"Switch\" to another project by running an Emacs command.
The available commands are presented as a dispatch menu
@@ -25538,6 +25797,12 @@ the buffer's directory name when buffers from two different projects
would otherwise have the same name.
(fn DIRNAME)")
+(defvar project-mode-line nil "\
+Whether to show current project name and Project menu on the mode line.
+This feature requires the presence of the following item in
+`mode-line-format': `(project-mode-line project-mode-line-format)'; it
+is part of the default mode line beginning with Emacs 30.")
+(custom-autoload 'project-mode-line "project" t)
(register-definition-prefixes "project" '("project-"))
@@ -26576,7 +26841,7 @@ This enforces rescanning the buffer on next use.")
(put 'reftex-vref-is-default 'safe-local-variable (lambda (x) (or (stringp x) (symbolp x))))
(put 'reftex-fref-is-default 'safe-local-variable (lambda (x) (or (stringp x) (symbolp x))))
(put 'reftex-level-indent 'safe-local-variable 'integerp)
-(put 'reftex-guess-label-type 'safe-local-variable (lambda (x) (memq x '(nil t))))
+(put 'reftex-guess-label-type 'safe-local-variable #'booleanp)
(register-definition-prefixes "reftex-vars" '("reftex-"))
@@ -28439,7 +28704,7 @@ Like `mail' command, but display mail buffer in another frame.
;;; Generated autoloads from emacs-lisp/seq.el
-(push (purecopy '(seq 2 23)) package--builtin-versions)
+(push (purecopy '(seq 2 24)) package--builtin-versions)
;;; Generated autoloads from server.el
@@ -30475,6 +30740,8 @@ but with the twist that BODY can evaluate itself recursively by
calling NAME, where the arguments passed to NAME are used
as the new values of the bound variables in the recursive invocation.
+This construct can only be used with lexical binding.
+
(fn NAME BINDINGS &rest BODY)" nil t)
(function-put 'named-let 'lisp-indent-function 2)
(autoload 'string-pixel-width "subr-x" "\
@@ -32306,7 +32573,10 @@ Convert SECONDS to a proper time, like `current-time' would.
(fn SECONDS)")
(autoload 'days-to-time "time-date" "\
-Convert DAYS into a time value.
+Convert Emacs-epoch DAYS into a time value.
+Note that this does not use the same epoch as `time-to-days'; you
+must subtract (time-to-days 0) first to convert, and may get nil
+if the result is before the start.
(fn DAYS)")
(autoload 'time-since "time-date" "\
@@ -32335,7 +32605,7 @@ Return the day number within the year corresponding to TIME.
(fn TIME)")
(autoload 'time-to-days "time-date" "\
-The absolute date corresponding to TIME, a time value.
+The absolute pseudo-Gregorian date for TIME, a time value.
The absolute date is the number of days elapsed since the imaginary
Gregorian date Sunday, December 31, 1 BC.
@@ -32652,20 +32922,14 @@ and done items are always shown on visiting a category.
(autoload 'todo-mode "todo-mode" "\
Major mode for displaying, navigating and editing todo lists.
-\\{todo-mode-map}
-
(fn)" t)
(autoload 'todo-archive-mode "todo-mode" "\
Major mode for archived todo categories.
-\\{todo-archive-mode-map}
-
(fn)" t)
(autoload 'todo-filtered-items-mode "todo-mode" "\
Mode for displaying and reprioritizing top priority Todo.
-\\{todo-filtered-items-mode-map}
-
(fn)" t)
(register-definition-prefixes "todo-mode" '("todo-"))
@@ -32966,6 +33230,7 @@ Add archive file name handler to `file-name-handler-alist'." (when (and tramp-ar
;;; Generated autoloads from transient.el
+(push (purecopy '(transient 0 5 2)) package--builtin-versions)
(autoload 'transient-define-prefix "transient" "\
Define NAME as a transient prefix command.
@@ -33058,7 +33323,7 @@ See info node `(transient)Modifying Existing Transients'.
(fn PREFIX LOC)")
(function-put 'transient-remove-suffix 'lisp-indent-function 'defun)
-(register-definition-prefixes "transient" '("transient"))
+(register-definition-prefixes "transient" '("static-if" "transient"))
;;; Generated autoloads from tree-widget.el
@@ -33307,7 +33572,9 @@ FRAC should be the inverse of the fractional value; for example, a value of
;;; Generated autoloads from progmodes/typescript-ts-mode.el
(autoload 'typescript-ts-base-mode "typescript-ts-mode" "\
-Major mode for editing TypeScript.
+Generic major mode for editing TypeScript.
+
+This mode is intended to be inherited by concrete major modes.
(fn)" t)
(autoload 'typescript-ts-mode "typescript-ts-mode" "\
@@ -33326,7 +33593,7 @@ The JSX-specific faces are used when `treesit-font-lock-level' is
at least 3 (which is the default value).
(fn)" t)
-(register-definition-prefixes "typescript-ts-mode" '("tsx-ts-mode--" "typescript-ts-mode-"))
+(register-definition-prefixes "typescript-ts-mode" '("tsx-ts-" "typescript-ts-"))
;;; Generated autoloads from international/ucs-normalize.el
@@ -33610,6 +33877,7 @@ Handle file: and ftp: URLs.
Attempt to resolve the given HOST using nslookup if possible.
(fn HOST)" t)
+(make-obsolete 'url-gateway-nslookup-host 'nil "30.1")
(autoload 'url-open-stream "url-gw" "\
Open a stream to HOST, possibly via a gateway.
Args per `open-network-stream'.
@@ -34377,18 +34645,23 @@ responsible for the given file.
(autoload 'vc-next-action "vc" "\
Do the next logical version control operation on the current fileset.
This requires that all files in the current VC fileset be in the
-same state. If not, signal an error.
-
-For merging-based version control systems:
- If every file in the VC fileset is not registered for version
- control, register the fileset (but don't commit).
- If every work file in the VC fileset is added or changed, pop
- up a *vc-log* buffer to commit the fileset.
+same state. If they are not, signal an error. Also signal an error if
+files in the fileset are missing (removed, but tracked by version control),
+or are ignored by the version control system.
+
+For modern merging-based version control systems:
+ If every file in the fileset is not registered for version
+ control, register the fileset (but don't commit). If VERBOSE is
+ non-nil (interactively, the prefix argument), ask for the VC
+ backend with which to register the fileset.
+ If every work file in the VC fileset is either added or modified,
+ pop up a *vc-log* buffer to commit the fileset changes.
For a centralized version control system, if any work file in
the VC fileset is out of date, offer to update the fileset.
For old-style locking-based version control systems, like RCS:
- If every file is not registered, register the file(s).
+ If every file is not registered, register the file(s); with a prefix
+ argument, allow to specify the VC backend for registration.
If every file is registered and unlocked, check out (lock)
the file(s) for editing.
If every file is locked by you and has changes, pop up a
@@ -34396,14 +34669,21 @@ For old-style locking-based version control systems, like RCS:
read-only copy of each changed file after checking in.
If every file is locked by you and unchanged, unlock them.
If every file is locked by someone else, offer to steal the lock.
+ If files are unlocked, but have changes, offer to either claim the
+ lock or revert to the last checked-in version.
+
+If this command is invoked from a patch buffer under `diff-mode', it
+will apply the diffs from the patch and pop up a *vc-log* buffer to
+check-in the resulting changes.
When using this command to register a new file (or files), it
will automatically deduce which VC repository to register it
with, using the most specific one.
If VERBOSE is non-nil (interactively, the prefix argument),
-you can specify a VC backend or (for centralized VCS only)
-the revision ID or branch ID.
+you can specify another VC backend for the file(s),
+or (for centralized VCS only) the revision ID or branch ID
+from which to check out the file(s).
(fn VERBOSE)" t)
(autoload 'vc-register "vc" "\
@@ -34707,7 +34987,7 @@ On a non-distributed version control system, this signals an error.
It also signals an error in a Bazaar bound branch.
(fn &optional ARG)" t)
-(autoload 'vc-switch-backend "vc" "\
+(autoload 'vc-change-backend "vc" "\
Make BACKEND the current version control system for FILE.
FILE must already be registered in BACKEND. The change is not
permanent, only for the current session. This function only changes
@@ -34716,7 +34996,6 @@ By default, this command cycles through the registered backends.
To get a prompt, use a prefix argument.
(fn FILE BACKEND)" t)
-(make-obsolete 'vc-switch-backend 'nil "28.1")
(autoload 'vc-transfer-file "vc" "\
Transfer FILE to another version control system NEW-BACKEND.
If NEW-BACKEND has a higher precedence than FILE's current backend
@@ -34772,7 +35051,7 @@ When invoked interactively in a Log View buffer with
marked revisions, use those.
(fn ADDRESSEE SUBJECT REVISIONS)" t)
-(register-definition-prefixes "vc" '("vc-" "with-vc-properties"))
+(register-definition-prefixes "vc" '("log-view-vc-prev-" "vc-" "with-vc-properties"))
;;; Generated autoloads from vc/vc-annotate.el
@@ -36107,6 +36386,18 @@ so the value of `wallpaper-commands' is ignored.
;;; Generated autoloads from emacs-lisp/warnings.el
+(defvar warning-suppress-types nil "\
+List of warning types not to display immediately.
+If any element of this list matches the TYPE argument to `display-warning',
+the warning is logged nonetheless, but the warnings buffer is
+not immediately displayed.
+The element must match an initial segment of the list TYPE.
+Thus, (foo bar) as an element matches (foo bar)
+or (foo bar ANYTHING...) as TYPE.
+If TYPE is a symbol FOO, that is equivalent to the list (FOO),
+so only the element (FOO) will match it.
+See also `warning-suppress-log-types'.")
+(custom-autoload 'warning-suppress-types "warnings" t)
(defvar warning-prefix-function nil "\
Function to generate warning prefixes.
This function, if non-nil, is called with two arguments,
@@ -36971,6 +37262,10 @@ updated (e.g. to re-interpret the current directory).
Used non-interactively, arguments are optional: if given then TOPIC
should be a topic string and non-nil RE-CACHE forces re-caching.
+Note that `M-x woman' doesn’t yet support the latest features of
+modern man pages, so we recommend using `M-x man' if that is
+available on your system.
+
(fn &optional TOPIC RE-CACHE)" t)
(autoload 'woman-dired-find-file "woman" "\
In dired, run the WoMan man-page browser on this file." t)
@@ -37355,6 +37650,102 @@ run a specific program. The program must be a member of
(fn &optional PGM)" t)
(register-definition-prefixes "zone" '("zone-"))
+
+
+;;; Generated autoloads from emacs-lisp/ert-font-lock.el
+
+(autoload 'ert-font-lock-deftest "ert-font-lock" "\
+Define test NAME (a symbol) using assertions from TEST-STR.
+
+Other than MAJOR-MODE and TEST-STR parameters, this macro accepts
+the same parameters and keywords as `ert-deftest' and is intended
+to be used through `ert'.
+
+(fn NAME () [DOCSTRING] [:expected-result RESULT-TYPE] [:tags \\='(TAG...)] MAJOR-MODE TEST-STR)" nil t)
+(function-put 'ert-font-lock-deftest 'doc-string-elt 3)
+(function-put 'ert-font-lock-deftest 'lisp-indent-function 2)
+(autoload 'ert-font-lock-deftest-file "ert-font-lock" "\
+Define test NAME (a symbol) using assertions from FILE.
+
+FILE - path to a file with assertions in ERT resource director as
+return by `ert-resource-directory'.
+
+Other than MAJOR-MODE and FILE parameters, this macro accepts the
+same parameters and keywords as `ert-deftest' and is intended to
+be used through `ert'.
+
+(fn NAME () [DOCSTRING] [:expected-result RESULT-TYPE] [:tags \\='(TAG...)] MAJOR-MODE FILE)" nil t)
+(function-put 'ert-font-lock-deftest-file 'doc-string-elt 3)
+(function-put 'ert-font-lock-deftest-file 'lisp-indent-function 2)
+(autoload 'ert-font-lock-test-string "ert-font-lock" "\
+Check font faces in TEST-STRING set by MODE.
+
+The function is meant to be run from within an ERT test.
+
+(fn TEST-STRING MODE)")
+(autoload 'ert-font-lock-test-file "ert-font-lock" "\
+Check font faces in FILENAME set by MODE.
+
+The function is meant to be run from within an ERT test.
+
+(fn FILENAME MODE)")
+(register-definition-prefixes "ert-font-lock" '("ert-font-lock--"))
+
+
+;;; Generated autoloads from touch-screen.el
+
+(autoload 'touch-screen-hold "touch-screen" "\
+Handle a long press EVENT.
+Ding and select the window at EVENT, then activate the mark. If
+`touch-screen-word-select' is enabled, try to select the whole
+word around EVENT; otherwise, set point to the location of EVENT.
+
+(fn EVENT)" t)
+(autoload 'touch-screen-track-tap "touch-screen" "\
+Track a single tap starting from EVENT.
+EVENT should be a `touchscreen-begin' event.
+
+Read touch screen events until a `touchscreen-end' event is
+received with the same ID as in EVENT. If UPDATE is non-nil and
+a `touchscreen-update' event is received in the mean time and
+contains a touch point with the same ID as in EVENT, call UPDATE
+with that event and DATA.
+
+If THRESHOLD is non-nil, enforce a threshold of movement that is
+either itself or 10 pixels when it is not a number. If the
+aforementioned touch point moves beyond that threshold on any
+axis, return nil immediately, and further resume mouse event
+translation for the touch point at hand.
+
+Return nil immediately if any other kind of event is received;
+otherwise, return t once the `touchscreen-end' event arrives.
+
+(fn EVENT &optional UPDATE DATA THRESHOLD)")
+(autoload 'touch-screen-track-drag "touch-screen" "\
+Track a single drag starting from EVENT.
+EVENT should be a `touchscreen-begin' event.
+
+Read touch screen events until a `touchscreen-end' event is
+received with the same ID as in EVENT. For each
+`touchscreen-update' event received in the mean time containing a
+touch point with the same ID as in EVENT, call UPDATE with the
+touch point in event and DATA, once the touch point has moved
+significantly by at least 5 pixels from where it was in EVENT.
+
+Return nil immediately if any other kind of event is received;
+otherwise, return either t or `no-drag' once the
+`touchscreen-end' event arrives; return `no-drag' returned if the
+touch point in EVENT did not move significantly, and t otherwise.
+
+(fn EVENT UPDATE &optional DATA)")
+(autoload 'touch-screen-inhibit-drag "touch-screen" "\
+Inhibit subsequent `touchscreen-drag' events from being sent.
+Prevent `touchscreen-drag' and translated mouse events from being
+sent until the touch sequence currently being translated ends.
+Must be called from a command bound to a `touchscreen-hold' or
+`touchscreen-drag' event.")
+(register-definition-prefixes "touch-screen" '("touch-screen-"))
+
;;; End of scraped data
diff --git a/lisp/leim/quail/arabic.el b/lisp/leim/quail/arabic.el
index 83a7c12147f..7c693190d89 100644
--- a/lisp/leim/quail/arabic.el
+++ b/lisp/leim/quail/arabic.el
@@ -1,6 +1,6 @@
;;; arabic.el --- Quail package for inputting Arabic -*- coding: utf-8; lexical-binding:t -*-
-;; Copyright (C) 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2024 Free Software Foundation, Inc.
;; Author: James Cloos <cloos@jhcloos.com>
;; Keywords: mule, input method, Arabic
diff --git a/lisp/leim/quail/cham.el b/lisp/leim/quail/cham.el
index 1778fa312c8..b5101ccbebf 100644
--- a/lisp/leim/quail/cham.el
+++ b/lisp/leim/quail/cham.el
@@ -1,6 +1,6 @@
;;; cham.el --- Quail package for inputting Cham characters -*- coding: utf-8; lexical-binding:t -*-
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
;; Author: Eli Zaretskii <eliz@gnu.org>
;; Keywords: i18n
diff --git a/lisp/leim/quail/compose.el b/lisp/leim/quail/compose.el
index 3200943f724..bc52c8efae3 100644
--- a/lisp/leim/quail/compose.el
+++ b/lisp/leim/quail/compose.el
@@ -1,6 +1,6 @@
;;; compose.el --- Quail package for Multi_key character composition -*-coding: utf-8; lexical-binding: t -*-
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
;; Author: Juri Linkov <juri@linkov.net>
;; Keywords: multilingual, input method, i18n
diff --git a/lisp/leim/quail/croatian.el b/lisp/leim/quail/croatian.el
index 84dd8b1e459..2524013fbe9 100644
--- a/lisp/leim/quail/croatian.el
+++ b/lisp/leim/quail/croatian.el
@@ -1,6 +1,6 @@
;;; croatian.el --- Quail package for inputting Croatian -*-coding: utf-8; lexical-binding:t -*-
-;; Copyright (C) 2003-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003-2024 Free Software Foundation, Inc.
;; Author: Hrvoje Nikšić <hrvoje.niksic@avl.com>
;; Keywords: i18n
diff --git a/lisp/leim/quail/cyril-jis.el b/lisp/leim/quail/cyril-jis.el
index f25cc0efe25..4cce8369905 100644
--- a/lisp/leim/quail/cyril-jis.el
+++ b/lisp/leim/quail/cyril-jis.el
@@ -1,6 +1,6 @@
;;; cyril-jis.el --- Quail package for inputting JISX0208 Cyrillic letters -*- lexical-binding: t -*-
-;; Copyright (C) 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2024 Free Software Foundation, Inc.
;; Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
;; 2006, 2007, 2008, 2009, 2010, 2011
;; National Institute of Advanced Industrial Science and Technology (AIST)
diff --git a/lisp/leim/quail/cyrillic.el b/lisp/leim/quail/cyrillic.el
index d0874124fc7..577898f82bd 100644
--- a/lisp/leim/quail/cyrillic.el
+++ b/lisp/leim/quail/cyrillic.el
@@ -1,6 +1,6 @@
;;; cyrillic.el --- Quail package for inputting Cyrillic characters -*- lexical-binding: t -*-
-;; Copyright (C) 1997-1998, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997-1998, 2001-2024 Free Software Foundation, Inc.
;; Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
;; 2006, 2007, 2008, 2009, 2010, 2011
;; National Institute of Advanced Industrial Science and Technology (AIST)
@@ -38,12 +38,12 @@
;; This was `cyrillic-jcuken'. Alexander Mikhailian
;; <mikhailian@altern.org> says: "cyrillic-jcuken" is actually
-;; russian. It is ok but a bit outdated. This layout has been used
+;; Russian. It is ok but a bit outdated. This layout has been used
;; in typewriters for ages but it has been superseded on desktops by
;; a variation of this layout, implemented in M$ Windows software.
;; The Windows layout is greatly preferred because of the comma and
;; period being placed more conveniently and, of course, because of
-;; the popularity of Windows software. This layout is a common option
+;; the popularity of Windows software. This layout is a common option
;; in X Windows and console layouts for GNU/Linux. [See
;; `russian-computer' below.]
(quail-define-package
diff --git a/lisp/leim/quail/czech.el b/lisp/leim/quail/czech.el
index 90ee15ad3b4..5c5390fe6e4 100644
--- a/lisp/leim/quail/czech.el
+++ b/lisp/leim/quail/czech.el
@@ -1,6 +1,6 @@
;;; czech.el --- Quail package for inputting Czech -*-coding: utf-8; lexical-binding:t -*-
-;; Copyright (C) 1998, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998, 2001-2024 Free Software Foundation, Inc.
;; Author: Milan Zamazal <pdm@zamazal.org>
;; Maintainer: Pavel Janík <Pavel@Janik.cz>
diff --git a/lisp/leim/quail/emoji.el b/lisp/leim/quail/emoji.el
index 553b0f8d966..c270898f75c 100644
--- a/lisp/leim/quail/emoji.el
+++ b/lisp/leim/quail/emoji.el
@@ -1,6 +1,6 @@
;;; emoji.el --- Quail package for emoji character composition -*- lexical-binding: t -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;; Author: Juri Linkov <juri@linkov.net>
;; Keywords: multilingual, input method, i18n
diff --git a/lisp/leim/quail/georgian.el b/lisp/leim/quail/georgian.el
index 54501c80bd6..d3a21107ce8 100644
--- a/lisp/leim/quail/georgian.el
+++ b/lisp/leim/quail/georgian.el
@@ -1,6 +1,6 @@
;;; georgian.el --- Quail package for inputting Georgian characters -*- coding: utf-8; lexical-binding:t -*-
-;; Copyright (C) 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2024 Free Software Foundation, Inc.
;; Author: Dave Love <fx@gnu.org>
;; Keywords: i18n
diff --git a/lisp/leim/quail/greek.el b/lisp/leim/quail/greek.el
index 0829097af5f..7cf839f2f58 100644
--- a/lisp/leim/quail/greek.el
+++ b/lisp/leim/quail/greek.el
@@ -1,6 +1,6 @@
;;; greek.el --- Quail package for inputting Greek -*- coding: utf-8; lexical-binding:t -*-
-;; Copyright (C) 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2024 Free Software Foundation, Inc.
;; Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
;; 2006, 2007, 2008, 2009, 2010, 2011
;; National Institute of Advanced Industrial Science and Technology (AIST)
diff --git a/lisp/leim/quail/hangul.el b/lisp/leim/quail/hangul.el
index 46a2e5a6ba2..79526fa5aa8 100644
--- a/lisp/leim/quail/hangul.el
+++ b/lisp/leim/quail/hangul.el
@@ -1,6 +1,6 @@
;;; hangul.el --- Korean Hangul input method -*- lexical-binding: t; -*-
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
;; Author: Jihyun Cho <jihyun.jo@gmail.com>
;; Keywords: multilingual, input method, Korean, Hangul
@@ -146,21 +146,34 @@ Setup `quail-overlay' to the last character."
(progn
(delete-region (region-beginning) (region-end))
(deactivate-mark)))
- (quail-delete-region)
- (let ((first (car queues)))
- (insert
- (hangul-character
- (+ (aref first 0) (hangul-djamo 'cho (aref first 0) (aref first 1)))
- (+ (aref first 2) (hangul-djamo 'jung (aref first 2) (aref first 3)))
- (+ (aref first 4) (hangul-djamo 'jong (aref first 4) (aref first 5))))))
- (move-overlay quail-overlay (overlay-start quail-overlay) (point))
- (dolist (queue (cdr queues))
- (insert
- (hangul-character
- (+ (aref queue 0) (hangul-djamo 'cho (aref queue 0) (aref queue 1)))
- (+ (aref queue 2) (hangul-djamo 'jung (aref queue 2) (aref queue 3)))
- (+ (aref queue 4) (hangul-djamo 'jong (aref queue 4) (aref queue 5)))))
- (move-overlay quail-overlay (1+ (overlay-start quail-overlay)) (point))))
+ (let* ((chars-to-insert
+ (with-temp-buffer
+ (dolist (queue queues (mapcar #'identity (buffer-string)))
+ (insert
+ (hangul-character
+ (+ (aref queue 0) (hangul-djamo 'cho (aref queue 0) (aref queue 1)))
+ (+ (aref queue 2) (hangul-djamo 'jung (aref queue 2) (aref queue 3)))
+ (+ (aref queue 4) (hangul-djamo 'jong (aref queue 4) (aref queue 5))))))))
+ (overwrite-maybe
+ (or
+ ;; If the overlay isn't showing (i.e. it has 0 length) then
+ ;; we may want to insert char overwriting (iff overwrite-mode is
+ ;; non-nil, of course)
+ (= (overlay-start quail-overlay) (overlay-end quail-overlay))
+ ;; Likewise we want to do it if there is more then one
+ ;; character that were combined.
+ (cdr chars-to-insert))))
+ (quail-delete-region) ; this empties the overlay
+ (dolist (c chars-to-insert)
+ (let ((last-command-event c)
+ (overwrite-mode (and overwrite-mode
+ overwrite-maybe
+ overwrite-mode)))
+ (self-insert-command 1)
+ ;; For chars other than fhe first, no more overwrites desired
+ (setq overwrite-maybe nil)))
+ ; this shows the overlay again (TODO: do we really always revive?)
+ (move-overlay quail-overlay (1- (point)) (point))))
(defun hangul-djamo (jamo char1 char2)
"Return the double Jamo index calculated from the arguments.
diff --git a/lisp/leim/quail/hanja.el b/lisp/leim/quail/hanja.el
index 5aa76ad1e82..644c4c3eb53 100644
--- a/lisp/leim/quail/hanja.el
+++ b/lisp/leim/quail/hanja.el
@@ -1,6 +1,6 @@
;;; hanja.el --- Quail-package for Korean Hanja (KSC5601) -*-coding: utf-8; lexical-binding: t -*-
-;; Copyright (C) 1997, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997, 2001-2024 Free Software Foundation, Inc.
;; Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
;; 2006, 2007, 2008, 2009, 2010, 2011
;; National Institute of Advanced Industrial Science and Technology (AIST)
diff --git a/lisp/leim/quail/hanja3.el b/lisp/leim/quail/hanja3.el
index 7b5caa66615..cfcda4fb274 100644
--- a/lisp/leim/quail/hanja3.el
+++ b/lisp/leim/quail/hanja3.el
@@ -1,6 +1,6 @@
;;; hanja3.el --- Quail-package for Korean Hanja (KSC5601) -*-coding: utf-8; lexical-binding: t -*-
-;; Copyright (C) 1997, 1999, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997, 1999, 2001-2024 Free Software Foundation, Inc.
;; Author: Koaunghi Un <koaunghi.un@zdv.uni-tuebingen.de>
;; Keywords: mule, quail, multilingual, input method, Korean, Hanja
diff --git a/lisp/leim/quail/indian.el b/lisp/leim/quail/indian.el
index a30028329c4..c1348081d58 100644
--- a/lisp/leim/quail/indian.el
+++ b/lisp/leim/quail/indian.el
@@ -1,6 +1,6 @@
;;; indian.el --- Quail packages for inputting Indian -*- lexical-binding: t; -*-
-;; Copyright (C) 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2000-2024 Free Software Foundation, Inc.
;; Author: KAWABATA, Taichi <kawabata@m17n.org>
@@ -154,8 +154,8 @@ strings that describe how to insert CONSONANT."
(setq consonants
(sort consonants
(lambda (x y)
- (or (seq-position (car x) quail-tamil-itrans--consonant-order) 1000)
- (or (seq-position (car y) quail-tamil-itrans--consonant-order) 1000))))
+ (< (or (seq-position quail-tamil-itrans--consonant-order (car x)) 1000)
+ (or (seq-position quail-tamil-itrans--consonant-order (car y)) 1000)))))
(let ((virama #x0BCD)
clm)
(with-temp-buffer
diff --git a/lisp/leim/quail/indonesian.el b/lisp/leim/quail/indonesian.el
index 6da2e9a6e86..f486d86479a 100644
--- a/lisp/leim/quail/indonesian.el
+++ b/lisp/leim/quail/indonesian.el
@@ -1,6 +1,6 @@
;;; indonesian.el --- Quail package for inputting Indonesian characters -*- lexical-binding: t; -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;; Author: समीर सिंह Sameer Singh <lumarzeli30@gmail.com>
;; Keywords: multilingual, input method, i18n, Indonesia
diff --git a/lisp/leim/quail/ipa-praat.el b/lisp/leim/quail/ipa-praat.el
index 58d2f5e55fb..be8115e006a 100644
--- a/lisp/leim/quail/ipa-praat.el
+++ b/lisp/leim/quail/ipa-praat.el
@@ -1,6 +1,6 @@
;;; ipa-praat.el --- Inputting IPA characters with the conventions of Praat -*- lexical-binding: t -*-
-;; Copyright (C) 2011-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2011-2024 Free Software Foundation, Inc.
;; Author: Oliver Scholz <epameinondas@gmx.de>
;; Keywords: multilingual, input method, IPA
diff --git a/lisp/leim/quail/ipa.el b/lisp/leim/quail/ipa.el
index 704d18ddc5f..a6a012fd434 100644
--- a/lisp/leim/quail/ipa.el
+++ b/lisp/leim/quail/ipa.el
@@ -1,6 +1,6 @@
;;; ipa.el --- Quail package for inputting IPA characters -*- lexical-binding: t; -*-
-;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
;; Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
;; 2006, 2007, 2008, 2009, 2010, 2011
;; National Institute of Advanced Industrial Science and Technology (AIST)
diff --git a/lisp/leim/quail/japanese.el b/lisp/leim/quail/japanese.el
index 1caaf9d93da..c3dabd68fcd 100644
--- a/lisp/leim/quail/japanese.el
+++ b/lisp/leim/quail/japanese.el
@@ -1,6 +1,6 @@
;;; japanese.el --- Quail package for inputting Japanese -*- lexical-binding: t; -*-
-;; Copyright (C) 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2024 Free Software Foundation, Inc.
;; Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
;; 2006, 2007, 2008, 2009, 2010, 2011
;; National Institute of Advanced Industrial Science and Technology (AIST)
diff --git a/lisp/leim/quail/latin-alt.el b/lisp/leim/quail/latin-alt.el
index e269a47fb02..6d3731ba264 100644
--- a/lisp/leim/quail/latin-alt.el
+++ b/lisp/leim/quail/latin-alt.el
@@ -1,6 +1,6 @@
;;; latin-alt.el --- Quail package for inputting various European characters -*-coding: utf-8; lexical-binding: t -*-
-;; Copyright (C) 1997-1998, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997-1998, 2001-2024 Free Software Foundation, Inc.
;; Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
;; 2008, 2009, 2010, 2011
;; National Institute of Advanced Industrial Science and Technology (AIST)
diff --git a/lisp/leim/quail/latin-ltx.el b/lisp/leim/quail/latin-ltx.el
index 9be3d722504..54c3121873e 100644
--- a/lisp/leim/quail/latin-ltx.el
+++ b/lisp/leim/quail/latin-ltx.el
@@ -1,6 +1,6 @@
;;; latin-ltx.el --- Quail package for TeX-style input -*- lexical-binding: t; -*-
-;; Copyright (C) 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2024 Free Software Foundation, Inc.
;; Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
;; 2010, 2011
;; National Institute of Advanced Industrial Science and Technology (AIST)
diff --git a/lisp/leim/quail/latin-post.el b/lisp/leim/quail/latin-post.el
index 453bea49026..0d2c1888426 100644
--- a/lisp/leim/quail/latin-post.el
+++ b/lisp/leim/quail/latin-post.el
@@ -1,6 +1,6 @@
;;; latin-post.el --- Quail packages for inputting various European characters -*-coding: utf-8; lexical-binding: t -*-
-;; Copyright (C) 1997-1998, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997-1998, 2001-2024 Free Software Foundation, Inc.
;; Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
;; 2006, 2007, 2008, 2009, 2010, 2011
;; National Institute of Advanced Industrial Science and Technology (AIST)
diff --git a/lisp/leim/quail/latin-pre.el b/lisp/leim/quail/latin-pre.el
index f469c1ec941..91164df0c72 100644
--- a/lisp/leim/quail/latin-pre.el
+++ b/lisp/leim/quail/latin-pre.el
@@ -1,6 +1,6 @@
;;; latin-pre.el --- Quail packages for inputting various European characters -*-coding: utf-8; lexical-binding: t -*-
-;; Copyright (C) 1997-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997-2024 Free Software Foundation, Inc.
;; Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
;; 2006, 2007, 2008, 2009, 2010, 2011
;; National Institute of Advanced Industrial Science and Technology (AIST)
@@ -789,9 +789,9 @@ and Silesian (both Steuer and Ślabikŏrzowy szrajbōnek) scripts."
("'Z" ?Ź)
(".z" ?ż)
(".Z" ?Ż)
- ;; Explicit input of prefix characters. Normally, to input a prefix
- ;; character itself, one needs to press <Tab>. Definitions below
- ;; allow to input those characters by entering them twice.
+ ;; Explicit input of prefix characters. Normally, to input a prefix
+ ;; character itself, one needs to press <Tab>. Definitions below
+ ;; allow inputting those characters by entering them twice.
("//" ?/)
("\\\\" ?\\)
("~~" ?~)
diff --git a/lisp/leim/quail/lrt.el b/lisp/leim/quail/lrt.el
index 4e45a951d9f..aa16e5a0982 100644
--- a/lisp/leim/quail/lrt.el
+++ b/lisp/leim/quail/lrt.el
@@ -1,6 +1,6 @@
;;; lrt.el --- Quail package for inputting Lao characters by LRT method -*- lexical-binding: t; -*-
-;; Copyright (C) 1998, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998, 2001-2024 Free Software Foundation, Inc.
;; Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
;; 2006, 2007, 2008, 2009, 2010, 2011
;; National Institute of Advanced Industrial Science and Technology (AIST)
diff --git a/lisp/leim/quail/misc-lang.el b/lisp/leim/quail/misc-lang.el
index e40bccc14f0..fc8fa79243b 100644
--- a/lisp/leim/quail/misc-lang.el
+++ b/lisp/leim/quail/misc-lang.el
@@ -1,6 +1,6 @@
;;; misc-lang.el --- Quail package for inputting Miscellaneous characters -*- lexical-binding: t; -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;; Author: समीर सिंह Sameer Singh <lumarzeli30@gmail.com>
;; Keywords: multilingual, input method, i18n, Miscellaneous
diff --git a/lisp/leim/quail/pakistan.el b/lisp/leim/quail/pakistan.el
new file mode 100644
index 00000000000..7cde2fde3aa
--- /dev/null
+++ b/lisp/leim/quail/pakistan.el
@@ -0,0 +1,726 @@
+;;; pakistan.el --- Input methods for some languages from Pakistan -*- lexical-binding: t; -*-
+;;
+;; Copyright (C) 2023-2024 Free Software Foundation, Inc.
+
+;; Author: Rahguzar <rahguzar@zohomail.eu>
+;; Keywords: convenience, multilingual, input method, Urdu, Balochi, Pashto, Sindhi, Hindko, Brahui
+;;
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+;;
+;;; Commentary:
+;; Provides a semi-phonetic input method for Urdu
+;;
+;;; Code:
+(require 'quail)
+
+;;;; Urdu Input Methods
+;;;;; Keyboard
+;; Layout taken from https://www.branah.com/urdu
+(quail-define-package
+ "urdu-keyboard" "Urdu" "ات" t
+ "Input method for Urdu.
+Uses keyboard layout from https://www.branah.com/urdu"
+ nil t t t t nil nil nil nil nil t)
+
+(quail-define-rules
+ ("q" ?ط)
+ ("w" ?ص)
+ ("e" ?ھ)
+ ("r" ?د)
+ ("t" ?ٹ)
+ ("y" ?پ)
+ ("u" ?ت)
+ ("i" ?ب)
+ ("o" ?ج)
+ ("p" ?ح)
+ ("a" ?م)
+ ("s" ?و)
+ ("d" ?ر)
+ ("f" ?ن)
+ ("g" ?ل)
+ ("h" ?ہ)
+ ("j" ?ا)
+ ("k" ?ک)
+ ("l" ?ی)
+ ("z" ?ق)
+ ("x" ?ف)
+ ("c" ?ے)
+ ("v" ?س)
+ ("b" ?ش)
+ ("n" ?غ)
+ ("m" ?ع)
+ ("Q" ?ظ)
+ ("W" ?ض)
+ ("E" ?ذ)
+ ("R" ?ڈ)
+ ("T" ?ث)
+ ("Y" ?ّ)
+ ("U" ?ۃ)
+ ("I" ?ـ)
+ ("O" ?چ)
+ ("P" ?خ)
+ ("A" ?ژ)
+ ("S" ?ز)
+ ("D" ?ڑ)
+ ("F" ?ں)
+ ("G" ?ۂ)
+ ("H" ?ء)
+ ("J" ?آ)
+ ("K" ?گ)
+ ("L" ?ي)
+ ("C" ?ۓ)
+ ("B" ?ؤ)
+ ("N" ?ئ)
+ ("[" ?\])
+ ("]" ?\[)
+ ("{" ?})
+ ("}" ?{)
+ (";" ?؛)
+ ("." ?۔)
+ ("," ?،)
+ ("?" ?؟))
+
+;;;;; Phonetic Keyboard
+(quail-define-package
+ "urdu-phonetic-keyboard" "Urdu" "اص" t
+ "Input method for Urdu.
+Uses phonetic keyboard layout from https://www.branah.com/urdu"
+ nil t t t t nil nil nil nil nil t)
+
+(quail-define-rules
+ ("q" ?ق)
+ ("w" ?و)
+ ("e" ?ع)
+ ("r" ?ر)
+ ("t" ?ت)
+ ("y" ?ے)
+ ("u" ?ء)
+ ("i" ?ی)
+ ("o" ?ہ)
+ ("p" ?پ)
+ ("a" ?ا)
+ ("s" ?س)
+ ("d" ?د)
+ ("f" ?ف)
+ ("g" ?گ)
+ ("h" ?ح)
+ ("j" ?ج)
+ ("k" ?ک)
+ ("l" ?ل)
+ ("z" ?ز)
+ ("x" ?ش)
+ ("c" ?چ)
+ ("v" ?ط)
+ ("b" ?ب)
+ ("n" ?ن)
+ ("m" ?م)
+ ("Q" ?ْ)
+ ("W" ?ٔ)
+ ("E" ?ٰ)
+ ("R" ?ڑ)
+ ("T" ?ٹ)
+ ("Y" ?َ)
+ ("U" ?ئ)
+ ("I" ?ِ)
+ ("O" ?ۃ)
+ ("P" ?ُ)
+ ("A" ?آ)
+ ("S" ?ص)
+ ("D" ?ڈ)
+ ("F" ?أ)
+ ("G" ?غ)
+ ("H" ?ھ)
+ ("J" ?ض)
+ ("K" ?خ)
+ ("L" ?ٖ)
+ ("Z" ?ذ)
+ ("X" ?ژ)
+ ("C" ?ث)
+ ("V" ?ظ)
+ ("B" ?ً)
+ ("N" ?ں)
+ ("M" ?ّ)
+ ("1" ?۱)
+ ("2" ?۲)
+ ("3" ?۳)
+ ("4" ?۴)
+ ("5" ?۵)
+ ("6" ?٦)
+ ("7" ?۷)
+ ("8" ?۸)
+ ("9" ?۹)
+ ("0" ?۰)
+ ("`" ?؏)
+ ("#" ?ؔ)
+ ("$" ?ؒ)
+ ("%" ?٪)
+ ("^" ?ؓ)
+ ("&" ?ؑ)
+ ("*" ?ؐ)
+ ("(" ?\))
+ (")" ?\()
+ ("=" ?+)
+ (";" ?؛)
+ ("\\" ?÷)
+ ("|" ?x)
+ ("," ?،)
+ ("." ?۔)
+ ("<" ?ٗ)
+ (">" ?.)
+ ("?" ?؟)
+ ("[" ?﷽)
+ ("]" ?ﷲ)
+ ("{" ?ﷺ))
+
+;;;;; Customizable Input Method
+;;;;;; Variable declarations
+;; We define these variables now so that byte-compiler does not complain.
+;; Later they will be changed to custom variables. Their value must be void
+;; here as otherwise cutsom will not initialize them to their standard value.
+(defvar pakistan-urdu-prefixes)
+(defvar pakistan-urdu-translations)
+(defvar pakistan-urdu-diacritics-and-other-symbols)
+(defvar pakistan-urdu-poetic-symbols)
+(defvar pakistan-urdu-religious-symbols)
+(defvar pakistan-urdu-use-roman-digits)
+(defvar pakistan-extra-balochi-brahui-translations)
+(defvar pakistan-extra-pashto-translations)
+(defvar pakistan-extra-saraiki-hindko-translations)
+(defvar pakistan-extra-sindhi-translations)
+
+;;;;;; Helper functions
+(defun pakistan--define-quail-rules (rules &optional prefix package)
+ "Define translations for `urdu-custom' input method as determined by RULES.
+PACKAGE determines the input method and defaults to `urdu-custom'. RULES is
+the list of rules to define, see `quail-defrule' for details. If non-nil
+PREFIX is a string that is prefixed to each string in RULES. PREFIX can be a
+symbol in which case it is looked up in `pakistan-urdu-prefixes' to obtain the
+string."
+ (setq package (or package "urdu-custom"))
+ (when (and prefix (symbolp prefix))
+ (setq prefix (car (alist-get prefix pakistan-urdu-prefixes))))
+ (dolist (rule rules)
+ (quail-defrule (concat prefix (car rule)) (cadr rule) package)))
+
+(defun pakistan--define-numeral-translations (&optional package)
+ "Define translations to translate digits to arabic digits.
+Translations are for PACKAGE which defaults to `urdu-custom'."
+ (pakistan--define-quail-rules
+ '(("0" ?۰)
+ ("1" ?۱)
+ ("2" ?۲)
+ ("3" ?۳)
+ ("4" ?۴)
+ ("5" ?۵)
+ ("6" ?۶)
+ ("7" ?۷)
+ ("8" ?۸)
+ ("9" ?۹)
+ ("%" ?٪))
+ nil package))
+
+(defun pakistan--set-numeral-translations (var val)
+ "VAR should be `pakistan-urdu-use-roman-digits' and VAL its value.
+This is a setter function for the custom-variable."
+ (set-default-toplevel-value var val)
+ (if val
+ (pakistan--regenerate-translations)
+ (pakistan--define-numeral-translations)))
+
+(defun pakistan--regenerate-translations ()
+ "Regenerate the translations for urdu-custom input method."
+ (quail-select-package "urdu-custom")
+ (quail-install-map (list nil))
+ (pakistan--define-quail-rules pakistan-urdu-translations)
+ (unless pakistan-urdu-use-roman-digits
+ (pakistan--define-numeral-translations))
+ (pakistan--define-quail-rules
+ pakistan-urdu-diacritics-and-other-symbols 'diacritics)
+ (pakistan--define-quail-rules pakistan-urdu-poetic-symbols 'poetic)
+ (pakistan--define-quail-rules pakistan-urdu-religious-symbols 'religious)
+ (pakistan--define-quail-rules
+ pakistan-extra-balochi-brahui-translations 'balochi-brahui)
+ (pakistan--define-quail-rules pakistan-extra-pashto-translations 'pashto)
+ (pakistan--define-quail-rules
+ pakistan-extra-saraiki-hindko-translations 'saraiki-hindko)
+ (pakistan--define-quail-rules pakistan-extra-sindhi-translations 'sindhi))
+
+(defun pakistan--set-prefixes (var val)
+ "VAR should be `pakistan-urdu-prefixes' and VAL is the value to be set.
+Setter function for `pakistan-urdu-prefixes'."
+ (set-default-toplevel-value var val)
+ (when (boundp 'pakistan-urdu-use-roman-digits)
+ (pakistan--regenerate-translations)))
+
+(defun pakistan--make-setter (&optional prefix)
+ "Return the setter function.
+The function adds rules to `urdu-custom' with PREFIX."
+ (lambda (var val)
+ (set-default-toplevel-value var val)
+ (if (boundp 'pakistan-urdu-use-roman-digits)
+ (pakistan--regenerate-translations)
+ (pakistan--define-quail-rules val prefix))))
+
+;;;;;; Package definition
+(quail-define-package
+ "urdu-custom" "Urdu" "اا" t
+ "Intuitive and customizable transl input method for Urdu.
+By default this input method doesn't try to follow the common romanization of
+Urdu very closely. The reason for this is allow to for input efficiency. It
+works as follows:
+
+1) All lower case letters on QWERTY keyboard are translated to an urdu
+character. When more than one Urdu letter corresponds to the same Roman
+letter, the most common Urdu letter has been chosen. The frequency analysis
+was done on the basis of Urdu word list at
+https://github.com/urduhack/urdu-words/blob/master/words.txt As a result some
+of the translations are:
+h → ہ
+s → س , c → ص
+z → ز
+
+2) For the next common letter the uppercase English letter is used, e.g.
+r → ر , R → ڑ
+n → ن , N → ں
+
+3) The letter x is used for postfix completions. There are two subcases:
+3a) When more than two urdu letter map to the same roman letter,
+e.g.
+t → ت, T → ٹ , tx → ط , Tx → ۃ
+h → ہ , H → ھ , hx → ح , Hx → ۂ
+s → س , c → ص , sx → ش , S → ث , cx → چ
+z → ز , Z → ض, zx → ذ , Zx → ظ
+3b) The urdu letters that are commonly romanized by a English letter + h
+can be obtained by the same English letter + x i.e.
+gx → غ , cx → چ, kx → خ , sx → ش
+
+4) Y → ژ is somewhat of an abberation. All four of z, Z, zx and Zx are
+used by more common letters. Y is used for ژ because it is sometimes
+pronounced close to Y for some European languages.
+
+These translations can be changed by customizing `pakistan-urdu-translations'.
+
+5) o is used for prefix completion of diacrtics or اعر۱ب as well as some
+poetic and religious symbols. The most common three diacritics are mapped to
+oa → zabr (a for above)
+ob → zer (b for below)
+oo → pesh (o for the circle in pesh)
+
+6) The poetic symbols are also available under G (for غزل), while religious
+symbols are also available under M (for مزہب).
+
+7) Characters from Balochi, Brahui Pashto, Saraiki and Sindhi which are not
+part of Urdu alphabet can also be input. Each set of these sets correspond to
+a different prefixes. See `pakistan-urdu-prefixes' for the prefixes.
+
+The translations and the prefixes described above can be customized. Various
+customization options can be found under the customization group
+`pakistan-urdu-input'."
+ nil t t t t nil nil nil nil nil t)
+
+;;;;;; Customizations
+(defgroup pakistan-urdu-input nil
+ "Customization group for Urdu input methods."
+ :group 'quail)
+
+(defcustom pakistan-urdu-prefixes
+ '((diacritics "o")
+ (poetic "G")
+ (religious "M")
+ (balochi-brahui "B")
+ (pashto "P")
+ (sindhi "C")
+ (saraiki-hindko "X"))
+ "Prefixes for `urdu-custom' input method."
+ :set #'pakistan--set-prefixes
+ :type '(repeat (list symbol string))
+ :version "30.1")
+
+(defcustom pakistan-urdu-translations
+ '(("a" ?ا)
+ ("y" ?ی)
+ ("r" ?ر)
+ ("n" ?ن)
+ ("v" ?و)
+ ("m" ?م)
+ ("t" ?ت)
+ ("l" ?ل)
+ ("k" ?ک)
+ ("b" ?ب)
+ ("d" ?د)
+ ("h" ?ہ)
+ ("s" ?س)
+ ("H" ?ھ)
+ ("p" ?پ)
+ ("N" ?ں)
+ ("g" ?گ)
+ ("sx" ?ش)
+ ("j" ?ج)
+ ("T" ?ٹ)
+ ("f" ?ف)
+ ("cx" ?چ)
+ ("z" ?ز)
+ ("u" ?ع)
+ ("q" ?ق)
+ ("kx" ?خ)
+ ("e" ?ے)
+ ("E" ?ۓ)
+ ("hx" ?ح)
+ ("i" ?ئ)
+ ("R" ?ڑ)
+ ("tx" ?ط)
+ ("c" ?ص)
+ ("D" ?ڈ)
+ ("gx" ?غ)
+ ("A" ?آ)
+ ("Z" ?ض)
+ ("V" ?ؤ)
+ ("zx" ?ذ)
+ ("S" ?ث)
+ ("Zx" ?ظ)
+ ("Hx" ?ۂ)
+ ("ix" ?ء)
+ ("Tx" ?ۃ)
+ ("Y" ?ژ)
+ ("ax" ?أ)
+ ("." ?۔)
+ ("," ?،)
+ (";" ?؛)
+ ("?" ?؟))
+ "Translations for Urdu characters and common punctuations."
+ :set (pakistan--make-setter)
+ :type '(repeat (list string character))
+ :version "30.1")
+
+(defcustom pakistan-urdu-diacritics-and-other-symbols
+ '(("a" ?َ) ;; zabar زبر
+ ("b" ?ِ) ;; zer زير
+ ("o" ?ُ) ;; pesh پيش
+ ("j" ?ْ) ;; jazam جزم
+ ("S" ?ّ) ;; tashdid تشدید
+ ("k" ?ٰ) ;; khari zabar کھڑی زبر
+ ("u" ?٘) ;; ulti jazm الٹی جزم
+ ("s" ?؎)
+ ("m" ?؏)
+ ("t" ?ؔ)
+ ("c" ?ؐ)
+ ("r" ?ؒ)
+ ("R" ?ؓ)
+ ("A" ?ؑ))
+ "Translations to input Urdu diacrtics.
+These are available under the prefix specified in `pakistan-urdu-prefixes'."
+ :set (pakistan--make-setter 'diacritics)
+ :type '(repeat (list string character))
+ :version "30.1")
+
+(defcustom pakistan-urdu-poetic-symbols
+ '(("s" ?؎)
+ ("m" ?؏)
+ ("t" ?ؔ))
+ "Translation to input Urdu peotic symbols.
+These are available under the prefix specified in `pakistan-urdu-prefixes'."
+ :set (pakistan--make-setter 'poetic)
+ :type '(repeat (list string character))
+ :version "30.1")
+
+(defcustom pakistan-urdu-religious-symbols
+ '(("s" ?ؐ)
+ ("r" ?ؒ)
+ ("R" ?ؓ)
+ ("a" ?ؑ)
+ ("A" ?ﷲ)
+ ("S" ?ﷺ))
+ "Translation to input Urdu peotic symbols.
+These are available under the prefix specified in `pakistan-urdu-prefixes'."
+ :set (pakistan--make-setter 'religious)
+ :type '(repeat (list string character))
+ :version "30.1")
+
+;; I don't understand how many of these letters are pronounced.
+;; So better translations are welcome.
+(defcustom pakistan-extra-balochi-brahui-translations
+ '(("v" ?ۏ)
+ ("y" ?ݔ)
+;; Brahui
+ ("l" ?ڷ))
+ "Translations to input Balochi and Brahui letters not found in Urdu.
+These are available under the prefix specified in `pakistan-urdu-prefixes'."
+ :set (pakistan--make-setter 'balochi-brahui)
+ :type '(repeat (list string character))
+ :version "30.1")
+
+(defcustom pakistan-extra-pashto-translations
+ '(("t" ?ټ)
+ ("d" ?ډ)
+ ("r" ?ړ)
+ ("n" ?ڼ)
+ ("s" ?ښ)
+ ("R" ?ږ)
+ ("h" ?څ)
+ ("H" ?ځ))
+ "Translations to input Pashto letters not found in Urdu.
+These are available under the prefix specified in `pakistan-urdu-prefixes'."
+ :set (pakistan--make-setter 'pashto)
+ :type '(repeat (list string character))
+ :version "30.1")
+
+(defcustom pakistan-extra-sindhi-translations
+ '(("k" ?ڪ)
+ ("j" ?ڄ)
+ ("t" ?ٺ)
+ ("T" ?ٽ)
+ ("tx" ?ٿ)
+ ("b" ?ٻ)
+ ("B" ?ڀ)
+ ("r" ?ڙ)
+ ("d" ?ڌ)
+ ("D" ?ڏ)
+ ("dx" ?ڊ)
+ ("Dx" ?ڍ)
+ ("h" ?ڃ)
+ ("c" ?ڇ)
+ ("p" ?ڦ)
+ ("n" ?ڻ)
+ ("g" ?ڳ)
+ ("G" ?ڱ))
+ "Translations to input Sindhi letters not found in Urdu.
+These are available under the prefix specified in `pakistan-urdu-prefixes'."
+ :set (pakistan--make-setter 'sindhi)
+ :type '(repeat (list string character))
+ :version "30.1")
+
+(defcustom pakistan-extra-saraiki-hindko-translations
+ '(("b" ?ٻ)
+ ("h" ?ڄ)
+ ("g" ?ڳ)
+ ("d" ?ݙ)
+ ("n" ?ݨ)
+;; Hindko
+ ("r" ?ݬ)
+ ("v" ?ڨ)
+ ("N" ?ݩ)
+ ("V" ?ٷ))
+"Translations to input Saraiki letters not found in Urdu.
+These are available under the prefix specified in `pakistan-urdu-prefixes'."
+ :set (pakistan--make-setter 'saraiki-hindko)
+ :type '(repeat (list string character))
+ :version "30.1")
+
+(defcustom pakistan-urdu-use-roman-digits
+ nil
+ "Whether urdu-custom input method should use roman digits."
+ :set #'pakistan--set-numeral-translations
+ :type 'boolean
+ :version "30.1")
+
+;;;; Sindhi Input Methods
+;;;;; Keyboard
+;; Layout taken from https://www.branah.com/sindhi
+(quail-define-package
+ "sindhi-keyboard" "Sindhi" "سِ" t
+ "Input method for Sindhi.
+Uses keyboard layout from https://www.branah.com/sindhi ."
+ nil t t t t nil nil nil nil nil t)
+
+(quail-define-rules
+ ("q" ?ق)
+ ("w" ?ص)
+ ("e" ?ي)
+ ("r" ?ر)
+ ("t" ?ت)
+ ("y" ?ٿ)
+ ("u" ?ع)
+ ("i" ?ڳ)
+ ("o" ?و)
+ ("p" ?پ)
+ ("a" ?ا)
+ ("s" ?س)
+ ("d" ?د)
+ ("f" ?ف)
+ ("g" ?گ)
+ ("h" ?ه)
+ ("j" ?ج)
+ ("k" ?ڪ)
+ ("l" ?ل)
+ ("z" ?ز)
+ ("x" ?خ)
+ ("c" ?ط)
+ ("v" ?ڀ)
+ ("b" ?ب)
+ ("n" ?ن)
+ ("m" ?م)
+ ("Q" ?َ)
+ ("W" ?ض)
+ ("E" ?ِ)
+ ("R" ?ڙ)
+ ("T" ?ٽ)
+ ("Y" ?ث)
+ ("U" ?غ)
+ ("I" ?ھ)
+ ("O" ?ُ)
+ ("P" ?ڦ)
+ ("A" ?آ)
+ ("S" ?ش)
+ ("D" ?ڊ)
+ ("F" ?ڦ)
+ ("G" ?ً)
+ ("H" ?ح)
+ ("J" ?ٍ)
+ ("K" ?ۡ)
+ ("L" ?:)
+ ("Z" ?ذ)
+ ("X" ?ّ)
+ ("C" ?ظ)
+ ("V" ?ء)
+ ("B" ?ٻ)
+ ("N" ?ڻ)
+ ("M" ?۾)
+ ("1" ?۱)
+ ("2" ?۲)
+ ("3" ?۳)
+ ("4" ?۴)
+ ("5" ?۵)
+ ("6" ?٦)
+ ("7" ?۷)
+ ("8" ?۸)
+ ("9" ?۹)
+ ("0" ?۰)
+ ("`" ?’)
+ ("-" ?ڏ)
+ ("=" ?ڌ)
+ ("~" ?‘)
+ ("@" ?ى)
+ ("#" ?ؔ)
+ ("$" ?ؒ)
+ ("%" ?٪)
+ ("^" ?ؓ)
+ ("&" ?۽)
+ ("*" ?ؤ)
+ ("(" ?\))
+ (")" ?\()
+ ("[" ?ڇ)
+ ("]" ?چ)
+ ("{" ?ڃ)
+ ("}" ?ڄ)
+ (";" ?ک)
+ ("'" ?ڱ)
+ ("\\" ?ڍ)
+ (":" ?؛)
+ ("|" ?ٺ)
+ ("," ?،)
+ ("/" ?ئ)
+ ("<" ?“)
+ (">" ?”)
+ ("?" ?؟))
+
+
+;;;; Pashto Input Methods
+;;;;; Keyboard
+(quail-define-package
+ "pashto-keyboard" "Pashto" "پ" t
+ "Input method for Pashto.
+Uses keyboard layout from https://www.branah.com/pashto ."
+ nil t t t t nil nil nil nil nil t)
+
+(quail-define-rules
+ ("q" ?ض)
+ ("w" ?ص)
+ ("e" ?ث)
+ ("r" ?ق)
+ ("t" ?ف)
+ ("y" ?غ)
+ ("u" ?ع)
+ ("i" ?ه)
+ ("o" ?خ)
+ ("p" ?ح)
+ ("a" ?ش)
+ ("s" ?س)
+ ("d" ?ی)
+ ("f" ?ب)
+ ("g" ?ل)
+ ("h" ?ا)
+ ("j" ?ت)
+ ("k" ?ن)
+ ("l" ?م)
+ ("z" ?ۍ)
+ ("x" ?ې)
+ ("c" ?ز)
+ ("v" ?ر)
+ ("b" ?ذ)
+ ("n" ?د)
+ ("m" ?ړ)
+ ("Q" ?ْ)
+ ("W" ?ٌ)
+ ("E" ?ٍ)
+ ("R" ?ً)
+ ("T" ?ُ)
+ ("Y" ?ِ)
+ ("U" ?َ)
+ ("I" ?ّ)
+ ("O" ?څ)
+ ("P" ?ځ)
+ ("A" ?ښ)
+ ("S" ?ﺉ)
+ ("D" ?ي)
+ ("F" ?پ)
+ ("G" ?أ)
+ ("H" ?آ)
+ ("J" ?ټ)
+ ("K" ?ڼ)
+ ("L" ?ة)
+ ("Z" ?ظ)
+ ("X" ?ط)
+ ("C" ?ژ)
+ ("V" ?ء)
+ ("B" ?‌)
+ ("N" ?ډ)
+ ("M" ?ؤ)
+ ("1" ?۱)
+ ("2" ?۲)
+ ("3" ?۳)
+ ("4" ?۴)
+ ("5" ?۵)
+ ("6" ?۶)
+ ("7" ?۷)
+ ("8" ?۸)
+ ("9" ?۹)
+ ("0" ?۰)
+ ("`" ?‍)
+ ("~" ?÷)
+ ("@" ?٬)
+ ("#" ?٫)
+ ("%" ?٪)
+ ("^" ?×)
+ ("&" ?«)
+ ("*" ?»)
+ ("_" ?ـ)
+ ("[" ?ج)
+ ("]" ?چ)
+ ("{" ?\[)
+ ("}" ?\])
+ (";" ?ک)
+ ("'" ?ګ)
+ ("\"" ?؛)
+ ("|" ?٭)
+ ("," ?و)
+ ("." ?ږ)
+ ("<" ?،)
+ (">" ?.)
+ ("?" ?؟))
+
+;;; End Matter
+(provide 'pakistan)
+;;; pakistan.el ends here
diff --git a/lisp/leim/quail/persian.el b/lisp/leim/quail/persian.el
index 758d2951292..de61481d7f1 100644
--- a/lisp/leim/quail/persian.el
+++ b/lisp/leim/quail/persian.el
@@ -1,6 +1,6 @@
;;; persian.el --- Quail package for inputting Persian/Farsi keyboard -*- coding: utf-8; lexical-binding: t -*-
-;; Copyright (C) 2011-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2011-2024 Free Software Foundation, Inc.
;; Author: Mohsen BANAN <emacs@mohsen.1.banan.byname.net>
;; URL: http://mohsen.1.banan.byname.net/contact
diff --git a/lisp/leim/quail/philippine.el b/lisp/leim/quail/philippine.el
index 8ed6e570b7d..2d063e7b0a4 100644
--- a/lisp/leim/quail/philippine.el
+++ b/lisp/leim/quail/philippine.el
@@ -1,6 +1,6 @@
;;; philippine.el --- Quail package for inputting Philippine characters -*- lexical-binding: t; -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;; Author: समीर सिंह Sameer Singh <lumarzeli30@gmail.com>
;; Keywords: multilingual, input method, i18n, Philippines
diff --git a/lisp/leim/quail/programmer-dvorak.el b/lisp/leim/quail/programmer-dvorak.el
index eb12bd9dd22..719a85b0e51 100644
--- a/lisp/leim/quail/programmer-dvorak.el
+++ b/lisp/leim/quail/programmer-dvorak.el
@@ -1,6 +1,6 @@
;;; programmer-dvorak.el --- Quail package for the programmer Dvorak layout -*- lexical-binding: t -*-
-;; Copyright (C) 2015-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2024 Free Software Foundation, Inc.
;; Author: Joakim Jalap <joakim.jalap@fastmail.com>
diff --git a/lisp/leim/quail/py-punct.el b/lisp/leim/quail/py-punct.el
index 71ed55bd5f5..3cc6739ba0b 100644
--- a/lisp/leim/quail/py-punct.el
+++ b/lisp/leim/quail/py-punct.el
@@ -1,6 +1,6 @@
;;; py-punct.el --- Quail packages for Chinese (pinyin + extra symbols) -*- lexical-binding: t -*-
-;; Copyright (C) 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2024 Free Software Foundation, Inc.
;; Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
;; 2006, 2007, 2008, 2009, 2010, 2011
;; National Institute of Advanced Industrial Science and Technology (AIST)
diff --git a/lisp/leim/quail/rfc1345.el b/lisp/leim/quail/rfc1345.el
index 0aba396b111..a635fd2568b 100644
--- a/lisp/leim/quail/rfc1345.el
+++ b/lisp/leim/quail/rfc1345.el
@@ -1,6 +1,6 @@
;;; rfc1345.el --- Quail method for RFC 1345 mnemonics -*- coding: utf-8; lexical-binding: t -*-
-;; Copyright (C) 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2024 Free Software Foundation, Inc.
;; Author: Dave Love <fx@gnu.org>
;; Keywords: i18n
diff --git a/lisp/leim/quail/sami.el b/lisp/leim/quail/sami.el
index 7e878f780fc..8620577c968 100644
--- a/lisp/leim/quail/sami.el
+++ b/lisp/leim/quail/sami.el
@@ -1,6 +1,6 @@
;;; sami.el --- Quail package for inputting Sámi -*-coding: utf-8; lexical-binding: t -*-
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
;; Author: Wojciech S. Gac <wojciech.s.gac@gmail.com>
;; Keywords: i18n, multilingual, input method, Sámi
diff --git a/lisp/leim/quail/sgml-input.el b/lisp/leim/quail/sgml-input.el
index 66f6658db3e..c411d781a2f 100644
--- a/lisp/leim/quail/sgml-input.el
+++ b/lisp/leim/quail/sgml-input.el
@@ -1,6 +1,6 @@
;;; sgml-input.el --- Quail method for Unicode entered as SGML entities -*- coding: utf-8; lexical-binding: t -*-
-;; Copyright (C) 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2024 Free Software Foundation, Inc.
;; Author: Dave Love <fx@gnu.org>
;; Keywords: i18n
diff --git a/lisp/leim/quail/sisheng.el b/lisp/leim/quail/sisheng.el
index 0961799c4ac..2f6db572b99 100644
--- a/lisp/leim/quail/sisheng.el
+++ b/lisp/leim/quail/sisheng.el
@@ -1,6 +1,6 @@
;;; sisheng.el --- sisheng input method for Chinese pinyin transliteration -*- lexical-binding: t; -*-
-;; Copyright (C) 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2004-2024 Free Software Foundation, Inc.
;; Author: Werner LEMBERG <wl@gnu.org>
diff --git a/lisp/leim/quail/slovak.el b/lisp/leim/quail/slovak.el
index 8996575fe78..dc0591f4f84 100644
--- a/lisp/leim/quail/slovak.el
+++ b/lisp/leim/quail/slovak.el
@@ -1,6 +1,6 @@
;;; slovak.el --- Quail package for inputting Slovak -*-coding: utf-8; lexical-binding: t -*-
-;; Copyright (C) 1998, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998, 2001-2024 Free Software Foundation, Inc.
;; Authors: Tibor Šimko <tibor.simko@fmph.uniba.sk>
;; Milan Zamazal <pdm@zamazal.org>
diff --git a/lisp/leim/quail/symbol-ksc.el b/lisp/leim/quail/symbol-ksc.el
index 7588922dc07..78334055127 100644
--- a/lisp/leim/quail/symbol-ksc.el
+++ b/lisp/leim/quail/symbol-ksc.el
@@ -1,6 +1,6 @@
;;; symbol-ksc.el --- Quail-package for Korean Symbol (KSC5601) -*-coding: utf-8; lexical-binding: t -*-
-;; Copyright (C) 1997, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997, 2001-2024 Free Software Foundation, Inc.
;; Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
;; 2006, 2007, 2008, 2009, 2010, 2011
;; National Institute of Advanced Industrial Science and Technology (AIST)
diff --git a/lisp/leim/quail/tamil-dvorak.el b/lisp/leim/quail/tamil-dvorak.el
index 7b4be6b7a43..7d8f7969d45 100644
--- a/lisp/leim/quail/tamil-dvorak.el
+++ b/lisp/leim/quail/tamil-dvorak.el
@@ -1,6 +1,6 @@
;;; tamil-dvorak.el --- Quail package for Tamil input with Dvorak keyboard -*- lexical-binding: t -*-
-;; Copyright (C) 2015-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2024 Free Software Foundation, Inc.
;; Author: Shakthi Kannan <author@shakthimaan.com>
diff --git a/lisp/leim/quail/tibetan.el b/lisp/leim/quail/tibetan.el
index d28d7be3b95..1cc7c22d12c 100644
--- a/lisp/leim/quail/tibetan.el
+++ b/lisp/leim/quail/tibetan.el
@@ -1,6 +1,6 @@
;;; tibetan.el --- Quail package for inputting Tibetan characters -*-coding: utf-8-emacs; lexical-binding: t; -*-
-;; Copyright (C) 1997, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997, 2001-2024 Free Software Foundation, Inc.
;; Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
;; 2006, 2007, 2008, 2009, 2010, 2011
;; National Institute of Advanced Industrial Science and Technology (AIST)
diff --git a/lisp/leim/quail/uni-input.el b/lisp/leim/quail/uni-input.el
index 46cc5d043fc..59ac47fffac 100644
--- a/lisp/leim/quail/uni-input.el
+++ b/lisp/leim/quail/uni-input.el
@@ -1,6 +1,6 @@
;;; uni-input.el --- Hex Unicode input method -*- lexical-binding: t; -*-
-;; Copyright (C) 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2024 Free Software Foundation, Inc.
;; Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
;; National Institute of Advanced Industrial Science and Technology (AIST)
;; Registration Number H14PRO021
diff --git a/lisp/leim/quail/vntelex.el b/lisp/leim/quail/vntelex.el
index 4f412090cfc..d37baa4007c 100644
--- a/lisp/leim/quail/vntelex.el
+++ b/lisp/leim/quail/vntelex.el
@@ -1,6 +1,6 @@
;;; vntelex.el --- Quail package for Vietnamese by Telex method -*- lexical-binding: t -*-
-;; Copyright (C) 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2024 Free Software Foundation, Inc.
;; Author: Werner Lemberg <wl@gnu.org>
;; Keywords: multilingual, input method, Vietnamese
diff --git a/lisp/leim/quail/vnvni.el b/lisp/leim/quail/vnvni.el
index b9b0f77e032..59d1a82eb21 100644
--- a/lisp/leim/quail/vnvni.el
+++ b/lisp/leim/quail/vnvni.el
@@ -1,6 +1,6 @@
;;; vnvni.el --- Quail package for Vietnamese by VNI method -*- lexical-binding: t -*-
-;; Copyright (C) 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2024 Free Software Foundation, Inc.
;; Author: Werner Lemberg <wl@gnu.org>
;; Nguyen Thai Ngoc Duy <pclouds@gmail.com>
diff --git a/lisp/leim/quail/welsh.el b/lisp/leim/quail/welsh.el
index a7799b6e5c3..349667d2df0 100644
--- a/lisp/leim/quail/welsh.el
+++ b/lisp/leim/quail/welsh.el
@@ -1,6 +1,6 @@
;;; welsh.el --- Quail package for inputting Welsh characters -*- coding: utf-8; lexical-binding: t -*-
-;; Copyright (C) 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2024 Free Software Foundation, Inc.
;; Author: Dave Love <fx@gnu.org>
;; Keywords: i18n
diff --git a/lisp/loadhist.el b/lisp/loadhist.el
index eb87016695c..ece95ed619b 100644
--- a/lisp/loadhist.el
+++ b/lisp/loadhist.el
@@ -1,6 +1,6 @@
;;; loadhist.el --- lisp functions for working with feature groups -*- lexical-binding: t -*-
-;; Copyright (C) 1995, 1998, 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1995, 1998, 2000-2024 Free Software Foundation, Inc.
;; Author: Eric S. Raymond <esr@thyrsus.com>
;; Maintainer: emacs-devel@gnu.org
@@ -108,7 +108,8 @@ from a file."
features))
features)))))
-(defvaralias 'loadhist-hook-functions 'unload-feature-special-hooks)
+(define-obsolete-variable-alias 'loadhist-hook-functions
+ 'unload-feature-special-hooks "30.1")
(defvar unload-feature-special-hooks
'(after-change-functions after-insert-file-functions
after-make-frame-functions auto-coding-functions
@@ -148,14 +149,14 @@ documentation of `unload-feature' for details.")
(save-current-buffer
(dolist (buffer (buffer-list))
(set-buffer buffer)
- (let ((proposed major-mode))
+ (let ((proposed (derived-mode-all-parents major-mode)))
;; Look for a predecessor mode not defined in the feature we're processing
- (while (and proposed (rassq proposed unload-function-defs-list))
- (setq proposed (get proposed 'derived-mode-parent)))
- (unless (eq proposed major-mode)
+ (while (and proposed (rassq (car proposed) unload-function-defs-list))
+ (setq proposed (cdr proposed)))
+ (unless (eq (car proposed) major-mode)
;; Two cases: either proposed is nil, and we want to switch to fundamental
;; mode, or proposed is not nil and not major-mode, and so we use it.
- (funcall (or proposed 'fundamental-mode)))))))
+ (funcall (or (car proposed) 'fundamental-mode)))))))
(defvar loadhist-unload-filename nil)
diff --git a/lisp/loadup.el b/lisp/loadup.el
index 38fb0fc1fa9..c498c0e53af 100644
--- a/lisp/loadup.el
+++ b/lisp/loadup.el
@@ -1,6 +1,6 @@
;;; loadup.el --- load up standardly loaded Lisp files for Emacs -*- lexical-binding: t; -*-
-;; Copyright (C) 1985-1986, 1992, 1994, 2001-2023 Free Software
+;; Copyright (C) 1985-1986, 1992, 1994, 2001-2024 Free Software
;; Foundation, Inc.
;; Maintainer: emacs-devel@gnu.org
@@ -248,7 +248,7 @@
(load "simple")
(load "emacs-lisp/seq")
(load "emacs-lisp/nadvice")
-(load "minibuffer") ;Needs cl-generic (and define-minor-mode).
+(load "minibuffer") ; Needs cl-generic, seq (and define-minor-mode).
(load "frame")
(load "startup")
(load "term/tty-colors")
@@ -298,12 +298,9 @@
(if (featurep 'dynamic-setting)
(load "dynamic-setting"))
-;; touch-screen.el is tiny and is used liberally throughout the button
-;; code etc, so it may as well be preloaded everywhere.
-(load "touch-screen")
-
(if (featurep 'x)
(progn
+ (load "touch-screen")
(load "x-dnd")
(load "term/common-win")
(load "term/x-win")))
@@ -316,6 +313,7 @@
(if (featurep 'android)
(progn
(load "ls-lisp")
+ (load "touch-screen")
(load "term/common-win")
(load "term/android-win")))
@@ -389,6 +387,9 @@
(load "tooltip"))
(load "international/iso-transl") ; Binds Alt-[ and friends.
+;; Used by `kill-buffer', for instance.
+(load "emacs-lisp/rmc")
+
;; This file doesn't exist when building a development version of Emacs
;; from the repository. It is generated just after temacs is built.
(load "leim/leim-list.el" t)
@@ -408,8 +409,17 @@
(message "Warning: Change in load-path due to site-load will be \
lost after dumping")))
-;; Used by `kill-buffer', for instance.
-(load "emacs-lisp/rmc")
+;; Actively check for advised functions during preload since:
+;; - advices in Emacs's core are generally considered bad style;
+;; - `Snarf-documentation' looses docstrings of primitives advised
+;; during preload (bug#66032#20).
+(mapatoms
+ (lambda (f)
+ (and (advice--p (symbol-function f))
+ ;; Don't make it an error because it's not serious enough and
+ ;; it can be annoying during development. Also there are still
+ ;; circumstances where we use advice on preloaded functions.
+ (message "Warning: Advice installed on preloaded function %S" f))))
;; Make sure default-directory is unibyte when dumping. This is
;; because we cannot decode and encode it correctly (since the locale
@@ -496,23 +506,23 @@ lost after dumping")))
;; At this point, we're ready to resume undo recording for scratch.
(buffer-enable-undo "*scratch*")
-(defvar comp-subr-arities-h)
-(when (featurep 'native-compile)
- ;; Save the arity for all primitives so the compiler can always
- ;; retrive it even in case of redefinition.
- (mapatoms (lambda (f)
- (when (subr-primitive-p (symbol-function f))
- (puthash f (func-arity f) comp-subr-arities-h))))
- ;; Fix the compilation unit filename to have it working when
- ;; installed or if the source directory got moved. This is set to be
- ;; a pair in the form of:
- ;; (rel-filename-from-install-bin . rel-filename-from-local-bin).
- (let ((bin-dest-dir (cadr (member "--bin-dest" command-line-args)))
- (eln-dest-dir (cadr (member "--eln-dest" command-line-args))))
- (when (and bin-dest-dir eln-dest-dir)
+(defvar load--bin-dest-dir nil
+ "Store the original value passed by \"--bin-dest\" during dump.
+Internal use only.")
+(defvar load--eln-dest-dir nil
+ "Store the original value passed by \"--eln-dest\" during dump.
+Internal use only.")
+
+(defun load--fixup-all-elns ()
+ "Fix all compilation unit filename.
+This to have it working when installed or if Emacs source
+directory got moved. This is set to be a pair in the form of:
+\(rel-filename-from-install-bin . rel-filename-from-local-bin)."
+ (when (and load--bin-dest-dir load--eln-dest-dir)
(setq eln-dest-dir
- (concat eln-dest-dir "native-lisp/" comp-native-version-dir "/"))
+ (concat load--eln-dest-dir "native-lisp/" comp-native-version-dir "/"))
(maphash (lambda (_ cu)
+ (when (stringp (native-comp-unit-file cu))
(let* ((file (native-comp-unit-file cu))
(preloaded (equal (substring (file-name-directory file)
-10 -1)
@@ -529,10 +539,20 @@ lost after dumping")))
(file-name-nondirectory
file)
eln-dest-dir-eff)
- bin-dest-dir)
+ load--bin-dest-dir)
;; Relative filename from the built uninstalled binary.
- (file-relative-name file invocation-directory)))))
- comp-loaded-comp-units-h)))
+ (file-relative-name file invocation-directory))))))
+ comp-loaded-comp-units-h)))
+
+(defvar comp-subr-arities-h)
+(when (featurep 'native-compile)
+ ;; Save the arity for all primitives so the compiler can always
+ ;; retrieve it even in case of redefinition.
+ (mapatoms (lambda (f)
+ (when (subr-primitive-p (symbol-function f))
+ (puthash f (func-arity f) comp-subr-arities-h))))
+ (setq load--bin-dest-dir (cadr (member "--bin-dest" command-line-args)))
+ (setq load--eln-dest-dir (cadr (member "--eln-dest" command-line-args)))
;; Set up the mechanism to allow inhibiting native-comp via
;; file-local variables.
(defvar comp--no-native-compile (make-hash-table :test #'equal)))
diff --git a/lisp/locate.el b/lisp/locate.el
index 63386e18ebb..d86e7fa678f 100644
--- a/lisp/locate.el
+++ b/lisp/locate.el
@@ -1,6 +1,6 @@
;;; locate.el --- interface to the locate command -*- lexical-binding:t -*-
-;; Copyright (C) 1996, 1998, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996, 1998, 2001-2024 Free Software Foundation, Inc.
;; Author: Peter Breton <pbreton@cs.umb.edu>
;; Keywords: unix files
@@ -141,13 +141,11 @@ system, or of all files that you have access to. Consult the
documentation of that program for the details about how it determines
which file names match SEARCH-STRING. (Those details vary highly with
the version.)"
- :type 'string
- :group 'locate)
+ :type 'string)
(defcustom locate-post-command-hook nil
"List of hook functions run after `locate' (see `run-hooks')."
- :type 'hook
- :group 'locate)
+ :type 'hook)
(defvar locate-history-list nil
"The history list used by the \\[locate] command.")
@@ -162,13 +160,11 @@ This function should take one argument, a string (the name to find)
and return a list of strings. The first element of the list should be
the name of a command to be executed by a shell, the remaining elements
should be the arguments to that command (including the name to find)."
- :type 'function
- :group 'locate)
+ :type 'function)
(defcustom locate-buffer-name "*Locate*"
"Name of the buffer to show results from the \\[locate] command."
- :type 'string
- :group 'locate)
+ :type 'string)
(defcustom locate-fcodes-file nil
"File name for the database of file names used by `locate'.
@@ -179,20 +175,17 @@ Just setting this variable does not actually change the database
that `locate' searches. The executive program that the Emacs
function `locate' uses, as given by the variables `locate-command'
or `locate-make-command-line', determines the database."
- :type '(choice (const :tag "None" nil) file)
- :group 'locate)
+ :type '(choice (const :tag "None" nil) file))
(defcustom locate-header-face nil
"Face used to highlight the locate header."
- :type '(choice (const :tag "None" nil) face)
- :group 'locate)
+ :type '(choice (const :tag "None" nil) face))
;;;###autoload
(defcustom locate-ls-subdir-switches (purecopy "-al")
"`ls' switches for inserting subdirectories in `*Locate*' buffers.
This should contain the \"-l\" switch, but not the \"-F\" or \"-b\" switches."
:type 'string
- :group 'locate
:version "22.1")
(defcustom locate-update-when-revert nil
@@ -202,13 +195,11 @@ If non-nil, offer to update the locate database when reverting that buffer.
option `locate-update-path'.)
If nil, reverting does not update the locate database."
:type 'boolean
- :group 'locate
:version "22.1")
(defcustom locate-update-command "updatedb"
"The executable program used to update the locate database."
- :type 'string
- :group 'locate)
+ :type 'string)
(defcustom locate-update-path "/"
"The default directory from where `locate-update-command' is called.
@@ -218,7 +209,6 @@ can be achieved by setting this option to \"/su::\" or \"/sudo::\"
permissions are sufficient to run the command, you can set this
option to \"/\"."
:type 'string
- :group 'locate
:version "22.1")
(defcustom locate-prompt-for-command nil
@@ -227,13 +217,11 @@ Otherwise, that behavior is invoked via a prefix argument.
Setting this option non-nil actually inverts the meaning of a prefix arg;
that is, with a prefix arg, you get the default behavior."
- :group 'locate
:type 'boolean)
(defcustom locate-mode-hook nil
"List of hook functions run by `locate-mode' (see `run-mode-hooks')."
- :type 'hook
- :group 'locate)
+ :type 'hook)
;; Functions
@@ -371,17 +359,17 @@ except that FILTER is not optional."
(defvar locate-mode-map
(let ((map (copy-keymap dired-mode-map)))
;; Undefine Useless Dired Menu bars
- (define-key map [menu-bar Dired] 'undefined)
- (define-key map [menu-bar subdir] 'undefined)
- (define-key map [menu-bar mark executables] 'undefined)
- (define-key map [menu-bar mark directory] 'undefined)
- (define-key map [menu-bar mark directories] 'undefined)
- (define-key map [menu-bar mark symlinks] 'undefined)
- (define-key map [M-mouse-2] 'locate-mouse-view-file)
- (define-key map "\C-c\C-t" 'locate-tags)
- (define-key map "l" 'locate-do-redisplay)
- (define-key map "U" 'dired-unmark-all-files)
- (define-key map "V" 'locate-find-directory)
+ (define-key map [menu-bar Dired] #'undefined)
+ (define-key map [menu-bar subdir] #'undefined)
+ (define-key map [menu-bar mark executables] #'undefined)
+ (define-key map [menu-bar mark directory] #'undefined)
+ (define-key map [menu-bar mark directories] #'undefined)
+ (define-key map [menu-bar mark symlinks] #'undefined)
+ (define-key map [M-mouse-2] #'locate-mouse-view-file)
+ (define-key map "\C-c\C-t" #'locate-tags)
+ (define-key map "l" #'locate-do-redisplay)
+ (define-key map "U" #'dired-unmark-all-files)
+ (define-key map "V" #'locate-find-directory)
map)
"Local keymap for Locate mode buffers.")
@@ -486,7 +474,7 @@ do not work in subdirectories.
(setq-local revert-buffer-function #'locate-update)
(setq-local page-delimiter "\n\n"))
-(put 'locate-mode 'derived-mode-parent 'dired-mode)
+(derived-mode-add-parents 'locate-mode '(dired-mode special-mode))
(defun locate-do-setup (search-string)
(goto-char (point-min))
diff --git a/lisp/lpr.el b/lisp/lpr.el
index 6b8343b695d..c860c633b73 100644
--- a/lisp/lpr.el
+++ b/lisp/lpr.el
@@ -1,6 +1,6 @@
;;; lpr.el --- print Emacs buffer on line printer -*- lexical-binding: t -*-
-;; Copyright (C) 1985, 1988, 1992, 1994, 2001-2023 Free Software
+;; Copyright (C) 1985, 1988, 1992, 1994, 2001-2024 Free Software
;; Foundation, Inc.
;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/ls-lisp.el b/lisp/ls-lisp.el
index b0f86839740..89f0238cf74 100644
--- a/lisp/ls-lisp.el
+++ b/lisp/ls-lisp.el
@@ -1,6 +1,6 @@
;;; ls-lisp.el --- emulate insert-directory completely in Emacs Lisp -*- lexical-binding: t -*-
-;; Copyright (C) 1992, 1994, 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1992, 1994, 2000-2024 Free Software Foundation, Inc.
;; Author: Sebastian Kremer <sk@thp.uni-koeln.de>
;; Modified by: Francis J. Wright <F.J.Wright@maths.qmw.ac.uk>
@@ -161,15 +161,15 @@ systems, set your locale instead."
((eq ls-lisp-emulation 'MS-Windows)
(if (and (fboundp 'w32-using-nt) (w32-using-nt))
'(links))) ; distinguish NT/2K from 9x
- ((eq ls-lisp-emulation 'UNIX) '(links uid)) ; UNIX ls
- (t '(links uid gid))) ; GNU ls
+ ((eq ls-lisp-emulation 'UNIX) '(links uid modes)) ; UNIX ls
+ (t '(links uid gid modes))) ; GNU ls
"A list of optional file attributes that ls-lisp should display.
It should contain none or more of the symbols: links, uid, gid.
A value of nil (or an empty list) means display none of them.
Concepts come from UNIX: `links' means count of names associated with
the file; `uid' means user (owner) identifier; `gid' means group
-identifier.
+identifier; `modes' means Unix-style permission bits (drwxrwxrwx).
If emulation is MacOS then default is nil;
if emulation is MS-Windows then default is `(links)' if platform is
@@ -180,7 +180,8 @@ if emulation is GNU then default is `(links uid gid)'."
;; Functionality suggested by Howard Melman <howard@silverstream.com>
:type '(set (const :tag "Show Link Count" links)
(const :tag "Show User" uid)
- (const :tag "Show Group" gid))
+ (const :tag "Show Group" gid)
+ (const :tag "Show Modes" modes))
:group 'ls-lisp)
(defcustom ls-lisp-use-insert-directory-program
@@ -248,89 +249,69 @@ to fail to line up, e.g. if month names are not all of the same length."
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(defun ls-lisp--insert-directory (orig-fun file switches &optional wildcard full-directory-p)
+(defun ls-lisp--insert-directory (file switches wildcard full-directory-p)
"Insert directory listing for FILE, formatted according to SWITCHES.
-Leaves point after the inserted text.
-SWITCHES may be a string of options, or a list of strings.
-Optional third arg WILDCARD means treat FILE as shell wildcard.
-Optional fourth arg FULL-DIRECTORY-P means file is a directory and
-switches do not contain `d', so that a full listing is expected.
-
-This version of the function comes from `ls-lisp.el'.
-If the value of `ls-lisp-use-insert-directory-program' is non-nil then
-this advice just delegates the work to ORIG-FUN (the normal `insert-directory'
-function from `files.el').
-But if the value of `ls-lisp-use-insert-directory-program' is nil
-then it runs a Lisp emulation.
-
-The Lisp emulation does not run any external programs or shells. It
-supports ordinary shell wildcards if `ls-lisp-support-shell-wildcards'
+This implementation of `insert-directory' works using Lisp functions rather
+than `insert-directory-program'.
+
+This Lisp emulation does not run any external programs or shells.
+ It supports ordinary shell wildcards if `ls-lisp-support-shell-wildcards'
is non-nil; otherwise, it interprets wildcards as regular expressions
to match file names. It does not support all `ls' switches -- those
that work are: A a B C c F G g h i n R r S s t U u v X. The l switch
is assumed to be always present and cannot be turned off.
Long variants of the above switches, as documented for GNU `ls',
are also supported; unsupported long options are silently ignored."
- (if ls-lisp-use-insert-directory-program
- (funcall orig-fun
- file switches wildcard full-directory-p)
- ;; We need the directory in order to find the right handler.
- (setq switches (or switches ""))
- (let ((handler (find-file-name-handler (expand-file-name file)
- 'insert-directory))
- (orig-file file)
- wildcard-regexp
- (ls-lisp-dirs-first
- (or ls-lisp-dirs-first
- (string-match "--group-directories-first" switches))))
- (if handler
- (funcall handler 'insert-directory file switches
- wildcard full-directory-p)
- (when (string-match "--group-directories-first" switches)
- ;; if ls-lisp-dirs-first is nil, dirs are grouped but come out in
- ;; reverse order:
- (setq ls-lisp-dirs-first t)
- (setq switches (replace-match "" nil nil switches)))
- ;; Remove unrecognized long options, and convert the
- ;; recognized ones to their short variants.
- (setq switches (ls-lisp--sanitize-switches switches))
- ;; Convert SWITCHES to a list of characters.
- (setq switches (delete ?\ (delete ?- (append switches nil))))
- ;; Sometimes we get ".../foo*/" as FILE. While the shell and
- ;; `ls' don't mind, we certainly do, because it makes us think
- ;; there is no wildcard, only a directory name.
- (if (and ls-lisp-support-shell-wildcards
- (string-match "[[?*]" file)
- ;; Prefer an existing file to wildcards, like
- ;; dired-noselect does.
- (not (file-exists-p file)))
- (progn
- (or (not (eq (aref file (1- (length file))) ?/))
- (setq file (substring file 0 (1- (length file)))))
- (setq wildcard t)))
- (if wildcard
- (setq wildcard-regexp
- (if ls-lisp-support-shell-wildcards
- (wildcard-to-regexp (file-name-nondirectory file))
- (file-name-nondirectory file))
- file (file-name-directory file))
- (if (memq ?B switches) (setq wildcard-regexp "[^~]\\'")))
- (condition-case err
- (ls-lisp-insert-directory
- file switches (ls-lisp-time-index switches)
- wildcard-regexp full-directory-p)
- (invalid-regexp
- ;; Maybe they wanted a literal file that just happens to
- ;; use characters special to shell wildcards.
- (if (equal (cadr err) "Unmatched [ or [^")
- (progn
- (setq wildcard-regexp (if (memq ?B switches) "[^~]\\'")
- file (file-relative-name orig-file))
- (ls-lisp-insert-directory
- file switches (ls-lisp-time-index switches)
- nil full-directory-p))
- (signal (car err) (cdr err)))))))))
-(advice-add 'insert-directory :around #'ls-lisp--insert-directory)
+ (setq switches (or switches ""))
+ (let ((orig-file file)
+ wildcard-regexp
+ (ls-lisp-dirs-first
+ (or ls-lisp-dirs-first
+ (string-match "--group-directories-first" switches))))
+ (when (string-match "--group-directories-first" switches)
+ ;; if ls-lisp-dirs-first is nil, dirs are grouped but come out in
+ ;; reverse order:
+ (setq ls-lisp-dirs-first t)
+ (setq switches (replace-match "" nil nil switches)))
+ ;; Remove unrecognized long options, and convert the
+ ;; recognized ones to their short variants.
+ (setq switches (ls-lisp--sanitize-switches switches))
+ ;; Convert SWITCHES to a list of characters.
+ (setq switches (delete ?\ (delete ?- (append switches nil))))
+ ;; Sometimes we get ".../foo*/" as FILE. While the shell and
+ ;; `ls' don't mind, we certainly do, because it makes us think
+ ;; there is no wildcard, only a directory name.
+ (if (and ls-lisp-support-shell-wildcards
+ (string-match "[[?*]" file)
+ ;; Prefer an existing file to wildcards, like
+ ;; dired-noselect does.
+ (not (file-exists-p file)))
+ (progn
+ (or (not (eq (aref file (1- (length file))) ?/))
+ (setq file (substring file 0 (1- (length file)))))
+ (setq wildcard t)))
+ (if wildcard
+ (setq wildcard-regexp
+ (if ls-lisp-support-shell-wildcards
+ (wildcard-to-regexp (file-name-nondirectory file))
+ (file-name-nondirectory file))
+ file (file-name-directory file))
+ (if (memq ?B switches) (setq wildcard-regexp "[^~]\\'")))
+ (condition-case err
+ (ls-lisp-insert-directory
+ file switches (ls-lisp-time-index switches)
+ wildcard-regexp full-directory-p)
+ (invalid-regexp
+ ;; Maybe they wanted a literal file that just happens to
+ ;; use characters special to shell wildcards.
+ (if (equal (cadr err) "Unmatched [ or [^")
+ (progn
+ (setq wildcard-regexp (if (memq ?B switches) "[^~]\\'")
+ file (file-relative-name orig-file))
+ (ls-lisp-insert-directory
+ file switches (ls-lisp-time-index switches)
+ nil full-directory-p))
+ (signal (car err) (cdr err)))))))
(defun ls-lisp-insert-directory
(file switches time-index wildcard-regexp full-directory-p)
@@ -468,50 +449,6 @@ not contain `d', so that a full listing is expected."
"Directory doesn't exist or is inaccessible"
file))))))
-(declare-function dired-read-dir-and-switches "dired" (str))
-(declare-function dired-goto-next-file "dired" ())
-
-(defun ls-lisp--dired (orig-fun dir-or-list &optional switches)
- (interactive (dired-read-dir-and-switches ""))
- (unless dir-or-list
- (setq dir-or-list default-directory))
- (if (consp dir-or-list)
- (funcall orig-fun dir-or-list switches)
- (let ((dir-wildcard (insert-directory-wildcard-in-dir-p
- (expand-file-name dir-or-list))))
- (if (not dir-wildcard)
- (funcall orig-fun dir-or-list switches)
- (let* ((default-directory (car dir-wildcard))
- (wildcard (cdr dir-wildcard))
- (files (file-expand-wildcards wildcard))
- (dir (car dir-wildcard)))
- ;; When the wildcard ends in a slash, file-expand-wildcards
- ;; returns nil; fix that by treating the wildcards as
- ;; specifying only directories whose names match the
- ;; widlcard.
- (if (and (null files)
- (directory-name-p wildcard))
- (setq files
- (delq nil
- (mapcar (lambda (fname)
- (if (file-accessible-directory-p fname)
- fname))
- (file-expand-wildcards
- (directory-file-name wildcard))))))
- (if files
- (let ((inhibit-read-only t)
- (buf
- (apply orig-fun (nconc (list dir) files) (and switches (list switches)))))
- (with-current-buffer buf
- (save-excursion
- (goto-char (point-min))
- (dired-goto-next-file)
- (forward-line 0)
- (insert " wildcard " (cdr dir-wildcard) "\n"))))
- (user-error "No files matching wildcard")))))))
-
-(advice-add 'dired :around #'ls-lisp--dired)
-
(defun ls-lisp-sanitize (file-alist)
"Sanitize the elements in FILE-ALIST.
Fixes any elements in the alist for directory entries whose file
@@ -808,7 +745,9 @@ SWITCHES and TIME-INDEX give the full switch list and time data."
(* 1024.0 (fceiling (/ file-size 1024.0)))))
(format ls-lisp-filesize-b-fmt
(fceiling (/ file-size 1024.0)))))
- drwxrwxrwx ; attribute string
+ (if (memq 'modes ls-lisp-verbosity)
+ drwxrwxrwx ; modes string
+ (substring drwxrwxrwx 0 4)) ; "d" or "-" for directory vs file
(if (memq 'links ls-lisp-verbosity)
(format "%3d" (file-attribute-link-number file-attr)))
;; Numeric uid/gid are more confusing than helpful;
@@ -897,13 +836,6 @@ All ls time options, namely c, t and u, are handled."
file-size)
(format " %7s" (file-size-human-readable file-size))))
-(defun ls-lisp-unload-function ()
- "Unload ls-lisp library."
- (advice-remove 'insert-directory #'ls-lisp--insert-directory)
- (advice-remove 'dired #'ls-lisp--dired)
- ;; Continue standard unloading.
- nil)
-
(defun ls-lisp--sanitize-switches (switches)
"Convert long options of GNU \"ls\" to their short form.
Conversion is done only for flags supported by ls-lisp.
diff --git a/lisp/macros.el b/lisp/macros.el
index 98ee3dc52f9..0a04bad762a 100644
--- a/lisp/macros.el
+++ b/lisp/macros.el
@@ -1,6 +1,6 @@
;;; macros.el --- non-primitive commands for keyboard macros -*- lexical-binding:t -*-
-;; Copyright (C) 1985-1987, 1992, 1994-1995, 2001-2023 Free Software
+;; Copyright (C) 1985-1987, 1992, 1994-1995, 2001-2024 Free Software
;; Foundation, Inc.
;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/mail/binhex.el b/lisp/mail/binhex.el
index 15f598fa224..2eac5dacc77 100644
--- a/lisp/mail/binhex.el
+++ b/lisp/mail/binhex.el
@@ -1,6 +1,6 @@
;;; binhex.el --- decode BinHex-encoded text -*- lexical-binding:t -*-
-;; Copyright (C) 1998-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-2024 Free Software Foundation, Inc.
;; Author: Shenghuo Zhu <zsh@cs.rochester.edu>
;; Keywords: binhex news
diff --git a/lisp/mail/blessmail.el b/lisp/mail/blessmail.el
index a9f9828926c..47e9bb58e06 100644
--- a/lisp/mail/blessmail.el
+++ b/lisp/mail/blessmail.el
@@ -1,6 +1,6 @@
;;; blessmail.el --- decide whether movemail needs special privileges -*- no-byte-compile: t; lexical-binding: t; -*-
-;; Copyright (C) 1994, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1994, 2001-2024 Free Software Foundation, Inc.
;; Maintainer: emacs-devel@gnu.org
;; Keywords: internal
diff --git a/lisp/mail/emacsbug.el b/lisp/mail/emacsbug.el
index bebaad720db..e89e66cc7cb 100644
--- a/lisp/mail/emacsbug.el
+++ b/lisp/mail/emacsbug.el
@@ -1,6 +1,6 @@
;;; emacsbug.el --- command to report Emacs bugs to appropriate mailing list -*- lexical-binding: t; -*-
-;; Copyright (C) 1985-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1985-2024 Free Software Foundation, Inc.
;; Author: K. Shane Hartman
;; Maintainer: emacs-devel@gnu.org
@@ -233,9 +233,11 @@ Already submitted bugs can be found in the Emacs bug tracker:
(set-frame-parameter nil 'unsplittable nil))
(error nil))
(compose-mail report-emacs-bug-address topic)
+ (rfc822-goto-eoh)
+ (insert "X-Debbugs-Cc: \n")
;; The rest of this does not execute if the user was asked to
;; confirm and said no.
- (when (eq major-mode 'message-mode)
+ (when (derived-mode-p 'message-mode)
;; Message-mode sorts the headers before sending. We sort now so
;; that report-emacs-bug-orig-text remains valid. (Bug#5178)
(message-sort-headers)
@@ -509,7 +511,7 @@ Message buffer where you can explain more about the patch."
(list (read-string (format-prompt "This patch is about" guess)
nil nil guess)
file)))
- (switch-to-buffer "*Patch Help*")
+ (pop-to-buffer-same-window "*Patch Help*")
(let ((inhibit-read-only t))
(erase-buffer)
(insert "Thank you for considering submitting a patch to the Emacs project.\n\n"
diff --git a/lisp/mail/flow-fill.el b/lisp/mail/flow-fill.el
index 7136e186ff1..919490ec5aa 100644
--- a/lisp/mail/flow-fill.el
+++ b/lisp/mail/flow-fill.el
@@ -1,6 +1,6 @@
;;; flow-fill.el --- interpret RFC2646 "flowed" text -*- lexical-binding:t -*-
-;; Copyright (C) 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2000-2024 Free Software Foundation, Inc.
;; Author: Simon Josefsson <jas@pdc.kth.se>
;; Keywords: mail
diff --git a/lisp/mail/footnote.el b/lisp/mail/footnote.el
index 4b2770ee3a1..dda099ac013 100644
--- a/lisp/mail/footnote.el
+++ b/lisp/mail/footnote.el
@@ -1,6 +1,6 @@
;;; footnote.el --- footnote support for message mode -*- lexical-binding:t -*-
-;; Copyright (C) 1997, 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997, 2000-2024 Free Software Foundation, Inc.
;; Author: Steven L Baur <steve@xemacs.org> (1997-2011)
;; Boruch Baum <boruch_baum@gmx.com> (2017-)
diff --git a/lisp/mail/hashcash.el b/lisp/mail/hashcash.el
index ecc03bfb537..cf7ad006c31 100644
--- a/lisp/mail/hashcash.el
+++ b/lisp/mail/hashcash.el
@@ -1,6 +1,6 @@
;;; hashcash.el --- Add hashcash payments to email -*- lexical-binding:t -*-
-;; Copyright (C) 2003-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003-2024 Free Software Foundation, Inc.
;; Written by: Paul Foley <mycroft@actrix.gen.nz> (1997-2002)
;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/mail/ietf-drums-date.el b/lisp/mail/ietf-drums-date.el
index b2cceb5cef2..ef8e9f8f32e 100644
--- a/lisp/mail/ietf-drums-date.el
+++ b/lisp/mail/ietf-drums-date.el
@@ -1,8 +1,9 @@
;;; ietf-drums-date.el --- parse time/date for ietf-drums.el -*- lexical-binding: t -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;; Author: Bob Rogers <rogers@rgrjr.com>
+;; Package: ietf-drums
;; Keywords: mail, util
;; This file is part of GNU Emacs.
diff --git a/lisp/mail/ietf-drums.el b/lisp/mail/ietf-drums.el
index aa714292bcc..eaccbff0b13 100644
--- a/lisp/mail/ietf-drums.el
+++ b/lisp/mail/ietf-drums.el
@@ -1,6 +1,6 @@
;;; ietf-drums.el --- Functions for parsing RFC 2822 headers -*- lexical-binding:t -*-
-;; Copyright (C) 1998-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-2024 Free Software Foundation, Inc.
;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
;; This file is part of GNU Emacs.
diff --git a/lisp/mail/mail-extr.el b/lisp/mail/mail-extr.el
index 71621f588e7..668cae05521 100644
--- a/lisp/mail/mail-extr.el
+++ b/lisp/mail/mail-extr.el
@@ -1,6 +1,6 @@
;;; mail-extr.el --- extract full name and address from email header -*- lexical-binding: t; -*-
-;; Copyright (C) 1991-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1991-2024 Free Software Foundation, Inc.
;; Author: Joe Wells <jbw@cs.bu.edu>
;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/mail/mail-hist.el b/lisp/mail/mail-hist.el
index 40be8d0f350..01ea5bb9617 100644
--- a/lisp/mail/mail-hist.el
+++ b/lisp/mail/mail-hist.el
@@ -1,6 +1,6 @@
;;; mail-hist.el --- headers and message body history for outgoing mail -*- lexical-binding: t; -*-
-;; Copyright (C) 1994-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1994-2024 Free Software Foundation, Inc.
;; Author: Karl Fogel <kfogel@red-bean.com>
;; Created: March, 1994
diff --git a/lisp/mail/mail-parse.el b/lisp/mail/mail-parse.el
index 7a6b351bff3..efaecc37b7d 100644
--- a/lisp/mail/mail-parse.el
+++ b/lisp/mail/mail-parse.el
@@ -1,6 +1,6 @@
;;; mail-parse.el --- Interface functions for parsing mail -*- lexical-binding: t -*-
-;; Copyright (C) 1998-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-2024 Free Software Foundation, Inc.
;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
;; This file is part of GNU Emacs.
diff --git a/lisp/mail/mail-prsvr.el b/lisp/mail/mail-prsvr.el
index 1487c32e9ed..7a261e64b24 100644
--- a/lisp/mail/mail-prsvr.el
+++ b/lisp/mail/mail-prsvr.el
@@ -1,6 +1,6 @@
;;; mail-prsvr.el --- Interface variables for parsing mail -*- lexical-binding: t -*-
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
;; This file is part of GNU Emacs.
diff --git a/lisp/mail/mail-utils.el b/lisp/mail/mail-utils.el
index a6a4545cf04..c9e4d0b3812 100644
--- a/lisp/mail/mail-utils.el
+++ b/lisp/mail/mail-utils.el
@@ -1,6 +1,6 @@
;;; mail-utils.el --- utility functions used both by rmail and rnews -*- lexical-binding: t -*-
-;; Copyright (C) 1985, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1985, 2001-2024 Free Software Foundation, Inc.
;; Maintainer: emacs-devel@gnu.org
;; Keywords: mail, news
diff --git a/lisp/mail/mailabbrev.el b/lisp/mail/mailabbrev.el
index 8b95820cdf8..68d325ea261 100644
--- a/lisp/mail/mailabbrev.el
+++ b/lisp/mail/mailabbrev.el
@@ -1,6 +1,6 @@
;;; mailabbrev.el --- abbrev-expansion of mail aliases -*- lexical-binding: t; -*-
-;; Copyright (C) 1985-1987, 1992-1993, 1996-1997, 2000-2023 Free
+;; Copyright (C) 1985-1987, 1992-1993, 1996-1997, 2000-2024 Free
;; Software Foundation, Inc.
;; Author: Jamie Zawinski <jwz@lucid.com; now jwz@jwz.org>
diff --git a/lisp/mail/mailalias.el b/lisp/mail/mailalias.el
index e3e4122039b..cce2fcb104d 100644
--- a/lisp/mail/mailalias.el
+++ b/lisp/mail/mailalias.el
@@ -1,6 +1,6 @@
;;; mailalias.el --- expand and complete mailing address aliases -*- lexical-binding: t -*-
-;; Copyright (C) 1985, 1987, 1995-1997, 2001-2023 Free Software
+;; Copyright (C) 1985, 1987, 1995-1997, 2001-2024 Free Software
;; Foundation, Inc.
;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/mail/mailclient.el b/lisp/mail/mailclient.el
index 613541e5dc4..1233d9ace95 100644
--- a/lisp/mail/mailclient.el
+++ b/lisp/mail/mailclient.el
@@ -1,6 +1,6 @@
;;; mailclient.el --- mail sending via system's mail client. -*- lexical-binding: t; -*-
-;; Copyright (C) 2005-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2005-2024 Free Software Foundation, Inc.
;; Author: David Reitter <david.reitter@gmail.com>
;; Keywords: mail
diff --git a/lisp/mail/mailheader.el b/lisp/mail/mailheader.el
index 92ea13a11f1..fd212d35a57 100644
--- a/lisp/mail/mailheader.el
+++ b/lisp/mail/mailheader.el
@@ -1,6 +1,6 @@
;;; mailheader.el --- mail header parsing, merging, formatting -*- lexical-binding: t; -*-
-;; Copyright (C) 1996, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996, 2001-2024 Free Software Foundation, Inc.
;; Author: Erik Naggum <erik@naggum.no>
;; Keywords: tools, mail, news
diff --git a/lisp/mail/mspools.el b/lisp/mail/mspools.el
index b5e4efa6be8..d20bab206c4 100644
--- a/lisp/mail/mspools.el
+++ b/lisp/mail/mspools.el
@@ -1,6 +1,6 @@
;;; mspools.el --- show mail spools waiting to be read -*- lexical-binding: t; -*-
-;; Copyright (C) 1997, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997, 2001-2024 Free Software Foundation, Inc.
;; Author: Stephen Eglen <stephen@gnu.org>
;; Created: 22 Jan 1997
diff --git a/lisp/mail/qp.el b/lisp/mail/qp.el
index 08f843e28f8..9e92eb635d2 100644
--- a/lisp/mail/qp.el
+++ b/lisp/mail/qp.el
@@ -1,6 +1,6 @@
;;; qp.el --- Quoted-Printable functions -*- lexical-binding:t -*-
-;; Copyright (C) 1998-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-2024 Free Software Foundation, Inc.
;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
;; Keywords: mail, extensions
diff --git a/lisp/mail/reporter.el b/lisp/mail/reporter.el
index 1271be16151..c35d109b928 100644
--- a/lisp/mail/reporter.el
+++ b/lisp/mail/reporter.el
@@ -1,6 +1,6 @@
;;; reporter.el --- customizable bug reporting of lisp programs -*- lexical-binding: t; -*-
-;; Copyright (C) 1993-1998, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1993-1998, 2001-2024 Free Software Foundation, Inc.
;; Author: 1993-1998 Barry A. Warsaw
;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/mail/rfc2045.el b/lisp/mail/rfc2045.el
index 123519ad777..0b498b306c1 100644
--- a/lisp/mail/rfc2045.el
+++ b/lisp/mail/rfc2045.el
@@ -1,6 +1,6 @@
;;; rfc2045.el --- Functions for decoding rfc2045 headers -*- lexical-binding:t -*-
-;; Copyright (C) 1998-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-2024 Free Software Foundation, Inc.
;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
;; This file is part of GNU Emacs.
diff --git a/lisp/mail/rfc2047.el b/lisp/mail/rfc2047.el
index b30a3779aa7..e122fe8c9b5 100644
--- a/lisp/mail/rfc2047.el
+++ b/lisp/mail/rfc2047.el
@@ -1,6 +1,6 @@
;;; rfc2047.el --- functions for encoding and decoding rfc2047 messages -*- lexical-binding:t -*-
-;; Copyright (C) 1998-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-2024 Free Software Foundation, Inc.
;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
;; MORIOKA Tomohiko <morioka@jaist.ac.jp>
diff --git a/lisp/mail/rfc2231.el b/lisp/mail/rfc2231.el
index 8c156927589..33324cafb5b 100644
--- a/lisp/mail/rfc2231.el
+++ b/lisp/mail/rfc2231.el
@@ -1,6 +1,6 @@
;;; rfc2231.el --- Functions for decoding rfc2231 headers -*- lexical-binding:t -*-
-;; Copyright (C) 1998-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-2024 Free Software Foundation, Inc.
;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
;; This file is part of GNU Emacs.
diff --git a/lisp/mail/rfc6068.el b/lisp/mail/rfc6068.el
index a0d03ac7908..06fe92f0ca7 100644
--- a/lisp/mail/rfc6068.el
+++ b/lisp/mail/rfc6068.el
@@ -1,6 +1,6 @@
;;; rfc6068.el --- support for rfc6068 -*- lexical-binding: t -*-
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
;; Keywords: mail
diff --git a/lisp/mail/rfc822.el b/lisp/mail/rfc822.el
index 866e5d7a1cc..e0145c4043b 100644
--- a/lisp/mail/rfc822.el
+++ b/lisp/mail/rfc822.el
@@ -1,6 +1,6 @@
;;; rfc822.el --- hairy RFC 822 (or later) parser for mail, news, etc. -*- lexical-binding: t; -*-
-;; Copyright (C) 1986-1987, 1990, 2001-2023 Free Software Foundation,
+;; Copyright (C) 1986-1987, 1990, 2001-2024 Free Software Foundation,
;; Inc.
;; Author: Richard Mlynarik <mly@eddie.mit.edu>
diff --git a/lisp/mail/rmail-spam-filter.el b/lisp/mail/rmail-spam-filter.el
index dd7fad0ad9c..98d54c25035 100644
--- a/lisp/mail/rmail-spam-filter.el
+++ b/lisp/mail/rmail-spam-filter.el
@@ -1,6 +1,6 @@
;;; rmail-spam-filter.el --- spam filter for Rmail, the Emacs mail reader -*- lexical-binding: t; -*-
-;; Copyright (C) 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2024 Free Software Foundation, Inc.
;; Keywords: email, spam, filter, rmail
;; Author: Eli Tziperman <eli AT deas.harvard.edu>
;; Package: rmail
diff --git a/lisp/mail/rmail.el b/lisp/mail/rmail.el
index 716848dc34f..74cf297c2fc 100644
--- a/lisp/mail/rmail.el
+++ b/lisp/mail/rmail.el
@@ -1,6 +1,6 @@
;;; rmail.el --- main code of "RMAIL" mail reader for Emacs -*- lexical-binding:t -*-
-;; Copyright (C) 1985-1988, 1993-1998, 2000-2023 Free Software
+;; Copyright (C) 1985-1988, 1993-1998, 2000-2024 Free Software
;; Foundation, Inc.
;; Maintainer: emacs-devel@gnu.org
@@ -90,7 +90,6 @@
its character representation and its display representation.")
(defvar deleted-head)
-(defvar font-lock-fontified)
(defvar mail-abbrev-syntax-table)
(defvar mail-abbrevs)
(defvar messages-head)
@@ -4612,6 +4611,16 @@ Argument MIME is non-nil if this is a mime message."
;; Decode any base64-encoded material in what we just decrypted.
(rmail-epa-decode armor-start after-end)
+ ;; If this is in a MIME part, convert CRLF into just LF (newline)
+ (when mime
+ (save-restriction
+ (narrow-to-region armor-start (- (point-max) after-end))
+ (goto-char (point-min))
+ (let ((inhibit-read-only t))
+ (while (search-forward "\r\n" nil t)
+ (delete-region (- (point) 2) (- (point) 1)))))
+ )
+
(list armor-start (- (point-max) after-end) mime
armor-end-regexp
(buffer-substring armor-start (- (point-max) after-end)))))
@@ -4655,7 +4664,33 @@ Argument MIME is non-nil if this is a mime message."
(push (rmail-epa-decrypt-1 mime) decrypts))))
(when (and decrypts (rmail-buffers-swapped-p))
- (when (y-or-n-p "Replace the original message? ")
+ (if (not (y-or-n-p "Replace the original message? "))
+ ;; User wants to decrypt only temporarily.
+ ;; Find, in the view buffer, the armors
+ ;; that we made decrypts for, and replace each one
+ ;; with its decrypt. In a mime part, replace CRLF with NL.
+ (dolist (d decrypts)
+ (if (re-search-forward "-----BEGIN PGP MESSAGE-----$" nil t)
+ (let (armor-start armor-end armor-end-regexp)
+ (setq armor-start (match-beginning 0)
+ armor-end-regexp (nth 3 d)
+ armor-end (re-search-forward
+ armor-end-regexp
+ nil t))
+
+ ;; Found as expected -- now replace it with the decrypt.
+ (when armor-end
+ (if (null (nth 2 d))
+ nil
+ ;; In a mime part --
+ ;; replace CRLF with NL in it.
+ (save-restriction
+ (narrow-to-region armor-start armor-end)
+ (goto-char (point-min))
+ (while (search-forward "\r\n" nil t)
+ (delete-region (- (point) 2) (- (point) 1))))))
+ )))
+ ;; User wants to decrypt the message perenently.
(when (eq major-mode 'rmail-mode)
(rmail-add-label "decrypt"))
(setq decrypts (nreverse decrypts))
diff --git a/lisp/mail/rmailedit.el b/lisp/mail/rmailedit.el
index b65777acc34..0c4b74c97da 100644
--- a/lisp/mail/rmailedit.el
+++ b/lisp/mail/rmailedit.el
@@ -1,6 +1,6 @@
;;; rmailedit.el --- "RMAIL edit mode" Edit the current message -*- lexical-binding: t; -*-
-;; Copyright (C) 1985, 1994, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1985, 1994, 2001-2024 Free Software Foundation, Inc.
;; Maintainer: emacs-devel@gnu.org
;; Keywords: mail
diff --git a/lisp/mail/rmailkwd.el b/lisp/mail/rmailkwd.el
index 82d91ff7870..d9c4cb8cfee 100644
--- a/lisp/mail/rmailkwd.el
+++ b/lisp/mail/rmailkwd.el
@@ -1,6 +1,6 @@
;;; rmailkwd.el --- part of the "RMAIL" mail reader for Emacs -*- lexical-binding: t; -*-
-;; Copyright (C) 1985, 1988, 1994, 2001-2023 Free Software Foundation,
+;; Copyright (C) 1985, 1988, 1994, 2001-2024 Free Software Foundation,
;; Inc.
;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/mail/rmailmm.el b/lisp/mail/rmailmm.el
index d2688118b97..422fe3a7227 100644
--- a/lisp/mail/rmailmm.el
+++ b/lisp/mail/rmailmm.el
@@ -1,6 +1,6 @@
;;; rmailmm.el --- MIME decoding and display stuff for RMAIL -*- lexical-binding: t; -*-
-;; Copyright (C) 2006-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2006-2024 Free Software Foundation, Inc.
;; Author: Alexander Pohoyda
;; Alex Schroeder
diff --git a/lisp/mail/rmailmsc.el b/lisp/mail/rmailmsc.el
index b8258d584fc..01962bf79e0 100644
--- a/lisp/mail/rmailmsc.el
+++ b/lisp/mail/rmailmsc.el
@@ -1,6 +1,6 @@
;;; rmailmsc.el --- miscellaneous support functions for the RMAIL mail reader -*- lexical-binding: t; -*-
-;; Copyright (C) 1985, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1985, 2001-2024 Free Software Foundation, Inc.
;; Maintainer: emacs-devel@gnu.org
;; Keywords: mail
diff --git a/lisp/mail/rmailout.el b/lisp/mail/rmailout.el
index 6d61dcd8208..1aa430c18c9 100644
--- a/lisp/mail/rmailout.el
+++ b/lisp/mail/rmailout.el
@@ -1,6 +1,6 @@
;;; rmailout.el --- "RMAIL" mail reader for Emacs: output message to a file -*- lexical-binding: t; -*-
-;; Copyright (C) 1985, 1987, 1993-1994, 2001-2023 Free Software
+;; Copyright (C) 1985, 1987, 1993-1994, 2001-2024 Free Software
;; Foundation, Inc.
;; Maintainer: emacs-devel@gnu.org
@@ -453,7 +453,7 @@ display message number MSG."
(narrow-to-region (point-max) (point-max)))
(insert-buffer-substring tembuf)
(rmail-count-new-messages t)
- ;; FIXME should re-use existing windows.
+ ;; FIXME should reuse existing windows.
(if (rmail-summary-exists)
(rmail-select-summary (rmail-update-summary)))
(rmail-show-message-1 msg)))
diff --git a/lisp/mail/rmailsort.el b/lisp/mail/rmailsort.el
index c2e358c5524..d897b0e76d9 100644
--- a/lisp/mail/rmailsort.el
+++ b/lisp/mail/rmailsort.el
@@ -1,6 +1,6 @@
;;; rmailsort.el --- Rmail: sort messages -*- lexical-binding: t; -*-
-;; Copyright (C) 1990, 1993-1994, 2001-2023 Free Software Foundation,
+;; Copyright (C) 1990, 1993-1994, 2001-2024 Free Software Foundation,
;; Inc.
;; Author: Masanobu UMEDA <umerin@mse.kyutech.ac.jp>
diff --git a/lisp/mail/rmailsum.el b/lisp/mail/rmailsum.el
index e3a6c16933b..18a36e5f0e9 100644
--- a/lisp/mail/rmailsum.el
+++ b/lisp/mail/rmailsum.el
@@ -1,6 +1,6 @@
;;; rmailsum.el --- make summary buffers for the mail reader -*- lexical-binding:t -*-
-;; Copyright (C) 1985, 1993-1996, 2000-2023 Free Software Foundation,
+;; Copyright (C) 1985, 1993-1996, 2000-2024 Free Software Foundation,
;; Inc.
;; Maintainer: emacs-devel@gnu.org
@@ -52,7 +52,7 @@ Setting this option to nil might speed up the generation of summaries."
(defcustom rmail-summary-progressively-narrow nil
"Non-nil means progressively narrow the set of messages produced by summary.
-This allows to apply the summary criteria on top one another,
+This enables you to apply the summary criteria on top one another,
thus progressively narrowing the selection of the messages produced
by each summary criteria.
For example, applying `rmail-summary-by-senders' on top
diff --git a/lisp/mail/sendmail.el b/lisp/mail/sendmail.el
index 8d7e90ccacf..d54fb51dfd3 100644
--- a/lisp/mail/sendmail.el
+++ b/lisp/mail/sendmail.el
@@ -1,6 +1,6 @@
;;; sendmail.el --- mail sending commands for Emacs -*- lexical-binding:t -*-
-;; Copyright (C) 1985-1986, 1992-1996, 1998, 2000-2023 Free Software
+;; Copyright (C) 1985-1986, 1992-1996, 1998, 2000-2024 Free Software
;; Foundation, Inc.
;; Maintainer: emacs-devel@gnu.org
@@ -151,11 +151,11 @@ not a valid RFC 822 (or later) header or continuation line,
that matches the variable `mail-header-separator'.
This is used by the default mail-sending commands. See also
`message-send-mail-function' for use with the Message package."
- :type '(radio (function-item sendmail-send-it :tag "Use Sendmail package")
- (function-item sendmail-query-once :tag "Query the user")
- (function-item smtpmail-send-it :tag "Use SMTPmail package")
- (function-item feedmail-send-it :tag "Use Feedmail package")
- (function-item mailclient-send-it :tag "Use Mailclient package")
+ :type '(radio (function-item sendmail-send-it)
+ (function-item sendmail-query-once)
+ (function-item :doc "Use SMTPmail package." smtpmail-send-it)
+ (function-item feedmail-send-it)
+ (function-item mailclient-send-it)
function)
:version "24.1")
@@ -269,7 +269,6 @@ The default value matches citations like `foo-bar>' plus whitespace."
(defvar mail-abbrevs-loaded nil)
(defvar mail-mode-map
(let ((map (make-sparse-keymap)))
- (define-key map "\M-\t" 'completion-at-point)
(define-key map "\C-c?" 'describe-mode)
(define-key map "\C-c\C-f\C-t" 'mail-to)
(define-key map "\C-c\C-f\C-b" 'mail-bcc)
diff --git a/lisp/mail/smtpmail.el b/lisp/mail/smtpmail.el
index 78688d170cc..ed21e777b28 100644
--- a/lisp/mail/smtpmail.el
+++ b/lisp/mail/smtpmail.el
@@ -1,6 +1,6 @@
;;; smtpmail.el --- simple SMTP protocol (RFC 821) for sending mail -*- lexical-binding:t -*-
-;; Copyright (C) 1995-1996, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1995-1996, 2001-2024 Free Software Foundation, Inc.
;; Author: Tomoji Kagatani <kagatani@rbc.ncl.omron.co.jp>
;; Maintainer: emacs-devel@gnu.org
@@ -1057,8 +1057,8 @@ Returns an error if the server cannot be contacted."
(while data-continue
(with-current-buffer buffer
(progress-reporter-update pr (point))
- (setq sending-data (buffer-substring (line-beginning-position)
- (line-end-position)))
+ (setq sending-data (buffer-substring-no-properties (line-beginning-position)
+ (line-end-position)))
(end-of-line 2)
(setq data-continue (not (eobp))))
(smtpmail-send-data-1 process sending-data))
diff --git a/lisp/mail/supercite.el b/lisp/mail/supercite.el
index 8d9cb5511ed..c3fa738150e 100644
--- a/lisp/mail/supercite.el
+++ b/lisp/mail/supercite.el
@@ -1,6 +1,6 @@
;;; supercite.el --- minor mode for citing mail and news replies -*- lexical-binding: t; -*-
-;; Copyright (C) 1993-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1993-2024 Free Software Foundation, Inc.
;; Author: 1993 Barry A. Warsaw <bwarsaw@python.org>
;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/mail/undigest.el b/lisp/mail/undigest.el
index 39e047eee72..98ac17a99ed 100644
--- a/lisp/mail/undigest.el
+++ b/lisp/mail/undigest.el
@@ -1,6 +1,6 @@
;;; undigest.el --- digest-cracking support for the RMAIL mail reader -*- lexical-binding:t -*-
-;; Copyright (C) 1985-1986, 1994, 1996, 2001-2023 Free Software
+;; Copyright (C) 1985-1986, 1994, 1996, 2001-2024 Free Software
;; Foundation, Inc.
;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/mail/unrmail.el b/lisp/mail/unrmail.el
index 7e0304c824c..a0bea65f017 100644
--- a/lisp/mail/unrmail.el
+++ b/lisp/mail/unrmail.el
@@ -1,6 +1,6 @@
;;; unrmail.el --- convert Rmail Babyl files to mbox files -*- lexical-binding: t; -*-
-;; Copyright (C) 1992, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1992, 2001-2024 Free Software Foundation, Inc.
;; Maintainer: emacs-devel@gnu.org
;; Keywords: mail
diff --git a/lisp/mail/uudecode.el b/lisp/mail/uudecode.el
index 4b9acd922d8..dd717a161d1 100644
--- a/lisp/mail/uudecode.el
+++ b/lisp/mail/uudecode.el
@@ -1,6 +1,6 @@
;;; uudecode.el --- elisp native uudecode -*- lexical-binding:t -*-
-;; Copyright (C) 1998-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-2024 Free Software Foundation, Inc.
;; Author: Shenghuo Zhu <zsh@cs.rochester.edu>
;; Keywords: uudecode news
diff --git a/lisp/mail/yenc.el b/lisp/mail/yenc.el
index a836f5b71bd..e7aac0a10d8 100644
--- a/lisp/mail/yenc.el
+++ b/lisp/mail/yenc.el
@@ -1,6 +1,6 @@
;;; yenc.el --- elisp native yenc decoder -*- lexical-binding:t -*-
-;; Copyright (C) 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2024 Free Software Foundation, Inc.
;; Author: Jesper Harder <harder@ifa.au.dk>
;; Keywords: yenc news
diff --git a/lisp/man.el b/lisp/man.el
index 506d6060269..55cb9383bec 100644
--- a/lisp/man.el
+++ b/lisp/man.el
@@ -1,6 +1,6 @@
;;; man.el --- browse UNIX manual pages -*- lexical-binding: t -*-
-;; Copyright (C) 1993-1994, 1996-1997, 2001-2023 Free Software
+;; Copyright (C) 1993-1994, 1996-1997, 2001-2024 Free Software
;; Foundation, Inc.
;; Author: Barry A. Warsaw <bwarsaw@cen.com>
@@ -105,6 +105,13 @@ When this is non-nil, call the \"man\" program synchronously
:group 'man
:version "30.1")
+(defcustom Man-support-remote-systems nil
+ "Whether to call the Un*x \"man\" program on remote systems.
+When this is non-nil, call the \"man\" program on the remote
+system determined by `default-directory'."
+ :type 'boolean
+ :version "30.1")
+
(defcustom Man-filter-list nil
"Manpage cleaning filter command phrases.
This variable contains a list of the following form:
@@ -531,8 +538,9 @@ Otherwise, the value is whatever the function
(define-button-type 'Man-xref-normal-file
'action (lambda (button)
- (let ((f (substitute-in-file-name
- (button-get button 'Man-target-string))))
+ (let ((f (concat (file-remote-p default-directory)
+ (substitute-in-file-name
+ (button-get button 'Man-target-string)))))
(if (file-exists-p f)
(if (file-readable-p f)
(view-file f)
@@ -545,6 +553,65 @@ Otherwise, the value is whatever the function
;; ======================================================================
;; utilities
+(defun Man-default-directory ()
+ "Return a default directory according to `Man-support-remote-systems'."
+ ;; Ensure that `default-directory' exists and is readable.
+ ;; We assume, that this function is always called inside the `man'
+ ;; command, so that we can check `current-prefix-arg' for reverting
+ ;; `Man-support-remote-systems'.
+ (let ((result default-directory)
+ (remote (if current-prefix-arg
+ (not Man-support-remote-systems)
+ Man-support-remote-systems)))
+
+ ;; Use a local directory if remote isn't possible.
+ (when (and (file-remote-p default-directory)
+ (not (and remote
+ ;; TODO:: Test that remote processes are supported.
+ )))
+ (setq result (expand-file-name "~/")))
+
+ ;; Check, whether the directory is accessible.
+ (if (file-accessible-directory-p result)
+ result
+ (expand-file-name (concat (file-remote-p result) "~/")))))
+
+(defun Man-shell-file-name ()
+ "Return a proper shell file name, respecting remote directories."
+ (or ; This works also in the local case.
+ (connection-local-value shell-file-name)
+ "/bin/sh"))
+
+(defun Man-header-file-path ()
+ "Return the C header file search path that Man should use.
+Normally, this is the value of the user option `Man-header-file-path',
+but when the man page is formatted on a remote system (see
+`Man-support-remote-systems'), this function tries to figure out the
+list of directories where the remote system has the C header files."
+ (let ((remote-id (file-remote-p default-directory)))
+ (if (null remote-id)
+ ;; The local case.
+ Man-header-file-path
+ ;; The remote case. Use connection-local variables.
+ (mapcar
+ (lambda (elt) (concat remote-id elt))
+ (with-connection-local-variables
+ (or (and (local-variable-p 'Man-header-file-path (current-buffer))
+ Man-header-file-path)
+ (setq-connection-local
+ Man-header-file-path
+ (let ((arch (with-temp-buffer
+ (when (zerop (ignore-errors
+ (process-file "gcc" nil '(t nil) nil
+ "-print-multiarch")))
+ (goto-char (point-min))
+ (buffer-substring (point) (line-end-position)))))
+ (base '("/usr/include" "/usr/local/include")))
+ (if (zerop (length arch))
+ base
+ (append
+ base (list (expand-file-name arch "/usr/include"))))))))))))
+
(defun Man-init-defvars ()
"Used for initializing variables based on display's color support.
This is necessary if one wants to dump man.el with Emacs."
@@ -583,7 +650,9 @@ This is necessary if one wants to dump man.el with Emacs."
(if Man-sed-script
(concat "-e '" Man-sed-script "'")
"")
- "-e '/^[\001-\032][\001-\032]*$/d'"
+ ;; Use octal numbers. Otherwise, \032 (Ctrl-Z) would
+ ;; suspend remote connections.
+ "-e '/^[\\o001-\\o032][\\o001-\\o032]*$/d'"
"-e '/\e[789]/s///g'"
"-e '/Reformatting page. Wait/d'"
"-e '/Reformatting entry. Wait/d'"
@@ -717,22 +786,23 @@ program has no such option, but interprets any name containing
a \"/\" as a local filename. The function returns either `man-db'
`man', or nil."
(if (eq Man-support-local-filenames 'auto-detect)
- (setq Man-support-local-filenames
- (with-temp-buffer
- (let ((default-directory
- ;; Ensure that `default-directory' exists and is readable.
- (if (file-accessible-directory-p default-directory)
- default-directory
- (expand-file-name "~/"))))
- (ignore-errors
- (call-process manual-program nil t nil "--help")))
- (cond ((search-backward "--local-file" nil 'move)
- 'man-db)
- ;; This feature seems to be present in at least ver 1.4f,
- ;; which is about 20 years old.
- ;; I don't know if this version has an official name?
- ((looking-at "^man, versione? [1-9]")
- 'man))))
+ (with-connection-local-variables
+ (or (and (local-variable-p 'Man-support-local-filenames (current-buffer))
+ Man-support-local-filenames)
+ (setq-connection-local
+ Man-support-local-filenames
+ (with-temp-buffer
+ (let ((default-directory (Man-default-directory)))
+ (ignore-errors
+ (process-file manual-program nil t nil "--help")))
+ (cond ((search-backward "--local-file" nil 'move)
+ 'man-db)
+ ;; This feature seems to be present in at least
+ ;; ver 1.4f, which is about 20 years old. I
+ ;; don't know if this version has an official
+ ;; name?
+ ((looking-at "^man, versione? [1-9]")
+ 'man))))))
Man-support-local-filenames))
@@ -918,7 +988,8 @@ foo(sec)[, bar(sec) [, ...]] [other stuff] - description"
(unless (and Man-completion-cache
(string-prefix-p (car Man-completion-cache) prefix))
(with-temp-buffer
- (setq default-directory "/") ;; in case inherited doesn't exist
+ ;; In case inherited doesn't exist.
+ (setq default-directory (Man-default-directory))
;; Actually for my `man' the arg is a regexp.
;; POSIX says it must be ERE and "man-db" seems to agree,
;; whereas under macOS it seems to be BRE-style and doesn't
@@ -932,7 +1003,7 @@ foo(sec)[, bar(sec) [, ...]] [other stuff] - description"
;; error later.
(when (eq 0
(ignore-errors
- (call-process
+ (process-file
manual-program nil '(t nil) nil
"-k" (concat (when (or Man-man-k-use-anchor
(string-equal prefix ""))
@@ -1016,7 +1087,12 @@ names or descriptions. The pattern argument is usually an
Note that in some cases you will need to use \\[quoted-insert] to quote the
SPC character in the above examples, because this command attempts
-to auto-complete your input based on the installed manual pages."
+to auto-complete your input based on the installed manual pages.
+
+If `default-directory' is remote, and `Man-support-remote-systems'
+is non-nil, this command formats the man page on the remote system.
+A prefix argument reverses the value of `Man-support-remote-systems'
+for the current invocation."
(interactive
(list (let* ((default-entry (Man-default-man-entry))
@@ -1082,12 +1158,7 @@ to auto-complete your input based on the installed manual pages."
Man-coding-system
locale-coding-system))
;; Avoid possible error by using a directory that always exists.
- (default-directory
- (if (and (file-directory-p default-directory)
- (not (find-file-name-handler default-directory
- 'file-directory-p)))
- default-directory
- "/")))
+ (default-directory (Man-default-directory)))
;; Prevent any attempt to use display terminal fanciness.
(setenv "TERM" "dumb")
;; In Debian Woody, at least, we get overlong lines under X
@@ -1116,9 +1187,13 @@ to auto-complete your input based on the installed manual pages."
(defun Man-getpage-in-background (topic)
"Use TOPIC to build and fire off the manpage and cleaning command.
Return the buffer in which the manpage will appear."
- (let* ((man-args topic)
- (bufname (concat "*Man " man-args "*"))
- (buffer (get-buffer bufname)))
+ (let* ((default-directory (Man-default-directory))
+ (man-args topic)
+ (bufname
+ (if (file-remote-p default-directory)
+ (format "*Man %s %s*" (file-remote-p default-directory) man-args)
+ (format "*Man %s*" man-args)))
+ (buffer (get-buffer bufname)))
(if buffer
(Man-notify-when-ready buffer)
(message "Invoking %s %s in the background" manual-program man-args)
@@ -1137,20 +1212,19 @@ Return the buffer in which the manpage will appear."
(Man-start-calling
(if (and (fboundp 'make-process)
(not Man-prefer-synchronous-call))
- (let ((proc (start-process
+ (let ((proc (start-file-process
manual-program buffer
- (if (memq system-type '(cygwin windows-nt))
- shell-file-name
- "sh")
+ (Man-shell-file-name)
shell-command-switch
(format (Man-build-man-command) man-args))))
(set-process-sentinel proc 'Man-bgproc-sentinel)
(set-process-filter proc 'Man-bgproc-filter))
(let* ((inhibit-read-only t)
(exit-status
- (call-process shell-file-name nil (list buffer nil) nil
- shell-command-switch
- (format (Man-build-man-command) man-args)))
+ (process-file
+ (Man-shell-file-name) nil (list buffer nil) nil
+ shell-command-switch
+ (format (Man-build-man-command) man-args)))
(msg ""))
(or (and (numberp exit-status)
(= exit-status 0))
@@ -1178,9 +1252,10 @@ Return the buffer in which the manpage will appear."
(buffer-read-only nil))
(erase-buffer)
(Man-start-calling
- (call-process shell-file-name nil (list (current-buffer) nil) nil
- shell-command-switch
- (format (Man-build-man-command) Man-arguments)))
+ (process-file
+ (Man-shell-file-name) nil (list (current-buffer) nil) nil
+ shell-command-switch
+ (format (Man-build-man-command) Man-arguments)))
(if Man-fontify-manpage-flag
(Man-fontify-manpage)
(Man-cleanup-manpage))
@@ -1944,7 +2019,7 @@ Specify which REFERENCE to use; default is based on word at point."
;; Header file support
(defun Man-view-header-file (file)
"View a header file specified by FILE from `Man-header-file-path'."
- (let ((path Man-header-file-path)
+ (let ((path (Man-header-file-path))
complete-path)
(while path
(setq complete-path (expand-file-name file (car path))
diff --git a/lisp/master.el b/lisp/master.el
index 8c77bcfbcf7..0caf4d7963f 100644
--- a/lisp/master.el
+++ b/lisp/master.el
@@ -1,6 +1,6 @@
;;; master.el --- make a buffer the master over another buffer -*- lexical-binding: t -*-
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
;; Author: Alex Schroeder <alex@gnu.org>
;; Old-Version: 1.0.2
diff --git a/lisp/mb-depth.el b/lisp/mb-depth.el
index 0727dd33ab8..d8cef7999ea 100644
--- a/lisp/mb-depth.el
+++ b/lisp/mb-depth.el
@@ -1,6 +1,6 @@
;;; mb-depth.el --- Indicate minibuffer-depth in prompt -*- lexical-binding: t -*-
;;
-;; Copyright (C) 2006-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2006-2024 Free Software Foundation, Inc.
;;
;; Author: Miles Bader <miles@gnu.org>
;; Keywords: convenience
diff --git a/lisp/md4.el b/lisp/md4.el
index 12ea672c7e6..72ba72f9103 100644
--- a/lisp/md4.el
+++ b/lisp/md4.el
@@ -1,6 +1,6 @@
;;; md4.el --- MD4 Message Digest Algorithm. -*- lexical-binding: t -*-
-;; Copyright (C) 2001, 2004, 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001, 2004, 2007-2024 Free Software Foundation, Inc.
;; Author: Taro Kawagishi <tarok@transpulse.org>
;; Keywords: MD4
diff --git a/lisp/menu-bar.el b/lisp/menu-bar.el
index 5e837485db3..477e3036b47 100644
--- a/lisp/menu-bar.el
+++ b/lisp/menu-bar.el
@@ -1,6 +1,6 @@
;;; menu-bar.el --- define a default menu bar -*- lexical-binding: t; -*-
-;; Copyright (C) 1993-1995, 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1993-1995, 2000-2024 Free Software Foundation, Inc.
;; Author: Richard M. Stallman
;; Maintainer: emacs-devel@gnu.org
@@ -1804,7 +1804,7 @@ mail status in mode line"))
(bindings--define-key menu [project-find-regexp] '(menu-item "Find Regexp..." project-find-regexp :help "Search for a regexp in files belonging to current project"))
(bindings--define-key menu [separator-project-search] menu-bar-separator)
(bindings--define-key menu [project-kill-buffers] '(menu-item "Kill Buffers..." project-kill-buffers :help "Kill the buffers belonging to the current project"))
- (bindings--define-key menu [project-list-buffers] '(menu-item "List Buffers..." project-list-buffers :help "Pop up a window listing all Emacs buffers belonging to current project"))
+ (bindings--define-key menu [project-list-buffers] '(menu-item "List Buffers" project-list-buffers :help "Pop up a window listing all Emacs buffers belonging to current project"))
(bindings--define-key menu [project-switch-to-buffer] '(menu-item "Switch To Buffer..." project-switch-to-buffer :help "Prompt for a buffer belonging to current project, and switch to it"))
(bindings--define-key menu [separator-project-buffers] menu-bar-separator)
(bindings--define-key menu [project-async-shell-command] '(menu-item "Async Shell Command..." project-async-shell-command :help "Invoke a shell command in project root asynchronously in background"))
@@ -1814,7 +1814,7 @@ mail status in mode line"))
(bindings--define-key menu [project-compile] '(menu-item "Compile..." project-compile :help "Invoke compiler or Make for current project, view errors"))
(bindings--define-key menu [separator-project-programs] menu-bar-separator)
(bindings--define-key menu [project-switch-project] '(menu-item "Switch Project..." project-switch-project :help "Switch to another project and then run a command"))
- (bindings--define-key menu [project-vc-dir] '(menu-item "VC Dir..." project-vc-dir :help "Show the VC status of the project repository"))
+ (bindings--define-key menu [project-vc-dir] '(menu-item "VC Dir" project-vc-dir :help "Show the VC status of the project repository"))
(bindings--define-key menu [project-dired] '(menu-item "Open Project Root" project-dired :help "Read the root directory of the current project, to operate on its files"))
(bindings--define-key menu [project-find-dir] '(menu-item "Open Directory..." project-find-dir :help "Open existing directory that belongs to current project"))
(bindings--define-key menu [project-or-external-find-file] '(menu-item "Open File Including External Roots..." project-or-external-find-file :help "Open existing file that belongs to current project or its external roots"))
@@ -2227,7 +2227,7 @@ otherwise it could decide to silently do nothing."
((not (menu-bar-menu-frame-live-and-visible-p)))
((menu-bar-non-minibuffer-window-p)
(kill-buffer (current-buffer))
- ;; Also close the current window if `menu-bar-close-windows' is
+ ;; Also close the current window if `menu-bar-close-window' is
;; set.
(when menu-bar-close-window
(ignore-errors (delete-window))))
@@ -2314,14 +2314,16 @@ The menu shows all the killed text sequences stored in `kill-ring'."
;;; Buffers Menu
-(defcustom buffers-menu-max-size 10
+;; Increasing this more might be problematic on TTY frames. See Bug#64398.
+(defcustom buffers-menu-max-size 15
"Maximum number of entries which may appear on the Buffers menu.
-If this is 10, then only the ten most-recently-selected buffers are shown.
-If this is nil, then all buffers are shown.
-A large number or nil slows down menu responsiveness."
- :type '(choice integer
- (const :tag "All" nil))
- :group 'menu)
+If this is a number, only that many most-recently-selected
+buffers are shown.
+If this is nil, all buffers are shown."
+ :type '(choice natnum
+ (const :tag "All" nil))
+ :group 'menu
+ :version "30.1")
(defcustom buffers-menu-buffer-name-length 30
"Maximum length of the buffer name on the Buffers menu.
diff --git a/lisp/mh-e/ChangeLog.1 b/lisp/mh-e/ChangeLog.1
index f918ab8fe74..10a19fdc49f 100644
--- a/lisp/mh-e/ChangeLog.1
+++ b/lisp/mh-e/ChangeLog.1
@@ -7534,7 +7534,7 @@
(mh-yank-cur-msg): Add a space between sexprs.
* mh-utils.el (mh-mark-active-p): New macro which papers over
- diffences between GNU Emacs and XEmacs. The variables mark-active
+ differences between GNU Emacs and XEmacs. The variables mark-active
and transient-mark-mode are used in GNU Emacs while zmacs-regions
and region-active-p are used in XEmacs.
@@ -11419,7 +11419,7 @@
(dist): Leave release in current directory.
- Copyright (C) 2003-2023 Free Software Foundation, Inc.
+ Copyright (C) 2003-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/lisp/mh-e/ChangeLog.2 b/lisp/mh-e/ChangeLog.2
index f0032e9db19..e632bcf1858 100644
--- a/lisp/mh-e/ChangeLog.2
+++ b/lisp/mh-e/ChangeLog.2
@@ -2576,7 +2576,7 @@
use function mh-variants instead.
(mh-variant-info, mh-variant-mh-info, mh-variant-mu-mh-info)
(mh-variant-nmh-info): Co-locate next to mh-variants, which uses
- them. Updated to use mh-file-command-p which is more accurrate
+ them. Updated to use mh-file-command-p which is more accurate
than file-executable-p which returns t for directories.
(mh-file-command-p): Move here from mh-utils, since
mh-variant-*-info are the only functions to use it.
@@ -3673,7 +3673,7 @@
See ChangeLog.1 for earlier changes.
- Copyright (C) 2005-2023 Free Software Foundation, Inc.
+ Copyright (C) 2005-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/lisp/mh-e/mh-acros.el b/lisp/mh-e/mh-acros.el
index 3981bb7f709..8f582df128d 100644
--- a/lisp/mh-e/mh-acros.el
+++ b/lisp/mh-e/mh-acros.el
@@ -1,6 +1,6 @@
;;; mh-acros.el --- macros used in MH-E -*- lexical-binding: t; -*-
-;; Copyright (C) 2004, 2006-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2004, 2006-2024 Free Software Foundation, Inc.
;; Author: Satyaki Das <satyaki@theforce.stanford.edu>
;; Maintainer: Bill Wohler <wohler@newt.com>
@@ -42,82 +42,9 @@
-;;; Compatibility
-
-;;;###mh-autoload
-(defmacro mh-do-in-gnu-emacs (&rest body)
- "Execute BODY if in GNU Emacs."
- (declare (obsolete progn "29.1") (debug t) (indent defun))
- (unless (featurep 'xemacs) `(progn ,@body)))
-
-;;;###mh-autoload
-(defmacro mh-do-in-xemacs (&rest body)
- "Execute BODY if in XEmacs."
- (declare (obsolete ignore "29.1") (debug t) (indent defun))
- (when (featurep 'xemacs) `(progn ,@body)))
-
-;;;###mh-autoload
-(defmacro mh-funcall-if-exists (function &rest args)
- "Call FUNCTION with ARGS as parameters if it exists."
- (declare (obsolete "use `(when (fboundp 'foo) (foo))' instead." "29.1")
- (debug (symbolp body)))
- ;; FIXME: Not clear when this should be used. If the function happens
- ;; not to exist at compile-time (e.g. because the corresponding package
- ;; wasn't loaded), then it won't ever be used :-(
- (when (fboundp function)
- `(when (fboundp ',function)
- (funcall ',function ,@args))))
-
-;;;###mh-autoload
-(defmacro defun-mh (name function arg-list &rest body)
- "Create function NAME.
-If FUNCTION exists, then NAME becomes an alias for FUNCTION.
-Otherwise, create function NAME with ARG-LIST and BODY."
- (declare (obsolete defun "29.1")
- (indent defun) (doc-string 4)
- (debug (&define name symbolp sexp def-body)))
- `(defalias ',name
- (if (fboundp ',function)
- ',function
- (lambda ,arg-list ,@body))))
-
-;;;###mh-autoload
-(defmacro defmacro-mh (name macro arg-list &rest body)
- "Create macro NAME.
-If MACRO exists, then NAME becomes an alias for MACRO.
-Otherwise, create macro NAME with ARG-LIST and BODY."
- (declare (obsolete defmacro "29.1")
- (indent defun) (doc-string 4)
- (debug (&define name symbolp sexp def-body)))
- (let ((defined-p (fboundp macro)))
- (if defined-p
- `(defalias ',name ',macro)
- `(defmacro ,name ,arg-list ,@body))))
-
-
;;; Miscellaneous
;;;###mh-autoload
-(defmacro mh-make-local-hook (hook)
- "Make HOOK local if needed.
-XEmacs and versions of GNU Emacs before 21.1 require
-`make-local-hook' to be called."
- (declare (obsolete nil "29.1"))
- (when (and (fboundp 'make-local-hook)
- (not (get 'make-local-hook 'byte-obsolete-info)))
- `(make-local-hook ,hook)))
-
-;;;###mh-autoload
-(defmacro mh-mark-active-p (check-transient-mark-mode-flag)
- "If CHECK-TRANSIENT-MARK-MODE-FLAG is non-nil then check if
-variable `transient-mark-mode' is active."
- (declare (obsolete nil "29.1"))
- (cond ((not check-transient-mark-mode-flag)
- 'mark-active)
- (t
- '(and transient-mark-mode mark-active))))
-
-;;;###mh-autoload
(defmacro with-mh-folder-updating (save-modification-flag &rest body)
"Format is (with-mh-folder-updating (SAVE-MODIFICATION-FLAG) &body BODY).
Execute BODY, which can modify the folder buffer without having to
diff --git a/lisp/mh-e/mh-alias.el b/lisp/mh-e/mh-alias.el
index 2b567411e0f..023bccad71a 100644
--- a/lisp/mh-e/mh-alias.el
+++ b/lisp/mh-e/mh-alias.el
@@ -1,6 +1,6 @@
;;; mh-alias.el --- MH-E mail alias completion and expansion -*- lexical-binding: t; -*-
-;; Copyright (C) 1994-1997, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1994-1997, 2001-2024 Free Software Foundation, Inc.
;; Author: Peter S. Galbraith <psg@debian.org>
;; Maintainer: Bill Wohler <wohler@newt.com>
diff --git a/lisp/mh-e/mh-buffers.el b/lisp/mh-e/mh-buffers.el
index b0f2e1963d6..e757f330675 100644
--- a/lisp/mh-e/mh-buffers.el
+++ b/lisp/mh-e/mh-buffers.el
@@ -1,6 +1,6 @@
;;; mh-buffers.el --- MH-E buffer constants and utilities -*- lexical-binding: t; -*-
-;; Copyright (C) 1993, 1995, 1997, 2000-2023 Free Software Foundation,
+;; Copyright (C) 1993, 1995, 1997, 2000-2024 Free Software Foundation,
;; Inc.
;; Author: Bill Wohler <wohler@newt.com>
diff --git a/lisp/mh-e/mh-comp.el b/lisp/mh-e/mh-comp.el
index 92d31bf1826..df2ca6ebd08 100644
--- a/lisp/mh-e/mh-comp.el
+++ b/lisp/mh-e/mh-comp.el
@@ -1,6 +1,6 @@
;;; mh-comp.el --- MH-E functions for composing and sending messages -*- lexical-binding: t; -*-
-;; Copyright (C) 1993, 1995, 1997, 2000-2023 Free Software Foundation,
+;; Copyright (C) 1993, 1995, 1997, 2000-2024 Free Software Foundation,
;; Inc.
;; Author: Bill Wohler <wohler@newt.com>
@@ -574,7 +574,7 @@ See also `mh-compose-forward-as-mime-flag',
(setq orig-subject (mh-get-header-field "Subject:")))
(let ((forw-subject
(mh-forwarded-letter-subject orig-from orig-subject)))
- (mh-insert-fields "Subject:" forw-subject)
+ (mh-modify-header-field "Subject" forw-subject t)
(goto-char (point-min))
;; Set the local value of mh-mail-header-separator according to what is
;; present in the buffer...
diff --git a/lisp/mh-e/mh-e.el b/lisp/mh-e/mh-e.el
index 34c809a5ecd..1a535620602 100644
--- a/lisp/mh-e/mh-e.el
+++ b/lisp/mh-e/mh-e.el
@@ -1,6 +1,6 @@
;;; mh-e.el --- GNU Emacs interface to the MH mail system -*- lexical-binding: t; -*-
-;; Copyright (C) 1985-1988, 1990, 1992-1995, 1997, 1999-2023 Free
+;; Copyright (C) 1985-1988, 1990, 1992-1995, 1997, 1999-2024 Free
;; Software Foundation, Inc.
;; Author: Bill Wohler <wohler@newt.com>
diff --git a/lisp/mh-e/mh-folder.el b/lisp/mh-e/mh-folder.el
index 68f72a6e0cf..1dae9a600fd 100644
--- a/lisp/mh-e/mh-folder.el
+++ b/lisp/mh-e/mh-folder.el
@@ -1,6 +1,6 @@
;;; mh-folder.el --- MH-Folder mode -*- lexical-binding: t; -*-
-;; Copyright (C) 2002-2003, 2005-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2003, 2005-2024 Free Software Foundation, Inc.
;; Author: Bill Wohler <wohler@newt.com>
;; Keywords: mail
diff --git a/lisp/mh-e/mh-funcs.el b/lisp/mh-e/mh-funcs.el
index df128c8f709..2684722eb26 100644
--- a/lisp/mh-e/mh-funcs.el
+++ b/lisp/mh-e/mh-funcs.el
@@ -1,6 +1,6 @@
;;; mh-funcs.el --- MH-E functions not everyone will use right away -*- lexical-binding: t; -*-
-;; Copyright (C) 1993, 1995, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1993, 1995, 2001-2024 Free Software Foundation, Inc.
;; Author: Bill Wohler <wohler@newt.com>
;; Keywords: mail
diff --git a/lisp/mh-e/mh-gnus.el b/lisp/mh-e/mh-gnus.el
index 4bc7119cb80..2053dcc708a 100644
--- a/lisp/mh-e/mh-gnus.el
+++ b/lisp/mh-e/mh-gnus.el
@@ -1,6 +1,6 @@
;;; mh-gnus.el --- make MH-E compatible with various versions of Gnus -*- lexical-binding: t; -*-
-;; Copyright (C) 2003-2004, 2006-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003-2004, 2006-2024 Free Software Foundation, Inc.
;; Author: Satyaki Das <satyaki@theforce.stanford.edu>
;; Maintainer: Bill Wohler <wohler@newt.com>
diff --git a/lisp/mh-e/mh-identity.el b/lisp/mh-e/mh-identity.el
index 307c7fcf9c7..bfd0a1c0277 100644
--- a/lisp/mh-e/mh-identity.el
+++ b/lisp/mh-e/mh-identity.el
@@ -1,6 +1,6 @@
;;; mh-identity.el --- multiple identify support for MH-E -*- lexical-binding: t; -*-
-;; Copyright (C) 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2024 Free Software Foundation, Inc.
;; Author: Peter S. Galbraith <psg@debian.org>
;; Maintainer: Bill Wohler <wohler@newt.com>
diff --git a/lisp/mh-e/mh-inc.el b/lisp/mh-e/mh-inc.el
index e4e88b36e3d..acb0474a8f9 100644
--- a/lisp/mh-e/mh-inc.el
+++ b/lisp/mh-e/mh-inc.el
@@ -1,6 +1,6 @@
;;; mh-inc.el --- MH-E "inc" and separate mail spool handling -*- lexical-binding: t; -*-
-;; Copyright (C) 2003-2004, 2006-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003-2004, 2006-2024 Free Software Foundation, Inc.
;; Author: Peter S. Galbraith <psg@debian.org>
;; Maintainer: Bill Wohler <wohler@newt.com>
diff --git a/lisp/mh-e/mh-junk.el b/lisp/mh-e/mh-junk.el
index c01ecc69285..9eb4f8d500c 100644
--- a/lisp/mh-e/mh-junk.el
+++ b/lisp/mh-e/mh-junk.el
@@ -1,6 +1,6 @@
;;; mh-junk.el --- MH-E interface to anti-spam measures -*- lexical-binding: t; -*-
-;; Copyright (C) 2003-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003-2024 Free Software Foundation, Inc.
;; Author: Satyaki Das <satyaki@theforce.stanford.edu>,
;; Bill Wohler <wohler@newt.com>
diff --git a/lisp/mh-e/mh-letter.el b/lisp/mh-e/mh-letter.el
index f75e2b9b80d..8e0241f345e 100644
--- a/lisp/mh-e/mh-letter.el
+++ b/lisp/mh-e/mh-letter.el
@@ -1,6 +1,6 @@
;;; mh-letter.el --- MH-Letter mode -*- lexical-binding: t; -*-
-;; Copyright (C) 1993, 1995, 1997, 2000-2023 Free Software Foundation,
+;; Copyright (C) 1993, 1995, 1997, 2000-2024 Free Software Foundation,
;; Inc.
;; Author: Bill Wohler <wohler@newt.com>
diff --git a/lisp/mh-e/mh-limit.el b/lisp/mh-e/mh-limit.el
index 845b6f99cf7..7af7f768b60 100644
--- a/lisp/mh-e/mh-limit.el
+++ b/lisp/mh-e/mh-limit.el
@@ -1,6 +1,6 @@
;;; mh-limit.el --- MH-E display limits -*- lexical-binding: t; -*-
-;; Copyright (C) 2001-2003, 2006-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2003, 2006-2024 Free Software Foundation, Inc.
;; Author: Peter S. Galbraith <psg@debian.org>
;; Keywords: mail
diff --git a/lisp/mh-e/mh-mime.el b/lisp/mh-e/mh-mime.el
index 6c498d8df71..b0920d524a7 100644
--- a/lisp/mh-e/mh-mime.el
+++ b/lisp/mh-e/mh-mime.el
@@ -1,6 +1,6 @@
;;; mh-mime.el --- MH-E MIME support -*- lexical-binding: t; -*-
-;; Copyright (C) 1993, 1995, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1993, 1995, 2001-2024 Free Software Foundation, Inc.
;; Author: Bill Wohler <wohler@newt.com>
;; Keywords: mail
@@ -1355,6 +1355,7 @@ See also \\[mh-mh-to-mime]."
("ftp") ; RFC2046 File Transfer Protocol
("gopher") ; RFC1738 The Gopher Protocol
("http") ; RFC1738 Hypertext Transfer Protocol
+ ("https") ; RFC2818 HTTP Over TLS
("local-file") ; RFC2046 Local file access
("mail-server") ; RFC2046 mail-server Electronic mail address
("mailto") ; RFC1738 Electronic mail address
diff --git a/lisp/mh-e/mh-print.el b/lisp/mh-e/mh-print.el
index eeea94a69e5..b7c07d4239c 100644
--- a/lisp/mh-e/mh-print.el
+++ b/lisp/mh-e/mh-print.el
@@ -1,6 +1,6 @@
;;; mh-print.el --- MH-E printing support -*- lexical-binding: t; -*-
-;; Copyright (C) 2003-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003-2024 Free Software Foundation, Inc.
;; Author: Jeffrey C Honig <jch@honig.net>
;; Maintainer: Bill Wohler <wohler@newt.com>
diff --git a/lisp/mh-e/mh-scan.el b/lisp/mh-e/mh-scan.el
index d0a279eac97..b076ff5dbec 100644
--- a/lisp/mh-e/mh-scan.el
+++ b/lisp/mh-e/mh-scan.el
@@ -1,6 +1,6 @@
;;; mh-scan.el --- MH-E scan line constants and utilities -*- lexical-binding: t; -*-
-;; Copyright (C) 1993, 1995, 1997, 2000-2023 Free Software Foundation,
+;; Copyright (C) 1993, 1995, 1997, 2000-2024 Free Software Foundation,
;; Inc.
;; Author: Bill Wohler <wohler@newt.com>
diff --git a/lisp/mh-e/mh-search.el b/lisp/mh-e/mh-search.el
index 63b4304985c..f475973631c 100644
--- a/lisp/mh-e/mh-search.el
+++ b/lisp/mh-e/mh-search.el
@@ -1,6 +1,6 @@
;;; mh-search.el --- MH-Search mode -*- lexical-binding: t; -*-
-;; Copyright (C) 1993, 1995, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1993, 1995, 2001-2024 Free Software Foundation, Inc.
;; Author: Indexed search by Satyaki Das <satyaki@theforce.stanford.edu>
;; Maintainer: Bill Wohler <wohler@newt.com>
diff --git a/lisp/mh-e/mh-seq.el b/lisp/mh-e/mh-seq.el
index f5716fe968f..0251d4875d4 100644
--- a/lisp/mh-e/mh-seq.el
+++ b/lisp/mh-e/mh-seq.el
@@ -1,6 +1,6 @@
;;; mh-seq.el --- MH-E sequences support -*- lexical-binding: t; -*-
-;; Copyright (C) 1993, 1995, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1993, 1995, 2001-2024 Free Software Foundation, Inc.
;; Author: Bill Wohler <wohler@newt.com>
;; Keywords: mail
diff --git a/lisp/mh-e/mh-show.el b/lisp/mh-e/mh-show.el
index 8a26ab6d81e..0f90fd6f057 100644
--- a/lisp/mh-e/mh-show.el
+++ b/lisp/mh-e/mh-show.el
@@ -1,6 +1,6 @@
;;; mh-show.el --- MH-Show mode -*- lexical-binding: t; -*-
-;; Copyright (C) 1993, 1995, 1997, 2000-2023 Free Software Foundation,
+;; Copyright (C) 1993, 1995, 1997, 2000-2024 Free Software Foundation,
;; Inc.
;; Author: Bill Wohler <wohler@newt.com>
diff --git a/lisp/mh-e/mh-speed.el b/lisp/mh-e/mh-speed.el
index 0258f0b3939..5b5ad48a291 100644
--- a/lisp/mh-e/mh-speed.el
+++ b/lisp/mh-e/mh-speed.el
@@ -1,6 +1,6 @@
;;; mh-speed.el --- MH-E speedbar support -*- lexical-binding: t; -*-
-;; Copyright (C) 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2024 Free Software Foundation, Inc.
;; Author: Satyaki Das <satyaki@theforce.stanford.edu>
;; Maintainer: Bill Wohler <wohler@newt.com>
diff --git a/lisp/mh-e/mh-thread.el b/lisp/mh-e/mh-thread.el
index 980a6a38902..8119de486a1 100644
--- a/lisp/mh-e/mh-thread.el
+++ b/lisp/mh-e/mh-thread.el
@@ -1,6 +1,6 @@
;;; mh-thread.el --- MH-E threading support -*- lexical-binding: t; -*-
-;; Copyright (C) 2002-2004, 2006-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2004, 2006-2024 Free Software Foundation, Inc.
;; Author: Satyaki Das <satyaki@theforce.stanford.edu>
;; Maintainer: Bill Wohler <wohler@newt.com>
diff --git a/lisp/mh-e/mh-tool-bar.el b/lisp/mh-e/mh-tool-bar.el
index c0fadc66096..580faf7c5df 100644
--- a/lisp/mh-e/mh-tool-bar.el
+++ b/lisp/mh-e/mh-tool-bar.el
@@ -1,6 +1,6 @@
;;; mh-tool-bar.el --- MH-E tool bar support -*- lexical-binding: t; -*-
-;; Copyright (C) 2002-2003, 2005-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2003, 2005-2024 Free Software Foundation, Inc.
;; Author: Satyaki Das <satyaki@theforce.stanford.edu>
;; Maintainer: Bill Wohler <wohler@newt.com>
diff --git a/lisp/mh-e/mh-utils.el b/lisp/mh-e/mh-utils.el
index 6f84fcdb2ba..7943879d887 100644
--- a/lisp/mh-e/mh-utils.el
+++ b/lisp/mh-e/mh-utils.el
@@ -1,6 +1,6 @@
;;; mh-utils.el --- MH-E general utilities -*- lexical-binding: t; -*-
-;; Copyright (C) 1993, 1995, 1997, 2000-2023 Free Software Foundation,
+;; Copyright (C) 1993, 1995, 1997, 2000-2024 Free Software Foundation,
;; Inc.
;; Author: Bill Wohler <wohler@newt.com>
diff --git a/lisp/mh-e/mh-xface.el b/lisp/mh-e/mh-xface.el
index 06233b1b217..83269146c41 100644
--- a/lisp/mh-e/mh-xface.el
+++ b/lisp/mh-e/mh-xface.el
@@ -1,6 +1,6 @@
;;; mh-xface.el --- MH-E X-Face and Face header field display -*- lexical-binding: t; -*-
-;; Copyright (C) 2002-2003, 2005-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2003, 2005-2024 Free Software Foundation, Inc.
;; Author: Bill Wohler <wohler@newt.com>
;; Keywords: mail
diff --git a/lisp/midnight.el b/lisp/midnight.el
index b2504536b48..bfa99d6a7a8 100644
--- a/lisp/midnight.el
+++ b/lisp/midnight.el
@@ -1,6 +1,6 @@
;;; midnight.el --- run something every midnight, e.g., kill old buffers -*- lexical-binding:t -*-
-;; Copyright (C) 1998, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998, 2001-2024 Free Software Foundation, Inc.
;; Author: Sam Steingold <sds@gnu.org>
;; Created: 1998-05-18
diff --git a/lisp/minibuf-eldef.el b/lisp/minibuf-eldef.el
index a9792383786..0edc10fd131 100644
--- a/lisp/minibuf-eldef.el
+++ b/lisp/minibuf-eldef.el
@@ -1,6 +1,6 @@
;;; minibuf-eldef.el --- Only show defaults in prompts when applicable -*- lexical-binding: t -*-
;;
-;; Copyright (C) 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2000-2024 Free Software Foundation, Inc.
;;
;; Author: Miles Bader <miles@gnu.org>
;; Keywords: convenience
diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el
index 35b359a75e2..fa2dcb4f698 100644
--- a/lisp/minibuffer.el
+++ b/lisp/minibuffer.el
@@ -1,6 +1,6 @@
;;; minibuffer.el --- Minibuffer and completion functions -*- lexical-binding: t -*-
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
;; Package: emacs
@@ -153,19 +153,6 @@ The metadata of a completion table should be constant between two boundaries."
(defun completion-metadata-get (metadata prop)
(cdr (assq prop metadata)))
-(defun completion--some (fun xs)
- "Apply FUN to each element of XS in turn.
-Return the first non-nil returned value.
-Like CL's `some'."
- (let ((firsterror nil)
- res)
- (while (and (not res) xs)
- (condition-case-unless-debug err
- (setq res (funcall fun (pop xs)))
- (error (unless firsterror (setq firsterror err)) nil)))
- (or res
- (if firsterror (signal (car firsterror) (cdr firsterror))))))
-
(defun complete-with-action (action collection string predicate)
"Perform completion according to ACTION.
STRING, COLLECTION and PREDICATE are used as in `try-completion'.
@@ -426,9 +413,9 @@ obeys predicates."
;; is returned by TABLE2 (because TABLE1 returned an empty list).
;; Same potential problem if any of the tables use quoting.
(lambda (string pred action)
- (completion--some (lambda (table)
- (complete-with-action action table string pred))
- tables)))
+ (seq-some (lambda (table)
+ (complete-with-action action table string pred))
+ tables)))
(defun completion-table-merge (&rest tables)
"Create a completion table that collects completions from all TABLES."
@@ -451,9 +438,9 @@ obeys predicates."
(all-completions string table pred))
tables)))
(t
- (completion--some (lambda (table)
- (complete-with-action action table string pred))
- tables)))))
+ (seq-some (lambda (table)
+ (complete-with-action action table string pred))
+ tables)))))
(defun completion-table-with-quoting (table unquote requote)
;; A difficult part of completion-with-quoting is to map positions in the
@@ -690,6 +677,17 @@ for use at QPOS."
'completions-common-part)
qprefix))))
(qcompletion (concat qprefix qnew)))
+ ;; Some completion tables (including this one) pass
+ ;; along necessary information as text properties
+ ;; on the first character of the completion. Make
+ ;; sure the quoted completion has these properties
+ ;; too.
+ (add-text-properties 0 1 (text-properties-at 0 completion)
+ qcompletion)
+ ;; Attach unquoted completion string, which is needed
+ ;; to score the completion in `completion--flex-score'.
+ (put-text-property 0 1 'completion--unquoted
+ completion qcompletion)
;; FIXME: Similarly here, Cygwin's mapping trips this
;; assertion.
;;(cl-assert
@@ -963,6 +961,8 @@ is at its default value `grow-only'."
(reverse multi-message-list)
multi-message-separator)))
+(defvar touch-screen-current-tool)
+
(defun clear-minibuffer-message ()
"Clear message temporarily shown in the minibuffer.
Intended to be called via `clear-message-function'."
@@ -977,7 +977,7 @@ Intended to be called via `clear-message-function'."
;; progress, because a preview message might currently be displayed
;; in the echo area. FIXME: find some way to place this in
;; touch-screen.el.
- (if (and touch-screen-preview-select
+ (if (and (bound-and-true-p touch-screen-preview-select)
(eq (nth 3 touch-screen-current-tool) 'drag))
'dont-clear-message
;; Return nil telling the caller that the message
@@ -1216,7 +1216,7 @@ overrides the default specified in `completion-category-defaults'."
(cl-assert (<= point (length string)))
(pop new))))
(result-and-style
- (completion--some
+ (seq-some
(lambda (style)
(let ((probe (funcall
(or (nth n (assq style completion-styles-alist))
@@ -1247,6 +1247,7 @@ Only the elements of table that satisfy predicate PRED are considered.
POINT is the position of point within STRING.
The return value is a list of completions and may contain the base-size
in the last `cdr'."
+ (setq completion-lazy-hilit-fn nil)
;; FIXME: We need to additionally return the info needed for the
;; second part of completion-base-position.
(completion--nth-completion 2 string table pred point metadata))
@@ -1315,14 +1316,29 @@ completion candidates than this number."
(defcustom completions-sort 'alphabetical
"Sort candidates in the *Completions* buffer.
-The value can be nil to disable sorting, `alphabetical' for
-alphabetical sorting or a custom sorting function. The sorting
-function takes and returns a list of completion candidate
-strings."
+Completion candidates in the *Completions* buffer are sorted
+depending on the value.
+
+If it's nil, sorting is disabled.
+If it's the symbol `alphabetical', candidates are sorted by
+`minibuffer-sort-alphabetically'.
+If it's the symbol `historical', candidates are sorted by
+`minibuffer-sort-by-history', which first sorts alphabetically,
+and then rearranges the order according to the order of the
+candidates in the minibuffer history.
+If it's a function, the function is called to sort the candidates.
+The sorting function takes a list of completion candidate
+strings, which it may modify; it should return a sorted list,
+which may be the same.
+
+If the completion-specific metadata provides a
+`display-sort-function', that function overrides the value of
+this variable."
:type '(choice (const :tag "No sorting" nil)
(const :tag "Alphabetical sorting" alphabetical)
+ (const :tag "Historical sorting" historical)
(function :tag "Custom function"))
- :version "29.1")
+ :version "30.1")
(defcustom completions-group nil
"Enable grouping of completion candidates in the *Completions* buffer.
@@ -1569,11 +1585,12 @@ scroll the window of possible completions."
(t (prog1 (pcase (completion--do-completion beg end)
(#b000 nil)
(_ t))
- (when (and (eq completion-auto-select t)
- (window-live-p minibuffer-scroll-window)
- (eq t (frame-visible-p (window-frame minibuffer-scroll-window))))
- ;; When the completion list window was displayed, select it.
- (switch-to-completions))))))
+ (if (window-live-p minibuffer-scroll-window)
+ (and (eq completion-auto-select t)
+ (eq t (frame-visible-p (window-frame minibuffer-scroll-window)))
+ ;; When the completion list window was displayed, select it.
+ (switch-to-completions))
+ (completion-in-region-mode -1))))))
(defun completion--cache-all-sorted-completions (beg end comps)
(add-hook 'after-change-functions
@@ -1647,6 +1664,44 @@ Remove completion BASE prefix string from history elements."
(substring c base-size)))
hist)))))
+(defun minibuffer-sort-alphabetically (completions)
+ "Sort COMPLETIONS alphabetically.
+
+COMPLETIONS are sorted alphabetically by `string-lessp'.
+
+This is a suitable function to use for `completions-sort' or to
+include as `display-sort-function' in completion metadata."
+ (sort completions #'string-lessp))
+
+(defvar minibuffer-completion-base nil
+ "The base for the current completion.
+
+This is the part of the current minibuffer input which comes
+before the current completion field, as determined by
+`completion-boundaries'. This is primarily relevant for file
+names, where this is the directory component of the file name.")
+
+(defun minibuffer-sort-by-history (completions)
+ "Sort COMPLETIONS by their position in `minibuffer-history-variable'.
+
+COMPLETIONS are sorted first by `minibuffer-sort-alphbetically',
+then any elements occurring in the minibuffer history list are
+moved to the front based on the chronological order they occur in
+the history. If a history variable hasn't been specified for
+this call of `completing-read', COMPLETIONS are sorted only by
+`minibuffer-sort-alphbetically'.
+
+This is a suitable function to use for `completions-sort' or to
+include as `display-sort-function' in completion metadata."
+ (let ((alphabetized (sort completions #'string-lessp)))
+ ;; Only use history when it's specific to these completions.
+ (if (eq minibuffer-history-variable
+ (default-value minibuffer-history-variable))
+ alphabetized
+ (minibuffer--sort-by-position
+ (minibuffer--sort-preprocess-history minibuffer-completion-base)
+ alphabetized))))
+
(defun minibuffer--group-by (group-fun sort-fun elems)
"Group ELEMS by GROUP-FUN and sort groups by SORT-FUN."
(let ((groups))
@@ -2310,8 +2365,11 @@ candidates."
(with-current-buffer standard-output
(goto-char (point-max))
- (when completions-header-format
- (insert (format completions-header-format (length completions))))
+ (if completions-header-format
+ (insert (format completions-header-format (length completions)))
+ (unless completion-show-help
+ ;; Ensure beginning-of-buffer isn't a completion.
+ (insert (propertize "\n" 'face '(:height 0)))))
(completion--insert-strings completions group-fun)))
(run-hooks 'completion-setup-hook)
@@ -2378,6 +2436,36 @@ These include:
(resize-temp-buffer-window win))
(fit-window-to-buffer win completions-max-height)))
+(defcustom completion-auto-deselect t
+ "If non-nil, deselect current completion candidate when you type in minibuffer.
+
+A non-nil value means that after typing at the minibuffer prompt,
+any completion candidate highlighted in *Completions* window (to
+indicate that it is the selected candidate) will be un-highlighted,
+and point in the *Completions* window will be moved off such a candidate.
+This means that `RET' (`minibuffer-choose-completion-or-exit') will exit
+the minubuffer with the minibuffer's current contents, instead of the
+selected completion candidate."
+ :type '(choice (const :tag "Candidates in *Completions* stay selected as you type" nil)
+ (const :tag "Typing deselects any completion candidate in *Completions*" t))
+ :version "30.1")
+
+(defun completions--deselect ()
+ "If point is in a completion candidate, move to just after the end of it.
+
+The candidate will still be chosen by `choose-completion' unless
+`choose-completion-deselect-if-after' is non-nil."
+ (when (get-text-property (point) 'completion--string)
+ (goto-char (or (next-single-property-change (point) 'completion--string)
+ (point-max)))))
+
+(defun completions--after-change (_start _end _old-len)
+ "Update displayed *Completions* buffer after change in buffer contents."
+ (when completion-auto-deselect
+ (when-let (window (get-buffer-window "*Completions*" 0))
+ (with-selected-window window
+ (completions--deselect)))))
+
(defun minibuffer-completion-help (&optional start end)
"Display a list of possible completions of the current minibuffer contents."
(interactive)
@@ -2400,6 +2488,7 @@ These include:
;; If there are no completions, or if the current input is already
;; the sole completion, then hide (previous&stale) completions.
(minibuffer-hide-completions)
+ (remove-hook 'after-change-functions #'completions--after-change t)
(if completions
(completion--message "Sole completion")
(unless completion-fail-discreetly
@@ -2409,12 +2498,18 @@ These include:
(let* ((last (last completions))
(base-size (or (cdr last) 0))
(prefix (unless (zerop base-size) (substring string 0 base-size)))
+ (minibuffer-completion-base (substring string 0 base-size))
(base-prefix (buffer-substring (minibuffer--completion-prompt-end)
(+ start base-size)))
(base-suffix
- (if (eq (alist-get 'category (cdr md)) 'file)
- (buffer-substring (save-excursion (or (search-forward "/" nil t) (point-max)))
- (point-max))
+ (if (or (eq (alist-get 'category (cdr md)) 'file)
+ completion-in-region-mode-predicate)
+ (buffer-substring
+ (save-excursion
+ (if completion-in-region-mode-predicate
+ (point)
+ (or (search-forward "/" nil t) (point-max))))
+ (point-max))
""))
(all-md (completion--metadata (buffer-substring-no-properties
start (point))
@@ -2455,6 +2550,8 @@ These include:
(body-function
. ,#'(lambda (_window)
(with-current-buffer mainbuf
+ (when completion-auto-deselect
+ (add-hook 'after-change-functions #'completions--after-change nil t))
;; Remove the base-size tail because `sort' requires a properly
;; nil-terminated list.
(when last (setcdr last nil))
@@ -2468,7 +2565,8 @@ These include:
(funcall sort-fun completions)
(pcase completions-sort
('nil completions)
- ('alphabetical (sort completions #'string-lessp))
+ ('alphabetical (minibuffer-sort-alphabetically completions))
+ ('historical (minibuffer-sort-by-history completions))
(_ (funcall completions-sort completions)))))
;; After sorting, group the candidates using the
@@ -2720,8 +2818,14 @@ Also respects the obsolete wrapper hook `completion-in-region-functions'.
completion-in-region-mode-predicate)
(setq-local minibuffer-completion-auto-choose nil)
(add-hook 'post-command-hook #'completion-in-region--postch)
- (push `(completion-in-region-mode . ,completion-in-region-mode-map)
- minor-mode-overriding-map-alist)))
+ (let* ((keymap completion-in-region-mode-map)
+ (keymap (if minibuffer-visible-completions
+ (make-composed-keymap
+ (list minibuffer-visible-completions-map
+ keymap))
+ keymap)))
+ (push `(completion-in-region-mode . ,keymap)
+ minor-mode-overriding-map-alist))))
;; Define-minor-mode added our keymap to minor-mode-map-alist, but we want it
;; on minor-mode-overriding-map-alist instead.
@@ -2966,8 +3070,45 @@ the mode hook of this mode."
:interactive nil
;; Enable text conversion, but always make sure `RET' does
;; something.
- (setq text-conversion-style 'action))
-
+ (setq text-conversion-style 'action)
+ (when minibuffer-visible-completions
+ (setq-local minibuffer-completion-auto-choose nil)))
+
+(defcustom minibuffer-visible-completions nil
+ "When non-nil, visible completions can be navigated from the minibuffer.
+This means that when the *Completions* buffer is visible in a window,
+then you can use the arrow keys in the minibuffer to move the cursor
+in the *Completions* buffer. Then you can type `RET',
+and the candidate highlighted in the *Completions* buffer
+will be accepted.
+But when the *Completions* buffer is not displayed on the screen,
+then the arrow keys move point in the minibuffer as usual, and
+`RET' accepts the input typed in the minibuffer."
+ :type 'boolean
+ :version "30.1")
+
+(defun minibuffer-visible-completions-bind (binding)
+ "Use BINDING when completions are visible.
+Return an item that is enabled only when a window
+displaying the *Completions* buffer exists."
+ `(menu-item
+ "" ,binding
+ :filter ,(lambda (cmd)
+ (when-let ((window (get-buffer-window "*Completions*" 0)))
+ (when (eq (buffer-local-value 'completion-reference-buffer
+ (window-buffer window))
+ (window-buffer (active-minibuffer-window)))
+ cmd)))))
+
+(defvar-keymap minibuffer-visible-completions-map
+ :doc "Local keymap for minibuffer input with visible completions."
+ "<left>" (minibuffer-visible-completions-bind #'minibuffer-previous-completion)
+ "<right>" (minibuffer-visible-completions-bind #'minibuffer-next-completion)
+ "<up>" (minibuffer-visible-completions-bind #'minibuffer-previous-line-completion)
+ "<down>" (minibuffer-visible-completions-bind #'minibuffer-next-line-completion)
+ "RET" (minibuffer-visible-completions-bind #'minibuffer-choose-completion-or-exit)
+ "C-g" (minibuffer-visible-completions-bind #'minibuffer-hide-completions))
+
;;; Completion tables.
(defun minibuffer--double-dollars (str)
@@ -3489,8 +3630,13 @@ Like `internal-complete-buffer', but removes BUFFER from the completion list."
(defun completion-emacs22-try-completion (string table pred point)
(let ((suffix (substring string point))
(completion (try-completion (substring string 0 point) table pred)))
- (if (not (stringp completion))
- completion
+ (cond
+ ((eq completion t)
+ (if (equal "" suffix)
+ t
+ (cons string point)))
+ ((not (stringp completion)) completion)
+ (t
;; Merge a trailing / in completion with a / after point.
;; We used to only do it for word completion, but it seems to make
;; sense for all completions.
@@ -3504,7 +3650,7 @@ Like `internal-complete-buffer', but removes BUFFER from the completion list."
(eq ?/ (aref suffix 0)))
;; This leaves point after the / .
(setq suffix (substring suffix 1)))
- (cons (concat completion suffix) (length completion)))))
+ (cons (concat completion suffix) (length completion))))))
(defun completion-emacs22-all-completions (string table pred point)
(let ((beforepoint (substring string 0 point)))
@@ -3762,108 +3908,202 @@ one large \"hole\" and a clumped-together \"oo\" match) higher
than the latter (which has two \"holes\" and three
one-letter-long matches).")
+(defvar completion-lazy-hilit nil
+ "If non-nil, request lazy highlighting of completion candidates.
+
+Lisp programs (a.k.a. \"front ends\") that present completion
+candidates may opt to bind this variable to a non-nil value when
+calling functions (such as `completion-all-completions') which
+produce completion candidates. This tells the underlying
+completion styles that they do not need to fontify (i.e.,
+propertize with the `face' property) completion candidates in a
+way that highlights the matching parts. Then it is the front end
+which presents the candidates that becomes responsible for this
+fontification. The front end does that by calling the function
+`completion-lazy-hilit' on each completion candidate that is to be
+displayed to the user.
+
+Note that only some completion styles take advantage of this
+variable for optimization purposes. Other styles will ignore the
+hint and fontify eagerly as usual. It is still safe for a
+front end to call `completion-lazy-hilit' in these situations.
+
+To author a completion style that takes advantage of this variable,
+see `completion-lazy-hilit-fn' and `completion-pcm--hilit-commonality'.")
+
+(defvar completion-lazy-hilit-fn nil
+ "Fontification function set by lazy-highlighting completions styles.
+When a given style wants to enable support for `completion-lazy-hilit'
+\(which see), that style should set this variable to a function of one
+argument. It will be called with each completion candidate, a string, to
+be displayed to the user, and should destructively propertize these
+strings with the `face' property.")
+
+(defun completion-lazy-hilit (str)
+ "Return a copy of completion candidate STR that is `face'-propertized.
+See documentation of the variable `completion-lazy-hilit' for more
+details."
+ (if (and completion-lazy-hilit completion-lazy-hilit-fn)
+ (funcall completion-lazy-hilit-fn (copy-sequence str))
+ str))
+
+(defun completion--hilit-from-re (string regexp &optional point-idx)
+ "Fontify STRING using REGEXP POINT-IDX.
+`completions-common-part' and `completions-first-difference' are
+used. POINT-IDX is the position of point in the presumed \"PCM\"
+pattern that was used to generate derive REGEXP from."
+(let* ((md (and regexp (string-match regexp string) (cddr (match-data t))))
+ (pos (if point-idx (match-beginning point-idx) (match-end 0)))
+ (me (and md (match-end 0)))
+ (from 0))
+ (while md
+ (add-face-text-property from (pop md) 'completions-common-part nil string)
+ (setq from (pop md)))
+ (if (> (length string) pos)
+ (add-face-text-property
+ pos (1+ pos)
+ 'completions-first-difference
+ nil string))
+ (unless (or (not me) (= from me))
+ (add-face-text-property from me 'completions-common-part nil string))
+ string))
+
+(defun completion--flex-score-1 (md-groups match-end len)
+ "Compute matching score of completion.
+The score lies in the range between 0 and 1, where 1 corresponds to
+the full match.
+MD-GROUPS is the \"group\" part of the match data.
+MATCH-END is the end of the match.
+LEN is the length of the completion string."
+ (let* ((from 0)
+ ;; To understand how this works, consider these simple
+ ;; ascii diagrams showing how the pattern "foo"
+ ;; flex-matches "fabrobazo", "fbarbazoo" and
+ ;; "barfoobaz":
+
+ ;; f abr o baz o
+ ;; + --- + --- +
+
+ ;; f barbaz oo
+ ;; + ------ ++
+
+ ;; bar foo baz
+ ;; +++
+
+ ;; "+" indicates parts where the pattern matched. A
+ ;; "hole" in the middle of the string is indicated by
+ ;; "-". Note that there are no "holes" near the edges
+ ;; of the string. The completion score is a number
+ ;; bound by (0..1] (i.e., larger than (but not equal
+ ;; to) zero, and smaller or equal to one): the higher
+ ;; the better and only a perfect match (pattern equals
+ ;; string) will have score 1. The formula takes the
+ ;; form of a quotient. For the numerator, we use the
+ ;; number of +, i.e. the length of the pattern. For
+ ;; the denominator, it first computes
+ ;;
+ ;; hole_i_contrib = 1 + (Li-1)^(1/tightness)
+ ;;
+ ;; , for each hole "i" of length "Li", where tightness
+ ;; is given by `flex-score-match-tightness'. The
+ ;; final value for the denominator is then given by:
+ ;;
+ ;; (SUM_across_i(hole_i_contrib) + 1) * len
+ ;;
+ ;; , where "len" is the string's length.
+ (score-numerator 0)
+ (score-denominator 0)
+ (last-b 0))
+ (while (and md-groups (car md-groups))
+ (let ((a from)
+ (b (pop md-groups)))
+ (setq
+ score-numerator (+ score-numerator (- b a)))
+ (unless (or (= a last-b)
+ (zerop last-b)
+ (= a len))
+ (setq
+ score-denominator (+ score-denominator
+ 1
+ (expt (- a last-b 1)
+ (/ 1.0
+ flex-score-match-tightness)))))
+ (setq
+ last-b b))
+ (setq from (pop md-groups)))
+ ;; If `pattern' doesn't have an explicit trailing any, the
+ ;; regex `re' won't produce match data representing the
+ ;; region after the match. We need to account to account
+ ;; for that extra bit of match (bug#42149).
+ (unless (= from match-end)
+ (let ((a from)
+ (b match-end))
+ (setq
+ score-numerator (+ score-numerator (- b a)))
+ (unless (or (= a last-b)
+ (zerop last-b)
+ (= a len))
+ (setq
+ score-denominator (+ score-denominator
+ 1
+ (expt (- a last-b 1)
+ (/ 1.0
+ flex-score-match-tightness)))))
+ (setq
+ last-b b)))
+ (/ score-numerator (* len (1+ score-denominator)) 1.0)))
+
+(defvar completion--flex-score-last-md nil
+ "Helper variable for `completion--flex-score'.")
+
+(defun completion--flex-score (str re &optional dont-error)
+ "Compute flex score of completion STR based on RE.
+If DONT-ERROR, just return nil if RE doesn't match STR."
+ (let ((case-fold-search completion-ignore-case))
+ (cond ((string-match re str)
+ (let* ((match-end (match-end 0))
+ (md (cddr
+ (setq
+ completion--flex-score-last-md
+ (match-data t completion--flex-score-last-md)))))
+ (completion--flex-score-1 md match-end (length str))))
+ ((not dont-error)
+ (error "Internal error: %s does not match %s" re str)))))
+
+(defvar completion-pcm--regexp nil
+ "Regexp from PCM pattern in `completion-pcm--hilit-commonality'.")
+
(defun completion-pcm--hilit-commonality (pattern completions)
"Show where and how well PATTERN matches COMPLETIONS.
PATTERN, a list of symbols and strings as seen
`completion-pcm--merge-completions', is assumed to match every
-string in COMPLETIONS. Return a deep copy of COMPLETIONS where
-each string is propertized with `completion-score', a number
-between 0 and 1, and with faces `completions-common-part',
-`completions-first-difference' in the relevant segments."
+string in COMPLETIONS.
+
+If `completion-lazy-hilit' is nil, return a deep copy of
+COMPLETIONS where each string is propertized with
+`completion-score', a number between 0 and 1, and with faces
+`completions-common-part', `completions-first-difference' in the
+relevant segments.
+
+Else, if `completion-lazy-hilit' is t, return COMPLETIONS
+unchanged, but setup a suitable `completion-lazy-hilit-fn' (which
+see) for later lazy highlighting."
+ (setq completion-pcm--regexp nil
+ completion-lazy-hilit-fn nil)
(cond
((and completions (cl-loop for e in pattern thereis (stringp e)))
(let* ((re (completion-pcm--pattern->regex pattern 'group))
- (point-idx (completion-pcm--pattern-point-idx pattern))
- (case-fold-search completion-ignore-case)
- last-md)
- (mapcar
- (lambda (str)
- ;; Don't modify the string itself.
- (setq str (copy-sequence str))
- (unless (string-match re str)
- (error "Internal error: %s does not match %s" re str))
- (let* ((pos (if point-idx (match-beginning point-idx) (match-end 0)))
- (match-end (match-end 0))
- (md (cddr (setq last-md (match-data t last-md))))
- (from 0)
- (end (length str))
- ;; To understand how this works, consider these simple
- ;; ascii diagrams showing how the pattern "foo"
- ;; flex-matches "fabrobazo", "fbarbazoo" and
- ;; "barfoobaz":
-
- ;; f abr o baz o
- ;; + --- + --- +
-
- ;; f barbaz oo
- ;; + ------ ++
-
- ;; bar foo baz
- ;; +++
-
- ;; "+" indicates parts where the pattern matched. A
- ;; "hole" in the middle of the string is indicated by
- ;; "-". Note that there are no "holes" near the edges
- ;; of the string. The completion score is a number
- ;; bound by (0..1] (i.e., larger than (but not equal
- ;; to) zero, and smaller or equal to one): the higher
- ;; the better and only a perfect match (pattern equals
- ;; string) will have score 1. The formula takes the
- ;; form of a quotient. For the numerator, we use the
- ;; number of +, i.e. the length of the pattern. For
- ;; the denominator, it first computes
- ;;
- ;; hole_i_contrib = 1 + (Li-1)^(1/tightness)
- ;;
- ;; , for each hole "i" of length "Li", where tightness
- ;; is given by `flex-score-match-tightness'. The
- ;; final value for the denominator is then given by:
- ;;
- ;; (SUM_across_i(hole_i_contrib) + 1) * len
- ;;
- ;; , where "len" is the string's length.
- (score-numerator 0)
- (score-denominator 0)
- (last-b 0)
- (update-score-and-face
- (lambda (a b)
- "Update score and face given match range (A B)."
- (add-face-text-property a b
- 'completions-common-part
- nil str)
- (setq
- score-numerator (+ score-numerator (- b a)))
- (unless (or (= a last-b)
- (zerop last-b)
- (= a (length str)))
- (setq
- score-denominator (+ score-denominator
- 1
- (expt (- a last-b 1)
- (/ 1.0
- flex-score-match-tightness)))))
- (setq
- last-b b))))
- (while md
- (funcall update-score-and-face from (pop md))
- (setq from (pop md)))
- ;; If `pattern' doesn't have an explicit trailing any, the
- ;; regex `re' won't produce match data representing the
- ;; region after the match. We need to account to account
- ;; for that extra bit of match (bug#42149).
- (unless (= from match-end)
- (funcall update-score-and-face from match-end))
- (if (> (length str) pos)
- (add-face-text-property
- pos (1+ pos)
- 'completions-first-difference
- nil str))
- (unless (zerop (length str))
- (put-text-property
- 0 1 'completion-score
- (/ score-numerator (* end (1+ score-denominator)) 1.0) str)))
- str)
- completions)))
+ (point-idx (completion-pcm--pattern-point-idx pattern)))
+ (setq completion-pcm--regexp re)
+ (cond (completion-lazy-hilit
+ (setq completion-lazy-hilit-fn
+ (lambda (str) (completion--hilit-from-re str re point-idx)))
+ completions)
+ (t
+ (mapcar
+ (lambda (str)
+ (completion--hilit-from-re (copy-sequence str) re point-idx))
+ completions)))))
(t completions)))
(defun completion-pcm--find-all-completions (string table pred point
@@ -4038,7 +4278,9 @@ the same set of elements."
(unique (or (and (eq prefix t) (setq prefix fixed))
(and (stringp prefix)
(eq t (try-completion prefix comps))))))
- (unless (or (eq elem 'prefix)
+ ;; if the common prefix is unique, it also is a common
+ ;; suffix, so we should add it for `prefix' elements
+ (unless (or (and (eq elem 'prefix) (not unique))
(equal prefix ""))
(push prefix res))
;; If there's only one completion, `elem' is not useful
@@ -4198,36 +4440,39 @@ that is non-nil."
(defun completion--flex-adjust-metadata (metadata)
"If `flex' is actually doing filtering, adjust sorting."
- (let ((flex-is-filtering-p
- ;; JT@2019-12-23: FIXME: this is kinda wrong. What we need
- ;; to test here is "some input that actually leads/led to
- ;; flex filtering", not "something after the minibuffer
- ;; prompt". E.g. The latter is always true for file
- ;; searches, meaning we'll be doing extra work when we
- ;; needn't.
- (or (not (window-minibuffer-p))
- (> (point-max) (minibuffer-prompt-end))))
+ (let ((flex-is-filtering-p completion-pcm--regexp)
(existing-dsf
(completion-metadata-get metadata 'display-sort-function))
(existing-csf
(completion-metadata-get metadata 'cycle-sort-function)))
(cl-flet
- ((compose-flex-sort-fn
- (existing-sort-fn) ; wish `cl-flet' had proper indentation...
- (lambda (completions)
- (sort
- (funcall existing-sort-fn completions)
- (lambda (c1 c2)
- (let ((s1 (get-text-property 0 'completion-score c1))
- (s2 (get-text-property 0 'completion-score c2)))
- (> (or s1 0) (or s2 0))))))))
+ ((compose-flex-sort-fn (existing-sort-fn)
+ (lambda (completions)
+ (let* ((sorted (sort
+ (mapcar
+ (lambda (str)
+ (cons
+ (- (completion--flex-score
+ (or (get-text-property
+ 0 'completion--unquoted str)
+ str)
+ completion-pcm--regexp))
+ str))
+ (if existing-sort-fn
+ (funcall existing-sort-fn completions)
+ completions))
+ #'car-less-than-car))
+ (cell sorted))
+ ;; Reuse the list
+ (while cell
+ (setcar cell (cdar cell))
+ (pop cell))
+ sorted))))
`(metadata
,@(and flex-is-filtering-p
- `((display-sort-function
- . ,(compose-flex-sort-fn (or existing-dsf #'identity)))))
+ `((display-sort-function . ,(compose-flex-sort-fn existing-dsf))))
,@(and flex-is-filtering-p
- `((cycle-sort-function
- . ,(compose-flex-sort-fn (or existing-csf #'identity)))))
+ `((cycle-sort-function . ,(compose-flex-sort-fn existing-csf))))
,@(cdr metadata)))))
(defun completion-flex--make-flex-pattern (pattern)
@@ -4381,6 +4626,11 @@ See `completing-read' for the meaning of the arguments."
;; in minibuffer-local-filename-completion-map can
;; override bindings in base-keymap.
base-keymap)))
+ (keymap (if minibuffer-visible-completions
+ (make-composed-keymap
+ (list minibuffer-visible-completions-map
+ keymap))
+ keymap))
(buffer (current-buffer))
(c-i-c completion-ignore-case)
(result
@@ -4500,40 +4750,75 @@ selected by these commands to the minibuffer."
:type 'boolean
:version "29.1")
-(defun minibuffer-next-completion (&optional n)
+(defun minibuffer-next-completion (&optional n vertical)
"Move to the next item in its completions window from the minibuffer.
+When the optional argument VERTICAL is non-nil, move vertically
+to the next item on the next line using `next-line-completion'.
+Otherwise, move to the next item horizontally using `next-completion'.
When `minibuffer-completion-auto-choose' is non-nil, then also
-insert the selected completion to the minibuffer."
+insert the selected completion candidate to the minibuffer."
(interactive "p")
(let ((auto-choose minibuffer-completion-auto-choose))
(with-minibuffer-completions-window
(when completions-highlight-face
(setq-local cursor-face-highlight-nonselected-window t))
- (next-completion (or n 1))
+ (if vertical
+ (next-line-completion (or n 1))
+ (next-completion (or n 1)))
(when auto-choose
- (let ((completion-use-base-affixes t))
+ (let ((completion-use-base-affixes t)
+ (completion-auto-deselect nil))
(choose-completion nil t t))))))
(defun minibuffer-previous-completion (&optional n)
"Move to the previous item in its completions window from the minibuffer.
When `minibuffer-completion-auto-choose' is non-nil, then also
-insert the selected completion to the minibuffer."
+insert the selected completion candidate to the minibuffer."
(interactive "p")
(minibuffer-next-completion (- (or n 1))))
+(defun minibuffer-next-line-completion (&optional n)
+ "Move to the next completion line from the minibuffer.
+This means to move to the completion candidate on the next line
+in the *Completions* buffer while point stays in the minibuffer.
+When `minibuffer-completion-auto-choose' is non-nil, then also
+insert the selected completion candidate to the minibuffer."
+ (interactive "p")
+ (minibuffer-next-completion (or n 1) t))
+
+(defun minibuffer-previous-line-completion (&optional n)
+ "Move to the previous completion line from the minibuffer.
+This means to move to the completion candidate on the previous line
+in the *Completions* buffer while point stays in the minibuffer.
+When `minibuffer-completion-auto-choose' is non-nil, then also
+insert the selected completion candidate to the minibuffer."
+ (interactive "p")
+ (minibuffer-next-completion (- (or n 1)) t))
+
(defun minibuffer-choose-completion (&optional no-exit no-quit)
"Run `choose-completion' from the minibuffer in its completions window.
-With prefix argument NO-EXIT, insert the completion at point to the
-minibuffer, but don't exit the minibuffer. When the prefix argument
+With prefix argument NO-EXIT, insert the completion candidate at point to
+the minibuffer, but don't exit the minibuffer. When the prefix argument
is not provided, then whether to exit the minibuffer depends on the value
of `completion-no-auto-exit'.
-If NO-QUIT is non-nil, insert the completion at point to the
+If NO-QUIT is non-nil, insert the completion candidate at point to the
minibuffer, but don't quit the completions window."
(interactive "P")
- (with-minibuffer-completions-window
+ (with-minibuffer-completions-window
(let ((completion-use-base-affixes t))
(choose-completion nil no-exit no-quit))))
+(defun minibuffer-choose-completion-or-exit (&optional no-exit no-quit)
+ "Choose the completion from the minibuffer or exit the minibuffer.
+When `minibuffer-choose-completion' can't find a completion candidate
+in the completions window, then exit the minibuffer using its present
+contents."
+ (interactive "P")
+ (condition-case nil
+ (let ((choose-completion-deselect-if-after t))
+ (minibuffer-choose-completion no-exit no-quit))
+ (error (minibuffer-complete-and-exit))))
+
(defun minibuffer-complete-history ()
"Complete the minibuffer history as far as possible.
Like `minibuffer-complete' but completes on the history items
@@ -4549,13 +4834,15 @@ instead of the default completion table."
history)
(user-error "No history available"))))
;; FIXME: Can we make it work for CRM?
- (completion-in-region
- (minibuffer--completion-prompt-end) (point-max)
- (lambda (string pred action)
- (if (eq action 'metadata)
- '(metadata (display-sort-function . identity)
- (cycle-sort-function . identity))
- (complete-with-action action completions string pred))))))
+ (let ((completion-in-region-mode-predicate
+ (lambda () (get-buffer-window "*Completions*" 0))))
+ (completion-in-region
+ (minibuffer--completion-prompt-end) (point-max)
+ (lambda (string pred action)
+ (if (eq action 'metadata)
+ '(metadata (display-sort-function . identity)
+ (cycle-sort-function . identity))
+ (complete-with-action action completions string pred)))))))
(defun minibuffer-complete-defaults ()
"Complete minibuffer defaults as far as possible.
@@ -4566,7 +4853,9 @@ instead of the completion table."
(functionp minibuffer-default-add-function))
(setq minibuffer-default-add-done t
minibuffer-default (funcall minibuffer-default-add-function)))
- (let ((completions (ensure-list minibuffer-default)))
+ (let ((completions (ensure-list minibuffer-default))
+ (completion-in-region-mode-predicate
+ (lambda () (get-buffer-window "*Completions*" 0))))
(completion-in-region
(minibuffer--completion-prompt-end) (point-max)
(lambda (string pred action)
@@ -4654,7 +4943,7 @@ This is run upon minibuffer setup."
(defun minibuffer-exit-on-screen-keyboard ()
"Hide the on-screen keyboard if it was displayed.
Hide the on-screen keyboard in a timer set to run in 0.1 seconds.
-It will be cancelled if the minibuffer is displayed again within
+It will be canceled if the minibuffer is displayed again within
that timeframe.
Do not hide the on screen keyboard inside a recursive edit.
@@ -4674,6 +4963,179 @@ The latter is implemented in `touch-screen.el'."
(add-hook 'minibuffer-setup-hook #'minibuffer-setup-on-screen-keyboard)
(add-hook 'minibuffer-exit-hook #'minibuffer-exit-on-screen-keyboard)
+(defvar minibuffer-regexp-mode)
+
+(defun minibuffer--regexp-propertize ()
+ "In current minibuffer propertize parens and slashes in regexps.
+Put punctuation `syntax-table' property on selected paren and
+backslash characters in current buffer to make `show-paren-mode'
+and `blink-matching-paren' more user-friendly."
+ (let (in-char-alt-p)
+ (save-excursion
+ (with-silent-modifications
+ (remove-text-properties (point-min) (point-max) '(syntax-table nil))
+ (goto-char (point-min))
+ (while (re-search-forward
+ (rx (| (group "\\\\")
+ (: "\\" (| (group (in "(){}"))
+ (group "[")
+ (group "]")))
+ (group "[:" (+ (in "A-Za-z")) ":]")
+ (group "[")
+ (group "]")
+ (group (in "(){}"))))
+ (point-max) 'noerror)
+ (cond
+ ((match-beginning 1)) ; \\, skip
+ ((match-beginning 2) ; \( \) \{ \}
+ (if in-char-alt-p
+ ;; Within character alternative, set symbol syntax for
+ ;; paren only.
+ (put-text-property (1- (point)) (point) 'syntax-table '(3))
+ ;; Not within character alternative, set symbol syntax for
+ ;; backslash only.
+ (put-text-property (- (point) 2) (1- (point)) 'syntax-table '(3))))
+ ((match-beginning 3) ; \[
+ (if in-char-alt-p
+ (progn
+ ;; Set symbol syntax for backslash.
+ (put-text-property (- (point) 2) (1- (point)) 'syntax-table '(3))
+ ;; Re-read bracket we might be before a character class.
+ (backward-char))
+ ;; Set symbol syntax for bracket.
+ (put-text-property (1- (point)) (point) 'syntax-table '(3))))
+ ((match-beginning 4) ; \]
+ (if in-char-alt-p
+ (progn
+ ;; Within character alternative, set symbol syntax for
+ ;; backslash, exit alternative.
+ (put-text-property (- (point) 2) (1- (point)) 'syntax-table '(3))
+ (setq in-char-alt-p nil))
+ ;; Not within character alternative, set symbol syntax for
+ ;; bracket.
+ (put-text-property (1- (point)) (point) 'syntax-table '(3))))
+ ((match-beginning 5)) ; POSIX character class, skip
+ ((match-beginning 6) ; [
+ (if in-char-alt-p
+ ;; Within character alternative, set symbol syntax.
+ (put-text-property (1- (point)) (point) 'syntax-table '(3))
+ ;; Start new character alternative.
+ (setq in-char-alt-p t)
+ ;; Looking for immediately following non-closing ].
+ (when (looking-at "\\^?\\]")
+ ;; Non-special right bracket, set symbol syntax.
+ (goto-char (match-end 0))
+ (put-text-property (1- (point)) (point) 'syntax-table '(3)))))
+ ((match-beginning 7) ; ]
+ (if in-char-alt-p
+ (setq in-char-alt-p nil)
+ ;; The only warning we can emit before RET.
+ (message "Not in character alternative")))
+ ((match-beginning 8) ; (){}
+ ;; Plain parenthesis or brace, set symbol syntax.
+ (put-text-property (1- (point)) (point) 'syntax-table '(3)))))))))
+
+;; The following variable is set by 'minibuffer--regexp-before-change'.
+;; If non-nil, either 'minibuffer--regexp-post-self-insert' or
+;; 'minibuffer--regexp-after-change', whichever comes next, will
+;; propertize the minibuffer via 'minibuffer--regexp-propertize' and
+;; reset this variable to nil, avoiding to propertize the buffer twice.
+(defvar-local minibuffer--regexp-primed nil
+ "Non-nil when minibuffer contents change.")
+
+(defun minibuffer--regexp-before-change (_a _b)
+ "`minibuffer-regexp-mode' function on `before-change-functions'."
+ (setq minibuffer--regexp-primed t))
+
+(defun minibuffer--regexp-after-change (_a _b _c)
+ "`minibuffer-regexp-mode' function on `after-change-functions'."
+ (when minibuffer--regexp-primed
+ (setq minibuffer--regexp-primed nil)
+ (minibuffer--regexp-propertize)))
+
+(defun minibuffer--regexp-post-self-insert ()
+ "`minibuffer-regexp-mode' function on `post-self-insert-hook'."
+ (when minibuffer--regexp-primed
+ (setq minibuffer--regexp-primed nil)
+ (minibuffer--regexp-propertize)))
+
+(defvar minibuffer--regexp-prompt-regexp
+ "\\(?:Posix search\\|RE search\\|Search for regexp\\|Query replace regexp\\)"
+ "Regular expression compiled from `minibuffer-regexp-prompts'.")
+
+(defcustom minibuffer-regexp-prompts
+ '("Posix search" "RE search" "Search for regexp" "Query replace regexp")
+ "List of regular expressions that trigger `minibuffer-regexp-mode' features.
+The features of `minibuffer-regexp-mode' will be activated in a minibuffer
+interaction if and only if a prompt matching some regexp in this list
+appears at the beginning of the minibuffer.
+
+Setting this variable directly with `setq' has no effect; instead,
+either use \\[customize-option] interactively or use `setopt'."
+ :type '(repeat (string :tag "Prompt"))
+ :set (lambda (sym val)
+ (set-default sym val)
+ (when val
+ (setq minibuffer--regexp-prompt-regexp
+ (concat "\\(?:" (mapconcat 'regexp-quote val "\\|") "\\)"))))
+ :version "30.1")
+
+(defun minibuffer--regexp-setup ()
+ "Function to activate`minibuffer-regexp-mode' in current buffer.
+Run by `minibuffer-setup-hook'."
+ (if (and minibuffer-regexp-mode
+ (save-excursion
+ (goto-char (point-min))
+ (looking-at minibuffer--regexp-prompt-regexp)))
+ (progn
+ (setq-local parse-sexp-lookup-properties t)
+ (add-hook 'before-change-functions #'minibuffer--regexp-before-change nil t)
+ (add-hook 'after-change-functions #'minibuffer--regexp-after-change nil t)
+ (add-hook 'post-self-insert-hook #'minibuffer--regexp-post-self-insert nil t))
+ ;; Make sure.
+ (minibuffer--regexp-exit)))
+
+(defun minibuffer--regexp-exit ()
+ "Function to deactivate `minibuffer-regexp-mode' in current buffer.
+Run by `minibuffer-exit-hook'."
+ (with-silent-modifications
+ (remove-text-properties (point-min) (point-max) '(syntax-table nil)))
+ (setq-local parse-sexp-lookup-properties nil)
+ (remove-hook 'before-change-functions #'minibuffer--regexp-before-change t)
+ (remove-hook 'after-change-functions #'minibuffer--regexp-after-change t)
+ (remove-hook 'post-self-insert-hook #'minibuffer--regexp-post-self-insert t))
+
+(define-minor-mode minibuffer-regexp-mode
+ "Minor mode for editing regular expressions in the minibuffer.
+Highlight parens via `show-paren-mode' and `blink-matching-paren'
+in a user-friendly way, avoid reporting alleged paren mismatches
+and make sexp navigation more intuitive.
+
+The list of prompts activating this mode in specific minibuffer
+interactions is customizable via `minibuffer-regexp-prompts'."
+ :global t
+ :initialize 'custom-initialize-delay
+ :init-value t
+ (if minibuffer-regexp-mode
+ (progn
+ (add-hook 'minibuffer-setup-hook #'minibuffer--regexp-setup)
+ (add-hook 'minibuffer-exit-hook #'minibuffer--regexp-exit))
+ ;; Clean up - why is Vminibuffer_list not available in Lisp?
+ (dolist (buffer (buffer-list))
+ (when (and (minibufferp)
+ parse-sexp-lookup-properties
+ (with-current-buffer buffer
+ (save-excursion
+ (goto-char (point-min))
+ (looking-at minibuffer--regexp-prompt-regexp))))
+ (with-current-buffer buffer
+ (with-silent-modifications
+ (remove-text-properties
+ (point-min) (point-max) '(syntax-table nil)))
+ (setq-local parse-sexp-lookup-properties t))))
+ (remove-hook 'minibuffer-setup-hook #'minibuffer--regexp-setup)
+ (remove-hook 'minibuffer-exit-hook #'minibuffer--regexp-exit)))
+
(provide 'minibuffer)
;;; minibuffer.el ends here
diff --git a/lisp/misc.el b/lisp/misc.el
index e8b38fad42e..fb40d1c16a3 100644
--- a/lisp/misc.el
+++ b/lisp/misc.el
@@ -1,6 +1,6 @@
;;; misc.el --- some nonstandard editing and utility commands for Emacs -*- lexical-binding:t -*-
-;; Copyright (C) 1989, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1989, 2001-2024 Free Software Foundation, Inc.
;; Maintainer: emacs-devel@gnu.org
;; Keywords: convenience
diff --git a/lisp/misearch.el b/lisp/misearch.el
index 9ac28c26c48..f53acae472e 100644
--- a/lisp/misearch.el
+++ b/lisp/misearch.el
@@ -1,6 +1,6 @@
;;; misearch.el --- isearch extensions for multi-buffer search -*- lexical-binding: t; -*-
-;; Copyright (C) 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2024 Free Software Foundation, Inc.
;; Author: Juri Linkov <juri@jurta.org>
;; Keywords: matching
@@ -387,6 +387,157 @@ whose file names match the specified wildcard."
(goto-char (if isearch-forward (point-min) (point-max)))
(isearch-forward-regexp nil t)))
+
+;;; Global multi-file replacements as diff
+
+(defcustom multi-file-diff-unsaved 'save-buffers
+ "What to do with unsaved edits when showing multi-file replacements as diffs.
+If the value is `save-buffers', save unsaved buffers before creating diff.
+If the value is `use-file', use text from the file even when the
+file-visiting buffer is modified.
+If the value is `use-modified-buffer', use text from the file-visiting
+modified buffer to be able to use unsaved changes."
+ :type '(choice
+ (const :tag "Save buffers" save-buffers)
+ (const :tag "Use file" use-file)
+ (const :tag "Use modified buffer" use-modified-buffer))
+ :version "30.1")
+
+(declare-function diff-setup-whitespace "diff-mode" ())
+(declare-function diff-setup-buffer-type "diff-mode" ())
+
+(defun multi-file-replace-as-diff (files from-string replacements regexp-flag delimited-flag)
+ "Show as diffs replacements of FROM-STRING with REPLACEMENTS.
+FILES is a list of file names. REGEXP-FLAG and DELIMITED-FLAG have
+the same meaning as in `perform-replace'."
+ (require 'diff)
+ (let ((inhibit-message t)
+ (diff-buffer (get-buffer-create "*replace-diff*")))
+ (when (eq multi-file-diff-unsaved 'save-buffers)
+ (save-some-buffers t (lambda ()
+ (seq-some (lambda (f-or-b)
+ (equal f-or-b buffer-file-name))
+ files))))
+ (with-current-buffer diff-buffer
+ (buffer-disable-undo (current-buffer))
+ (let ((inhibit-read-only t))
+ (erase-buffer))
+ ;; Make the *vc-diff* buffer read only, the diff-mode key
+ ;; bindings are nicer for read only buffers.
+ (setq buffer-read-only t)
+ (diff-mode))
+ (dolist (file-name files)
+ (let* ((file-exists (file-exists-p file-name))
+ (file-buffer
+ (when (or (not file-exists)
+ (eq multi-file-diff-unsaved 'use-modified-buffer))
+ (find-buffer-visiting file-name))))
+ (when file-name
+ (with-temp-buffer
+ (if (and file-buffer
+ (or (not file-exists)
+ (buffer-modified-p file-buffer)))
+ (insert-buffer-substring file-buffer)
+ (insert-file-contents file-name))
+ (goto-char (point-min))
+ (perform-replace from-string replacements nil regexp-flag delimited-flag)
+ (multi-file-diff-no-select
+ (if file-exists file-name file-buffer)
+ (current-buffer) nil diff-buffer
+ (concat file-name "~") file-name)))))
+ (with-current-buffer diff-buffer
+ (diff-setup-whitespace)
+ (diff-setup-buffer-type)
+ (buffer-enable-undo (current-buffer))
+ (setq-local revert-buffer-function
+ (lambda (_ignore-auto _noconfirm)
+ (multi-file-replace-as-diff
+ files from-string replacements regexp-flag delimited-flag)))
+ (goto-char (point-min)))
+ (pop-to-buffer diff-buffer)))
+
+;;;###autoload
+(defun multi-file-replace-regexp-as-diff (files regexp to-string &optional delimited)
+ "Show as diffs replacements of REGEXP with TO-STRING in FILES.
+DELIMITED has the same meaning as in `replace-regexp'.
+The replacements are displayed in the buffer *replace-diff* that
+you can later apply as a patch after reviewing the changes."
+ (interactive
+ (let ((files (multi-isearch-read-files))
+ (common
+ (query-replace-read-args
+ (concat "Replace"
+ (if current-prefix-arg " word" "")
+ " regexp as diff in files")
+ t t)))
+ (list files (nth 0 common) (nth 1 common) (nth 2 common))))
+ (multi-file-replace-as-diff files regexp to-string t delimited))
+
+;;;###autoload
+(defun replace-regexp-as-diff (regexp to-string &optional delimited)
+ "Show as diffs replacements of REGEXP with TO-STRING in the current buffer.
+DELIMITED has the same meaning as in `replace-regexp'.
+The replacements are displayed in the buffer *replace-diff* that
+you can later apply as a patch after reviewing the changes."
+ (interactive
+ (let ((common
+ (query-replace-read-args
+ (concat "Replace"
+ (if current-prefix-arg " word" "")
+ " regexp as diff")
+ t t)))
+ (list (nth 0 common) (nth 1 common) (nth 2 common))))
+ (multi-file-replace-as-diff
+ (list buffer-file-name) regexp to-string t delimited))
+
+(defvar diff-use-labels)
+(declare-function diff-check-labels "diff" (&optional force))
+(declare-function diff-file-local-copy "diff" (file-or-buf))
+
+(defun multi-file-diff-no-select (old new &optional switches buf label-old label-new)
+ ;; Based on `diff-no-select' tailored to multi-file diffs.
+ "Compare the OLD and NEW file/buffer.
+If the optional SWITCHES is nil, the switches specified in the
+variable `diff-switches' are passed to the diff command,
+otherwise SWITCHES is used. SWITCHES can be a string or a list
+of strings. BUF should be non-nil. LABEL-OLD and LABEL-NEW
+specify labels to use for file names."
+ (unless (bufferp new) (setq new (expand-file-name new)))
+ (unless (bufferp old) (setq old (expand-file-name old)))
+ (or switches (setq switches diff-switches)) ; If not specified, use default.
+ (setq switches (ensure-list switches))
+ (diff-check-labels)
+ (let* ((old-alt (diff-file-local-copy old))
+ (new-alt (diff-file-local-copy new))
+ (command
+ (mapconcat #'identity
+ `(,diff-command
+ ;; Use explicitly specified switches
+ ,@switches
+ ,@(mapcar #'shell-quote-argument
+ (nconc
+ (and (or old-alt new-alt)
+ (eq diff-use-labels t)
+ (list "--label"
+ (cond ((stringp label-old) label-old)
+ ((stringp old) old)
+ ((prin1-to-string old)))
+ "--label"
+ (cond ((stringp label-new) label-new)
+ ((stringp new) new)
+ ((prin1-to-string new)))))
+ (list (or old-alt old)
+ (or new-alt new)))))
+ " ")))
+ (with-current-buffer buf
+ (let ((inhibit-read-only t))
+ (insert command "\n")
+ (call-process shell-file-name nil buf nil
+ shell-command-switch command))
+ (if old-alt (delete-file old-alt))
+ (if new-alt (delete-file new-alt)))))
+
+
(defvar unload-function-defs-list)
(defun multi-isearch-unload-function ()
diff --git a/lisp/mouse-copy.el b/lisp/mouse-copy.el
index f45e6039320..0c4e7bcb566 100644
--- a/lisp/mouse-copy.el
+++ b/lisp/mouse-copy.el
@@ -1,6 +1,6 @@
;;; mouse-copy.el --- one-click text copy and move -*- lexical-binding: t -*-
-;; Copyright (C) 1996, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996, 2001-2024 Free Software Foundation, Inc.
;; Author: John Heidemann <johnh@ISI.EDU>
;; Keywords: mouse
diff --git a/lisp/mouse-drag.el b/lisp/mouse-drag.el
index bcaaa18e53c..4f46370fcf0 100644
--- a/lisp/mouse-drag.el
+++ b/lisp/mouse-drag.el
@@ -1,6 +1,6 @@
;;; mouse-drag.el --- use mouse-2 to do a new style of scrolling -*- lexical-binding: t -*-
-;; Copyright (C) 1996-1997, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-1997, 2001-2024 Free Software Foundation, Inc.
;; Author: John Heidemann <johnh@ISI.EDU>
;; Keywords: mouse
diff --git a/lisp/mouse.el b/lisp/mouse.el
index 11a2db52eec..d1b06c2040d 100644
--- a/lisp/mouse.el
+++ b/lisp/mouse.el
@@ -1,6 +1,6 @@
;;; mouse.el --- window system-independent mouse support -*- lexical-binding: t -*-
-;; Copyright (C) 1993-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1993-2024 Free Software Foundation, Inc.
;; Maintainer: emacs-devel@gnu.org
;; Keywords: hardware, mouse
@@ -35,7 +35,7 @@
(put 'track-mouse 'lisp-indent-function 0)
(defgroup mouse nil
- "Input from the mouse." ;; "Mouse support."
+ "Input from the mouse."
:group 'environment
:group 'editing)
@@ -1829,10 +1829,11 @@ The region will be defined with mark and point."
map)
t (lambda ()
(funcall cleanup)
- ;; Don't deactivate the mark when the context menu was invoked
- ;; by down-mouse-3 immediately after down-mouse-1 and without
- ;; releasing the mouse button with mouse-1. This allows to use
- ;; region-related context menu to operate on the selected region.
+ ;; Don't deactivate the mark when the context menu was
+ ;; invoked by down-mouse-3 immediately after
+ ;; down-mouse-1 and without releasing the mouse button
+ ;; with mouse-1. This enables region-related context
+ ;; menu to operate on the selected region.
(unless (and context-menu-mode
(eq (car-safe (aref (this-command-keys-vector) 0))
'down-mouse-3))
diff --git a/lisp/mpc.el b/lisp/mpc.el
index b937a6b5945..9577e0f2f42 100644
--- a/lisp/mpc.el
+++ b/lisp/mpc.el
@@ -1,6 +1,6 @@
;;; mpc.el --- A client for the Music Player Daemon -*- lexical-binding: t -*-
-;; Copyright (C) 2006-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2006-2024 Free Software Foundation, Inc.
;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
;; Keywords: multimedia
diff --git a/lisp/msb.el b/lisp/msb.el
index e055148c751..ec5ca9790da 100644
--- a/lisp/msb.el
+++ b/lisp/msb.el
@@ -1,6 +1,6 @@
;;; msb.el --- customizable buffer-selection with multiple menus -*- lexical-binding: t; -*-
-;; Copyright (C) 1993-1995, 1997-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1993-1995, 1997-2024 Free Software Foundation, Inc.
;; Author: Lars Lindberg <lars.lindberg@home.se>
;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/mwheel.el b/lisp/mwheel.el
index 86ed7393a17..b75b6f27d53 100644
--- a/lisp/mwheel.el
+++ b/lisp/mwheel.el
@@ -1,6 +1,6 @@
;;; mwheel.el --- Mouse wheel support -*- lexical-binding:t -*-
-;; Copyright (C) 1998-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-2024 Free Software Foundation, Inc.
;; Keywords: mouse
;; Package: emacs
diff --git a/lisp/net/ange-ftp.el b/lisp/net/ange-ftp.el
index 16ec33f92dc..fb723fb8878 100644
--- a/lisp/net/ange-ftp.el
+++ b/lisp/net/ange-ftp.el
@@ -1,6 +1,6 @@
;;; ange-ftp.el --- transparent FTP support for GNU Emacs -*- lexical-binding:t -*-
-;; Copyright (C) 1989-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1989-2024 Free Software Foundation, Inc.
;; Author: Andy Norman <ange@hplb.hpl.hp.com>
;; Maintainer: emacs-devel@gnu.org
@@ -2164,7 +2164,7 @@ Create a new process if needed."
proc)))
(defun ange-ftp-passive-mode (proc on-or-off)
- (if (string-match (concat "Passive mode " on-or-off)
+ (if (string-match (concat "Passive mode:? " on-or-off)
(cdr (ange-ftp-raw-send-cmd
proc (concat "passive " on-or-off)
"Trying passive mode..." nil)))
@@ -2850,7 +2850,8 @@ NO-ERROR, if a listing for DIRECTORY cannot be obtained."
(ange-ftp-switches-ok dired-actual-switches))
(and (boundp 'dired-listing-switches)
(ange-ftp-switches-ok
- dired-listing-switches))
+ (connection-local-value
+ dired-listing-switches)))
"-al")
t no-error)
(gethash directory ange-ftp-files-hashtable)))))
@@ -4233,7 +4234,7 @@ directory, so that Emacs will know its current contents."
(host (nth 0 parsed))
(user (nth 1 parsed))
(localname (nth 2 parsed)))
- (and (or (not connected)
+ (and (or (memq connected '(nil never))
(let ((proc (get-process (ange-ftp-ftp-process-buffer host user))))
(and proc (processp proc)
(memq (process-status proc) '(run open)))))
@@ -4403,40 +4404,6 @@ NEWNAME should be the name to give the new compressed or uncompressed file.")
(error (signal (car err) (cdr err))))
(ange-ftp-run-real-handler operation args))))
-;; The following code is commented out because Tramp now deals with
-;; Ange-FTP filenames, too.
-
-;;-;;; This regexp takes care of real ange-ftp file names (with a slash
-;;-;;; and colon).
-;;-;;; Don't allow the host name to end in a period--some systems use /.:
-;;-;;;###autoload
-;;-(or (assoc "^/[^/:]*[^/:.]:" file-name-handler-alist)
-;;- (setq file-name-handler-alist
-;;- (cons '("^/[^/:]*[^/:.]:" . ange-ftp-hook-function)
-;;- file-name-handler-alist)))
-;;-
-;;-;;; This regexp recognizes absolute filenames with only one component,
-;;-;;; for the sake of hostname completion.
-;;-;;;###autoload
-;;-(or (assoc "^/[^/:]*\\'" file-name-handler-alist)
-;;- (setq file-name-handler-alist
-;;- (cons '("^/[^/:]*\\'" . ange-ftp-completion-hook-function)
-;;- file-name-handler-alist)))
-;;-
-;;-;;; This regexp recognizes absolute filenames with only one component
-;;-;;; on Windows, for the sake of hostname completion.
-;;-;;; NB. Do not mark this as autoload, because it is very common to
-;;-;;; do completions in the root directory of drives on Windows.
-;;-(and (memq system-type '(ms-dos windows-nt))
-;;- (or (assoc "^[a-zA-Z]:/[^/:]*\\'" file-name-handler-alist)
-;;- (setq file-name-handler-alist
-;;- (cons '("^[a-zA-Z]:/[^/:]*\\'" .
-;;- ange-ftp-completion-hook-function)
-;;- file-name-handler-alist))))
-
-;;; The above two forms are sufficient to cause this file to be loaded
-;;; if the user ever uses a file name with a colon in it.
-
;;; This sets the mode
(add-hook 'find-file-hook 'ange-ftp-set-buffer-mode)
diff --git a/lisp/net/browse-url.el b/lisp/net/browse-url.el
index daa46baf8f2..359453ca433 100644
--- a/lisp/net/browse-url.el
+++ b/lisp/net/browse-url.el
@@ -1,6 +1,6 @@
;;; browse-url.el --- pass a URL to a web browser -*- lexical-binding: t; -*-
-;; Copyright (C) 1995-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1995-2024 Free Software Foundation, Inc.
;; Author: Denis Howe <dbh@doc.ic.ac.uk>
;; Maintainer: emacs-devel@gnu.org
@@ -236,7 +236,7 @@ be used instead."
(defcustom browse-url-button-regexp
(concat
- "\\b\\(\\(www\\.\\|\\(s?https?\\|ftp\\|file\\|gopher\\|gemini\\|"
+ "\\b\\(\\(www\\.\\|\\(s?https?\\|ftps?\\|file\\|gophers?\\|gemini\\|"
"nntp\\|news\\|telnet\\|wais\\|mailto\\|info\\):\\)"
"\\(//[-a-z0-9_.]+:[0-9]*\\)?"
(let ((chars "-a-z0-9_=#$@~%&*+\\/[:word:]")
@@ -244,7 +244,7 @@ be used instead."
(concat
"\\(?:"
;; Match paired parentheses, e.g. in Wikipedia URLs:
- ;; http://thread.gmane.org/47B4E3B2.3050402@gmail.com
+ ;; http://thread.gmane.org/47B4E3B2.3050402@gmail.com [dead link]
"[" chars punct "]+" "(" "[" chars punct "]+" ")"
"\\(?:" "[" chars punct "]+" "[" chars "]" "\\)?"
"\\|"
@@ -680,7 +680,9 @@ For example, when point is on an URL fragment like
Note that if you set this to \"https\", websites that do not yet
support HTTPS may not load correctly in your web browser. Such
websites are increasingly rare, but they do still exist."
- :type 'string
+ :type '(choice (const :tag "HTTP" "http")
+ (const :tag "HTTPS" "https")
+ (string :tag "Something else" "https"))
:version "29.1")
(defun browse-url-url-at-point ()
@@ -914,6 +916,11 @@ If ARGS are omitted, the default is to pass
;; (setenv "WAYLAND_DISPLAY" dpy)
)
(setenv "DISPLAY" dpy)))
+ ((featurep 'android)
+ ;; Avoid modifying the DISPLAY environment variable here,
+ ;; which interferes with any X server the user may have
+ ;; expressly set.
+ nil)
(t
(setenv "DISPLAY" dpy)))))
(if (functionp function)
@@ -1300,7 +1307,7 @@ Default to the URL around or before point."
(let* ((scheme (save-match-data
(if (string-match "\\(.+\\):/" url)
(match-string 1 url)
- "http")))
+ browse-url-default-scheme)))
(mime (concat "application/x-vnd.Be.URL." scheme)))
(haiku-roster-launch mime (vector url))))
@@ -1330,7 +1337,7 @@ point."
(setq url (browse-url-encode-url url)))
;; Make sure the URL starts with an appropriate scheme.
(unless (string-match "\\(.+\\):/" url)
- (setq url (concat "http://" url)))
+ (setq url (concat browse-url-default-scheme "://" url)))
(android-browse-url url browse-url-android-share))
(function-put 'browse-url-default-android-browser
@@ -1457,8 +1464,7 @@ used instead of `browse-url-new-window-flag'."
;;;###autoload
(defun browse-url-w3-gnudoit (url &optional _new-window)
- ;; new-window ignored
- "Ask another Emacs running gnuserv to load the URL using the W3 browser.
+ "Ask another Emacs running emacsclient to load the URL using the W3 browser.
The `browse-url-gnudoit-program' program is used with options given by
`browse-url-gnudoit-args'. Default to the URL around or before point."
(declare (obsolete nil "25.1"))
diff --git a/lisp/net/dbus.el b/lisp/net/dbus.el
index fff860b05c3..77b334e704e 100644
--- a/lisp/net/dbus.el
+++ b/lisp/net/dbus.el
@@ -1,6 +1,6 @@
;;; dbus.el --- Elisp bindings for D-Bus. -*- lexical-binding: t -*-
-;; Copyright (C) 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2024 Free Software Foundation, Inc.
;; Author: Michael Albinus <michael.albinus@gmx.de>
;; Keywords: comm, hardware
@@ -686,7 +686,9 @@ operation. One of the following keywords is returned:
`:non-existent': Service name does not exist on this bus.
`:not-owner': We are neither the primary owner nor waiting in the
-queue of this service."
+queue of this service.
+
+When SERVICE is not a known name but a unique name, the function returns nil."
(maphash
(lambda (key value)
@@ -698,14 +700,17 @@ queue of this service."
(puthash key (delete elt value) dbus-registered-objects-table)
(remhash key dbus-registered-objects-table)))))))
dbus-registered-objects-table)
- (let ((reply (dbus-call-method
- bus dbus-service-dbus dbus-path-dbus dbus-interface-dbus
- "ReleaseName" service)))
- (pcase reply
- (1 :released)
- (2 :non-existent)
- (3 :not-owner)
- (_ (signal 'dbus-error (list "Could not unregister service" service))))))
+
+ (unless (string-prefix-p ":" service)
+ (let ((reply (dbus-call-method
+ bus dbus-service-dbus dbus-path-dbus dbus-interface-dbus
+ "ReleaseName" service)))
+ (pcase reply
+ (1 :released)
+ (2 :non-existent)
+ (3 :not-owner)
+ (_ (signal
+ 'dbus-error (list "Could not unregister service" service)))))))
(defun dbus-register-signal
(bus service path interface signal handler &rest args)
diff --git a/lisp/net/dictionary-connection.el b/lisp/net/dictionary-connection.el
index 3fa675491b2..19bfbba456e 100644
--- a/lisp/net/dictionary-connection.el
+++ b/lisp/net/dictionary-connection.el
@@ -1,6 +1,6 @@
;;; dictionary-connection.el --- TCP-based client connection for dictionary -*- lexical-binding:t -*-
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
;; Author: Torsten Hilbrich <torsten.hilbrich@gmx.net>
;; Keywords: network
diff --git a/lisp/net/dictionary.el b/lisp/net/dictionary.el
index ca706c3c6e9..1981b757017 100644
--- a/lisp/net/dictionary.el
+++ b/lisp/net/dictionary.el
@@ -1,6 +1,6 @@
;;; dictionary.el --- Client for rfc2229 dictionary servers -*- lexical-binding:t -*-
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
;; Author: Torsten Hilbrich <torsten.hilbrich@gmx.net>
;; Keywords: interface, dictionary
@@ -309,12 +309,12 @@ Otherwise, `dictionary-search' displays definitions in a *Dictionary* buffer."
:version "30.1")
(defface dictionary-word-definition-face
-'((((supports (:family "DejaVu Serif")))
- (:family "DejaVu Serif"))
- (((type x))
- (:font "Sans Serif"))
- (t
- (:font "default")))
+ '((((supports (:family "DejaVu Serif")))
+ (:family "DejaVu Serif"))
+ (((type x))
+ (:font "Sans Serif"))
+ (t
+ (:font "default")))
"The face that is used for displaying the definition of the word."
:group 'dictionary
:version "28.1")
@@ -405,6 +405,22 @@ Otherwise, `dictionary-search' displays definitions in a *Dictionary* buffer."
"M-SPC" #'scroll-down-command
"DEL" #'scroll-down-command)
+(easy-menu-define dictionary-mode-menu dictionary-mode-map
+ "Menu for the Dictionary mode."
+ '("Dictionary"
+ ["Search Definition" dictionary-search
+ :help "Look up a new word"]
+ ["List Matching Words" dictionary-match-words
+ :help "List all words matching a pattern"]
+ ["Lookup Word At Point" dictionary-lookup-definition
+ :help "Look up the word at point"]
+ ["Select Dictionary" dictionary-select-dictionary
+ :help "Select one or more dictionaries to search within"]
+ ["Select Match Strategy" dictionary-select-strategy
+ :help "Select the algorithm to match queries and entries with"]
+ ["Back" dictionary-previous
+ :help "Return to the previous match or location"]))
+
(defvar dictionary-connection
nil
"The current network connection.")
@@ -423,6 +439,30 @@ Otherwise, `dictionary-search' displays definitions in a *Dictionary* buffer."
;; Basic function providing startup actions
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+(defvar dictionary-tool-bar-map
+ (let ((map (make-sparse-keymap)))
+ ;; Most of these items are the same as in the default tool bar
+ ;; map, but with extraneous items removed, and with extra search
+ ;; and navigation items.
+ (tool-bar-local-item-from-menu 'find-file "new" map
+ nil :label "New File"
+ :vert-only t)
+ (tool-bar-local-item-from-menu 'menu-find-file-existing "open" map
+ nil :label "Open" :vert-only t)
+ (tool-bar-local-item-from-menu 'dired "diropen" map nil :vert-only t)
+ (tool-bar-local-item-from-menu 'kill-this-buffer "close" map nil
+ :vert-only t)
+ (define-key-after map [separator-1] menu-bar-separator)
+ (tool-bar-local-item-from-menu 'dictionary-search "search"
+ map dictionary-mode-map :vert-only t
+ :help "Start a new search query.")
+ (tool-bar-local-item-from-menu 'dictionary-previous "left-arrow"
+ map dictionary-mode-map
+ :vert-only t
+ :help "Go backwards in history.")
+ map)
+ "Like the default `tool-bar-map', but with additions for Dictionary mode")
+
;;;###autoload
(define-derived-mode dictionary-mode special-mode "Dictionary"
"Mode for searching a dictionary.
@@ -452,6 +492,8 @@ This is a quick reference to this mode describing the default key bindings:
(make-local-variable 'dictionary-positions)
(make-local-variable 'dictionary-default-dictionary)
(make-local-variable 'dictionary-default-strategy)
+ ;; Replace the tool bar map with `dictionary-tool-bar-map'.
+ (setq-local tool-bar-map dictionary-tool-bar-map)
(add-hook 'kill-buffer-hook #'dictionary-close t t))
;;;###autoload
diff --git a/lisp/net/dig.el b/lisp/net/dig.el
index 694a3a3a3d9..6a2e8c54e14 100644
--- a/lisp/net/dig.el
+++ b/lisp/net/dig.el
@@ -1,6 +1,6 @@
;;; dig.el --- Domain Name System dig interface -*- lexical-binding:t -*-
-;; Copyright (C) 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2000-2024 Free Software Foundation, Inc.
;; Author: Simon Josefsson <simon@josefsson.org>
;; Keywords: DNS BIND dig comm
diff --git a/lisp/net/dns.el b/lisp/net/dns.el
index 42e7fb415d3..23ea88ef4ad 100644
--- a/lisp/net/dns.el
+++ b/lisp/net/dns.el
@@ -1,6 +1,6 @@
;;; dns.el --- Domain Name Service lookups -*- lexical-binding:t -*-
-;; Copyright (C) 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2024 Free Software Foundation, Inc.
;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
;; Keywords: network comm
diff --git a/lisp/net/eudc-bob.el b/lisp/net/eudc-bob.el
index f345a94bab4..be067452b75 100644
--- a/lisp/net/eudc-bob.el
+++ b/lisp/net/eudc-bob.el
@@ -1,6 +1,6 @@
;;; eudc-bob.el --- Binary Objects Support for EUDC -*- lexical-binding: t; -*-
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
;; Author: Oscar Figueiredo <oscar@cpe.fr>
;; Pavel Janík <Pavel@Janik.cz>
diff --git a/lisp/net/eudc-capf.el b/lisp/net/eudc-capf.el
index d454851ae67..ac070c82cca 100644
--- a/lisp/net/eudc-capf.el
+++ b/lisp/net/eudc-capf.el
@@ -1,21 +1,22 @@
;;; eudc-capf.el --- EUDC - completion-at-point bindings -*- lexical-binding:t -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
-;;
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
+
;; Author: Alexander Adolf
-;;
+;; Package: eudc
+
;; This file is part of GNU Emacs.
-;;
+
;; GNU Emacs is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
-;;
+
;; GNU Emacs is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
-;;
+
;; You should have received a copy of the GNU General Public License
;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
diff --git a/lisp/net/eudc-export.el b/lisp/net/eudc-export.el
index 7bde976239d..9ff7979a13a 100644
--- a/lisp/net/eudc-export.el
+++ b/lisp/net/eudc-export.el
@@ -1,6 +1,6 @@
;;; eudc-export.el --- functions to export EUDC query results -*- lexical-binding: t; -*-
-;; Copyright (C) 1998-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-2024 Free Software Foundation, Inc.
;; Author: Oscar Figueiredo <oscar@cpe.fr>
;; Pavel Janík <Pavel@Janik.cz>
diff --git a/lisp/net/eudc-hotlist.el b/lisp/net/eudc-hotlist.el
index a8b9fddde56..97f4ffe8a9c 100644
--- a/lisp/net/eudc-hotlist.el
+++ b/lisp/net/eudc-hotlist.el
@@ -1,6 +1,6 @@
;;; eudc-hotlist.el --- hotlist management for EUDC -*- lexical-binding: t; -*-
-;; Copyright (C) 1998-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-2024 Free Software Foundation, Inc.
;; Author: Oscar Figueiredo <oscar@cpe.fr>
;; Pavel Janík <Pavel@Janik.cz>
diff --git a/lisp/net/eudc-vars.el b/lisp/net/eudc-vars.el
index b6b06f0c9fa..240385b2acf 100644
--- a/lisp/net/eudc-vars.el
+++ b/lisp/net/eudc-vars.el
@@ -1,6 +1,6 @@
;;; eudc-vars.el --- Emacs Unified Directory Client -*- lexical-binding: t -*-
-;; Copyright (C) 1998-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-2024 Free Software Foundation, Inc.
;; Author: Oscar Figueiredo <oscar@cpe.fr>
;; Pavel Janík <Pavel@Janik.cz>
diff --git a/lisp/net/eudc.el b/lisp/net/eudc.el
index aae7a45563d..ea90e4a7e77 100644
--- a/lisp/net/eudc.el
+++ b/lisp/net/eudc.el
@@ -1,6 +1,6 @@
;;; eudc.el --- Emacs Unified Directory Client -*- lexical-binding:t -*-
-;; Copyright (C) 1998-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-2024 Free Software Foundation, Inc.
;; Author: Oscar Figueiredo <oscar@cpe.fr>
;; Pavel Janík <Pavel@Janik.cz>
diff --git a/lisp/net/eudcb-bbdb.el b/lisp/net/eudcb-bbdb.el
index 37f7c65633b..78d01187556 100644
--- a/lisp/net/eudcb-bbdb.el
+++ b/lisp/net/eudcb-bbdb.el
@@ -1,6 +1,6 @@
;;; eudcb-bbdb.el --- Emacs Unified Directory Client - BBDB Backend -*- lexical-binding: t; -*-
-;; Copyright (C) 1998-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-2024 Free Software Foundation, Inc.
;; Author: Oscar Figueiredo <oscar@cpe.fr>
;; Pavel Janík <Pavel@Janik.cz>
diff --git a/lisp/net/eudcb-ecomplete.el b/lisp/net/eudcb-ecomplete.el
index 20bdd9059f5..0cf7a253727 100644
--- a/lisp/net/eudcb-ecomplete.el
+++ b/lisp/net/eudcb-ecomplete.el
@@ -1,29 +1,32 @@
;;; eudcb-ecomplete.el --- EUDC - ecomplete backend -*- lexical-binding: t -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
-;;
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
+
;; Author: Alexander Adolf
-;;
+;; Package: eudc
+
;; This file is part of GNU Emacs.
-;;
+
;; GNU Emacs is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
-;;
+
;; GNU Emacs is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
-;;
+
;; You should have received a copy of the GNU General Public License
;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
;;; Commentary:
+
;; This library provides an interface to the ecomplete package as
;; an EUDC data source.
;;; Usage:
+
;; No setup is required, since there is an entry for this backend
;; in `eudc-server-hotlist' by default.
;;
diff --git a/lisp/net/eudcb-ldap.el b/lisp/net/eudcb-ldap.el
index b1733e99f5c..c0ea840c82d 100644
--- a/lisp/net/eudcb-ldap.el
+++ b/lisp/net/eudcb-ldap.el
@@ -1,6 +1,6 @@
;;; eudcb-ldap.el --- Emacs Unified Directory Client - LDAP Backend -*- lexical-binding: t; -*-
-;; Copyright (C) 1998-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-2024 Free Software Foundation, Inc.
;; Author: Oscar Figueiredo <oscar@cpe.fr>
;; Pavel Janík <Pavel@Janik.cz>
diff --git a/lisp/net/eudcb-mab.el b/lisp/net/eudcb-mab.el
index 805c742d9e0..2f4d210d01e 100644
--- a/lisp/net/eudcb-mab.el
+++ b/lisp/net/eudcb-mab.el
@@ -1,6 +1,6 @@
;;; eudcb-mab.el --- Emacs Unified Directory Client - AddressBook backend -*- lexical-binding: t; -*-
-;; Copyright (C) 2003-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003-2024 Free Software Foundation, Inc.
;; Author: John Wiegley <johnw@newartisans.com>
;; Maintainer: Thomas Fitzsimmons <fitzsim@fitzsim.org>
diff --git a/lisp/net/eudcb-macos-contacts.el b/lisp/net/eudcb-macos-contacts.el
index bb73237e6ec..69c89e5a681 100644
--- a/lisp/net/eudcb-macos-contacts.el
+++ b/lisp/net/eudcb-macos-contacts.el
@@ -1,8 +1,9 @@
;;; eudcb-macos-contacts.el --- EUDC - macOS Contacts backend -*- lexical-binding: t; -*-
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
;; Author: Alexander Adolf
+;; Package: eudc
;; This file is part of GNU Emacs.
@@ -20,11 +21,13 @@
;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
;;; Commentary:
+
;; This library provides an interface to the macOS Contacts app as
;; an EUDC data source. It uses AppleScript to interface with the
;; Contacts app on localhost, so no 3rd party tools are needed.
;;; Usage:
+
;; To load the library, first `require' it:
;;
;; (require 'eudcb-macos-contacts)
diff --git a/lisp/net/eudcb-mailabbrev.el b/lisp/net/eudcb-mailabbrev.el
index e47f8687093..1addfafdc21 100644
--- a/lisp/net/eudcb-mailabbrev.el
+++ b/lisp/net/eudcb-mailabbrev.el
@@ -1,29 +1,32 @@
;;; eudcb-mailabbrev.el --- EUDC - mailabbrev backend -*- lexical-binding: t -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
-;;
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
+
;; Author: Alexander Adolf
-;;
+;; Package: eudc
+
;; This file is part of GNU Emacs.
-;;
+
;; GNU Emacs is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
-;;
+
;; GNU Emacs is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
-;;
+
;; You should have received a copy of the GNU General Public License
;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
;;; Commentary:
+
;; This library provides an interface to the mailabbrev package as
;; an EUDC data source.
;;; Usage:
+
;; No setup is required, since there is an entry for this backend
;; in `eudc-server-hotlist' by default.
;;
diff --git a/lisp/net/eww.el b/lisp/net/eww.el
index 3cdbe9dd471..22f07cbc5b4 100644
--- a/lisp/net/eww.el
+++ b/lisp/net/eww.el
@@ -1,6 +1,6 @@
;;; eww.el --- Emacs Web Wowser -*- lexical-binding:t -*-
-;; Copyright (C) 2013-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2024 Free Software Foundation, Inc.
;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
;; Keywords: html
@@ -100,7 +100,7 @@ no parameters) that returns a directory name."
Each of the elements is a function returning either a string or a list
of strings. The results will be joined into a single list with
duplicate entries (if any) removed."
- :version "27.1"
+ :version "30.1"
:group 'eww
:type 'hook
:options '(eww-links-at-point
@@ -566,7 +566,7 @@ NO-SELECT non-nil means do not make the new buffer the current buffer."
(tab-new)
(eww--open-url-in-new-buffer url)
(when no-select
- (tab-bar-switch-to-prev-tab)))
+ (tab-bar-switch-to-recent-tab)))
(if no-select
(save-window-excursion (eww--open-url-in-new-buffer url))
(eww--open-url-in-new-buffer url)))
@@ -620,46 +620,51 @@ The renaming scheme is performed in accordance with
(let ((redirect (plist-get status :redirect)))
(when redirect
(setq url redirect)))
- (with-current-buffer buffer
- ;; Save the https peer status.
- (plist-put eww-data :peer (plist-get status :peer))
- ;; Make buffer listings more informative.
- (setq list-buffers-directory url)
- ;; Let the URL library have a handle to the current URL for
- ;; referer purposes.
- (setq url-current-lastloc (url-generic-parse-url url)))
- (unwind-protect
- (progn
- (cond
- ((and eww-use-external-browser-for-content-type
- (string-match-p eww-use-external-browser-for-content-type
- (car content-type)))
- (erase-buffer)
- (insert "<title>Unsupported content type</title>")
- (insert (format "<h1>Content-type %s is unsupported</h1>"
- (car content-type)))
- (insert (format "<a href=%S>Direct link to the document</a>"
- url))
- (goto-char (point-min))
- (eww-display-html charset url nil point buffer encode))
- ((eww-html-p (car content-type))
- (eww-display-html charset url nil point buffer encode))
- ((equal (car content-type) "application/pdf")
- (eww-display-pdf))
- ((string-match-p "\\`image/" (car content-type))
- (eww-display-image buffer))
- (t
- (eww-display-raw buffer (or encode charset 'utf-8))))
- (with-current-buffer buffer
- (plist-put eww-data :url url)
- (eww--after-page-change)
- (setq eww-history-position 0)
- (and last-coding-system-used
- (set-buffer-file-coding-system last-coding-system-used))
- (run-hooks 'eww-after-render-hook)
- ;; Enable undo again so that undo works in text input
- ;; boxes.
- (setq buffer-undo-list nil)))
+ (when (buffer-live-p buffer)
+ (with-current-buffer buffer
+ ;; Save the https peer status.
+ (plist-put eww-data :peer (plist-get status :peer))
+ ;; Make buffer listings more informative.
+ (setq list-buffers-directory url)
+ ;; Let the URL library have a handle to the current URL for
+ ;; referer purposes.
+ (setq url-current-lastloc (url-generic-parse-url url)))
+ (unwind-protect
+ (progn
+ (cond
+ ((and eww-use-external-browser-for-content-type
+ (string-match-p eww-use-external-browser-for-content-type
+ (car content-type)))
+ (erase-buffer)
+ (insert "<title>Unsupported content type</title>")
+ (insert (format "<h1>Content-type %s is unsupported</h1>"
+ (car content-type)))
+ (insert (format "<a href=%S>Direct link to the document</a>"
+ url))
+ (goto-char (point-min))
+ (eww-display-html charset url nil point buffer encode))
+ ((eww-html-p (car content-type))
+ (eww-display-html charset url nil point buffer encode))
+ ((equal (car content-type) "application/pdf")
+ (eww-display-pdf))
+ ((string-match-p "\\`image/" (car content-type))
+ (eww-display-image buffer))
+ (t
+ (eww-display-raw buffer (or encode charset 'utf-8))))
+ (with-current-buffer buffer
+ (plist-put eww-data :url url)
+ (eww--after-page-change)
+ (setq eww-history-position 0)
+ (and last-coding-system-used
+ (set-buffer-file-coding-system last-coding-system-used))
+ (unless shr-fill-text
+ (visual-line-mode))
+ (run-hooks 'eww-after-render-hook)
+ ;; Enable undo again so that undo works in text input
+ ;; boxes.
+ (setq buffer-undo-list nil)))
+ (kill-buffer data-buffer)))
+ (unless (buffer-live-p buffer)
(kill-buffer data-buffer))))
(defun eww-parse-headers ()
@@ -1214,6 +1219,8 @@ the like."
(setq-local shr-url-transformer #'eww--transform-url)
;; Also rescale images when rescaling the text.
(add-hook 'text-scale-mode-hook #'eww--rescale-images nil t)
+ (setq-local outline-search-function 'shr-outline-search
+ outline-level 'shr-outline-level)
(setq buffer-read-only t))
(defvar text-scale-mode)
@@ -2059,7 +2066,8 @@ If CHARSET is nil then use UTF-8."
(let ((completion-extra-properties
'(:annotation-function (lambda (buf)
(with-current-buffer buf
- (format " %s" (eww-current-url)))))))
+ (format " %s" (eww-current-url))))))
+ (curbuf (current-buffer)))
(pop-to-buffer-same-window
(read-buffer "Switch to EWW buffer: "
(cl-loop for buf in (nreverse (buffer-list))
@@ -2067,9 +2075,10 @@ If CHARSET is nil then use UTF-8."
return buf)
t
(lambda (bufn)
- (with-current-buffer
- (if (consp bufn) (cdr bufn) (get-buffer bufn))
- (derived-mode-p 'eww-mode)))))))
+ (setq bufn (if (consp bufn) (cdr bufn) (get-buffer bufn)))
+ (and (with-current-buffer bufn
+ (derived-mode-p 'eww-mode))
+ (not (eq bufn curbuf))))))))
(defun eww-toggle-fonts ()
"Toggle whether to use monospaced or font-enabled layouts."
diff --git a/lisp/net/gnutls.el b/lisp/net/gnutls.el
index 36b1654222a..b0c3dcb9a70 100644
--- a/lisp/net/gnutls.el
+++ b/lisp/net/gnutls.el
@@ -1,6 +1,6 @@
;;; gnutls.el --- Support SSL/TLS connections through GnuTLS -*- lexical-binding: t; -*-
-;; Copyright (C) 2010-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2010-2024 Free Software Foundation, Inc.
;; Author: Ted Zlatanov <tzz@lifelogs.com>
;; Keywords: comm, tls, ssl, encryption
@@ -96,7 +96,7 @@ Security'."
(repeat :tag "List of hostname regexps with flags for each"
(list
(choice :tag "Hostname"
- (const ".*" :tag "Any hostname")
+ (const :tag "Any hostname" ".*")
regexp)
(set (const :trustfiles)
(const :hostname))))))
diff --git a/lisp/net/goto-addr.el b/lisp/net/goto-addr.el
index 57187cfce65..7c72c67f187 100644
--- a/lisp/net/goto-addr.el
+++ b/lisp/net/goto-addr.el
@@ -1,6 +1,6 @@
;;; goto-addr.el --- click to browse URL or to send to e-mail address -*- lexical-binding: t; -*-
-;; Copyright (C) 1995, 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1995, 2000-2024 Free Software Foundation, Inc.
;; Author: Eric Ding <ericding@alum.mit.edu>
;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/net/hmac-def.el b/lisp/net/hmac-def.el
index 010e97dda02..3d4810a1646 100644
--- a/lisp/net/hmac-def.el
+++ b/lisp/net/hmac-def.el
@@ -1,6 +1,6 @@
;;; hmac-def.el --- A macro for defining HMAC functions. -*- lexical-binding: t -*-
-;; Copyright (C) 1999, 2001, 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999, 2001, 2007-2024 Free Software Foundation, Inc.
;; Author: Shuhei KOBAYASHI <shuhei@aqua.ocn.ne.jp>
;; Keywords: HMAC, RFC2104
diff --git a/lisp/net/hmac-md5.el b/lisp/net/hmac-md5.el
index 4d111e2b62b..1c4ac24a9c4 100644
--- a/lisp/net/hmac-md5.el
+++ b/lisp/net/hmac-md5.el
@@ -1,6 +1,6 @@
;;; hmac-md5.el --- Compute HMAC-MD5. -*- lexical-binding:t -*-
-;; Copyright (C) 1999, 2001, 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999, 2001, 2007-2024 Free Software Foundation, Inc.
;; Author: Shuhei KOBAYASHI <shuhei@aqua.ocn.ne.jp>
;; Keywords: HMAC, RFC2104, HMAC-MD5, MD5, KEYED-MD5, CRAM-MD5
diff --git a/lisp/net/imap.el b/lisp/net/imap.el
index cfb92674d8a..f10b5b8fc12 100644
--- a/lisp/net/imap.el
+++ b/lisp/net/imap.el
@@ -1,6 +1,6 @@
;;; imap.el --- imap library -*- lexical-binding:t -*-
-;; Copyright (C) 1998-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-2024 Free Software Foundation, Inc.
;; Author: Simon Josefsson <simon@josefsson.org>
;; Keywords: mail
@@ -1833,7 +1833,7 @@ on failure."
(defun imap-send-command (command &optional buffer)
(with-current-buffer (or buffer (current-buffer))
- (if (not (listp command)) (setq command (list command)))
+ (setq command (ensure-list command))
(let ((tag (setq imap-tag (1+ imap-tag)))
cmd cmdstr)
(setq cmdstr (concat (number-to-string imap-tag) " "))
diff --git a/lisp/net/ldap.el b/lisp/net/ldap.el
index 5c3766a76b3..2ec3f927a40 100644
--- a/lisp/net/ldap.el
+++ b/lisp/net/ldap.el
@@ -1,6 +1,6 @@
;;; ldap.el --- client interface to LDAP for Emacs -*- lexical-binding: t; -*-
-;; Copyright (C) 1998-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-2024 Free Software Foundation, Inc.
;; Author: Oscar Figueiredo <oscar@cpe.fr>
;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/net/mailcap.el b/lisp/net/mailcap.el
index 4d01737e3e6..5ff75deb4e6 100644
--- a/lisp/net/mailcap.el
+++ b/lisp/net/mailcap.el
@@ -1,6 +1,6 @@
;;; mailcap.el --- MIME media types configuration -*- lexical-binding: t -*-
-;; Copyright (C) 1998-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-2024 Free Software Foundation, Inc.
;; Author: William M. Perry <wmperry@aventail.com>
;; Lars Magne Ingebrigtsen <larsi@gnus.org>
@@ -689,9 +689,9 @@ to supply to the test."
status cache result)
(cond ((not (or (stringp viewer) (fboundp viewer)))
nil) ; Non-existent Lisp function
+ ((null test-info) t) ; No test clause
((setq cache (assoc test mailcap-viewer-test-cache))
(cadr cache))
- ((not test-info) t) ; No test clause
(t
(setq
result
diff --git a/lisp/net/mairix.el b/lisp/net/mairix.el
index 4f90470d4fb..9557d1a5760 100644
--- a/lisp/net/mairix.el
+++ b/lisp/net/mairix.el
@@ -1,6 +1,6 @@
;;; mairix.el --- Mairix interface for Emacs -*- lexical-binding: t; -*-
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
;; Author: David Engster <dengste@eml.cc>
;; Keywords: mail searching
@@ -60,8 +60,7 @@
;;; History:
-;; 07/28/2008: version 0.2. Added VM interface, written by Ulrich
-;; Mueller.
+;; 07/28/2008: version 0.2. Added VM interface, written by Ulrich Müller.
;; 07/14/2008: Initial release
@@ -288,7 +287,7 @@ Currently there are `threads' and `flags'.")
(message-field-value field)))
;;; VM
-;;; written by Ulrich Mueller
+;;; written by Ulrich Müller
(declare-function vm-quit "ext:vm-folder" (&optional no-change))
(declare-function vm-visit-folder "ext:vm-startup"
diff --git a/lisp/net/net-utils.el b/lisp/net/net-utils.el
index cb725c0674e..83842cd6788 100644
--- a/lisp/net/net-utils.el
+++ b/lisp/net/net-utils.el
@@ -1,6 +1,6 @@
;;; net-utils.el --- network functions -*- lexical-binding: t; -*-
-;; Copyright (C) 1998-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-2024 Free Software Foundation, Inc.
;; Author: Peter Breton <pbreton@cs.umb.edu>
;; Created: Sun Mar 16 1997
diff --git a/lisp/net/network-stream.el b/lisp/net/network-stream.el
index 8cb5236ceb9..dcb3ad61f6d 100644
--- a/lisp/net/network-stream.el
+++ b/lisp/net/network-stream.el
@@ -1,6 +1,6 @@
;;; network-stream.el --- open network processes, possibly with encryption -*- lexical-binding: t -*-
-;; Copyright (C) 2010-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2010-2024 Free Software Foundation, Inc.
;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
;; Keywords: network
diff --git a/lisp/net/newst-backend.el b/lisp/net/newst-backend.el
index 31dc8d8e177..920111f2134 100644
--- a/lisp/net/newst-backend.el
+++ b/lisp/net/newst-backend.el
@@ -1,6 +1,6 @@
;;; newst-backend.el --- Retrieval backend for newsticker -*- lexical-binding:t -*-
-;; Copyright (C) 2003-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003-2024 Free Software Foundation, Inc.
;; Author: Ulf Jasper <ulf.jasper@web.de>
;; Filename: newst-backend.el
@@ -618,13 +618,13 @@ If URL is nil it is searched at point."
(end-of-line)
(and
(re-search-backward
- "http://"
+ (rx "http" (? "s") "://")
(if (> (point) (+ (point-min) 100))
(- (point) 100)
(point-min))
t)
(re-search-forward
- "http://[-a-zA-Z0-9&/_.]*"
+ (rx "http" (? "s") "://" (zero-or-more (any "-a-zA-Z0-9&/_.")))
(if (< (point) (- (point-max) 200))
(+ (point) 200)
(point-max))
@@ -1676,15 +1676,6 @@ Sat, 07 Sep 2002 00:00:01 GMT
nil))))
nil))
-;; FIXME: Can this be replaced by seq-intersection?
-(defun newsticker--lists-intersect-p (list1 list2)
- "Return t if LIST1 and LIST2 share elements."
- (let ((result nil))
- (dolist (elt list1)
- (if (memq elt list2)
- (setq result t)))
- result))
-
(defun newsticker--update-process-ids ()
"Update list of ids of active newsticker processes.
Checks list of active processes against list of newsticker processes."
diff --git a/lisp/net/newst-plainview.el b/lisp/net/newst-plainview.el
index 55fa19cbf2a..6b7050a9ff0 100644
--- a/lisp/net/newst-plainview.el
+++ b/lisp/net/newst-plainview.el
@@ -1,6 +1,6 @@
;;; newst-plainview.el --- Single buffer frontend for newsticker. -*- lexical-binding: t; -*-
-;; Copyright (C) 2003-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003-2024 Free Software Foundation, Inc.
;; Author: Ulf Jasper <ulf.jasper@web.de>
;; Filename: newst-plainview.el
@@ -573,14 +573,10 @@ calls `w3m-toggle-inline-image'. It works only if
(when pos
(goto-char pos)
(when (get-text-property pos 'w3m-image)
- (let ((invis (newsticker--lists-intersect-p
- (get-text-property (1- (point))
- 'invisible)
- buffer-invisibility-spec)))
- (unless (car (get-text-property (1- (point))
- 'display))
- (unless invis
- (w3m-toggle-inline-image t)))))))))))))
+ (unless (car (get-text-property (1- (point))
+ 'display))
+ (unless (invisible-p (1- (point)))
+ (w3m-toggle-inline-image t))))))))))))
;; ======================================================================
;;; Keymap stuff
@@ -606,9 +602,7 @@ is non-nil."
(goto-char (point-min))
(newsticker-next-new-item t))
(setq go-ahead nil))
- (unless (newsticker--lists-intersect-p
- (get-text-property (point) 'invisible)
- buffer-invisibility-spec)
+ (unless (invisible-p (point))
;; this item is invisible -- continue search
(setq go-ahead nil))))
(run-hooks 'newsticker-select-item-hook)
@@ -627,9 +621,7 @@ is non-nil."
(unless do-not-wrap-at-bob
(goto-char (point-max))
(newsticker--buffer-goto '(item) 'new t)))
- (unless (newsticker--lists-intersect-p
- (get-text-property (point) 'invisible)
- buffer-invisibility-spec)
+ (unless (invisible-p (point))
(setq go-ahead nil))))
(run-hooks 'newsticker-select-item-hook)
(point))
@@ -652,9 +644,7 @@ non-nil."
(unless do-not-wrap-at-eob
(goto-char (point-min)))
(setq go-ahead nil))
- (unless (newsticker--lists-intersect-p
- (get-text-property (point) 'invisible)
- buffer-invisibility-spec)
+ (unless (invisible-p (point))
(setq go-ahead nil))))
(run-hooks 'newsticker-select-item-hook)
(force-mode-line-update)
@@ -673,9 +663,7 @@ auto-narrow-to-item is enabled, nil is returned."
(while go-ahead
(unless (newsticker--buffer-goto '(item))
(setq go-ahead nil))
- (unless (newsticker--lists-intersect-p
- (get-text-property (point) 'invisible)
- buffer-invisibility-spec)
+ (unless (invisible-p (point))
(setq go-ahead nil)))
(if (and (> (point) current-pos)
(< (point) end-of-feed))
@@ -700,9 +688,7 @@ is non-nil."
(goto-char (point-max))))
(while go-ahead
(if (newsticker--buffer-goto search-list nil t)
- (unless (newsticker--lists-intersect-p
- (get-text-property (point) 'invisible)
- buffer-invisibility-spec)
+ (unless (invisible-p (point))
(setq go-ahead nil))
(goto-char (point-min))
(setq go-ahead nil))))
@@ -1079,9 +1065,7 @@ If VALUE is nil, auto-narrowing is turned off, otherwise it is turned on."
(while (< (point) (point-max))
(unless (newsticker--buffer-goto '(item))
(throw 'result nil))
- (unless (newsticker--lists-intersect-p
- (get-text-property (point) 'invisible)
- buffer-invisibility-spec)
+ (unless (invisible-p (point))
(throw 'result t))))))
(defun newsticker-previous-item-available-p ()
@@ -1091,9 +1075,7 @@ If VALUE is nil, auto-narrowing is turned off, otherwise it is turned on."
(while (> (point) (point-min))
(unless (newsticker--buffer-goto '(item) nil t)
(throw 'result nil))
- (unless (newsticker--lists-intersect-p
- (get-text-property (point) 'invisible)
- buffer-invisibility-spec)
+ (unless (invisible-p (point))
(throw 'result t))))))
(defun newsticker-item-not-old-p ()
diff --git a/lisp/net/newst-reader.el b/lisp/net/newst-reader.el
index 9ec0b395675..130e01a0deb 100644
--- a/lisp/net/newst-reader.el
+++ b/lisp/net/newst-reader.el
@@ -1,6 +1,6 @@
;;; newst-reader.el --- Generic RSS reader functions. -*- lexical-binding: t; -*-
-;; Copyright (C) 2003-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003-2024 Free Software Foundation, Inc.
;; Author: Ulf Jasper <ulf.jasper@web.de>
;; Filename: newst-reader.el
@@ -237,7 +237,8 @@ for formatting."
(cond ((listp contents)
(mapc (lambda (i)
(if (and (stringp i)
- (string-match "^http://.*" i))
+ (string-match
+ (rx bol "http" (? "s") "://" (* nonl)) i))
(let ((pos (point)))
(insert i " ") ; avoid self-reference from the
; nt-link thing
@@ -248,7 +249,7 @@ for formatting."
'help-echo
(format "mouse-2: visit (%s)" i)
'keymap keymap)))
- (insert (format "%s" i))))
+ (insert (format "%s" i))))
contents))
(t
(insert (format "%s" contents))))
diff --git a/lisp/net/newst-ticker.el b/lisp/net/newst-ticker.el
index 064b72f02c2..cd0ecd4b868 100644
--- a/lisp/net/newst-ticker.el
+++ b/lisp/net/newst-ticker.el
@@ -1,6 +1,6 @@
;;; newst-ticker.el --- mode line ticker for newsticker. -*- lexical-binding: t; -*-
-;; Copyright (C) 2003-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003-2024 Free Software Foundation, Inc.
;; Author: Ulf Jasper <ulf.jasper@web.de>
;; Filename: newst-ticker.el
diff --git a/lisp/net/newst-treeview.el b/lisp/net/newst-treeview.el
index 39988ba6cfb..81b6e275ded 100644
--- a/lisp/net/newst-treeview.el
+++ b/lisp/net/newst-treeview.el
@@ -1,6 +1,6 @@
;;; newst-treeview.el --- Treeview frontend for newsticker. -*- lexical-binding:t -*-
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
;; Author: Ulf Jasper <ulf.jasper@web.de>
;; Filename: newst-treeview.el
@@ -1466,7 +1466,7 @@ Move to next item unless DONT-PROCEED is non-nil."
nil)))
(defun newsticker--treeview-get-second-child (node)
- "Get scond child of NODE."
+ "Get second child of NODE."
(let ((children (widget-get node :children)))
(if children
(car (cdr children))
diff --git a/lisp/net/newsticker.el b/lisp/net/newsticker.el
index c86174b6d8e..b34c0268941 100644
--- a/lisp/net/newsticker.el
+++ b/lisp/net/newsticker.el
@@ -1,6 +1,6 @@
;;; newsticker.el --- A Newsticker for Emacs. -*- lexical-binding: t -*-
-;; Copyright (C) 2003-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003-2024 Free Software Foundation, Inc.
;; Author: Ulf Jasper <ulf.jasper@web.de>
;; Filename: newsticker.el
diff --git a/lisp/net/nsm.el b/lisp/net/nsm.el
index 7cbeb48f5be..830dc9372ab 100644
--- a/lisp/net/nsm.el
+++ b/lisp/net/nsm.el
@@ -1,6 +1,6 @@
;;; nsm.el --- Network Security Manager -*- lexical-binding:t -*-
-;; Copyright (C) 2014-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2014-2024 Free Software Foundation, Inc.
;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
;; Keywords: encryption, security, network
@@ -149,10 +149,11 @@ unencrypted."
(dhe-prime-kx medium)
(sha1-sig medium)
(ecdsa-cbc-cipher medium)
+ ;; Deprecated by NIST from 2016/2023 (see also CVE-2016-2183).
+ (3des-cipher medium)
;; Towards TLS 1.3
(dhe-kx high)
(rsa-kx high)
- (3des-cipher high)
(cbc-cipher high))
"This variable specifies what TLS connection checks to perform.
It's an alist where the key is the name of the check, and the
@@ -169,13 +170,13 @@ otherwise.
See also: `nsm-check-tls-connection', `nsm-save-host-names',
`nsm-settings-file'"
- :version "27.1"
:type '(repeat (list (symbol :tag "Check function")
(choice :tag "Level"
:value medium
(const :tag "Low" low)
(const :tag "Medium" medium)
- (const :tag "High" high)))))
+ (const :tag "High" high))))
+ :version "30.1")
(defun nsm-save-fingerprint-maybe (host port status &rest _)
"Save the certificate's fingerprint.
@@ -386,12 +387,11 @@ between the user and the server, to downgrade vulnerable TLS
connections to insecure 512-bit export grade cryptography.
The Logjam paper suggests using 1024-bit prime on the client to
-mitigate some effects of this attack, and upgrade to 2048-bit as
-soon as server configurations allow. According to SSLLabs' SSL
-Pulse tracker, only about 75% of server support 2048-bit key
-exchange in June 2018[2]. To provide a balance between
-compatibility and security, this function only checks for a
-minimum key strength of 1024-bit.
+mitigate some effects of this attack, and upgrading to 2048-bit
+as soon as server configurations allow. According to SSLLabs'
+SSL Pulse tracker the overwhelming majority of servers support
+2048-bit key exchange in October 2023[2]. This function
+therefore checks for a minimum key strength of 2048 bits.
See also: `nsm-protocol-check--dhe-kx'
@@ -403,10 +403,10 @@ Diffie-Hellman Fails in Practice\", `https://weakdh.org/'
`https://www.ssllabs.com/ssl-pulse/'"
(let ((prime-bits (plist-get status :diffie-hellman-prime-bits)))
(if (and (string-match "^\\bDHE\\b" (plist-get status :key-exchange))
- (< prime-bits 1024))
+ (< prime-bits 2048))
(format-message
"Diffie-Hellman key strength (%s bits) too weak (%s bits)"
- prime-bits 1024))))
+ prime-bits 2048))))
(defun nsm-protocol-check--dhe-kx (_host _port status &optional _settings)
"Check for existence of DH key exchange based on integer factorization.
@@ -484,7 +484,7 @@ because of MAC-then-encrypt. This construction is vulnerable to
padding oracle attacks[1].
Since GnuTLS 3.4.0, the TLS encrypt-then-MAC extension[2] has
-been enabled by default[3]. If encrypt-then-MAC is negotiated,
+been enabled by default[3]. If encrypt-then-MAC is negotiated,
this check has no effect.
Reference:
@@ -550,14 +550,14 @@ Due to its use of 64-bit block size, it is known that a
ciphertext collision is highly likely when 2^32 blocks are
encrypted with the same key bundle under 3-key 3DES. Practical
birthday attacks of this kind have been demonstrated by Sweet32[1].
-As such, NIST is in the process of disallowing its use in TLS[2].
+As such, NIST has disallowed its use after December 31, 2023[2].
[1]: Bhargavan, Leurent (2016). \"On the Practical (In-)Security of
64-bit Block Ciphers — Collision Attacks on HTTP over TLS and
OpenVPN\", `https://sweet32.info/'
-[2]: NIST Information Technology Laboratory (Jul 2017). \"Update to
-Current Use and Deprecation of TDEA\",
-`https://csrc.nist.gov/News/2017/Update-to-Current-Use-and-Deprecation-of-TDEA'"
+[2]: National Institute of Standards and Technology (Mar 2019).
+\"Transitioning the Use of Cryptographic Algorithms and Key
+Lengths\", `https://doi.org/10.6028/NIST.SP.800-131Ar2'"
(let ((cipher (plist-get status :cipher)))
(and (string-match "\\b3DES\\b" cipher)
(format-message
diff --git a/lisp/net/ntlm.el b/lisp/net/ntlm.el
index c92c90bf694..e753fe39602 100644
--- a/lisp/net/ntlm.el
+++ b/lisp/net/ntlm.el
@@ -1,6 +1,6 @@
;;; ntlm.el --- NTLM (NT LanManager) authentication support -*- lexical-binding:t -*-
-;; Copyright (C) 2001, 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001, 2007-2024 Free Software Foundation, Inc.
;; Author: Taro Kawagishi <tarok@transpulse.org>
;; Maintainer: Thomas Fitzsimmons <fitzsim@fitzsim.org>
@@ -8,6 +8,9 @@
;; Version: 2.1.0
;; Created: February 2001
+;; This is a GNU ELPA :core package. Avoid functionality that is not
+;; compatible with the version of Emacs recorded above.
+
;; This file is part of GNU Emacs.
;; GNU Emacs is free software: you can redistribute it and/or modify
diff --git a/lisp/net/pop3.el b/lisp/net/pop3.el
index d2fdbc3ffff..27a8e904fc3 100644
--- a/lisp/net/pop3.el
+++ b/lisp/net/pop3.el
@@ -1,6 +1,6 @@
;;; pop3.el --- Post Office Protocol (RFC 1460) interface -*- lexical-binding:t -*-
-;; Copyright (C) 1996-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-2024 Free Software Foundation, Inc.
;; Author: Richard L. Pieri <ratinox@peorth.gweep.net>
;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/net/puny.el b/lisp/net/puny.el
index 8879e34ce27..a83ede919fe 100644
--- a/lisp/net/puny.el
+++ b/lisp/net/puny.el
@@ -1,6 +1,6 @@
;;; puny.el --- translate non-ASCII domain names to ASCII -*- lexical-binding:t -*-
-;; Copyright (C) 2015-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2024 Free Software Foundation, Inc.
;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
;; Keywords: mail, net
diff --git a/lisp/net/rcirc.el b/lisp/net/rcirc.el
index a6dad4b640d..0835d25460c 100644
--- a/lisp/net/rcirc.el
+++ b/lisp/net/rcirc.el
@@ -1,6 +1,6 @@
;;; rcirc.el --- default, simple IRC client -*- lexical-binding: t; -*-
-;; Copyright (C) 2005-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2005-2024 Free Software Foundation, Inc.
;; Author: Ryan Yeske <rcyeske@gmail.com>
;; Maintainers: Ryan Yeske <rcyeske@gmail.com>,
@@ -229,6 +229,12 @@ Uninteresting lines are those whose responses are listed in
Used as the first arg to `format-time-string'."
:type 'string)
+(defcustom rcirc-log-time-format "%d-%b %H:%M "
+ "Describes how timestamps are printed in the log files.
+Used as the first arg to `format-time-string'."
+ :version "30.1"
+ :type 'string )
+
(defcustom rcirc-input-ring-size 1024
"Size of input history ring."
:type 'integer)
@@ -392,8 +398,9 @@ and the cdr part is used for encoding."
(cons (coding-system :tag "Decode")
(coding-system :tag "Encode")))))
-(defcustom rcirc-multiline-major-mode 'fundamental-mode
+(defcustom rcirc-multiline-major-mode #'text-mode
"Major-mode function to use in multiline edit buffers."
+ :version "30.1"
:type 'function)
(defcustom rcirc-nick-completion-format "%s: "
@@ -859,6 +866,7 @@ If QUIET is non-nil, no not emit a message."
(if (rcirc--connection-open-p process)
(throw 'exit (or quiet (message "Server process is alive")))
(delete-process process))
+ (setq rcirc-user-authenticated nil)
(let ((conn-info rcirc-connection-info))
(setf (nth 5 conn-info)
(cl-remove-if-not #'rcirc-channel-p
@@ -2207,7 +2215,7 @@ disk. PROCESS is the process object for the current connection."
(parse-iso8601-time-string time t))))
(unless (null filename)
(let ((cell (assoc-string filename rcirc-log-alist))
- (line (concat (format-time-string rcirc-time-format time)
+ (line (concat (format-time-string rcirc-log-time-format time)
(substring-no-properties
(rcirc-format-response-string process sender
response target text))
@@ -2972,20 +2980,13 @@ keywords when no KEYWORD is given."
browse-url-button-regexp)
"Regexp matching URLs. Set to nil to disable URL features in rcirc.")
-;; cf cl-remove-if-not
-(defun rcirc-condition-filter (condp lst)
- "Remove all items not satisfying condition CONDP in list LST.
-CONDP is a function that takes a list element as argument and returns
-non-nil if that element should be included. Returns a new list."
- (delq nil (mapcar (lambda (x) (and (funcall condp x) x)) lst)))
-
(defun rcirc-browse-url (&optional arg)
"Prompt for URL to browse based on URLs in buffer before point.
If ARG is given, opens the URL in a new browser window."
(interactive "P")
(let* ((point (point))
- (filtered (rcirc-condition-filter
+ (filtered (seq-filter
(lambda (x) (>= point (cdr x)))
rcirc-urls))
(completions (mapcar (lambda (x) (car x)) filtered))
@@ -4006,6 +4007,8 @@ PROCESS is the process object for the current connection."
(define-obsolete-function-alias 'rcirc-format-strike-trough
'rcirc-format-strike-through "30.1")
+(define-obsolete-function-alias 'rcirc-condition-filter #'seq-filter "30.1")
+
(provide 'rcirc)
;;; rcirc.el ends here
diff --git a/lisp/net/rfc2104.el b/lisp/net/rfc2104.el
index ea6a5382f4e..907ec11de9c 100644
--- a/lisp/net/rfc2104.el
+++ b/lisp/net/rfc2104.el
@@ -1,6 +1,6 @@
;;; rfc2104.el --- RFC2104 Hashed Message Authentication Codes -*- lexical-binding:t -*-
-;; Copyright (C) 1998-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-2024 Free Software Foundation, Inc.
;; Author: Simon Josefsson <jas@pdc.kth.se>
;; Keywords: mail
diff --git a/lisp/net/sasl-cram.el b/lisp/net/sasl-cram.el
index 5ae2c447ba5..ed6e00f578a 100644
--- a/lisp/net/sasl-cram.el
+++ b/lisp/net/sasl-cram.el
@@ -1,6 +1,6 @@
;;; sasl-cram.el --- CRAM-MD5 module for the SASL client framework -*- lexical-binding: t -*-
-;; Copyright (C) 2000, 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2000, 2007-2024 Free Software Foundation, Inc.
;; Author: Daiki Ueno <ueno@gnu.org>
;; Kenichi OKADA <okada@opaopa.org>
diff --git a/lisp/net/sasl-digest.el b/lisp/net/sasl-digest.el
index 140758e23b0..75106fceee9 100644
--- a/lisp/net/sasl-digest.el
+++ b/lisp/net/sasl-digest.el
@@ -1,6 +1,6 @@
;;; sasl-digest.el --- DIGEST-MD5 module for the SASL client framework -*- lexical-binding: t -*-
-;; Copyright (C) 2000, 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2000, 2007-2024 Free Software Foundation, Inc.
;; Author: Daiki Ueno <ueno@unixuser.org>
;; Kenichi OKADA <okada@opaopa.org>
diff --git a/lisp/net/sasl-ntlm.el b/lisp/net/sasl-ntlm.el
index c70059ac69d..a845598b4f0 100644
--- a/lisp/net/sasl-ntlm.el
+++ b/lisp/net/sasl-ntlm.el
@@ -1,6 +1,6 @@
;;; sasl-ntlm.el --- NTLM (NT Lan Manager) module for the SASL client framework -*- lexical-binding: t -*-
-;; Copyright (C) 2000, 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2000, 2007-2024 Free Software Foundation, Inc.
;; Author: Taro Kawagishi <tarok@transpulse.org>
;; Keywords: SASL, NTLM
diff --git a/lisp/net/sasl-scram-rfc.el b/lisp/net/sasl-scram-rfc.el
index ddccf2b1425..8450f648cd9 100644
--- a/lisp/net/sasl-scram-rfc.el
+++ b/lisp/net/sasl-scram-rfc.el
@@ -1,6 +1,6 @@
;;; sasl-scram-rfc.el --- SCRAM-SHA-1 module for the SASL client framework -*- lexical-binding: t; -*-
-;; Copyright (C) 2014-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2014-2024 Free Software Foundation, Inc.
;; Author: Magnus Henoch <magnus.henoch@gmail.com>
;; Package: sasl
diff --git a/lisp/net/sasl-scram-sha256.el b/lisp/net/sasl-scram-sha256.el
index 27267f3c2e2..345bb6e4313 100644
--- a/lisp/net/sasl-scram-sha256.el
+++ b/lisp/net/sasl-scram-sha256.el
@@ -1,6 +1,6 @@
;;; sasl-scram-sha256.el --- SCRAM-SHA-256 module for the SASL client framework -*- lexical-binding: t; -*-
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
;; Author: Simon Josefsson <simon@josefsson.org>
;; Package: sasl
diff --git a/lisp/net/sasl.el b/lisp/net/sasl.el
index 7fe97904a4c..621b873af59 100644
--- a/lisp/net/sasl.el
+++ b/lisp/net/sasl.el
@@ -1,6 +1,6 @@
;;; sasl.el --- SASL client framework -*- lexical-binding: t -*-
-;; Copyright (C) 2000, 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2000, 2007-2024 Free Software Foundation, Inc.
;; Author: Daiki Ueno <ueno@gnu.org>
;; Keywords: SASL
diff --git a/lisp/net/secrets.el b/lisp/net/secrets.el
index 08ab942fddb..c1a670fde8c 100644
--- a/lisp/net/secrets.el
+++ b/lisp/net/secrets.el
@@ -1,6 +1,6 @@
;;; secrets.el --- Client interface to gnome-keyring and kwallet. -*- lexical-binding: t -*-
-;; Copyright (C) 2010-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2010-2024 Free Software Foundation, Inc.
;; Author: Michael Albinus <michael.albinus@gmx.de>
;; Keywords: comm password passphrase
diff --git a/lisp/net/shr-color.el b/lisp/net/shr-color.el
index cc2e6dc469b..9bd05381c3b 100644
--- a/lisp/net/shr-color.el
+++ b/lisp/net/shr-color.el
@@ -1,6 +1,6 @@
;;; shr-color.el --- Simple HTML Renderer color management -*- lexical-binding:t -*-
-;; Copyright (C) 2010-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2010-2024 Free Software Foundation, Inc.
;; Author: Julien Danjou <julien@danjou.info>
;; Keywords: html
diff --git a/lisp/net/shr.el b/lisp/net/shr.el
index b5bb7b42650..17fdffd619d 100644
--- a/lisp/net/shr.el
+++ b/lisp/net/shr.el
@@ -1,6 +1,6 @@
;;; shr.el --- Simple HTML Renderer -*- lexical-binding: t -*-
-;; Copyright (C) 2010-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2010-2024 Free Software Foundation, Inc.
;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
;; Keywords: html
@@ -163,6 +163,48 @@ the specpdl size. If nil, just give up."
:version "28.1"
:type 'boolean)
+(defcustom shr-fill-text t
+ "Non-nil means to fill the text according to the width of the window.
+If nil, text is not filled, and `visual-line-mode' can be used to reflow text."
+ :version "30.1"
+ :type 'boolean)
+
+
+(defcustom shr-sup-raise-factor 0.2
+ "The value of raise property for superscripts.
+Should be a non-negative float number between 0 and 1."
+ :version "30.1"
+ :type 'float)
+
+(defcustom shr-sub-raise-factor -0.2
+ "The value of raise property for subscripts.
+Should be a non-positive float number between 0 and 1."
+ :version "30.1"
+ :type 'float)
+
+(defcustom shr-image-ascent 100
+ "The value to be used for :ascent property when inserting images."
+ :version "30.1"
+ :type 'integer)
+
+(defcustom shr-max-inline-image-size nil
+ "If non-nil, determines when the images can be displayed inline.
+If nil, images are never displayed inline.
+
+It non-nil, it should be cons (WIDTH . HEIGHT).
+
+WIDTH can be an integer which is interpreted as number of pixels. If the width
+of an image exceeds this amount, the image is displayed on a separate line.
+WIDTH can also be floating point number, in which case the image is displayed
+inline if it occupies less than this fraction of window width.
+
+HEIGHT can be also be an integer or a floating point number. If it is an
+integer and the pixel height of an image exceeds it, the image image is
+displayed on a separate line. If it is a float number , the limit is
+interpreted as a multiple of the height of default font."
+ :version "30.1"
+ :type '(choice (const nil) (cons number number)))
+
(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
@@ -697,7 +739,8 @@ size, and full-buffer size."
(replace-match " " t t)))
(defun shr-insert (text)
- (when (and (not (bolp))
+ (when (and (not shr-max-inline-image-size)
+ (not (bolp))
(get-text-property (1- (point)) 'image-url))
(insert "\n"))
(cond
@@ -741,7 +784,7 @@ size, and full-buffer size."
(or shr-current-font 'shr-text)))))))))
(defun shr-fill-lines (start end)
- (if (<= shr-internal-width 0)
+ (if (or (not shr-fill-text) (<= shr-internal-width 0))
nil
(save-restriction
(narrow-to-region start end)
@@ -1049,6 +1092,19 @@ the mouse click event."
(declare-function image-size "image.c" (spec &optional pixels frame))
(declare-function image-animate "image" (image &optional index limit position))
+(defun shr--inline-image-p (image)
+ "Return non-nil if IMAGE should be displayed inline."
+ (when shr-max-inline-image-size
+ (let ((size (image-size image t))
+ (max-width (car shr-max-inline-image-size))
+ (max-height (cdr shr-max-inline-image-size)))
+ (unless (integerp max-width)
+ (setq max-width (* max-width (window-width nil t))))
+ (unless (integerp max-height)
+ (setq max-height (* max-height (frame-char-height))))
+ (and (< (car size) max-width)
+ (< (cdr size) max-height)))))
+
(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
@@ -1063,11 +1119,11 @@ element is the data blob and the second element is the content-type."
(start (point))
(image (cond
((eq size 'original)
- (create-image data nil t :ascent 100
+ (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 100)))
+ (create-image data 'svg t :ascent shr-image-ascent)))
((eq size 'full)
(ignore-errors
(shr-rescale-image data content-type
@@ -1079,19 +1135,27 @@ element is the data blob and the second element is the content-type."
(plist-get flags :width)
(plist-get flags :height)))))))
(when image
+ ;; The trailing space can confuse shr-insert into not
+ ;; putting any space after inline images.
+ ;; ALT may be nil when visiting image URLs in eww
+ ;; (bug#67764).
+ (setq alt (if alt (string-trim alt) "*"))
;; When inserting big-ish pictures, put them at the
;; beginning of the line.
- (when (and (> (current-column) 0)
- (> (car (image-size image t)) 400))
- (insert "\n"))
- (let ((image-pos (point)))
- (if (eq size 'original)
- (insert-sliced-image image (or alt "*") nil 20 1)
- (insert-image image (or alt "*")))
- (put-text-property start (point) 'image-size size)
- (when (and shr-image-animate
- (cdr (image-multi-frame-p image)))
- (image-animate image nil 60 image-pos))))
+ (let ((inline (shr--inline-image-p image)))
+ (when (and (> (current-column) 0)
+ (not inline))
+ (insert "\n"))
+ (let ((image-pos (point)))
+ (if (eq size 'original)
+ (insert-sliced-image image alt nil 20 1)
+ (insert-image image alt))
+ (put-text-property start (point) 'image-size size)
+ (when (and (not inline) shr-max-inline-image-size)
+ (insert "\n"))
+ (when (and shr-image-animate
+ (cdr (image-multi-frame-p image)))
+ (image-animate image nil 60 image-pos)))))
image)
(insert (or alt ""))))
@@ -1114,7 +1178,7 @@ The size of the displayed image will not exceed
MAX-WIDTH/MAX-HEIGHT. If not given, use the current window
width/height instead."
(if (not (get-buffer-window (current-buffer) t))
- (create-image data nil t :ascent 100)
+ (create-image data nil t :ascent shr-image-ascent)
(let* ((edges (window-inside-pixel-edges
(get-buffer-window (current-buffer))))
(max-width (truncate (* shr-max-image-proportion
@@ -1135,13 +1199,13 @@ width/height instead."
(< (* height scaling) max-height))
(create-image
data (shr--image-type) t
- :ascent 100
+ :ascent shr-image-ascent
:width width
:height height
:format content-type)
(create-image
data (shr--image-type) t
- :ascent 100
+ :ascent shr-image-ascent
:max-width max-width
:max-height max-height
:format content-type)))))
@@ -1210,7 +1274,11 @@ START, and END. Note that START and END should be markers."
(defun shr-heading (dom &rest types)
(shr-ensure-paragraph)
- (apply #'shr-fontize-dom dom types)
+ (let ((start (point))
+ (level (string-to-number
+ (string-remove-prefix "shr-h" (symbol-name (car types))))))
+ (apply #'shr-fontize-dom dom types)
+ (put-text-property start (pos-eol) 'outline-level level))
(shr-ensure-paragraph))
(defun shr-urlify (start url &optional title)
@@ -1381,13 +1449,20 @@ ones, in case fg and bg are nil."
(defun shr-tag-sup (dom)
(let ((start (point)))
(shr-generic dom)
- (put-text-property start (point) 'display '(raise 0.2))
+ (put-text-property start (point) 'display `(raise ,shr-sup-raise-factor))
(add-face-text-property start (point) 'shr-sup)))
(defun shr-tag-sub (dom)
+ ;; Why would a subscript be at the beginning of a line? It does
+ ;; happen sometimes because of a <br> tag and the intent seems to be
+ ;; alignment of subscript and superscript but I don't think that is
+ ;; possible in Emacs. So we remove the newline in that case.
+ (when (bolp)
+ (forward-char -1)
+ (delete-char 1))
(let ((start (point)))
(shr-generic dom)
- (put-text-property start (point) 'display '(raise -0.2))
+ (put-text-property start (point) 'display `(raise ,shr-sub-raise-factor))
(add-face-text-property start (point) 'shr-sup)))
(defun shr-tag-p (dom)
@@ -1652,7 +1727,8 @@ The preference is a float determined from `shr-prefer-media-type'."
(and dom
(or (> (length (dom-attr dom 'src)) 0)
(> (length (dom-attr dom 'srcset)) 0))))
- (when (> (current-column) 0)
+ (when (and (not shr-max-inline-image-size)
+ (> (current-column) 0))
(insert "\n"))
(let ((alt (dom-attr dom 'alt))
(width (shr-string-number (dom-attr dom 'width)))
@@ -1703,8 +1779,14 @@ The preference is a float determined from `shr-prefer-media-type'."
(when (image-type-available-p 'svg)
(insert-image
(shr-make-placeholder-image dom)
- (or alt "")))
- (insert " ")
+ (or (string-trim alt) "")))
+ ;; Paradoxically this space causes shr not to insert spaces after
+ ;; inline images. Since the image is temporary it seem like there
+ ;; should be no downside to not inserting it but since I don't
+ ;; understand the code well and for the sake of backward compatibility
+ ;; we preserve it unless user has set `shr-max-inline-image-size'.
+ (unless shr-max-inline-image-size
+ (insert " "))
(url-queue-retrieve
url #'shr-image-fetched
(list (current-buffer) start (set-marker (make-marker) (point))
@@ -1840,7 +1922,7 @@ BASE is the URL of the HTML being rendered."
(svg-rectangle svg 0 0 width height :gradient "background"
:stroke-width 2 :stroke-color "black")
(let ((image (svg-image svg :scale 1)))
- (setf (image-property image :ascent) 100)
+ (setf (image-property image :ascent) shr-image-ascent)
image)))
(defun shr-tag-pre (dom)
@@ -2000,6 +2082,41 @@ BASE is the URL of the HTML being rendered."
(shr-generic dom)
(insert ?\N{POP DIRECTIONAL ISOLATE}))
+;;; Outline Support
+(defun shr-outline-search (&optional bound move backward looking-at)
+ "A function that can be used as `outline-search-function' for rendered html.
+See `outline-search-function' for BOUND, MOVE, BACKWARD and LOOKING-AT."
+ (if looking-at
+ (get-text-property (point) 'outline-level)
+ (let ((heading-found nil)
+ (bound (or bound
+ (if backward (point-min) (point-max)))))
+ (save-excursion
+ (when (and (not (bolp))
+ (get-text-property (point) 'outline-level))
+ (forward-line (if backward -1 1)))
+ (if backward
+ (unless (get-text-property (point) 'outline-level)
+ (goto-char (or (previous-single-property-change
+ (point) 'outline-level nil bound)
+ bound)))
+ (goto-char (or (text-property-not-all (point) bound 'outline-level nil)
+ bound)))
+ (goto-char (pos-bol))
+ (when (get-text-property (point) 'outline-level)
+ (setq heading-found (point))))
+ (if heading-found
+ (progn
+ (set-match-data (list heading-found heading-found))
+ (goto-char heading-found))
+ (when move
+ (goto-char bound)
+ nil)))))
+
+(defun shr-outline-level ()
+ "Function to be used as `outline-level' with `shr-outline-search'."
+ (get-text-property (point) 'outline-level))
+
;;; Table rendering algorithm.
;; Table rendering is the only complicated thing here. We do this by
@@ -2617,11 +2734,12 @@ flags that control whether to collect or render objects."
columns))
(defun shr-count (dom elem)
+ ;; This is faster than `seq-count', and shr can use it.
(let ((i 0))
(dolist (sub (dom-children dom))
(when (and (not (stringp sub))
- (eq (dom-tag sub) elem))
- (setq i (1+ i))))
+ (eq (dom-tag sub) elem))
+ (setq i (1+ i))))
i))
(defun shr-max-columns (dom)
diff --git a/lisp/net/sieve-manage.el b/lisp/net/sieve-manage.el
index 5bee4f4c4ad..0faeb02bcfd 100644
--- a/lisp/net/sieve-manage.el
+++ b/lisp/net/sieve-manage.el
@@ -1,6 +1,6 @@
;;; sieve-manage.el --- Implementation of the managesieve protocol in elisp -*- lexical-binding:t -*-
-;; Copyright (C) 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2024 Free Software Foundation, Inc.
;; Author: Simon Josefsson <simon@josefsson.org>
;; Albert Krewinkel <tarleb@moltkeplatz.de>
@@ -171,8 +171,8 @@ Valid states are `closed', `initial', `nonauth', and `auth'.")
"Append ARGS to sieve-manage log buffer.
ARGS can be a string or a list of strings.
-The buffer to use for logging is specifified via
-`sieve-manage-log'. If it is nil, logging is disabled."
+The buffer to use for logging is specified via `sieve-manage-log'.
+If it is nil, logging is disabled."
(when sieve-manage-log
(with-current-buffer (or (get-buffer sieve-manage-log)
(with-current-buffer
@@ -511,7 +511,7 @@ If NAME is nil, return the full server list of capabilities."
(while (not pos)
(setq pos (search-forward-regexp pattern nil t))
(goto-char (point-min))
- (sleep-for 0 50))
+ (sleep-for 0.05))
pos))
(defun sieve-manage-drop-next-answer ()
diff --git a/lisp/net/sieve-mode.el b/lisp/net/sieve-mode.el
index a54c3c6f103..4fbdd183973 100644
--- a/lisp/net/sieve-mode.el
+++ b/lisp/net/sieve-mode.el
@@ -1,6 +1,6 @@
;;; sieve-mode.el --- Sieve code editing commands for Emacs -*- lexical-binding: t -*-
-;; Copyright (C) 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2024 Free Software Foundation, Inc.
;; Author: Simon Josefsson <simon@josefsson.org>
@@ -55,39 +55,19 @@
;; Font-lock
(defface sieve-control-commands
- '((((type tty) (class color)) (:foreground "blue" :weight light))
- (((class grayscale) (background light)) (:foreground "LightGray" :bold t))
- (((class grayscale) (background dark)) (:foreground "DimGray" :bold t))
- (((class color) (background light)) (:foreground "Orchid"))
- (((class color) (background dark)) (:foreground "LightSteelBlue"))
- (t (:bold t)))
+ '((t :inherit font-lock-builtin-face))
"Face used for Sieve Control Commands.")
(defface sieve-action-commands
- '((((type tty) (class color)) (:foreground "blue" :weight bold))
- (((class color) (background light)) (:foreground "Blue"))
- (((class color) (background dark)) (:foreground "LightSkyBlue"))
- (t (:inverse-video t :bold t)))
+ '((t :inherit font-lock-function-name-face))
"Face used for Sieve Action Commands.")
(defface sieve-test-commands
- '((((type tty) (class color)) (:foreground "magenta"))
- (((class grayscale) (background light))
- (:foreground "LightGray" :bold t :underline t))
- (((class grayscale) (background dark))
- (:foreground "Gray50" :bold t :underline t))
- (((class color) (background light)) (:foreground "CadetBlue"))
- (((class color) (background dark)) (:foreground "Aquamarine"))
- (t (:bold t :underline t)))
+ '((t :inherit font-lock-constant-face))
"Face used for Sieve Test Commands.")
(defface sieve-tagged-arguments
- '((((type tty) (class color)) (:foreground "cyan" :weight bold))
- (((class grayscale) (background light)) (:foreground "LightGray" :bold t))
- (((class grayscale) (background dark)) (:foreground "DimGray" :bold t))
- (((class color) (background light)) (:foreground "Purple"))
- (((class color) (background dark)) (:foreground "Cyan"))
- (t (:bold t)))
+ '((t :inherit font-lock-keyword face))
"Face used for Sieve Tagged Arguments.")
diff --git a/lisp/net/sieve.el b/lisp/net/sieve.el
index fbd07dee27c..fddc6e21bcc 100644
--- a/lisp/net/sieve.el
+++ b/lisp/net/sieve.el
@@ -1,6 +1,6 @@
;;; sieve.el --- Utilities to manage sieve scripts -*- lexical-binding: t; -*-
-;; Copyright (C) 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2024 Free Software Foundation, Inc.
;; Author: Simon Josefsson <simon@josefsson.org>
diff --git a/lisp/net/snmp-mode.el b/lisp/net/snmp-mode.el
index 24f6bd8ae57..016b7a39d9d 100644
--- a/lisp/net/snmp-mode.el
+++ b/lisp/net/snmp-mode.el
@@ -1,6 +1,6 @@
;;; snmp-mode.el --- SNMP & SNMPv2 MIB major mode -*- lexical-binding: t -*-
-;; Copyright (C) 1995, 1998, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1995, 1998, 2001-2024 Free Software Foundation, Inc.
;; Author: Paul D. Smith <psmith@BayNetworks.com>
;; Keywords: data
diff --git a/lisp/net/soap-client.el b/lisp/net/soap-client.el
index 010e86354b6..de04d58ed18 100644
--- a/lisp/net/soap-client.el
+++ b/lisp/net/soap-client.el
@@ -1,6 +1,6 @@
;;; soap-client.el --- Access SOAP web services -*- lexical-binding: t -*-
-;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
;; Author: Alexandru Harsanyi <AlexHarsanyi@gmail.com>
;; Author: Thomas Fitzsimmons <fitzsim@fitzsim.org>
@@ -11,6 +11,9 @@
;; URL: https://github.com/alex-hhh/emacs-soap-client
;; Package-Requires: ((emacs "24.1") (cl-lib "0.6.1"))
+;; This is a GNU ELPA :core package. Avoid functionality that is not
+;; compatible with the version of Emacs recorded above.
+
;; This file is part of GNU Emacs.
;; GNU Emacs is free software: you can redistribute it and/or modify
@@ -1953,7 +1956,7 @@ This is a specialization of `soap-decode-type' for
(xml-get-children node (intern e-name)))
;; e-name is nil so a) we don't know which
;; children to operate on, and b) we want to
- ;; re-use soap-decode-xs-complex-type, which
+ ;; reuse soap-decode-xs-complex-type, which
;; expects a node argument with a complex
;; type; therefore we need to operate on the
;; entire node. We wrap node in a list so
diff --git a/lisp/net/soap-inspect.el b/lisp/net/soap-inspect.el
index 97e962dfae5..c7e9d477a78 100644
--- a/lisp/net/soap-inspect.el
+++ b/lisp/net/soap-inspect.el
@@ -1,6 +1,6 @@
;;; soap-inspect.el --- Interactive WSDL inspector -*- lexical-binding: t -*-
-;; Copyright (C) 2010-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2010-2024 Free Software Foundation, Inc.
;; Author: Alexandru Harsanyi <AlexHarsanyi@gmail.com>
;; Created: October 2010
diff --git a/lisp/net/socks.el b/lisp/net/socks.el
index 968a28d2be8..ecbac7e2345 100644
--- a/lisp/net/socks.el
+++ b/lisp/net/socks.el
@@ -1,6 +1,6 @@
;;; socks.el --- A Socks v5 Client for Emacs -*- lexical-binding:t -*-
-;; Copyright (C) 1996-2000, 2002, 2007-2023 Free Software Foundation,
+;; Copyright (C) 1996-2000, 2002, 2007-2024 Free Software Foundation,
;; Inc.
;; Author: William M. Perry <wmperry@gnu.org>
@@ -162,6 +162,7 @@
(radio-button-choice :tag "SOCKS Version"
:format "%t: %v"
(const :tag "SOCKS v4 " :format "%t" :value 4)
+ (const :tag "SOCKS v4a" :format "%t" :value 4a)
(const :tag "SOCKS v5" :format "%t" :value 5))))
@@ -202,6 +203,12 @@
"Command not supported"
"Address type not supported"))
+(defconst socks--errors-4
+ '("Granted"
+ "Rejected or failed"
+ "Cannot connect to identd on the client"
+ "Client and identd report differing user IDs"))
+
;; The socks v5 address types
(defconst socks-address-type-v4 1)
(defconst socks-address-type-name 3)
@@ -309,7 +316,8 @@
((pred (= socks-address-type-name))
(if (< (length string) 5)
255
- (+ 1 (aref string 4)))))))
+ (+ 1 (aref string 4))))
+ (0 0))))
(if (< (length string) desired-len)
nil ; Need to spin some more
(process-put proc 'socks-state socks-state-connected)
@@ -399,6 +407,7 @@ When ATYPE indicates an IP, param ADDRESS must be given as raw bytes."
(format "%c%s" (length address) address))
(t
(error "Unknown address type: %d" atype))))
+ trailing
request version)
(or (process-get proc 'socks)
(error "socks-send-command called on non-SOCKS connection %S" proc))
@@ -415,6 +424,12 @@ When ATYPE indicates an IP, param ADDRESS must be given as raw bytes."
(t
(error "Unsupported address type for HTTP: %d" atype)))
port)))
+ ((and (eq version '4a)
+ (setf addr "\0\0\0\1"
+ trailing (concat address "\0")
+ version 4 ; become version 4
+ (process-get proc 'socks-server-protocol) 4)
+ nil)) ; fall through
((equal version 4)
(setq request (concat
(unibyte-string
@@ -423,8 +438,9 @@ When ATYPE indicates an IP, param ADDRESS must be given as raw bytes."
(ash port -8) ; port, high byte
(logand port #xff)) ; port, low byte
addr ; address
- (user-full-name) ; username
- "\0"))) ; terminate username
+ socks-username ; username
+ "\0" ; terminate username
+ trailing))) ; optional host to look up
((equal version 5)
(setq request (concat
(unibyte-string
@@ -445,7 +461,13 @@ When ATYPE indicates an IP, param ADDRESS must be given as raw bytes."
nil ; Sweet sweet success!
(delete-process proc)
(error "SOCKS: %s"
- (nth (or (process-get proc 'socks-reply) 1) socks-errors)))
+ (let ((err (process-get proc 'socks-reply)))
+ (if (eql version 5)
+ (nth (or err 1) socks-errors)
+ ;; The defined error codes for v4 range from
+ ;; 90-93, but we store them in a simple list.
+ (nth (pcase err (90 0) (92 2) (93 3) (_ 1))
+ socks--errors-4)))))
proc))
diff --git a/lisp/net/telnet.el b/lisp/net/telnet.el
index fbe9af3d6a5..d0008501ea3 100644
--- a/lisp/net/telnet.el
+++ b/lisp/net/telnet.el
@@ -1,6 +1,6 @@
;;; telnet.el --- run a telnet session from within an Emacs buffer -*- lexical-binding: t; -*-
-;; Copyright (C) 1985-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1985-2024 Free Software Foundation, Inc.
;; Author: William F. Schelter
;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/net/tramp-adb.el b/lisp/net/tramp-adb.el
index 076103e8ae4..2e4ad1cc412 100644
--- a/lisp/net/tramp-adb.el
+++ b/lisp/net/tramp-adb.el
@@ -1,6 +1,6 @@
;;; tramp-adb.el --- Functions for calling Android Debug Bridge from Tramp -*- lexical-binding:t -*-
-;; Copyright (C) 2011-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2011-2024 Free Software Foundation, Inc.
;; Author: Jürgen Hötzel <juergen@archlinux.org>
;; Keywords: comm, processes
@@ -435,7 +435,7 @@ Emacs dired can't find files."
(defun tramp-adb-handle-file-name-all-completions (filename directory)
"Like `file-name-all-completions' for Tramp files."
- (ignore-error file-missing
+ (tramp-skeleton-file-name-all-completions filename directory
(all-completions
filename
(with-parsed-tramp-file-name (expand-file-name directory) nil
@@ -450,17 +450,10 @@ Emacs dired can't find files."
(file-name-as-directory f)
f))
(with-current-buffer (tramp-get-buffer v)
- (delete-dups
- (append
- ;; On some file systems like "sdcard", "." and ".." are
- ;; not included. We fix this by `delete-dups'.
- '("." "..")
- (delq
- nil
- (mapcar
- (lambda (l)
- (and (not (string-match-p (rx bol (* blank) eol) l)) l))
- (split-string (buffer-string) "\n"))))))))))))
+ (mapcar
+ (lambda (l)
+ (and (not (string-match-p (rx bol (* blank) eol) l)) l))
+ (split-string (buffer-string) "\n" 'omit)))))))))
(defun tramp-adb-handle-file-local-copy (filename)
"Like `file-local-copy' for Tramp files."
@@ -923,7 +916,7 @@ implementation will be used."
(when (string-match-p (rx multibyte) command)
(tramp-error
- v 'file-error "Cannot apply multi-byte command `%s'" command))
+ v 'file-error "Cannot apply multibyte command `%s'" command))
(while (get-process name1)
;; NAME must be unique as process name.
diff --git a/lisp/net/tramp-archive.el b/lisp/net/tramp-archive.el
index 590544f199f..298cacdb0e0 100644
--- a/lisp/net/tramp-archive.el
+++ b/lisp/net/tramp-archive.el
@@ -1,6 +1,6 @@
;;; tramp-archive.el --- Tramp archive manager -*- lexical-binding:t -*-
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
;; Author: Michael Albinus <michael.albinus@gmx.de>
;; Keywords: comm, processes
diff --git a/lisp/net/tramp-cache.el b/lisp/net/tramp-cache.el
index 8282e9c87ff..25123a6e282 100644
--- a/lisp/net/tramp-cache.el
+++ b/lisp/net/tramp-cache.el
@@ -1,6 +1,6 @@
;;; tramp-cache.el --- file information caching for Tramp -*- lexical-binding:t -*-
-;; Copyright (C) 2000, 2005-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2000, 2005-2024 Free Software Foundation, Inc.
;; Author: Daniel Pittman <daniel@inanna.danann.net>
;; Michael Albinus <michael.albinus@gmx.de>
@@ -28,8 +28,8 @@
;; An implementation of information caching for remote files.
;; Each connection, identified by a `tramp-file-name' structure or by
-;; a process, has a unique cache. We distinguish 6 kind of caches,
-;; depending on the key:
+;; a process, has a unique cache. We distinguish several kinds of
+;; caches, depending on the key:
;;
;; - localname is nil. These are reusable properties. Examples:
;; "remote-shell" identifies the POSIX shell to be called on the
@@ -50,11 +50,14 @@
;; definitions already sent to the remote shell, "last-cmd-time" is
;; the timestamp a command has been sent to the remote process.
;;
-;; - The key is nil. These are temporary properties related to the
-;; local machine. Examples: "parse-passwd" and "parse-group" keep
-;; the results of parsing "/etc/passwd" and "/etc/group",
+;; - The key is `tramp-null-hop' or nil. These are temporary
+;; properties related to the local machine. If the key is nil, it
+;; is silently converted into `tramp-null-hop'.
+;; Examples: "parse-passwd" and "parse-group" keep the results of
+;; parsing "/etc/passwd" and "/etc/group",
;; "{uid,gid}-{integer,string}" are the local uid and gid, and
-;; "locale" is the used shell locale.
+;; "locale" is the used shell locale. "user-host-completions" keeps
+;; the reachable hosts for the commands in tramp-container.el.
;;
;; - The key is `tramp-cache-version'. It keeps the Tramp version the
;; cache data was produced with. If the cache is read by another
@@ -337,7 +340,7 @@ Preserve timestamps."
(declare (indent 3) (debug t))
`(progn
;; Unify localname. Remove hop from `tramp-file-name' structure.
- (setq ,key (tramp-file-name-unify ,key ,file))
+ (setf ,key (tramp-file-name-unify ,key ,file))
(let* ((hash (tramp-get-hash-table ,key))
(cached (and (hash-table-p hash) (gethash ,property hash))))
(unwind-protect (progn ,@body)
@@ -355,7 +358,7 @@ Preserve timestamps."
(declare (indent 3) (debug t))
`(progn
;; Unify localname. Remove hop from `tramp-file-name' structure.
- (setq ,key (tramp-file-name-unify ,key ,file))
+ (setf ,key (tramp-file-name-unify ,key ,file))
(let* ((hash (tramp-get-hash-table ,key))
(values
(and (hash-table-p hash)
@@ -471,7 +474,7 @@ used to cache connection properties of the local machine."
"Save PROPERTY, run BODY, reset PROPERTY."
(declare (indent 2) (debug t))
`(progn
- (setq ,key (tramp-file-name-unify ,key))
+ (setf ,key (tramp-file-name-unify ,key))
(let* ((hash (tramp-get-hash-table ,key))
(cached (and (hash-table-p hash)
(gethash ,property hash tramp-cache-undefined))))
@@ -488,7 +491,7 @@ used to cache connection properties of the local machine."
PROPERTIES is a list of file properties (strings)."
(declare (indent 2) (debug t))
`(progn
- (setq ,key (tramp-file-name-unify ,key))
+ (setf ,key (tramp-file-name-unify ,key))
(let* ((hash (tramp-get-hash-table ,key))
(values
(mapcar
@@ -568,6 +571,8 @@ PROPERTIES is a list of file properties (strings)."
(stringp tramp-persistency-file-name))
(let ((cache (copy-hash-table tramp-cache-data))
print-length print-level)
+ ;; Remove `tramp-null-hop'.
+ (remhash tramp-null-hop cache)
;; Remove temporary data. If there is the key "login-as", we
;; don't save either, because all other properties might
;; depend on the login name, and we want to give the
diff --git a/lisp/net/tramp-cmds.el b/lisp/net/tramp-cmds.el
index 87651d60328..a545a8e7273 100644
--- a/lisp/net/tramp-cmds.el
+++ b/lisp/net/tramp-cmds.el
@@ -1,6 +1,6 @@
;;; tramp-cmds.el --- Interactive commands for Tramp -*- lexical-binding:t -*-
-;; Copyright (C) 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2024 Free Software Foundation, Inc.
;; Author: Michael Albinus <michael.albinus@gmx.de>
;; Keywords: comm, processes
@@ -31,6 +31,8 @@
(require 'tramp)
;; Pacify byte-compiler.
+(declare-function dired-advertise "dired")
+(declare-function dired-unadvertise "dired")
(declare-function mml-mode "mml")
(declare-function mml-insert-empty-tag "mml")
(declare-function reporter-dump-variable "reporter")
@@ -52,6 +54,7 @@ SYNTAX can be one of the symbols `default' (default),
(when syntax
(customize-set-variable 'tramp-syntax syntax)))
+;; Use `match-buffers' starting with Emacs 29.1.
;;;###tramp-autoload
(defun tramp-list-tramp-buffers ()
"Return a list of all Tramp connection buffers."
@@ -63,6 +66,7 @@ SYNTAX can be one of the symbols `default' (default),
(all-completions
"*trace tramp" (mapcar #'list (mapcar #'buffer-name (buffer-list))))))
+;; Use `match-buffers' starting with Emacs 29.1.
;;;###tramp-autoload
(defun tramp-list-remote-buffers ()
"Return a list of all buffers with remote `default-directory'."
@@ -73,6 +77,8 @@ SYNTAX can be one of the symbols `default' (default),
(when (tramp-tramp-file-p (tramp-get-default-directory x)) x))
(buffer-list))))
+;;; Cleanup
+
;;;###tramp-autoload
(defvar tramp-cleanup-connection-hook nil
"List of functions to be called after Tramp connection is cleaned up.
@@ -219,13 +225,13 @@ functions are called with `current-buffer' set."
(add-hook 'tramp-cleanup-some-buffers-hook
#'buffer-file-name)
-(defun tramp-cleanup-dired-buffer-p ()
+(defun tramp-dired-buffer-p ()
"Return t if current buffer runs `dired-mode'."
(declare (tramp-suppress-trace t))
(derived-mode-p 'dired-mode))
(add-hook 'tramp-cleanup-some-buffers-hook
- #'tramp-cleanup-dired-buffer-p)
+ #'tramp-dired-buffer-p)
(defvar tramp-tainted-remote-process-buffers nil
"List of process buffers to be cleaned up.")
@@ -254,12 +260,12 @@ functions are called with `current-buffer' set."
(remove-hook 'kill-buffer-hook
#'tramp-delete-tainted-remote-process-buffer-function)))
-(defun tramp-cleanup-remote-process-p ()
+(defun tramp-remote-process-p ()
"Return t if current buffer belongs to a remote process."
(memq (current-buffer) tramp-tainted-remote-process-buffers))
(add-hook 'tramp-cleanup-some-buffers-hook
- #'tramp-cleanup-remote-process-p)
+ #'tramp-remote-process-p)
;;;###tramp-autoload
(defun tramp-cleanup-some-buffers ()
@@ -286,6 +292,8 @@ non-nil."
(let ((tramp-cleanup-some-buffers-hook '(tramp-compat-always)))
(tramp-cleanup-some-buffers)))
+;;; Rename
+
(defcustom tramp-default-rename-alist nil
"Default target for renaming remote buffer file names.
This is an alist of cons cells (SOURCE . TARGET). The first
@@ -550,6 +558,73 @@ For details, see `tramp-rename-files'."
(function-put
#'tramp-rename-these-files 'completion-predicate #'tramp-command-completion-p)
+;;; Run as sudo
+
+(defcustom tramp-file-name-with-method "sudo"
+ "Which method to be used in `tramp-file-name-with-sudo'."
+ :group 'tramp
+ :version "30.1"
+ :type '(choice (const "su")
+ (const "sudo")
+ (const "doas")
+ (const "ksu")))
+
+(defun tramp-file-name-with-sudo (filename)
+ "Convert FILENAME into a multi-hop file name with \"sudo\".
+An alternative method could be chosen with `tramp-file-name-with-method'."
+ (setq filename (expand-file-name filename))
+ (if (tramp-tramp-file-p filename)
+ (with-parsed-tramp-file-name filename nil
+ (cond
+ ;; Remote file with proper method.
+ ((string-equal method tramp-file-name-with-method)
+ filename)
+ ;; Remote file on the local host.
+ ((and
+ (stringp tramp-local-host-regexp) (stringp host)
+ (string-match-p tramp-local-host-regexp host))
+ (tramp-make-tramp-file-name
+ (make-tramp-file-name
+ :method tramp-file-name-with-method :localname localname)))
+ ;; Remote file with multi-hop capable method..
+ ((tramp-multi-hop-p v)
+ (tramp-make-tramp-file-name
+ (make-tramp-file-name
+ :method (tramp-find-method tramp-file-name-with-method nil host)
+ :user (tramp-find-user tramp-file-name-with-method nil host)
+ :host (tramp-find-host tramp-file-name-with-method nil host)
+ :localname localname :hop (tramp-make-tramp-hop-name v))))
+ ;; Other remote file.
+ (t (tramp-user-error v "Multi-hop with `%s' not applicable" method))))
+ ;; Local file.
+ (tramp-make-tramp-file-name
+ (make-tramp-file-name
+ :method tramp-file-name-with-method :localname filename))))
+
+;;;###tramp-autoload
+(defun tramp-revert-buffer-with-sudo ()
+ "Revert current buffer to visit with \"sudo\" permissions.
+An alternative method could be chosen with `tramp-file-name-with-method'.
+If the buffer visits a file, the file is replaced.
+If the buffer runs `dired', the buffer is reverted."
+ (interactive)
+ (cond
+ ((buffer-file-name)
+ (find-alternate-file (tramp-file-name-with-sudo (buffer-file-name))))
+ ((tramp-dired-buffer-p)
+ (dired-unadvertise (expand-file-name default-directory))
+ (setq default-directory (tramp-file-name-with-sudo default-directory)
+ list-buffers-directory
+ (tramp-file-name-with-sudo list-buffers-directory))
+ (if (consp dired-directory)
+ (setcar
+ dired-directory (tramp-file-name-with-sudo (car dired-directory)))
+ (setq dired-directory (tramp-file-name-with-sudo dired-directory)))
+ (dired-advertise)
+ (revert-buffer))))
+
+;;; Recompile on ELPA
+
;; This function takes action since Emacs 28.1, when
;; `read-extended-command-predicate' is set to
;; `command-completion-default-include-p'.
diff --git a/lisp/net/tramp-compat.el b/lisp/net/tramp-compat.el
index 5bd3dff3d21..8065ba01734 100644
--- a/lisp/net/tramp-compat.el
+++ b/lisp/net/tramp-compat.el
@@ -1,6 +1,6 @@
;;; tramp-compat.el --- Tramp compatibility functions -*- lexical-binding:t -*-
-;; Copyright (C) 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2024 Free Software Foundation, Inc.
;; Author: Michael Albinus <michael.albinus@gmx.de>
;; Keywords: comm, processes
@@ -61,6 +61,7 @@
;; avoid them in cases we know what we do.
(defmacro tramp-compat-funcall (function &rest arguments)
"Call FUNCTION with ARGUMENTS if it exists. Do not raise compiler warnings."
+ (declare (indent 1) (debug t))
`(when (functionp ,function)
(with-no-warnings (funcall ,function ,@arguments))))
@@ -75,7 +76,7 @@
(prog1 (setq xdg (concat (file-name-as-directory xdg) "emacs"))
(make-directory xdg t))
(eval (car (get 'temporary-file-directory 'standard-value)) t)))
- "The default value of `temporary-file-directory'.")
+ "The default value of `temporary-file-directory' for Tramp.")
(defsubst tramp-compat-make-temp-name ()
"Generate a local temporary file name (compat function)."
@@ -306,6 +307,16 @@ Also see `ignore'."
?\N{KHMER SIGN CAMNUC PII KUUH})
"List of characters equivalent to trailing colon in \"password\" prompts."))
+;; Macro `connection-local-p' is new in Emacs 30.1.
+(if (macrop 'connection-local-p)
+ (defalias 'tramp-compat-connection-local-p #'connection-local-p)
+ (defmacro tramp-compat-connection-local-p (variable)
+ "Non-nil if VARIABLE has a connection-local binding in `default-directory'."
+ `(let (connection-local-variables-alist file-local-variables-alist)
+ (hack-connection-local-variables
+ (connection-local-criteria-for-default-directory))
+ (and (assq ',variable connection-local-variables-alist) t))))
+
(dolist (elt (all-completions "tramp-compat-" obarray 'functionp))
(function-put (intern elt) 'tramp-suppress-trace t))
diff --git a/lisp/net/tramp-container.el b/lisp/net/tramp-container.el
index 7f8d4473ad7..1f578949e4d 100644
--- a/lisp/net/tramp-container.el
+++ b/lisp/net/tramp-container.el
@@ -1,6 +1,6 @@
;;; tramp-container.el --- Tramp integration for Docker-like containers -*- lexical-binding: t; -*-
-;; Copyright © 2022-2023 Free Software Foundation, Inc.
+;; Copyright © 2022-2024 Free Software Foundation, Inc.
;; Author: Brian Cully <bjc@kublai.com>
;; Keywords: comm, processes
@@ -158,55 +158,80 @@ If it is nil, the default context will be used."
"Tramp method name to use to connect to Flatpak sandboxes.")
;;;###tramp-autoload
-(defun tramp-container--completion-function (program)
+(defmacro tramp-skeleton-completion-function (method &rest body)
+ "Skeleton for `tramp-*-completion-function' with multi-hop support.
+BODY is the backend specific code."
+ (declare (indent 1) (debug t))
+ `(let* ((default-directory
+ (or (and (member ,method tramp-completion-multi-hop-methods)
+ tramp--last-hop-directory)
+ tramp-compat-temporary-file-directory))
+ (program (let ((tramp-verbose 0))
+ (tramp-get-method-parameter
+ (make-tramp-file-name :method ,method)
+ 'tramp-login-program)))
+ (vec (when (tramp-tramp-file-p default-directory)
+ (tramp-dissect-file-name default-directory)))
+ non-essential)
+ ;; We don't use connection properties, because this information
+ ;; shouldn't be kept persistently.
+ (with-tramp-file-property
+ vec (concat "/" ,method ":") "user-host-completions"
+ ,@body)))
+
+;;;###tramp-autoload
+(defun tramp-container--completion-function (method)
"List running containers available for connection.
-PROGRAM is the program to be run for \"ps\", either
-`tramp-docker-program' or `tramp-podman-program'.
+METHOD is the Tramp method to be used for \"ps\", either
+`tramp-docker-method' or `tramp-podman-method'.
This function is used by `tramp-set-completion-function', please
see its function help for a description of the format."
- (when-let ((default-directory tramp-compat-temporary-file-directory)
- (raw-list (shell-command-to-string
- (concat program " ps --format '{{.ID}}\t{{.Names}}'")))
- (lines (split-string raw-list "\n" 'omit))
- (names (mapcar
- (lambda (line)
- (when (string-match
- (rx bol (group (1+ nonl))
- "\t" (? (group (1+ nonl))) eol)
- line)
- (or (match-string 2 line) (match-string 1 line))))
- lines)))
- (mapcar (lambda (name) (list nil name)) (delq nil names))))
+ (tramp-skeleton-completion-function method
+ (when-let ((raw-list
+ (shell-command-to-string
+ (concat program " ps --format '{{.ID}}\t{{.Names}}'")))
+ (lines (split-string raw-list "\n" 'omit))
+ (names
+ (mapcar
+ (lambda (line)
+ (when (string-match
+ (rx bol (group (1+ nonl))
+ "\t" (? (group (1+ nonl))) eol)
+ line)
+ (or (match-string 2 line) (match-string 1 line))))
+ lines)))
+ (mapcar (lambda (name) (list nil name)) (delq nil names)))))
;;;###tramp-autoload
-(defun tramp-kubernetes--completion-function (&rest _args)
+(defun tramp-kubernetes--completion-function (method)
"List Kubernetes pods available for connection.
This function is used by `tramp-set-completion-function', please
see its function help for a description of the format."
- (when-let ((default-directory tramp-compat-temporary-file-directory)
- (raw-list (shell-command-to-string
- (concat
- tramp-kubernetes-program " "
- (tramp-kubernetes--context-namespace nil)
- " get pods --no-headers"
- ;; We separate pods by "|". Inside a pod,
- ;; its name is separated from the containers
- ;; by ":". Containers are separated by ",".
- " -o jsonpath='{range .items[*]}{\"|\"}{.metadata.name}"
- "{\":\"}{range .spec.containers[*]}{.name}{\",\"}"
- "{end}{end}'")))
- (lines (split-string raw-list "|" 'omit)))
- (let (names)
- (dolist (line lines)
- (setq line (split-string line ":" 'omit))
- ;; Pod name.
- (push (car line) names)
- ;; Container names.
- (dolist (elt (split-string (cadr line) "," 'omit))
- (push (concat elt "." (car line)) names)))
- (mapcar (lambda (name) (list nil name)) (delq nil names)))))
+ (tramp-skeleton-completion-function method
+ (when-let ((raw-list
+ (shell-command-to-string
+ (concat
+ program " "
+ (tramp-kubernetes--context-namespace vec)
+ " get pods --no-headers"
+ ;; We separate pods by "|". Inside a pod, its name
+ ;; is separated from the containers by ":".
+ ;; Containers are separated by ",".
+ " -o jsonpath='{range .items[*]}{\"|\"}{.metadata.name}"
+ "{\":\"}{range .spec.containers[*]}{.name}{\",\"}"
+ "{end}{end}'")))
+ (lines (split-string raw-list "|" 'omit)))
+ (let (names)
+ (dolist (line lines)
+ (setq line (split-string line ":" 'omit))
+ ;; Pod name.
+ (push (car line) names)
+ ;; Container names.
+ (dolist (elt (split-string (cadr line) "," 'omit))
+ (push (concat elt "." (car line)) names)))
+ (mapcar (lambda (name) (list nil name)) (delq nil names))))))
(defconst tramp-kubernetes--host-name-regexp
(rx (? (group (regexp tramp-host-regexp)) ".")
@@ -229,30 +254,53 @@ see its function help for a description of the format."
(match-string 2 host)))
""))
+;; We must change `vec' and `default-directory' to the previous hop,
+;; in order to run `process-file' in a proper environment.
+(defmacro tramp-skeleton-kubernetes-vector (vec &rest body)
+ "Skeleton for `tramp-kubernetes--current-context*' with multi-hop support.
+BODY is the backend specific code."
+ (declare (indent 1) (debug t))
+ `(let* ((vec
+ (cond
+ ((null ,vec) tramp-null-hop)
+ ((equal (tramp-file-name-method ,vec) tramp-kubernetes-method)
+ (if (tramp-file-name-hop ,vec)
+ (tramp-dissect-hop-name (tramp-file-name-hop ,vec))
+ tramp-null-hop))
+ (t ,vec)))
+ (default-directory
+ (if (equal vec tramp-null-hop)
+ tramp-compat-temporary-file-directory
+ (tramp-make-tramp-file-name vec "/"))))
+ ,@body))
+
(defun tramp-kubernetes--current-context (vec)
"Return Kubernetes current context.
Obey `tramp-kubernetes-context'"
(or tramp-kubernetes-context
- (with-tramp-connection-property nil "current-context"
- (with-temp-buffer
- (when (zerop
- (tramp-call-process
- vec tramp-kubernetes-program nil t nil
- "config" "current-context"))
- (goto-char (point-min))
- (buffer-substring (point) (line-end-position)))))))
+ (tramp-skeleton-kubernetes-vector vec
+ (with-tramp-file-property
+ vec (concat "/" tramp-kubernetes-method ":") "current-context"
+ (with-temp-buffer
+ (when (zerop
+ (process-file
+ tramp-kubernetes-program nil t nil
+ "config" "current-context"))
+ (goto-char (point-min))
+ (buffer-substring (point) (line-end-position))))))))
(defun tramp-kubernetes--current-context-data (vec)
"Return Kubernetes current context data as JSON string."
(when-let ((current-context (tramp-kubernetes--current-context vec)))
- (with-temp-buffer
- (when (zerop
- (tramp-call-process
- vec tramp-kubernetes-program nil t nil
- "config" "view" "-o"
- (format
- "jsonpath='{.contexts[?(@.name == \"%s\")]}'" current-context)))
- (buffer-string)))))
+ (tramp-skeleton-kubernetes-vector vec
+ (with-temp-buffer
+ (when (zerop
+ (process-file
+ tramp-kubernetes-program nil t nil
+ "config" "view" "-o"
+ (format
+ "jsonpath='{.contexts[?(@.name == \"%s\")]}'" current-context)))
+ (buffer-string))))))
;;;###tramp-autoload
(defun tramp-kubernetes--context-namespace (vec)
@@ -266,49 +314,48 @@ Obey `tramp-kubernetes-context'"
" "))
;;;###tramp-autoload
-(defun tramp-toolbox--completion-function (&rest _args)
+(defun tramp-toolbox--completion-function (method)
"List Toolbox containers available for connection.
This function is used by `tramp-set-completion-function', please
see its function help for a description of the format."
- (when-let ((default-directory tramp-compat-temporary-file-directory)
- (raw-list (shell-command-to-string
- (concat tramp-toolbox-program " list -c")))
- ;; Ignore header line.
- (lines (cdr (split-string raw-list "\n" 'omit)))
- (names (mapcar
- (lambda (line)
- (when (string-match
- (rx bol (1+ (not space))
- (1+ space) (group (1+ (not space))) space)
- line)
- (match-string 1 line)))
- lines)))
- (mapcar (lambda (name) (list nil name)) (delq nil names))))
+ (tramp-skeleton-completion-function method
+ (when-let ((raw-list (shell-command-to-string (concat program " list -c")))
+ ;; Ignore header line.
+ (lines (cdr (split-string raw-list "\n" 'omit)))
+ (names (mapcar
+ (lambda (line)
+ (when (string-match
+ (rx bol (1+ (not space))
+ (1+ space) (group (1+ (not space))) space)
+ line)
+ (match-string 1 line)))
+ lines)))
+ (mapcar (lambda (name) (list nil name)) (delq nil names)))))
;;;###tramp-autoload
-(defun tramp-flatpak--completion-function (&rest _args)
+(defun tramp-flatpak--completion-function (method)
"List Flatpak sandboxes available for connection.
It returns application IDs or, in case there is no application
ID, instance IDs.
This function is used by `tramp-set-completion-function', please
see its function help for a description of the format."
- (when-let ((default-directory tramp-compat-temporary-file-directory)
- (raw-list
- (shell-command-to-string
- (concat tramp-flatpak-program
- " ps --columns=instance,application")))
- (lines (split-string raw-list "\n" 'omit))
- (names (mapcar
- (lambda (line)
- (when (string-match
- (rx bol (* space) (group (+ (not space)))
- (? (+ space) (group (+ (not space)))) eol)
- line)
- (or (match-string 2 line) (match-string 1 line))))
- lines)))
- (mapcar (lambda (name) (list nil name)) (delq nil names))))
+ (tramp-skeleton-completion-function method
+ (when-let ((raw-list
+ (shell-command-to-string
+ ;; Ignore header line.
+ (concat program " ps --columns=instance,application | cat -")))
+ (lines (split-string raw-list "\n" 'omit))
+ (names (mapcar
+ (lambda (line)
+ (when (string-match
+ (rx bol (* space) (group (+ (not space)))
+ (? (+ space) (group (+ (not space)))) eol)
+ line)
+ (or (match-string 2 line) (match-string 1 line))))
+ lines)))
+ (mapcar (lambda (name) (list nil name)) (delq nil names)))))
;;;###tramp-autoload
(defvar tramp-default-remote-shell) ;; Silence byte compiler.
@@ -382,25 +429,29 @@ see its function help for a description of the format."
(tramp-set-completion-function
tramp-docker-method
- `((tramp-container--completion-function
- ,(executable-find tramp-docker-program))))
+ `((tramp-container--completion-function ,tramp-docker-method)))
(tramp-set-completion-function
tramp-podman-method
- `((tramp-container--completion-function
- ,(executable-find tramp-podman-program))))
+ `((tramp-container--completion-function ,tramp-podman-method)))
(tramp-set-completion-function
tramp-kubernetes-method
- '((tramp-kubernetes--completion-function "")))
+ `((tramp-kubernetes--completion-function ,tramp-kubernetes-method)))
(tramp-set-completion-function
tramp-toolbox-method
- '((tramp-toolbox--completion-function "")))
+ `((tramp-toolbox--completion-function ,tramp-toolbox-method)))
(tramp-set-completion-function
tramp-flatpak-method
- '((tramp-flatpak--completion-function "")))
+ `((tramp-flatpak--completion-function ,tramp-flatpak-method)))
+
+ (add-to-list 'tramp-completion-multi-hop-methods tramp-docker-method)
+ (add-to-list 'tramp-completion-multi-hop-methods tramp-podman-method)
+ (add-to-list 'tramp-completion-multi-hop-methods tramp-kubernetes-method)
+ (add-to-list 'tramp-completion-multi-hop-methods tramp-toolbox-method)
+ (add-to-list 'tramp-completion-multi-hop-methods tramp-flatpak-method)
;; Default connection-local variables for Tramp.
@@ -410,7 +461,8 @@ see its function help for a description of the format."
(tramp-extra-expand-args
. (?a (tramp-kubernetes--container (car tramp-current-connection))
?h (tramp-kubernetes--pod (car tramp-current-connection))
- ?x (tramp-kubernetes--context-namespace (car tramp-current-connection)))))
+ ?x (tramp-kubernetes--context-namespace
+ (car tramp-current-connection)))))
"Default connection-local variables for remote kubernetes connections.")
(connection-local-set-profile-variables
diff --git a/lisp/net/tramp-crypt.el b/lisp/net/tramp-crypt.el
index 79eafc5c12e..a7af64bff5c 100644
--- a/lisp/net/tramp-crypt.el
+++ b/lisp/net/tramp-crypt.el
@@ -1,6 +1,6 @@
;;; tramp-crypt.el --- Tramp crypt utilities -*- lexical-binding:t -*-
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
;; Author: Michael Albinus <michael.albinus@gmx.de>
;; Keywords: comm, processes
@@ -148,6 +148,8 @@ If NAME doesn't belong to an encrypted remote directory, return nil."
(and tramp-crypt-enabled (stringp name)
(not (file-name-quoted-p name))
(not (string-suffix-p tramp-crypt-encfs-config name))
+ ;; No lock file name.
+ (not (string-prefix-p ".#" (file-name-nondirectory name)))
(dolist (dir tramp-crypt-directories)
(and (string-prefix-p
dir (file-name-as-directory (expand-file-name name)))
@@ -157,7 +159,7 @@ If NAME doesn't belong to an encrypted remote directory, return nil."
;; New handlers should be added here.
;;;###tramp-autoload
(defconst tramp-crypt-file-name-handler-alist
- '(;; `abbreviate-file-name' performed by default handler.
+ '((abbreviate-file-name . identity)
(access-file . tramp-crypt-handle-access-file)
(add-name-to-file . tramp-handle-add-name-to-file)
;; `byte-compiler-base-file-name' performed by default handler.
@@ -492,7 +494,7 @@ See `tramp-crypt-do-encrypt-or-decrypt-file'."
;;;###tramp-autoload
(defun tramp-crypt-add-directory (name)
- "Mark remote directory NAME for encryption.
+ "Mark expanded remote directory NAME for encryption.
Files in that directory and all subdirectories will be encrypted
before copying to, and decrypted after copying from that
directory. File names will be also encrypted."
@@ -516,7 +518,7 @@ directory. File names will be also encrypted."
#'tramp-crypt-command-completion-p)
(defun tramp-crypt-remove-directory (name)
- "Unmark remote directory NAME for encryption.
+ "Unmark expanded remote directory NAME for encryption.
Existing files in that directory and its subdirectories will be
kept in their encrypted form."
;; (declare (completion tramp-crypt-command-completion-p))
@@ -739,7 +741,7 @@ absolute file names."
(defun tramp-crypt-handle-file-name-all-completions (filename directory)
"Like `file-name-all-completions' for Tramp files."
- (ignore-error file-missing
+ (tramp-skeleton-file-name-all-completions filename directory
(all-completions
filename
(let* (completion-regexp-list
@@ -853,6 +855,23 @@ WILDCARD is not supported."
(tramp-compat-funcall
'unlock-file (tramp-crypt-encrypt-file-name filename))))
+(defun tramp-crypt-cleanup-connection (vec)
+ "Cleanup crypt resources determined by VEC."
+ (let ((tramp-cleanup-connection-hook
+ (remove
+ #'tramp-crypt-cleanup-connection tramp-cleanup-connection-hook))
+ (tramp-crypt-enabled t))
+ (dolist (dir tramp-crypt-directories)
+ (when (tramp-file-name-equal-p vec (tramp-dissect-file-name dir))
+ (tramp-cleanup-connection (tramp-crypt-dissect-file-name dir))))))
+
+;; Add cleanup hooks.
+(add-hook 'tramp-cleanup-connection-hook #'tramp-crypt-cleanup-connection)
+(add-hook 'tramp-crypt-unload-hook
+ (lambda ()
+ (remove-hook 'tramp-cleanup-connection-hook
+ #'tramp-crypt-cleanup-connection)))
+
(with-eval-after-load 'bookmark
(add-hook 'bookmark-inhibit-context-functions
#'tramp-crypt-file-name-p)
diff --git a/lisp/net/tramp-ftp.el b/lisp/net/tramp-ftp.el
index 1712c00b0a0..28ef8c67777 100644
--- a/lisp/net/tramp-ftp.el
+++ b/lisp/net/tramp-ftp.el
@@ -1,6 +1,6 @@
;;; tramp-ftp.el --- Tramp convenience functions for Ange-FTP -*- lexical-binding:t -*-
-;; Copyright (C) 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2024 Free Software Foundation, Inc.
;; Author: Michael Albinus <michael.albinus@gmx.de>
;; Keywords: comm, processes
diff --git a/lisp/net/tramp-fuse.el b/lisp/net/tramp-fuse.el
index aadc64666a5..3d42948043c 100644
--- a/lisp/net/tramp-fuse.el
+++ b/lisp/net/tramp-fuse.el
@@ -1,6 +1,6 @@
;;; tramp-fuse.el --- Tramp access functions for FUSE mounts -*- lexical-binding:t -*-
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
;; Author: Michael Albinus <michael.albinus@gmx.de>
;; Keywords: comm, processes
@@ -102,22 +102,12 @@
(defun tramp-fuse-handle-file-name-all-completions (filename directory)
"Like `file-name-all-completions' for Tramp files."
- (tramp-fuse-remove-hidden-files
- (ignore-error file-missing
+ (tramp-skeleton-file-name-all-completions filename directory
+ (tramp-fuse-remove-hidden-files
(all-completions
filename
- (delete-dups
- (append
- (file-name-all-completions
- filename (tramp-fuse-local-file-name directory))
- ;; Some storage systems do not return "." and "..".
- (let (result)
- (dolist (item '(".." ".") result)
- (when (string-prefix-p filename item)
- (catch 'match
- (dolist (elt completion-regexp-list)
- (unless (string-match-p elt item) (throw 'match nil)))
- (setq result (cons (concat item "/") result))))))))))))
+ (file-name-all-completions
+ filename (tramp-fuse-local-file-name directory))))))
;; This function isn't used.
(defun tramp-fuse-handle-insert-directory
diff --git a/lisp/net/tramp-gvfs.el b/lisp/net/tramp-gvfs.el
index 71ef8215ab0..72589e7ce4a 100644
--- a/lisp/net/tramp-gvfs.el
+++ b/lisp/net/tramp-gvfs.el
@@ -1,6 +1,6 @@
;;; tramp-gvfs.el --- Tramp access functions for GVFS daemon -*- lexical-binding:t -*-
-;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
;; Author: Michael Albinus <michael.albinus@gmx.de>
;; Keywords: comm, processes
@@ -980,8 +980,8 @@ or `dbus-call-method-asynchronously'."
(vec bus service path interface)
"Return all properties of INTERFACE.
The call will be traced by Tramp with trace level 6."
- ;; Check, that interface exists at object path. Retrieve properties.
(declare (indent 1) (debug t))
+ ;; Check, that interface exists at object path. Retrieve properties.
`(when (member
,interface
(tramp-dbus-function
@@ -1208,6 +1208,9 @@ file names."
(tramp-run-real-handler #'expand-file-name (list name))
;; Dissect NAME.
(with-parsed-tramp-file-name name nil
+ ;; Tilde expansion shall be possible also for quoted localname.
+ (when (string-prefix-p "~" (file-name-unquote localname))
+ (setq localname (file-name-unquote localname)))
;; If there is a default location, expand tilde.
(when (string-match
(rx bos "~" (group (* (not "/"))) (group (* nonl)) eos) localname)
@@ -1460,13 +1463,13 @@ If FILE-SYSTEM is non-nil, return file system attributes."
(defun tramp-gvfs-handle-file-name-all-completions (filename directory)
"Like `file-name-all-completions' for Tramp files."
- (unless (tramp-compat-string-search "/" filename)
- (ignore-error file-missing
+ (tramp-skeleton-file-name-all-completions filename directory
+ (unless (tramp-compat-string-search "/" filename)
(all-completions
filename
(with-parsed-tramp-file-name (expand-file-name directory) nil
(with-tramp-file-property v localname "file-name-all-completions"
- (let ((result '("./" "../")))
+ (let (result)
;; Get a list of directories and files.
(dolist (item
(tramp-gvfs-get-directory-attributes directory)
@@ -1490,10 +1493,10 @@ If FILE-SYSTEM is non-nil, return file system attributes."
(cond
((and (memq 'change flags) (memq 'attribute-change flags))
'(created changed changes-done-hint moved deleted
- attribute-changed))
+ attribute-changed unmounted))
((memq 'change flags)
- '(created changed changes-done-hint moved deleted))
- ((memq 'attribute-change flags) '(attribute-changed))))
+ '(created changed changes-done-hint moved deleted unmounted))
+ ((memq 'attribute-change flags) '(attribute-changed unmounted))))
(p (apply
#'start-process
"gvfs-monitor" (generate-new-buffer " *gvfs-monitor*")
diff --git a/lisp/net/tramp-integration.el b/lisp/net/tramp-integration.el
index c73c86a9110..c0b60f57e40 100644
--- a/lisp/net/tramp-integration.el
+++ b/lisp/net/tramp-integration.el
@@ -1,6 +1,6 @@
;;; tramp-integration.el --- Tramp integration into other packages -*- lexical-binding:t -*-
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
;; Author: Michael Albinus <michael.albinus@gmx.de>
;; Keywords: comm, processes
@@ -136,7 +136,7 @@ been set up by `rfn-eshadow-setup-minibuffer'."
;; Remove last element of `(exec-path)', which is `exec-directory'.
;; Use `path-separator' as it does eshell.
(setq eshell-path-env
- (if (file-remote-p default-directory)
+ (if (tramp-tramp-file-p default-directory)
(string-join (butlast (exec-path)) path-separator)
(getenv "PATH"))))
@@ -158,7 +158,7 @@ been set up by `rfn-eshadow-setup-minibuffer'."
(defun tramp-recentf-exclude-predicate (name)
"Predicate to exclude a remote file name from recentf.
NAME must be equal to `tramp-current-connection'."
- (when (file-remote-p name)
+ (when (tramp-tramp-file-p name)
(tramp-file-name-equal-p
(tramp-dissect-file-name name) (car tramp-current-connection))))
diff --git a/lisp/net/tramp-message.el b/lisp/net/tramp-message.el
index c91af638449..96071e626a5 100644
--- a/lisp/net/tramp-message.el
+++ b/lisp/net/tramp-message.el
@@ -1,6 +1,6 @@
;;; tramp-message.el --- Tramp messages -*- lexical-binding:t -*-
-;; Copyright (C) 2023 Free Software Foundation, Inc.
+;; Copyright (C) 2023-2024 Free Software Foundation, Inc.
;; Author: Michael Albinus <michael.albinus@gmx.de>
;; Keywords: comm, processes
@@ -236,9 +236,12 @@ ARGUMENTS to actually emit the message (if applicable)."
tramp-trace-functions))
(unless (get elt 'tramp-suppress-trace)
(trace-function-background elt (tramp-trace-buffer-name vec)))))
- ;; Delete debug file.
+ ;; Delete debug file. Announce its further existence.
(when (and tramp-debug-to-file (tramp-get-debug-file-name vec))
- (ignore-errors (delete-file (tramp-get-debug-file-name vec)))))
+ (ignore-errors (delete-file (tramp-get-debug-file-name vec)))
+ (let ((message-log-max t))
+ (message
+ "Tramp debug file is %s" (tramp-get-debug-file-name vec)))))
(unless (bolp)
(insert "\n"))
;; Timestamp.
@@ -301,18 +304,6 @@ applicable)."
(if tramp-debug-command-messages
(max tramp-verbose 6) tramp-verbose)))
(when (<= level tramp-verbose)
- ;; Display only when there is a minimum level, and the
- ;; progress reporter doesn't suppress further messages.
- (when (and (<= level 3) (null tramp-inhibit-progress-reporter))
- (apply #'message
- (concat
- (cond
- ((= level 0) "")
- ((= level 1) "")
- ((= level 2) "Warning: ")
- (t "Tramp: "))
- fmt-string)
- arguments))
;; Log only when there is a minimum level.
(when (>= tramp-verbose 4)
(let ((tramp-verbose 0))
@@ -328,16 +319,29 @@ applicable)."
(process-buffer vec-or-proc)
(tramp-get-connection-buffer
vec-or-proc 'dont-create))))))))
- ;; Translate proc to vec.
+ ;; Translate proc to vec. Handle nil vec.
(when (processp vec-or-proc)
- (setq vec-or-proc (process-get vec-or-proc 'tramp-vector))))
+ (setq vec-or-proc (process-get vec-or-proc 'tramp-vector)))
+ (setq vec-or-proc (tramp-file-name-unify vec-or-proc)))
;; Do it.
(when (and (tramp-file-name-p vec-or-proc)
(or (null tramp-debug-command-messages) (= level 6)))
(apply #'tramp-debug-message
vec-or-proc
(concat (format "(%d) # " level) fmt-string)
- arguments)))))))
+ arguments)))
+ ;; Display only when there is a minimum level, and the
+ ;; progress reporter doesn't suppress further messages.
+ (when (and (<= level 3) (null tramp-inhibit-progress-reporter))
+ (apply #'message
+ (concat
+ (cond
+ ((= level 0) "")
+ ((= level 1) "")
+ ((= level 2) "Warning: ")
+ (t "Tramp: "))
+ fmt-string)
+ arguments))))))
;; We cannot use the `declare' form for `tramp-suppress-trace' in
;; autoloaded functions, because the tramp-loaddefs.el generation
@@ -351,10 +355,8 @@ forces the backtrace even if `tramp-verbose' is less than 10.
This function is meant for debugging purposes."
(let ((tramp-verbose (if force 10 tramp-verbose)))
(when (>= tramp-verbose 10)
- (if vec-or-proc
- (tramp-message
- vec-or-proc 10 "\n%s" (with-output-to-string (backtrace)))
- (with-output-to-temp-buffer "*debug tramp*" (backtrace))))))
+ (tramp-message
+ vec-or-proc 10 "\n%s" (with-output-to-string (backtrace))))))
(defsubst tramp-error (vec-or-proc signal fmt-string &rest arguments)
"Emit an error.
@@ -370,13 +372,12 @@ FMT-STRING and ARGUMENTS."
;; character, as in smb domain spec.
(setq arguments (list fmt-string)
fmt-string "%s"))
- (when vec-or-proc
- (tramp-message
- vec-or-proc 1 "%s"
- (error-message-string
- (list signal
- (get signal 'error-message)
- (apply #'format-message fmt-string arguments)))))
+ (tramp-message
+ vec-or-proc 1 "%s"
+ (error-message-string
+ (list signal
+ (get signal 'error-message)
+ (apply #'format-message fmt-string arguments))))
(signal signal (list (substring-no-properties
(apply #'format-message fmt-string arguments))))))
@@ -514,7 +515,7 @@ This shouldn't be changed globally, but let-bind where needed.")
Bound in `tramp-*-file-name-handler' functions.")
(defun tramp-debug-message-buttonize (position)
- "Buttonize function in current buffer, at next line starting after POSTION."
+ "Buttonize function in current buffer, at next line starting after POSITION."
(declare (tramp-suppress-trace t))
(save-excursion
(goto-char position)
diff --git a/lisp/net/tramp-rclone.el b/lisp/net/tramp-rclone.el
index c2b84845f68..ced3c1b5aa8 100644
--- a/lisp/net/tramp-rclone.el
+++ b/lisp/net/tramp-rclone.el
@@ -1,6 +1,6 @@
;;; tramp-rclone.el --- Tramp access functions to cloud storages -*- lexical-binding:t -*-
-;; Copyright (C) 2018-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2018-2024 Free Software Foundation, Inc.
;; Author: Michael Albinus <michael.albinus@gmx.de>
;; Keywords: comm, processes
diff --git a/lisp/net/tramp-sh.el b/lisp/net/tramp-sh.el
index 0599f89655c..6489f473634 100644
--- a/lisp/net/tramp-sh.el
+++ b/lisp/net/tramp-sh.el
@@ -1,6 +1,6 @@
;;; tramp-sh.el --- Tramp access functions for (s)sh-like connections -*- lexical-binding:t -*-
-;; Copyright (C) 1998-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-2024 Free Software Foundation, Inc.
;; (copyright statements below in code to be updated with the above notice)
@@ -31,8 +31,7 @@
;;; Code:
-(eval-when-compile (require 'cl-lib))
-(require 'cl-seq)
+(require 'cl-lib)
(require 'tramp)
;; `dired-*' declarations can be removed, starting with Emacs 29.1.
@@ -522,8 +521,8 @@ The string is used in `tramp-methods'.")
(tramp-set-completion-function "fcp" tramp-completion-function-alist-ssh))
(defcustom tramp-sh-extra-args
- `((,(rx "/bash" eos) . "-noediting -norc -noprofile")
- (,(rx "/zsh" eos) . "-f +Z -V"))
+ `((,(rx (| bos "/") "bash" eos) . "-noediting -norc -noprofile")
+ (,(rx (| bos "/") "zsh" eos) . "-f +Z -V"))
"Alist specifying extra arguments to pass to the remote shell.
Entries are (REGEXP . ARGS) where REGEXP is a regular expression
matching the shell file name and ARGS is a string specifying the
@@ -534,12 +533,13 @@ This variable is only used when Tramp needs to start up another shell
for tilde expansion. The extra arguments should typically prevent the
shell from reading its init file."
:group 'tramp
- :version "27.1"
+ :version "30.1"
:type '(alist :key-type regexp :value-type string))
(defconst tramp-actions-before-shell
'((tramp-login-prompt-regexp tramp-action-login)
(tramp-password-prompt-regexp tramp-action-password)
+ (tramp-otp-password-prompt-regexp tramp-action-otp-password)
(tramp-wrong-passwd-regexp tramp-action-permission-denied)
(shell-prompt-pattern tramp-action-succeed)
(tramp-shell-prompt-pattern tramp-action-succeed)
@@ -563,6 +563,7 @@ corresponding PATTERN matches, the ACTION function is called.")
(defconst tramp-actions-copy-out-of-band
'((tramp-password-prompt-regexp tramp-action-password)
+ (tramp-otp-password-prompt-regexp tramp-action-otp-password)
(tramp-wrong-passwd-regexp tramp-action-permission-denied)
(tramp-copy-failed-regexp tramp-action-permission-denied)
(tramp-security-key-confirm-regexp tramp-action-show-and-confirm-message)
@@ -634,7 +635,10 @@ characters need to be doubled.")
(defconst tramp-perl-file-name-all-completions
"%p -e '
-($dir = $ARGV[0]) =~ s#/+$##;
+$dir = $ARGV[0];
+if ($dir ne \"/\") {
+ $dir =~ s#/+$##;
+}
opendir(d, $dir) || die(\"$dir: $!\\nfail\\n\");
@files = readdir(d); closedir(d);
print \"(\\n\";
@@ -740,6 +744,13 @@ on the remote file system, including SELinux context.
Format specifiers are replaced by `tramp-expand-script', percent
characters need to be doubled.")
+(defconst tramp-ls-file-attributes
+ "%s -ild %s \"$1\" || return\n%s -lnd%s %s \"$1\""
+ "Shell function to produce output suitable for use with `file-attributes'
+on the remote file system.
+Format specifiers are replaced by `tramp-expand-script', percent
+characters need to be doubled.")
+
(defconst tramp-perl-directory-files-and-attributes
"%p -e '
chdir($ARGV[0]) or printf(\"\\\"Cannot change to $ARGV[0]: $''!''\\\"\\n\"), exit();
@@ -1228,7 +1239,7 @@ Operations not mentioned here will be handled by the normal Emacs functions.")
(with-current-buffer (tramp-get-connection-buffer v)
(goto-char (point-min))
(tramp-set-file-property v localname "file-symlink-marker" (read (current-buffer)))
- ;; We cannote call `read', the file name isn't quoted.
+ ;; We cannot call `read', the file name isn't quoted.
(forward-line)
(buffer-substring (point) (line-end-position))))
@@ -1279,6 +1290,9 @@ Operations not mentioned here will be handled by the normal Emacs functions.")
(defconst tramp-sunos-unames (rx (| "SunOS 5.10" "SunOS 5.11"))
"Regexp to determine remote SunOS.")
+(defconst tramp-bsd-unames (rx (| "BSD" "DragonFly" "Darwin"))
+ "Regexp to determine remote *BSD and macOS.")
+
(defun tramp-sh--quoting-style-options (vec)
"Quoting style options to be used for VEC."
(or
@@ -1292,43 +1306,25 @@ Operations not mentioned here will be handled by the normal Emacs functions.")
(defun tramp-do-file-attributes-with-ls (vec localname)
"Implement `file-attributes' for Tramp files using the ls(1) command."
- (let (symlinkp dirp
+ (tramp-message vec 5 "file attributes with ls: %s" localname)
+ (let ((tramp-ls-file-attributes
+ (format tramp-ls-file-attributes
+ (tramp-get-ls-command vec)
+ ;; On systems which have no quoting style, file
+ ;; names with special characters could fail.
+ (tramp-sh--quoting-style-options vec)
+ (tramp-get-ls-command vec)
+ (if (tramp-remote-selinux-p vec) "Z" "")
+ (tramp-sh--quoting-style-options vec)))
+ symlinkp dirp
res-inode res-filemodes res-numlinks
res-uid-string res-gid-string res-uid-integer res-gid-integer
res-size res-symlink-target res-context)
- (tramp-message vec 5 "file attributes with ls: %s" localname)
- ;; We cannot send both commands combined, it could exceed NAME_MAX
- ;; or PATH_MAX. Happened on macOS, for example.
+ (tramp-maybe-send-script
+ vec tramp-ls-file-attributes "tramp_ls_file_attributes")
(when (tramp-send-command-and-check
- vec
- (format "cd %s && (%s %s || %s -h %s)"
- (tramp-shell-quote-argument
- (tramp-run-real-handler
- #'file-name-directory (list localname)))
- (tramp-get-file-exists-command vec)
- (if (string-empty-p (file-name-nondirectory localname))
- "."
- (tramp-shell-quote-argument
- (file-name-nondirectory localname)))
- (tramp-get-test-command vec)
- (if (string-empty-p (file-name-nondirectory localname))
- "."
- (tramp-shell-quote-argument
- (file-name-nondirectory localname)))))
- (tramp-send-command
- vec
- (format "%s -ild %s %s; %s -lnd%s %s %s"
- (tramp-get-ls-command vec)
- ;; On systems which have no quoting style, file names
- ;; with special characters could fail.
- (tramp-sh--quoting-style-options vec)
- (tramp-shell-quote-argument localname)
- (tramp-get-ls-command vec)
- (if (tramp-remote-selinux-p vec) "Z" "")
- ;; On systems which have no quoting style, file names
- ;; with special characters could fail.
- (tramp-sh--quoting-style-options vec)
- (tramp-shell-quote-argument localname)))
+ vec (format "tramp_ls_file_attributes %s"
+ (tramp-shell-quote-argument localname)))
;; Parse `ls -l' output ...
(with-current-buffer (tramp-get-buffer vec)
(when (> (buffer-size) 0)
@@ -1795,7 +1791,7 @@ ID-FORMAT valid values are `string' and `integer'."
;; On BSD-derived systems files always inherit the
;; parent directory's group, so skip the group-gid
;; test.
- (tramp-check-remote-uname v (rx (| "BSD" "DragonFly" "Darwin")))
+ (tramp-check-remote-uname v tramp-bsd-unames)
(= (file-attribute-group-id attributes)
(tramp-get-remote-gid v 'integer)))))))))
@@ -1852,60 +1848,60 @@ ID-FORMAT valid values are `string' and `integer'."
;; files.
(defun tramp-sh-handle-file-name-all-completions (filename directory)
"Like `file-name-all-completions' for Tramp files."
- (with-parsed-tramp-file-name (expand-file-name directory) nil
- (when (and (not (tramp-compat-string-search "/" filename))
- (tramp-connectable-p v))
- (unless (tramp-compat-string-search "/" filename)
- (ignore-error file-missing
- (all-completions
- filename
- (with-tramp-file-property v localname "file-name-all-completions"
- (let (result)
- ;; Get a list of directories and files, including
- ;; reliably tagging the directories with a trailing "/".
- ;; Because I rock. --daniel@danann.net
- (if (tramp-get-remote-perl v)
- (progn
- (tramp-maybe-send-script
- v tramp-perl-file-name-all-completions
- "tramp_perl_file_name_all_completions")
- (setq result
- (tramp-send-command-and-read
- v (format "tramp_perl_file_name_all_completions %s"
- (tramp-shell-quote-argument localname))
- 'noerror))
- ;; Cached values.
- (dolist (elt result)
- (tramp-set-file-property
- v (cadr elt) "file-directory-p" (nth 2 elt))
- (tramp-set-file-property
- v (cadr elt) "file-exists-p" (nth 3 elt))
- (tramp-set-file-property
- v (cadr elt) "file-readable-p" (nth 4 elt)))
- ;; Result.
- (mapcar #'car result))
-
- ;; Do it with ls.
- (when (tramp-send-command-and-check
- v (format (concat
- "cd %s 2>&1 && %s -a 2>%s"
- " | while IFS= read f; do"
- " if %s -d \"$f\" 2>%s;"
- " then echo \"$f/\"; else echo \"$f\"; fi;"
- " done")
- (tramp-shell-quote-argument localname)
- (tramp-get-ls-command v)
- (tramp-get-remote-null-device v)
- (tramp-get-test-command v)
- (tramp-get-remote-null-device v)))
-
- ;; Now grab the output.
- (with-current-buffer (tramp-get-buffer v)
- (goto-char (point-max))
- (while (zerop (forward-line -1))
- (push
- (buffer-substring (point) (line-end-position)) result)))
- result))))))))))
+ (tramp-skeleton-file-name-all-completions filename directory
+ (with-parsed-tramp-file-name (expand-file-name directory) nil
+ (when (and (not (tramp-compat-string-search "/" filename))
+ (tramp-connectable-p v))
+ (unless (tramp-compat-string-search "/" filename)
+ (all-completions
+ filename
+ (with-tramp-file-property v localname "file-name-all-completions"
+ (let (result)
+ ;; Get a list of directories and files, including
+ ;; reliably tagging the directories with a trailing "/".
+ ;; Because I rock. --daniel@danann.net
+ (if (tramp-get-remote-perl v)
+ (progn
+ (tramp-maybe-send-script
+ v tramp-perl-file-name-all-completions
+ "tramp_perl_file_name_all_completions")
+ (setq result
+ (tramp-send-command-and-read
+ v (format "tramp_perl_file_name_all_completions %s"
+ (tramp-shell-quote-argument localname))
+ 'noerror))
+ ;; Cached values.
+ (dolist (elt result)
+ (tramp-set-file-property
+ v (cadr elt) "file-directory-p" (nth 2 elt))
+ (tramp-set-file-property
+ v (cadr elt) "file-exists-p" (nth 3 elt))
+ (tramp-set-file-property
+ v (cadr elt) "file-readable-p" (nth 4 elt)))
+ ;; Result.
+ (mapcar #'car result))
+
+ ;; Do it with ls.
+ (when (tramp-send-command-and-check
+ v (format (concat
+ "cd %s 2>&1 && %s -a 2>%s"
+ " | while IFS= read f; do"
+ " if %s -d \"$f\" 2>%s;"
+ " then echo \"$f/\"; else echo \"$f\"; fi;"
+ " done")
+ (tramp-shell-quote-argument localname)
+ (tramp-get-ls-command v)
+ (tramp-get-remote-null-device v)
+ (tramp-get-test-command v)
+ (tramp-get-remote-null-device v)))
+
+ ;; Now grab the output.
+ (with-current-buffer (tramp-get-buffer v)
+ (goto-char (point-max))
+ (while (zerop (forward-line -1))
+ (push
+ (buffer-substring (point) (line-end-position)) result)))
+ result))))))))))
;; cp, mv and ln
@@ -2527,7 +2523,7 @@ The method used must be an out-of-band method."
(tramp-get-connection-name v)
(tramp-get-connection-buffer v)
copy-program copy-args)))
- ;; This is neded for ssh or PuTTY based processes, and
+ ;; This is needed for ssh or PuTTY based processes, and
;; only if the respective options are set. Perhaps,
;; the setting could be more fine-grained.
;; (process-put p 'tramp-shared-socket t)
@@ -2640,21 +2636,23 @@ The method used must be an out-of-band method."
(defun tramp-sh-handle-insert-directory
(filename switches &optional wildcard full-directory-p)
"Like `insert-directory' for Tramp files."
- (unless switches (setq switches ""))
- ;; Check, whether directory is accessible.
- (unless wildcard
- (access-file filename "Reading directory"))
- (with-parsed-tramp-file-name (expand-file-name filename) nil
- (if (and (featurep 'ls-lisp)
- (not ls-lisp-use-insert-directory-program))
- (tramp-handle-insert-directory
- filename switches wildcard full-directory-p)
- (when (stringp switches)
- (setq switches (split-string switches)))
- (setq switches
- (append switches (split-string (tramp-sh--quoting-style-options v))))
- (unless (tramp-get-ls-command-with v "--dired")
- (setq switches (delete "-N" (delete "--dired" switches))))
+ (if (and (featurep 'ls-lisp)
+ (not ls-lisp-use-insert-directory-program))
+ (tramp-handle-insert-directory
+ filename switches wildcard full-directory-p)
+ (unless switches (setq switches ""))
+ ;; Check, whether directory is accessible.
+ (unless wildcard
+ (access-file filename "Reading directory"))
+ (with-parsed-tramp-file-name (expand-file-name filename) nil
+ (let ((dired (tramp-get-ls-command-with v "--dired")))
+ (when (stringp switches)
+ (setq switches (split-string switches)))
+ (setq switches
+ (append switches (split-string (tramp-sh--quoting-style-options v))
+ (when dired `(,dired))))
+ (unless dired
+ (setq switches (delete "-N" (delete "--dired" switches)))))
(when wildcard
(setq wildcard (tramp-run-real-handler
#'file-name-nondirectory (list localname)))
@@ -2662,7 +2660,8 @@ The method used must be an out-of-band method."
#'file-name-directory (list localname))))
(unless (or full-directory-p (member "-d" switches))
(setq switches (append switches '("-d"))))
- (setq switches (mapconcat #'tramp-shell-quote-argument switches " "))
+ (setq switches (delete-dups switches)
+ switches (mapconcat #'tramp-shell-quote-argument switches " "))
(when wildcard
(setq switches (concat switches " " wildcard)))
(tramp-message
@@ -2831,9 +2830,13 @@ the result will be a local, non-Tramp, file name."
(with-parsed-tramp-file-name name nil
;; If connection is not established yet, run the real handler.
(if (not (tramp-connectable-p v))
- (tramp-run-real-handler #'expand-file-name (list name))
+ (tramp-drop-volume-letter
+ (tramp-run-real-handler #'expand-file-name (list name)))
(unless (tramp-run-real-handler #'file-name-absolute-p (list localname))
(setq localname (concat "~/" localname)))
+ ;; Tilde expansion shall be possible also for quoted localname.
+ (when (string-prefix-p "~" (file-name-unquote localname))
+ (setq localname (file-name-unquote localname)))
;; Tilde expansion if necessary. This needs a shell which
;; groks tilde expansion! The function `tramp-find-shell' is
;; supposed to find such a shell on the remote host. Please
@@ -2874,7 +2877,16 @@ the result will be a local, non-Tramp, file name."
(tramp-run-real-handler
#'expand-file-name (list localname))))))))))
-;;; Remote commands:
+;;; Remote processes:
+
+(defcustom tramp-pipe-stty-settings "-icanon min 1 time 0"
+ "How to prevent blocking read in pipeline processes.
+This is used in `make-process' with `connection-type' `pipe'."
+ :group 'tramp
+ :version "29.3"
+ :type '(choice (const :tag "Use size limit" "-icanon min 1 time 0")
+ (const :tag "Use timeout" "-icanon min 0 time 1")
+ string))
;; We use BUFFER also as connection buffer during setup. Because of
;; this, its original contents must be saved, and restored once
@@ -3086,12 +3098,21 @@ implementation will be used."
;; otherwise strings larger than 4096
;; bytes, sent by the process, could
;; block, see termios(3) and Bug#61341.
+ ;; In order to prevent blocking read
+ ;; from pipe processes, "stty -icanon"
+ ;; is used. By default, it expects at
+ ;; least one character to read. When a
+ ;; process does not read from stdin,
+ ;; like magit, it should set a timeout
+ ;; instead. See`tramp-pipe-stty-settings'.
+ ;; (Bug#62093)
;; FIXME: Shall we rather use "stty raw"?
- (if (tramp-check-remote-uname v "Darwin")
- (tramp-send-command
- v "stty -icanon min 1 time 0")
- (tramp-send-command
- v "stty -icrnl -icanon min 1 time 0")))
+ (tramp-send-command
+ v (format
+ "stty %s %s"
+ (if (tramp-check-remote-uname v "Darwin")
+ "" "-icrnl")
+ tramp-pipe-stty-settings)))
;; `tramp-maybe-open-connection' and
;; `tramp-send-command-and-read' could
;; have trashed the connection buffer.
@@ -3801,11 +3822,12 @@ Fall back to normal file name handler if no Tramp handler exists."
(cond
((and (memq 'change flags) (memq 'attribute-change flags))
(concat "create,modify,move,moved_from,moved_to,move_self,"
- "delete,delete_self,attrib,ignored"))
+ "delete,delete_self,attrib"))
((memq 'change flags)
(concat "create,modify,move,moved_from,moved_to,move_self,"
- "delete,delete_self,ignored"))
- ((memq 'attribute-change flags) "attrib,ignored"))
+ "delete,delete_self"))
+ ((memq 'attribute-change flags) "attrib"))
+ events (concat events ",ignored,unmount")
;; "-P" has been added to version 3.21, so we cannot assume it yet.
sequence `(,command "-mq" "-e" ,events ,localname)
;; Make events a list of symbols.
@@ -3820,10 +3842,10 @@ Fall back to normal file name handler if no Tramp handler exists."
(cond
((and (memq 'change flags) (memq 'attribute-change flags))
'(created changed changes-done-hint moved deleted
- attribute-changed))
+ attribute-changed unmounted))
((memq 'change flags)
- '(created changed changes-done-hint moved deleted))
- ((memq 'attribute-change flags) '(attribute-changed)))
+ '(created changed changes-done-hint moved deleted unmounted))
+ ((memq 'attribute-change flags) '(attribute-changed unmounted)))
sequence `(,command "monitor" ,localname)))
;; None.
(t (tramp-error
@@ -3843,7 +3865,7 @@ Fall back to normal file name handler if no Tramp handler exists."
v 'file-notify-error
"`%s' failed to start on remote host"
(string-join sequence " "))
- ;; This is neded for ssh or PuTTY based processes, and only if
+ ;; This is needed for ssh or PuTTY based processes, and only if
;; the respective options are set. Perhaps, the setting could
;; be more fine-grained.
;; (process-put p 'tramp-shared-socket t)
@@ -4180,13 +4202,7 @@ variable PATH."
(format
"PATH=%s && export PATH"
(string-join (tramp-get-remote-path vec) ":")))
- (pipe-buf
- (with-tramp-connection-property vec "pipe-buf"
- (tramp-send-command-and-read
- vec
- (format "getconf PIPE_BUF / 2>%s || echo 4096"
- (tramp-get-remote-null-device vec))
- 'noerror)))
+ (pipe-buf (tramp-get-remote-pipe-buf vec))
tmpfile chunk chunksize)
(tramp-message vec 5 "Setting $PATH environment variable")
(if (tramp-compat-length< command pipe-buf)
@@ -4424,7 +4440,7 @@ seconds. If not, it produces an error message with the given ERROR-ARGS."
"A function to be called with one argument, VEC.
It should return a string which is used to check, whether the
configuration of the remote host has been changed (which would
-require to flush the cache data). This string is kept as
+require flushing the cache data). This string is kept as
connection property \"config-check-data\".
This variable is intended as connection-local variable.")
@@ -4579,7 +4595,7 @@ process to set up. VEC specifies the connection."
(tramp-send-command vec "set +H" t))
;; Disable tab expansion.
- (if (string-match-p (rx (| "BSD" "DragonFly" "Darwin")) uname)
+ (if (string-match-p tramp-bsd-unames uname)
(tramp-send-command vec "stty tabs" t)
(tramp-send-command vec "stty tab0" t))
@@ -5239,7 +5255,7 @@ connection if a previous connection has died for some reason."
(and tramp-encoding-command-interactive
`(,tramp-encoding-command-interactive)))))))
- ;; This is neded for ssh or PuTTY based processes,
+ ;; This is needed for ssh or PuTTY based processes,
;; and only if the respective options are set.
;; Perhaps, the setting could be more fine-grained.
;; (process-put p 'tramp-shared-socket t)
@@ -5524,7 +5540,7 @@ raises an error."
(unless noerror signal-hook-function)))
(read (current-buffer)))
;; Error handling.
- (when (search-forward-regexp (rx (not blank)) (line-end-position) t)
+ (when (search-forward-regexp (rx (not space)) (line-end-position) t)
(error nil)))
(error (unless noerror
(tramp-error
@@ -5581,6 +5597,7 @@ raises an error."
"Check whether REGEXP matches the connection property \"uname\"."
(string-match-p regexp (tramp-get-connection-property vec "uname" "")))
+;;;###tramp-autoload
(defun tramp-get-remote-path (vec)
"Compile list of remote directories for PATH.
Nonexistent directories are removed from spec."
@@ -5664,6 +5681,27 @@ Nonexistent directories are removed from spec."
(lambda (x) (not (tramp-get-file-property vec x "file-directory-p")))
remote-path))))))
+;; The PIPE_BUF in POSIX [1] can be as low as 512 [2]. Here are the values
+;; on various platforms:
+;; - 512 on macOS, FreeBSD, NetBSD, OpenBSD, MirBSD, native Windows.
+;; - 4 KiB on Linux, OSF/1, Cygwin, Haiku.
+;; - 5 KiB on Solaris.
+;; - 8 KiB on HP-UX, Plan9.
+;; - 10 KiB on IRIX.
+;; - 32 KiB on AIX, Minix.
+;; [1] https://pubs.opengroup.org/onlinepubs/9699919799/functions/write.html
+;; [2] https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/limits.h.html
+;; See Bug#65324.
+;;;###tramp-autoload
+(defun tramp-get-remote-pipe-buf (vec)
+ "Return PIPE_BUF config from the remote side."
+ (with-tramp-connection-property vec "pipe-buf"
+ (tramp-send-command-and-read
+ vec
+ (format "getconf PIPE_BUF / 2>%s || echo 4096"
+ (tramp-get-remote-null-device vec))
+ 'noerror)))
+
(defun tramp-get-remote-locale (vec)
"Determine remote locale, supporting UTF8 if possible."
(with-tramp-connection-property vec "locale"
@@ -5687,7 +5725,10 @@ Nonexistent directories are removed from spec."
(tramp-message vec 5 "Finding a suitable `ls' command")
(or
(catch 'ls-found
- (dolist (cmd '("ls" "gnuls" "gls"))
+ (dolist (cmd
+ ;; Prefer GNU ls on *BSD and macOS.
+ (if (tramp-check-remote-uname vec tramp-bsd-unames)
+ '( "gls" "ls" "gnuls") '("ls" "gnuls" "gls")))
(let ((dl (tramp-get-remote-path vec))
result)
(while (and dl (setq result (tramp-find-executable vec cmd dl t t)))
diff --git a/lisp/net/tramp-smb.el b/lisp/net/tramp-smb.el
index f3f2c40e62c..3616cad2fb3 100644
--- a/lisp/net/tramp-smb.el
+++ b/lisp/net/tramp-smb.el
@@ -1,6 +1,6 @@
;;; tramp-smb.el --- Tramp access functions for SMB servers -*- lexical-binding:t -*-
-;; Copyright (C) 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2024 Free Software Foundation, Inc.
;; Author: Michael Albinus <michael.albinus@gmx.de>
;; Keywords: comm, processes
@@ -618,7 +618,7 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are completely ignored."
;; with `jka-compr-handler', so we cannot trust its result as
;; indication for a remote file name.
(if-let ((tmpfile
- (and (file-remote-p filename) (file-local-copy filename))))
+ (and (tramp-tramp-file-p filename) (file-local-copy filename))))
;; Remote filename.
(condition-case err
(rename-file tmpfile newname ok-if-already-exists)
@@ -722,6 +722,9 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are completely ignored."
(tramp-run-real-handler #'expand-file-name (list name))
;; Dissect NAME.
(with-parsed-tramp-file-name name nil
+ ;; Tilde expansion shall be possible also for quoted localname.
+ (when (string-prefix-p "~" (file-name-unquote localname))
+ (setq localname (file-name-unquote localname)))
;; Tilde expansion if necessary.
(when (string-match
(rx bos "~" (group (* (not "/"))) (group (* nonl)) eos) localname)
@@ -969,20 +972,19 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are completely ignored."
;; files.
(defun tramp-smb-handle-file-name-all-completions (filename directory)
"Like `file-name-all-completions' for Tramp files."
- (ignore-error file-missing
+ (tramp-skeleton-file-name-all-completions filename directory
(all-completions
filename
(when (file-directory-p directory)
(with-parsed-tramp-file-name (expand-file-name directory) nil
(with-tramp-file-property v localname "file-name-all-completions"
- (delete-dups
- (mapcar
- (lambda (x)
- (list
- (if (tramp-compat-string-search "d" (nth 1 x))
- (file-name-as-directory (nth 0 x))
- (nth 0 x))))
- (tramp-smb-get-file-entries directory)))))))))
+ (mapcar
+ (lambda (x)
+ (list
+ (if (tramp-compat-string-search "d" (nth 1 x))
+ (file-name-as-directory (nth 0 x))
+ (nth 0 x))))
+ (tramp-smb-get-file-entries directory))))))))
(defun tramp-smb-handle-file-system-info (filename)
"Like `file-system-info' for Tramp files."
diff --git a/lisp/net/tramp-sshfs.el b/lisp/net/tramp-sshfs.el
index 131f632a0fe..8dad599c7e7 100644
--- a/lisp/net/tramp-sshfs.el
+++ b/lisp/net/tramp-sshfs.el
@@ -1,6 +1,6 @@
;;; tramp-sshfs.el --- Tramp access functions via sshfs -*- lexical-binding:t -*-
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
;; Author: Michael Albinus <michael.albinus@gmx.de>
;; Keywords: comm, processes
@@ -60,7 +60,7 @@
;; These are for remote processes.
(tramp-login-program "ssh")
(tramp-login-args (("-q") ("-l" "%u") ("-p" "%p")
- ("-e" "none") ("-t" "-t")
+ ("-e" "none") ("%a" "%a")
("%h") ("%l")))
(tramp-direct-async t)
(tramp-remote-shell ,tramp-default-remote-shell)
@@ -326,7 +326,7 @@ arguments to pass to the OPERATION."
?h (or (tramp-file-name-host v) "")
?u (or (tramp-file-name-user v) "")
?p (or (tramp-file-name-port v) "")
- ?l command))
+ ?a "-t" ?l command))
;; Synchronize stderr.
(when tmpstderr
diff --git a/lisp/net/tramp-sudoedit.el b/lisp/net/tramp-sudoedit.el
index 3d6e1d92d0b..0c717c4a5aa 100644
--- a/lisp/net/tramp-sudoedit.el
+++ b/lisp/net/tramp-sudoedit.el
@@ -1,6 +1,6 @@
;;; tramp-sudoedit.el --- Functions for accessing under root permissions -*- lexical-binding:t -*-
-;; Copyright (C) 2018-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2018-2024 Free Software Foundation, Inc.
;; Author: Michael Albinus <michael.albinus@gmx.de>
;; Keywords: comm, processes
@@ -23,7 +23,7 @@
;;; Commentary:
-;; The "sudoedit" Tramp method allows to edit a file as a different
+;; The "sudoedit" Tramp method enables editing a file as a different
;; user on the local host. Contrary to the "sudo" method, all magic
;; file name functions are implemented by single "sudo ..." commands.
;; The purpose is to make editing such a file as secure as possible;
@@ -274,8 +274,8 @@ absolute file names."
(not (directory-name-p newname)))
(tramp-error v 'file-error "File is a directory %s" newname))
- (if (or (and (file-remote-p filename) (not t1))
- (and (file-remote-p newname) (not t2)))
+ (if (or (and (tramp-tramp-file-p filename) (not t1))
+ (and (tramp-tramp-file-p newname) (not t2)))
;; We cannot copy or rename directly.
(let ((tmpfile (tramp-compat-make-temp-file filename)))
(if (eq op 'copy)
@@ -296,7 +296,7 @@ absolute file names."
;; When `newname' is local, we must change the ownership to
;; the local user.
- (unless (file-remote-p newname)
+ (unless (tramp-tramp-file-p newname)
(tramp-set-file-uid-gid
(concat (file-remote-p filename) newname)
(tramp-get-local-uid 'integer)
@@ -381,6 +381,9 @@ the result will be a local, non-Tramp, file name."
;; but to the root home directory.
(when (tramp-string-empty-or-nil-p localname)
(setq localname "~"))
+ ;; Tilde expansion shall be possible also for quoted localname.
+ (when (string-prefix-p "~" (file-name-unquote localname))
+ (setq localname (file-name-unquote localname)))
(unless (file-name-absolute-p localname)
(setq localname (format "~%s/%s" user localname)))
(when (string-match
@@ -486,7 +489,7 @@ the result will be a local, non-Tramp, file name."
(defun tramp-sudoedit-handle-file-name-all-completions (filename directory)
"Like `file-name-all-completions' for Tramp files."
- (ignore-error file-missing
+ (tramp-skeleton-file-name-all-completions filename directory
(all-completions
filename
(with-parsed-tramp-file-name (expand-file-name directory) nil
@@ -500,13 +503,11 @@ the result will be a local, non-Tramp, file name."
(if (ignore-errors (file-directory-p (expand-file-name f directory)))
(file-name-as-directory f)
f))
- (delq
- nil
- (mapcar
- (lambda (l) (and (not (string-match-p (rx bol (* blank) eol) l)) l))
- (split-string
- (tramp-get-buffer-string (tramp-get-connection-buffer v))
- "\n" 'omit)))))))))
+ (mapcar
+ (lambda (l) (and (not (string-match-p (rx bol (* blank) eol) l)) l))
+ (split-string
+ (tramp-get-buffer-string (tramp-get-connection-buffer v))
+ "\n" 'omit))))))))
(defun tramp-sudoedit-handle-file-readable-p (filename)
"Like `file-readable-p' for Tramp files."
diff --git a/lisp/net/tramp-uu.el b/lisp/net/tramp-uu.el
index e7527f06e81..025c9d62890 100644
--- a/lisp/net/tramp-uu.el
+++ b/lisp/net/tramp-uu.el
@@ -1,6 +1,6 @@
;;; tramp-uu.el --- uuencode in Lisp -*- lexical-binding:t -*-
-;; Copyright (C) 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2024 Free Software Foundation, Inc.
;; Author: Kai Großjohann <kai.grossjohann@gmx.net>
;; Maintainer: Michael Albinus <michael.albinus@gmx.de>
diff --git a/lisp/net/tramp.el b/lisp/net/tramp.el
index 30602c353b3..2f6b526039f 100644
--- a/lisp/net/tramp.el
+++ b/lisp/net/tramp.el
@@ -1,6 +1,6 @@
;;; tramp.el --- Transparent Remote Access, Multiple Protocol -*- lexical-binding:t -*-
-;; Copyright (C) 1998-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-2024 Free Software Foundation, Inc.
;; Author: Kai Großjohann <kai.grossjohann@gmx.net>
;; Michael Albinus <michael.albinus@gmx.de>
@@ -8,6 +8,9 @@
;; Keywords: comm, processes
;; Package: tramp
+;; This is a GNU ELPA :core package. Avoid functionality that is not
+;; compatible with the version of Emacs recorded in trampver.el.
+
;; This file is part of GNU Emacs.
;; GNU Emacs is free software: you can redistribute it and/or modify
@@ -64,7 +67,11 @@
(declare-function file-notify-rm-watch "filenotify")
(declare-function netrc-parse "netrc")
(defvar auto-save-file-name-transforms)
+(defvar ls-lisp-dirs-first)
+(defvar ls-lisp-emulation)
+(defvar ls-lisp-ignore-case)
(defvar ls-lisp-use-insert-directory-program)
+(defvar ls-lisp-verbosity)
(defvar tramp-prefix-format)
(defvar tramp-prefix-regexp)
(defvar tramp-method-regexp)
@@ -240,9 +247,9 @@ pair of the form (KEY VALUE). The following KEYs are defined:
\"%\" followed by a letter are expanded in the arguments as
follows:
- - \"%h\" is replaced by the host name
- - \"%u\" is replaced by the user name
- - \"%p\" is replaced by the port number
+ - \"%h\" is replaced by the host name.
+ - \"%u\" is replaced by the user name.
+ - \"%p\" is replaced by the port number.
- \"%%\" can be used to obtain a literal percent character.
If a sub-list containing \"%h\", \"%u\" or \"%p\" is
@@ -271,6 +278,8 @@ pair of the form (KEY VALUE). The following KEYs are defined:
- \"%z\" is replaced by the `tramp-scp-direct-remote-copying'
argument if it is supported.
- \"%d\" is replaced by the device detected by `tramp-adb-get-device'.
+ - \"%a\" adds the pseudo-terminal allocation argument \"-t\" in
+ asynchronous processes, if the connection type is not `pipe'.
The existence of `tramp-login-args', combined with the
absence of `tramp-copy-args', is an indication that the
@@ -405,7 +414,7 @@ Another host name is useful only in combination with
;; an external method.
(cond
;; PuTTY is installed. We don't take it, if it is installed on a
- ;; non-windows system, or pscp from the pssh (parallel ssh) package
+ ;; non-Windows system, or pscp from the pssh (parallel ssh) package
;; is found.
((and (eq system-type 'windows-nt) (executable-find "pscp")) "pscp")
;; There is an ssh installation.
@@ -543,14 +552,17 @@ host runs a restricted shell, it shall be added to this list, too."
;;;###tramp-autoload
(defcustom tramp-local-host-regexp
- (rx
- bos
- (| (literal tramp-system-name)
- (| "localhost" "localhost4" "localhost6" "127.0.0.1" "::1"))
- eos)
+ (rx bos
+ (| (literal tramp-system-name)
+ (| "localhost" "127.0.0.1" "::1"
+ ;; Fedora.
+ "localhost4" "localhost6"
+ ;; Ubuntu.
+ "ip6-localhost" "ip6-loopback"))
+ eos)
"Host names which are regarded as local host.
If the local host runs a chrooted environment, set this to nil."
- :version "29.1"
+ :version "30.1"
:type '(choice (const :tag "Chrooted environment" nil)
(regexp :tag "Host regexp")))
@@ -659,6 +671,17 @@ The `sudo' program appears to insert a `^@' character into the prompt."
:version "29.1"
:type 'regexp)
+(defcustom tramp-otp-password-prompt-regexp
+ (rx-to-string
+ `(: bol (* nonl)
+ ;; JumpCloud.
+ (group (| "Verification code"))
+ (* nonl) (any . ,tramp-compat-password-colon-equivalents) (* blank)))
+ "Regexp matching one-time password prompts.
+The regexp should match at end of buffer."
+ :version "29.2"
+ :type 'regexp)
+
(defcustom tramp-wrong-passwd-regexp
(rx bol (* nonl)
(| "Permission denied"
@@ -727,8 +750,9 @@ The regexp should match at end of buffer."
;; A security key requires the user physically to touch the device
;; with their finger. We must tell it to the user.
-;; Added in OpenSSH 8.2. I've tested it with yubikey. Nitrokey,
-;; which has also passed the tests, does not show such a message.
+;; Added in OpenSSH 8.2. I've tested it with yubikey. Nitrokey and
+;; Titankey, which have also passed the tests, do not show such a
+;; message.
(defcustom tramp-security-key-confirm-regexp
(rx bol (* "\r") "Confirm user presence for key " (* nonl) (* (any "\r\n")))
"Regular expression matching security key confirmation message.
@@ -1190,7 +1214,7 @@ The `ftp' syntax does not support methods.")
;; We cannot use `tramp-prefix-regexp', because it starts with `bol'.
(literal tramp-prefix-format)
- ;; Optional multi hops.
+ ;; Optional multi-hops.
(* (regexp tramp-remote-file-name-spec-regexp)
(regexp tramp-postfix-hop-regexp))
@@ -1331,6 +1355,7 @@ let-bind this variable."
;; GNU/Linux (Debian, Suse, RHEL, Cygwin, MINGW64): /bin:/usr/bin
;; FreeBSD, DragonFly: /usr/bin:/bin:/usr/sbin:/sbin: - beware trailing ":"!
;; FreeBSD 12.1, Darwin: /usr/bin:/bin:/usr/sbin:/sbin
+;; NetBSD 9.3: /usr/bin:/bin:/usr/sbin:/sbin:/usr/pkg/bin:/usr/pkg/sbin:/usr/local/bin:/usr/local/sbin
;; IRIX64: /usr/bin
;; QNAP QTS: ---
;; Hydra: /run/current-system/sw/bin:/bin:/usr/bin
@@ -1457,10 +1482,12 @@ calling HANDLER.")
(function-put #'tramp-file-name-localname 'tramp-suppress-trace t)
(function-put #'tramp-file-name-hop 'tramp-suppress-trace t)
-;; Needed for `tramp-read-passwd' and `tramp-get-remote-null-device'.
+;;;###tramp-autoload
(defconst tramp-null-hop
- (make-tramp-file-name :user (user-login-name) :host tramp-system-name)
-"Connection hop which identifies the virtual hop before the first one.")
+ (make-tramp-file-name
+ :method "local" :user (user-login-name) :host tramp-system-name)
+ "Connection hop which identifies the virtual hop before the first one.
+Used also for caching properties of the local machine.")
(defun tramp-file-name-user-domain (vec)
"Return user and domain components of VEC."
@@ -1490,14 +1517,17 @@ If nil, return `tramp-default-port'."
;;;###tramp-autoload
(defun tramp-file-name-unify (vec &optional localname)
"Unify VEC by removing localname and hop from `tramp-file-name' structure.
-If LOCALNAME is an absolute file name, set it as localname. If
-LOCALNAME is a relative file name, return `tramp-cache-undefined'.
-Objects returned by this function compare `equal' if they refer to the
-same connection. Make a copy in order to avoid side effects."
+IF VEC is nil, set it to `tramp-null-hop'.
+If LOCALNAME is an absolute file name, set it as localname.
+If LOCALNAME is a relative file name, return `tramp-cache-undefined'.
+Objects returned by this function compare `equal' if they refer
+to the same connection. Make a copy in order to avoid side
+effects."
;; (declare (tramp-suppress-trace t))
(if (and (stringp localname)
(not (file-name-absolute-p localname)))
(setq vec tramp-cache-undefined)
+ (unless vec (setq vec tramp-null-hop))
(when (tramp-file-name-p vec)
(setq vec (copy-tramp-file-name vec))
(setf (tramp-file-name-localname vec)
@@ -2134,6 +2164,8 @@ Example:
;; DNS-SD service type.
((string-match-p
tramp-dns-sd-service-regexp (nth 1 (car v))))
+ ;; Method.
+ ((string-equal method (nth 1 (car v))))
;; Configuration file or empty string.
(t (file-exists-p (nth 1 (car v))))))
(setq r (delete (car v) r)))
@@ -2713,85 +2745,113 @@ not in completion mode."
(tramp-run-real-handler #'file-exists-p (list filename))))
+(defmacro tramp-skeleton-file-name-all-completions
+ (filename directory &rest body)
+ "Skeleton for `tramp-*-handle-filename-all-completions'.
+BODY is the backend specific code."
+ (declare (indent 2) (debug t))
+ `(ignore-error file-missing
+ (delete-dups (delq nil
+ (let* ((case-fold-search read-file-name-completion-ignore-case)
+ (result (progn ,@body)))
+ ;; Some storage systems do not return "." and "..".
+ (when (tramp-tramp-file-p ,directory)
+ (dolist (elt '(".." "."))
+ (when (string-prefix-p ,filename elt)
+ (setq result (cons (concat elt "/") result)))))
+ (if (consp completion-regexp-list)
+ ;; Discriminate over `completion-regexp-list'.
+ (mapcar
+ (lambda (x)
+ (when (stringp x)
+ (catch 'match
+ (dolist (elt completion-regexp-list x)
+ (unless (string-match-p elt x) (throw 'match nil))))))
+ result)
+ result))))))
+
+(defvar tramp--last-hop-directory nil
+ "Tracks the directory from which to run login programs.")
+
;; Method, host name and user name completion.
;; `tramp-completion-dissect-file-name' returns a list of
;; `tramp-file-name' structures. For all of them we return possible
;; completions.
(defun tramp-completion-handle-file-name-all-completions (filename directory)
"Like `file-name-all-completions' for partial Tramp files."
- (let ((fullname
- (tramp-drop-volume-letter (expand-file-name filename directory)))
- ;; When `tramp-syntax' is `simplified', we need a default method.
- (tramp-default-method
- (and (string-empty-p tramp-postfix-method-format)
- tramp-default-method))
- (tramp-default-method-alist
- (and (string-empty-p tramp-postfix-method-format)
- tramp-default-method-alist))
- tramp-default-user tramp-default-user-alist
- tramp-default-host tramp-default-host-alist
- hop result result1)
-
- ;; Suppress hop from completion.
- (when (string-match
- (rx
- (regexp tramp-prefix-regexp)
- (group (+ (regexp tramp-remote-file-name-spec-regexp)
- (regexp tramp-postfix-hop-regexp))))
- fullname)
- (setq hop (match-string 1 fullname)
- fullname (replace-match "" nil nil fullname 1)))
-
- ;; Possible completion structures.
- (dolist (elt (tramp-completion-dissect-file-name fullname))
- (let* ((method (tramp-file-name-method elt))
- (user (tramp-file-name-user elt))
- (host (tramp-file-name-host elt))
- (localname (tramp-file-name-localname elt))
- (m (tramp-find-method method user host))
- all-user-hosts)
-
- (unless localname ;; Nothing to complete.
-
- (if (or user host)
-
- ;; Method dependent user / host combinations.
- (progn
- (mapc
- (lambda (x)
- (setq all-user-hosts
- (append all-user-hosts
- (funcall (nth 0 x) (nth 1 x)))))
- (tramp-get-completion-function m))
+ (tramp-skeleton-file-name-all-completions filename directory
+ (let ((fullname
+ (tramp-drop-volume-letter (expand-file-name filename directory)))
+ (directory (tramp-drop-volume-letter directory))
+ tramp--last-hop-directory hop result result1)
+ ;; Suppress hop from completion.
+ (when (string-match
+ (rx
+ (regexp tramp-prefix-regexp)
+ (group (+ (regexp tramp-remote-file-name-spec-regexp)
+ (regexp tramp-postfix-hop-regexp))))
+ fullname)
+ (setq hop (match-string 1 fullname)
+ fullname (replace-match "" nil nil fullname 1)
+ tramp--last-hop-directory
+ (tramp-make-tramp-file-name (tramp-dissect-hop-name hop))))
+
+ (let (;; When `tramp-syntax' is `simplified', we need a default method.
+ (tramp-default-method
+ (and (string-empty-p tramp-postfix-method-format)
+ tramp-default-method))
+ (tramp-default-method-alist
+ (and (string-empty-p tramp-postfix-method-format)
+ tramp-default-method-alist))
+ tramp-default-user tramp-default-user-alist
+ tramp-default-host tramp-default-host-alist)
+
+ ;; Possible completion structures.
+ (dolist (elt (tramp-completion-dissect-file-name fullname))
+ (let* ((method (tramp-file-name-method elt))
+ (user (tramp-file-name-user elt))
+ (host (tramp-file-name-host elt))
+ (localname (tramp-file-name-localname elt))
+ (m (tramp-find-method method user host))
+ all-user-hosts)
+
+ (unless localname ;; Nothing to complete.
+ (if (or user host)
+ ;; Method dependent user / host combinations.
+ (progn
+ (mapc
+ (lambda (x)
+ (setq all-user-hosts
+ (append all-user-hosts
+ (funcall (nth 0 x) (nth 1 x)))))
+ (tramp-get-completion-function m))
+
+ (setq result
+ (append result
+ (mapcar
+ (lambda (x)
+ (tramp-get-completion-user-host
+ method user host (nth 0 x) (nth 1 x)))
+ all-user-hosts))))
+
+ ;; Possible methods.
(setq result
- (append result
- (mapcar
- (lambda (x)
- (tramp-get-completion-user-host
- method user host (nth 0 x) (nth 1 x)))
- (delq nil all-user-hosts)))))
-
- ;; Possible methods.
- (setq result
- (append result (tramp-get-completion-methods m)))))))
-
- ;; Unify list, add hop, remove nil elements.
- (dolist (elt result)
- (when elt
- (string-match tramp-prefix-regexp elt)
- (setq elt (replace-match (concat tramp-prefix-format hop) nil nil elt))
- (push
- (substring elt (length (tramp-drop-volume-letter directory)))
- result1)))
-
- ;; Complete local parts.
- (delete-dups
- (append
- result1
- (ignore-errors
- (tramp-run-real-handler
- #'file-name-all-completions (list filename directory)))))))
+ (append result (tramp-get-completion-methods m hop)))))))
+
+ ;; Add hop.
+ (dolist (elt result)
+ (when elt
+ (setq elt (replace-regexp-in-string
+ tramp-prefix-regexp (concat tramp-prefix-format hop) elt))
+ (push (substring elt (length directory)) result1)))
+
+ ;; Complete local parts.
+ (append
+ result1
+ (ignore-errors
+ (tramp-run-real-handler
+ #'file-name-all-completions (list filename directory))))))))
;; Method, host name and user name completion for a file.
(defun tramp-completion-handle-file-name-completion
@@ -2911,11 +2971,14 @@ remote host and localname (filename on remote host)."
;; This function returns all possible method completions, adding the
;; trailing method delimiter.
-(defun tramp-get-completion-methods (partial-method)
- "Return all method completions for PARTIAL-METHOD."
+(defun tramp-get-completion-methods (partial-method &optional multi-hop)
+ "Return all method completions for PARTIAL-METHOD.
+If MULTI-HOP is non-nil, return only multi-hop capable methods."
(mapcar
(lambda (method)
(and method (string-prefix-p (or partial-method "") method)
+ (or (not multi-hop)
+ (tramp-multi-hop-p (make-tramp-file-name :method method)))
(tramp-completion-make-tramp-file-name method nil nil nil)))
(mapcar #'car tramp-methods)))
@@ -2994,6 +3057,12 @@ This function is added always in `tramp-get-completion-function'
for all methods. Resulting data are derived from default settings."
`((,(tramp-find-user method nil nil) ,(tramp-find-host method nil nil))))
+;;;###tramp-autoload
+(defcustom tramp-completion-multi-hop-methods nil
+ "Methods for which to provide completions over multi-hop connections."
+ :version "30.1"
+ :type '(repeat (string :tag "Method name")))
+
(defcustom tramp-completion-use-auth-sources auth-source-do-cache
"Whether to use `auth-source-search' for completion of user and host names.
This could be disturbing, if it requires a password / passphrase,
@@ -3259,7 +3328,7 @@ BODY is the backend specific code."
(with-parsed-tramp-file-name (expand-file-name ,directory) nil
(tramp-barf-if-file-missing v ,directory
(when (file-directory-p ,directory)
- (setq ,directory
+ (setf ,directory
(file-name-as-directory (expand-file-name ,directory)))
(let ((temp
(with-tramp-file-property v localname "directory-files" ,@body))
@@ -3390,7 +3459,7 @@ BODY is the backend specific code."
"Apparent cycle of symbolic links for %s" ,filename))
;; If the resulting localname looks remote, we must quote
;; it for security reasons.
- (when (file-remote-p result)
+ (when (tramp-tramp-file-p result)
(setq result (file-name-quote result 'top)))
result)))))))
@@ -3430,7 +3499,7 @@ on the same host. Otherwise, TARGET is quoted."
(let ((non-essential t))
(when (and (tramp-tramp-file-p ,target)
(tramp-file-name-equal-p v (tramp-dissect-file-name ,target)))
- (setq ,target (tramp-file-local-name (expand-file-name ,target))))
+ (setf ,target (tramp-file-local-name (expand-file-name ,target))))
;; There could be a cyclic link.
(tramp-flush-file-properties
v (expand-file-name ,target (tramp-file-local-name default-directory))))
@@ -3489,7 +3558,7 @@ BODY is the backend specific code."
(let ((inhibit-file-name-handlers
`(tramp-file-name-handler
tramp-crypt-file-name-handler
- . inhibit-file-name-handlers))
+ . ,inhibit-file-name-handlers))
(inhibit-file-name-operation 'write-region))
(find-file-name-handler ,visit 'write-region))))
;; We use this to save the value of
@@ -3530,7 +3599,7 @@ BODY is the backend specific code."
;; Lock file.
(when (and (not (auto-save-file-name-p
(file-name-nondirectory filename)))
- (file-remote-p lockname)
+ (tramp-tramp-file-p lockname)
(not file-locked))
(setq file-locked t)
;; `lock-file' exists since Emacs 28.1.
@@ -3769,6 +3838,9 @@ Let-bind it when necessary.")
(with-parsed-tramp-file-name name nil
(unless (tramp-run-real-handler #'file-name-absolute-p (list localname))
(setq localname (concat "/" localname)))
+ ;; Tilde expansion shall be possible also for quoted localname.
+ (when (string-prefix-p "~" (file-name-unquote localname))
+ (setq localname (file-name-unquote localname)))
;; Expand tilde. Usually, the methods applying this handler do
;; not support tilde expansion. But users could declare a
;; respective connection property. (Bug#53847)
@@ -4057,7 +4129,7 @@ Let-bind it when necessary.")
(< numchase numchase-limit))
(setq numchase (1+ numchase)
result
- (if (file-remote-p symlink-target)
+ (if (tramp-tramp-file-p symlink-target)
(file-name-quote symlink-target 'top)
(tramp-drop-volume-letter
(expand-file-name
@@ -4121,7 +4193,7 @@ Let-bind it when necessary.")
(tramp-error v 'file-error "Unsafe backup file name"))))))
(defun tramp-handle-insert-directory
- (filename switches &optional wildcard full-directory-p)
+ (filename switches &optional wildcard full-directory-p)
"Like `insert-directory' for Tramp files."
(require 'ls-lisp)
(unless switches (setq switches ""))
@@ -4134,8 +4206,14 @@ Let-bind it when necessary.")
(access-file filename "Reading directory"))
(with-parsed-tramp-file-name (expand-file-name filename) nil
(with-tramp-progress-reporter v 0 (format "Opening directory %s" filename)
- (let (ls-lisp-use-insert-directory-program start)
- ;; Silence byte compiler.
+ ;; We bind `ls-lisp-emulation' to nil (which is GNU).
+ ;; `ls-lisp-set-options' modifies `ls-lisp-ignore-case',
+ ;; `ls-lisp-dirs-first' and `ls-lisp-verbosity', so we bind them
+ ;; as well. We don't want to use `insert-directory-program'.
+ (let (ls-lisp-emulation ls-lisp-ignore-case ls-lisp-dirs-first
+ ls-lisp-verbosity ls-lisp-use-insert-directory-program start)
+ ;; Set proper options based on `ls-lisp-emulation'.
+ (tramp-compat-funcall 'ls-lisp-set-options)
(tramp-run-real-handler
#'insert-directory
(list filename switches wildcard full-directory-p))
@@ -4565,8 +4643,9 @@ Do not set it manually, it is used buffer-local in `tramp-get-lock-pid'.")
(defun tramp-multi-hop-p (vec)
"Whether the method of VEC is capable of multi-hops."
- (and (tramp-sh-file-name-handler-p vec)
- (not (tramp-get-method-parameter vec 'tramp-copy-program))))
+ (let ((tramp-verbose 0))
+ (and (tramp-sh-file-name-handler-p vec)
+ (not (tramp-get-method-parameter vec 'tramp-copy-program)))))
(defun tramp-add-hops (vec)
"Add ad-hoc proxy definitions to `tramp-default-proxies-alist'."
@@ -4770,7 +4849,12 @@ a connection-local variable."
(unless (or (null stderr) (bufferp stderr))
(signal 'wrong-type-argument (list #'bufferp stderr)))
- (let* ((buffer
+ ;; Check for `tramp-sh-file-name-handler', because something
+ ;; is different between tramp-sh.el, and tramp-adb.el or
+ ;; tramp-sshfs.el.
+ (let* ((sh-file-name-handler-p (tramp-sh-file-name-handler-p v))
+ (adb-file-name-handler-p (tramp-adb-file-name-p v))
+ (buffer
(if buffer
(get-buffer-create buffer)
;; BUFFER can be nil. We use a temporary buffer.
@@ -4790,6 +4874,12 @@ a connection-local variable."
(member
elt (default-toplevel-value 'process-environment))))
(setq env (cons elt env)))))
+ ;; Add remote path if exists.
+ (env (if-let ((sh-file-name-handler-p)
+ (remote-path
+ (string-join (tramp-get-remote-path v) ":")))
+ (setenv-internal env "PATH" remote-path 'keep)
+ env))
(env (setenv-internal
env "INSIDE_EMACS" (tramp-inside-emacs) 'keep))
(env (mapcar #'tramp-shell-quote-argument (delq nil env)))
@@ -4800,82 +4890,83 @@ a connection-local variable."
(append
`("cd" ,(tramp-shell-quote-argument localname) "&&" "(" "env")
env `(,command ")")))
- ;; Add remote shell if needed.
+ ;; Add remote shell if needed.
(command
(if (consp (tramp-get-method-parameter v 'tramp-direct-async))
(append
(tramp-get-method-parameter v 'tramp-direct-async)
`(,(string-join command " ")))
- command)))
-
- ;; Check for `tramp-sh-file-name-handler', because something
- ;; is different between tramp-sh.el, and tramp-adb.el or
- ;; tramp-sshfs.el.
- (let* ((sh-file-name-handler-p (tramp-sh-file-name-handler-p v))
- (adb-file-name-handler-p (tramp-adb-file-name-p v))
- (login-program
- (tramp-get-method-parameter v 'tramp-login-program))
- ;; We don't create the temporary file. In fact, it
- ;; is just a prefix for the ControlPath option of
- ;; ssh; the real temporary file has another name, and
- ;; it is created and protected by ssh. It is also
- ;; removed by ssh when the connection is closed. The
- ;; temporary file name is cached in the main
- ;; connection process, therefore we cannot use
- ;; `tramp-get-connection-process'.
- (tmpfile
- (when sh-file-name-handler-p
- (with-tramp-connection-property
- (tramp-get-process v) "temp-file"
- (tramp-compat-make-temp-name))))
- (options
- (when sh-file-name-handler-p
- (tramp-compat-funcall
- 'tramp-ssh-controlmaster-options v)))
- (device
- (when adb-file-name-handler-p
- (tramp-compat-funcall
- 'tramp-adb-get-device v)))
- login-args p)
-
- ;; Replace `login-args' place holders. Split
- ;; ControlMaster options.
- (setq
- login-args
- (append
- (flatten-tree (tramp-get-method-parameter v 'tramp-async-args))
- (flatten-tree
- (mapcar
- (lambda (x) (split-string x " "))
- (tramp-expand-args
- v 'tramp-login-args
- ?h (or host "") ?u (or user "") ?p (or port "")
- ?c (format-spec (or options "") (format-spec-make ?t tmpfile))
- ?d (or device "") ?l ""))))
- p (make-process
- :name name :buffer buffer
- :command (append `(,login-program) login-args command)
- :coding coding :noquery noquery :connection-type connection-type
- :sentinel sentinel :stderr stderr))
- ;; Set filter. Prior Emacs 29.1, it doesn't work reliably
- ;; to provide it as `make-process' argument when filter is
- ;; t. See Bug#51177.
- (when filter
- (set-process-filter p filter))
- (tramp-post-process-creation p v)
- ;; Query flag is overwritten in `tramp-post-process-creation',
- ;; so we reset it.
- (set-process-query-on-exit-flag p (null noquery))
- ;; This is neded for ssh or PuTTY based processes, and
- ;; only if the respective options are set. Perhaps, the
- ;; setting could be more fine-grained.
- ;; (process-put p 'tramp-shared-socket t)
- (process-put p 'remote-command orig-command)
- (tramp-set-connection-property p "remote-command" orig-command)
- (when (bufferp stderr)
- (tramp-taint-remote-process-buffer stderr))
-
- p))))))
+ command))
+ (login-program
+ (tramp-get-method-parameter v 'tramp-login-program))
+ ;; We don't create the temporary file. In fact, it is
+ ;; just a prefix for the ControlPath option of ssh; the
+ ;; real temporary file has another name, and it is
+ ;; created and protected by ssh. It is also removed by
+ ;; ssh when the connection is closed. The temporary
+ ;; file name is cached in the main connection process,
+ ;; therefore we cannot use
+ ;; `tramp-get-connection-process'.
+ (tmpfile
+ (when sh-file-name-handler-p
+ (with-tramp-connection-property
+ (tramp-get-process v) "temp-file"
+ (tramp-compat-make-temp-name))))
+ (options
+ (when sh-file-name-handler-p
+ (tramp-compat-funcall
+ 'tramp-ssh-controlmaster-options v)))
+ (device
+ (when adb-file-name-handler-p
+ (tramp-compat-funcall
+ 'tramp-adb-get-device v)))
+ (pta (unless (eq connection-type 'pipe) "-t"))
+ login-args p)
+
+ ;; Command could be too long, for example due to a longish PATH.
+ (when (and sh-file-name-handler-p
+ (tramp-compat-length>
+ (string-join command) (tramp-get-remote-pipe-buf v)))
+ (signal 'error (cons "Command too long:" command)))
+
+ ;; Replace `login-args' place holders. Split ControlMaster
+ ;; options.
+ (setq
+ login-args
+ (append
+ (flatten-tree (tramp-get-method-parameter v 'tramp-async-args))
+ (flatten-tree
+ (mapcar
+ (lambda (x) (split-string x " "))
+ (tramp-expand-args
+ v 'tramp-login-args
+ ?h (or host "") ?u (or user "") ?p (or port "")
+ ?c (format-spec (or options "") (format-spec-make ?t tmpfile))
+ ?d (or device "") ?a (or pta "") ?l ""))))
+ p (make-process
+ :name name :buffer buffer
+ :command (append `(,login-program) login-args command)
+ :coding coding :noquery noquery :connection-type connection-type
+ :sentinel sentinel :stderr stderr))
+ ;; Set filter. Prior Emacs 29.1, it doesn't work reliably
+ ;; to provide it as `make-process' argument when filter is
+ ;; t. See Bug#51177.
+ (when filter
+ (set-process-filter p filter))
+ (tramp-post-process-creation p v)
+ ;; Query flag is overwritten in `tramp-post-process-creation',
+ ;; so we reset it.
+ (set-process-query-on-exit-flag p (null noquery))
+ ;; This is needed for ssh or PuTTY based processes, and
+ ;; only if the respective options are set. Perhaps, the
+ ;; setting could be more fine-grained.
+ ;; (process-put p 'tramp-shared-socket t)
+ (process-put p 'remote-command orig-command)
+ (tramp-set-connection-property p "remote-command" orig-command)
+ (when (bufferp stderr)
+ (tramp-taint-remote-process-buffer stderr))
+
+ p)))))
(defun tramp-handle-make-symbolic-link
(_target linkname &optional _ok-if-already-exists)
@@ -5344,6 +5435,25 @@ of."
(narrow-to-region (point-max) (point-max))))
t)
+(defun tramp-action-otp-password (proc vec)
+ "Query the user for a one-time password."
+ (with-current-buffer (process-buffer proc)
+ (let ((case-fold-search t)
+ prompt)
+ (goto-char (point-min))
+ (tramp-check-for-regexp proc tramp-process-action-regexp)
+ (setq prompt (concat (match-string 1) " "))
+ (tramp-message vec 3 "Sending %s" (match-string 1))
+ ;; We don't call `tramp-send-string' in order to hide the
+ ;; password from the debug buffer and the traces.
+ (process-send-string
+ proc
+ (concat
+ (tramp-read-passwd-without-cache proc prompt) tramp-local-end-of-line))
+ ;; Hide password prompt.
+ (narrow-to-region (point-max) (point-max))))
+ t)
+
(defun tramp-action-succeed (_proc _vec)
"Signal success in finding shell prompt."
(throw 'tramp-action 'ok))
@@ -5594,7 +5704,8 @@ If the user quits via `C-g', it is propagated up to `tramp-file-name-handler'."
(v (process-get proc 'tramp-vector)))
(dolist (p (delq proc (process-list)))
(when (tramp-file-name-equal-p v (process-get p 'tramp-vector))
- (with-local-quit (accept-process-output p 0 nil t)))))
+ (with-tramp-suspended-timers
+ (with-local-quit (accept-process-output p 0 nil t))))))
(with-current-buffer (process-buffer proc)
(let ((inhibit-read-only t)
@@ -6158,20 +6269,20 @@ Set connection properties \"{uid,gid,groups}-{integer,string}\"."
(goto-char (point-min))
;; Read uid.
(when (search-forward-regexp
- (rx "uid=" (group (+ digit)) "(" (group (+ (any "_" word))) ")")
+ (rx "uid=" (group (+ digit)) "(" (group (+ (any "_-" alnum))) ")")
nil 'noerror)
(setq uid-integer (string-to-number (match-string 1))
uid-string (match-string 2)))
;; Read gid.
(when (search-forward-regexp
- (rx "gid=" (group (+ digit)) "(" (group (+ (any "_" word))) ")")
+ (rx "gid=" (group (+ digit)) "(" (group (+ (any "_-" alnum))) ")")
nil 'noerror)
(setq gid-integer (string-to-number (match-string 1))
gid-string (match-string 2)))
;; Read groups.
(when (search-forward-regexp (rx "groups=") nil 'noerror)
(while (looking-at
- (rx (group (+ digit)) "(" (group (+ (any "_" word))) ")"))
+ (rx (group (+ digit)) "(" (group (+ (any "_-" alnum))) ")"))
(setq groups-integer (cons (string-to-number (match-string 1))
groups-integer)
groups-string (cons (match-string 2) groups-string))
@@ -6380,6 +6491,7 @@ are written with verbosity of 6."
(temporary-file-directory tramp-compat-temporary-file-directory)
(process-environment (default-toplevel-value 'process-environment))
(buffer (if (eq buffer t) (current-buffer) buffer))
+ (vec (or vec (car tramp-current-connection)))
result)
(tramp-message
vec 6 "`%s %s' %s %s %s %s"
@@ -6507,8 +6619,8 @@ Consults the auth-source package."
(defun tramp-read-passwd-without-cache (proc &optional prompt)
"Read a password from user (compat function)."
- ;; We suspend the timers while reading the password.
(declare (tramp-suppress-trace t))
+ ;; We suspend the timers while reading the password.
(let (tramp-dont-suspend-timers)
(with-tramp-suspended-timers
(password-read
@@ -6630,7 +6742,14 @@ If PROCESS is a process object which contains the property
`remote-pid', or PROCESS is a number and REMOTE is a remote file name,
PROCESS is interpreted as process on the respective remote host, which
will be the process to signal.
+If PROCESS is a string, it is interpreted as process object with
+the respective process name, or as a number.
SIGCODE may be an integer, or a symbol whose name is a signal name."
+ (when (stringp process)
+ (setq process (or (get-process process)
+ (and (string-match-p (rx bol (+ digit) eol) process)
+ (string-to-number process))
+ (signal 'wrong-type-argument (list #'processp process)))))
(let (pid vec)
(cond
((processp process)
diff --git a/lisp/net/trampver.el b/lisp/net/trampver.el
index 4d56cf367e3..bfabbbeaf34 100644
--- a/lisp/net/trampver.el
+++ b/lisp/net/trampver.el
@@ -1,7 +1,7 @@
;;; trampver.el --- Transparent Remote Access, Multiple Protocol -*- lexical-binding:t -*-
;;; lisp/trampver.el. Generated from trampver.el.in by configure.
-;; Copyright (C) 2003-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003-2024 Free Software Foundation, Inc.
;; Author: Kai Großjohann <kai.grossjohann@gmx.net>
;; Maintainer: Michael Albinus <michael.albinus@gmx.de>
@@ -105,7 +105,7 @@
("2.3.5.26.3" . "26.3")
("2.4.3.27.1" . "27.1") ("2.4.5.27.2" . "27.2")
("2.5.2.28.1" . "28.1") ("2.5.3.28.2" . "28.2") ("2.5.4" . "28.3")
- ("2.6.0.29.1" . "29.1")))
+ ("2.6.0.29.1" . "29.1") ("2.6.2.29.2" . "29.2")))
(add-hook 'tramp-unload-hook
(lambda ()
diff --git a/lisp/net/webjump.el b/lisp/net/webjump.el
index fe7c3679876..cff838fca51 100644
--- a/lisp/net/webjump.el
+++ b/lisp/net/webjump.el
@@ -1,6 +1,6 @@
;;; webjump.el --- programmable Web hotlist -*- lexical-binding: t; -*-
-;; Copyright (C) 1996-1997, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-1997, 2001-2024 Free Software Foundation, Inc.
;; Author: Neil W. Van Dyke <nwv@acm.org>
;; Maintainer: emacs-devel@gnu.org
@@ -123,7 +123,7 @@ external browser like IceCat."
;; Misc. general interest.
("National Weather Service" . webjump-to-iwin)
("Usenet FAQs" .
- "www.faqs.org/faqs/")
+ "http://www.faqs.org/faqs/")
("RTFM Usenet FAQs by Group" .
"ftp://rtfm.mit.edu/pub/usenet-by-group/")
("RTFM Usenet FAQs by Hierarchy" .
@@ -132,7 +132,7 @@ external browser like IceCat."
;; Computer social issues, privacy, professionalism.
("Association for Computing Machinery" . "www.acm.org")
- ("Computer Professionals for Social Responsibility" . "www.cpsr.org")
+ ("Computer Professionals for Social Responsibility" . "http://www.cpsr.org")
("Electronic Frontier Foundation" . "www.eff.org")
("IEEE Computer Society" . "www.computer.org")
("Risks Digest" . webjump-to-risks)
@@ -194,7 +194,7 @@ If the symbol of a function is given, then the function will be called with the
Web site name (the one you specified in the CAR of the alist cell) as a
parameter. This might come in handy for various kludges.
-For convenience, if the `http://', `ftp://', or `file://' prefix is missing
+For convenience, if the `https://', `ftp://', or `file://' prefix is missing
from a URL, WebJump will make a guess at what you wanted and prepend it before
submitting the URL."
:type '(alist :key-type (string :tag "Name")
@@ -262,33 +262,22 @@ Please submit bug reports and other feedback to the author, Neil W. Van Dyke
(completing-read "WebJump to site: " webjump-sites nil t)
webjump-sites t))
(name (car item))
- (expr (cdr item)))
- (if webjump-use-internal-browser
- (browse-url-with-browser-kind
- 'internal (webjump-url-fix
- (cond ((not expr) "")
- ((stringp expr) expr)
- ((vectorp expr) (webjump-builtin expr name))
- ((listp expr) (eval expr t))
- ((symbolp expr)
- (if (fboundp expr)
- (funcall expr name)
- (error "WebJump URL function \"%s\" undefined"
- expr)))
- (t (error "WebJump URL expression for \"%s\" invalid"
- name)))))
- (browse-url (webjump-url-fix
- (cond ((not expr) "")
- ((stringp expr) expr)
- ((vectorp expr) (webjump-builtin expr name))
- ((listp expr) (eval expr t))
- ((symbolp expr)
- (if (fboundp expr)
- (funcall expr name)
- (error "WebJump URL function \"%s\" undefined"
- expr)))
- (t (error "WebJump URL expression for \"%s\" invalid"
- name))))))))
+ (expr (cdr item))
+ (fun (if webjump-use-internal-browser
+ (apply-partially #'browse-url-with-browser-kind 'internal)
+ #'browse-url)))
+ (funcall fun (webjump-url-fix
+ (cond ((not expr) "")
+ ((stringp expr) expr)
+ ((vectorp expr) (webjump-builtin expr name))
+ ((listp expr) (eval expr t))
+ ((symbolp expr)
+ (if (fboundp expr)
+ (funcall expr name)
+ (error "WebJump URL function \"%s\" undefined"
+ expr)))
+ (t (error "WebJump URL expression for \"%s\" invalid"
+ name)))))))
(defun webjump-builtin (expr name)
(if (< (length expr) 1)
@@ -380,9 +369,11 @@ Please submit bug reports and other feedback to the author, Neil W. Van Dyke
((string-match "^[a-zA-Z]+:" url) url)
((string-match "^/" url) (concat "file://" url))
((string-match "^\\([^\\./]+\\)" url)
+ ;; FIXME: ftp.gnu.org and many others now prefer HTTPS instead
+ ;; of FTP. Does this heuristic make sense these days?
(concat (if (string= (downcase (match-string 1 url)) "ftp")
"ftp"
- "http")
+ "https")
"://"
url))
(t url)))))
diff --git a/lisp/net/zeroconf.el b/lisp/net/zeroconf.el
index 238bf20bb66..54422d43cd7 100644
--- a/lisp/net/zeroconf.el
+++ b/lisp/net/zeroconf.el
@@ -1,6 +1,6 @@
;;; zeroconf.el --- Service browser using Avahi. -*- lexical-binding:t -*-
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
;; Author: Michael Albinus <michael.albinus@gmx.de>
;; Keywords: comm, hardware
diff --git a/lisp/newcomment.el b/lisp/newcomment.el
index 9ae7de70a0e..ee7b2ea34d8 100644
--- a/lisp/newcomment.el
+++ b/lisp/newcomment.el
@@ -1,6 +1,6 @@
;;; newcomment.el --- (un)comment regions of buffers -*- lexical-binding: t -*-
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
;; Author: code extracted from Emacs-20's simple.el
;; Maintainer: Stefan Monnier <monnier@gnu.org>
diff --git a/lisp/notifications.el b/lisp/notifications.el
index a694b38e52e..6abc6e163ed 100644
--- a/lisp/notifications.el
+++ b/lisp/notifications.el
@@ -1,6 +1,6 @@
;;; notifications.el --- Client interface to desktop notifications. -*- lexical-binding: t -*-
-;; Copyright (C) 2010-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2010-2024 Free Software Foundation, Inc.
;; Author: Julien Danjou <julien@danjou.info>
;; Keywords: comm desktop notifications
diff --git a/lisp/novice.el b/lisp/novice.el
index 05e4bfc91c9..33a6d153180 100644
--- a/lisp/novice.el
+++ b/lisp/novice.el
@@ -1,6 +1,6 @@
;;; novice.el --- handling of disabled commands ("novice mode") for Emacs -*- lexical-binding: t -*-
-;; Copyright (C) 1985-1987, 1994, 2001-2023 Free Software Foundation,
+;; Copyright (C) 1985-1987, 1994, 2001-2024 Free Software Foundation,
;; Inc.
;; Maintainer: emacs-devel@gnu.org
@@ -67,9 +67,10 @@ If nil, the feature is disabled, i.e., all commands work normally.")
"Here's the first part of its description:\n\n")
;; Keep only the first paragraph of the documentation.
(with-temp-buffer
- (insert (condition-case ()
- (documentation cmd)
- (error "<< not documented >>")))
+ (insert (or (condition-case ()
+ (documentation cmd)
+ (error nil))
+ "<< not documented >>"))
(goto-char (point-min))
(when (search-forward "\n\n" nil t)
(delete-region (match-beginning 0) (point-max)))
diff --git a/lisp/nxml/nxml-enc.el b/lisp/nxml/nxml-enc.el
index 1fd7abef974..b5b6c844ceb 100644
--- a/lisp/nxml/nxml-enc.el
+++ b/lisp/nxml/nxml-enc.el
@@ -1,9 +1,9 @@
;;; nxml-enc.el --- XML encoding auto-detection -*- lexical-binding:t -*-
-;; Copyright (C) 2003, 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003, 2007-2024 Free Software Foundation, Inc.
;; Author: James Clark
-;; Keywords: wp, hypermedia, languages, XML
+;; Keywords: text, hypermedia, languages, XML
;; This file is part of GNU Emacs.
diff --git a/lisp/nxml/nxml-maint.el b/lisp/nxml/nxml-maint.el
index 24eb711eb99..be49e41dbed 100644
--- a/lisp/nxml/nxml-maint.el
+++ b/lisp/nxml/nxml-maint.el
@@ -1,9 +1,9 @@
;;; nxml-maint.el --- commands for maintainers of nxml-*.el -*- lexical-binding:t -*-
-;; Copyright (C) 2003, 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003, 2007-2024 Free Software Foundation, Inc.
;; Author: James Clark
-;; Keywords: wp, hypermedia, languages, XML
+;; Keywords: text, hypermedia, languages, XML
;; This file is part of GNU Emacs.
diff --git a/lisp/nxml/nxml-mode.el b/lisp/nxml/nxml-mode.el
index 67d136b5a66..02391dc6968 100644
--- a/lisp/nxml/nxml-mode.el
+++ b/lisp/nxml/nxml-mode.el
@@ -1,9 +1,9 @@
;;; nxml-mode.el --- a new XML mode -*- lexical-binding:t -*-
-;; Copyright (C) 2003-2004, 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003-2004, 2007-2024 Free Software Foundation, Inc.
;; Author: James Clark
-;; Keywords: wp, hypermedia, languages, XML
+;; Keywords: text, hypermedia, languages, XML
;; This file is part of GNU Emacs.
@@ -390,7 +390,6 @@ reference.")
"C-c C-u" #'nxml-insert-named-char
"C-c C-o" nxml-outline-prefix-map
"/" #'nxml-electric-slash
- "M-TAB" #'completion-at-point
"S-<mouse-2>" #'nxml-mouse-hide-direct-text-content)
(defvar nxml-font-lock-keywords
diff --git a/lisp/nxml/nxml-ns.el b/lisp/nxml/nxml-ns.el
index 2781ea87938..10dafe32e62 100644
--- a/lisp/nxml/nxml-ns.el
+++ b/lisp/nxml/nxml-ns.el
@@ -1,9 +1,9 @@
;;; nxml-ns.el --- XML namespace processing -*- lexical-binding:t -*-
-;; Copyright (C) 2003, 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003, 2007-2024 Free Software Foundation, Inc.
;; Author: James Clark
-;; Keywords: wp, hypermedia, languages, XML
+;; Keywords: text, hypermedia, languages, XML
;; This file is part of GNU Emacs.
diff --git a/lisp/nxml/nxml-outln.el b/lisp/nxml/nxml-outln.el
index 5f1eec75ef9..a470fbdc5b1 100644
--- a/lisp/nxml/nxml-outln.el
+++ b/lisp/nxml/nxml-outln.el
@@ -1,9 +1,9 @@
;;; nxml-outln.el --- outline support for nXML mode -*- lexical-binding:t -*-
-;; Copyright (C) 2004, 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2004, 2007-2024 Free Software Foundation, Inc.
;; Author: James Clark
-;; Keywords: wp, hypermedia, languages, XML
+;; Keywords: text, hypermedia, languages, XML
;; This file is part of GNU Emacs.
diff --git a/lisp/nxml/nxml-parse.el b/lisp/nxml/nxml-parse.el
index f2440065deb..61ff0b68b68 100644
--- a/lisp/nxml/nxml-parse.el
+++ b/lisp/nxml/nxml-parse.el
@@ -1,9 +1,9 @@
;;; nxml-parse.el --- XML parser, sharing infrastructure with nxml-mode -*- lexical-binding:t -*-
-;; Copyright (C) 2003, 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003, 2007-2024 Free Software Foundation, Inc.
;; Author: James Clark
-;; Keywords: wp, hypermedia, languages, XML
+;; Keywords: text, hypermedia, languages, XML
;; This file is part of GNU Emacs.
diff --git a/lisp/nxml/nxml-rap.el b/lisp/nxml/nxml-rap.el
index 8e11707b9b7..6117b8bd33a 100644
--- a/lisp/nxml/nxml-rap.el
+++ b/lisp/nxml/nxml-rap.el
@@ -1,9 +1,9 @@
;;; nxml-rap.el --- low-level support for random access parsing for nXML mode -*- lexical-binding:t -*-
-;; Copyright (C) 2003-2004, 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003-2004, 2007-2024 Free Software Foundation, Inc.
;; Author: James Clark
-;; Keywords: wp, hypermedia, languages, XML
+;; Keywords: text, hypermedia, languages, XML
;; This file is part of GNU Emacs.
diff --git a/lisp/nxml/nxml-util.el b/lisp/nxml/nxml-util.el
index e9d04126400..7f425f8bcea 100644
--- a/lisp/nxml/nxml-util.el
+++ b/lisp/nxml/nxml-util.el
@@ -1,9 +1,9 @@
;;; nxml-util.el --- utility functions for nxml-*.el -*- lexical-binding:t -*-
-;; Copyright (C) 2003, 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003, 2007-2024 Free Software Foundation, Inc.
;; Author: James Clark
-;; Keywords: wp, hypermedia, languages, XML
+;; Keywords: text, hypermedia, languages, XML
;; This file is part of GNU Emacs.
diff --git a/lisp/nxml/rng-cmpct.el b/lisp/nxml/rng-cmpct.el
index 98aad8bd4dd..9aa7eecf346 100644
--- a/lisp/nxml/rng-cmpct.el
+++ b/lisp/nxml/rng-cmpct.el
@@ -1,9 +1,9 @@
;;; rng-cmpct.el --- parsing of RELAX NG Compact Syntax schemas -*- lexical-binding:t -*-
-;; Copyright (C) 2003-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003-2024 Free Software Foundation, Inc.
;; Author: James Clark
-;; Keywords: wp, hypermedia, languages, XML, RelaxNG
+;; Keywords: text, hypermedia, languages, XML, RelaxNG
;; This file is part of GNU Emacs.
diff --git a/lisp/nxml/rng-dt.el b/lisp/nxml/rng-dt.el
index 577157687a3..b7fd46dd894 100644
--- a/lisp/nxml/rng-dt.el
+++ b/lisp/nxml/rng-dt.el
@@ -1,9 +1,9 @@
;;; rng-dt.el --- datatype library interface for RELAX NG -*- lexical-binding:t -*-
-;; Copyright (C) 2003, 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003, 2007-2024 Free Software Foundation, Inc.
;; Author: James Clark
-;; Keywords: wp, hypermedia, languages, XML, RelaxNG
+;; Keywords: text, hypermedia, languages, XML, RelaxNG
;; This file is part of GNU Emacs.
diff --git a/lisp/nxml/rng-loc.el b/lisp/nxml/rng-loc.el
index 82e8494a49f..3e55bc5d4b9 100644
--- a/lisp/nxml/rng-loc.el
+++ b/lisp/nxml/rng-loc.el
@@ -1,9 +1,9 @@
;;; rng-loc.el --- Locate the schema to use for validation -*- lexical-binding:t -*-
-;; Copyright (C) 2003, 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003, 2007-2024 Free Software Foundation, Inc.
;; Author: James Clark
-;; Keywords: wp, hypermedia, languages, XML, RelaxNG
+;; Keywords: text, hypermedia, languages, XML, RelaxNG
;; This file is part of GNU Emacs.
diff --git a/lisp/nxml/rng-maint.el b/lisp/nxml/rng-maint.el
index 42feb221e81..62f5ce8b93d 100644
--- a/lisp/nxml/rng-maint.el
+++ b/lisp/nxml/rng-maint.el
@@ -1,9 +1,9 @@
;;; rng-maint.el --- commands for RELAX NG maintainers -*- lexical-binding:t -*-
-;; Copyright (C) 2003, 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003, 2007-2024 Free Software Foundation, Inc.
;; Author: James Clark
-;; Keywords: wp, hypermedia, languages, XML, RelaxNG
+;; Keywords: text, hypermedia, languages, XML, RelaxNG
;; This file is part of GNU Emacs.
diff --git a/lisp/nxml/rng-match.el b/lisp/nxml/rng-match.el
index 51c197cd6c6..61e4ffdb1a9 100644
--- a/lisp/nxml/rng-match.el
+++ b/lisp/nxml/rng-match.el
@@ -1,9 +1,9 @@
;;; rng-match.el --- matching of RELAX NG patterns against XML events -*- lexical-binding:t -*-
-;; Copyright (C) 2003, 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003, 2007-2024 Free Software Foundation, Inc.
;; Author: James Clark
-;; Keywords: wp, hypermedia, languages, XML, RelaxNG
+;; Keywords: text, hypermedia, languages, XML, RelaxNG
;; This file is part of GNU Emacs.
diff --git a/lisp/nxml/rng-nxml.el b/lisp/nxml/rng-nxml.el
index fd1f4fb904e..af16e7ae50b 100644
--- a/lisp/nxml/rng-nxml.el
+++ b/lisp/nxml/rng-nxml.el
@@ -1,9 +1,9 @@
;;; rng-nxml.el --- make nxml-mode take advantage of rng-validate-mode -*- lexical-binding:t -*-
-;; Copyright (C) 2003, 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003, 2007-2024 Free Software Foundation, Inc.
;; Author: James Clark
-;; Keywords: wp, hypermedia, languages, XML, RelaxNG
+;; Keywords: text, hypermedia, languages, XML, RelaxNG
;; This file is part of GNU Emacs.
diff --git a/lisp/nxml/rng-parse.el b/lisp/nxml/rng-parse.el
index 1728de7aadd..cb49f4f69e3 100644
--- a/lisp/nxml/rng-parse.el
+++ b/lisp/nxml/rng-parse.el
@@ -1,9 +1,9 @@
;;; rng-parse.el --- parse an XML file and validate it against a schema -*- lexical-binding:t -*-
-;; Copyright (C) 2003, 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003, 2007-2024 Free Software Foundation, Inc.
;; Author: James Clark
-;; Keywords: wp, hypermedia, languages, XML, RelaxNG
+;; Keywords: text, hypermedia, languages, XML, RelaxNG
;; This file is part of GNU Emacs.
diff --git a/lisp/nxml/rng-pttrn.el b/lisp/nxml/rng-pttrn.el
index f37ace7f734..996e9ca0929 100644
--- a/lisp/nxml/rng-pttrn.el
+++ b/lisp/nxml/rng-pttrn.el
@@ -1,9 +1,9 @@
;;; rng-pttrn.el --- RELAX NG patterns -*- lexical-binding:t -*-
-;; Copyright (C) 2003, 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003, 2007-2024 Free Software Foundation, Inc.
;; Author: James Clark
-;; Keywords: wp, hypermedia, languages, XML, RelaxNG
+;; Keywords: text, hypermedia, languages, XML, RelaxNG
;; This file is part of GNU Emacs.
diff --git a/lisp/nxml/rng-uri.el b/lisp/nxml/rng-uri.el
index 4cfa212990d..587ca226de8 100644
--- a/lisp/nxml/rng-uri.el
+++ b/lisp/nxml/rng-uri.el
@@ -1,9 +1,9 @@
;;; rng-uri.el --- URI parsing and manipulation -*- lexical-binding:t -*-
-;; Copyright (C) 2003, 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003, 2007-2024 Free Software Foundation, Inc.
;; Author: James Clark
-;; Keywords: wp, hypermedia, languages, XML
+;; Keywords: text, hypermedia, languages, XML
;; This file is part of GNU Emacs.
diff --git a/lisp/nxml/rng-util.el b/lisp/nxml/rng-util.el
index 4f49885fc45..f9d47c20347 100644
--- a/lisp/nxml/rng-util.el
+++ b/lisp/nxml/rng-util.el
@@ -1,9 +1,9 @@
;;; rng-util.el --- utility functions for RELAX NG library -*- lexical-binding: t; -*-
-;; Copyright (C) 2003, 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003, 2007-2024 Free Software Foundation, Inc.
;; Author: James Clark
-;; Keywords: wp, hypermedia, languages, XML, RelaxNG
+;; Keywords: text, hypermedia, languages, XML, RelaxNG
;; This file is part of GNU Emacs.
diff --git a/lisp/nxml/rng-valid.el b/lisp/nxml/rng-valid.el
index 898fe204fd4..1c9998345fb 100644
--- a/lisp/nxml/rng-valid.el
+++ b/lisp/nxml/rng-valid.el
@@ -1,9 +1,9 @@
;;; rng-valid.el --- real-time validation of XML using RELAX NG -*- lexical-binding:t -*-
-;; Copyright (C) 2003, 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003, 2007-2024 Free Software Foundation, Inc.
;; Author: James Clark
-;; Keywords: wp, hypermedia, languages, XML, RelaxNG
+;; Keywords: text, hypermedia, languages, XML, RelaxNG
;; This file is part of GNU Emacs.
diff --git a/lisp/nxml/rng-xsd.el b/lisp/nxml/rng-xsd.el
index cd963534402..417e4c7b5bc 100644
--- a/lisp/nxml/rng-xsd.el
+++ b/lisp/nxml/rng-xsd.el
@@ -1,9 +1,9 @@
;;; rng-xsd.el --- W3C XML Schema datatypes library for RELAX NG -*- lexical-binding:t -*-
-;; Copyright (C) 2003, 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003, 2007-2024 Free Software Foundation, Inc.
;; Author: James Clark
-;; Keywords: wp, hypermedia, languages, XML, RelaxNG
+;; Keywords: text, hypermedia, languages, XML, RelaxNG
;; This file is part of GNU Emacs.
diff --git a/lisp/nxml/xmltok.el b/lisp/nxml/xmltok.el
index 78fa91b5cdc..a4816d1b3f7 100644
--- a/lisp/nxml/xmltok.el
+++ b/lisp/nxml/xmltok.el
@@ -1,9 +1,9 @@
;;; xmltok.el --- XML tokenization -*- lexical-binding:t -*-
-;; Copyright (C) 2003, 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003, 2007-2024 Free Software Foundation, Inc.
;; Author: James Clark
-;; Keywords: wp, hypermedia, languages, XML
+;; Keywords: text, hypermedia, languages, XML
;; This file is part of GNU Emacs.
diff --git a/lisp/nxml/xsd-regexp.el b/lisp/nxml/xsd-regexp.el
index 3c33c4c0170..5474ac179d6 100644
--- a/lisp/nxml/xsd-regexp.el
+++ b/lisp/nxml/xsd-regexp.el
@@ -1,9 +1,9 @@
;;; xsd-regexp.el --- translate W3C XML Schema regexps to Emacs regexps -*- lexical-binding:t -*-
-;; Copyright (C) 2003, 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003, 2007-2024 Free Software Foundation, Inc.
;; Author: James Clark
-;; Keywords: wp, hypermedia, languages, XML, regexp
+;; Keywords: text, hypermedia, languages, XML, regexp
;; This file is part of GNU Emacs.
diff --git a/lisp/obarray.el b/lisp/obarray.el
index 485627d51de..a26992df8e2 100644
--- a/lisp/obarray.el
+++ b/lisp/obarray.el
@@ -1,6 +1,6 @@
;;; obarray.el --- obarray functions -*- lexical-binding: t -*-
-;; Copyright (C) 2015-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2024 Free Software Foundation, Inc.
;; Maintainer: emacs-devel@gnu.org
;; Keywords: obarray functions
diff --git a/lisp/obsolete/autoarg.el b/lisp/obsolete/autoarg.el
index cd4628be669..84354c893ab 100644
--- a/lisp/obsolete/autoarg.el
+++ b/lisp/obsolete/autoarg.el
@@ -1,6 +1,6 @@
;;; autoarg.el --- make digit keys supply prefix args -*- lexical-binding: t -*-
-;; Copyright (C) 1998, 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998, 2000-2024 Free Software Foundation, Inc.
;; Author: Dave Love <fx@gnu.org>
;; Created: 1998-09-04
diff --git a/lisp/obsolete/autoload.el b/lisp/obsolete/autoload.el
index ecf931d0881..850ec83e645 100644
--- a/lisp/obsolete/autoload.el
+++ b/lisp/obsolete/autoload.el
@@ -1,6 +1,6 @@
;;; autoload.el --- maintain autoloads in loaddefs.el -*- lexical-binding: t -*-
-;; Copyright (C) 1991-1997, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1991-1997, 2001-2024 Free Software Foundation, Inc.
;; Author: Roland McGrath <roland@gnu.org>
;; Keywords: maint
diff --git a/lisp/obsolete/bruce.el b/lisp/obsolete/bruce.el
index 83f91ab8816..2a44946c7b6 100644
--- a/lisp/obsolete/bruce.el
+++ b/lisp/obsolete/bruce.el
@@ -1,7 +1,7 @@
;;; bruce.el --- bruce phrase utility for overloading the Communications -*- lexical-binding: t; -*-
;;; Decency Act snoops, if any.
-;; Copyright (C) 1988, 1993, 1997, 2001-2023 Free Software Foundation,
+;; Copyright (C) 1988, 1993, 1997, 2001-2024 Free Software Foundation,
;; Inc.
;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/obsolete/cc-compat.el b/lisp/obsolete/cc-compat.el
index 33330623739..b3643f888e4 100644
--- a/lisp/obsolete/cc-compat.el
+++ b/lisp/obsolete/cc-compat.el
@@ -1,6 +1,6 @@
;;; cc-compat.el --- cc-mode compatibility with c-mode.el confusion -*- lexical-binding: t; -*-
-;; Copyright (C) 1985, 1987, 1992-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1985, 1987, 1992-2024 Free Software Foundation, Inc.
;; Authors: 1998- Martin Stjernholm
;; 1994-1999 Barry A. Warsaw
diff --git a/lisp/obsolete/cl-compat.el b/lisp/obsolete/cl-compat.el
index 255c3dc8277..606f8da3748 100644
--- a/lisp/obsolete/cl-compat.el
+++ b/lisp/obsolete/cl-compat.el
@@ -1,6 +1,6 @@
;;; cl-compat.el --- Common Lisp extensions for GNU Emacs Lisp (compatibility) -*- lexical-binding: t; -*-
-;; Copyright (C) 1993, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1993, 2001-2024 Free Software Foundation, Inc.
;; Author: Dave Gillespie <daveg@synaptics.com>
;; Version: 2.02
diff --git a/lisp/obsolete/cl.el b/lisp/obsolete/cl.el
index 1b86ed259f7..bb8139e2fb3 100644
--- a/lisp/obsolete/cl.el
+++ b/lisp/obsolete/cl.el
@@ -1,6 +1,6 @@
;;; cl.el --- Compatibility aliases for the old CL library. -*- lexical-binding: t -*-
-;; Copyright (C) 2012-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2012-2024 Free Software Foundation, Inc.
;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
;; Deprecated-since: 27.1
diff --git a/lisp/obsolete/crisp.el b/lisp/obsolete/crisp.el
index c7e3919cdba..3a3a44f850f 100644
--- a/lisp/obsolete/crisp.el
+++ b/lisp/obsolete/crisp.el
@@ -1,6 +1,6 @@
;;; crisp.el --- CRiSP/Brief Emacs emulator -*- lexical-binding: t; -*-
-;; Copyright (C) 1997-1999, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997-1999, 2001-2024 Free Software Foundation, Inc.
;; Author: Gary D. Foster <Gary.Foster@Corp.Sun.COM>
;; Keywords: emulations brief crisp
diff --git a/lisp/obsolete/eieio-compat.el b/lisp/obsolete/eieio-compat.el
index bb3d5ccb49c..26648a4d7bb 100644
--- a/lisp/obsolete/eieio-compat.el
+++ b/lisp/obsolete/eieio-compat.el
@@ -1,6 +1,6 @@
;;; eieio-compat.el --- Compatibility with Older EIEIO versions -*- lexical-binding:t -*-
-;; Copyright (C) 1995-1996, 1998-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1995-1996, 1998-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
;; Keywords: OO, lisp
diff --git a/lisp/obsolete/eudcb-ph.el b/lisp/obsolete/eudcb-ph.el
index 356987afebf..fd3d3821989 100644
--- a/lisp/obsolete/eudcb-ph.el
+++ b/lisp/obsolete/eudcb-ph.el
@@ -1,6 +1,6 @@
;;; eudcb-ph.el --- Emacs Unified Directory Client - CCSO PH/QI Backend -*- lexical-binding: t; -*-
-;; Copyright (C) 1998-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-2024 Free Software Foundation, Inc.
;; Author: Oscar Figueiredo <oscar@cpe.fr>
;; Pavel Janík <Pavel@Janik.cz>
diff --git a/lisp/obsolete/gs.el b/lisp/obsolete/gs.el
index 07623acddc9..516468058f2 100644
--- a/lisp/obsolete/gs.el
+++ b/lisp/obsolete/gs.el
@@ -1,6 +1,6 @@
;;; gs.el --- interface to Ghostscript -*- lexical-binding: t; -*-
-;; Copyright (C) 1998, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998, 2001-2024 Free Software Foundation, Inc.
;; Maintainer: emacs-devel@gnu.org
;; Keywords: internal
diff --git a/lisp/obsolete/gulp.el b/lisp/obsolete/gulp.el
index 0263c67df9e..03c005f498b 100644
--- a/lisp/obsolete/gulp.el
+++ b/lisp/obsolete/gulp.el
@@ -1,6 +1,6 @@
;;; gulp.el --- ask for updates for Lisp packages -*- lexical-binding: t; -*-
-;; Copyright (C) 1996, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996, 2001-2024 Free Software Foundation, Inc.
;; Author: Sam Shteingold <shteingd@math.ucla.edu>
;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/obsolete/html2text.el b/lisp/obsolete/html2text.el
index 42ec65bc194..ffe70bc9b9a 100644
--- a/lisp/obsolete/html2text.el
+++ b/lisp/obsolete/html2text.el
@@ -1,6 +1,6 @@
;;; html2text.el --- a simple html to plain text converter -*- lexical-binding: t; -*-
-;; Copyright (C) 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2024 Free Software Foundation, Inc.
;; Author: Joakim Hove <hove@phys.ntnu.no>
;; Obsolete-since: 26.1
diff --git a/lisp/obsolete/info-edit.el b/lisp/obsolete/info-edit.el
index 5b9bb4c253e..fb6de736590 100644
--- a/lisp/obsolete/info-edit.el
+++ b/lisp/obsolete/info-edit.el
@@ -1,6 +1,6 @@
;;; info-edit.el --- Editing info files -*- lexical-binding:t -*-
-;; Copyright (C) 1985-1986, 1992-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1985-1986, 1992-2024 Free Software Foundation, Inc.
;; Maintainer: emacs-devel@gnu.org
;; Keywords: help
diff --git a/lisp/obsolete/inversion.el b/lisp/obsolete/inversion.el
index 03094825ecd..21e6ffd6275 100644
--- a/lisp/obsolete/inversion.el
+++ b/lisp/obsolete/inversion.el
@@ -1,6 +1,6 @@
;;; inversion.el --- When you need something in version XX.XX -*- lexical-binding: t; -*-
-;; Copyright (C) 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
;; Version: 1.3
diff --git a/lisp/obsolete/iswitchb.el b/lisp/obsolete/iswitchb.el
index 59e6c0403a2..3f05b7fe7ac 100644
--- a/lisp/obsolete/iswitchb.el
+++ b/lisp/obsolete/iswitchb.el
@@ -1,6 +1,6 @@
;;; iswitchb.el --- switch between buffers using substrings -*- lexical-binding: t; -*-
-;; Copyright (C) 1996-1997, 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-1997, 2000-2024 Free Software Foundation, Inc.
;; Author: Stephen Eglen <stephen@gnu.org>
;; Keywords: completion convenience
diff --git a/lisp/obsolete/landmark.el b/lisp/obsolete/landmark.el
index 57ca28e6d1d..0a67bba8028 100644
--- a/lisp/obsolete/landmark.el
+++ b/lisp/obsolete/landmark.el
@@ -1,6 +1,6 @@
;;; landmark.el --- Neural-network robot that learns landmarks -*- lexical-binding:t -*-
-;; Copyright (C) 1996-1997, 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-1997, 2000-2024 Free Software Foundation, Inc.
;; Author: Terrence Brannon <metaperl@gmail.com>
;; Created: December 16, 1996 - first release to usenet
@@ -549,10 +549,10 @@ along the DX, DY direction, considering that DVAL has been added on SQUARE."
;;; GAME CONTROL.
;;;
-;; Several variables are used to monitor a game, including a GAME-HISTORY (the
-;; list of all (SQUARE . PREVSCORE) played) that allows to take moves back
-;; (anti-updating the score table) and to compute the table from scratch in
-;; case of an interruption.
+;; Several variables are used to monitor a game, including a
+;; GAME-HISTORY (the list of all (SQUARE . PREVSCORE) played) that
+;; enables rescinding moves (anti-updating the score table) and to
+;; compute the table from scratch in case of an interruption.
(defvar landmark-game-in-progress nil
"Non-nil if a game is in progress.")
diff --git a/lisp/obsolete/linum.el b/lisp/obsolete/linum.el
index 017afe10c1a..1f46957caa6 100644
--- a/lisp/obsolete/linum.el
+++ b/lisp/obsolete/linum.el
@@ -1,6 +1,6 @@
;;; linum.el --- display line numbers in the left margin -*- lexical-binding: t -*-
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
;; Author: Markus Triska <markus.triska@gmx.at>
;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/obsolete/longlines.el b/lisp/obsolete/longlines.el
index 0f9f73d044b..6aa388805f2 100644
--- a/lisp/obsolete/longlines.el
+++ b/lisp/obsolete/longlines.el
@@ -1,13 +1,13 @@
;;; longlines.el --- automatically wrap long lines -*- lexical-binding: t; -*-
-;; Copyright (C) 2000-2001, 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2000-2001, 2004-2024 Free Software Foundation, Inc.
;; Authors: Kai Grossjohann <Kai.Grossjohann@CS.Uni-Dortmund.DE>
;; Alex Schroeder <alex@gnu.org>
;; Chong Yidong <cyd@stupidchicken.com>
;; Maintainer: emacs-devel@gnu.org
;; Obsolete-since: 24.4
-;; Keywords: convenience, wp
+;; Keywords: convenience, text
;; This file is part of GNU Emacs.
diff --git a/lisp/obsolete/makesum.el b/lisp/obsolete/makesum.el
index 69f1820eaba..85bd5c8f99d 100644
--- a/lisp/obsolete/makesum.el
+++ b/lisp/obsolete/makesum.el
@@ -1,6 +1,6 @@
;;; makesum.el --- generate key binding summary for Emacs -*- lexical-binding:t -*-
-;; Copyright (C) 1985, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1985, 2001-2024 Free Software Foundation, Inc.
;; Maintainer: emacs-devel@gnu.org
;; Keywords: help
diff --git a/lisp/obsolete/mantemp.el b/lisp/obsolete/mantemp.el
index 9fd6c91cc4e..32d7f81cf60 100644
--- a/lisp/obsolete/mantemp.el
+++ b/lisp/obsolete/mantemp.el
@@ -1,6 +1,6 @@
;;; mantemp.el --- create manual template instantiations from g++ 2.7.2 output -*- lexical-binding: t; -*-
-;; Copyright (C) 1996, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996, 2001-2024 Free Software Foundation, Inc.
;; Author: Tom Houlder <thoulder@icor.fr>
;; Created: 10 Dec 1996
diff --git a/lisp/obsolete/messcompat.el b/lisp/obsolete/messcompat.el
index a7d40e43f50..b30794c0eae 100644
--- a/lisp/obsolete/messcompat.el
+++ b/lisp/obsolete/messcompat.el
@@ -1,6 +1,6 @@
;;; messcompat.el --- making message mode compatible with mail mode -*- lexical-binding: t; -*-
-;; Copyright (C) 1996-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-2024 Free Software Foundation, Inc.
;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
;; Keywords: mail, news
diff --git a/lisp/obsolete/metamail.el b/lisp/obsolete/metamail.el
index 561c0dc4ebd..8e3000e7268 100644
--- a/lisp/obsolete/metamail.el
+++ b/lisp/obsolete/metamail.el
@@ -1,6 +1,6 @@
;;; metamail.el --- Metamail interface for GNU Emacs -*- lexical-binding: t; -*-
-;; Copyright (C) 1993, 1996, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1993, 1996, 2001-2024 Free Software Foundation, Inc.
;; Author: Masanobu UMEDA <umerin@mse.kyutech.ac.jp>
;; Keywords: mail, news, mime, multimedia
diff --git a/lisp/obsolete/mh-compat.el b/lisp/obsolete/mh-compat.el
index e45263bfd9f..ca72bf3b22d 100644
--- a/lisp/obsolete/mh-compat.el
+++ b/lisp/obsolete/mh-compat.el
@@ -1,6 +1,6 @@
;;; mh-compat.el --- make MH-E compatible with various versions of Emacs -*- lexical-binding: t; -*-
-;; Copyright (C) 2006-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2006-2024 Free Software Foundation, Inc.
;; Author: Bill Wohler <wohler@newt.com>
;; Keywords: mail
diff --git a/lisp/obsolete/netrc.el b/lisp/obsolete/netrc.el
index 07f7fb94833..dc856612e30 100644
--- a/lisp/obsolete/netrc.el
+++ b/lisp/obsolete/netrc.el
@@ -1,6 +1,6 @@
;;; netrc.el --- .netrc parsing functionality -*- lexical-binding: t -*-
-;; Copyright (C) 1996-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-2024 Free Software Foundation, Inc.
;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
;; Keywords: news
diff --git a/lisp/obsolete/nnir.el b/lisp/obsolete/nnir.el
index a3c61490154..dbcc3eaffec 100644
--- a/lisp/obsolete/nnir.el
+++ b/lisp/obsolete/nnir.el
@@ -1,6 +1,6 @@
;;; nnir.el --- Search mail with various search engines -*- lexical-binding:t -*-
-;; Copyright (C) 1998-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-2024 Free Software Foundation, Inc.
;; Author: Kai Großjohann <grossjohann@ls6.cs.uni-dortmund.de>
;; Swish-e and Swish++ backends by:
diff --git a/lisp/obsolete/otodo-mode.el b/lisp/obsolete/otodo-mode.el
index 0077088a20b..deca885b44b 100644
--- a/lisp/obsolete/otodo-mode.el
+++ b/lisp/obsolete/otodo-mode.el
@@ -1,6 +1,6 @@
;;; otodo-mode.el --- major mode for editing TODO list files -*- lexical-binding: t; -*-
-;; Copyright (C) 1997, 1999, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997, 1999, 2001-2024 Free Software Foundation, Inc.
;; Author: Oliver Seidel <privat@os10000.net>
;; Maintainer: Stephen Berman <stephen.berman@gmx.net>
diff --git a/lisp/obsolete/pgg-def.el b/lisp/obsolete/pgg-def.el
index 62f5368a730..8cf571ab274 100644
--- a/lisp/obsolete/pgg-def.el
+++ b/lisp/obsolete/pgg-def.el
@@ -1,6 +1,6 @@
;;; pgg-def.el --- functions/macros for defining PGG functions -*- lexical-binding: t; -*-
-;; Copyright (C) 1999, 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999, 2002-2024 Free Software Foundation, Inc.
;; Author: Daiki Ueno <ueno@unixuser.org>
;; Created: 1999/11/02
diff --git a/lisp/obsolete/pgg-gpg.el b/lisp/obsolete/pgg-gpg.el
index 6af59c8e3e5..586fa67a8e8 100644
--- a/lisp/obsolete/pgg-gpg.el
+++ b/lisp/obsolete/pgg-gpg.el
@@ -1,6 +1,6 @@
;;; pgg-gpg.el --- GnuPG support for PGG. -*- lexical-binding: t; -*-
-;; Copyright (C) 1999-2000, 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2000, 2002-2024 Free Software Foundation, Inc.
;; Author: Daiki Ueno <ueno@unixuser.org>
;; Symmetric encryption and gpg-agent support added by:
diff --git a/lisp/obsolete/pgg-parse.el b/lisp/obsolete/pgg-parse.el
index ca713203b47..0b45eb27279 100644
--- a/lisp/obsolete/pgg-parse.el
+++ b/lisp/obsolete/pgg-parse.el
@@ -1,6 +1,6 @@
;;; pgg-parse.el --- OpenPGP packet parsing -*- lexical-binding: t; -*-
-;; Copyright (C) 1999, 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999, 2002-2024 Free Software Foundation, Inc.
;; Author: Daiki Ueno <ueno@unixuser.org>
;; Created: 1999/10/28
diff --git a/lisp/obsolete/pgg-pgp.el b/lisp/obsolete/pgg-pgp.el
index e000e7ead59..76261957e18 100644
--- a/lisp/obsolete/pgg-pgp.el
+++ b/lisp/obsolete/pgg-pgp.el
@@ -1,6 +1,6 @@
;;; pgg-pgp.el --- PGP 2.* and 6.* support for PGG. -*- lexical-binding: t; -*-
-;; Copyright (C) 1999-2000, 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2000, 2002-2024 Free Software Foundation, Inc.
;; Author: Daiki Ueno <ueno@unixuser.org>
;; Created: 1999/11/02
diff --git a/lisp/obsolete/pgg-pgp5.el b/lisp/obsolete/pgg-pgp5.el
index 8871ab3f9e0..09e273a49d0 100644
--- a/lisp/obsolete/pgg-pgp5.el
+++ b/lisp/obsolete/pgg-pgp5.el
@@ -1,6 +1,6 @@
;;; pgg-pgp5.el --- PGP 5.* support for PGG. -*- lexical-binding: t; -*-
-;; Copyright (C) 1999-2000, 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2000, 2002-2024 Free Software Foundation, Inc.
;; Author: Daiki Ueno <ueno@unixuser.org>
;; Created: 1999/11/02
diff --git a/lisp/obsolete/pgg.el b/lisp/obsolete/pgg.el
index f2196c1b8eb..6c00ad201f1 100644
--- a/lisp/obsolete/pgg.el
+++ b/lisp/obsolete/pgg.el
@@ -1,6 +1,6 @@
;;; pgg.el --- glue for the various PGP implementations. -*- lexical-binding: t; -*-
-;; Copyright (C) 1999-2000, 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2000, 2002-2024 Free Software Foundation, Inc.
;; Author: Daiki Ueno <ueno@unixuser.org>
;; Symmetric encryption added by: Sascha Wilde <wilde@sha-bang.de>
diff --git a/lisp/obsolete/ps-def.el b/lisp/obsolete/ps-def.el
index 222f5622b7f..641845d2b95 100644
--- a/lisp/obsolete/ps-def.el
+++ b/lisp/obsolete/ps-def.el
@@ -1,10 +1,10 @@
;;; ps-def.el --- Emacs definitions for ps-print -*- lexical-binding: t -*-
-;; Copyright (C) 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2024 Free Software Foundation, Inc.
;; Author: Vinicius Jose Latorre <viniciusjl.gnu@gmail.com>
;; Kenichi Handa <handa@gnu.org> (multi-byte characters)
-;; Keywords: wp, print, PostScript
+;; Keywords: text, print, PostScript
;; URL: https://www.emacswiki.org/cgi-bin/wiki/ViniciusJoseLatorre
;; Package: ps-print
;; Obsolete-since: 29.1
diff --git a/lisp/obsolete/quickurl.el b/lisp/obsolete/quickurl.el
index 65a4c06e163..7393bebdce1 100644
--- a/lisp/obsolete/quickurl.el
+++ b/lisp/obsolete/quickurl.el
@@ -1,6 +1,6 @@
;;; quickurl.el --- insert a URL based on text at point in buffer -*- lexical-binding: t; -*-
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
;; Author: Dave Pearson <davep@davep.org>
;; Created: 1999-05-28
diff --git a/lisp/obsolete/rcompile.el b/lisp/obsolete/rcompile.el
index d9f498a313b..e0826475e32 100644
--- a/lisp/obsolete/rcompile.el
+++ b/lisp/obsolete/rcompile.el
@@ -1,6 +1,6 @@
;;; rcompile.el --- run a compilation on a remote machine -*- lexical-binding: t; -*-
-;; Copyright (C) 1993-1994, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1993-1994, 2001-2024 Free Software Foundation, Inc.
;; Author: Alon Albert <alon@milcse.rtsg.mot.com>
;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/obsolete/rfc2368.el b/lisp/obsolete/rfc2368.el
index 77a1a6d910f..ddfb14d5e08 100644
--- a/lisp/obsolete/rfc2368.el
+++ b/lisp/obsolete/rfc2368.el
@@ -1,6 +1,6 @@
;;; rfc2368.el --- support for rfc2368 -*- lexical-binding:t -*-
-;; Copyright (C) 1998, 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998, 2000-2024 Free Software Foundation, Inc.
;; Author: Sen Nagata <sen@eccosys.com>
;; Keywords: mail
diff --git a/lisp/obsolete/rlogin.el b/lisp/obsolete/rlogin.el
index 1afa50cb0ff..f285165ba21 100644
--- a/lisp/obsolete/rlogin.el
+++ b/lisp/obsolete/rlogin.el
@@ -1,6 +1,6 @@
;;; rlogin.el --- remote login interface -*- lexical-binding:t -*-
-;; Copyright (C) 1992-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1992-2024 Free Software Foundation, Inc.
;; Author: Noah Friedman <friedman@splode.com>
;; Keywords: unix, comm
diff --git a/lisp/obsolete/sb-image.el b/lisp/obsolete/sb-image.el
index 28926ac5d61..d65ea502685 100644
--- a/lisp/obsolete/sb-image.el
+++ b/lisp/obsolete/sb-image.el
@@ -1,6 +1,6 @@
;;; sb-image.el --- Image management for speedbar -*- lexical-binding: t; -*-
-;; Copyright (C) 1999-2003, 2005-2019, 2021-2023 Free Software
+;; Copyright (C) 1999-2003, 2005-2019, 2021-2024 Free Software
;; Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/lisp/obsolete/starttls.el b/lisp/obsolete/starttls.el
index bbf70df82a4..dab65bbef87 100644
--- a/lisp/obsolete/starttls.el
+++ b/lisp/obsolete/starttls.el
@@ -1,6 +1,6 @@
;;; starttls.el --- STARTTLS functions -*- lexical-binding: t; -*-
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
;; Author: Daiki Ueno <ueno@unixuser.org>
;; Author: Simon Josefsson <simon@josefsson.org>
diff --git a/lisp/obsolete/sup-mouse.el b/lisp/obsolete/sup-mouse.el
index 96a9d28f379..e7bb58950a0 100644
--- a/lisp/obsolete/sup-mouse.el
+++ b/lisp/obsolete/sup-mouse.el
@@ -1,6 +1,6 @@
;;; sup-mouse.el --- supdup mouse support for lisp machines -*- lexical-binding: t; -*-
-;; Copyright (C) 1985-1986, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1985-1986, 2001-2024 Free Software Foundation, Inc.
;; Author: Wolfgang Rupprecht
;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/obsolete/terminal.el b/lisp/obsolete/terminal.el
index 4e23fc3c710..13667589c9e 100644
--- a/lisp/obsolete/terminal.el
+++ b/lisp/obsolete/terminal.el
@@ -1,6 +1,6 @@
;;; terminal.el --- terminal emulator for GNU Emacs -*- lexical-binding: t; -*-
-;; Copyright (C) 1986-1989, 1993-1994, 2001-2023 Free Software
+;; Copyright (C) 1986-1989, 1993-1994, 2001-2024 Free Software
;; Foundation, Inc.
;; Author: Richard Mlynarik <mly@eddie.mit.edu>
@@ -1154,7 +1154,7 @@ subprocess started."
(defun te-parse-program-and-args (s)
- (cond ((string-match "\\`\\([-a-zA-Z0-9+=_.@/:]+[ \t]*\\)+\\'" s)
+ (cond ((string-match "\\`[-a-zA-Z0-9+=_.@/:][-a-zA-Z0-9+=_.@/: \t]*\\'" s)
(let ((l ()) (p 0))
(while p
(setq l (cons (if (string-match
diff --git a/lisp/obsolete/thumbs.el b/lisp/obsolete/thumbs.el
index ddf734f22ea..781e91c471c 100644
--- a/lisp/obsolete/thumbs.el
+++ b/lisp/obsolete/thumbs.el
@@ -1,6 +1,6 @@
;;; thumbs.el --- Thumbnails previewer for images files -*- lexical-binding: t -*-
-;; Copyright (C) 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2004-2024 Free Software Foundation, Inc.
;; Author: Jean-Philippe Theberge <jphiltheberge@videotron.ca>
;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/obsolete/tls.el b/lisp/obsolete/tls.el
index 9089684cd52..447b0691afd 100644
--- a/lisp/obsolete/tls.el
+++ b/lisp/obsolete/tls.el
@@ -1,6 +1,6 @@
;;; tls.el --- TLS/SSL support via wrapper around GnuTLS -*- lexical-binding: t; -*-
-;; Copyright (C) 1996-1999, 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-1999, 2002-2024 Free Software Foundation, Inc.
;; Author: Simon Josefsson <simon@josefsson.org>
;; Keywords: comm, tls, gnutls, ssl
diff --git a/lisp/obsolete/tpu-edt.el b/lisp/obsolete/tpu-edt.el
index 4c8beb7dcff..62431662baa 100644
--- a/lisp/obsolete/tpu-edt.el
+++ b/lisp/obsolete/tpu-edt.el
@@ -1,6 +1,6 @@
;;; tpu-edt.el --- Emacs emulating TPU emulating EDT -*- lexical-binding: t; -*-
-;; Copyright (C) 1993-1995, 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1993-1995, 2000-2024 Free Software Foundation, Inc.
;; Author: Rob Riepel <riepel@networking.stanford.edu>
;; Version: 4.5
diff --git a/lisp/obsolete/tpu-extras.el b/lisp/obsolete/tpu-extras.el
index f3b91ba878a..801a20d3550 100644
--- a/lisp/obsolete/tpu-extras.el
+++ b/lisp/obsolete/tpu-extras.el
@@ -1,6 +1,6 @@
;;; tpu-extras.el --- scroll margins and free cursor mode for TPU-edt -*- lexical-binding: t; -*-
-;; Copyright (C) 1993-1995, 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1993-1995, 2000-2024 Free Software Foundation, Inc.
;; Author: Rob Riepel <riepel@networking.stanford.edu>
;; Keywords: emulations
diff --git a/lisp/obsolete/tpu-mapper.el b/lisp/obsolete/tpu-mapper.el
index 2c9836cc2ee..ed5608a7222 100644
--- a/lisp/obsolete/tpu-mapper.el
+++ b/lisp/obsolete/tpu-mapper.el
@@ -1,6 +1,6 @@
;;; tpu-mapper.el --- create a TPU-edt X-windows keymap file -*- lexical-binding: t; -*-
-;; Copyright (C) 1993-1995, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1993-1995, 2001-2024 Free Software Foundation, Inc.
;; Author: Rob Riepel <riepel@networking.stanford.edu>
;; Keywords: emulations
diff --git a/lisp/obsolete/uce.el b/lisp/obsolete/uce.el
index 58036cc6e01..85e25cb7558 100644
--- a/lisp/obsolete/uce.el
+++ b/lisp/obsolete/uce.el
@@ -1,6 +1,6 @@
;;; uce.el --- facilitate reply to unsolicited commercial email -*- lexical-binding: t; -*-
-;; Copyright (C) 1996, 1998, 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996, 1998, 2000-2024 Free Software Foundation, Inc.
;; Author: stanislav shalunov <shalunov@mccme.ru>
;; Created: 10 Dec 1996
diff --git a/lisp/obsolete/url-about.el b/lisp/obsolete/url-about.el
index fe1c51cc10c..b9de3a8674d 100644
--- a/lisp/obsolete/url-about.el
+++ b/lisp/obsolete/url-about.el
@@ -1,6 +1,6 @@
;;; url-about.el --- Show internal URLs -*- lexical-binding: t; -*-
-;; Copyright (C) 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2024 Free Software Foundation, Inc.
;; Keywords: comm, data, processes, hypermedia
;; Obsolete-since: 29.1
diff --git a/lisp/obsolete/url-dired.el b/lisp/obsolete/url-dired.el
index 98af8e236e4..6004ebeb0d2 100644
--- a/lisp/obsolete/url-dired.el
+++ b/lisp/obsolete/url-dired.el
@@ -1,6 +1,6 @@
;;; url-dired.el --- URL Dired minor mode -*- lexical-binding: t -*-
-;; Copyright (C) 1996-1999, 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-1999, 2004-2024 Free Software Foundation, Inc.
;; Keywords: comm, files
;; Obsolete-since: 29.1
diff --git a/lisp/obsolete/url-ns.el b/lisp/obsolete/url-ns.el
index 20318867634..41aaa5b63be 100644
--- a/lisp/obsolete/url-ns.el
+++ b/lisp/obsolete/url-ns.el
@@ -1,6 +1,6 @@
;;; url-ns.el --- Various netscape-ish functions for proxy definitions -*- lexical-binding: t; -*-
-;; Copyright (C) 1997-1999, 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997-1999, 2004-2024 Free Software Foundation, Inc.
;; Keywords: comm, data, processes, hypermedia
;; Obsolete-since: 27.1
@@ -39,13 +39,14 @@
;;;###autoload
(defun dnsResolve (host)
- (url-gateway-nslookup-host host))
+ (with-suppressed-warnings ((obsolete url-gateway-nslookup-host))
+ (url-gateway-nslookup-host host)))
;;;###autoload
(defun isResolvable (host)
(if (string-match "^[0-9.]+$" host)
t
- (not (string= host (url-gateway-nslookup-host host)))))
+ (not (string= host (dnsResolve host)))))
;;;###autoload
(defun isInNet (ip net mask)
diff --git a/lisp/obsolete/vc-arch.el b/lisp/obsolete/vc-arch.el
index 0b74d48d27d..7cb31951502 100644
--- a/lisp/obsolete/vc-arch.el
+++ b/lisp/obsolete/vc-arch.el
@@ -1,6 +1,6 @@
;;; vc-arch.el --- VC backend for the Arch version-control system -*- lexical-binding: t -*-
-;; Copyright (C) 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2004-2024 Free Software Foundation, Inc.
;; Author: FSF (see vc.el for full credits)
;; Maintainer: Stefan Monnier <monnier@gnu.org>
diff --git a/lisp/obsolete/vc-mtn.el b/lisp/obsolete/vc-mtn.el
index e1c96b5511b..a185d58ac1d 100644
--- a/lisp/obsolete/vc-mtn.el
+++ b/lisp/obsolete/vc-mtn.el
@@ -1,6 +1,6 @@
;;; vc-mtn.el --- VC backend for Monotone -*- lexical-binding: t -*-
-;; Copyright (C) 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2024 Free Software Foundation, Inc.
;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
;; Keywords: vc
diff --git a/lisp/obsolete/vip.el b/lisp/obsolete/vip.el
index 5b19f916c57..eecedbd5e74 100644
--- a/lisp/obsolete/vip.el
+++ b/lisp/obsolete/vip.el
@@ -1,6 +1,6 @@
;;; vip.el --- a VI Package for GNU Emacs -*- lexical-binding: t; -*-
-;; Copyright (C) 1986-1988, 1992-1993, 1998, 2001-2023 Free Software
+;; Copyright (C) 1986-1988, 1992-1993, 1998, 2001-2024 Free Software
;; Foundation, Inc.
;; Author: Masahiko Sato <ms@sail.stanford.edu>
diff --git a/lisp/obsolete/vt-control.el b/lisp/obsolete/vt-control.el
index 179c03596b2..45fa8b04e4d 100644
--- a/lisp/obsolete/vt-control.el
+++ b/lisp/obsolete/vt-control.el
@@ -1,6 +1,6 @@
;;; vt-control.el --- Common VTxxx control functions -*- lexical-binding:t -*-
-;; Copyright (C) 1993-1994, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1993-1994, 2001-2024 Free Software Foundation, Inc.
;; Author: Rob Riepel <riepel@networking.stanford.edu>
;; Keywords: terminals
diff --git a/lisp/obsolete/vt100-led.el b/lisp/obsolete/vt100-led.el
index cfdd07b513f..8762b2ded80 100644
--- a/lisp/obsolete/vt100-led.el
+++ b/lisp/obsolete/vt100-led.el
@@ -1,6 +1,6 @@
;;; vt100-led.el --- functions for LED control on VT-100 terminals & clones -*- lexical-binding:t -*-
-;; Copyright (C) 1988, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1988, 2001-2024 Free Software Foundation, Inc.
;; Author: Howard Gayle
;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/obsolete/ws-mode.el b/lisp/obsolete/ws-mode.el
index d41fd8ffc36..d8ee63c8a01 100644
--- a/lisp/obsolete/ws-mode.el
+++ b/lisp/obsolete/ws-mode.el
@@ -1,6 +1,6 @@
;;; ws-mode.el --- WordStar emulation mode for GNU Emacs -*- lexical-binding: t -*-
-;; Copyright (C) 1991, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1991, 2001-2024 Free Software Foundation, Inc.
;; Author: Juergen Nickelsen <nickel@cs.tu-berlin.de>
;; Version: 0.7
diff --git a/lisp/obsolete/yow.el b/lisp/obsolete/yow.el
index 59ae9a6263b..eb4c65c4084 100644
--- a/lisp/obsolete/yow.el
+++ b/lisp/obsolete/yow.el
@@ -1,6 +1,6 @@
;;; yow.el --- quote random zippyisms -*- lexical-binding: t; -*-
-;; Copyright (C) 1993-1995, 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1993-1995, 2000-2024 Free Software Foundation, Inc.
;; Author: Richard Mlynarik
;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/org/ChangeLog.1 b/lisp/org/ChangeLog.1
index a4eae350d98..74a62e00855 100644
--- a/lisp/org/ChangeLog.1
+++ b/lisp/org/ChangeLog.1
@@ -12523,7 +12523,7 @@
2012-01-03 Carsten Dominik <carsten.dominik@gmail.com> (tiny change)
* org-clock.el (org-clock-in, org-clock-find-position):
- Remove erraneous space in regexp.
+ Remove erroneous space in regexp.
2012-01-03 Eric Schulte <eric.schulte@gmx.com>
@@ -12700,7 +12700,7 @@
2012-01-03 Carsten Dominik <carsten.dominik@gmail.com> (tiny change)
* org-clock.el (org-clock-in, org-clock-find-position):
- Remove erraneous space in regexp.
+ Remove erroneous space in regexp.
2012-01-03 Jambunathan K <kjambunathan@gmail.com>
@@ -14573,7 +14573,7 @@
2012-01-03 Nicolas Goaziou <n.goaziou@gmail.com>
- * org-footnote.el (org-footnote-at-definition-p): Re-use
+ * org-footnote.el (org-footnote-at-definition-p): Reuse
`org-footnote-definition-re'.
2012-01-03 Nicolas Goaziou <n.goaziou@gmail.com>
@@ -18471,7 +18471,7 @@
* org-list.el (org-in-item-p): When point was just after
org-list-end-re, check wouldn't be done for starting line. So, if
- the first line was an item, it wouln't be noticed and function
+ the first line was an item, it wouldn't be noticed and function
would return nil. Simplify and comment code.
2011-07-28 Nicolas Goaziou <n.goaziou@gmail.com>
@@ -19554,7 +19554,7 @@
2011-07-28 Julien Danjou <julien@danjou.info>
- * org-agenda.el (org-format-agenda-item): Simplify time comuting.
+ * org-agenda.el (org-format-agenda-item): Simplify time computing.
2011-07-28 Nicolas Goaziou <n.goaziou@gmail.com>
@@ -22539,7 +22539,7 @@
2010-11-11 Dan Davison <davison@stats.ox.ac.uk>
- * org-src.el (org-src-font-lock-fontify-block): Re-use hidden
+ * org-src.el (org-src-font-lock-fontify-block): Reuse hidden
language major mode buffers during fontification.
2010-11-11 Dan Davison <davison@stats.ox.ac.uk>
@@ -25932,7 +25932,7 @@
* org-latex.el (org-export-as-latex): Do nit require the buffer to
be visiting a file when only exporting to a buffer or string.
- (org-export-latex-fix-inputenc): Only save the buffer is there is
+ (org-export-latex-fix-inputenc): Only save the buffer if there is
a file name attached to it.
2010-04-10 Dan Davison <davison@stats.ox.ac.uk>
@@ -26729,7 +26729,7 @@
2009-11-20 Eric Schulte <schulte.eric@gmail.com>
* org-exp-blocks.el (org-export-blocks-format-ditaa): Use sha1
- hash keys to cache and re-use images generated by the
+ hash keys to cache and reuse images generated by the
org-exp-blocks interface to ditaa and dot.
* org.el (org-format-latex): Latex images are now saved to files
@@ -29300,7 +29300,7 @@
statistics.
(org-hierarchical-checkbox-statistics): New option.
- * org.el (org-cycle): Remove erraneous space character.
+ * org.el (org-cycle): Remove erroneous space character.
* org-icalendar.el (org-icalendar-timezone): Initialize from
environment.
@@ -32833,7 +32833,7 @@
;; add-log-time-zone-rule: t
;; End:
- Copyright (C) 2008-2023 Free Software Foundation, Inc.
+ Copyright (C) 2008-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/lisp/org/ob-C.el b/lisp/org/ob-C.el
index 7763c4c07c1..1a25306570e 100644
--- a/lisp/org/ob-C.el
+++ b/lisp/org/ob-C.el
@@ -1,6 +1,6 @@
;;; ob-C.el --- Babel Functions for C and Similar Languages -*- lexical-binding: t; -*-
-;; Copyright (C) 2010-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2010-2024 Free Software Foundation, Inc.
;; Author: Eric Schulte
;; Thierry Banel
diff --git a/lisp/org/ob-R.el b/lisp/org/ob-R.el
index f2cc069aa5e..670be050bf2 100644
--- a/lisp/org/ob-R.el
+++ b/lisp/org/ob-R.el
@@ -1,6 +1,6 @@
;;; ob-R.el --- Babel Functions for R -*- lexical-binding: t; -*-
-;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
;; Author: Eric Schulte
;; Dan Davison
diff --git a/lisp/org/ob-awk.el b/lisp/org/ob-awk.el
index e5e42a91d14..777baa04234 100644
--- a/lisp/org/ob-awk.el
+++ b/lisp/org/ob-awk.el
@@ -1,6 +1,6 @@
;;; ob-awk.el --- Babel Functions for Awk -*- lexical-binding: t; -*-
-;; Copyright (C) 2011-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2011-2024 Free Software Foundation, Inc.
;; Author: Eric Schulte
;; Maintainer: Tyler Smith <tyler@plantarum.ca>
diff --git a/lisp/org/ob-calc.el b/lisp/org/ob-calc.el
index 5572ce818bd..d335aab7499 100644
--- a/lisp/org/ob-calc.el
+++ b/lisp/org/ob-calc.el
@@ -1,6 +1,6 @@
;;; ob-calc.el --- Babel Functions for Calc -*- lexical-binding: t; -*-
-;; Copyright (C) 2010-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2010-2024 Free Software Foundation, Inc.
;; Author: Eric Schulte
;; Maintainer: Tom Gillespie <tgbugs@gmail.com>
diff --git a/lisp/org/ob-clojure.el b/lisp/org/ob-clojure.el
index d993e0cb79e..f6d57c01316 100644
--- a/lisp/org/ob-clojure.el
+++ b/lisp/org/ob-clojure.el
@@ -1,6 +1,6 @@
;;; ob-clojure.el --- Babel Functions for Clojure -*- lexical-binding: t; -*-
-;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
;; Author: Joel Boehland, Eric Schulte, Oleh Krehel, Frederick Giasson
;; Maintainer: Daniel Kraus <daniel@kraus.my>
diff --git a/lisp/org/ob-comint.el b/lisp/org/ob-comint.el
index adfe31c4008..66861a54ffc 100644
--- a/lisp/org/ob-comint.el
+++ b/lisp/org/ob-comint.el
@@ -1,6 +1,6 @@
;;; ob-comint.el --- Babel Functions for Interaction with Comint Buffers -*- lexical-binding: t; -*-
-;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
;; Author: Eric Schulte
;; Keywords: literate programming, reproducible research, comint
diff --git a/lisp/org/ob-core.el b/lisp/org/ob-core.el
index e69ce4f1d12..0367b11330d 100644
--- a/lisp/org/ob-core.el
+++ b/lisp/org/ob-core.el
@@ -1,6 +1,6 @@
;;; ob-core.el --- Working with Code Blocks -*- lexical-binding: t; -*-
-;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
;; Authors: Eric Schulte
;; Dan Davison
@@ -1932,12 +1932,12 @@ buffer or nil if no such result exists."
(defun org-babel-result-names (&optional file)
"Return the names of results in FILE or the current buffer."
- (save-excursion
- (when file (find-file file)) (goto-char (point-min))
- (let ((case-fold-search t) names)
+ (with-current-buffer (if file (find-file-noselect file) (current-buffer))
+ (org-with-point-at 1
+ (let ((case-fold-search t) names)
(while (re-search-forward org-babel-result-w-name-regexp nil t)
(setq names (cons (match-string-no-properties 9) names)))
- names)))
+ names))))
;;;###autoload
(defun org-babel-next-src-block (&optional arg)
@@ -2358,7 +2358,7 @@ INFO may provide the values of these header arguments (in the
using the argument supplied to specify the export block
or snippet type."
(cond ((stringp result)
- (setq result (org-no-properties result))
+ (setq result (substring-no-properties result))
(when (member "file" result-params)
(setq result
(org-babel-result-to-file
diff --git a/lisp/org/ob-css.el b/lisp/org/ob-css.el
index f93c576fc5c..4806d80c5b8 100644
--- a/lisp/org/ob-css.el
+++ b/lisp/org/ob-css.el
@@ -1,6 +1,6 @@
;;; ob-css.el --- Babel Functions for CSS -*- lexical-binding: t; -*-
-;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
;; Author: Eric Schulte
;; Keywords: literate programming, reproducible research
diff --git a/lisp/org/ob-ditaa.el b/lisp/org/ob-ditaa.el
index 62200082851..b8ead656fac 100644
--- a/lisp/org/ob-ditaa.el
+++ b/lisp/org/ob-ditaa.el
@@ -1,6 +1,6 @@
;;; ob-ditaa.el --- Babel Functions for ditaa -*- lexical-binding: t; -*-
-;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
;; Author: Eric Schulte
;; Keywords: literate programming, reproducible research
diff --git a/lisp/org/ob-dot.el b/lisp/org/ob-dot.el
index ecef071a780..ed2955ba512 100644
--- a/lisp/org/ob-dot.el
+++ b/lisp/org/ob-dot.el
@@ -1,6 +1,6 @@
;;; ob-dot.el --- Babel Functions for dot -*- lexical-binding: t; -*-
-;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
;; Author: Eric Schulte
;; Maintainer: Justin Abrahms <justin@abrah.ms>
diff --git a/lisp/org/ob-emacs-lisp.el b/lisp/org/ob-emacs-lisp.el
index f2111d6493c..2adb6725c3c 100644
--- a/lisp/org/ob-emacs-lisp.el
+++ b/lisp/org/ob-emacs-lisp.el
@@ -1,6 +1,6 @@
;;; ob-emacs-lisp.el --- Babel Functions for Emacs-lisp Code -*- lexical-binding: t; -*-
-;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
;; Author: Eric Schulte
;; Keywords: literate programming, reproducible research
diff --git a/lisp/org/ob-eshell.el b/lisp/org/ob-eshell.el
index 95f5777ae7d..eefb43dc1a9 100644
--- a/lisp/org/ob-eshell.el
+++ b/lisp/org/ob-eshell.el
@@ -1,6 +1,6 @@
;;; ob-eshell.el --- Babel Functions for Eshell -*- lexical-binding: t; -*-
-;; Copyright (C) 2018-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2018-2024 Free Software Foundation, Inc.
;; Author: stardiviner <numbchild@gmail.com>
;; Maintainer: stardiviner <numbchild@gmail.com>
@@ -47,11 +47,12 @@
"Execute a block of Eshell code BODY with PARAMS.
This function is called by `org-babel-execute-src-block'.
-The BODY can be any code which allowed executed in Eshell.
-Eshell allow to execute normal shell command and Elisp code.
-More details please reference Eshell Info.
+The BODY argument is code which can be executed in Eshell.
+Eshell allows executing normal shell command and Elisp code.
+For more details, see Info node `(eshell) Top'.
-The PARAMS are variables assignments."
+The PARAMS argument is passed to
+`org-babel-expand-body:generic' (which see)."
(let* ((session (org-babel-eshell-initiate-session
(cdr (assq :session params))))
(full-body (org-babel-expand-body:generic
diff --git a/lisp/org/ob-eval.el b/lisp/org/ob-eval.el
index 07e53077253..62c558642a0 100644
--- a/lisp/org/ob-eval.el
+++ b/lisp/org/ob-eval.el
@@ -1,6 +1,6 @@
;;; ob-eval.el --- Babel Functions for External Code Evaluation -*- lexical-binding: t; -*-
-;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
;; Author: Eric Schulte
;; Keywords: literate programming, reproducible research, comint
diff --git a/lisp/org/ob-exp.el b/lisp/org/ob-exp.el
index 4d1b084be01..489ffdb330b 100644
--- a/lisp/org/ob-exp.el
+++ b/lisp/org/ob-exp.el
@@ -1,6 +1,6 @@
;;; ob-exp.el --- Exportation of Babel Source Blocks -*- lexical-binding: t; -*-
-;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
;; Authors: Eric Schulte
;; Dan Davison
diff --git a/lisp/org/ob-forth.el b/lisp/org/ob-forth.el
index e5dcad6d038..c39cce32f11 100644
--- a/lisp/org/ob-forth.el
+++ b/lisp/org/ob-forth.el
@@ -1,6 +1,6 @@
;;; ob-forth.el --- Babel Functions for Forth -*- lexical-binding: t; -*-
-;; Copyright (C) 2014-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2014-2024 Free Software Foundation, Inc.
;; Author: Eric Schulte
;; Keywords: literate programming, reproducible research, forth
diff --git a/lisp/org/ob-fortran.el b/lisp/org/ob-fortran.el
index 2c050cb18a8..d1bc06b2bd7 100644
--- a/lisp/org/ob-fortran.el
+++ b/lisp/org/ob-fortran.el
@@ -1,6 +1,6 @@
;;; ob-fortran.el --- Babel Functions for Fortran -*- lexical-binding: t; -*-
-;; Copyright (C) 2011-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2011-2024 Free Software Foundation, Inc.
;; Authors: Sergey Litvinov
;; Eric Schulte
diff --git a/lisp/org/ob-gnuplot.el b/lisp/org/ob-gnuplot.el
index e3e42918c75..8d7e62928a2 100644
--- a/lisp/org/ob-gnuplot.el
+++ b/lisp/org/ob-gnuplot.el
@@ -1,6 +1,6 @@
;;; ob-gnuplot.el --- Babel Functions for Gnuplot -*- lexical-binding: t; -*-
-;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
;; Author: Eric Schulte
;; Maintainer: Ihor Radchenko <yantar92@gmail.com>
diff --git a/lisp/org/ob-groovy.el b/lisp/org/ob-groovy.el
index c0da69fcbf1..6e5208f5edc 100644
--- a/lisp/org/ob-groovy.el
+++ b/lisp/org/ob-groovy.el
@@ -1,6 +1,6 @@
;;; ob-groovy.el --- Babel Functions for Groovy -*- lexical-binding: t; -*-
-;; Copyright (C) 2013-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2024 Free Software Foundation, Inc.
;; Author: Miro Bezjak <bezjak.miro@gmail.com>
;; Maintainer: Palak Mathur <palakmathur@gmail.com>
diff --git a/lisp/org/ob-haskell.el b/lisp/org/ob-haskell.el
index 7185ed61ffe..c891e94283e 100644
--- a/lisp/org/ob-haskell.el
+++ b/lisp/org/ob-haskell.el
@@ -1,6 +1,6 @@
;;; ob-haskell.el --- Babel Functions for Haskell -*- lexical-binding: t; -*-
-;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
;; Author: Eric Schulte
;; Maintainer: Lawrence Bottorff <borgauf@gmail.com>
diff --git a/lisp/org/ob-java.el b/lisp/org/ob-java.el
index 89386052666..c0dafbdceba 100644
--- a/lisp/org/ob-java.el
+++ b/lisp/org/ob-java.el
@@ -1,6 +1,6 @@
;;; ob-java.el --- org-babel functions for java evaluation -*- lexical-binding: t -*-
-;; Copyright (C) 2011-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2011-2024 Free Software Foundation, Inc.
;; Authors: Eric Schulte
;; Dan Davison
diff --git a/lisp/org/ob-js.el b/lisp/org/ob-js.el
index de7ea91317f..eb53f3730cf 100644
--- a/lisp/org/ob-js.el
+++ b/lisp/org/ob-js.el
@@ -1,6 +1,6 @@
;;; ob-js.el --- Babel Functions for Javascript -*- lexical-binding: t; -*-
-;; Copyright (C) 2010-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2010-2024 Free Software Foundation, Inc.
;; Author: Eric Schulte
;; Keywords: literate programming, reproducible research, js
diff --git a/lisp/org/ob-julia.el b/lisp/org/ob-julia.el
index cb5c7fa3b02..7a90d16408d 100644
--- a/lisp/org/ob-julia.el
+++ b/lisp/org/ob-julia.el
@@ -1,6 +1,6 @@
;;; ob-julia.el --- org-babel functions for julia code evaluation -*- lexical-binding: t; -*-
-;; Copyright (C) 2013-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2024 Free Software Foundation, Inc.
;; Authors: G. Jay Kerns
;; Maintainer: Pedro Bruel <pedro.bruel@gmail.com>
;; Keywords: literate programming, reproducible research, scientific computing
diff --git a/lisp/org/ob-latex.el b/lisp/org/ob-latex.el
index ce39628d642..3be59494032 100644
--- a/lisp/org/ob-latex.el
+++ b/lisp/org/ob-latex.el
@@ -1,6 +1,6 @@
;;; ob-latex.el --- Babel Functions for LaTeX -*- lexical-binding: t; -*-
-;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
;; Author: Eric Schulte
;; Keywords: literate programming, reproducible research
diff --git a/lisp/org/ob-lilypond.el b/lisp/org/ob-lilypond.el
index 9693b89e23b..d3c7a45933f 100644
--- a/lisp/org/ob-lilypond.el
+++ b/lisp/org/ob-lilypond.el
@@ -1,6 +1,6 @@
;;; ob-lilypond.el --- Babel Functions for Lilypond -*- lexical-binding: t; -*-
-;; Copyright (C) 2010-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2010-2024 Free Software Foundation, Inc.
;; Author: Martyn Jago
;; Keywords: babel language, literate programming
diff --git a/lisp/org/ob-lisp.el b/lisp/org/ob-lisp.el
index 048ef883ca1..da2d6cf8d61 100644
--- a/lisp/org/ob-lisp.el
+++ b/lisp/org/ob-lisp.el
@@ -1,6 +1,6 @@
;;; ob-lisp.el --- Babel Functions for Common Lisp -*- lexical-binding: t; -*-
-;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
;; Authors: Joel Boehland
;; Eric Schulte
diff --git a/lisp/org/ob-lob.el b/lisp/org/ob-lob.el
index f77bda73dd6..cf1183f40f4 100644
--- a/lisp/org/ob-lob.el
+++ b/lisp/org/ob-lob.el
@@ -1,6 +1,6 @@
;;; ob-lob.el --- Functions Supporting the Library of Babel -*- lexical-binding: t; -*-
-;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
;; Authors: Eric Schulte
;; Dan Davison
diff --git a/lisp/org/ob-lua.el b/lisp/org/ob-lua.el
index 81521d9e0a5..6d60538e8ab 100644
--- a/lisp/org/ob-lua.el
+++ b/lisp/org/ob-lua.el
@@ -1,6 +1,6 @@
;;; ob-lua.el --- Org Babel functions for Lua evaluation -*- lexical-binding: t; -*-
-;; Copyright (C) 2014, 2016-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2014, 2016-2024 Free Software Foundation, Inc.
;; Authors: Dieter Schoen
;; Keywords: literate programming, reproducible research
@@ -326,7 +326,7 @@ last statement in BODY, as elisp."
If RESULT-TYPE equals `output' then return standard output as a
string. If RESULT-TYPE equals `value' then return the value of the
last statement in BODY, as elisp."
- (let* ((send-wait (lambda () (comint-send-input nil t) (sleep-for 0 5)))
+ (let* ((send-wait (lambda () (comint-send-input nil t) (sleep-for 0.005)))
(dump-last-value
(lambda
(tmp-file pp)
diff --git a/lisp/org/ob-makefile.el b/lisp/org/ob-makefile.el
index 25306159bbb..636108615a5 100644
--- a/lisp/org/ob-makefile.el
+++ b/lisp/org/ob-makefile.el
@@ -1,6 +1,6 @@
;;; ob-makefile.el --- Babel Functions for Makefile -*- lexical-binding: t; -*-
-;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
;; Author: Eric Schulte
;; Thomas S. Dye
diff --git a/lisp/org/ob-matlab.el b/lisp/org/ob-matlab.el
index 43344495df2..de8deadbec6 100644
--- a/lisp/org/ob-matlab.el
+++ b/lisp/org/ob-matlab.el
@@ -1,6 +1,6 @@
;;; ob-matlab.el --- Babel support for Matlab -*- lexical-binding: t; -*-
-;; Copyright (C) 2010-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2010-2024 Free Software Foundation, Inc.
;; Author: Dan Davison
;; Keywords: literate programming, reproducible research
diff --git a/lisp/org/ob-maxima.el b/lisp/org/ob-maxima.el
index d1d7c742440..86f59a08702 100644
--- a/lisp/org/ob-maxima.el
+++ b/lisp/org/ob-maxima.el
@@ -1,6 +1,6 @@
;;; ob-maxima.el --- Babel Functions for Maxima -*- lexical-binding: t; -*-
-;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
;; Author: Eric S Fraga
;; Eric Schulte
diff --git a/lisp/org/ob-ocaml.el b/lisp/org/ob-ocaml.el
index 09224b98ba7..48e2d7b76fd 100644
--- a/lisp/org/ob-ocaml.el
+++ b/lisp/org/ob-ocaml.el
@@ -1,6 +1,6 @@
;;; ob-ocaml.el --- Babel Functions for Ocaml -*- lexical-binding: t; -*-
-;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
;; Author: Eric Schulte
;; Keywords: literate programming, reproducible research
diff --git a/lisp/org/ob-octave.el b/lisp/org/ob-octave.el
index 1de263a52d0..75f0ad79e02 100644
--- a/lisp/org/ob-octave.el
+++ b/lisp/org/ob-octave.el
@@ -1,6 +1,6 @@
;;; ob-octave.el --- Babel Functions for Octave and Matlab -*- lexical-binding: t; -*-
-;; Copyright (C) 2010-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2010-2024 Free Software Foundation, Inc.
;; Author: Dan Davison
;; Keywords: literate programming, reproducible research
diff --git a/lisp/org/ob-org.el b/lisp/org/ob-org.el
index 1bf02b461cd..9f6bae6a587 100644
--- a/lisp/org/ob-org.el
+++ b/lisp/org/ob-org.el
@@ -1,6 +1,6 @@
;;; ob-org.el --- Babel Functions for Org Code Blocks -*- lexical-binding: t; -*-
-;; Copyright (C) 2010-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2010-2024 Free Software Foundation, Inc.
;; Author: Eric Schulte
;; Keywords: literate programming, reproducible research
diff --git a/lisp/org/ob-perl.el b/lisp/org/ob-perl.el
index c8cff5da559..1006ffb12b3 100644
--- a/lisp/org/ob-perl.el
+++ b/lisp/org/ob-perl.el
@@ -1,6 +1,6 @@
;;; ob-perl.el --- Babel Functions for Perl -*- lexical-binding: t; -*-
-;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
;; Authors: Dan Davison
;; Eric Schulte
diff --git a/lisp/org/ob-plantuml.el b/lisp/org/ob-plantuml.el
index 3202c6e415d..aad210d61e5 100644
--- a/lisp/org/ob-plantuml.el
+++ b/lisp/org/ob-plantuml.el
@@ -1,6 +1,6 @@
;;; ob-plantuml.el --- Babel Functions for Plantuml -*- lexical-binding: t; -*-
-;; Copyright (C) 2010-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2010-2024 Free Software Foundation, Inc.
;; Author: Zhang Weize
;; Keywords: literate programming, reproducible research
@@ -57,7 +57,7 @@ The JAR can be configured via `org-plantuml-jar-path'.
`plantuml' means to use the PlantUML executable.
The executable can be configured via `org-plantuml-executable-path'.
-You can also configure extra arguments via `org-plantuml-executable-args'."
+You can also configure extra arguments via `org-plantuml-args'."
:group 'org-babel
:package-version '(Org . "9.4")
:type 'symbol
diff --git a/lisp/org/ob-processing.el b/lisp/org/ob-processing.el
index 4eeaf98e0a2..9b055768c9b 100644
--- a/lisp/org/ob-processing.el
+++ b/lisp/org/ob-processing.el
@@ -1,6 +1,6 @@
;;; ob-processing.el --- Babel functions for processing -*- lexical-binding: t; -*-
-;; Copyright (C) 2015-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2024 Free Software Foundation, Inc.
;; Author: Jarmo Hurri (adapted from ob-asymptote.el written by Eric Schulte)
;; Maintainer: Jarmo Hurri <jarmo.hurri@iki.fi>
diff --git a/lisp/org/ob-python.el b/lisp/org/ob-python.el
index c19af0ab331..1a442a5a08f 100644
--- a/lisp/org/ob-python.el
+++ b/lisp/org/ob-python.el
@@ -1,6 +1,6 @@
;;; ob-python.el --- Babel Functions for Python -*- lexical-binding: t; -*-
-;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
;; Authors: Eric Schulte
;; Dan Davison
@@ -235,7 +235,7 @@ then create. Return the initialized session."
;; multiple prompts during initialization.
(with-current-buffer py-buffer
(while (not org-babel-python--initialized)
- (org-babel-comint-wait-for-output py-buffer)))
+ (sleep-for 0.01)))
(org-babel-comint-wait-for-output py-buffer))
(setq org-babel-python-buffers
(cons (cons session py-buffer)
@@ -403,7 +403,7 @@ last statement in BODY, as elisp."
(body (org-babel-python-format-session-value
tmp-src-file tmp-results-file result-params)))
(org-babel-python--send-string session body)
- (sleep-for 0 10)
+ (sleep-for 0.01)
(org-babel-eval-read-file tmp-results-file)))))))
(org-babel-result-cond result-params
results
diff --git a/lisp/org/ob-ref.el b/lisp/org/ob-ref.el
index 2eae3690d93..219a3694452 100644
--- a/lisp/org/ob-ref.el
+++ b/lisp/org/ob-ref.el
@@ -1,6 +1,6 @@
;;; ob-ref.el --- Babel Functions for Referencing External Data -*- lexical-binding: t; -*-
-;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
;; Authors: Eric Schulte
;; Dan Davison
diff --git a/lisp/org/ob-ruby.el b/lisp/org/ob-ruby.el
index b94bc73dd79..ef65ea20d06 100644
--- a/lisp/org/ob-ruby.el
+++ b/lisp/org/ob-ruby.el
@@ -1,6 +1,6 @@
;;; ob-ruby.el --- Babel Functions for Ruby -*- lexical-binding: t; -*-
-;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
;; Author: Eric Schulte
;; Keywords: literate programming, reproducible research
diff --git a/lisp/org/ob-sass.el b/lisp/org/ob-sass.el
index 1498b931efd..a6b4a6462bb 100644
--- a/lisp/org/ob-sass.el
+++ b/lisp/org/ob-sass.el
@@ -1,6 +1,6 @@
;;; ob-sass.el --- Babel Functions for the Sass CSS generation language -*- lexical-binding: t; -*-
-;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
;; Author: Eric Schulte
;; Keywords: literate programming, reproducible research
diff --git a/lisp/org/ob-scheme.el b/lisp/org/ob-scheme.el
index ef41a2ec4a5..d13b975084c 100644
--- a/lisp/org/ob-scheme.el
+++ b/lisp/org/ob-scheme.el
@@ -1,6 +1,6 @@
;;; ob-scheme.el --- Babel Functions for Scheme -*- lexical-binding: t; -*-
-;; Copyright (C) 2010-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2010-2024 Free Software Foundation, Inc.
;; Authors: Eric Schulte
;; Michael Gauland
diff --git a/lisp/org/ob-screen.el b/lisp/org/ob-screen.el
index 269538e7967..5a9c36065e6 100644
--- a/lisp/org/ob-screen.el
+++ b/lisp/org/ob-screen.el
@@ -1,6 +1,6 @@
;;; ob-screen.el --- Babel Support for Interactive Terminal -*- lexical-binding: t; -*-
-;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
;; Author: Benjamin Andresen
;; Maintainer: Ken Mankoff <mankoff@gmail.com>
diff --git a/lisp/org/ob-sed.el b/lisp/org/ob-sed.el
index 6469901fd07..fa6a2bb199d 100644
--- a/lisp/org/ob-sed.el
+++ b/lisp/org/ob-sed.el
@@ -1,6 +1,6 @@
;;; ob-sed.el --- Babel Functions for Sed Scripts -*- lexical-binding: t; -*-
-;; Copyright (C) 2015-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2024 Free Software Foundation, Inc.
;; Author: Bjarte Johansen
;; Keywords: literate programming, reproducible research
diff --git a/lisp/org/ob-shell.el b/lisp/org/ob-shell.el
index 2c30a26056b..0c17f466223 100644
--- a/lisp/org/ob-shell.el
+++ b/lisp/org/ob-shell.el
@@ -1,6 +1,6 @@
;;; ob-shell.el --- Babel Functions for Shell Evaluation -*- lexical-binding: t; -*-
-;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
;; Author: Eric Schulte
;; Keywords: literate programming, reproducible research
@@ -166,6 +166,11 @@ This function is called by `org-babel-execute-src-block'."
"Return a list of statements declaring the values as a generic variable."
(format "%s=%s" varname (org-babel-sh-var-to-sh values sep hline)))
+(defun org-babel--variable-assignments:fish
+ (varname values &optional sep hline)
+ "Return a list of statements declaring the values as a fish variable."
+ (format "set %s %s" varname (org-babel-sh-var-to-sh values sep hline)))
+
(defun org-babel--variable-assignments:bash_array
(varname values &optional sep hline)
"Return a list of statements declaring the values as a bash array."
@@ -211,8 +216,11 @@ This function is called by `org-babel-execute-src-block'."
(if (string-suffix-p "bash" shell-file-name)
(org-babel--variable-assignments:bash
(car pair) (cdr pair) sep hline)
- (org-babel--variable-assignments:sh-generic
- (car pair) (cdr pair) sep hline)))
+ (if (string-suffix-p "fish" shell-file-name)
+ (org-babel--variable-assignments:fish
+ (car pair) (cdr pair) sep hline)
+ (org-babel--variable-assignments:sh-generic
+ (car pair) (cdr pair) sep hline))))
(org-babel--get-vars params))))
(defun org-babel-sh-var-to-sh (var &optional sep hline)
diff --git a/lisp/org/ob-sql.el b/lisp/org/ob-sql.el
index f73e7003f6d..319d864a051 100644
--- a/lisp/org/ob-sql.el
+++ b/lisp/org/ob-sql.el
@@ -1,6 +1,6 @@
;;; ob-sql.el --- Babel Functions for SQL -*- lexical-binding: t; -*-
-;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
;; Author: Eric Schulte
;; Maintainer: Daniel Kraus <daniel@kraus.my>
diff --git a/lisp/org/ob-sqlite.el b/lisp/org/ob-sqlite.el
index 526b73ebd9b..296c9e3e703 100644
--- a/lisp/org/ob-sqlite.el
+++ b/lisp/org/ob-sqlite.el
@@ -1,6 +1,6 @@
;;; ob-sqlite.el --- Babel Functions for SQLite Databases -*- lexical-binding: t; -*-
-;; Copyright (C) 2010-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2010-2024 Free Software Foundation, Inc.
;; Author: Eric Schulte
;; Maintainer: Nick Savage <nick@nicksavage.ca>
diff --git a/lisp/org/ob-table.el b/lisp/org/ob-table.el
index 5c91f33f877..c96875df08b 100644
--- a/lisp/org/ob-table.el
+++ b/lisp/org/ob-table.el
@@ -1,6 +1,6 @@
;;; ob-table.el --- Support for Calling Babel Functions from Tables -*- lexical-binding: t; -*-
-;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
;; Author: Eric Schulte
;; Keywords: literate programming, reproducible research
diff --git a/lisp/org/ob-tangle.el b/lisp/org/ob-tangle.el
index a833037ca2b..13c928df316 100644
--- a/lisp/org/ob-tangle.el
+++ b/lisp/org/ob-tangle.el
@@ -1,6 +1,6 @@
;;; ob-tangle.el --- Extract Source Code From Org Files -*- lexical-binding: t; -*-
-;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
;; Author: Eric Schulte
;; Keywords: literate programming, reproducible research
diff --git a/lisp/org/ob.el b/lisp/org/ob.el
index 4444ced5864..d3a29b83351 100644
--- a/lisp/org/ob.el
+++ b/lisp/org/ob.el
@@ -1,6 +1,6 @@
;;; ob.el --- Working with Code Blocks in Org -*- lexical-binding: t; -*-
-;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
;; Authors: Eric Schulte
;; Keywords: literate programming, reproducible research
diff --git a/lisp/org/oc-basic.el b/lisp/org/oc-basic.el
index 1c8c37aa941..f05a4da8aab 100644
--- a/lisp/org/oc-basic.el
+++ b/lisp/org/oc-basic.el
@@ -1,6 +1,6 @@
;;; oc-basic.el --- basic back-end for citations -*- lexical-binding: t; -*-
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
;; Author: Nicolas Goaziou <mail@nicolasgoaziou.fr>
@@ -162,7 +162,7 @@ Return a hash table with citation references as keys and fields alist as values.
(puthash (cdr (assq 'id item))
(mapcar (pcase-lambda (`(,field . ,value))
(pcase field
- ((or 'author 'editors)
+ ((or 'author 'editor)
;; Author and editors are arrays of
;; objects, each of them designing a
;; person. These objects may contain
diff --git a/lisp/org/oc-biblatex.el b/lisp/org/oc-biblatex.el
index b2d31f0f635..098a37bd850 100644
--- a/lisp/org/oc-biblatex.el
+++ b/lisp/org/oc-biblatex.el
@@ -1,6 +1,6 @@
;;; oc-biblatex.el --- biblatex citation processor for Org -*- lexical-binding: t; -*-
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
;; Author: Nicolas Goaziou <mail@nicolasgoaziou.fr>
@@ -26,7 +26,7 @@
;; The processor relies on "biblatex" LaTeX package. As such it ensures that
;; the package is properly required in the document's preamble. More
-;; accurately, it will re-use any "\usepackage{biblatex}" already present in
+;; accurately, it will reuse any "\usepackage{biblatex}" already present in
;; the document (e.g., through `org-latex-packages-alist'), or insert one using
;; options defined in `org-cite-biblatex-options'.
diff --git a/lisp/org/oc-bibtex.el b/lisp/org/oc-bibtex.el
index d5e5490ede2..8d04daef97b 100644
--- a/lisp/org/oc-bibtex.el
+++ b/lisp/org/oc-bibtex.el
@@ -1,6 +1,6 @@
;;; oc-bibtex.el --- Vanilla citation processor for LaTeX -*- lexical-binding: t; -*-
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
;; Author: Nicolas Goaziou <mail@nicolasgoaziou.fr>
diff --git a/lisp/org/oc-csl.el b/lisp/org/oc-csl.el
index 2b00cb59904..ccdf028339e 100644
--- a/lisp/org/oc-csl.el
+++ b/lisp/org/oc-csl.el
@@ -1,6 +1,6 @@
;;; oc-csl.el --- csl citation processor for Org -*- lexical-binding: t; -*-
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
;; Author: Nicolas Goaziou <mail@nicolasgoaziou.fr>
;; Maintainer: András Simonyi <andras.simonyi@gmail.com>
diff --git a/lisp/org/oc-natbib.el b/lisp/org/oc-natbib.el
index 855be2a5c12..0dddca0e2b4 100644
--- a/lisp/org/oc-natbib.el
+++ b/lisp/org/oc-natbib.el
@@ -1,6 +1,6 @@
;;; oc-natbib.el --- Citation processor using natbib LaTeX package -*- lexical-binding: t; -*-
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
;; Author: Nicolas Goaziou <mail@nicolasgoaziou.fr>
diff --git a/lisp/org/oc.el b/lisp/org/oc.el
index 8a7b662098a..4270d67787a 100644
--- a/lisp/org/oc.el
+++ b/lisp/org/oc.el
@@ -1,6 +1,6 @@
;;; oc.el --- Org Cite library -*- lexical-binding: t; -*-
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
;; Author: Nicolas Goaziou <mail@nicolasgoaziou.fr>
@@ -52,7 +52,7 @@
;; through the "cite_export" keyword.
;; Eventually, this library provides some tools, mainly targeted at
-;; processor implementors. Most are export-specific and are located
+;; processor implementers. Most are export-specific and are located
;; in the "Tools only available during export" and "Tools generating
;; or operating on parsed data" sections.
diff --git a/lisp/org/ol-bbdb.el b/lisp/org/ol-bbdb.el
index 47bd9d98cb5..dba587e345e 100644
--- a/lisp/org/ol-bbdb.el
+++ b/lisp/org/ol-bbdb.el
@@ -1,10 +1,10 @@
;;; ol-bbdb.el --- Links to BBDB entries -*- lexical-binding: t; -*-
-;; Copyright (C) 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2004-2024 Free Software Foundation, Inc.
;; Authors: Carsten Dominik <carsten.dominik@gmail.com>
;; Thomas Baumann <thomas dot baumann at ch dot tum dot de>
-;; Keywords: outlines, hypermedia, calendar, wp
+;; Keywords: outlines, hypermedia, calendar, text
;; URL: https://orgmode.org
;;
;; This file is part of GNU Emacs.
diff --git a/lisp/org/ol-bibtex.el b/lisp/org/ol-bibtex.el
index a16a4b39277..ea4b54cc25a 100644
--- a/lisp/org/ol-bibtex.el
+++ b/lisp/org/ol-bibtex.el
@@ -1,11 +1,11 @@
;;; ol-bibtex.el --- Links to BibTeX entries -*- lexical-binding: t; -*-
;;
-;; Copyright (C) 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2024 Free Software Foundation, Inc.
;;
;; Authors: Bastien Guerry <bzg@gnu.org>
;; Carsten Dominik <carsten dot dominik at gmail dot com>
;; Eric Schulte <schulte dot eric at gmail dot com>
-;; Keywords: org, wp, capture
+;; Keywords: org, text, capture
;;
;; This file is part of GNU Emacs.
;;
diff --git a/lisp/org/ol-docview.el b/lisp/org/ol-docview.el
index a9cd9b9950f..f12d3558d42 100644
--- a/lisp/org/ol-docview.el
+++ b/lisp/org/ol-docview.el
@@ -1,9 +1,9 @@
;;; ol-docview.el --- Links to Docview mode buffers -*- lexical-binding: t; -*-
-;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
;; Author: Jan Böcker <jan.boecker at jboecker dot de>
-;; Keywords: outlines, hypermedia, calendar, wp
+;; Keywords: outlines, hypermedia, calendar, text
;; URL: https://orgmode.org
;;
;; This file is part of GNU Emacs.
diff --git a/lisp/org/ol-doi.el b/lisp/org/ol-doi.el
index 971b0508787..0550a48b63e 100644
--- a/lisp/org/ol-doi.el
+++ b/lisp/org/ol-doi.el
@@ -1,6 +1,6 @@
;;; ol-doi.el --- DOI links support in Org -*- lexical-binding: t; -*-
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
;; Author: Nicolas Goaziou <mail@nicolasgoaziou.fr>
diff --git a/lisp/org/ol-eshell.el b/lisp/org/ol-eshell.el
index b7d3baf3895..dead1aa8a3a 100644
--- a/lisp/org/ol-eshell.el
+++ b/lisp/org/ol-eshell.el
@@ -1,6 +1,6 @@
;;; ol-eshell.el --- Links to Working Directories in Eshell -*- lexical-binding: t; -*-
-;; Copyright (C) 2011-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2011-2024 Free Software Foundation, Inc.
;; Author: Konrad Hinsen <konrad.hinsen AT fastmail.net>
diff --git a/lisp/org/ol-eww.el b/lisp/org/ol-eww.el
index ee970b6aaa1..fb711c60527 100644
--- a/lisp/org/ol-eww.el
+++ b/lisp/org/ol-eww.el
@@ -1,6 +1,6 @@
;;; ol-eww.el --- Store URL and kill from Eww mode -*- lexical-binding: t -*-
-;; Copyright (C) 2014-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2014-2024 Free Software Foundation, Inc.
;; Author: Marco Wahl <marcowahlsoft>a<gmailcom>
;; Keywords: link, eww
diff --git a/lisp/org/ol-gnus.el b/lisp/org/ol-gnus.el
index 7c07ce0454d..91af4d10a25 100644
--- a/lisp/org/ol-gnus.el
+++ b/lisp/org/ol-gnus.el
@@ -1,10 +1,10 @@
;;; ol-gnus.el --- Links to Gnus Groups and Messages -*- lexical-binding: t; -*-
-;; Copyright (C) 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2004-2024 Free Software Foundation, Inc.
;; Author: Carsten Dominik <carsten.dominik@gmail.com>
;; Tassilo Horn <tassilo at member dot fsf dot org>
-;; Keywords: outlines, hypermedia, calendar, wp
+;; Keywords: outlines, hypermedia, calendar, text
;; URL: https://orgmode.org
;;
;; This file is part of GNU Emacs.
diff --git a/lisp/org/ol-info.el b/lisp/org/ol-info.el
index ad9e4a12bd7..48581bd779b 100644
--- a/lisp/org/ol-info.el
+++ b/lisp/org/ol-info.el
@@ -1,9 +1,9 @@
;;; ol-info.el --- Links to Info Nodes -*- lexical-binding: t; -*-
-;; Copyright (C) 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2004-2024 Free Software Foundation, Inc.
;; Author: Carsten Dominik <carsten.dominik@gmail.com>
-;; Keywords: outlines, hypermedia, calendar, wp
+;; Keywords: outlines, hypermedia, calendar, text
;; URL: https://orgmode.org
;;
;; This file is part of GNU Emacs.
@@ -129,13 +129,13 @@ If LINK is not an info link then DESC is returned."
(defconst org-info-emacs-documents
'("ada-mode" "auth" "autotype" "bovine" "calc" "ccmode" "cl" "dbus" "dired-x"
- "ebrowse" "ede" "ediff" "edt" "efaq-w32" "efaq" "eieio" "eintr" "elisp"
- "emacs-gnutls" "emacs-mime" "emacs" "epa" "erc" "ert" "eshell" "eudc" "eww"
- "flymake" "forms" "gnus" "htmlfontify" "idlwave" "ido" "info" "mairix-el"
- "message" "mh-e" "newsticker" "nxml-mode" "octave-mode" "org" "pcl-cvs"
- "pgg" "rcirc" "reftex" "remember" "sasl" "sc" "semantic" "ses" "sieve"
- "smtpmail" "speedbar" "srecode" "todo-mode" "tramp" "url" "vip" "viper"
- "widget" "wisent" "woman")
+ "ebrowse" "ede" "ediff" "edt" "efaq-w32" "efaq" "eglot" "eieio" "eintr"
+ "elisp" "emacs-gnutls" "emacs-mime" "emacs" "epa" "erc" "ert" "eshell"
+ "eudc" "eww" "flymake" "forms" "gnus" "htmlfontify" "idlwave" "ido" "info"
+ "mairix-el" "message" "mh-e" "modus-themes" "newsticker" "nxml-mode" "octave-mode"
+ "org" "pcl-cvs" "pgg" "rcirc" "reftex" "remember" "sasl" "sc" "semantic"
+ "ses" "sieve" "smtpmail" "speedbar" "srecode" "todo-mode" "tramp" "transient"
+ "url" "use-package" "vhdl-mode" "vip" "viper" "vtable" "widget" "wisent" "woman")
"List of Emacs documents available.
Taken from <https://www.gnu.org/software/emacs/manual/html_mono/.>")
diff --git a/lisp/org/ol-irc.el b/lisp/org/ol-irc.el
index 3760644e858..78c4884b00f 100644
--- a/lisp/org/ol-irc.el
+++ b/lisp/org/ol-irc.el
@@ -1,6 +1,6 @@
;;; ol-irc.el --- Links to IRC Sessions -*- lexical-binding: t; -*-
;;
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
;;
;; Author: Philip Jackson <emacs@shellarchive.co.uk>
;; Keywords: erc, irc, link, org
diff --git a/lisp/org/ol-man.el b/lisp/org/ol-man.el
index 40fdc8f9237..5ce04330021 100644
--- a/lisp/org/ol-man.el
+++ b/lisp/org/ol-man.el
@@ -1,9 +1,9 @@
;;; ol-man.el --- Links to man pages -*- lexical-binding: t; -*-
;;
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
;; Author: Carsten Dominik <carsten.dominik@gmail.com>
;; Maintainer: Bastien Guerry <bzg@gnu.org>
-;; Keywords: outlines, hypermedia, calendar, wp
+;; Keywords: outlines, hypermedia, calendar, text
;; URL: https://orgmode.org
;;
;; This file is part of GNU Emacs.
diff --git a/lisp/org/ol-mhe.el b/lisp/org/ol-mhe.el
index 403b5a25483..52339c0a622 100644
--- a/lisp/org/ol-mhe.el
+++ b/lisp/org/ol-mhe.el
@@ -1,9 +1,9 @@
;;; ol-mhe.el --- Links to MH-E Messages -*- lexical-binding: t; -*-
-;; Copyright (C) 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2004-2024 Free Software Foundation, Inc.
;; Author: Thomas Baumann <thomas dot baumann at ch dot tum dot de>
-;; Keywords: outlines, hypermedia, calendar, wp
+;; Keywords: outlines, hypermedia, calendar, text
;; URL: https://orgmode.org
;;
;; This file is part of GNU Emacs.
diff --git a/lisp/org/ol-rmail.el b/lisp/org/ol-rmail.el
index 2877798281d..a1af1b94915 100644
--- a/lisp/org/ol-rmail.el
+++ b/lisp/org/ol-rmail.el
@@ -1,9 +1,9 @@
;;; ol-rmail.el --- Links to Rmail Messages -*- lexical-binding: t; -*-
-;; Copyright (C) 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2004-2024 Free Software Foundation, Inc.
;; Author: Carsten Dominik <carsten.dominik@gmail.com>
-;; Keywords: outlines, hypermedia, calendar, wp
+;; Keywords: outlines, hypermedia, calendar, text
;; URL: https://orgmode.org
;;
;; This file is part of GNU Emacs.
diff --git a/lisp/org/ol-w3m.el b/lisp/org/ol-w3m.el
index 6fb01a60d59..e8981173371 100644
--- a/lisp/org/ol-w3m.el
+++ b/lisp/org/ol-w3m.el
@@ -1,9 +1,9 @@
;;; ol-w3m.el --- Copy and Paste From W3M -*- lexical-binding: t; -*-
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
;; Author: Andy Stewart <lazycat dot manatee at gmail dot com>
-;; Keywords: outlines, hypermedia, calendar, wp
+;; Keywords: outlines, hypermedia, calendar, text
;; URL: https://orgmode.org
;;
;; This file is part of GNU Emacs.
diff --git a/lisp/org/ol.el b/lisp/org/ol.el
index 9ad191c8f78..ac0c308da21 100644
--- a/lisp/org/ol.el
+++ b/lisp/org/ol.el
@@ -1,9 +1,9 @@
;;; ol.el --- Org links library -*- lexical-binding: t; -*-
-;; Copyright (C) 2018-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2018-2024 Free Software Foundation, Inc.
;; Author: Carsten Dominik <carsten.dominik@gmail.com>
-;; Keywords: outlines, hypermedia, calendar, wp
+;; Keywords: outlines, hypermedia, calendar, text
;; This file is part of GNU Emacs.
@@ -1803,7 +1803,7 @@ generate a description as described in `org-link-parameters'
docstring. Otherwise, if `org-link-make-description-function' is
non-nil, this function will be called with the link target, and
the result will be the default link description. When called
-non-interactively, don't allow to edit the default description."
+non-interactively, don't allow editing the default description."
(interactive "P")
(let* ((wcf (current-window-configuration))
(origbuf (current-buffer))
@@ -2042,7 +2042,7 @@ Also refresh fontification if needed."
(interactive)
(let ((old-regexp org-target-link-regexp)
;; Some languages, e.g., Chinese, do not use spaces to
- ;; separate words. Also allow to surround radio targets with
+ ;; separate words. Also allow surrounding radio targets with
;; line-breakable characters.
(before-re "\\(?:^\\|[^[:alnum:]]\\|\\c|\\)\\(")
(after-re "\\)\\(?:$\\|[^[:alnum:]]\\|\\c|\\)")
diff --git a/lisp/org/org-agenda.el b/lisp/org/org-agenda.el
index d3e61643190..f8195a053bc 100644
--- a/lisp/org/org-agenda.el
+++ b/lisp/org/org-agenda.el
@@ -1,9 +1,9 @@
;;; org-agenda.el --- Dynamic task and appointment lists for Org -*- lexical-binding: t; -*-
-;; Copyright (C) 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2004-2024 Free Software Foundation, Inc.
;; Author: Carsten Dominik <carsten.dominik@gmail.com>
-;; Keywords: outlines, hypermedia, calendar, wp
+;; Keywords: outlines, hypermedia, calendar, text
;; URL: https://orgmode.org
;;
;; This file is part of GNU Emacs.
@@ -6321,6 +6321,11 @@ specification like [h]h:mm."
(org-element-cache-map
(lambda (el)
(when (and (org-element-property :deadline el)
+ ;; Only consider active timestamp values.
+ (memq (org-element-property
+ :type
+ (org-element-property :deadline el))
+ '(diary active active-range))
(or (not with-hour)
(org-element-property
:hour-start
@@ -6662,6 +6667,11 @@ scheduled items with an hour specification like [h]h:mm."
(org-element-cache-map
(lambda (el)
(when (and (org-element-property :scheduled el)
+ ;; Only consider active timestamp values.
+ (memq (org-element-property
+ :type
+ (org-element-property :scheduled el))
+ '(diary active active-range))
(or (not with-hour)
(org-element-property
:hour-start
@@ -6784,7 +6794,8 @@ scheduled items with an hour specification like [h]h:mm."
(let ((deadline (time-to-days
(when (org-element-property :deadline el)
(org-time-string-to-time
- (org-element-property :deadline el))))))
+ (org-element-interpret-data
+ (org-element-property :deadline el)))))))
(and (<= schedule deadline) (> current deadline))))
(`not-today pastschedp)
(`t t)
diff --git a/lisp/org/org-archive.el b/lisp/org/org-archive.el
index e74c59a51d9..f5c223661c4 100644
--- a/lisp/org/org-archive.el
+++ b/lisp/org/org-archive.el
@@ -1,9 +1,9 @@
;;; org-archive.el --- Archiving for Org -*- lexical-binding: t; -*-
-;; Copyright (C) 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2004-2024 Free Software Foundation, Inc.
;; Author: Carsten Dominik <carsten.dominik@gmail.com>
-;; Keywords: outlines, hypermedia, calendar, wp
+;; Keywords: outlines, hypermedia, calendar, text
;; URL: https://orgmode.org
;;
;; This file is part of GNU Emacs.
diff --git a/lisp/org/org-attach-git.el b/lisp/org/org-attach-git.el
index 4763aefd45c..48b2198402d 100644
--- a/lisp/org/org-attach-git.el
+++ b/lisp/org/org-attach-git.el
@@ -1,6 +1,6 @@
;;; org-attach-git.el --- Automatic git commit extension to org-attach -*- lexical-binding: t; -*-
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
;; Original Author: John Wiegley <johnw@newartisans.com>
;; Restructurer: Gustav Wikström <gustav@whil.se>
diff --git a/lisp/org/org-attach.el b/lisp/org/org-attach.el
index e8b27751e76..7130e5629ab 100644
--- a/lisp/org/org-attach.el
+++ b/lisp/org/org-attach.el
@@ -1,6 +1,6 @@
;;; org-attach.el --- Manage file attachments to Org outlines -*- lexical-binding: t; -*-
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
;; Author: John Wiegley <johnw@newartisans.com>
;; Keywords: org data attachment
diff --git a/lisp/org/org-capture.el b/lisp/org/org-capture.el
index a696c615b2a..1897c096306 100644
--- a/lisp/org/org-capture.el
+++ b/lisp/org/org-capture.el
@@ -1,9 +1,9 @@
;;; org-capture.el --- Fast note taking in Org -*- lexical-binding: t; -*-
-;; Copyright (C) 2010-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2010-2024 Free Software Foundation, Inc.
;; Author: Carsten Dominik <carsten.dominik@gmail.com>
-;; Keywords: outlines, hypermedia, calendar, wp
+;; Keywords: outlines, hypermedia, calendar, text
;; URL: https://orgmode.org
;;
;; This file is part of GNU Emacs.
@@ -1312,7 +1312,7 @@ may have been stored before."
(while (< (point) end)
(indent-to i)
(forward-line)))
- ;; Pre-pending an item could change the type of the list
+ ;; Prepending an item could change the type of the list
;; if there is a mismatch. In this situation,
;; prioritize the existing list.
(when prepend?
diff --git a/lisp/org/org-clock.el b/lisp/org/org-clock.el
index 6ab313e1218..e79677ad6be 100644
--- a/lisp/org/org-clock.el
+++ b/lisp/org/org-clock.el
@@ -1,9 +1,9 @@
;;; org-clock.el --- The time clocking code for Org mode -*- lexical-binding: t; -*-
-;; Copyright (C) 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2004-2024 Free Software Foundation, Inc.
;; Author: Carsten Dominik <carsten.dominik@gmail.com>
-;; Keywords: outlines, hypermedia, calendar, wp
+;; Keywords: outlines, hypermedia, calendar, text
;; URL: https://orgmode.org
;;
;; This file is part of GNU Emacs.
diff --git a/lisp/org/org-colview.el b/lisp/org/org-colview.el
index 28cfd0d910c..ccf1ca731a4 100644
--- a/lisp/org/org-colview.el
+++ b/lisp/org/org-colview.el
@@ -1,9 +1,9 @@
;;; org-colview.el --- Column View in Org -*- lexical-binding: t; -*-
-;; Copyright (C) 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2004-2024 Free Software Foundation, Inc.
;; Author: Carsten Dominik <carsten.dominik@gmail.com>
-;; Keywords: outlines, hypermedia, calendar, wp
+;; Keywords: outlines, hypermedia, calendar, text
;; URL: https://orgmode.org
;;
;; This file is part of GNU Emacs.
@@ -525,7 +525,8 @@ for the duration of the command.")
(setq header-line-format org-previous-header-line-format)
(kill-local-variable 'org-previous-header-line-format)
(remove-hook 'post-command-hook #'org-columns-hscroll-title 'local))
- (set-marker org-columns-begin-marker nil)
+ (when (markerp org-columns-begin-marker)
+ (set-marker org-columns-begin-marker nil))
(when (markerp org-columns-top-level-marker)
(set-marker org-columns-top-level-marker nil))
(with-silent-modifications
diff --git a/lisp/org/org-compat.el b/lisp/org/org-compat.el
index d5bf2191ae7..e9f68518e6f 100644
--- a/lisp/org/org-compat.el
+++ b/lisp/org/org-compat.el
@@ -1,9 +1,9 @@
;;; org-compat.el --- Compatibility Code for Older Emacsen -*- lexical-binding: t; -*-
-;; Copyright (C) 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2004-2024 Free Software Foundation, Inc.
;; Author: Carsten Dominik <carsten.dominik@gmail.com>
-;; Keywords: outlines, hypermedia, calendar, wp
+;; Keywords: outlines, hypermedia, calendar, text
;; URL: https://orgmode.org
;;
;; This file is part of GNU Emacs.
@@ -141,7 +141,7 @@ Unibyte strings are converted to multibyte for comparison."
Elements in COMPONENTS must be a string or nil.
DIRECTORY or the non-final elements in COMPONENTS may or may not end
with a slash -- if they don't end with a slash, a slash will be
-inserted before contatenating."
+inserted before concatenating."
(save-match-data
(mapconcat
#'identity
diff --git a/lisp/org/org-crypt.el b/lisp/org/org-crypt.el
index b5df115cf90..ccf1dc63386 100644
--- a/lisp/org/org-crypt.el
+++ b/lisp/org/org-crypt.el
@@ -1,6 +1,6 @@
;;; org-crypt.el --- Public Key Encryption for Org Entries -*- lexical-binding: t; -*-
;;
-;; Copyright (C) 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2024 Free Software Foundation, Inc.
;; Author: John Wiegley <johnw@gnu.org>
diff --git a/lisp/org/org-ctags.el b/lisp/org/org-ctags.el
index 990214f4117..2417353ee5d 100644
--- a/lisp/org/org-ctags.el
+++ b/lisp/org/org-ctags.el
@@ -1,9 +1,9 @@
;;; org-ctags.el --- Integrate Emacs "tags" Facility with Org -*- lexical-binding: t; -*-
-;; Copyright (C) 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2024 Free Software Foundation, Inc.
;; Author: Paul Sexton <eeeickythump@gmail.com>
-;; Keywords: org, wp
+;; Keywords: org, text
;; This file is part of GNU Emacs.
;;
diff --git a/lisp/org/org-cycle.el b/lisp/org/org-cycle.el
index 90fc95f41f7..53e086552f6 100644
--- a/lisp/org/org-cycle.el
+++ b/lisp/org/org-cycle.el
@@ -1,6 +1,6 @@
;;; org-cycle.el --- Visibility cycling of Org entries -*- lexical-binding: t; -*-
;;
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
;;
;; Maintainer: Ihor Radchenko <yantar92 at gmail dot com>
;; Keywords: folding, visibility cycling, invisible text
diff --git a/lisp/org/org-datetree.el b/lisp/org/org-datetree.el
index 035ef047a9d..90581f1360c 100644
--- a/lisp/org/org-datetree.el
+++ b/lisp/org/org-datetree.el
@@ -1,9 +1,9 @@
;;; org-datetree.el --- Create date entries in a tree -*- lexical-binding: t; -*-
-;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
;; Author: Carsten Dominik <carsten.dominik@gmail.com>
-;; Keywords: outlines, hypermedia, calendar, wp
+;; Keywords: outlines, hypermedia, calendar, text
;; URL: https://orgmode.org
;;
;; This file is part of GNU Emacs.
diff --git a/lisp/org/org-duration.el b/lisp/org/org-duration.el
index 2919efd4c77..1ab84776117 100644
--- a/lisp/org/org-duration.el
+++ b/lisp/org/org-duration.el
@@ -1,9 +1,9 @@
;;; org-duration.el --- Library handling durations -*- lexical-binding: t; -*-
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
;; Author: Nicolas Goaziou <mail@nicolasgoaziou.fr>
-;; Keywords: outlines, hypermedia, calendar, wp
+;; Keywords: outlines, hypermedia, calendar, text
;; This file is part of GNU Emacs.
diff --git a/lisp/org/org-element.el b/lisp/org/org-element.el
index 296468eed1a..6e87e870996 100644
--- a/lisp/org/org-element.el
+++ b/lisp/org/org-element.el
@@ -1,9 +1,9 @@
;;; org-element.el --- Parser for Org Syntax -*- lexical-binding: t; -*-
-;; Copyright (C) 2012-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2012-2024 Free Software Foundation, Inc.
;; Author: Nicolas Goaziou <n.goaziou at gmail dot com>
-;; Keywords: outlines, hypermedia, calendar, wp
+;; Keywords: outlines, hypermedia, calendar, text
;; This file is part of GNU Emacs.
@@ -2968,7 +2968,7 @@ CONTENTS is verse block contents."
;; object types they can contain will be specified in
;; `org-element-object-restrictions'.
;;
-;; Creating a new type of object requires to alter
+;; Creating a new type of object requires altering
;; `org-element--object-regexp' and `org-element--object-lex', add the
;; new type in `org-element-all-objects', and possibly add
;; restrictions in `org-element-object-restrictions'.
@@ -3523,7 +3523,7 @@ Assume point is at the beginning of the link."
;;
;; Also treat any newline character and associated
;; indentation as a single space character. This is not
- ;; compatible with RFC 3986, which requires to ignore
+ ;; compatible with RFC 3986, which requires ignoring
;; them altogether. However, doing so would require
;; users to encode spaces on the fly when writing links
;; (e.g., insert [[shell:ls%20*.org]] instead of
@@ -5484,7 +5484,7 @@ This variable is used to determine when re-parsing buffer is not going
to slow down the command.
If the commands end up modifying the cache, the worst case scenario is
-performance drop. So, advicing these commands is safe. Yet, it is
+performance drop. So, advising these commands is safe. Yet, it is
better to remove the commands advised in such a way from this list.")
(defmacro org-element--request-key (request)
@@ -5906,7 +5906,7 @@ If this warning appears regularly, please report the warning text to Org mode ma
(org-element-property :begin element)
(org-element-property :org-element--cache-sync-key element))
(org-element-cache-reset)
- (throw 'quit nil))
+ (throw 'org-element--cache-quit nil))
(or (avl-tree-delete org-element--cache element)
(progn
;; This should not happen, but if it is, would be better to know
@@ -5919,7 +5919,7 @@ If this warning appears regularly, please report the warning text to Org mode ma
(org-element-property :begin element)
(org-element-property :org-element--cache-sync-key element))
(org-element-cache-reset)
- (throw 'quit nil)))))
+ (throw 'org-element--cache-quit nil)))))
;;;; Synchronization
@@ -6382,6 +6382,10 @@ completing the request."
;; We altered the tree structure. The tree
;; traversal needs to be restarted.
(setf (org-element--request-key request) key)
+ ;; Make sure that we restart tree traversal
+ ;; past already shifted elements (before the
+ ;; removed DATA).
+ (setq start key)
(setf (org-element--request-parent request) parent)
;; Restart tree traversal.
(setq node (org-element--cache-root)
@@ -6705,20 +6709,8 @@ The function returns the new value of `org-element--cache-change-warning'."
(setq org-element--cache-change-tic (buffer-chars-modified-tick))
(setq org-element--cache-last-buffer-size (buffer-size))
(goto-char beg)
- (beginning-of-line)
- (let ((bottom (save-excursion
- (goto-char end)
- (if (and (bolp)
- ;; When beg == end, still extent to eol.
- (> (point) beg))
- ;; FIXME: Potential pitfall.
- ;; We are appending to an element end.
- ;; Unless the last inserted char is not
- ;; newline, the next element is not broken
- ;; and does not need to be purged from the
- ;; cache.
- end
- (line-end-position)))))
+ (forward-line 0)
+ (let ((bottom (save-excursion (goto-char end) (line-end-position))))
(prog1
;; Use the worst change warning to not miss important edits.
;; This function is called before edit and after edit by
@@ -7859,7 +7851,7 @@ element ending there."
(setq cached-only nil))
(let (element)
(when (org-element--cache-active-p)
- (if (not org-element--cache) (org-element-cache-reset)
+ (if (not (org-with-base-buffer nil org-element--cache)) (org-element-cache-reset)
(unless cached-only (org-element--cache-sync (current-buffer) pom))))
(setq element (if cached-only
(when (and (org-element--cache-active-p)
diff --git a/lisp/org/org-entities.el b/lisp/org/org-entities.el
index 61083022b82..5820c7428cd 100644
--- a/lisp/org/org-entities.el
+++ b/lisp/org/org-entities.el
@@ -1,10 +1,10 @@
;;; org-entities.el --- Support for Special Entities -*- lexical-binding: t; -*-
-;; Copyright (C) 2010-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2010-2024 Free Software Foundation, Inc.
;; Author: Carsten Dominik <carsten.dominik@gmail.com>,
;; Ulf Stegemann <ulf at zeitform dot de>
-;; Keywords: outlines, calendar, wp
+;; Keywords: outlines, calendar, text
;; URL: https://orgmode.org
;;
;; This file is part of GNU Emacs.
@@ -41,14 +41,19 @@
(defun org-entities--user-safe-p (v)
"Non-nil if V is a safe value for `org-entities-user'."
- (pcase v
- (`nil t)
- (`(,(and (pred stringp)
- (pred (string-match-p "\\`[a-zA-Z][a-zA-Z0-9]*\\'")))
- ,(pred stringp) ,(pred booleanp) ,(pred stringp)
- ,(pred stringp) ,(pred stringp) ,(pred stringp))
- t)
- (_ nil)))
+ (cond
+ ((not v) t)
+ ((listp v)
+ (seq-every-p
+ (lambda (e)
+ (pcase e
+ (`(,(and (pred stringp)
+ (pred (string-match-p "\\`[a-zA-Z][a-zA-Z0-9]*\\'")))
+ ,(pred stringp) ,(pred booleanp) ,(pred stringp)
+ ,(pred stringp) ,(pred stringp) ,(pred stringp))
+ t)
+ (_ nil)))
+ v))))
(defcustom org-entities-user nil
"User-defined entities used in Org to produce special characters.
diff --git a/lisp/org/org-faces.el b/lisp/org/org-faces.el
index bb0958033fe..cb5c423ad0f 100644
--- a/lisp/org/org-faces.el
+++ b/lisp/org/org-faces.el
@@ -1,9 +1,9 @@
;;; org-faces.el --- Face definitions -*- lexical-binding: t; -*-
-;; Copyright (C) 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2004-2024 Free Software Foundation, Inc.
;; Author: Carsten Dominik <carsten.dominik@gmail.com>
-;; Keywords: outlines, hypermedia, calendar, wp
+;; Keywords: outlines, hypermedia, calendar, text
;; URL: https://orgmode.org
;;
;; This file is part of GNU Emacs.
diff --git a/lisp/org/org-feed.el b/lisp/org/org-feed.el
index f0b294b4a59..e4035dd4e96 100644
--- a/lisp/org/org-feed.el
+++ b/lisp/org/org-feed.el
@@ -1,9 +1,9 @@
;;; org-feed.el --- Add RSS feed items to Org files -*- lexical-binding: t; -*-
;;
-;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
;;
;; Author: Carsten Dominik <carsten.dominik@gmail.com>
-;; Keywords: outlines, hypermedia, calendar, wp
+;; Keywords: outlines, hypermedia, calendar, text
;; URL: https://orgmode.org
;;
;; This file is part of GNU Emacs.
diff --git a/lisp/org/org-fold-core.el b/lisp/org/org-fold-core.el
index 6c17b00faf8..73b3c9bbf8c 100644
--- a/lisp/org/org-fold-core.el
+++ b/lisp/org/org-fold-core.el
@@ -1,6 +1,6 @@
;;; org-fold-core.el --- Folding buffer text -*- lexical-binding: t; -*-
;;
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
;;
;; Author: Ihor Radchenko <yantar92 at gmail dot com>
;; Keywords: folding, invisible text
diff --git a/lisp/org/org-fold.el b/lisp/org/org-fold.el
index 1b7ca22b044..241324624c9 100644
--- a/lisp/org/org-fold.el
+++ b/lisp/org/org-fold.el
@@ -1,6 +1,6 @@
;;; org-fold.el --- Folding of Org entries -*- lexical-binding: t; -*-
;;
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
;;
;; Author: Ihor Radchenko <yantar92 at gmail dot com>
;; Keywords: folding, invisible text
diff --git a/lisp/org/org-footnote.el b/lisp/org/org-footnote.el
index 6bdd0b32fed..608d694294c 100644
--- a/lisp/org/org-footnote.el
+++ b/lisp/org/org-footnote.el
@@ -1,9 +1,9 @@
;;; org-footnote.el --- Footnote support in Org -*- lexical-binding: t; -*-
;;
-;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
;;
;; Author: Carsten Dominik <carsten.dominik@gmail.com>
-;; Keywords: outlines, hypermedia, calendar, wp
+;; Keywords: outlines, hypermedia, calendar, text
;; URL: https://orgmode.org
;;
;; This file is part of GNU Emacs.
diff --git a/lisp/org/org-goto.el b/lisp/org/org-goto.el
index 00bf5d46aaa..e9df4057e4b 100644
--- a/lisp/org/org-goto.el
+++ b/lisp/org/org-goto.el
@@ -1,9 +1,9 @@
;;; org-goto.el --- Fast navigation in an Org buffer -*- lexical-binding: t; -*-
-;; Copyright (C) 2012-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2012-2024 Free Software Foundation, Inc.
;; Author: Carsten Dominik <carsten.dominik@gmail.com>
-;; Keywords: outlines, hypermedia, calendar, wp
+;; Keywords: outlines, hypermedia, calendar, text
;; This file is part of GNU Emacs.
diff --git a/lisp/org/org-habit.el b/lisp/org/org-habit.el
index fb6a48b5f55..ca2910e1538 100644
--- a/lisp/org/org-habit.el
+++ b/lisp/org/org-habit.el
@@ -1,9 +1,9 @@
;;; org-habit.el --- The habit tracking code for Org -*- lexical-binding: t; -*-
-;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
;; Author: John Wiegley <johnw at gnu dot org>
-;; Keywords: outlines, hypermedia, calendar, wp
+;; Keywords: outlines, hypermedia, calendar, text
;; URL: https://orgmode.org
;;
;; This file is part of GNU Emacs.
diff --git a/lisp/org/org-id.el b/lisp/org/org-id.el
index 490e4ddee5b..9586b728e70 100644
--- a/lisp/org/org-id.el
+++ b/lisp/org/org-id.el
@@ -1,9 +1,9 @@
;;; org-id.el --- Global identifiers for Org entries -*- lexical-binding: t; -*-
;;
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
;;
;; Author: Carsten Dominik <carsten.dominik@gmail.com>
-;; Keywords: outlines, hypermedia, calendar, wp
+;; Keywords: outlines, hypermedia, calendar, text
;; URL: https://orgmode.org
;;
;; This file is part of GNU Emacs.
diff --git a/lisp/org/org-indent.el b/lisp/org/org-indent.el
index fe52338788c..a612e1c9dc9 100644
--- a/lisp/org/org-indent.el
+++ b/lisp/org/org-indent.el
@@ -1,9 +1,9 @@
;;; org-indent.el --- Dynamic indentation for Org -*- lexical-binding: t; -*-
-;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
;;
;; Author: Carsten Dominik <carsten.dominik@gmail.com>
-;; Keywords: outlines, hypermedia, calendar, wp
+;; Keywords: outlines, hypermedia, calendar, text
;; URL: https://orgmode.org
;;
;; This file is part of GNU Emacs.
diff --git a/lisp/org/org-inlinetask.el b/lisp/org/org-inlinetask.el
index cb7fdf88bde..7cbdaae4e8e 100644
--- a/lisp/org/org-inlinetask.el
+++ b/lisp/org/org-inlinetask.el
@@ -1,9 +1,9 @@
;;; org-inlinetask.el --- Tasks Independent of Outline Hierarchy -*- lexical-binding: t; -*-
-;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
;;
;; Author: Carsten Dominik <carsten.dominik@gmail.com>
-;; Keywords: outlines, hypermedia, calendar, wp
+;; Keywords: outlines, hypermedia, calendar, text
;; URL: https://orgmode.org
;; This file is part of GNU Emacs.
diff --git a/lisp/org/org-keys.el b/lisp/org/org-keys.el
index 37a150bb7bf..a0dbb289dba 100644
--- a/lisp/org/org-keys.el
+++ b/lisp/org/org-keys.el
@@ -1,6 +1,6 @@
;;; org-keys.el --- Key bindings for Org mode -*- lexical-binding: t; -*-
-;; Copyright (C) 2018-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2018-2024 Free Software Foundation, Inc.
;; Author: Nicolas Goaziou <mail@nicolasgoaziou.fr>
diff --git a/lisp/org/org-lint.el b/lisp/org/org-lint.el
index 0e2967b6cb6..5a202808e76 100644
--- a/lisp/org/org-lint.el
+++ b/lisp/org/org-lint.el
@@ -1,9 +1,9 @@
;;; org-lint.el --- Linting for Org documents -*- lexical-binding: t; -*-
-;; Copyright (C) 2015-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2024 Free Software Foundation, Inc.
;; Author: Nicolas Goaziou <mail@nicolasgoaziou.fr>
-;; Keywords: outlines, hypermedia, calendar, wp
+;; Keywords: outlines, hypermedia, calendar, text
;; This file is part of GNU Emacs.
diff --git a/lisp/org/org-list.el b/lisp/org/org-list.el
index 1fc99d0708a..dbef7a82b1f 100644
--- a/lisp/org/org-list.el
+++ b/lisp/org/org-list.el
@@ -1,10 +1,10 @@
;;; org-list.el --- Plain lists for Org -*- lexical-binding: t; -*-
;;
-;; Copyright (C) 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2004-2024 Free Software Foundation, Inc.
;;
;; Author: Carsten Dominik <carsten.dominik@gmail.com>
;; Bastien Guerry <bzg@gnu.org>
-;; Keywords: outlines, hypermedia, calendar, wp
+;; Keywords: outlines, hypermedia, calendar, text
;; URL: https://orgmode.org
;;
;; This file is part of GNU Emacs.
diff --git a/lisp/org/org-macro.el b/lisp/org/org-macro.el
index 481e431c2f9..737eab5d2bb 100644
--- a/lisp/org/org-macro.el
+++ b/lisp/org/org-macro.el
@@ -1,9 +1,9 @@
;;; org-macro.el --- Macro Replacement Code for Org -*- lexical-binding: t; -*-
-;; Copyright (C) 2013-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2024 Free Software Foundation, Inc.
;; Author: Nicolas Goaziou <n.goaziou@gmail.com>
-;; Keywords: outlines, hypermedia, calendar, wp
+;; Keywords: outlines, hypermedia, calendar, text
;; This file is part of GNU Emacs.
diff --git a/lisp/org/org-macs.el b/lisp/org/org-macs.el
index 4efa8ba6800..5df6062e464 100644
--- a/lisp/org/org-macs.el
+++ b/lisp/org/org-macs.el
@@ -1,9 +1,9 @@
;;; org-macs.el --- Top-level Definitions for Org -*- lexical-binding: t; -*-
-;; Copyright (C) 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2004-2024 Free Software Foundation, Inc.
;; Author: Carsten Dominik <carsten.dominik@gmail.com>
-;; Keywords: outlines, hypermedia, calendar, wp
+;; Keywords: outlines, hypermedia, calendar, text
;; URL: https://orgmode.org
;;
;; This file is part of GNU Emacs.
@@ -56,8 +56,8 @@ by `package-activate-all').")
;; `org-assert-version' calls would fail using strict
;; `org-git-version' check because the generated Org version strings
;; will not match.
- `(unless (or org--inhibit-version-check (equal (org-release) ,(org-release)))
- (warn "Org version mismatch. Org loading aborted.
+ `(unless (or ,org--inhibit-version-check (equal (org-release) ,(org-release)))
+ (warn "Org version mismatch.
This warning usually appears when a built-in Org version is loaded
prior to the more recent Org version.
@@ -91,10 +91,15 @@ Version mismatch is commonly encountered in the following situations:
early in the config. Ideally, right after the straight.el
bootstrap. Moving `use-package' :straight declaration may not be
sufficient if the corresponding `use-package' statement is
- deferring the loading."
+ deferring the loading.
+
+4. A new Org version is synchronized with Emacs git repository and
+ stale .elc files are still left from the previous build.
+
+ It is recommended to remove .elc files from lisp/org directory and
+ re-compile."
;; Avoid `warn' replacing "'" with "’" (see `format-message').
- "(straight-use-package 'org)")
- (error "Org version mismatch. Make sure that correct `load-path' is set early in init.el")))
+ "(straight-use-package 'org)")))
;; We rely on org-macs when generating Org version. Checking Org
;; version here will interfere with Org build process.
@@ -1119,7 +1124,12 @@ Return width in pixels when PIXELS is non-nil."
(setq pixel-width
(if (get-buffer-window (current-buffer))
(car (window-text-pixel-size
- nil (line-beginning-position) (point-max)))
+ ;; FIXME: 10000 because
+ ;; `most-positive-fixnum' ain't working
+ ;; (tests failing) and this call will be
+ ;; removed after we drop Emacs 28 support
+ ;; anyway.
+ nil (line-beginning-position) (point-max) 10000))
(let ((dedicatedp (window-dedicated-p))
(oldbuffer (window-buffer)))
(unwind-protect
@@ -1128,7 +1138,7 @@ Return width in pixels when PIXELS is non-nil."
(set-window-dedicated-p nil nil)
(set-window-buffer nil (current-buffer))
(car (window-text-pixel-size
- nil (line-beginning-position) (point-max))))
+ nil (line-beginning-position) (point-max) 10000)))
(set-window-buffer nil oldbuffer)
(set-window-dedicated-p nil dedicatedp)))))
(unless pixels
@@ -1137,7 +1147,7 @@ Return width in pixels when PIXELS is non-nil."
(setq symbol-width
(if (get-buffer-window (current-buffer))
(car (window-text-pixel-size
- nil (line-beginning-position) (point-max)))
+ nil (line-beginning-position) (point-max) 10000))
(let ((dedicatedp (window-dedicated-p))
(oldbuffer (window-buffer)))
(unwind-protect
@@ -1146,7 +1156,7 @@ Return width in pixels when PIXELS is non-nil."
(set-window-dedicated-p nil nil)
(set-window-buffer nil (current-buffer))
(car (window-text-pixel-size
- nil (line-beginning-position) (point-max))))
+ nil (line-beginning-position) (point-max) 10000)))
(set-window-buffer nil oldbuffer)
(set-window-dedicated-p nil dedicatedp)))))))
(if pixels
diff --git a/lisp/org/org-mobile.el b/lisp/org/org-mobile.el
index 01395a4b616..c34011fc3dc 100644
--- a/lisp/org/org-mobile.el
+++ b/lisp/org/org-mobile.el
@@ -1,8 +1,8 @@
;;; org-mobile.el --- Code for Asymmetric Sync With a Mobile Device -*- lexical-binding: t; -*-
-;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
;;
;; Author: Carsten Dominik <carsten.dominik@gmail.com>
-;; Keywords: outlines, hypermedia, calendar, wp
+;; Keywords: outlines, hypermedia, calendar, text
;; URL: https://orgmode.org
;;
;; This file is part of GNU Emacs.
diff --git a/lisp/org/org-mouse.el b/lisp/org/org-mouse.el
index e0671f3d7d5..35d1b6f1ce1 100644
--- a/lisp/org/org-mouse.el
+++ b/lisp/org/org-mouse.el
@@ -1,6 +1,6 @@
;;; org-mouse.el --- Better mouse support for Org -*- lexical-binding: t; -*-
-;; Copyright (C) 2006-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2006-2024 Free Software Foundation, Inc.
;; Author: Piotr Zielinski <piotr dot zielinski at gmail dot com>
;; Maintainer: Carsten Dominik <carsten.dominik@gmail.com>
@@ -859,6 +859,10 @@ This means, between the beginning of line and the point."
(org-mouse-in-region-p (posn-point (event-start event))))
(mouse-drag-region event)))
+;; This function conflicts with touch screen gestures as it relays
+;; events to `mouse-drag-region'.
+(put 'org-mouse-down-mouse 'ignored-mouse-command t)
+
(add-hook 'org-mode-hook
(lambda ()
(setq org-mouse-context-menu-function #'org-mouse-context-menu)
diff --git a/lisp/org/org-num.el b/lisp/org/org-num.el
index 807fa66223b..00a25b11e53 100644
--- a/lisp/org/org-num.el
+++ b/lisp/org/org-num.el
@@ -1,9 +1,9 @@
;;; org-num.el --- Dynamic Headlines Numbering -*- lexical-binding: t; -*-
-;; Copyright (C) 2018-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2018-2024 Free Software Foundation, Inc.
;; Author: Nicolas Goaziou <mail@nicolasgoaziou.fr>
-;; Keywords: outlines, hypermedia, calendar, wp
+;; Keywords: outlines, hypermedia, calendar, text
;; This file is part of GNU Emacs.
diff --git a/lisp/org/org-pcomplete.el b/lisp/org/org-pcomplete.el
index 0567052c089..c793563570b 100644
--- a/lisp/org/org-pcomplete.el
+++ b/lisp/org/org-pcomplete.el
@@ -1,10 +1,10 @@
;;; org-pcomplete.el --- In-buffer Completion Code -*- lexical-binding: t; -*-
-;; Copyright (C) 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2004-2024 Free Software Foundation, Inc.
;;
;; Author: Carsten Dominik <carsten.dominik@gmail.com>
;; John Wiegley <johnw at gnu dot org>
-;; Keywords: outlines, hypermedia, calendar, wp
+;; Keywords: outlines, hypermedia, calendar, text
;; URL: https://orgmode.org
;;
;; This file is part of GNU Emacs.
diff --git a/lisp/org/org-persist.el b/lisp/org/org-persist.el
index 01078f4596d..9acf35bd488 100644
--- a/lisp/org/org-persist.el
+++ b/lisp/org/org-persist.el
@@ -1,6 +1,6 @@
;;; org-persist.el --- Persist cached data across Emacs sessions -*- lexical-binding: t; -*-
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
;; Author: Ihor Radchenko <yantar92 at gmail dot com>
;; Keywords: cache, storage
@@ -111,7 +111,7 @@
;;
;; Each collection is represented as a plist containing the following
;; properties:
-;; - `:container' : list of data continers to be stored in single
+;; - `:container' : list of data containers to be stored in single
;; file;
;; - `:persist-file': data file name;
;; - `:associated' : list of associated objects;
@@ -253,7 +253,7 @@ The index is a list of plists. Each plist contains information about
persistent data storage. Each plist contains the following
properties:
- - `:container' : list of data continers to be stored in single file
+ - `:container' : list of data containers to be stored in single file
- `:persist-file': data file name
- `:associated' : list of associated objects
- `:last-access' : last date when the container has been read
@@ -481,9 +481,14 @@ MISC, if non-nil will be appended to the collection. It must be a plist."
(unless (stringp associated)
(setq associated (cadr associated)))
(let* ((rtn `(:file ,associated))
- (inode (and (fboundp 'file-attribute-inode-number)
- (file-attribute-inode-number
- (file-attributes associated)))))
+ (inode (and
+ ;; Do not store :inode for remote files - it may
+ ;; be time-consuming on slow connections or even
+ ;; fail completely when ssh connection is closed.
+ (not (file-remote-p associated))
+ (fboundp 'file-attribute-inode-number)
+ (file-attribute-inode-number
+ (file-attributes associated)))))
(when inode (plist-put rtn :inode inode))
rtn))
((or (pred bufferp) `(:buffer ,_))
@@ -501,6 +506,10 @@ MISC, if non-nil will be appended to the collection. It must be a plist."
(or (buffer-base-buffer associated)
associated)))
(setq inode (when (and file
+ ;; Do not store :inode for remote files - it may
+ ;; be time-consuming on slow connections or even
+ ;; fail completely when ssh connection is closed.
+ (not (file-remote-p file))
(fboundp 'file-attribute-inode-number))
(file-attribute-inode-number
(file-attributes file))))
diff --git a/lisp/org/org-plot.el b/lisp/org/org-plot.el
index fe61e9ace7e..3fea8b5b8b4 100644
--- a/lisp/org/org-plot.el
+++ b/lisp/org/org-plot.el
@@ -1,6 +1,6 @@
;;; org-plot.el --- Support for Plotting from Org -*- lexical-binding: t; -*-
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
;;
;; Author: Eric Schulte <schulte dot eric at gmail dot com>
;; Maintainer: TEC <orgmode@tec.tecosaur.net>
diff --git a/lisp/org/org-protocol.el b/lisp/org/org-protocol.el
index 2b07a377e2a..61a9229adf1 100644
--- a/lisp/org/org-protocol.el
+++ b/lisp/org/org-protocol.el
@@ -1,13 +1,13 @@
;;; org-protocol.el --- Intercept Calls from Emacsclient to Trigger Custom Actions -*- lexical-binding: t; -*-
;;
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
;;
;; Authors: Bastien Guerry <bzg@gnu.org>
;; Daniel M German <dmg AT uvic DOT org>
;; Sebastian Rose <sebastian_rose AT gmx DOT de>
;; Ross Patterson <me AT rpatterson DOT net>
;; Maintainer: Sebastian Rose <sebastian_rose AT gmx DOT de>
-;; Keywords: org, emacsclient, wp
+;; Keywords: org, emacsclient, text
;; This file is part of GNU Emacs.
;;
@@ -34,7 +34,10 @@
;; `org-protocol-protocol-alist' and `org-protocol-protocol-alist-default'.
;;
;; Any application that supports calling external programs with an URL
-;; as argument may be used with this functionality.
+;; as argument could use this functionality. For example, you can
+;; configure bookmarks in your web browser to send a link to the
+;; current page to Org and create a note from it using `org-capture'.
+;; See Info node `(org) Protocols' for more information.
;;
;;
;; Usage:
@@ -44,13 +47,13 @@
;;
;; (require 'org-protocol)
;;
-;; 3.) Ensure emacs-server is up and running.
-;; 4.) Try this from the command line (adjust the URL as needed):
+;; 2.) Ensure emacs-server is up and running.
+;; 3.) Try this from the command line (adjust the URL as needed):
;;
;; $ emacsclient \
;; "org-protocol://store-link?url=http:%2F%2Flocalhost%2Findex.html&title=The%20title"
;;
-;; 5.) Optionally add custom sub-protocols and handlers:
+;; 4.) Optionally, add custom sub-protocols and handlers:
;;
;; (setq org-protocol-protocol-alist
;; '(("my-protocol"
@@ -64,10 +67,11 @@
;; If it works, you can now setup other applications for using this feature.
;;
;;
-;; As of March 2009 Firefox users follow the steps documented on
-;; https://kb.mozillazine.org/Register_protocol, Opera setup is described here:
-;; http://www.opera.com/support/kb/view/535/
+;; Firefox users follow the steps documented on
+;; https://kb.mozillazine.org/Register_protocol, Opera setup is
+;; described here: http://www.opera.com/support/kb/view/535/
;;
+;; See also: https://orgmode.org/worg/org-contrib/org-protocol.html
;;
;; Documentation
;; -------------
@@ -123,9 +127,6 @@
;; Note that using double slashes is optional from org-protocol.el's point of
;; view because emacsclient squashes the slashes to one.
;;
-;;
-;; provides: 'org-protocol
-;;
;;; Code:
(require 'org-macs)
diff --git a/lisp/org/org-refile.el b/lisp/org/org-refile.el
index 5a41c022fee..4f204c739fa 100644
--- a/lisp/org/org-refile.el
+++ b/lisp/org/org-refile.el
@@ -1,9 +1,9 @@
;;; org-refile.el --- Refile Org Subtrees -*- lexical-binding: t; -*-
-;; Copyright (C) 2010-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2010-2024 Free Software Foundation, Inc.
;; Author: Carsten Dominik <carsten.dominik@gmail.com>
-;; Keywords: outlines, hypermedia, calendar, wp
+;; Keywords: outlines, hypermedia, calendar, text
;;
;; This file is part of GNU Emacs.
diff --git a/lisp/org/org-src.el b/lisp/org/org-src.el
index aadd8eba579..8cc11965812 100644
--- a/lisp/org/org-src.el
+++ b/lisp/org/org-src.el
@@ -1,11 +1,11 @@
;;; org-src.el --- Source code examples in Org -*- lexical-binding: t; -*-
;;
-;; Copyright (C) 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2004-2024 Free Software Foundation, Inc.
;;
;; Author: Carsten Dominik <carsten.dominik@gmail.com>
;; Bastien Guerry <bzg@gnu.org>
;; Dan Davison <davison at stats dot ox dot ac dot uk>
-;; Keywords: outlines, hypermedia, calendar, wp
+;; Keywords: outlines, hypermedia, calendar, text
;; URL: https://orgmode.org
;;
;; This file is part of GNU Emacs.
@@ -658,7 +658,9 @@ as `org-src-fontify-natively' is non-nil."
(when new-prop
(if (not (eq prop 'invisible))
(put-text-property
- (+ start (1- pos)) (1- (+ start next)) prop new-prop
+ (+ start (- pos (point-min)))
+ (+ start (- next (point-min)))
+ prop new-prop
org-buffer)
;; Special case. `invisible' text property may
;; clash with Org folding. Do not assign
@@ -690,7 +692,8 @@ as `org-src-fontify-natively' is non-nil."
(when invisibility-spec
(add-to-invisibility-spec invisibility-spec))
(put-text-property
- (+ start (1- pos)) (1- (+ start next))
+ (+ start (- pos (point-min)))
+ (+ start (- next (point-min)))
'org-src-invisible new-prop
org-buffer)))))))
(setq pos next)))
diff --git a/lisp/org/org-table.el b/lisp/org/org-table.el
index 221497f53b7..bf0f503da2e 100644
--- a/lisp/org/org-table.el
+++ b/lisp/org/org-table.el
@@ -1,9 +1,9 @@
;;; org-table.el --- The Table Editor for Org -*- lexical-binding: t; -*-
-;; Copyright (C) 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2004-2024 Free Software Foundation, Inc.
;; Author: Carsten Dominik <carsten.dominik@gmail.com>
-;; Keywords: outlines, hypermedia, calendar, wp
+;; Keywords: outlines, hypermedia, calendar, text
;; URL: https://orgmode.org
;;
;; This file is part of GNU Emacs.
@@ -417,7 +417,7 @@ It is probably good to never set this variable to nil, for the sake of
portability of tables."
:group 'org-table-calculation
:type '(choice
- (const :tag "Allow to cross" t)
+ (const :tag "Allow crossing hline" t)
(const :tag "Stick to hline" nil)
(const :tag "Error on attempt to cross" error)))
@@ -3900,7 +3900,7 @@ When non-nil, return the overlay narrowing the field."
;; Aligning table from the first row will not shrink again the
;; second row, which was not visible initially.
;;
- ;; However, fixing it requires to check every row, which may be
+ ;; However, fixing it requires checking every row, which may be
;; slow on large tables. Moreover, the hindrance of this
;; pathological case is very limited.
(beginning-of-line)
@@ -4894,7 +4894,7 @@ This function sets up the following dynamically scoped variables:
(push (cons field v) org-table-local-parameters)
(push (list field line col)
org-table-named-field-locations))))))))))
- ;; Re-use existing markers when possible.
+ ;; Reuse existing markers when possible.
(if (markerp org-table-current-begin-pos)
(move-marker org-table-current-begin-pos (point))
(setq org-table-current-begin-pos (point-marker)))
diff --git a/lisp/org/org-tempo.el b/lisp/org/org-tempo.el
index 81ec8fdccfe..638f0ea3f4a 100644
--- a/lisp/org/org-tempo.el
+++ b/lisp/org/org-tempo.el
@@ -1,9 +1,9 @@
;;; org-tempo.el --- Template expansion for Org structures -*- lexical-binding: t; -*-
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
;;
;; Author: Rasmus Pank Roulund <emacs at pank dot eu>
-;; Keywords: outlines, hypermedia, calendar, wp
+;; Keywords: outlines, hypermedia, calendar, text
;; URL: https://orgmode.org
;;
;; This file is part of GNU Emacs.
diff --git a/lisp/org/org-timer.el b/lisp/org/org-timer.el
index 919630e696f..561b2bc0f83 100644
--- a/lisp/org/org-timer.el
+++ b/lisp/org/org-timer.el
@@ -1,9 +1,9 @@
;;; org-timer.el --- Timer code for Org mode -*- lexical-binding: t; -*-
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
;; Author: Carsten Dominik <carsten.dominik@gmail.com>
-;; Keywords: outlines, hypermedia, calendar, wp
+;; Keywords: outlines, hypermedia, calendar, text
;; URL: https://orgmode.org
;;
;; This file is part of GNU Emacs.
diff --git a/lisp/org/org-version.el b/lisp/org/org-version.el
index 57e406b24fc..b41756ac53e 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.6.7"))
+ (let ((org-release "9.6.15"))
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.6.7-13-g99cc96"))
+ (let ((org-git-version "release_9.6.15"))
org-git-version))
(provide 'org-version)
diff --git a/lisp/org/org.el b/lisp/org/org.el
index 175e095e806..2c5de69a36c 100644
--- a/lisp/org/org.el
+++ b/lisp/org/org.el
@@ -1,15 +1,15 @@
;;; org.el --- Outline-based notes management and organizer -*- lexical-binding: t; -*-
;; Carstens outline-mode for keeping track of everything.
-;; Copyright (C) 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2004-2024 Free Software Foundation, Inc.
;;
;; Author: Carsten Dominik <carsten.dominik@gmail.com>
;; Maintainer: Bastien Guerry <bzg@gnu.org>
-;; Keywords: outlines, hypermedia, calendar, wp
+;; Keywords: outlines, hypermedia, calendar, text
;; URL: https://orgmode.org
;; Package-Requires: ((emacs "26.1"))
-;; Version: 9.6.7
+;; Version: 9.6.15
;; This file is part of GNU Emacs.
;;
@@ -1021,7 +1021,7 @@ time."
This is useful since some lines containing links can be very long and
uninteresting. Also tables look terrible when wrapped.
-The variable `org-startup-truncated' allows to configure
+The variable `org-startup-truncated' enables you to configure
truncation for Org mode different to the other modes that use the
variable `truncate-lines' and as a shortcut instead of putting
the variable `truncate-lines' into the `org-mode-hook'. If one
@@ -1230,7 +1230,7 @@ This applies to indirect buffers created with the commands
Valid values are:
current-window Display in the current window
other-window Just display in another window.
-dedicated-frame Create one new frame, and re-use it each time.
+dedicated-frame Create one new frame, and reuse it each time.
new-frame Make a new frame each time. Note that in this case
previously-made indirect buffers are kept, and you need to
kill these buffers yourself."
@@ -1321,14 +1321,15 @@ Possible values for the file identifier are:
to open [[file:document.pdf::5]] with evince at page 5.
Likely, you will need more entries: without page
- number; with search pattern; with cross-reference
- anchor; some combination of options. Consider simple
- pattern here and a Lisp function to determine command
- line arguments instead. Passing argument list to
- `call-process' or `make-process' directly allows to
- avoid treating some character in peculiar file names
- as shell specialls causing executing part of file
- name as a subcommand.
+ number; with search pattern; with
+ cross-reference anchor; some combination of
+ options. Consider simple pattern here and a
+ Lisp function to determine command line
+ arguments instead. Passing an argument list to
+ `call-process' or `make-process' directly avoids
+ treating some character in peculiar file names
+ as shell specials that prompt parts of said file
+ names to be executed as subcommands.
`directory' Matches a directory
`remote' Matches a remote file, accessible through tramp.
@@ -3760,7 +3761,6 @@ This is needed for font-lock setup.")
(defvar calc-embedded-close-formula)
(defvar calc-embedded-open-formula)
(defvar calc-embedded-open-mode)
-(defvar font-lock-unfontify-region-function)
(defvar org-agenda-tags-todo-honor-ignore-options)
(defvar remember-data-file)
(defvar texmathp-why)
@@ -4582,7 +4582,7 @@ is available. This option applies only if FILE is a URL."
file)
nil))
(error (if noerror
- (message "Org could't download \"%s\": %s %S" file (car error) (cdr error))
+ (message "Org couldn't download \"%s\": %s %S" file (car error) (cdr error))
(signal (car error) (cdr error)))))
(funcall (if noerror #'message #'user-error)
"The remote resource %S is considered unsafe, and will not be downloaded."
@@ -6323,7 +6323,10 @@ unconditionally."
(if (not level) (outline-next-heading) ;before first headline
(org-back-to-heading invisible-ok)
(when (equal arg '(16)) (org-up-heading-safe))
- (org-end-of-subtree)))
+ (org-end-of-subtree invisible-ok 'to-heading)))
+ ;; At `point-max', if the file does not have ending newline,
+ ;; create one, so that we are not appending stars at non-empty
+ ;; line.
(unless (bolp) (insert "\n"))
(when (and blank? (save-excursion
(backward-char)
@@ -6335,7 +6338,9 @@ unconditionally."
(backward-char))
(unless (and blank? (org-previous-line-empty-p))
(org-N-empty-lines-before-current (if blank? 1 0)))
- (insert stars " ")
+ (insert stars " " "\n")
+ ;; Move point after stars.
+ (backward-char)
;; When INVISIBLE-OK is non-nil, ensure newly created headline
;; is visible.
(unless invisible-ok
@@ -11341,7 +11346,7 @@ See also `org-scan-tags'."
(let ((match0 match)
(re (concat
"^&?\\([-+:]\\)?\\({[^}]+}\\|LEVEL\\([<=>]\\{1,2\\}\\)"
- "\\([0-9]+\\)\\|\\(\\(?:[[:alnum:]_]+\\(?:\\\\-\\)*\\)+\\)"
+ "\\([0-9]+\\)\\|\\([[:alnum:]_]\\(?:[[:alnum:]_]\\|\\\\-\\)*\\)"
"\\([<>=]\\{1,2\\}\\)"
"\\({[^}]+}\\|\"[^\"]*\"\\|-?[.0-9]+\\(?:[eE][-+]?[0-9]+\\)?\\)"
"\\|" org-tag-re "\\)"))
@@ -13223,7 +13228,7 @@ Optional argument DEFAULT provides a default value for PROPERTY."
nil nil nil nil default-prop)))
(defun org-set-property-and-value (use-last)
- "Allow to set [PROPERTY]: [value] direction from prompt.
+ "Allow setting [PROPERTY]: [value] direction from prompt.
When use-default, don't even ask, just use the last
\"[PROPERTY]: [value]\" string from the history."
(interactive "P")
@@ -14030,6 +14035,7 @@ user."
(unless deltadef
(let ((now (decode-time)))
(setq day (nth 3 now) month (nth 4 now) year (nth 5 now))))
+ ;; FIXME: Duplicated value in ‘cond’: ""
(cond ((member deltaw '("h" ""))
(when (boundp 'org-time-was-given)
(setq org-time-was-given t))
@@ -14754,12 +14760,12 @@ is considered `day' (i.e. only `bracket', `day', and `after' return
values are possible).
When matching, the match groups are the following:
- group 1: year, if any
- group 2: month, if any
- group 3: day number, if any
- group 4: day name, if any
- group 5: hours, if any
- group 6: minutes, if any"
+ group 2: year, if any
+ group 3: month, if any
+ group 4: day number, if any
+ group 5: day name, if any
+ group 7: hours, if any
+ group 8: minutes, if any"
(let* ((regexp
(if extended
(if (eq extended 'agenda)
@@ -17650,8 +17656,8 @@ region."
(defun org-open-line (n)
"Insert a new row in tables, call `open-line' elsewhere.
If `org-special-ctrl-o' is nil, just call `open-line' everywhere.
-As a special case, when a document starts with a table, allow to
-call `open-line' on the very first character."
+As a special case, when a document starts with a table, allow
+calling `open-line' on the very first character."
(interactive "*p")
(if (and org-special-ctrl-o (/= (point) 1) (org-at-table-p))
(org-table-insert-row)
@@ -17663,6 +17669,8 @@ If INDENT is non-nil, call `newline-and-indent' with ARG to
indent unconditionally; otherwise, call `newline' with ARG and
INTERACTIVE, which can trigger indentation if
`electric-indent-mode' is enabled."
+ (when interactive
+ (org-fold-check-before-invisible-edit 'insert))
(if indent
(org-newline-and-indent arg)
(newline arg interactive)))
@@ -18865,9 +18873,7 @@ ELEMENT."
(goto-char start)
(current-indentation)))
;; In any other case, indent like the current line.
- (t (current-indentation)))))
- ;; Finally, no indentation is needed, fall back to 0.
- (t (current-indentation))))))
+ (t (current-indentation)))))))))
(defun org--align-node-property ()
"Align node property at point.
@@ -19979,7 +19985,7 @@ With argument N not nil or 1, move forward N - 1 lines first."
(if (eq special 'reversed)
(when (and (= origin bol) (eq last-command this-command))
(goto-char refpos))
- (when (or (> origin refpos) (= origin bol))
+ (when (or (> origin refpos) (<= origin bol))
(goto-char refpos)))))
((and (looking-at org-list-full-item-re)
(memq (org-element-type (save-match-data (org-element-at-point)))
@@ -19994,7 +20000,7 @@ With argument N not nil or 1, move forward N - 1 lines first."
(if (eq special 'reversed)
(when (and (= (point) origin) (eq last-command this-command))
(goto-char after-bullet))
- (when (or (> origin after-bullet) (= (point) origin))
+ (when (or (> origin after-bullet) (>= (point) origin))
(goto-char after-bullet)))))
;; No special context. Point is already at beginning of line.
(t nil))))
@@ -20049,7 +20055,7 @@ With argument N not nil or 1, move forward N - 1 lines first."
(goto-char tags)
(end-of-line)))
(t
- (if (or (< origin tags) (= origin (line-end-position)))
+ (if (or (< origin tags) (>= origin (line-end-position)))
(goto-char tags)
(end-of-line))))))
((bound-and-true-p visual-line-mode)
diff --git a/lisp/org/ox-ascii.el b/lisp/org/ox-ascii.el
index 692dd216d61..74fbe20e85d 100644
--- a/lisp/org/ox-ascii.el
+++ b/lisp/org/ox-ascii.el
@@ -1,10 +1,10 @@
;;; ox-ascii.el --- ASCII Back-End for Org Export Engine -*- lexical-binding: t; -*-
-;; Copyright (C) 2012-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2012-2024 Free Software Foundation, Inc.
;; Author: Nicolas Goaziou <n.goaziou at gmail dot com>
;; Maintainer: Nicolas Goaziou <mail@nicolasgoaziou.fr>
-;; Keywords: outlines, hypermedia, calendar, wp
+;; Keywords: outlines, hypermedia, calendar, text
;; This file is part of GNU Emacs.
diff --git a/lisp/org/ox-beamer.el b/lisp/org/ox-beamer.el
index 689bf1559b4..3d4d998432d 100644
--- a/lisp/org/ox-beamer.el
+++ b/lisp/org/ox-beamer.el
@@ -1,11 +1,11 @@
;;; ox-beamer.el --- Beamer Back-End for Org Export Engine -*- lexical-binding: t; -*-
-;; Copyright (C) 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2024 Free Software Foundation, Inc.
;; Author: Carsten Dominik <carsten.dominik AT gmail DOT com>
;; Nicolas Goaziou <n.goaziou AT gmail DOT com>
;; Maintainer: Nicolas Goaziou <mail@nicolasgoaziou.fr>
-;; Keywords: org, wp, tex
+;; Keywords: org, text, tex
;; This file is part of GNU Emacs.
@@ -924,13 +924,12 @@ holding export options."
"Support for editing Beamer oriented Org mode files."
:lighter " Bm")
-(when (fboundp 'font-lock-add-keywords)
- (font-lock-add-keywords
- 'org-mode
- '((":\\(B_[a-z]+\\|BMCOL\\):" 1 'org-beamer-tag prepend))
- 'prepend))
+(font-lock-add-keywords
+ 'org-mode
+ '((":\\(B_[a-z]+\\|BMCOL\\):" 1 'org-beamer-tag prepend))
+ 'prepend)
-(defface org-beamer-tag '((t (:box (:line-width 1 :color grey40))))
+(defface org-beamer-tag '((t (:box (:line-width 1 :color "grey40"))))
"The special face for beamer tags."
:group 'org-export-beamer)
diff --git a/lisp/org/ox-html.el b/lisp/org/ox-html.el
index b27254b8ac5..cde4f6117ec 100644
--- a/lisp/org/ox-html.el
+++ b/lisp/org/ox-html.el
@@ -1,11 +1,11 @@
;;; ox-html.el --- HTML Back-End for Org Export Engine -*- lexical-binding: t; -*-
-;; Copyright (C) 2011-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2011-2024 Free Software Foundation, Inc.
;; Author: Carsten Dominik <carsten.dominik@gmail.com>
;; Jambunathan K <kjambunathan at gmail dot com>
;; Maintainer: TEC <orgmode@tec.tecosaur.net>
-;; Keywords: outlines, hypermedia, calendar, wp
+;; Keywords: outlines, hypermedia, calendar, text
;; This file is part of GNU Emacs.
@@ -3094,6 +3094,7 @@ CONTENTS is nil. INFO is a plist holding contextual information."
(let ((latex-frag (org-element-property :value latex-fragment))
(processing-type (plist-get info :with-latex)))
(cond
+ ;; FIXME: Duplicated value in ‘cond’: t
((memq processing-type '(t mathjax))
(org-html-format-latex latex-frag 'mathjax info))
((memq processing-type '(t html))
diff --git a/lisp/org/ox-icalendar.el b/lisp/org/ox-icalendar.el
index 81a77a77056..1a6d29938fd 100644
--- a/lisp/org/ox-icalendar.el
+++ b/lisp/org/ox-icalendar.el
@@ -1,11 +1,11 @@
;;; ox-icalendar.el --- iCalendar Back-End for Org Export Engine -*- lexical-binding: t; -*-
-;; Copyright (C) 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2004-2024 Free Software Foundation, Inc.
;; Author: Carsten Dominik <carsten.dominik@gmail.com>
;; Nicolas Goaziou <mail@nicolasgoaziou.fr>
;; Maintainer: Nicolas Goaziou <mail@nicolasgoaziou.fr>
-;; Keywords: outlines, hypermedia, calendar, wp
+;; Keywords: outlines, hypermedia, calendar, text
;; URL: https://orgmode.org
;; This file is part of GNU Emacs.
diff --git a/lisp/org/ox-koma-letter.el b/lisp/org/ox-koma-letter.el
index 33eb0597b08..aef25232c20 100644
--- a/lisp/org/ox-koma-letter.el
+++ b/lisp/org/ox-koma-letter.el
@@ -1,13 +1,13 @@
;;; ox-koma-letter.el --- KOMA Scrlttr2 Back-End for Org Export Engine -*- lexical-binding: t; -*-
-;; Copyright (C) 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2024 Free Software Foundation, Inc.
;; Author: Nicolas Goaziou <n.goaziou AT gmail DOT com>
;; Alan Schmitt <alan.schmitt AT polytechnique DOT org>
;; Viktor Rosenfeld <listuser36 AT gmail DOT com>
;; Rasmus Pank Roulund <emacs AT pank DOT eu>
;; Maintainer: Marco Wahl <marcowahlsoft@gmail.com>
-;; Keywords: org, wp, tex
+;; Keywords: org, text, tex
;; This file is part of GNU Emacs.
diff --git a/lisp/org/ox-latex.el b/lisp/org/ox-latex.el
index 768bf402b70..9d250f716b6 100644
--- a/lisp/org/ox-latex.el
+++ b/lisp/org/ox-latex.el
@@ -1,10 +1,10 @@
;;; ox-latex.el --- LaTeX Back-End for Org Export Engine -*- lexical-binding: t; -*-
-;; Copyright (C) 2011-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2011-2024 Free Software Foundation, Inc.
;; Author: Nicolas Goaziou <n.goaziou at gmail dot com>
;; Maintainer: Daniel Fleischer <danflscr@gmail.com>
-;; Keywords: outlines, hypermedia, calendar, wp
+;; Keywords: outlines, hypermedia, calendar, text
;; This file is part of GNU Emacs.
diff --git a/lisp/org/ox-man.el b/lisp/org/ox-man.el
index bb716f7b9f2..2019a531fa7 100644
--- a/lisp/org/ox-man.el
+++ b/lisp/org/ox-man.el
@@ -1,10 +1,10 @@
;;; ox-man.el --- Man Back-End for Org Export Engine -*- lexical-binding: t; -*-
-;; Copyright (C) 2011-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2011-2024 Free Software Foundation, Inc.
;; Author: Nicolas Goaziou <n.goaziou at gmail dot com>
;; Luis R Anaya <papoanaya aroba hot mail punto com>
-;; Keywords: outlines, hypermedia, calendar, wp
+;; Keywords: outlines, hypermedia, calendar, text
;; This file is part of GNU Emacs.
diff --git a/lisp/org/ox-md.el b/lisp/org/ox-md.el
index 5be0ca22e07..35bc4aa642b 100644
--- a/lisp/org/ox-md.el
+++ b/lisp/org/ox-md.el
@@ -1,10 +1,10 @@
;;; ox-md.el --- Markdown Back-End for Org Export Engine -*- lexical-binding: t; -*-
-;; Copyright (C) 2012-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2012-2024 Free Software Foundation, Inc.
;; Author: Nicolas Goaziou <n.goaziou@gmail.com>
;; Maintainer: Nicolas Goaziou <mail@nicolasgoaziou.fr>
-;; Keywords: org, wp, markdown
+;; Keywords: org, text, markdown
;; This file is part of GNU Emacs.
@@ -305,7 +305,7 @@ INFO is a plist used as a communication channel."
(section-title (org-html--translate "Footnotes" info)))
(when fn-alist
(format (plist-get info :md-footnotes-section)
- (org-md--headline-title headline-style 1 section-title)
+ (org-md--headline-title headline-style (plist-get info :md-toplevel-hlevel) section-title)
(mapconcat (lambda (fn) (org-md--footnote-formatted fn info))
fn-alist
"\n")))))
diff --git a/lisp/org/ox-odt.el b/lisp/org/ox-odt.el
index dd96ed8e064..d0d4727e7aa 100644
--- a/lisp/org/ox-odt.el
+++ b/lisp/org/ox-odt.el
@@ -1,9 +1,9 @@
;;; ox-odt.el --- OpenDocument Text Exporter for Org Mode -*- lexical-binding: t; -*-
-;; Copyright (C) 2010-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2010-2024 Free Software Foundation, Inc.
;; Author: Jambunathan K <kjambunathan at gmail dot com>
-;; Keywords: outlines, hypermedia, calendar, wp
+;; Keywords: outlines, hypermedia, calendar, text
;; URL: https://orgmode.org
;; This file is part of GNU Emacs.
diff --git a/lisp/org/ox-org.el b/lisp/org/ox-org.el
index ed72cf4f2ba..fdd0658fb62 100644
--- a/lisp/org/ox-org.el
+++ b/lisp/org/ox-org.el
@@ -1,10 +1,10 @@
;;; ox-org.el --- Org Back-End for Org Export Engine -*- lexical-binding: t; -*-
-;; Copyright (C) 2013-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2024 Free Software Foundation, Inc.
;; Author: Nicolas Goaziou <n.goaziou@gmail.com>
;; Maintainer: Nicolas Goaziou <mail@nicolasgoaziou.fr>
-;; Keywords: org, wp
+;; Keywords: org, text
;; This file is part of GNU Emacs.
diff --git a/lisp/org/ox-publish.el b/lisp/org/ox-publish.el
index cff34f05882..ce45c6f1b77 100644
--- a/lisp/org/ox-publish.el
+++ b/lisp/org/ox-publish.el
@@ -1,9 +1,9 @@
;;; ox-publish.el --- Publish Related Org Mode Files as a Website -*- lexical-binding: t; -*-
-;; Copyright (C) 2006-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2006-2024 Free Software Foundation, Inc.
;; Author: David O'Toole <dto@gnu.org>
;; Maintainer: Nicolas Goaziou <mail@nicolasgoaziou.fr>
-;; Keywords: hypermedia, outlines, wp
+;; Keywords: hypermedia, outlines, text
;; This file is part of GNU Emacs.
;;
diff --git a/lisp/org/ox-texinfo.el b/lisp/org/ox-texinfo.el
index 5befcac1c39..84313645e6e 100644
--- a/lisp/org/ox-texinfo.el
+++ b/lisp/org/ox-texinfo.el
@@ -1,9 +1,9 @@
;;; ox-texinfo.el --- Texinfo Back-End for Org Export Engine -*- lexical-binding: t; -*-
-;; Copyright (C) 2012-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2012-2024 Free Software Foundation, Inc.
;; Author: Jonathan Leech-Pepin <jonathan.leechpepin at gmail dot com>
;; Maintainer: Nicolas Goaziou <mail@nicolasgoaziou.fr>
-;; Keywords: outlines, hypermedia, calendar, wp
+;; Keywords: outlines, hypermedia, calendar, text
;; This file is part of GNU Emacs.
diff --git a/lisp/org/ox.el b/lisp/org/ox.el
index 94cc5a22881..19bf559c9e7 100644
--- a/lisp/org/ox.el
+++ b/lisp/org/ox.el
@@ -1,10 +1,10 @@
;;; ox.el --- Export Framework for Org Mode -*- lexical-binding: t; -*-
-;; Copyright (C) 2012-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2012-2024 Free Software Foundation, Inc.
;; Author: Nicolas Goaziou <mail@nicolasgoaziou.fr>
;; Maintainer: Nicolas Goaziou <mail@nicolasgoaziou.fr>
-;; Keywords: outlines, hypermedia, calendar, wp
+;; Keywords: outlines, hypermedia, calendar, text
;; This file is part of GNU Emacs.
@@ -264,13 +264,17 @@ See `org-export-inline-image-p' for more information about
rules.")
(defconst org-export-ignored-local-variables
- '( org-font-lock-keywords org-element--cache-change-tic
- org-element--cache-change-tic org-element--cache-size
- org-element--headline-cache-size
- org-element--cache-sync-keys-value
- org-element--cache-change-warning org-element--headline-cache
- org-element--cache org-element--cache-sync-keys
- org-element--cache-sync-requests org-element--cache-sync-timer)
+ '( org-font-lock-keywords
+ org-element--cache org-element--cache-size
+ org-element--headline-cache org-element--headline-cache-size
+ org-element--cache-hash-left org-element--cache-hash-right
+ org-element--cache-sync-requests org-element--cache-sync-timer
+ org-element--cache-sync-keys-value org-element--cache-change-tic
+ org-element--cache-last-buffer-size
+ org-element--cache-diagnostics-ring
+ org-element--cache-diagnostics-ring-size
+ org-element--cache-gapless
+ org-element--cache-change-warning)
"List of variables not copied through upon buffer duplication.
Export process takes place on a copy of the original buffer.
When this copy is created, all Org related local variables not in
@@ -6691,6 +6695,11 @@ or FILE."
',ext-plist)))
(with-temp-buffer
(insert output)
+ ;; Ensure final newline. This is what was done
+ ;; historically, when we used `write-file'.
+ ;; Note that adding a newline is only safe for
+ ;; non-binary data.
+ (unless (bolp) (insert "\n"))
(let ((coding-system-for-write ',encoding))
(write-region (point-min) (point-max) ,file)))
(or (ignore-errors (funcall ',post-process ,file)) ,file)))
@@ -6698,6 +6707,11 @@ or FILE."
backend subtreep visible-only body-only ext-plist)))
(with-temp-buffer
(insert output)
+ ;; Ensure final newline. This is what was done
+ ;; historically, when we used `write-file'.
+ ;; Note that adding a newline is only safe for
+ ;; non-binary data.
+ (unless (bolp) (insert "\n"))
(let ((coding-system-for-write encoding))
(write-region (point-min) (point-max) file)))
(when (and (org-export--copy-to-kill-ring-p) (org-string-nw-p output))
diff --git a/lisp/outline.el b/lisp/outline.el
index 97a51c9b92a..96e0d0df205 100644
--- a/lisp/outline.el
+++ b/lisp/outline.el
@@ -1,6 +1,6 @@
;;; outline.el --- outline mode commands for Emacs -*- lexical-binding: t; -*-
-;; Copyright (C) 1986-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1986-2024 Free Software Foundation, Inc.
;; Maintainer: emacs-devel@gnu.org
;; Keywords: outlines
@@ -314,12 +314,15 @@ These buttons can be used to hide and show the body under the heading.
When the value is `insert', additional placeholders for buttons are
inserted to the buffer, so buttons are not only clickable,
but also typing `RET' on them can hide and show the body.
+Using the value `insert' is not recommended in editable
+buffers because it modifies them.
When the value is `in-margins', then clickable buttons are
displayed in the margins before the headings.
When the value is `t', clickable buttons are displayed
in the buffer before the headings. The values `t' and
`in-margins' can be used in editing buffers because they
don't modify the buffer."
+ ;; The value `insert' is not intended to be customizable.
:type '(choice (const :tag "Do not use outline buttons" nil)
(const :tag "Show outline buttons in margins" in-margins)
(const :tag "Show outline buttons in buffer" t))
diff --git a/lisp/paren.el b/lisp/paren.el
index 6296d7e67fa..cb29b8311a5 100644
--- a/lisp/paren.el
+++ b/lisp/paren.el
@@ -1,6 +1,6 @@
;;; paren.el --- highlight matching paren -*- lexical-binding:t -*-
-;; Copyright (C) 1993, 1996, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1993, 1996, 2001-2024 Free Software Foundation, Inc.
;; Author: rms@gnu.org
;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/password-cache.el b/lisp/password-cache.el
index b131a6eb63f..0280c31a624 100644
--- a/lisp/password-cache.el
+++ b/lisp/password-cache.el
@@ -1,6 +1,6 @@
;;; password-cache.el --- Read passwords, possibly using a password cache. -*- lexical-binding: t -*-
-;; Copyright (C) 1999-2000, 2003-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2000, 2003-2024 Free Software Foundation, Inc.
;; Author: Simon Josefsson <simon@josefsson.org>
;; Created: 2003-12-21
diff --git a/lisp/pcmpl-cvs.el b/lisp/pcmpl-cvs.el
index 0ad70e96b27..ed83052bdb9 100644
--- a/lisp/pcmpl-cvs.el
+++ b/lisp/pcmpl-cvs.el
@@ -1,6 +1,6 @@
;;; pcmpl-cvs.el --- functions for dealing with cvs completions -*- lexical-binding: t -*-
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
;; Author: John Wiegley <johnw@gnu.org>
;; Package: pcomplete
diff --git a/lisp/pcmpl-git.el b/lisp/pcmpl-git.el
index 698d2e747b5..facca4107a1 100644
--- a/lisp/pcmpl-git.el
+++ b/lisp/pcmpl-git.el
@@ -1,6 +1,6 @@
;;; pcmpl-git.el --- Completions for Git -*- lexical-binding: t -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;; Package: pcomplete
diff --git a/lisp/pcmpl-gnu.el b/lisp/pcmpl-gnu.el
index 1553c3efed7..237e3d62526 100644
--- a/lisp/pcmpl-gnu.el
+++ b/lisp/pcmpl-gnu.el
@@ -1,6 +1,6 @@
;;; pcmpl-gnu.el --- completions for GNU project tools -*- lexical-binding: t -*-
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
;; Package: pcomplete
diff --git a/lisp/pcmpl-linux.el b/lisp/pcmpl-linux.el
index 589b4799c8d..3aee0b296f6 100644
--- a/lisp/pcmpl-linux.el
+++ b/lisp/pcmpl-linux.el
@@ -1,6 +1,6 @@
;;; pcmpl-linux.el --- functions for dealing with GNU/Linux completions -*- lexical-binding: t -*-
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
;; Package: pcomplete
diff --git a/lisp/pcmpl-rpm.el b/lisp/pcmpl-rpm.el
index f8f43a505ea..65c12d2337e 100644
--- a/lisp/pcmpl-rpm.el
+++ b/lisp/pcmpl-rpm.el
@@ -1,6 +1,6 @@
;;; pcmpl-rpm.el --- functions for dealing with rpm completions -*- lexical-binding: t -*-
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
;; Package: pcomplete
diff --git a/lisp/pcmpl-unix.el b/lisp/pcmpl-unix.el
index e6b67256a4c..65308cffec4 100644
--- a/lisp/pcmpl-unix.el
+++ b/lisp/pcmpl-unix.el
@@ -1,6 +1,6 @@
;;; pcmpl-unix.el --- standard UNIX completions -*- lexical-binding:t -*-
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
;; Package: pcomplete
@@ -685,6 +685,14 @@ Includes files as well as host names followed by a colon."
(funcall (or (pcomplete-find-completion-function (pcomplete-arg 1))
pcomplete-default-completion-function)))
+;;;###autoload
+(defun pcomplete/doas ()
+ "Completion for the `doas' command."
+ (pcomplete-opt "C(pcomplete-entries)Lnsu(pcmpl-unix-user-names)")
+ (funcall pcomplete-command-completion-function)
+ (funcall (or (pcomplete-find-completion-function (pcomplete-arg 1))
+ pcomplete-default-completion-function)))
+
(provide 'pcmpl-unix)
;;; pcmpl-unix.el ends here
diff --git a/lisp/pcmpl-x.el b/lisp/pcmpl-x.el
index 4ee7b4aa52b..8af78345f35 100644
--- a/lisp/pcmpl-x.el
+++ b/lisp/pcmpl-x.el
@@ -1,6 +1,6 @@
;;; pcmpl-x.el --- completion for miscellaneous tools -*- lexical-binding: t; -*-
-;; Copyright (C) 2013-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2024 Free Software Foundation, Inc.
;; Author: Leo Liu <sdl.web@gmail.com>
;; Keywords: processes, tools, convenience
diff --git a/lisp/pcomplete.el b/lisp/pcomplete.el
index 151611f94b7..196c5f159cd 100644
--- a/lisp/pcomplete.el
+++ b/lisp/pcomplete.el
@@ -1,6 +1,6 @@
;;; pcomplete.el --- programmable completion -*- lexical-binding: t -*-
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
;; Author: John Wiegley <johnw@gnu.org>
;; Keywords: processes abbrev
@@ -470,6 +470,8 @@ Same as `pcomplete' but using the standard completion UI."
;; rely less on c-t-subvert.
(beg (max (- (point) (length pcomplete-stub))
argbeg))
+ (end (point))
+ tmp
buftext)
;; Try and improve our guess of `beg' in case the difference
;; between pcomplete-stub and the buffer's text is simply due to
@@ -477,11 +479,19 @@ Same as `pcomplete' but using the standard completion UI."
;; indispensable but reduces the reliance on c-t-subvert and
;; improves corner case behaviors.
(while (progn (setq buftext (pcomplete-unquote-argument
- (buffer-substring beg (point))))
+ (buffer-substring beg end)))
(and (> beg argbeg)
(> (length pcomplete-stub) (length buftext))))
(setq beg (max argbeg (- beg (- (length pcomplete-stub)
(length buftext))))))
+ ;; Try and improve our guess of `end' in case it's not point.
+ (while (and (< (length buftext) (length pcomplete-stub))
+ (< end (point-max))
+ (string-prefix-p (setq tmp (pcomplete-unquote-argument
+ (buffer-substring beg (1+ end))))
+ pcomplete-stub))
+ (setq end (1+ end))
+ (setq buftext tmp))
(when completions
(let ((table
(completion-table-with-quoting
@@ -515,7 +525,7 @@ Same as `pcomplete' but using the standard completion UI."
seen)))))))
(when completion-ignore-case
(setq table (completion-table-case-fold table)))
- (list beg (point) table
+ (list beg end table
:annotation-function
(lambda (cand)
(when (stringp cand)
@@ -675,35 +685,13 @@ parts of the list.
The OFFSET argument is added to/taken away from the index that will be
used. This is really only useful with `first' and `last', for
-accessing absolute argument positions.
-
-When the argument has been transformed into something that is not
-a string by `pcomplete-parse-arguments-function', the text
-representation of the argument, namely what the user actually
-typed in, is returned, and the value of the argument is stored in
-the pcomplete-arg-value text property of that string."
- (let ((arg
- (nth (+ (pcase index
- ('first 0)
- ('last pcomplete-last)
- (_ (- pcomplete-index (or index 0))))
- (or offset 0))
- pcomplete-args)))
- (if (or (stringp arg)
- ;; FIXME: 'last' is handled specially in Emacs 29, because
- ;; 'pcomplete-parse-arguments' accepts a list of strings
- ;; (which are completion candidates) as return value for
- ;; (pcomplete-arg 'last). See below: "it means it's a
- ;; list of completions computed during parsing,
- ;; e.g. Eshell uses that to turn globs into lists of
- ;; completions". This special case will be dealt with
- ;; differently in Emacs 30: the pcomplete-arg-value
- ;; property will be used by 'pcomplete-parse-arguments'.
- (eq index 'last))
- arg
- (propertize
- (car (split-string (pcomplete-actual-arg index offset)))
- 'pcomplete-arg-value arg))))
+accessing absolute argument positions."
+ (nth (+ (pcase index
+ ('first 0)
+ ('last pcomplete-last)
+ (_ (- pcomplete-index (or index 0))))
+ (or offset 0))
+ pcomplete-args))
(defun pcomplete-begin (&optional index offset)
"Return the beginning position of the INDEXth argument.
@@ -914,14 +902,16 @@ this is `comint-dynamic-complete-functions'."
(and dir-ignore (string-match dir-ignore file))
(and file-ignore (string-match file-ignore file))))))))
(reg-pred (if regexp (lambda (file) (string-match regexp file))))
- (pred (cond
- ((null (or ign-pred reg-pred)) predicate)
- ((null (or ign-pred predicate)) reg-pred)
- ((null (or reg-pred predicate)) ign-pred)
- (t (lambda (f)
+ ;; `completion-file-name-table' calls `file-exists-p' when
+ ;; the predicate is nil.
+ ;; So likewise, defer to PREDICATE if it's there, else take
+ ;; ourselves to be responsible for calling `file-exists-p'.
+ (pred (if (or ign-pred reg-pred)
+ (lambda (f)
(and (or (null reg-pred) (funcall reg-pred f))
(or (null ign-pred) (funcall ign-pred f))
- (or (null predicate) (funcall predicate f))))))))
+ (funcall (or predicate #'file-exists-p) f)))
+ predicate)))
(lambda (s p a)
(if (and (eq a 'metadata) pcomplete-compare-entry-function)
`(metadata (cycle-sort-function
diff --git a/lisp/pgtk-dnd.el b/lisp/pgtk-dnd.el
index f2998fd1e67..edc51320a79 100644
--- a/lisp/pgtk-dnd.el
+++ b/lisp/pgtk-dnd.el
@@ -1,6 +1,6 @@
;;; pgtk-dnd.el --- drag and drop support for GDK -*- lexical-binding: t; -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;; Maintainer: emacs-devel@gnu.org
;; Keywords: window, drag, drop
@@ -238,10 +238,9 @@ WINDOW is the window where the drop happened.
STRING is the uri-list as a string. The URIs are separated by \\r\\n."
(let ((uri-list (split-string string "[\0\r\n]" t))
retval)
- (dolist (bf uri-list)
- ;; If one URL is handled, treat as if the whole drop succeeded.
- (let ((did-action (dnd-handle-one-url window action bf)))
- (when did-action (setq retval did-action))))
+ (let ((did-action (dnd-handle-multiple-urls window uri-list
+ action)))
+ (when did-action (setq retval did-action)))
retval))
(defun pgtk-dnd-handle-file-name (window action string)
@@ -252,17 +251,22 @@ STRING is the file names as a string, separated by nulls."
(coding (or file-name-coding-system
default-file-name-coding-system))
retval)
- (dolist (bf uri-list)
- ;; If one URL is handled, treat as if the whole drop succeeded.
- (if coding (setq bf (encode-coding-string bf coding)))
- (let* ((file-uri (concat "file://"
- (mapconcat 'url-hexify-string
- (split-string bf "/") "/")))
- (did-action (dnd-handle-one-url window action file-uri)))
- (when did-action (setq retval did-action))))
+ (let ((did-action
+ (dnd-handle-multiple-urls
+ window (mapcar
+ (lambda (item)
+ (when coding
+ (setq item (encode-coding-string item
+ coding)))
+ (concat "file://"
+ (mapconcat 'url-hexify-string
+ (split-string item "/")
+ "/")))
+ uri-list)
+ action)))
+ (when did-action (setq retval did-action)))
retval))
-
(defun pgtk-dnd-choose-type (types &optional known-types)
"Choose which type we want to receive for the drop.
TYPES are the types the source of the drop offers, a vector of type names
diff --git a/lisp/pixel-scroll.el b/lisp/pixel-scroll.el
index 488f6781254..4bf912e54c0 100644
--- a/lisp/pixel-scroll.el
+++ b/lisp/pixel-scroll.el
@@ -1,6 +1,6 @@
;;; pixel-scroll.el --- Scroll a line smoothly -*- lexical-binding: t -*-
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
;; Author: Tak Kunihiro <tkk@misasa.okayama-u.ac.jp>
;; Keywords: mouse
;; Package: emacs
@@ -148,67 +148,62 @@ is always with pixel resolution.")
"<next>" #'pixel-scroll-interpolate-down
"<prior>" #'pixel-scroll-interpolate-up)
+(defgroup pixel-scroll-precision nil
+ "Precise pixel scrolling."
+ :group 'mouse
+ :version "30.1")
+
(defcustom pixel-scroll-precision-use-momentum nil
"If non-nil, continue to scroll the display after wheel movement stops.
This is only effective if supported by your mouse or touchpad."
- :group 'mouse
:type 'boolean
:version "29.1")
(defcustom pixel-scroll-precision-momentum-tick 0.01
"Number of seconds between each momentum scroll."
- :group 'mouse
:type 'float
:version "29.1")
(defcustom pixel-scroll-precision-momentum-seconds 1.75
"The maximum duration in seconds of momentum scrolling."
- :group 'mouse
:type 'float
:version "29.1")
(defcustom pixel-scroll-precision-momentum-min-velocity 10.0
"The minimum scrolled pixels per second before momentum scrolling starts."
- :group 'mouse
:type 'float
:version "29.1")
(defcustom pixel-scroll-precision-initial-velocity-factor (/ 0.0335 4)
"Factor applied to the initial velocity before momentum scrolling begins."
- :group 'mouse
:type 'float
:version "29.1")
(defcustom pixel-scroll-precision-large-scroll-height nil
"Pixels that must be scrolled before an animation is performed.
Nil means to not interpolate such scrolls."
- :group 'mouse
:type '(choice (const :tag "Do not interpolate large scrolls" nil)
number)
:version "29.1")
(defcustom pixel-scroll-precision-interpolation-total-time 0.1
"The total time in seconds to spend interpolating a large scroll."
- :group 'mouse
:type 'float
:version "29.1")
(defcustom pixel-scroll-precision-interpolation-factor 2.0
"A factor to apply to the distance of an interpolated scroll."
- :group 'mouse
:type 'float
:version "29.1")
(defcustom pixel-scroll-precision-interpolation-between-scroll 0.001
"The number of seconds between each step of an interpolated scroll."
- :group 'mouse
:type 'float
:version "29.1")
(defcustom pixel-scroll-precision-interpolate-page nil
"Whether or not to interpolate scrolling via the Page Down and Page Up keys.
This is only effective when `pixel-scroll-precision-mode' is enabled."
- :group 'scrolling
:type 'boolean
:version "29.1")
@@ -216,7 +211,6 @@ This is only effective when `pixel-scroll-precision-mode' is enabled."
"Whether or not to interpolate scrolling from a mouse.
If non-nil, scrolling from the mouse wheel of an actual mouse (as
opposed to a touchpad) will cause Emacs to interpolate the scroll."
- :group 'scrolling
:type 'boolean
:version "29.1")
@@ -851,7 +845,7 @@ It is a vector of the form [ VELOCITY TIME SIGN ]."
;;;###autoload
(define-minor-mode pixel-scroll-precision-mode
"Toggle pixel scrolling.
-When enabled, this minor mode allows to scroll the display
+When enabled, this minor mode allows you to scroll the display
precisely, according to the turning of the mouse wheel."
:global t
:group 'mouse
diff --git a/lisp/play/5x5.el b/lisp/play/5x5.el
index 772c252512d..d3393cbf9d1 100644
--- a/lisp/play/5x5.el
+++ b/lisp/play/5x5.el
@@ -1,6 +1,6 @@
;;; 5x5.el --- simple little puzzle game -*- lexical-binding: t -*-
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
;; Author: Dave Pearson <davep@davep.org>
;; Created: 1998-10-03
diff --git a/lisp/play/animate.el b/lisp/play/animate.el
index 01e7a91f03c..33df0a65797 100644
--- a/lisp/play/animate.el
+++ b/lisp/play/animate.el
@@ -1,6 +1,6 @@
;;; animate.el --- make text dance -*- lexical-binding:t -*-
-;; Copyright (C) 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2024 Free Software Foundation, Inc.
;; Maintainer: Richard Stallman <rms@gnu.org>
;; Keywords: games
diff --git a/lisp/play/blackbox.el b/lisp/play/blackbox.el
index dff585a5983..b8bbfda7821 100644
--- a/lisp/play/blackbox.el
+++ b/lisp/play/blackbox.el
@@ -1,6 +1,6 @@
;;; blackbox.el --- blackbox game in Emacs Lisp -*- lexical-binding: t -*-
-;; Copyright (C) 1985-1987, 1992, 2001-2023 Free Software Foundation,
+;; Copyright (C) 1985-1987, 1992, 2001-2024 Free Software Foundation,
;; Inc.
;; Author: F. Thomas May <uw-nsr!uw-warp!tom@beaver.cs.washington.edu>
diff --git a/lisp/play/bubbles.el b/lisp/play/bubbles.el
index e68778d28b2..112b02605da 100644
--- a/lisp/play/bubbles.el
+++ b/lisp/play/bubbles.el
@@ -1,6 +1,6 @@
;;; bubbles.el --- Puzzle game for Emacs -*- lexical-binding:t -*-
-;; Copyright (C) 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2024 Free Software Foundation, Inc.
;; Author: Ulf Jasper <ulf.jasper@web.de>
;; URL: http://ulf.epplejasper.de/
diff --git a/lisp/play/cookie1.el b/lisp/play/cookie1.el
index e5c0d6a14d2..c8e9d097a5f 100644
--- a/lisp/play/cookie1.el
+++ b/lisp/play/cookie1.el
@@ -1,6 +1,6 @@
;;; cookie1.el --- retrieve random phrases from fortune cookie files -*- lexical-binding: t -*-
-;; Copyright (C) 1993, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1993, 2001-2024 Free Software Foundation, Inc.
;; Author: Eric S. Raymond <esr@thyrsus.com>
;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/play/decipher.el b/lisp/play/decipher.el
index 88300c1d818..bfc28ec9f89 100644
--- a/lisp/play/decipher.el
+++ b/lisp/play/decipher.el
@@ -1,6 +1,6 @@
;;; decipher.el --- cryptanalyze monoalphabetic substitution ciphers -*- lexical-binding: t; -*-
;;
-;; Copyright (C) 1995-1996, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1995-1996, 2001-2024 Free Software Foundation, Inc.
;;
;; Author: Christopher J. Madsen <chris_madsen@geocities.com>
;; Keywords: games
diff --git a/lisp/play/dissociate.el b/lisp/play/dissociate.el
index 0c655281192..f96418ef1bd 100644
--- a/lisp/play/dissociate.el
+++ b/lisp/play/dissociate.el
@@ -1,6 +1,6 @@
;;; dissociate.el --- scramble text amusingly for Emacs -*- lexical-binding:t -*-
-;; Copyright (C) 1985, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1985, 2001-2024 Free Software Foundation, Inc.
;; Maintainer: emacs-devel@gnu.org
;; Keywords: games
diff --git a/lisp/play/doctor.el b/lisp/play/doctor.el
index 891274448d3..79ddc4fc929 100644
--- a/lisp/play/doctor.el
+++ b/lisp/play/doctor.el
@@ -1,6 +1,6 @@
;;; doctor.el --- psychological help for frustrated users -*- lexical-binding: t -*-
-;; Copyright (C) 1985-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1985-2024 Free Software Foundation, Inc.
;; Maintainer: emacs-devel@gnu.org
;; Keywords: games
diff --git a/lisp/play/dunnet.el b/lisp/play/dunnet.el
index e290a9d73ec..8d9a7853242 100644
--- a/lisp/play/dunnet.el
+++ b/lisp/play/dunnet.el
@@ -1,6 +1,6 @@
;;; dunnet.el --- text adventure for Emacs -*- lexical-binding: t -*-
-;; Copyright (C) 1992-1993, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1992-1993, 2001-2024 Free Software Foundation, Inc.
;; Author: Ron Schnell <ronnie@driver-aces.com>
;; Created: 25 Jul 1992
diff --git a/lisp/play/fortune.el b/lisp/play/fortune.el
index 36551321a56..de3caacdda5 100644
--- a/lisp/play/fortune.el
+++ b/lisp/play/fortune.el
@@ -1,6 +1,6 @@
;;; fortune.el --- use fortune to create signatures -*- lexical-binding: t -*-
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
;; Author: Holger Schauer <Holger.Schauer@gmx.de>
;; Keywords: games utils mail
diff --git a/lisp/play/gamegrid.el b/lisp/play/gamegrid.el
index bf195d6a0ec..a098d0f6f69 100644
--- a/lisp/play/gamegrid.el
+++ b/lisp/play/gamegrid.el
@@ -1,6 +1,6 @@
;;; gamegrid.el --- library for implementing grid-based games on Emacs -*- lexical-binding:t -*-
-;; Copyright (C) 1997-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997-2024 Free Software Foundation, Inc.
;; Author: Glynn Clements <glynn@sensei.co.uk>
;; Old-Version: 1.02
diff --git a/lisp/play/gametree.el b/lisp/play/gametree.el
index 971d8ea70ca..86b63adddc7 100644
--- a/lisp/play/gametree.el
+++ b/lisp/play/gametree.el
@@ -1,6 +1,6 @@
;;; gametree.el --- manage game analysis trees in Emacs -*- lexical-binding: t -*-
-;; Copyright (C) 1997, 1999, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997, 1999, 2001-2024 Free Software Foundation, Inc.
;; Author: Ian T Zimmerman <itz@rahul.net>
;; Created: Wed Dec 10 07:41:46 PST 1997
diff --git a/lisp/play/gomoku.el b/lisp/play/gomoku.el
index 7d57b15673a..0ff745916e7 100644
--- a/lisp/play/gomoku.el
+++ b/lisp/play/gomoku.el
@@ -1,6 +1,6 @@
;;; gomoku.el --- Gomoku game between you and Emacs -*- lexical-binding:t -*-
-;; Copyright (C) 1988, 1994, 1996, 2001-2023 Free Software Foundation,
+;; Copyright (C) 1988, 1994, 1996, 2001-2024 Free Software Foundation,
;; Inc.
;; Author: Philippe Schnoebelen <phs@lsv.ens-cachan.fr>
diff --git a/lisp/play/handwrite.el b/lisp/play/handwrite.el
index 735874e8da6..c71dffc42ed 100644
--- a/lisp/play/handwrite.el
+++ b/lisp/play/handwrite.el
@@ -1,11 +1,11 @@
;;; handwrite.el --- turns your emacs buffer into a handwritten document -*- lexical-binding: t -*-
-;; Copyright (C) 1996-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-2024 Free Software Foundation, Inc.
;; Author: Danny Roozendaal (was: <danny@tvs.kun.nl>)
;; Maintainer: emacs-devel@gnu.org
;; Created: October 21 1996
-;; Keywords: wp, print, postscript, cursive writing
+;; Keywords: text, print, postscript, cursive writing
;; This file is part of GNU Emacs.
diff --git a/lisp/play/life.el b/lisp/play/life.el
index 2796a92d4dd..377cbf2a7bc 100644
--- a/lisp/play/life.el
+++ b/lisp/play/life.el
@@ -1,6 +1,6 @@
;;; life.el --- John Horton Conway's Game of Life -*- lexical-binding:t -*-
-;; Copyright (C) 1988, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1988, 2001-2024 Free Software Foundation, Inc.
;; Author: Kyle Jones <kyleuunet.uu.net>
;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/play/morse.el b/lisp/play/morse.el
index 4b2f2cfb4a8..1f4d269cbb9 100644
--- a/lisp/play/morse.el
+++ b/lisp/play/morse.el
@@ -1,6 +1,6 @@
;;; morse.el --- convert text to morse code and back -*- lexical-binding: t -*-
-;; Copyright (C) 1995-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1995-2024 Free Software Foundation, Inc.
;; Author: Rick Farnbach <rick_farnbach@MENTORG.COM>
;; Keywords: games
diff --git a/lisp/play/mpuz.el b/lisp/play/mpuz.el
index f9811f91172..03ce52cdb4c 100644
--- a/lisp/play/mpuz.el
+++ b/lisp/play/mpuz.el
@@ -1,6 +1,6 @@
;;; mpuz.el --- multiplication puzzle for GNU Emacs -*- lexical-binding: t -*-
-;; Copyright (C) 1990, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1990, 2001-2024 Free Software Foundation, Inc.
;; Author: Philippe Schnoebelen <phs@lsv.ens-cachan.fr>
;; Overhauled: Daniel Pfeiffer <occitan@esperanto.org>
diff --git a/lisp/play/pong.el b/lisp/play/pong.el
index bb9611f0b48..15de02d468b 100644
--- a/lisp/play/pong.el
+++ b/lisp/play/pong.el
@@ -1,6 +1,6 @@
;;; pong.el --- classical implementation of pong -*- lexical-binding:t -*-
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
;; Author: Benjamin Drieu <bdrieu@april.org>
;; Keywords: games
diff --git a/lisp/play/snake.el b/lisp/play/snake.el
index 17a90817e72..e6dea3e31ae 100644
--- a/lisp/play/snake.el
+++ b/lisp/play/snake.el
@@ -1,6 +1,6 @@
;;; snake.el --- implementation of Snake for Emacs -*- lexical-binding:t -*-
-;; Copyright (C) 1997, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997, 2001-2024 Free Software Foundation, Inc.
;; Author: Glynn Clements <glynn@sensei.co.uk>
;; Created: 1997-09-10
diff --git a/lisp/play/solitaire.el b/lisp/play/solitaire.el
index f5788593794..c4927ea3cd2 100644
--- a/lisp/play/solitaire.el
+++ b/lisp/play/solitaire.el
@@ -1,6 +1,6 @@
;;; solitaire.el --- game of solitaire in Emacs Lisp -*- lexical-binding: t -*-
-;; Copyright (C) 1994, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1994, 2001-2024 Free Software Foundation, Inc.
;; Author: Jan Schormann <Jan.Schormann@rechen-gilde.de>
;; Created: Fri afternoon, Jun 3, 1994
diff --git a/lisp/play/spook.el b/lisp/play/spook.el
index 3fa8444b167..6dc89e3536b 100644
--- a/lisp/play/spook.el
+++ b/lisp/play/spook.el
@@ -1,6 +1,6 @@
;;; spook.el --- spook phrase utility for overloading the NSA line eater -*- lexical-binding:t -*-
-;; Copyright (C) 1988, 1993, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1988, 1993, 2001-2024 Free Software Foundation, Inc.
;; Maintainer: emacs-devel@gnu.org
;; Keywords: games
diff --git a/lisp/play/tetris.el b/lisp/play/tetris.el
index 41276f1dbca..f3c595f0fc3 100644
--- a/lisp/play/tetris.el
+++ b/lisp/play/tetris.el
@@ -1,6 +1,6 @@
;;; tetris.el --- implementation of Tetris for Emacs -*- lexical-binding:t -*-
-;; Copyright (C) 1997, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997, 2001-2024 Free Software Foundation, Inc.
;; Author: Glynn Clements <glynn@sensei.co.uk>
;; Old-Version: 2.01
diff --git a/lisp/play/zone.el b/lisp/play/zone.el
index 235c6f4e7b5..67c890eec7e 100644
--- a/lisp/play/zone.el
+++ b/lisp/play/zone.el
@@ -1,9 +1,9 @@
;;; zone.el --- idle display hacks -*- lexical-binding: t -*-
-;; Copyright (C) 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2000-2024 Free Software Foundation, Inc.
;; Author: Victor Zandy <zandy@cs.wisc.edu>
-;; Maintainer: Thien-Thi Nguyen <ttn@gnu.org>
+;; Maintainer: emacs-devel@gnu.org
;; Keywords: games
;; Created: June 6, 1998
diff --git a/lisp/plstore.el b/lisp/plstore.el
index d18d461d7d1..db977cb6308 100644
--- a/lisp/plstore.el
+++ b/lisp/plstore.el
@@ -1,6 +1,6 @@
;;; plstore.el --- secure plist store -*- lexical-binding: t -*-
-;; Copyright (C) 2011-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2011-2024 Free Software Foundation, Inc.
;; Author: Daiki Ueno <ueno@gnu.org>
;; Keywords: PGP, GnuPG
@@ -24,14 +24,31 @@
;; Plist based data store providing search and partial encryption.
;;
-;; By default, this package uses symmetric encryption, which means
+;; By default, this library uses symmetric encryption, which means
;; that you have to enter the password protecting your store more
;; often than you probably expect to. To use public key encryption
-;; with this package, create a GnuPG key and customize user option
+;; with this library, create a GnuPG key and customize user option
;; `plstore-encrypt-to' to use it. You can then configure the GnuPG
;; agent to adjust caching and expiration of the passphrase for your
;; store.
;;
+;; You can read more on these topics in the EasyPG Assistant user's
+;; manual (Info node `(epa)'), of which much information also applies
+;; to this library. Most notably:
+;;
+;; - Info node `(epa)GnuPG version compatibility'
+;; - Info node `(epa)GnuPG Pinentry'
+;; - Info node `(epa)Caching Passphrases'
+;;
+;; Use only keyword symbols (starting with a colon) as property names
+;; in any plist stored with this library. While this library does not
+;; actively enforce the use of keyword symbols, it silently assumes
+;; that the first character of all property names can be discarded
+;; without sacrificing uniqueness of names (FIXME). Likewise, this
+;; library does not enforce that the plists provided as input are
+;; actually valid and can behave in undefined ways if they are not
+;; (FIXME).
+;;
;; Creating:
;;
;; ;; Open a new store associated with ~/.emacs.d/auth.plist.
@@ -52,8 +69,8 @@
;; (plstore-close store)
;;
;; Avoid marking one property both as public *and* secret, as the
-;; behavior of this package with respect to such duplicate properties
-;; is not (yet) defined.
+;; behavior of this library with respect to such duplicate properties
+;; is not defined (FIXME).
;;
;; Searching:
;;
@@ -71,7 +88,7 @@
;; ;; While the entry "baz" associated with "baz.example.org" has also
;; ;; a secret property `:password', it is encrypted together with
;; ;; `:user' of "bar", so no need to decrypt the secret.
-;; (plstore-find store '(:host ("bar.example.org")))
+;; (plstore-find store '(:host ("baz.example.org")))
;;
;; (plstore-close store)
;;
@@ -87,8 +104,8 @@
;; `:secret-' prefix) is marked as secret. Thus, when you save the
;; buffer, the `:secret-user' property is encrypted as `:user'. Do
;; not use a property consisting solely of the prefix, as the behavior
-;; of this package with respect to such properties is not (yet)
-;; defined.
+;; of this library with respect to such properties is not defined
+;; (FIXME).
;;
;; You can toggle the view between encrypted form and the decrypted
;; form with C-c C-c.
@@ -101,7 +118,7 @@
;; Internals:
;;
;; This is information on the internal data structure and functions of
-;; this package. None of it should be necessary to actually use it.
+;; this library. None of it should be necessary to actually use it.
;; For easier reading, we usually do not distinguish in this internal
;; documentation between a Lisp object and its printed representation.
;;
@@ -553,18 +570,23 @@ SECRET-KEYS is a plist containing secret data."
(defvar pp-escape-newlines)
(defun plstore--insert-buffer (plstore)
- "Insert the file representation of PLSTORE at point.
-Assumes that PLSTORE has been decrypted."
+ "Insert the file representation of PLSTORE at point."
(insert ";;; public entries -*- mode: plstore -*- \n"
(pp-to-string (plstore--get-alist plstore)))
- (if (plstore--get-secret-alist plstore)
+ (let ((pp-escape-newlines nil)
+ (cipher nil))
+ (cond
+ ;; Reuse the encrypted data as cipher text if this store has not
+ ;; been decrypted yet.
+ ((plstore--get-encrypted-data plstore)
+ (setq cipher (plstore--get-encrypted-data plstore)))
+ ;; Encrypt the secret alist to generate the cipher text.
+ ((plstore--get-secret-alist plstore)
(let ((context (epg-make-context 'OpenPGP))
- (pp-escape-newlines nil)
(recipients
(cond
((listp plstore-encrypt-to) plstore-encrypt-to)
- ((stringp plstore-encrypt-to) (list plstore-encrypt-to))))
- cipher)
+ ((stringp plstore-encrypt-to) (list plstore-encrypt-to)))))
(setf (epg-context-armor context) t)
(epg-context-set-passphrase-callback
context
@@ -584,12 +606,17 @@ Assumes that PLSTORE has been decrypted."
If no one is selected, symmetric encryption will be performed. "
recipients)
(if plstore-encrypt-to
- (epg-list-keys context recipients)))))
- (goto-char (point-max))
- (insert ";;; secret entries\n" (pp-to-string cipher)))))
+ (epg-list-keys context recipients))))))))
+ (when cipher
+ (goto-char (point-max))
+ (insert ";;; secret entries\n" (pp-to-string cipher)))))
(defun plstore-save (plstore)
- "Save PLSTORE to its associated file."
+ "Save PLSTORE to its associated file.
+Save with symmetric encryption or public key encryption depending
+on `plstore-encrypt-to'. If `plstore-encrypt-to' is non-nil but
+none of the recipients from `plstore-encrypt-to' matches any
+GnuPG key, silently save with symmetric encryption." ; (FIXME)
(with-current-buffer (plstore--get-buffer plstore)
(erase-buffer)
(plstore--insert-buffer plstore)
diff --git a/lisp/printing.el b/lisp/printing.el
index 4a6d14260a0..d9bc97d48af 100644
--- a/lisp/printing.el
+++ b/lisp/printing.el
@@ -1,9 +1,9 @@
;;; printing.el --- printing utilities -*- lexical-binding:t -*-
-;; Copyright (C) 2000-2001, 2003-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2000-2024 Free Software Foundation, Inc.
;; Author: Vinicius Jose Latorre <viniciusjl.gnu@gmail.com>
-;; Keywords: wp, print, PostScript
+;; Keywords: text, print, PostScript
;; Old-Version: 6.9.3
;; URL: https://www.emacswiki.org/cgi-bin/wiki/ViniciusJoseLatorre
@@ -1148,8 +1148,7 @@ Used by `pr-menu-bind' and `pr-update-menus'.")
(defun pr-menu-get-item (name-list)
;; NAME-LIST is a string or a list of strings.
- (or (listp name-list)
- (setq name-list (list name-list)))
+ (setq name-list (ensure-list name-list))
(and name-list
(let* ((reversed (reverse name-list))
(name (easy-menu-intern (car reversed)))
@@ -5519,7 +5518,7 @@ COMMAND.exe, COMMAND.bat and COMMAND.com in this order."
(setq ext (cdr ext)
found nil))
found)
- ;; non-windows systems
+ ;; non-Windows systems
(and (file-regular-p cmd)
(file-executable-p cmd)
cmd)))
diff --git a/lisp/proced.el b/lisp/proced.el
index 47de74b0ecb..3435f1ab8cd 100644
--- a/lisp/proced.el
+++ b/lisp/proced.el
@@ -1,6 +1,6 @@
;;; proced.el --- operate on system processes like dired -*- lexical-binding:t -*-
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
;; Author: Roland Winkler <winkler@gnu.org>
;; Keywords: Processes, Unix
diff --git a/lisp/profiler.el b/lisp/profiler.el
index 634cdaf09ea..80f84037a63 100644
--- a/lisp/profiler.el
+++ b/lisp/profiler.el
@@ -1,6 +1,6 @@
;;; profiler.el --- UI and helper functions for Emacs's native profiler -*- lexical-binding: t -*-
-;; Copyright (C) 2012-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2012-2024 Free Software Foundation, Inc.
;; Author: Tomohiro Matsuyama <tomo@cx4a.org>
;; Keywords: lisp
diff --git a/lisp/progmodes/antlr-mode.el b/lisp/progmodes/antlr-mode.el
index a54df19425a..1364214329a 100644
--- a/lisp/progmodes/antlr-mode.el
+++ b/lisp/progmodes/antlr-mode.el
@@ -1,6 +1,6 @@
;;; antlr-mode.el --- major mode for ANTLR grammar files -*- lexical-binding: t; -*-
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
;; Author: Christoph Wedler <Christoph.Wedler@sap.com>
;; Keywords: languages, ANTLR, code generator
diff --git a/lisp/progmodes/asm-mode.el b/lisp/progmodes/asm-mode.el
index 0f5af9803a5..d47c525c5f9 100644
--- a/lisp/progmodes/asm-mode.el
+++ b/lisp/progmodes/asm-mode.el
@@ -1,6 +1,6 @@
;;; asm-mode.el --- mode for editing assembler code -*- lexical-binding: t; -*-
-;; Copyright (C) 1991, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1991, 2001-2024 Free Software Foundation, Inc.
;; Author: Eric S. Raymond <esr@thyrsus.com>
;; Maintainer: emacs-devel@gnu.org
@@ -52,9 +52,13 @@
:link '(custom-group-link :tag "Font Lock Faces group" font-lock-faces)
:group 'languages)
+(defun asm--safe-comment-char-p (char)
+ (memq char '(?\; ?# ?@)))
+
(defcustom asm-comment-char ?\;
"The `comment-start' character assumed by Asm mode."
- :type 'character)
+ :type 'character
+ :safe #'asm--safe-comment-char-p)
(defvar asm-mode-syntax-table
(let ((st (make-syntax-table)))
diff --git a/lisp/progmodes/autoconf.el b/lisp/progmodes/autoconf.el
index 61e764c2bdc..95de105a9c5 100644
--- a/lisp/progmodes/autoconf.el
+++ b/lisp/progmodes/autoconf.el
@@ -1,6 +1,6 @@
;;; autoconf.el --- mode for editing Autoconf configure.ac files -*- lexical-binding: t; -*-
-;; Copyright (C) 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2000-2024 Free Software Foundation, Inc.
;; Author: Dave Love <fx@gnu.org>
;; Keywords: languages
diff --git a/lisp/progmodes/bat-mode.el b/lisp/progmodes/bat-mode.el
index 9eab9fd41a6..0687a0c9f32 100644
--- a/lisp/progmodes/bat-mode.el
+++ b/lisp/progmodes/bat-mode.el
@@ -1,6 +1,6 @@
;;; bat-mode.el --- Major mode for editing DOS/Windows scripts -*- lexical-binding: t -*-
-;; Copyright (C) 2003, 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003, 2008-2024 Free Software Foundation, Inc.
;; Author: Arni Magnusson <arnima@hafro.is>
;; Keywords: languages
diff --git a/lisp/progmodes/bug-reference.el b/lisp/progmodes/bug-reference.el
index bc280284588..29ff521253b 100644
--- a/lisp/progmodes/bug-reference.el
+++ b/lisp/progmodes/bug-reference.el
@@ -1,6 +1,6 @@
;;; bug-reference.el --- buttonize bug references -*- lexical-binding: t; -*-
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
;; Author: Tom Tromey <tromey@redhat.com>
;; Created: 21 Mar 2007
@@ -35,6 +35,8 @@
;;; Code:
+(require 'thingatpt)
+
(defgroup bug-reference nil
"Hyperlinking references to bug reports."
;; Somewhat arbitrary, by analogy with eg goto-address.
@@ -465,10 +467,10 @@ and set it if applicable."
(defun bug-reference--try-setup-gnus-article ()
(when (and bug-reference-mode ;; Only if enabled in article buffers.
(derived-mode-p
- 'gnus-article-mode
- ;; Apparently, gnus-article-prepare-hook is run in the
- ;; summary buffer...
- 'gnus-summary-mode)
+ '(gnus-article-mode
+ ;; Apparently, `gnus-article-prepare-hook' is run in the
+ ;; summary buffer...
+ gnus-summary-mode))
gnus-article-buffer
gnus-original-article-buffer
(buffer-live-p (get-buffer gnus-article-buffer))
@@ -654,17 +656,31 @@ have been run, the auto-setup is inhibited.")
(run-hook-with-args-until-success
'bug-reference-auto-setup-functions)))))
-;;;###autoload
-(define-minor-mode bug-reference-mode
- "Toggle hyperlinking bug references in the buffer (Bug Reference mode)."
- :after-hook (bug-reference--run-auto-setup)
- (if bug-reference-mode
- (jit-lock-register #'bug-reference-fontify)
+(defun bug-reference--url-at-point ()
+ "`thing-at-point' provider function."
+ (get-char-property (point) 'bug-reference-url))
+
+(defun bug-reference--init (enable)
+ (if enable
+ (progn
+ (jit-lock-register #'bug-reference-fontify)
+ (setq-local thing-at-point-provider-alist
+ (append thing-at-point-provider-alist
+ '((url . bug-reference--url-at-point)))))
(jit-lock-unregister #'bug-reference-fontify)
+ (setq thing-at-point-provider-alist
+ (delete '((url . bug-reference--url-at-point))
+ thing-at-point-provider-alist))
(save-restriction
(widen)
(bug-reference-unfontify (point-min) (point-max)))))
+;;;###autoload
+(define-minor-mode bug-reference-mode
+ "Toggle hyperlinking bug references in the buffer (Bug Reference mode)."
+ :after-hook (bug-reference--run-auto-setup)
+ (bug-reference--init bug-reference-mode))
+
(defun bug-reference-mode-force-auto-setup ()
"Enable `bug-reference-mode' and force auto-setup.
Enabling `bug-reference-mode' runs its auto-setup only if
@@ -681,12 +697,7 @@ same buffer is re-used for different contexts."
(define-minor-mode bug-reference-prog-mode
"Like `bug-reference-mode', but only buttonize in comments and strings."
:after-hook (bug-reference--run-auto-setup)
- (if bug-reference-prog-mode
- (jit-lock-register #'bug-reference-fontify)
- (jit-lock-unregister #'bug-reference-fontify)
- (save-restriction
- (widen)
- (bug-reference-unfontify (point-min) (point-max)))))
+ (bug-reference--init bug-reference-prog-mode))
(provide 'bug-reference)
;;; bug-reference.el ends here
diff --git a/lisp/progmodes/c-ts-common.el b/lisp/progmodes/c-ts-common.el
index e0a7c46508e..07161025d5d 100644
--- a/lisp/progmodes/c-ts-common.el
+++ b/lisp/progmodes/c-ts-common.el
@@ -1,8 +1,9 @@
;;; c-ts-common.el --- Utilities for C like Languages -*- lexical-binding: t; -*-
-;; Copyright (C) 2023 Free Software Foundation, Inc.
+;; Copyright (C) 2023-2024 Free Software Foundation, Inc.
;; Maintainer : 付禹安 (Yuan Fu) <casouri@gmail.com>
+;; Package : emacs
;; Keywords : c c++ java javascript rust languages tree-sitter
;; This file is part of GNU Emacs.
@@ -115,7 +116,7 @@ non-whitespace characters of the current line."
"Regexp pattern that matches a comment in C-like languages.")
(defun c-ts-common--fill-paragraph (&optional arg)
- "Fillling function for `c-ts-common'.
+ "Filling function for `c-ts-common'.
ARG is passed to `fill-paragraph'."
(interactive "*P")
(save-restriction
@@ -133,7 +134,7 @@ ARG is passed to `fill-paragraph'."
t)))
(defun c-ts-common--fill-block-comment (&optional arg)
- "Fillling function for block comments.
+ "Filling function for block comments.
ARG is passed to `fill-paragraph'. Assume point is in a block
comment."
(let* ((node (treesit-node-at (point)))
diff --git a/lisp/progmodes/c-ts-mode.el b/lisp/progmodes/c-ts-mode.el
index b3c48eb2c65..e5835bdb62d 100644
--- a/lisp/progmodes/c-ts-mode.el
+++ b/lisp/progmodes/c-ts-mode.el
@@ -1,6 +1,6 @@
;;; c-ts-mode.el --- tree-sitter support for C and C++ -*- lexical-binding: t; -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;; Author : Theodor Thornhill <theo@thornhill.no>
;; Maintainer : Theodor Thornhill <theo@thornhill.no>
@@ -71,6 +71,8 @@
(eval-when-compile (require 'rx))
(declare-function treesit-parser-create "treesit.c")
+(declare-function treesit-parser-root-node "treesit.c")
+(declare-function treesit-parser-set-included-ranges "treesit.c")
(declare-function treesit-node-parent "treesit.c")
(declare-function treesit-node-start "treesit.c")
(declare-function treesit-node-end "treesit.c")
@@ -80,7 +82,6 @@
(declare-function treesit-node-prev-sibling "treesit.c")
(declare-function treesit-node-first-child-for-pos "treesit.c")
(declare-function treesit-node-next-sibling "treesit.c")
-(declare-function treesit-parser-set-included-ranges "treesit.c")
(declare-function treesit-query-compile "treesit.c")
;;; Custom variables
@@ -134,7 +135,7 @@ symbol."
res)
(let ((buffer (car buffers)))
(with-current-buffer buffer
- (if (derived-mode-p 'c-ts-mode 'c++-ts-mode)
+ (if (derived-mode-p '(c-ts-mode c++-ts-mode))
(loop (append res (list buffer)) (cdr buffers))
(loop res (cdr buffers))))))))
@@ -192,7 +193,7 @@ in this Emacs session."
To set the default indent style globally, use
`c-ts-mode-set-global-style'."
(interactive (list (c-ts-mode--prompt-for-style)))
- (if (not (derived-mode-p 'c-ts-mode 'c++-ts-mode))
+ (if (not (derived-mode-p '(c-ts-mode c++-ts-mode)))
(user-error "The current buffer is not in `c-ts-mode' nor `c++-ts-mode'")
(setq-local c-ts-mode-indent-style style)
(setq treesit-simple-indent-rules
@@ -321,7 +322,8 @@ PARENT and BOL are like other anchor functions."
(treesit-node-parent prev-sibling) t)))
;; If the start of the previous sibling isn't at the
;; beginning of a line, something's probably not quite
- ;; right, go a step further.
+ ;; right, go a step further. (E.g., comment after a
+ ;; statement.)
(_ (goto-char (treesit-node-start prev-sibling))
(if (looking-back (rx bol (* whitespace))
(line-beginning-position))
@@ -355,11 +357,40 @@ PARENT, BOL, ARGS are the same as other anchor functions."
(apply (alist-get 'standalone-parent treesit-simple-indent-presets)
parent (treesit-node-parent parent) bol args))
+(defun c-ts-mode--else-heuristic (node parent bol &rest _)
+ "Heuristic matcher for when \"else\" is followed by a closing bracket.
+NODE, PARENT, and BOL are the same as in other matchers."
+ (and (null node)
+ (save-excursion
+ (forward-line -1)
+ (looking-at (rx (* whitespace) "else" (* whitespace) eol)))
+ (let ((next-node (treesit-node-first-child-for-pos parent bol)))
+ (equal (treesit-node-type next-node) "}"))))
+
+(defun c-ts-mode--first-sibling (node parent &rest _)
+ "Matches when NODE is the \"first sibling\".
+\"First sibling\" is defined as: the first child node of PARENT
+such that it's on its own line. NODE is the node to match and
+PARENT is its parent."
+ (let ((prev-sibling (treesit-node-prev-sibling node t)))
+ (or (null prev-sibling)
+ (save-excursion
+ (goto-char (treesit-node-start prev-sibling))
+ (<= (line-beginning-position)
+ (treesit-node-start parent)
+ (line-end-position))))))
+
(defun c-ts-mode--indent-styles (mode)
"Indent rules supported by `c-ts-mode'.
MODE is either `c' or `cpp'."
(let ((common
`((c-ts-mode--for-each-tail-body-matcher prev-line c-ts-mode-indent-offset)
+ ;; If the user types "else" and hits RET, they expect point
+ ;; on the empty line to be indented; this rule does that.
+ ;; This heuristic is intentionally very specific because
+ ;; more general heuristic is very error-prone, see
+ ;; discussion in bug#67417.
+ (c-ts-mode--else-heuristic prev-line c-ts-mode-indent-offset)
((parent-is "translation_unit") column-0 0)
((query "(ERROR (ERROR)) @indent") column-0 0)
@@ -406,6 +437,8 @@ MODE is either `c' or `cpp'."
((parent-is "preproc") c-ts-mode--anchor-prev-sibling 0)
((parent-is "function_definition") parent-bol 0)
+ ((parent-is "pointer_declarator") parent-bol 0)
+ ((parent-is ,(rx bos "declaration" eos)) parent-bol 0)
((parent-is "conditional_expression") first-sibling 0)
((parent-is "assignment_expression") parent-bol c-ts-mode-indent-offset)
((parent-is "concatenated_string") first-sibling 0)
@@ -441,7 +474,11 @@ MODE is either `c' or `cpp'."
((parent-is "field_declaration_list") c-ts-mode--anchor-prev-sibling 0)
;; Statement in {} blocks.
- ((or (match nil "compound_statement" nil 1 1)
+ ((or (and (parent-is "compound_statement")
+ ;; If the previous sibling(s) are not on their
+ ;; own line, indent as if this node is the first
+ ;; sibling (Bug#67357)
+ c-ts-mode--first-sibling)
(match null "compound_statement"))
standalone-parent c-ts-mode-indent-offset)
((parent-is "compound_statement") c-ts-mode--anchor-prev-sibling 0)
@@ -452,7 +489,9 @@ MODE is either `c' or `cpp'."
;; These rules are for cases where the body is bracketless.
;; Tested by the "Bracketless Simple Statement" test.
((parent-is "if_statement") standalone-parent c-ts-mode-indent-offset)
+ ((parent-is "else_clause") standalone-parent c-ts-mode-indent-offset)
((parent-is "for_statement") standalone-parent c-ts-mode-indent-offset)
+ ((match "while" "do_statement") parent-bol 0) ; (do_statement "while")
((parent-is "while_statement") standalone-parent c-ts-mode-indent-offset)
((parent-is "do_statement") standalone-parent c-ts-mode-indent-offset)
@@ -477,12 +516,13 @@ MODE is either `c' or `cpp'."
((node-is "labeled_statement") parent-bol c-ts-mode-indent-offset)
((parent-is "labeled_statement") parent-bol c-ts-mode-indent-offset)
((parent-is "compound_statement") parent-bol c-ts-mode-indent-offset)
- ((parent-is "if_statement") parent-bol 0)
- ((parent-is "for_statement") parent-bol 0)
- ((parent-is "while_statement") parent-bol 0)
- ((parent-is "switch_statement") parent-bol 0)
- ((parent-is "case_statement") parent-bol 0)
- ((parent-is "do_statement") parent-bol 0)
+ ((match "compound_statement" "if_statement") standalone-parent 0)
+ ((match "compound_statement" "else_clause") standalone-parent 0)
+ ((match "compound_statement" "for_statement") standalone-parent 0)
+ ((match "compound_statement" "while_statement") standalone-parent 0)
+ ((match "compound_statement" "switch_statement") standalone-parent 0)
+ ((match "compound_statement" "case_statement") standalone-parent 0)
+ ((match "compound_statement" "do_statement") standalone-parent 0)
,@common))))
(defun c-ts-mode--top-level-label-matcher (node parent &rest _)
@@ -495,6 +535,13 @@ NODE should be a labeled_statement. PARENT is its parent."
;;; Font-lock
+(defvar c-ts-mode--feature-list
+ '(( comment definition)
+ ( keyword preprocessor string type)
+ ( assignment constant escape-sequence label literal)
+ ( bracket delimiter error function operator property variable))
+ "`treesit-font-lock-feature-list' for `c-ts-mode'.")
+
(defvar c-ts-mode--preproc-keywords
'("#define" "#if" "#ifdef" "#ifndef"
"#else" "#elif" "#endif" "#include")
@@ -1013,17 +1060,46 @@ if `c-ts-mode-emacs-sources-support' is non-nil."
(or (treesit-add-log-current-defun)
(c-ts-mode--defun-name (c-ts-mode--emacs-defun-at-point))))
+;;; Things
+
+(defvar c-ts-mode--thing-settings
+ `(;; It's more useful to include semicolons as sexp so
+ ;; that users can move to the end of a statement.
+ (sexp (not ,(rx (or "{" "}" "[" "]" "(" ")" ","))))
+ ;; compound_statement makes us jump over too big units
+ ;; of code, so skip that one, and include the other
+ ;; statements.
+ (sentence
+ ,(regexp-opt '("preproc"
+ "declaration"
+ "specifier"
+ "attributed_statement"
+ "labeled_statement"
+ "expression_statement"
+ "if_statement"
+ "switch_statement"
+ "do_statement"
+ "while_statement"
+ "for_statement"
+ "return_statement"
+ "break_statement"
+ "continue_statement"
+ "goto_statement"
+ "case_statement")))
+ (text ,(regexp-opt '("comment"
+ "raw_string_literal"))))
+ "`treesit-thing-settings' for both C and C++.")
+
;;; Support for FOR_EACH_* macros
;;
;; FOR_EACH_TAIL, FOR_EACH_TAIL_SAFE, FOR_EACH_FRAME etc., followed by
;; an unbracketed body will mess up the parser, which parses the thing
;; as a function declaration. We "fix" it by adding a shadow parser
-;; for a language 'emacs-c' (which is just 'c' but under a different
-;; name). We use 'emacs-c' to find each FOR_EACH_* macro with a
-;; unbracketed body, and set the ranges of the C parser so that it
-;; skips those FOR_EACH_*'s. Note that we only ignore FOR_EACH_*'s
-;; with a unbracketed body. Those with a bracketed body parse more
-;; or less fine.
+;; with the tag `for-each'. We use this parser to find each
+;; FOR_EACH_* macro with a unbracketed body, and set the ranges of the
+;; default C parser so that it skips those FOR_EACH_*'s. Note that we
+;; only ignore FOR_EACH_*'s with a unbracketed body. Those with a
+;; bracketed body parse more or less fine.
;;
;; In the meantime, we have a special fontification rule for
;; FOR_EACH_* macros with a bracketed body that removes any applied
@@ -1044,12 +1120,12 @@ For BOL see `treesit-simple-indent-rules'."
(defvar c-ts-mode--emacs-c-range-query
(when (treesit-available-p)
(treesit-query-compile
- 'emacs-c `(((declaration
- type: (macro_type_specifier
- name: (identifier) @_name)
- @for-each-tail)
- (:match ,c-ts-mode--for-each-tail-regexp
- @_name)))))
+ 'c `(((declaration
+ type: (macro_type_specifier
+ name: (identifier) @_name)
+ @for-each-tail)
+ (:match ,c-ts-mode--for-each-tail-regexp
+ @_name)))))
"Query that finds a FOR_EACH_* macro with an unbracketed body.")
(defvar-local c-ts-mode--for-each-tail-ranges nil
@@ -1079,9 +1155,11 @@ parser parse the whole buffer."
"Set ranges for the C parser to skip some FOR_EACH_* macros.
BEG and END are described in `treesit-range-rules'."
(let* ((c-parser (treesit-parser-create 'c))
+ (for-each-parser (treesit-parser-create 'c nil nil 'for-each))
(old-ranges c-ts-mode--for-each-tail-ranges)
(new-ranges (treesit-query-range
- 'emacs-c c-ts-mode--emacs-c-range-query beg end))
+ (treesit-parser-root-node for-each-parser)
+ c-ts-mode--emacs-c-range-query beg end))
(set-ranges (treesit--clip-ranges
(treesit--merge-ranges
old-ranges new-ranges beg end)
@@ -1127,34 +1205,12 @@ BEG and END are described in `treesit-range-rules'."
(setq-local treesit-defun-skipper #'c-ts-mode--defun-skipper)
(setq-local treesit-defun-name-function #'c-ts-mode--defun-name)
- (setq-local treesit-sentence-type-regexp
- ;; compound_statement makes us jump over too big units
- ;; of code, so skip that one, and include the other
- ;; statements.
- (regexp-opt '("preproc"
- "declaration"
- "specifier"
- "attributed_statement"
- "labeled_statement"
- "expression_statement"
- "if_statement"
- "switch_statement"
- "do_statement"
- "while_statement"
- "for_statement"
- "return_statement"
- "break_statement"
- "continue_statement"
- "goto_statement"
- "case_statement")))
-
;; IMO it makes more sense to define what's NOT sexp, since sexp by
;; spirit, especially when used for movement, is like "expression"
;; or "syntax unit". --yuan
- (setq-local treesit-sexp-type-regexp
- ;; It more useful to include semicolons as sexp so that
- ;; users can move to the end of a statement.
- (rx (not (or "{" "}" "[" "]" "(" ")" ","))))
+ (setq-local treesit-thing-settings
+ `((c ,@c-ts-mode--thing-settings)
+ (cpp ,@c-ts-mode--thing-settings)))
;; Nodes like struct/enum/union_specifier can appear in
;; function_definitions, so we need to find the top-level node.
@@ -1204,10 +1260,7 @@ BEG and END are described in `treesit-range-rules'."
c-ts-mode--defun-for-class-in-imenu-p nil))))
(setq-local treesit-font-lock-feature-list
- '(( comment definition)
- ( keyword preprocessor string type)
- ( assignment constant escape-sequence label literal)
- ( bracket delimiter error function operator property variable))))
+ c-ts-mode--feature-list))
(defvar treesit-load-name-override-list)
@@ -1231,16 +1284,10 @@ in your configuration."
:after-hook (c-ts-mode-set-modeline)
(when (treesit-ready-p 'c)
- ;; Add a fake "emacs-c" language which is just C. Used for
- ;; skipping FOR_EACH_* macros, see `c-ts-mode--emacs-set-ranges'.
- (setf (alist-get 'emacs-c treesit-load-name-override-list)
- '("libtree-sitter-c" "tree_sitter_c"))
- ;; If Emacs source support is enabled, make sure emacs-c parser is
- ;; after c parser in the parser list. This way various tree-sitter
- ;; functions will automatically use the c parser rather than the
- ;; emacs-c parser.
+ ;; Create an "for-each" parser, see `c-ts-mode--emacs-set-ranges'
+ ;; for more.
(when c-ts-mode-emacs-sources-support
- (treesit-parser-create 'emacs-c))
+ (treesit-parser-create 'c nil nil 'for-each))
(treesit-parser-create 'c)
;; Comments.
@@ -1291,9 +1338,6 @@ recommended to enable `electric-pair-mode' with this mode."
:after-hook (c-ts-mode-set-modeline)
(when (treesit-ready-p 'cpp)
- (setq-local treesit-text-type-regexp
- (regexp-opt '("comment"
- "raw_string_literal")))
(treesit-parser-create 'cpp)
@@ -1339,7 +1383,7 @@ recommended to enable `electric-pair-mode' with this mode."
c-ts-mode-indent-style)
:help "Show the name of the C/C++ indentation style for current buffer"]
["Set Comment Style" c-ts-mode-toggle-comment-style
- :help "Toglle C/C++ comment style between block and line comments"])
+ :help "Toggle C/C++ comment style between block and line comments"])
"--"
("Toggle..."
["SubWord Mode" subword-mode
@@ -1412,5 +1456,6 @@ the code is C or C++ and based on that chooses whether to enable
(add-to-list 'auto-mode-alist '("\\.h\\'" . c-or-c++-ts-mode)))
(provide 'c-ts-mode)
+(provide 'c++-ts-mode)
;;; c-ts-mode.el ends here
diff --git a/lisp/progmodes/cc-align.el b/lisp/progmodes/cc-align.el
index 91a7665edbb..fbbb81b6f10 100644
--- a/lisp/progmodes/cc-align.el
+++ b/lisp/progmodes/cc-align.el
@@ -1,6 +1,6 @@
;;; cc-align.el --- custom indentation functions for CC Mode -*- lexical-binding: t -*-
-;; Copyright (C) 1985, 1987, 1992-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1985, 1987, 1992-2024 Free Software Foundation, Inc.
;; Authors: 2004- Alan Mackenzie
;; 1998- Martin Stjernholm
diff --git a/lisp/progmodes/cc-awk.el b/lisp/progmodes/cc-awk.el
index c367341345d..e299f4fa8d2 100644
--- a/lisp/progmodes/cc-awk.el
+++ b/lisp/progmodes/cc-awk.el
@@ -1,6 +1,6 @@
;;; cc-awk.el --- AWK specific code within cc-mode. -*- lexical-binding: t -*-
-;; Copyright (C) 1988, 1994, 1996, 2000-2023 Free Software Foundation,
+;; Copyright (C) 1988, 1994, 1996, 2000-2024 Free Software Foundation,
;; Inc.
;; Author: Alan Mackenzie <acm@muc.de> (originally based on awk-mode.el)
@@ -754,14 +754,14 @@
(if (eq (char-after beg) ?_) (setq beg (1+ beg)))
;; First put the properties on the delimiters.
- (cond ((eq end (point-max)) ; string/regexp terminated by EOB
- (c-put-char-property beg 'syntax-table '(15))) ; (15) = "string fence"
- ((/= (char-after beg) (char-after end)) ; missing end delimiter
- (c-put-char-property beg 'syntax-table '(15))
- (c-put-char-property end 'syntax-table '(15)))
- ((eq (char-after beg) ?/) ; Properly bracketed regexp
- (c-put-char-property beg 'syntax-table '(7)) ; (7) = "string"
- (c-put-char-property end 'syntax-table '(7)))
+ (cond ((eq end (point-max)) ; string/regexp terminated by EOB
+ (c-put-string-fence beg))
+ ((/= (char-after beg) (char-after end)) ; missing end delimiter
+ (c-put-string-fence beg)
+ (c-put-string-fence end))
+ ((eq (char-after beg) ?/) ; Properly bracketed regexp
+ (c-put-char-property beg 'syntax-table '(7)) ; (7) = "string"
+ (c-put-char-property end 'syntax-table '(7)))
(t)) ; Properly bracketed string: Nothing to do.
;; Now change the properties of any escaped "s in the string to punctuation.
(save-excursion
diff --git a/lisp/progmodes/cc-bytecomp.el b/lisp/progmodes/cc-bytecomp.el
index c3caffbe8d2..b6923e46339 100644
--- a/lisp/progmodes/cc-bytecomp.el
+++ b/lisp/progmodes/cc-bytecomp.el
@@ -1,6 +1,6 @@
;;; cc-bytecomp.el --- compile time setup for proper compilation -*- lexical-binding: t -*-
-;; Copyright (C) 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2000-2024 Free Software Foundation, Inc.
;; Author: Martin Stjernholm
;; Maintainer: bug-cc-mode@gnu.org
diff --git a/lisp/progmodes/cc-cmds.el b/lisp/progmodes/cc-cmds.el
index 15b103a081f..7cd6cb0dda0 100644
--- a/lisp/progmodes/cc-cmds.el
+++ b/lisp/progmodes/cc-cmds.el
@@ -1,6 +1,6 @@
;;; cc-cmds.el --- user level commands for CC Mode -*- lexical-binding: t -*-
-;; Copyright (C) 1985, 1987, 1992-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1985, 1987, 1992-2024 Free Software Foundation, Inc.
;; Authors: 2003- Alan Mackenzie
;; 1998- Martin Stjernholm
@@ -4909,7 +4909,8 @@ If a fill prefix is specified, it overrides all the above."
(setq c-lit-limits (c-literal-limits nil nil t)))
(unless c-lit-type
(setq c-lit-type (c-literal-type c-lit-limits)))
- (if (memq (cond ((c-query-and-set-macro-start) 'cpp)
+ (if (memq (cond ((memq c-lit-type '(c c++ string)) c-lit-type)
+ ((c-query-and-set-macro-start) 'cpp)
((null c-lit-type) 'code)
(t c-lit-type))
c-ignore-auto-fill)
diff --git a/lisp/progmodes/cc-defs.el b/lisp/progmodes/cc-defs.el
index 2cbe9ca7e92..f84d95dbc94 100644
--- a/lisp/progmodes/cc-defs.el
+++ b/lisp/progmodes/cc-defs.el
@@ -1,6 +1,6 @@
;;; cc-defs.el --- compile time definitions for CC Mode -*- lexical-binding: t -*-
-;; Copyright (C) 1985, 1987, 1992-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1985, 1987, 1992-2024 Free Software Foundation, Inc.
;; Authors: 2003- Alan Mackenzie
;; 1998- Martin Stjernholm
@@ -733,9 +733,10 @@ various buffer change hooks."
(defmacro c-forward-syntactic-ws (&optional limit)
"Forward skip over syntactic whitespace.
-Syntactic whitespace is defined as whitespace characters, comments,
-and preprocessor directives. However if point starts inside a comment
-or preprocessor directive, the content of it is not treated as
+Syntactic whitespace is defined as whitespace characters with
+whitespace (or comment-end) syntax, comments, and preprocessor
+directives. However if point starts inside a comment or
+preprocessor directive, the content of it is not treated as
whitespace.
LIMIT sets an upper limit of the forward movement, if specified. If
@@ -755,9 +756,10 @@ comment at the start of cc-engine.el for more info."
(defmacro c-backward-syntactic-ws (&optional limit)
"Backward skip over syntactic whitespace.
-Syntactic whitespace is defined as whitespace characters, comments,
-and preprocessor directives. However if point starts inside a comment
-or preprocessor directive, the content of it is not treated as
+Syntactic whitespace is defined as whitespace characters with
+whitespace (or comment-end) syntax, comments, and preprocessor
+directives. However if point starts inside a comment or
+preprocessor directive, the content of it is not treated as
whitespace.
LIMIT sets a lower limit of the backward movement, if specified. If
@@ -925,7 +927,8 @@ be after it."
(when dest (goto-char dest) t)))
(defmacro c-beginning-of-defun-1 ()
- ;; Wrapper around beginning-of-defun.
+ ;; Wrapper around beginning-of-defun. Note that the return value from this
+ ;; macro has no significance.
;;
;; NOTE: This function should contain the only explicit use of
;; beginning-of-defun in CC Mode. Eventually something better than
@@ -938,44 +941,49 @@ be after it."
;; `c-parse-state'.
`(progn
- (if (and ,(fboundp 'buffer-syntactic-context-depth)
- c-enable-xemacs-performance-kludge-p)
- ,(when (fboundp 'buffer-syntactic-context-depth)
- ;; XEmacs only. This can improve the performance of
- ;; c-parse-state to between 3 and 60 times faster when
- ;; braces are hung. It can also degrade performance by
- ;; about as much when braces are not hung.
- '(let (beginning-of-defun-function end-of-defun-function
- pos)
- (while (not pos)
- (save-restriction
- (widen)
- (setq pos (c-safe-scan-lists
- (point) -1 (buffer-syntactic-context-depth))))
- (cond
- ((bobp) (setq pos (point-min)))
- ((not pos)
- (let ((distance (skip-chars-backward "^{")))
- ;; unbalanced parenthesis, while invalid C code,
- ;; shouldn't cause an infloop! See unbal.c
- (when (zerop distance)
- ;; Punt!
- (beginning-of-defun)
- (setq pos (point)))))
- ((= pos 0))
- ((not (eq (char-after pos) ?{))
- (goto-char pos)
- (setq pos nil))
- ))
- (goto-char pos)))
- ;; Emacs, which doesn't have buffer-syntactic-context-depth
- (let (beginning-of-defun-function end-of-defun-function)
- (beginning-of-defun)))
- ;; if defun-prompt-regexp is non-nil, b-o-d won't leave us at the
- ;; open brace.
- (and defun-prompt-regexp
- (looking-at defun-prompt-regexp)
- (goto-char (match-end 0)))))
+ (while
+ (progn
+ (if (and ,(fboundp 'buffer-syntactic-context-depth)
+ c-enable-xemacs-performance-kludge-p)
+ ,(when (fboundp 'buffer-syntactic-context-depth)
+ ;; XEmacs only. This can improve the performance of
+ ;; c-parse-state to between 3 and 60 times faster when
+ ;; braces are hung. It can also degrade performance by
+ ;; about as much when braces are not hung.
+ '(let (beginning-of-defun-function end-of-defun-function
+ pos)
+ (while (not pos)
+ (save-restriction
+ (widen)
+ (setq pos (c-safe-scan-lists
+ (point) -1 (buffer-syntactic-context-depth))))
+ (cond
+ ((bobp) (setq pos (point-min)))
+ ((not pos)
+ (let ((distance (skip-chars-backward "^{")))
+ ;; unbalanced parenthesis, while invalid C code,
+ ;; shouldn't cause an infloop! See unbal.c
+ (when (zerop distance)
+ ;; Punt!
+ (beginning-of-defun)
+ (setq pos (point)))))
+ ((= pos 0))
+ ((not (eq (char-after pos) ?{))
+ (goto-char pos)
+ (setq pos nil))
+ ))
+ (goto-char pos)))
+ ;; Emacs, which doesn't have buffer-syntactic-context-depth
+ (let (beginning-of-defun-function end-of-defun-function)
+ (beginning-of-defun)))
+ (and (not (bobp))
+ ;; if defun-prompt-regexp is non-nil, b-o-d won't leave us at
+ ;; the open brace.
+ defun-prompt-regexp
+ (looking-at (concat defun-prompt-regexp "\\s("))
+ (or (not (eq (char-before (match-end 0)) ?{))
+ (progn (goto-char (1- (match-end 0)))
+ nil)))))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -1102,6 +1110,38 @@ continuations."
(eq (char-before) ?\\)))
(backward-char))))
+(defmacro c-skip-ws-chars-forward (string &optional lim)
+ ;; Move point forward, stopping before a char which isn't in STRING, or a
+ ;; char whose syntax isn't whitespace or comment-end, or at pos LIM.
+ ;; Note that \n usually has comment-end syntax.
+ ;;
+ ;; Returns the distance traveled, either zero or positive.
+ (declare (debug t))
+ `(let ((-lim- ,lim)
+ (here (point))
+ count)
+ (setq count (skip-chars-forward ,string -lim-))
+ (when (> count 0)
+ (goto-char here)
+ (setq count (skip-syntax-forward " >" (+ here count))))
+ count))
+
+(defmacro c-skip-ws-chars-backward (string &optional lim)
+ ;; Move point backward, stopping after a char which isn't in STRING, or a
+ ;; char whose syntax isn't whitespace or comment-end, or at pos LIM. Note
+ ;; that \n usually has comment-end syntax.
+ ;;
+ ;; Returns the distance traveled, either zero or negative.
+ (declare (debug t))
+ `(let ((-lim- ,lim)
+ (here (point))
+ count)
+ (setq count (skip-chars-backward ,string -lim-))
+ (when (< count 0)
+ (goto-char here)
+ (setq count (skip-syntax-backward " >" (+ here count))))
+ count))
+
(eval-and-compile
(defvar c-langs-are-parametric nil))
@@ -1208,6 +1248,17 @@ MODE is either a mode symbol or a list of mode symbols."
`((setq c-syntax-table-hwm (min c-syntax-table-hwm -pos-))))
(put-text-property -pos- (1+ -pos-) ',property ,value))))
+(defmacro c-put-string-fence (pos)
+ ;; Put the string-fence syntax-table text property at POS.
+ ;; Since the character there cannot then count as syntactic whitespace,
+ ;; clear the properties `c-is-sws' and `c-in-sws' (see functions
+ ;; `c-forward-sws' and `c-backward-sws' in cc-engine.el for details).
+ (declare (debug t))
+ `(let ((-pos- ,pos))
+ (c-put-char-property -pos- 'syntax-table '(15))
+ (c-clear-char-property -pos- 'c-is-sws)
+ (c-clear-char-property -pos- 'c-in-sws)))
+
(eval-and-compile
;; Constant to decide at compilation time whether to use category
;; properties. Currently (2010-03) they're available only on GNU
@@ -1298,27 +1349,19 @@ MODE is either a mode symbol or a list of mode symbols."
(most-positive-fixnum))))
(defmacro c-put-char-properties (from to property value)
- ;; FIXME!!! Doc comment here!
+ ;; Put the given PROPERTY with the given VALUE on the characters between
+ ;; FROM and TO. PROPERTY is assumed to be constant. The return value is
+ ;; undefined.
+ ;;
+ ;; This macro does hidden buffer changes.
(declare (debug t))
(setq property (eval property))
- `(let ((-to- ,to) (-from- ,from))
- ,(if c-use-extents
- ;; XEmacs
- `(progn
- (map-extents (lambda (ext ignored)
- (delete-extent ext))
- nil -from- -to- nil nil ',property)
- (set-extent-properties (make-extent -from- -to-)
- (cons property
- (cons ,value
- '(start-open t
- end-open t)))))
- ;; Emacs
- `(progn
+ `(let ((-from- ,from))
+ (progn
,@(when (and (fboundp 'syntax-ppss)
(eq `,property 'syntax-table))
`((setq c-syntax-table-hwm (min c-syntax-table-hwm -from-))))
- (put-text-property -from- -to- ',property ,value)))))
+ (put-text-property -from- ,to ',property ,value))))
(defmacro c-clear-char-properties (from to property)
;; Remove all the occurrences of the given property in the given
diff --git a/lisp/progmodes/cc-engine.el b/lisp/progmodes/cc-engine.el
index abcc20fcb82..4c591fbba36 100644
--- a/lisp/progmodes/cc-engine.el
+++ b/lisp/progmodes/cc-engine.el
@@ -1,6 +1,6 @@
;;; cc-engine.el --- core syntax guessing engine for CC mode -*- lexical-binding:t; coding: utf-8 -*-
-;; Copyright (C) 1985, 1987, 1992-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1985, 1987, 1992-2024 Free Software Foundation, Inc.
;; Authors: 2001- Alan Mackenzie
;; 1998- Martin Stjernholm
@@ -976,10 +976,10 @@ comment at the start of cc-engine.el for more info."
(point-min)))
(widen)
- (if (save-excursion
- (and (c-beginning-of-macro)
- (/= (point) start)))
- (setq macro-start (point)))
+ (save-excursion
+ (if (and (c-beginning-of-macro)
+ (/= (point) start))
+ (setq macro-start (point))))
;; Try to skip back over unary operator characters, to register
;; that we've moved.
@@ -2130,7 +2130,7 @@ comment at the start of cc-engine.el for more info."
;; Skip simple ws and do a quick check on the following character to see
;; if it's anything that can't start syntactic ws, so we can bail out
;; early in the majority of cases when there just are a few ws chars.
- (skip-chars-forward " \t\n\r\f\v")
+ (c-skip-ws-chars-forward " \t\n\r\f\v")
(when (or (looking-at c-syntactic-ws-start)
(and c-opt-cpp-prefix
(looking-at c-noise-macro-name-re))
@@ -2180,7 +2180,7 @@ comment at the start of cc-engine.el for more info."
rung-pos (point) (point-max))
(setq rung-pos (point))
- (and (> (skip-chars-forward " \t\n\r\f\v") 0)
+ (and (> (c-skip-ws-chars-forward " \t\n\r\f\v") 0)
(not (eobp))))
;; We'll loop here if there is simple ws after the last rung.
@@ -2246,7 +2246,7 @@ comment at the start of cc-engine.el for more info."
(and c-opt-cpp-prefix
(looking-at c-opt-cpp-start)
(setq macro-start (point))
- (progn (skip-chars-backward " \t")
+ (progn (c-skip-ws-chars-backward " \t")
(bolp))
(or (bobp)
(progn (backward-char)
@@ -2286,7 +2286,7 @@ comment at the start of cc-engine.el for more info."
;; We've searched over a piece of non-white syntactic ws. See if this
;; can be cached.
(setq next-rung-pos (point))
- (skip-chars-forward " \t\n\r\f\v")
+ (c-skip-ws-chars-forward " \t\n\r\f\v")
(setq rung-end-pos (min (1+ (point)) (point-max)))
(if (or
@@ -2383,7 +2383,7 @@ comment at the start of cc-engine.el for more info."
;; bail out early in the majority of cases when there just are a few ws
;; chars. Newlines are complicated in the backward direction, so we can't
;; skip over them.
- (skip-chars-backward " \t\f")
+ (c-skip-ws-chars-backward " \t\f")
(when (and (not (bobp))
(save-excursion
(or (and
@@ -2411,7 +2411,7 @@ comment at the start of cc-engine.el for more info."
(setq simple-ws-beg (or attr-end ; After attribute.
(match-end 1) ; Noise macro, etc.
(match-end 0))) ; c-syntactic-ws-end
- (skip-chars-backward " \t\n\r\f\v")
+ (c-skip-ws-chars-backward " \t\n\r\f\v")
(if (setq rung-is-marked (text-property-any
(point) (min (1+ rung-pos) (point-max))
'c-is-sws t))
@@ -2448,10 +2448,10 @@ comment at the start of cc-engine.el for more info."
(point) rung-pos (point-min))
(setq rung-pos (point))
- (if (and (< (min (skip-chars-backward " \t\f\v")
+ (if (and (< (min (c-skip-ws-chars-backward " \t\f\v")
(progn
(setq simple-ws-beg (point))
- (skip-chars-backward " \t\n\r\f\v")))
+ (c-skip-ws-chars-backward " \t\n\r\f\v")))
0)
(setq rung-is-marked
(text-property-any (point) rung-pos
@@ -2531,7 +2531,7 @@ comment at the start of cc-engine.el for more info."
;; the macro, and then `simple-ws-beg' must be kept on the
;; same side of those comments.
(goto-char simple-ws-beg)
- (skip-chars-backward " \t\n\r\f\v")
+ (c-skip-ws-chars-backward " \t\n\r\f\v")
(if (eq (char-before) ?\\)
(forward-char))
(forward-line 1)
@@ -2544,7 +2544,7 @@ comment at the start of cc-engine.el for more info."
t)))
((/= (save-excursion
- (skip-chars-forward " \t\n\r\f\v" simple-ws-beg)
+ (c-skip-ws-chars-forward " \t\n\r\f\v" simple-ws-beg)
(setq next-rung-pos (point)))
simple-ws-beg)
;; Skipped over comments. Must put point at the end of
@@ -2581,7 +2581,7 @@ comment at the start of cc-engine.el for more info."
;; We've searched over a piece of non-white syntactic ws. See if this
;; can be cached.
(setq next-rung-pos (point))
- (skip-chars-backward " \t\f\v")
+ (c-skip-ws-chars-backward " \t\f\v")
(if (or
;; Cache if we started either from a marked rung or from a
@@ -2591,7 +2591,7 @@ comment at the start of cc-engine.el for more info."
;; Cache if there's a marked rung in the encountered simple ws.
(save-excursion
- (skip-chars-backward " \t\n\r\f\v")
+ (c-skip-ws-chars-backward " \t\n\r\f\v")
(text-property-any (point) (min (1+ next-rung-pos) (point-max))
'c-is-sws t)))
@@ -7202,10 +7202,8 @@ comment at the start of cc-engine.el for more info."
(progn
(c-clear-char-property (1- beg-literal-end)
'syntax-table)
- (c-put-char-property (1- end-literal-end)
- 'syntax-table '(15)))
- (c-put-char-property (1- beg-literal-end)
- 'syntax-table '(15))
+ (c-put-string-fence (1- end-literal-end)))
+ (c-put-string-fence (1- beg-literal-end))
(c-clear-char-property (1- end-literal-end)
'syntax-table)))
@@ -7284,10 +7282,8 @@ comment at the start of cc-engine.el for more info."
(progn
(c-clear-char-property (1- beg-literal-end)
'syntax-table)
- (c-put-char-property (1- end-literal-end)
- 'syntax-table '(15)))
- (c-put-char-property (1- beg-literal-end)
- 'syntax-table '(15))
+ (c-put-string-fence (1- end-literal-end)))
+ (c-put-string-fence (1- beg-literal-end))
(c-clear-char-property (1- end-literal-end)
'syntax-table)))))
;; Extend the fontification region, if needed.
@@ -7558,7 +7554,7 @@ multi-line strings (but not C++, for example)."
(defun c-ml-string-opener-intersects-region (&optional start finish)
;; If any part of the region [START FINISH] is inside an ml-string opener,
;; return a dotted list of the start, end and double-quote position of the
- ;; first such opener. That list wlll not include any "context characters"
+ ;; first such opener. That list will not include any "context characters"
;; before or after the opener. If an opener is found, the match-data will
;; indicate it, with (match-string 1) being the entire delimiter, and
;; (match-string 2) the "main" double-quote. Otherwise, the match-data is
@@ -7946,7 +7942,7 @@ multi-line strings (but not C++, for example)."
(insert (nth 3 (car state))))
((eq (nth 3 (car state)) t)
(insert ?\")
- (c-put-char-property end 'syntax-table '(15))))
+ (c-put-string-fence end)))
(c-truncate-lit-pos-cache end)
;; ....ensure c-new-END extends right to the end of the about
;; to be un-stringed raw string....
@@ -8191,7 +8187,7 @@ multi-line strings (but not C++, for example)."
(goto-char (cadr end-delim))
t)
(c-put-char-property (cddr delim) 'syntax-table '(1))
- (c-put-char-property (1- (cadr delim)) 'syntax-table '(15))
+ (c-put-string-fence (1- (cadr delim)))
(c-truncate-lit-pos-cache (1- (cddr delim)))
(when bound
;; In a CPP construct, we try to apply a generic-string
@@ -8221,10 +8217,10 @@ multi-line strings (but not C++, for example)."
(cadr delim) t))
(if (match-beginning 10)
(progn
- (c-put-char-property (match-beginning 10) 'syntax-table '(15))
+ (c-put-string-fence (match-beginning 10))
(c-truncate-lit-pos-cache (match-beginning 10)))
(c-put-char-property (match-beginning 5) 'syntax-table '(1))
- (c-put-char-property (1+ (match-beginning 5)) 'syntax-table '(15))
+ (c-put-string-fence (1+ (match-beginning 5)))
(c-truncate-lit-pos-cache (match-beginning 5))))
(goto-char bound))
nil))
@@ -9444,37 +9440,47 @@ multi-line strings (but not C++, for example)."
(or c-promote-possible-types (eq res t)))
(c-record-type-id (cons (match-beginning 1) (match-end 1))))
- (if (and c-opt-type-component-key
+ (cond
+ ((and c-opt-type-component-key
(save-match-data
(looking-at c-opt-type-component-key)))
;; There might be more keywords for the type.
- (let (safe-pos)
- (c-forward-keyword-clause 1 t)
- (while (progn
- (setq safe-pos (point))
- (c-forward-syntactic-ws)
- (looking-at c-opt-type-component-key))
- (when (and c-record-type-identifiers
- (looking-at c-primitive-type-key))
- (c-record-type-id (cons (match-beginning 1)
- (match-end 1))))
- (c-forward-keyword-clause 1 t))
- (if (looking-at c-primitive-type-key)
- (progn
- (when c-record-type-identifiers
- (c-record-type-id (cons (match-beginning 1)
- (match-end 1))))
- (c-forward-keyword-clause 1 t)
- (setq res t))
- (goto-char safe-pos)
- (setq res 'prefix))
- (setq pos (point)))
- (if (save-match-data (c-forward-keyword-clause 1 t))
- (setq pos (point))
- (if pos
- (goto-char pos)
- (goto-char (match-end 1))
- (setq pos (point)))))
+ (let (safe-pos)
+ (c-forward-keyword-clause 1 t)
+ (while (progn
+ (setq safe-pos (point))
+ (c-forward-syntactic-ws)
+ (looking-at c-opt-type-component-key))
+ (when (and c-record-type-identifiers
+ (looking-at c-primitive-type-key))
+ (c-record-type-id (cons (match-beginning 1)
+ (match-end 1))))
+ (c-forward-keyword-clause 1 t))
+ (if (looking-at c-primitive-type-key)
+ (progn
+ (when c-record-type-identifiers
+ (c-record-type-id (cons (match-beginning 1)
+ (match-end 1))))
+ (c-forward-keyword-clause 1 t)
+ (setq res t)
+ (while (progn
+ (setq safe-pos (point))
+ (c-forward-syntactic-ws)
+ (looking-at c-opt-type-component-key))
+ (c-forward-keyword-clause 1 t)))
+ (goto-char safe-pos)
+ (setq res 'prefix))
+ (setq pos (point))))
+ ((save-match-data (c-forward-keyword-clause 1 t))
+ (while (progn
+ (setq pos (point))
+ (c-forward-syntactic-ws)
+ (and c-opt-type-component-key
+ (looking-at c-opt-type-component-key)))
+ (c-forward-keyword-clause 1 t)))
+ (pos (goto-char pos))
+ (t (goto-char (match-end 1))
+ (setq pos (point))))
(c-forward-syntactic-ws))
((and (eq name-res t)
@@ -9885,7 +9891,7 @@ point unchanged and return nil."
;; Note that this function is incomplete, handling only those cases expected
;; to be common in a C++20 requires clause.
;;
- ;; Note also that (...) is not recognised as a primary expression if the
+ ;; Note also that (...) is not recognized as a primary expression if the
;; next token is an open brace.
(let ((here (point))
(c-restricted-<>-arglists t)
@@ -12270,11 +12276,14 @@ comment at the start of cc-engine.el for more info."
;; Each time around the following checks one
;; declaration (which may contain several identifiers).
(while (and
- (consp (setq decl-or-cast
- (c-forward-decl-or-cast-1
- after-prec-token
- nil ; Or 'arglist ???
- nil)))
+ (not (eq (char-after) ?{))
+ (or
+ (consp (setq decl-or-cast
+ (c-forward-decl-or-cast-1
+ after-prec-token
+ nil ; Or 'arglist ???
+ nil)))
+ (throw 'knr nil))
(memq (char-after) '(?\; ?\,))
(goto-char (car decl-or-cast))
(save-excursion
@@ -12618,31 +12627,27 @@ comment at the start of cc-engine.el for more info."
(let ((open-brace (point)) kwd-start first-specifier-pos)
(c-syntactic-skip-backward c-block-prefix-charset limit t)
- (when (and c-recognize-<>-arglists
- (eq (char-before) ?>))
- ;; Could be at the end of a template arglist.
- (let ((c-parse-and-markup-<>-arglists t))
- (while (and
- (c-backward-<>-arglist nil limit)
- (progn
- (c-syntactic-skip-backward c-block-prefix-charset limit t)
- (eq (char-before) ?>))))))
-
- ;; Skip back over noise clauses.
- (while (and
- c-opt-cpp-prefix
- (eq (char-before) ?\))
- (let ((after-paren (point)))
- (if (and (c-go-list-backward)
- (progn (c-backward-syntactic-ws)
- (c-simple-skip-symbol-backward))
- (or (looking-at c-paren-nontype-key)
- (looking-at c-noise-macro-with-parens-name-re)))
- (progn
- (c-syntactic-skip-backward c-block-prefix-charset limit t)
- t)
- (goto-char after-paren)
- nil))))
+ (while
+ (or
+ ;; Could be after a template arglist....
+ (and c-recognize-<>-arglists
+ (eq (char-before) ?>)
+ (let ((c-parse-and-markup-<>-arglists t))
+ (c-backward-<>-arglist nil limit)))
+ ;; .... or after a noise clause with parens.
+ (and c-opt-cpp-prefix
+ (let ((after-paren (point)))
+ (if (eq (char-before) ?\))
+ (and
+ (c-go-list-backward)
+ (eq (char-after) ?\()
+ (progn (c-backward-syntactic-ws)
+ (c-simple-skip-symbol-backward))
+ (or (looking-at c-paren-nontype-key) ; e.g. __attribute__
+ (looking-at c-noise-macro-with-parens-name-re)))
+ (goto-char after-paren)
+ nil))))
+ (c-syntactic-skip-backward c-block-prefix-charset limit t))
;; Note: Can't get bogus hits inside template arglists below since they
;; have gotten paren syntax above.
@@ -12652,10 +12657,18 @@ comment at the start of cc-engine.el for more info."
;; The `c-decl-block-key' search continues from there since
;; we know it can't match earlier.
(if goto-start
- (when (c-syntactic-re-search-forward c-symbol-start
- open-brace t t)
- (goto-char (setq first-specifier-pos (match-beginning 0)))
- t)
+ (progn
+ (while
+ (and
+ (c-syntactic-re-search-forward c-symbol-start
+ open-brace t t)
+ (goto-char (match-beginning 0))
+ (if (or (looking-at c-noise-macro-name-re)
+ (looking-at c-noise-macro-with-parens-name-re))
+ (c-forward-noise-clause)
+ (setq first-specifier-pos (match-beginning 0))
+ nil)))
+ first-specifier-pos)
t)
(cond
@@ -12724,34 +12737,39 @@ comment at the start of cc-engine.el for more info."
(goto-char first-specifier-pos)
(while (< (point) kwd-start)
- (if (looking-at c-symbol-key)
- ;; Accept any plain symbol token on the ground that
- ;; it's a specifier masked through a macro (just
- ;; like `c-forward-decl-or-cast-1' skip forward over
- ;; such tokens).
- ;;
- ;; Could be more restrictive wrt invalid keywords,
- ;; but that'd only occur in invalid code so there's
- ;; no use spending effort on it.
- (let ((end (match-end 0))
- (kwd-sym (c-keyword-sym (match-string 0))))
- (unless
- (and kwd-sym
- ;; Moving over a protection kwd and the following
- ;; ":" (in C++ Mode) to the next token could take
- ;; us all the way up to `kwd-start', leaving us
- ;; no chance to update `first-specifier-pos'.
- (not (c-keyword-member kwd-sym 'c-protection-kwds))
- (c-forward-keyword-clause 0))
- (goto-char end)
- (c-forward-syntactic-ws)))
-
+ (cond
+ ((or (looking-at c-noise-macro-name-re)
+ (looking-at c-noise-macro-with-parens-name-re))
+ (c-forward-noise-clause))
+ ((looking-at c-symbol-key)
+ ;; Accept any plain symbol token on the ground that
+ ;; it's a specifier masked through a macro (just
+ ;; like `c-forward-decl-or-cast-1' skips forward over
+ ;; such tokens).
+ ;;
+ ;; Could be more restrictive wrt invalid keywords,
+ ;; but that'd only occur in invalid code so there's
+ ;; no use spending effort on it.
+ (let ((end (match-end 0))
+ (kwd-sym (c-keyword-sym (match-string 0))))
+ (unless
+ (and kwd-sym
+ ;; Moving over a protection kwd and the following
+ ;; ":" (in C++ Mode) to the next token could take
+ ;; us all the way up to `kwd-start', leaving us
+ ;; no chance to update `first-specifier-pos'.
+ (not (c-keyword-member kwd-sym 'c-protection-kwds))
+ (c-forward-keyword-clause 0))
+ (goto-char end)
+ (c-forward-syntactic-ws))))
+
+ ((c-syntactic-re-search-forward c-symbol-start
+ kwd-start 'move t)
;; Can't parse a declaration preamble and is still
;; before `kwd-start'. That means `first-specifier-pos'
;; was in some earlier construct. Search again.
- (if (c-syntactic-re-search-forward c-symbol-start
- kwd-start 'move t)
- (goto-char (setq first-specifier-pos (match-beginning 0)))
+ (goto-char (setq first-specifier-pos (match-beginning 0))))
+ (t
;; Got no preamble before the block declaration keyword.
(setq first-specifier-pos kwd-start))))
@@ -13003,7 +13021,7 @@ comment at the start of cc-engine.el for more info."
(defun c-laomib-get-cache (containing-sexp start)
;; Get an element from `c-laomib-cache' matching CONTAINING-SEXP, and which
- ;; is suitable for start postiion START.
+ ;; is suitable for start position START.
;; Return that element or nil if one wasn't found.
(let ((ptr c-laomib-cache)
elt)
@@ -14166,7 +14184,8 @@ comment at the start of cc-engine.el for more info."
(defun c-add-class-syntax (symbol
containing-decl-open
containing-decl-start
- containing-decl-kwd)
+ containing-decl-kwd
+ &rest args)
;; The inclass and class-close syntactic symbols are added in
;; several places and some work is needed to fix everything.
;; Therefore it's collected here.
@@ -14181,7 +14200,7 @@ comment at the start of cc-engine.el for more info."
;; Ought to use `c-add-stmt-syntax' instead of backing up to boi
;; here, but we have to do like this for compatibility.
(back-to-indentation)
- (c-add-syntax symbol (point))
+ (apply #'c-add-syntax symbol (point) args)
(if (and (c-keyword-member containing-decl-kwd
'c-inexpr-class-kwds)
(/= containing-decl-start (c-point 'boi containing-decl-start)))
@@ -14215,9 +14234,10 @@ comment at the start of cc-engine.el for more info."
;; CASE B.1: class-open
((save-excursion
(and (eq (char-after) ?{)
- (c-looking-at-decl-block t)
+ (setq placeholder (c-looking-at-decl-block t))
(setq beg-of-same-or-containing-stmt (point))))
- (c-add-syntax 'class-open beg-of-same-or-containing-stmt))
+ (c-add-syntax 'class-open beg-of-same-or-containing-stmt
+ (c-point 'boi placeholder)))
;; CASE B.2: brace-list-open
((or (consp special-brace-list)
@@ -14712,7 +14732,10 @@ comment at the start of cc-engine.el for more info."
'lambda-intro-cont)))
(goto-char (cdr placeholder))
(back-to-indentation)
- (c-add-stmt-syntax tmpsymbol nil t
+ (c-add-stmt-syntax tmpsymbol
+ (and (eq tmpsymbol 'class-open)
+ (list (point)))
+ t
(c-most-enclosing-brace state-cache (point))
paren-state)
(unless (eq (point) (cdr placeholder))
@@ -14755,9 +14778,10 @@ comment at the start of cc-engine.el for more info."
(goto-char indent-point)
(skip-chars-forward " \t")
(and (eq (char-after) ?{)
- (c-looking-at-decl-block t)
+ (setq tmp-pos (c-looking-at-decl-block t))
(setq placeholder (point))))
- (c-add-syntax 'class-open placeholder))
+ (c-add-syntax 'class-open placeholder
+ (c-point 'boi tmp-pos)))
;; CASE 5A.3: brace list open
((save-excursion
@@ -15155,10 +15179,14 @@ comment at the start of cc-engine.el for more info."
((and containing-sexp
(eq char-after-ip ?})
(eq containing-decl-open containing-sexp))
+ (save-excursion
+ (goto-char containing-decl-open)
+ (setq tmp-pos (c-looking-at-decl-block t)))
(c-add-class-syntax 'class-close
containing-decl-open
containing-decl-start
- containing-decl-kwd))
+ containing-decl-kwd
+ (c-point 'boi tmp-pos)))
;; CASE 5H: we could be looking at subsequent knr-argdecls
((and c-recognize-knr-p
diff --git a/lisp/progmodes/cc-fonts.el b/lisp/progmodes/cc-fonts.el
index 6e5ee28c4ec..89f197b98e6 100644
--- a/lisp/progmodes/cc-fonts.el
+++ b/lisp/progmodes/cc-fonts.el
@@ -1,6 +1,6 @@
;; cc-fonts.el --- font lock support for CC Mode -*- lexical-binding: t -*-
-;; Copyright (C) 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2024 Free Software Foundation, Inc.
;; Authors: 2003- Alan Mackenzie
;; 2002- Martin Stjernholm
diff --git a/lisp/progmodes/cc-guess.el b/lisp/progmodes/cc-guess.el
index 797e0a1939b..f7fe5feeca6 100644
--- a/lisp/progmodes/cc-guess.el
+++ b/lisp/progmodes/cc-guess.el
@@ -1,6 +1,6 @@
;;; cc-guess.el --- guess indentation values by scanning existing code -*- lexical-binding: t -*-
-;; Copyright (C) 1985, 1987, 1992-2006, 2011-2023 Free Software
+;; Copyright (C) 1985, 1987, 1992-2006, 2011-2024 Free Software
;; Foundation, Inc.
;; Author: 1994-1995 Barry A. Warsaw
diff --git a/lisp/progmodes/cc-langs.el b/lisp/progmodes/cc-langs.el
index ef7f27dc435..ad21bd1d5ef 100644
--- a/lisp/progmodes/cc-langs.el
+++ b/lisp/progmodes/cc-langs.el
@@ -1,6 +1,6 @@
;;; cc-langs.el --- language specific settings for CC Mode -*- lexical-binding: t; coding: utf-8 -*-
-;; Copyright (C) 1985, 1987, 1992-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1985, 1987, 1992-2024 Free Software Foundation, Inc.
;; Authors: 2002- Alan Mackenzie
;; 1998- Martin Stjernholm
diff --git a/lisp/progmodes/cc-menus.el b/lisp/progmodes/cc-menus.el
index 8d9864c4f6d..25b3c89f73b 100644
--- a/lisp/progmodes/cc-menus.el
+++ b/lisp/progmodes/cc-menus.el
@@ -1,6 +1,6 @@
;;; cc-menus.el --- imenu support for CC Mode -*- lexical-binding: t -*-
-;; Copyright (C) 1985, 1987, 1992-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1985, 1987, 1992-2024 Free Software Foundation, Inc.
;; Authors: 1998- Martin Stjernholm
;; 1992-1999 Barry A. Warsaw
diff --git a/lisp/progmodes/cc-mode.el b/lisp/progmodes/cc-mode.el
index 1dbe91b5633..64a679eacc7 100644
--- a/lisp/progmodes/cc-mode.el
+++ b/lisp/progmodes/cc-mode.el
@@ -1,6 +1,6 @@
;;; cc-mode.el --- major mode for editing C and similar languages -*- lexical-binding: t -*-
-;; Copyright (C) 1985, 1987, 1992-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1985, 1987, 1992-2024 Free Software Foundation, Inc.
;; Authors: 2003- Alan Mackenzie
;; 1998- Martin Stjernholm
@@ -256,8 +256,11 @@ control). See \"cc-mode.el\" for more info."
(put 'c-initialize-cc-mode initprop c-initialization-ok))))
;; Set up text conversion, for Emacs >= 30.0
+ ;; This is needed here because CC-mode's implementation of
+ ;; electricity does not rely on `post-self-insert-hook' (which is
+ ;; already handled adequately by `analyze-text-conversion').
(when (boundp 'post-text-conversion-hook)
- (add-hook 'post-text-conversion-hook #'c-post-text-conversion))
+ (add-hook 'post-text-conversion-hook #'c-post-text-conversion nil t))
(unless new-style-init
(c-init-language-vars-for 'c-mode)))
@@ -1279,7 +1282,9 @@ Note that the style variables are always made local to the buffer."
;; VALUE (which should not be nil).
;; `(let ((-pos- ,pos)
;; (-value- ,value))
- (c-put-char-property pos 'syntax-table value)
+ (if (equal value '(15))
+ (c-put-string-fence pos)
+ (c-put-char-property pos 'syntax-table value))
(c-put-char-property pos 'c-fl-syn-tab value)
(cond
((null c-min-syn-tab-mkr)
@@ -1372,8 +1377,14 @@ Note that the style variables are always made local to the buffer."
(not (nth 3 s))
(c-get-char-property (1- (point)) 'c-fl-syn-tab))
(c-put-char-property pos 'syntax-table '(1))
- (c-put-char-properties (1+ pos) (c-point 'eol pos)
- 'syntax-table '(1)))
+ ;; Remove syntax-table text properties from template
+ ;; delimiters.
+ (c-clear-char-property-with-value
+ (1+ pos) (c-point 'eol pos)
+ 'syntax-table c-<-as-paren-syntax)
+ (c-clear-char-property-with-value
+ (1+ pos) (c-point 'eol pos)
+ 'syntax-table c->-as-paren-syntax))
(setq pos (point)))
(setq pos (1+ pos)))))))))
diff --git a/lisp/progmodes/cc-styles.el b/lisp/progmodes/cc-styles.el
index e412a52cfb8..ff6371d9368 100644
--- a/lisp/progmodes/cc-styles.el
+++ b/lisp/progmodes/cc-styles.el
@@ -1,6 +1,6 @@
;;; cc-styles.el --- support for styles in CC Mode -*- lexical-binding: t -*-
-;; Copyright (C) 1985, 1987, 1992-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1985, 1987, 1992-2024 Free Software Foundation, Inc.
;; Authors: 2004- Alan Mackenzie
;; 1998- Martin Stjernholm
diff --git a/lisp/progmodes/cc-vars.el b/lisp/progmodes/cc-vars.el
index c7b66f040cd..3845c2d55f0 100644
--- a/lisp/progmodes/cc-vars.el
+++ b/lisp/progmodes/cc-vars.el
@@ -1,6 +1,6 @@
;;; cc-vars.el --- user customization variables for CC Mode -*- lexical-binding: t -*-
-;; Copyright (C) 1985, 1987, 1992-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1985, 1987, 1992-2024 Free Software Foundation, Inc.
;; Authors: 2002- Alan Mackenzie
;; 1998- Martin Stjernholm
diff --git a/lisp/progmodes/cfengine.el b/lisp/progmodes/cfengine.el
index 639c1fe7947..2b40fac752f 100644
--- a/lisp/progmodes/cfengine.el
+++ b/lisp/progmodes/cfengine.el
@@ -1,6 +1,6 @@
;;; cfengine.el --- mode for editing Cfengine files -*- lexical-binding: t; -*-
-;; Copyright (C) 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2024 Free Software Foundation, Inc.
;; Author: Dave Love <fx@gnu.org>
;; Maintainer: Ted Zlatanov <tzz@lifelogs.com>
diff --git a/lisp/progmodes/cl-font-lock.el b/lisp/progmodes/cl-font-lock.el
index 5febf7ff15f..f6d4cde3fec 100644
--- a/lisp/progmodes/cl-font-lock.el
+++ b/lisp/progmodes/cl-font-lock.el
@@ -1,12 +1,12 @@
;;; cl-font-lock.el --- Pretty Common Lisp font locking -*- lexical-binding: t; -*-
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
;; Author: Yue Daian <sheepduke@gmail.com>
;; Maintainer: Spenser Truex <web@spensertruex.com>
;; Created: 2019-06-16
;; Old-Version: 0.3.0
;; Package-Requires: ((emacs "24.5"))
-;; Keywords: lisp wp files convenience
+;; Keywords: lisp text files convenience
;; URL: https://github.com/cl-font-lock/cl-font-lock
;; This file is part of GNU Emacs
diff --git a/lisp/progmodes/cmacexp.el b/lisp/progmodes/cmacexp.el
index 110726fa362..062f2d0b4e2 100644
--- a/lisp/progmodes/cmacexp.el
+++ b/lisp/progmodes/cmacexp.el
@@ -1,6 +1,6 @@
;;; cmacexp.el --- expand C macros in a region -*- lexical-binding: t -*-
-;; Copyright (C) 1992-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1992-2024 Free Software Foundation, Inc.
;; Author: Francesco Potortì <pot@gnu.org>
;; Adapted-By: ESR
diff --git a/lisp/progmodes/cmake-ts-mode.el b/lisp/progmodes/cmake-ts-mode.el
index 53d471c381a..d933e4ebb81 100644
--- a/lisp/progmodes/cmake-ts-mode.el
+++ b/lisp/progmodes/cmake-ts-mode.el
@@ -1,6 +1,6 @@
;;; cmake-ts-mode.el --- tree-sitter support for CMake -*- lexical-binding: t; -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;; Author : Randy Taylor <dev@rjt.dev>
;; Maintainer : Randy Taylor <dev@rjt.dev>
@@ -63,7 +63,15 @@
((parent-is "foreach_loop") parent-bol cmake-ts-mode-indent-offset)
((parent-is "function_def") parent-bol cmake-ts-mode-indent-offset)
((parent-is "if_condition") parent-bol cmake-ts-mode-indent-offset)
- ((parent-is "normal_command") parent-bol cmake-ts-mode-indent-offset)))
+ ((parent-is "normal_command") parent-bol cmake-ts-mode-indent-offset)
+ ;;; Release v0.4.0 wraps arguments in an argument_list node.
+ ,@(ignore-errors
+ (treesit-query-capture 'cmake '((argument_list) @capture))
+ `(((parent-is "argument_list") grand-parent cmake-ts-mode-indent-offset)))
+ ;;; Release v0.3.0 wraps the body of commands into a body node.
+ ,@(ignore-errors
+ (treesit-query-capture 'cmake '((body) @capture))
+ `(((parent-is "body") grand-parent cmake-ts-mode-indent-offset)))))
"Tree-sitter indent rules for `cmake-ts-mode'.")
(defvar cmake-ts-mode--constants
@@ -89,8 +97,8 @@
"CMake if conditions for tree-sitter font-locking.")
(defun cmake-ts-mode--font-lock-compatibility-fe9b5e0 ()
- "Indent rules helper, to handle different releases of tree-sitter-cmake.
-Check if a node type is available, then return the right indent rules."
+ "Font lock helper, to handle different releases of tree-sitter-cmake.
+Check if a node type is available, then return the right font lock rules."
;; handle commit fe9b5e0
(condition-case nil
(progn (treesit-query-capture 'cmake '((argument_list) @capture))
diff --git a/lisp/progmodes/compile.el b/lisp/progmodes/compile.el
index f85cc0909dd..4af6a96900a 100644
--- a/lisp/progmodes/compile.el
+++ b/lisp/progmodes/compile.el
@@ -1,6 +1,6 @@
;;; compile.el --- run compiler as inferior of Emacs, parse error messages -*- lexical-binding:t -*-
-;; Copyright (C) 1985-1987, 1993-1999, 2001-2023 Free Software
+;; Copyright (C) 1985-1987, 1993-1999, 2001-2024 Free Software
;; Foundation, Inc.
;; Authors: Roland McGrath <roland@gnu.org>,
@@ -683,7 +683,10 @@ File = \\(.+\\), Line = \\([0-9]+\\)\\(?:, Column = \\([0-9]+\\)\\)?"
"Alist of values for `compilation-error-regexp-alist'.")
(defcustom compilation-error-regexp-alist
- (mapcar #'car compilation-error-regexp-alist-alist)
+ ;; Omit `omake' by default: its mere presence here triggers special processing
+ ;; and modifies regexps for other rules (see `compilation-parse-errors'),
+ ;; which may slow down matching (or even cause mismatches).
+ (delq 'omake (mapcar #'car compilation-error-regexp-alist-alist))
"Alist that specifies how to match errors in compiler output.
On GNU and Unix, any string is a valid filename, so these
matchers must make some common sense assumptions, which catch
@@ -1786,7 +1789,7 @@ to a function that generates a unique name."
;; run compile with the default command line
(defun recompile (&optional edit-command)
"Re-compile the program including the current buffer.
-If this is run in a Compilation mode buffer, re-use the arguments from the
+If this is run in a Compilation mode buffer, reuse the arguments from the
original use. Otherwise, recompile using `compile-command'.
If the optional argument `edit-command' is non-nil, the command can be edited."
(interactive "P")
@@ -2721,7 +2724,7 @@ looking for the next message."
(compilation-loop > compilation-next-single-property-change 1-
(if (get-buffer-process (current-buffer))
"No more %ss yet"
- "Moved past last %s")
+ "Past last %s")
(point-max))
;; Don't move "back" to message at or before point.
;; Pass an explicit (point-min) to make sure pt is non-nil.
diff --git a/lisp/progmodes/cperl-mode.el b/lisp/progmodes/cperl-mode.el
index 75ea81d55a4..9f7f29b8182 100644
--- a/lisp/progmodes/cperl-mode.el
+++ b/lisp/progmodes/cperl-mode.el
@@ -1,6 +1,6 @@
;;; cperl-mode.el --- Perl code editing commands for Emacs -*- lexical-binding:t -*-
-;; Copyright (C) 1985-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1985-2024 Free Software Foundation, Inc.
;; Author: Ilya Zakharevich <ilyaz@cpan.org>
;; Bob Olson
@@ -79,6 +79,9 @@
(eval-when-compile (require 'cl-lib))
(require 'facemenu)
+(defvar Man-switches)
+(defvar manual-program)
+(defvar imenu-max-items)
(defvar msb-menu-cond)
(defvar gud-perldb-history)
(defvar vc-rcs-header)
@@ -101,7 +104,10 @@
:version "20.3")
(defgroup cperl-indentation-details nil
- "Indentation."
+ "Indentation.
+The option `cperl-file-style' (which see) can be used to set
+several indentation options in one go, following popular
+indentation styles."
:prefix "cperl-"
:group 'cperl)
@@ -154,6 +160,26 @@ for constructs with multiline if/unless/while/until/for/foreach condition."
:type 'boolean
:group 'cperl-autoinsert-details)
+(defcustom cperl-file-style nil
+ "Indentation style to use in cperl-mode.
+\"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
+in perlstyle. The other styles have been developed for other
+programming languages, mostly C."
+ :type '(choice (const "PBP")
+ (const "CPerl")
+ (const "PerlStyle")
+ (const "GNU")
+ (const "C++")
+ (const "K&R")
+ (const "BSD")
+ (const "Whitesmith")
+ (const :tag "Default" nil))
+ :group 'cperl-indentation-details
+ :version "29.1")
+;;;###autoload(put 'cperl-file-style 'safe-local-variable 'stringp)
+
(defcustom cperl-indent-level 2
"Indentation of CPerl statements with respect to containing block."
:type 'integer
@@ -333,17 +359,7 @@ Affects: `cperl-font-lock', `cperl-electric-lbrace-space',
(defcustom cperl-vc-rcs-header '("($rcs) = (' $Id\ $ ' =~ /(\\d+(\\.\\d+)+)/);")
"Special version of `vc-rcs-header' that is used in CPerl mode buffers."
:type '(repeat string)
- :group 'cperl)
-
-;; (defcustom cperl-clobber-mode-lists
-;; (not
-;; (and
-;; (boundp 'interpreter-mode-alist)
-;; (assoc "miniperl" interpreter-mode-alist)
-;; (assoc "\\.\\([pP][Llm]\\|al\\)$" auto-mode-alist)))
-;; "Whether to install us into `interpreter-' and `extension' mode lists."
-;; :type 'boolean
-;; :group 'cperl)
+ :group 'cperl)
(defcustom cperl-info-on-command-no-prompt nil
"Not-nil (and non-null) means not to prompt on \\[cperl-info-on-command].
@@ -386,6 +402,8 @@ Font for POD headers."
:type 'face
:version "21.1"
:group 'cperl-faces)
+(make-obsolete-variable 'cperl-invalid-face
+ 'show-trailing-whitespace "30.1")
(defcustom cperl-pod-here-fontify t
"Not-nil after evaluation means to highlight POD and here-docs sections."
@@ -440,6 +458,11 @@ after reload."
Older version of this page was called `perl5', newer `perl'."
:type 'string
:group 'cperl-help-system)
+(make-obsolete-variable 'cperl-info-page
+ (concat "The Perl info page is no longer maintained. "
+ "Consider installing the perl-doc package from "
+ "GNU ELPA to access Perl documentation.")
+ "30.1")
(defcustom cperl-use-syntax-table-text-property t
"Non-nil means CPerl sets up and uses `syntax-table' text property."
@@ -480,12 +503,6 @@ If nil, the value of `cperl-indent-level' will be used."
:group 'cperl)
(make-obsolete-variable 'cperl-under-as-char 'superword-mode "24.4")
-(defcustom cperl-extra-perl-args ""
- "Extra arguments to use when starting Perl.
-Currently used with `cperl-check-syntax' only."
- :type 'string
- :group 'cperl)
-
(defcustom cperl-message-electric-keyword t
"Non-nil means that the `cperl-electric-keyword' prints a help message."
:type 'boolean
@@ -543,19 +560,17 @@ This way enabling/disabling of menu items is more correct."
:type 'boolean
:group 'cperl-speed)
-(defcustom cperl-file-style nil
- "Indentation style to use in cperl-mode."
- :type '(choice (const "CPerl")
- (const "PBP")
- (const "PerlStyle")
- (const "GNU")
- (const "C++")
- (const "K&R")
- (const "BSD")
- (const "Whitesmith")
- (const :tag "Default" nil))
- :version "29.1")
-;;;###autoload(put 'cperl-file-style 'safe-local-variable 'stringp)
+(defcustom cperl-fontify-trailer
+ 'perl-code
+ "How to fontify text after an \"__END__\" or \"__DATA__\" token.
+If \"perl-code\", treat as Perl code for fontification, and
+examine for imenu entries. Use this setting if you have trailing
+POD documentation, or for modules which use AutoLoad or
+AutoSplit. If \"comment\", treat as comment, and do not look for
+imenu entries."
+ :type '(choice (const perl-code)
+ (const comment))
+ :group 'cperl-faces)
(defcustom cperl-ps-print-face-properties
'((font-lock-keyword-face nil nil bold shadow)
@@ -626,22 +641,14 @@ This way enabling/disabling of menu items is more correct."
;;; Short extra-docs.
(defvar cperl-tips 'please-ignore-this-line
- "Note that to enable Compile choices in the menu you need to install
-mode-compile.el.
-
-If your Emacs does not default to `cperl-mode' on Perl files, and you
+ "If your Emacs does not default to `cperl-mode' on Perl files, and you
want it to: put the following into your .emacs file:
(add-to-list \\='major-mode-remap-alist \\='(perl-mode . cperl-mode))
-Get perl5-info from
- $CPAN/doc/manual/info/perl5-old/perl5-info.tar.gz
-Also, one can generate a newer documentation running `pod2texi' converter
- $CPAN/doc/manual/info/perl5/pod2texi-0.1.tar.gz
-
-If you use imenu-go, run imenu on perl5-info buffer (you can do it
-from Perl menu). If many files are related, generate TAGS files from
-Tools/Tags submenu in Perl menu.
+To read Perl documentation in info format you can convert POD to
+texinfo with the converter `pod2texi' from the texinfo project:
+ https://www.gnu.org/software/texinfo/manual/pod2texi.html
If some class structure is too complicated, use Tools/Hierarchy-view
from Perl menu, or hierarchic view of imenu. The second one uses the
@@ -708,45 +715,42 @@ voice);
3) Separate list of packages/classes;
4) Hierarchical view of methods in (sub)packages;
5) and functions (by the full name - with package);
- e) Has an interface to INFO docs for Perl; The interface is
- very flexible, including shrink-wrapping of
- documentation buffer/frame;
- f) Has a builtin list of one-line explanations for perl constructs.
- g) Can show these explanations if you stay long enough at the
+ e) Has a builtin list of one-line explanations for perl constructs.
+ f) Can show these explanations if you stay long enough at the
corresponding place (or on demand);
- h) Has an enhanced fontification (using 3 or 4 additional faces
+ g) Has an enhanced fontification (using 3 or 4 additional faces
comparing to font-lock - basically, different
namespaces in Perl have different colors);
- i) Can construct TAGS basing on its knowledge of Perl syntax,
+ h) Can construct TAGS basing on its knowledge of Perl syntax,
the standard menu has 6 different way to generate
TAGS (if \"by directory\", .xs files - with C-language
bindings - are included in the scan);
- j) Can build a hierarchical view of classes (via imenu) basing
+ i) Can build a hierarchical view of classes (via imenu) basing
on generated TAGS file;
- k) Has electric parentheses, electric newlines, uses Abbrev
+ j) Has electric parentheses, electric newlines, uses Abbrev
for electric logical constructs
while () {}
with different styles of expansion (context sensitive
to be not so bothering). Electric parentheses behave
\"as they should\" in a presence of a visible region.
- l) Changes msb.el \"on the fly\" to insert a group \"Perl files\";
- m) Can convert from
+ k) Changes msb.el \"on the fly\" to insert a group \"Perl files\";
+ l) Can convert from
if (A) { B }
to
B if A;
- n) Highlights (by user-choice) either 3-delimiters constructs
+ m) Highlights (by user-choice) either 3-delimiters constructs
(such as tr/a/b/), or regular expressions and `y/tr';
- o) Highlights trailing whitespace;
- p) Is able to manipulate Perl Regular Expressions to ease
+ o) Is able to manipulate Perl Regular Expressions to ease
conversion to a more readable form.
- q) Can ispell POD sections and HERE-DOCs.
- r) Understands comments and character classes inside regular
+ p) Can ispell POD sections and HERE-DOCs.
+ q) Understands comments and character classes inside regular
expressions; can find matching () and [] in a regular expression.
- s) Allows indentation of //x-style regular expressions;
- t) Highlights different symbols in regular expressions according
+ r) Allows indentation of //x-style regular expressions;
+ s) Highlights different symbols in regular expressions according
to their function; much less problems with backslashitis;
- u) Allows to find regular expressions which contain interpolated parts.
+ t) Allows you to locate regular expressions which contain
+ interpolated parts.
5) The indentation engine was very smart, but most of tricks may be
not needed anymore with the support for `syntax-table' property. Has
@@ -834,7 +838,6 @@ B) Speed of editing operations.
`font-lock-type-face' Overridable keywords
`font-lock-variable-name-face' Variable declarations, indirect array and
hash names, POD headers/item names
- `cperl-invalid-face' Trailing whitespace
Note that in several situations the highlighting tries to inform about
possible confusion, such as different colors for function names in
@@ -911,17 +914,6 @@ Unless KEEP, removes the old indentation."
(delete-horizontal-space))
(indent-to column minimum))
-;; Probably it is too late to set these guys already, but it can help later:
-
-;;(and cperl-clobber-mode-lists
-;;(setq auto-mode-alist
-;; (append '(("\\.\\([pP][Llm]\\|al\\)$" . perl-mode)) auto-mode-alist ))
-;;(and (boundp 'interpreter-mode-alist)
-;; (setq interpreter-mode-alist (append interpreter-mode-alist
-;; '(("miniperl" . perl-mode))))))
-(eval-when-compile
- (mapc #'require '(imenu easymenu etags timer man info)))
-
(define-abbrev-table 'cperl-mode-electric-keywords-abbrev-table
(mapcar (lambda (x)
(let ((name (car x))
@@ -992,12 +984,12 @@ Unless KEEP, removes the old indentation."
(define-key map "\177" 'cperl-electric-backspace)
(define-key map "\t" 'cperl-indent-command)
;; don't clobber the backspace binding:
- (define-key map [(control ?c) (control ?h) ?F] 'cperl-info-on-command)
+ (define-key map [(control ?c) (control ?h) ?F] 'cperl-perldoc)
(if (cperl-val 'cperl-clobber-lisp-bindings)
(progn
(define-key map [(control ?h) ?f]
;;(concat (char-to-string help-char) "f") ; does not work
- 'cperl-info-on-command)
+ 'cperl-perldoc)
(define-key map [(control ?h) ?v]
;;(concat (char-to-string help-char) "v") ; does not work
'cperl-get-help)
@@ -1008,7 +1000,7 @@ Unless KEEP, removes the old indentation."
;;(concat (char-to-string help-char) "v") ; does not work
(key-binding "\C-hv")))
(define-key map [(control ?c) (control ?h) ?f]
- 'cperl-info-on-current-command)
+ 'cperl-perldoc)
(define-key map [(control ?c) (control ?h) ?v]
;;(concat (char-to-string help-char) "v") ; does not work
'cperl-get-help))
@@ -1061,17 +1053,10 @@ Unless KEEP, removes the old indentation."
["Comment region" cperl-comment-region (use-region-p)]
["Uncomment region" cperl-uncomment-region (use-region-p)]
"----"
- ["Run" mode-compile (fboundp 'mode-compile)]
- ["Kill" mode-compile-kill (and (fboundp 'mode-compile-kill)
- (get-buffer "*compilation*"))]
- ["Next error" next-error (get-buffer "*compilation*")]
- ["Check syntax" cperl-check-syntax (fboundp 'mode-compile)]
- "----"
["Debugger" cperl-db t]
"----"
("Tools"
["Imenu" imenu]
- ["Imenu on Perl Info" cperl-imenu-on-info (featurep 'imenu)]
"----"
["Ispell PODs" cperl-pod-spell
;; Better not to update syntaxification here:
@@ -1130,8 +1115,6 @@ Unless KEEP, removes the old indentation."
;; This is from imenu-go.el. I can't find it on any ELPA
;; archive, so I'm not sure if it's still in use or not.
(fboundp 'imenu-go-find-at-position)]
- ["Help on function" cperl-info-on-command t]
- ["Help on function at point" cperl-info-on-current-command t]
["Help on symbol at point" cperl-get-help t]
["Perldoc" cperl-perldoc t]
["Perldoc on word at point" cperl-perldoc-at-point t]
@@ -1489,7 +1472,7 @@ function tests that property."
(defun cperl-block-declaration-p ()
"Test whether the following ?\\{ opens a declaration block.
-Returns the column where the declarating keyword is found, or nil
+Returns the column where the declaring keyword is found, or nil
if this isn't a declaration block. Declaration blocks are named
subroutines, packages and the like. They start with a keyword
and a name, to be followed by various descriptive items which are
@@ -1722,30 +1705,21 @@ into
\\{cperl-mode-map}
-Setting the variable `cperl-font-lock' to t switches on `font-lock-mode'
-\(even with older Emacsen), `cperl-electric-lbrace-space' to t switches
-on electric space between $ and {, `cperl-electric-parens-string' is
-the string that contains parentheses that should be electric in CPerl
-\(see also `cperl-electric-parens-mark' and `cperl-electric-parens'),
-setting `cperl-electric-keywords' enables electric expansion of
-control structures in CPerl. `cperl-electric-linefeed' governs which
-one of two linefeed behavior is preferable. You can enable all these
-options simultaneously (recommended mode of use) by setting
-`cperl-hairy' to t. In this case you can switch separate options off
-by setting them to `null'. Note that one may undo the extra
-whitespace inserted by semis and braces in `auto-newline'-mode by
-consequent \\[cperl-electric-backspace].
-
-If your site has perl5 documentation in info format, you can use commands
-\\[cperl-info-on-current-command] and \\[cperl-info-on-command] to access it.
-These keys run commands `cperl-info-on-current-command' and
-`cperl-info-on-command', which one is which is controlled by variable
-`cperl-info-on-command-no-prompt' and `cperl-clobber-lisp-bindings'
-\(in turn affected by `cperl-hairy').
-
-Even if you have no info-format documentation, short one-liner-style
-help is available on \\[cperl-get-help], and one can run perldoc or
-man via menu.
+Setting the variable `cperl-font-lock' to t switches on `font-lock-mode',
+`cperl-electric-lbrace-space' to t switches on electric space between $
+and {, `cperl-electric-parens-string' is the string that contains
+parentheses that should be electric in CPerl (see also
+`cperl-electric-parens-mark' and `cperl-electric-parens'), setting
+`cperl-electric-keywords' enables electric expansion of control
+structures in CPerl. `cperl-electric-linefeed' governs which one of two
+linefeed behavior is preferable. You can enable all these options
+simultaneously by setting `cperl-hairy' to t. In this case you can
+switch separate options off by setting them to `null'. Note that one may
+undo the extra whitespace inserted by semis and braces in
+`auto-newline'-mode by consequent \\[cperl-electric-backspace].
+
+Short one-liner-style help is available on \\[cperl-get-help],
+and one can run perldoc or man via menu.
It is possible to show this help automatically after some idle time.
This is regulated by variable `cperl-lazy-help-time'. Default with
@@ -1837,8 +1811,8 @@ or as help on variables `cperl-tips', `cperl-problems',
(cperl-val 'cperl-info-on-command-no-prompt))
(progn
;; don't clobber the backspace binding:
- (define-key cperl-mode-map "\C-hf" 'cperl-info-on-current-command)
- (define-key cperl-mode-map "\C-c\C-hf" 'cperl-info-on-command)))
+ (define-key cperl-mode-map "\C-hf" 'cperl-perldoc)
+ (define-key cperl-mode-map "\C-c\C-hf" 'cperl-perldoc)))
(setq local-abbrev-table cperl-mode-abbrev-table)
(if (cperl-val 'cperl-electric-keywords)
(abbrev-mode 1))
@@ -2744,7 +2718,7 @@ PRESTART is the position basing on which START was found."
(defun cperl-beginning-of-property (p prop &optional lim)
"Given that P has a property PROP, find where the property starts.
Will not look before LIM."
-;;; XXXX What to do at point-max???
+;; XXXX What to do at point-max???
(or (previous-single-property-change (cperl-1+ p) prop lim)
(point-min))
;; (cond ((eq p (point-min))
@@ -2858,6 +2832,7 @@ Will not look before LIM."
;; in which case this line is the first argument decl.
(skip-chars-forward " \t")
(cperl-backward-to-noncomment (or old-indent (point-min)))
+ ;; Determine whether point is between statements
(setq state
(or (bobp)
(eq (point) old-indent) ; old-indent was at comment
@@ -2876,7 +2851,8 @@ Will not look before LIM."
(looking-at
(rx (sequence (0+ blank)
(eval cperl--label-rx))))))
- (get-text-property (point) 'first-format-line)))
+ (get-text-property (1- (point)) 'first-format-line)
+ (equal (get-text-property (point) 'syntax-type) 'format)))
;; Look at previous line that's at column 0
;; to determine whether we are in top-level decls
@@ -3093,7 +3069,7 @@ and closing parentheses and brackets."
(error nil))
(current-column))
((eq 'indentable (elt i 0)) ; Indenter for REGEXP qw() etc
- (cond ;;; [indentable terminator start-pos is-block]
+ (cond ; [indentable terminator start-pos is-block]
((eq 'terminator (elt i 1)) ; Lone terminator of "indentable string"
(goto-char (elt i 2)) ; After opening parens
(1- (current-column)))
@@ -3978,10 +3954,8 @@ recursive calls in starting lines of here-documents."
"\\([^\"'`\n]*\\)" ; 4 + 1
"\\4"
"\\|"
- ;; Second variant: Identifier or \ID (same as 'ID') or empty
- "\\\\?\\(\\([a-zA-Z_][a-zA-Z_0-9]*\\)?\\)" ; 5 + 1, 6 + 1
- ;; Do not have <<= or << 30 or <<30 or << $blah.
- ;; "\\([^= \t0-9$@%&]\\|[ \t]+[^ \t\n0-9$@%&]\\)" ; 6 + 1
+ ;; Second variant: Identifier or \ID (same as 'ID')
+ "\\\\?\\(\\([a-zA-Z_][a-zA-Z_0-9]*\\)\\)" ; 5 + 1, 6 + 1
"\\)"
"\\|"
;; -------- format capture groups 8-9
@@ -4169,20 +4143,10 @@ recursive calls in starting lines of here-documents."
;; Here document
;; We can do many here-per-line;
;; but multiline quote on the same line as <<HERE confuses us...
- ;; ;; One extra () before this:
- ;;"<<"
+ ;; One extra () before this:
;; "<<\\(~?\\)" ; HERE-DOC, indented-p = capture 2
- ;; ;; First variant "BLAH" or just ``.
- ;; "[ \t]*" ; Yes, whitespace is allowed!
- ;; "\\([\"'`]\\)" ; 3 + 1
- ;; "\\([^\"'`\n]*\\)" ; 4 + 1
- ;; "\\4"
- ;; "\\|"
- ;; ;; Second variant: Identifier or \ID or empty
- ;; "\\\\?\\(\\([a-zA-Z_][a-zA-Z_0-9]*\\)?\\)" ; 5 + 1, 6 + 1
- ;; ;; Do not have <<= or << 30 or <<30 or << $blah.
- ;; ;; "\\([^= \t0-9$@%&]\\|[ \t]+[^ \t\n0-9$@%&]\\)" ; 6 + 1
- ;; "\\)"
+ ;; First variant "BLAH" or just ``: capture groups 4 and 5
+ ;; Second variant: Identifier or \ID: capture group 6 and 7
((match-beginning 3) ; 2 + 1: found "<<", detect its type
(let* ((matched-pos (match-beginning 0))
(quoted-delim-p (if (match-beginning 6) nil t))
@@ -4201,14 +4165,11 @@ recursive calls in starting lines of here-documents."
overshoot (nth 1 here-doc-results))
(and (nth 2 here-doc-results)
(setq warning-message (nth 2 here-doc-results)))))))
- ;; format
+ ;; format capture groups 8-9
((match-beginning 8)
- ;; 1+6=7 extra () before this:
- ;;"^[ \t]*\\(format\\)[ \t]*\\([a-zA-Z0-9_]+\\)?[ \t]*=[ \t]*$"
(setq b (point)
- name (if (match-beginning 8) ; 7 + 1
- (buffer-substring (match-beginning 8) ; 7 + 1
- (match-end 8)) ; 7 + 1
+ name (if (match-beginning 9) ; 7 + 2
+ (match-string-no-properties 9) ; 7 + 2
"")
tb (match-beginning 0))
(setq argument nil)
@@ -4241,10 +4202,10 @@ recursive calls in starting lines of here-documents."
(if (looking-at "^\\.$") ; ";" is not supported yet
(progn
;; Highlight the ending delimiter
- (cperl-postpone-fontification (point) (+ (point) 2)
+ (cperl-postpone-fontification (point) (+ (point) 1)
'face font-lock-string-face)
- (cperl-commentify (point) (+ (point) 2) nil)
- (cperl-put-do-not-fontify (point) (+ (point) 2) t))
+ (cperl-commentify (point) (+ (point) 1) nil)
+ (cperl-put-do-not-fontify (point) (+ (point) 1) t))
(setq warning-message
(format "End of format `%s' not found." name))
(or (car err-l) (setcar err-l b)))
@@ -4252,12 +4213,9 @@ recursive calls in starting lines of here-documents."
(if (> (point) max)
(setq tmpend tb))
(put-text-property b (point) 'syntax-type 'format))
- ;; qq-like String or Regexp:
+ ;; quotelike operator or regexp: capture groups 10 or 11
+ ;; matches some false positives, to be eliminated here
((or (match-beginning 10) (match-beginning 11))
- ;; 1+6+2=9 extra () before this:
- ;; "\\<\\(q[wxqr]?\\|[msy]\\|tr\\)\\>"
- ;; "\\|"
- ;; "\\([/<]\\)" ; /blah/ or <file*glob>
(setq b1 (if (match-beginning 10) 10 11)
argument (buffer-substring
(match-beginning b1) (match-end b1))
@@ -4314,13 +4272,23 @@ recursive calls in starting lines of here-documents."
(and (eq (char-syntax (preceding-char)) ?w)
(progn
(forward-sexp -1)
-;; After these keywords `/' starts a RE. One should add all the
-;; functions/builtins which expect an argument, but ...
+ ;; After these keywords `/'
+ ;; starts a RE. One should
+ ;; add all the
+ ;; functions/builtins which
+ ;; expect an argument, but
+ ;; ...
(and
(not (memq (preceding-char)
'(?$ ?@ ?& ?%)))
(looking-at
- "\\(while\\|if\\|unless\\|until\\|for\\(each\\)?\\|and\\|or\\|not\\|xor\\|split\\|grep\\|map\\|print\\|say\\|return\\)\\>"))))
+ (regexp-opt
+ '("while" "if" "unless"
+ "until" "for" "foreach"
+ "and" "or" "not"
+ "xor" "split" "grep" "map"
+ "print" "say" "return")
+ 'symbols)))))
(and (eq (preceding-char) ?.)
(eq (char-after (- (point) 2)) ?.))
(bobp))
@@ -4520,12 +4488,13 @@ recursive calls in starting lines of here-documents."
(1- e) e 'face my-cperl-delimiters-face)))
(if (and is-REx cperl-regexp-scan)
;; Process RExen: embedded comments, charclasses and ]
-;;;/\3333\xFg\x{FFF}a\ppp\PPP\qqq\C\99f(?{ foo })(??{ foo })/;
-;;;/a\.b[^a[:ff:]b]x$ab->$[|$,$ab->[cd]->[ef]|$ab[xy].|^${a,b}{c,d}/;
-;;;/(?<=foo)(?<!bar)(x)(?:$ab|\$\/)$|\\\b\x888\776\[\:$/xxx;
-;;;m?(\?\?{b,a})? + m/(??{aa})(?(?=xx)aa|bb)(?#aac)/;
-;;;m$(^ab[c]\$)$ + m+(^ab[c]\$\+)+ + m](^ab[c\]$|.+)] + m)(^ab[c]$|.+\));
-;;;m^a[\^b]c^ + m.a[^b]\.c.;
+ ;; Examples:
+ ;;/\3333\xFg\x{FFF}a\ppp\PPP\qqq\C\99f(?{ foo })(??{ foo })/;
+ ;;/a\.b[^a[:ff:]b]x$ab->$[|$,$ab->[cd]->[ef]|$ab[xy].|^${a,b}{c,d}/;
+ ;;/(?<=foo)(?<!bar)(x)(?:$ab|\$\/)$|\\\b\x888\776\[\:$/xxx;
+ ;;m?(\?\?{b,a})? + m/(??{aa})(?(?=xx)aa|bb)(?#aac)/;
+ ;;m$(^ab[c]\$)$ + m+(^ab[c]\$\+)+ + m](^ab[c\]$|.+)] + m)(^ab[c]$|.+\));
+ ;;m^a[\^b]c^ + m.a[^b]\.c.;
(save-excursion
(goto-char (1+ b))
;; First
@@ -4589,8 +4558,6 @@ recursive calls in starting lines of here-documents."
"\\?([0-9]+)" ; (?(1)foo|bar)
"\\|"
"\\?<[=!]"
- ;;;"\\|"
- ;;; "\\?"
"\\)?"
"\\)"
"\\|"
@@ -4735,8 +4702,8 @@ recursive calls in starting lines of here-documents."
(setq REx-subgr-end qtag) ;End smart-highlighted
;; Apparently, I can't put \] into a charclass
;; in m]]: m][\\\]\]] produces [\\]]
-;;; POSIX? [:word:] [:^word:] only inside []
-;;; "\\=\\(\\\\.\\|[^][\\]\\|\\[:\\^?\sw+:]\\|\\[[^:]\\)*]")
+ ;; POSIX? [:word:] [:^word:] only inside []
+ ;; "\\=\\(\\\\.\\|[^][\\]\\|\\[:\\^?\sw+:]\\|\\[[^:]\\)*]")
(while ; look for unescaped ]
(and argument
(re-search-forward
@@ -4924,14 +4891,14 @@ recursive calls in starting lines of here-documents."
;; "\\(\\<sub[ \t\n\f]+\\|[&*$@%]\\)[a-zA-Z0-9_]*'")
((match-beginning 19) ; old $abc'efg syntax
(setq bb (match-end 0))
- ;;;(if (nth 3 state) nil ; in string
(put-text-property (1- bb) bb 'syntax-table cperl-st-word)
(goto-char bb))
;; 1+6+2+1+1+6+1+1=19 extra () before this:
;; "__\\(END\\|DATA\\)__"
((match-beginning 20) ; __END__, __DATA__
- (setq bb (match-end 0))
- ;; (put-text-property b (1+ bb) 'syntax-type 'pod) ; Cheat
+ (if (eq cperl-fontify-trailer 'perl-code)
+ (setq bb (match-end 0))
+ (setq bb (point-max)))
(cperl-commentify b bb nil)
(setq end t))
;; "\\\\\\(['`\"($]\\)"
@@ -4940,7 +4907,7 @@ recursive calls in starting lines of here-documents."
(setq bb (match-end 0))
(goto-char b)
(skip-chars-backward "\\\\")
- ;;;(setq i2 (= (% (skip-chars-backward "\\\\") 2) -1))
+ ;; (setq i2 (= (% (skip-chars-backward "\\\\") 2) -1))
(cperl-modify-syntax-type b cperl-st-punct)
(goto-char bb))
(t (error "Error in regexp of the sniffer")))
@@ -5890,9 +5857,6 @@ functions (which they are not). Inherits from `default'.")
(setq
t-font-lock-keywords
(list
- ;; -------- trailing spaces -> use invalid-face as a warning
- ;; (matcher subexp facespec)
- `("[ \t]+$" 0 ',cperl-invalid-face t)
;; -------- function definition _and_ declaration
;; (matcher (subexp facespec))
;; facespec is evaluated depending on whether the
@@ -5921,7 +5885,7 @@ functions (which they are not). Inherits from `default'.")
(eval cperl--ws*-rx))
;; ... or the start of a "sloppy" signature
(sequence (eval cperl--sloppy-signature-rx)
- ;; arbtrarily continue "a few lines"
+ ;; arbitrarily continue "a few lines"
(repeat 0 200 (not (in "{"))))
;; make sure we have a reasonably
;; short match for an incomplete sub
@@ -6066,35 +6030,6 @@ functions (which they are not). Inherits from `default'.")
;; (matcher subexp facespec)
'("^[ \t]*format[ \t]+\\([a-zA-Z_][a-zA-Z_0-9:]*\\)[ \t]*=[ \t]*$"
1 font-lock-function-name-face)
- ;; -------- bareword hash key: $foo{bar}, $foo[1]{bar}
- ;; (matcher (subexp facespec) ...
- `(,(rx (or (in "]}\\%@>*&")
- (sequence "$" (eval cperl--normal-identifier-rx)))
- (0+ blank) "{" (0+ blank)
- (group-n 1 (sequence (opt "-")
- (eval cperl--basic-identifier-rx)))
- (0+ blank) "}")
-;; '("\\([]}\\%@>*&]\\|\\$[a-zA-Z0-9_:]*\\)[ \t]*{[ \t]*\\(-?[a-zA-Z0-9_:]+\\)[ \t]*}"
- (1 font-lock-string-face t)
- ;; -------- anchored bareword hash key: $foo{bar}{baz}
- ;; ... (anchored-matcher pre-form post-form subex-highlighters)
- (,(rx point
- (0+ blank) "{" (0+ blank)
- (group-n 1 (sequence (opt "-")
- (eval cperl--basic-identifier-rx)))
- (0+ blank) "}")
- ;; ("\\=[ \t]*{[ \t]*\\(-?[a-zA-Z0-9_:]+\\)[ \t]*}"
- nil nil
- (1 font-lock-string-face t)))
- ;; -------- hash element assignments with bareword key => value
- ;; (matcher subexp facespec)
- `(,(rx (in "[ \t{,()")
- (group-n 1 (sequence (opt "-")
- (eval cperl--basic-identifier-rx)))
- (0+ blank) "=>")
- 1 font-lock-string-face t)
- ;; '("[[ \t{,(]\\(-?[a-zA-Z0-9_:]+\\)[ \t]*=>" 1
- ;; font-lock-string-face t)
;; -------- labels
;; (matcher subexp facespec)
`(,(rx
@@ -6117,9 +6052,9 @@ functions (which they are not). Inherits from `default'.")
(group (eval cperl--basic-identifier-rx))))
1 font-lock-constant-face)
;; Uncomment to get perl-mode-like vars
- ;;; '("[$*]{?\\(\\sw+\\)" 1 font-lock-variable-name-face)
- ;;; '("\\([@%]\\|\\$#\\)\\(\\sw+\\)"
- ;;; (2 (cons font-lock-variable-name-face '(underline))))
+ ;; '("[$*]{?\\(\\sw+\\)" 1 font-lock-variable-name-face)
+ ;; '("\\([@%]\\|\\$#\\)\\(\\sw+\\)"
+ ;; (2 (cons font-lock-variable-name-face '(underline))))
;; 1=my_etc, 2=white? 3=(+white? 4=white? 5=var
;; -------- variable declarations
;; (matcher (subexp facespec) ...
@@ -6194,32 +6129,33 @@ functions (which they are not). Inherits from `default'.")
(setq
t-font-lock-keywords-1
`(
- ;; -------- arrays and hashes. Access to elements is fixed below
- ;; (matcher subexp facespec)
- ;; facespec is an expression to distinguish between arrays and hashes
- (,(rx (group-n 1 (group-n 2 (or (in "@%") "$#"))
- (eval cperl--normal-identifier-rx)))
- 1
-;; ("\\(\\([@%]\\|\\$#\\)[a-zA-Z_:][a-zA-Z0-9_:]*\\)" 1
- (if (eq (char-after (match-beginning 2)) ?%)
- 'cperl-hash-face
- 'cperl-array-face)
- nil)
- ;; -------- access to array/hash elements
- ;; (matcher subexp facespec)
- ;; facespec is an expression to distinguish between arrays and hashes
- (,(rx (group-n 1 (group-n 2 (in "$@%"))
- (eval cperl--normal-identifier-rx))
- (0+ blank)
- (group-n 3 (in "[{")))
-;; ("\\(\\([$@%]+\\)[a-zA-Z_:][a-zA-Z0-9_:]*\\)[ \t]*\\([[{]\\)"
- 1
- (if (= (- (match-end 2) (match-beginning 2)) 1)
- (if (eq (char-after (match-beginning 3)) ?{)
- 'cperl-hash-face
- 'cperl-array-face) ; arrays and hashes
- font-lock-variable-name-face) ; Just to put something
- t) ; override previous
+ ;; -------- bareword hash key: $foo{bar}, $foo[1]{bar}
+ ;; (matcher (subexp facespec) ...
+ (,(rx (or (in "]}\\%@>*&")
+ (sequence "$" (eval cperl--normal-identifier-rx)))
+ (0+ blank) "{" (0+ blank)
+ (group-n 1 (sequence (opt "-")
+ (eval cperl--basic-identifier-rx)))
+ (0+ blank) "}")
+;; '("\\([]}\\%@>*&]\\|\\$[a-zA-Z0-9_:]*\\)[ \t]*{[ \t]*\\(-?[a-zA-Z0-9_:]+\\)[ \t]*}"
+ (1 font-lock-string-face)
+ ;; -------- anchored bareword hash key: $foo{bar}{baz}
+ ;; ... (anchored-matcher pre-form post-form subex-highlighters)
+ (,(rx point
+ (0+ blank) "{" (0+ blank)
+ (group-n 1 (sequence (opt "-")
+ (eval cperl--basic-identifier-rx)))
+ (0+ blank) "}")
+ ;; ("\\=[ \t]*{[ \t]*\\(-?[a-zA-Z0-9_:]+\\)[ \t]*}"
+ nil nil
+ (1 font-lock-string-face)))
+ ;; -------- hash element assignments with bareword key => value
+ ;; (matcher subexp facespec)
+ (,(rx (in "[ \t{,()")
+ (group-n 1 (sequence (opt "-")
+ (eval cperl--basic-identifier-rx)))
+ (0+ blank) "=>")
+ 1 font-lock-string-face)
;; -------- @$ array dereferences, $#$ last array index
;; (matcher (subexp facespec) (subexp facespec))
(,(rx (group-n 1 (or "@" "$#"))
@@ -6238,8 +6174,34 @@ functions (which they are not). Inherits from `default'.")
;; ("\\(%\\)\\(\\$+\\([a-zA-Z_:][a-zA-Z0-9_:]*\\|[^ \t\n]\\)\\)"
(1 'cperl-hash-face)
(2 font-lock-variable-name-face))
-;;("\\([smy]\\|tr\\)\\([^a-z_A-Z0-9]\\)\\(\\([^\n\\]*||\\)\\)\\2")
-;;; Too much noise from \s* @s[ and friends
+ ;; -------- access to array/hash elements
+ ;; (matcher subexp facespec)
+ ;; facespec is an expression to distinguish between arrays and hashes
+ (,(rx (group-n 1 (group-n 2 (in "$@%"))
+ (eval cperl--normal-identifier-rx))
+ (0+ blank)
+ (group-n 3 (in "[{")))
+;; ("\\(\\([$@%]+\\)[a-zA-Z_:][a-zA-Z0-9_:]*\\)[ \t]*\\([[{]\\)"
+ 1
+ (if (= (- (match-end 2) (match-beginning 2)) 1)
+ (if (eq (char-after (match-beginning 3)) ?{)
+ 'cperl-hash-face
+ 'cperl-array-face) ; arrays and hashes
+ font-lock-variable-name-face) ; Just to put something
+ nil) ; do not override previous
+ ;; -------- "Pure" arrays and hashes.
+ ;; (matcher subexp facespec)
+ ;; facespec is an expression to distinguish between arrays and hashes
+ (,(rx (group-n 1 (group-n 2 (or (in "@%") "$#"))
+ (eval cperl--normal-identifier-rx)))
+ 1
+ ;; ("\\(\\([@%]\\|\\$#\\)[a-zA-Z_:][a-zA-Z0-9_:]*\\)" 1
+ (if (eq (char-after (match-beginning 2)) ?%)
+ 'cperl-hash-face
+ 'cperl-array-face)
+ nil)
+ ;;("\\([smy]\\|tr\\)\\([^a-z_A-Z0-9]\\)\\(\\([^\n\\]*||\\)\\)\\2")
+ ;; Too much noise from \s* @s[ and friends
;;("\\(\\<\\([msy]\\|tr\\)[ \t]*\\([^ \t\na-zA-Z0-9_]\\)\\|\\(/\\)\\)"
;;(3 font-lock-function-name-face t t)
;;(4
@@ -6566,13 +6528,6 @@ side-effect of memorizing only. Examples in `cperl-style-examples'."
cperl-old-style (cdr cperl-old-style))
(set (car setting) (cdr setting)))))
-(defvar perl-dbg-flags)
-(defun cperl-check-syntax ()
- (interactive)
- (require 'mode-compile)
- (let ((perl-dbg-flags (concat cperl-extra-perl-args " -wc")))
- (eval '(mode-compile)))) ; Avoid a warning
-
(declare-function Info-find-node "info"
(filename nodename &optional no-going-back strict-case
noerror))
@@ -6616,10 +6571,7 @@ side-effect of memorizing only. Examples in `cperl-style-examples'."
'find-tag-default))))))
(defun cperl-info-on-command (command)
- "Show documentation for Perl command COMMAND in other window.
-If perl-info buffer is shown in some frame, uses this frame.
-Customized by setting variables `cperl-shrink-wrap-info-frame',
-`cperl-max-help-size'."
+ (declare (obsolete cperl-perldoc "30.1"))
(interactive
(let* ((default (cperl-word-at-point))
(read (read-string
@@ -6695,52 +6647,30 @@ Customized by setting variables `cperl-shrink-wrap-info-frame',
(select-window iniwin)))
(defun cperl-info-on-current-command ()
- "Show documentation for Perl command at point in other window."
+ (declare (obsolete cperl-perldoc "30.1"))
(interactive)
- (cperl-info-on-command (cperl-word-at-point)))
+ (cperl-perldoc (cperl-word-at-point)))
(defun cperl-imenu-info-imenu-search ()
+ (declare (obsolete nil "30.1"))
(if (looking-at "^-X[ \t\n]") nil
(re-search-backward
"^\n\\([-a-zA-Z_]+\\)[ \t\n]")
(forward-line 1)))
(defun cperl-imenu-info-imenu-name ()
+ (declare (obsolete nil "30.1"))
(buffer-substring
(match-beginning 1) (match-end 1)))
(declare-function imenu-choose-buffer-index "imenu" (&optional prompt alist))
(defun cperl-imenu-on-info ()
- "Show imenu for Perl Info Buffer.
-Opens Perl Info buffer if needed."
+ (declare (obsolete nil "30.1"))
(interactive)
- (require 'imenu)
- (let* ((buffer (current-buffer))
- imenu-create-index-function
- imenu-prev-index-position-function
- imenu-extract-index-name-function
- (index-item (save-restriction
- (save-window-excursion
- (set-buffer (cperl-info-buffer nil))
- (setq imenu-create-index-function
- 'imenu-default-create-index-function
- imenu-prev-index-position-function
- #'cperl-imenu-info-imenu-search
- imenu-extract-index-name-function
- #'cperl-imenu-info-imenu-name)
- (imenu-choose-buffer-index)))))
- (and index-item
- (progn
- (push-mark)
- (pop-to-buffer "*info-perl*")
- (cond
- ((markerp (cdr index-item))
- (goto-char (marker-position (cdr index-item))))
- (t
- (goto-char (cdr index-item))))
- (set-window-start (selected-window) (point))
- (pop-to-buffer buffer)))))
+ (message
+ (concat "The info file `perl' is no longer available.\n"
+ "Consider installing the perl-doc package from GNU ELPA.")))
(defun cperl-lineup (beg end &optional step minshift)
"Lineup construction in a region.
@@ -7374,9 +7304,6 @@ One may build such TAGS files from CPerl mode menu."
(nreverse list2))
list1)))))
-(defvar imenu-max-items nil
- "Max items in an imenu list. Defined in imenu.el.")
-
(defun cperl-menu-to-keymap (menu)
(let (list)
(cons 'keymap
@@ -8834,8 +8761,6 @@ start with default arguments, then refine the slowdown regions."
(message "to %s:%6s,%7s" l delta tot))
tot))
-(defvar font-lock-cache-position)
-
(defun cperl-emulate-lazy-lock (&optional window-size)
"Emulate `lazy-lock' without `condition-case', so `debug-on-error' works.
Start fontifying the buffer from the start (or end) using the given
@@ -8907,6 +8832,7 @@ Delay of auto-help controlled by `cperl-lazy-help-time'."
;;; Plug for wrong font-lock:
(defun cperl-font-lock-unfontify-region-function (beg end)
+ (declare (obsolete nil "30.1"))
(with-silent-modifications
(remove-text-properties beg end '(face nil))))
@@ -8980,7 +8906,8 @@ do extra unwind via `cperl-unwind-to-safe'."
(defun cperl-fontify-update-bad (end)
;; Since fontification happens with different region than syntaxification,
- ;; do to the end of buffer, not to END;;; likewise, start earlier if needed
+ ;; do to the end of buffer, not to END
+ ;; likewise, start earlier if needed
(let* ((pos (point)) (prop (get-text-property pos 'cperl-postpone)) posend)
(if prop
(setq pos (or (cperl-beginning-of-property
diff --git a/lisp/progmodes/cpp.el b/lisp/progmodes/cpp.el
index ebc76c10fdb..827ad6d24ee 100644
--- a/lisp/progmodes/cpp.el
+++ b/lisp/progmodes/cpp.el
@@ -1,6 +1,6 @@
;;; cpp.el --- highlight or hide text according to cpp conditionals -*- lexical-binding: t -*-
-;; Copyright (C) 1994-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1994-2024 Free Software Foundation, Inc.
;; Author: Per Abrahamsen <abraham@dina.kvl.dk>
;; Keywords: c, faces, tools
diff --git a/lisp/progmodes/csharp-mode.el b/lisp/progmodes/csharp-mode.el
index 37bb84ab5ba..7bf57bcbe21 100644
--- a/lisp/progmodes/csharp-mode.el
+++ b/lisp/progmodes/csharp-mode.el
@@ -1,6 +1,6 @@
;;; csharp-mode.el --- Support for editing C# -*- lexical-binding: t; -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;; Author : Theodor Thornhill <theo@thornhill.no>
;; Jostein Kjønigsen <jostein@kjonigsen.net>
@@ -493,7 +493,7 @@ compilation and evaluation time conflicts."
;; Next non-whitespace character should be '{'
(goto-char (c-point 'boi))
(unless (eq (char-after) ?{)
- (backward-up-list 1 t t))
+ (ignore-errors (backward-up-list 1 t t)))
(save-excursion
;; 'new' should be part of the line
(goto-char (c-point 'iopl))
@@ -959,10 +959,12 @@ Key bindings:
;; Comments.
(c-ts-common-comment-setup)
- (setq-local treesit-text-type-regexp
- (regexp-opt '("comment"
- "verbatim_string-literal"
- "interpolated_verbatim_string-text")))
+ (setq-local treesit-thing-settings
+ `((c-sharp
+ (text
+ ,(regexp-opt '("comment"
+ "verbatim_string-literal"
+ "interpolated_verbatim_string-text"))))))
;; Indent.
(setq-local treesit-simple-indent-rules csharp-ts-mode--indent-rules)
diff --git a/lisp/progmodes/cwarn.el b/lisp/progmodes/cwarn.el
index cf0e6508011..0f4fca3664e 100644
--- a/lisp/progmodes/cwarn.el
+++ b/lisp/progmodes/cwarn.el
@@ -1,6 +1,6 @@
;;; cwarn.el --- highlight suspicious C and C++ constructions -*- lexical-binding: t -*-
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
;; Author: Anders Lindgren
;; Keywords: c, languages, faces
diff --git a/lisp/progmodes/dcl-mode.el b/lisp/progmodes/dcl-mode.el
index cf589762e8f..b8ca1f2d600 100644
--- a/lisp/progmodes/dcl-mode.el
+++ b/lisp/progmodes/dcl-mode.el
@@ -1,6 +1,6 @@
;;; dcl-mode.el --- major mode for editing DCL command files -*- lexical-binding: t; -*-
-;; Copyright (C) 1997-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997-2024 Free Software Foundation, Inc.
;; Author: Odd Gripenstam <gripenstamol@decus.se>
;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/progmodes/dockerfile-ts-mode.el b/lisp/progmodes/dockerfile-ts-mode.el
index 333158e20f6..334f3064d98 100644
--- a/lisp/progmodes/dockerfile-ts-mode.el
+++ b/lisp/progmodes/dockerfile-ts-mode.el
@@ -1,6 +1,6 @@
;;; dockerfile-ts-mode.el --- tree-sitter support for Dockerfiles -*- lexical-binding: t; -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;; Author : Randy Taylor <dev@rjt.dev>
;; Maintainer : Randy Taylor <dev@rjt.dev>
@@ -175,8 +175,9 @@ the subtrees."
dockerfile-ts-mode--indent-rules)
;; Navigation
- (setq-local treesit-sentence-type-regexp
- "instruction")
+ (setq-local treesit-thing-settings
+ `((dockerfile
+ (sentence "instruction"))))
;; Font-lock.
(setq-local treesit-font-lock-settings
diff --git a/lisp/progmodes/ebnf-abn.el b/lisp/progmodes/ebnf-abn.el
index d05128b88ad..2037696bf2f 100644
--- a/lisp/progmodes/ebnf-abn.el
+++ b/lisp/progmodes/ebnf-abn.el
@@ -1,9 +1,9 @@
;;; ebnf-abn.el --- parser for ABNF (Augmented BNF) -*- lexical-binding: t; -*-
-;; Copyright (C) 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2024 Free Software Foundation, Inc.
;; Author: Vinicius Jose Latorre <viniciusjl.gnu@gmail.com>
-;; Keywords: wp, ebnf, PostScript
+;; Keywords: text, ebnf, PostScript
;; Old-Version: 1.2
;; Package: ebnf2ps
diff --git a/lisp/progmodes/ebnf-bnf.el b/lisp/progmodes/ebnf-bnf.el
index d746efbe690..c1862843368 100644
--- a/lisp/progmodes/ebnf-bnf.el
+++ b/lisp/progmodes/ebnf-bnf.el
@@ -1,9 +1,9 @@
;;; ebnf-bnf.el --- parser for EBNF -*- lexical-binding: t; -*-
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
;; Author: Vinicius Jose Latorre <viniciusjl.gnu@gmail.com>
-;; Keywords: wp, ebnf, PostScript
+;; Keywords: text, ebnf, PostScript
;; Old-Version: 1.10
;; Package: ebnf2ps
diff --git a/lisp/progmodes/ebnf-dtd.el b/lisp/progmodes/ebnf-dtd.el
index 3a2add32d77..a9d1cc5e2b8 100644
--- a/lisp/progmodes/ebnf-dtd.el
+++ b/lisp/progmodes/ebnf-dtd.el
@@ -1,9 +1,9 @@
;;; ebnf-dtd.el --- parser for DTD (Data Type Description for XML) -*- lexical-binding: t; -*-
-;; Copyright (C) 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2024 Free Software Foundation, Inc.
;; Author: Vinicius Jose Latorre <viniciusjl.gnu@gmail.com>
-;; Keywords: wp, ebnf, PostScript
+;; Keywords: text, ebnf, PostScript
;; Old-Version: 1.1
;; Package: ebnf2ps
diff --git a/lisp/progmodes/ebnf-ebx.el b/lisp/progmodes/ebnf-ebx.el
index 29a50005494..b88e68dc4a6 100644
--- a/lisp/progmodes/ebnf-ebx.el
+++ b/lisp/progmodes/ebnf-ebx.el
@@ -1,9 +1,9 @@
;;; ebnf-ebx.el --- parser for EBNF used to specify XML (EBNFX) -*- lexical-binding: t; -*-
-;; Copyright (C) 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2024 Free Software Foundation, Inc.
;; Author: Vinicius Jose Latorre <viniciusjl.gnu@gmail.com>
-;; Keywords: wp, ebnf, PostScript
+;; Keywords: text, ebnf, PostScript
;; Old-Version: 1.2
;; Package: ebnf2ps
diff --git a/lisp/progmodes/ebnf-iso.el b/lisp/progmodes/ebnf-iso.el
index c4d11c97fff..e8d3e65976d 100644
--- a/lisp/progmodes/ebnf-iso.el
+++ b/lisp/progmodes/ebnf-iso.el
@@ -1,9 +1,9 @@
;;; ebnf-iso.el --- parser for ISO EBNF -*- lexical-binding: t; -*-
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
;; Author: Vinicius Jose Latorre <viniciusjl.gnu@gmail.com>
-;; Keywords: wp, ebnf, PostScript
+;; Keywords: text, ebnf, PostScript
;; Old-Version: 1.9
;; Package: ebnf2ps
diff --git a/lisp/progmodes/ebnf-otz.el b/lisp/progmodes/ebnf-otz.el
index 4155dc0d2cd..15141e762d4 100644
--- a/lisp/progmodes/ebnf-otz.el
+++ b/lisp/progmodes/ebnf-otz.el
@@ -1,9 +1,9 @@
;;; ebnf-otz.el --- syntactic chart OpTimiZer -*- lexical-binding: t; -*-
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
;; Author: Vinicius Jose Latorre <viniciusjl.gnu@gmail.com>
-;; Keywords: wp, ebnf, PostScript
+;; Keywords: text, ebnf, PostScript
;; Old-Version: 1.0
;; Package: ebnf2ps
diff --git a/lisp/progmodes/ebnf-yac.el b/lisp/progmodes/ebnf-yac.el
index aaec71daa73..0ef98bd2d14 100644
--- a/lisp/progmodes/ebnf-yac.el
+++ b/lisp/progmodes/ebnf-yac.el
@@ -1,9 +1,9 @@
;;; ebnf-yac.el --- parser for Yacc/Bison -*- lexical-binding: t; -*-
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
;; Author: Vinicius Jose Latorre <viniciusjl.gnu@gmail.com>
-;; Keywords: wp, ebnf, PostScript
+;; Keywords: text, ebnf, PostScript
;; Old-Version: 1.4
;; Package: ebnf2ps
diff --git a/lisp/progmodes/ebnf2ps.el b/lisp/progmodes/ebnf2ps.el
index 3e83d288408..c74a523808f 100644
--- a/lisp/progmodes/ebnf2ps.el
+++ b/lisp/progmodes/ebnf2ps.el
@@ -1,9 +1,9 @@
;;; ebnf2ps.el --- translate an EBNF to a syntactic chart on PostScript -*- lexical-binding:t -*-
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
;; Author: Vinicius Jose Latorre <viniciusjl.gnu@gmail.com>
-;; Keywords: wp, ebnf, PostScript
+;; Keywords: text, ebnf, PostScript
;; Old-Version: 4.4
;; URL: https://www.emacswiki.org/cgi-bin/wiki/ViniciusJoseLatorre
@@ -5247,7 +5247,7 @@ killed after process termination."
(or ebnf-fonts-required
(setq ebnf-fonts-required
(mapconcat #'identity
- (ps-remove-duplicates
+ (delete-dups
(mapcar #'ebnf-font-name-select
(list ebnf-production-font
ebnf-terminal-font
diff --git a/lisp/progmodes/ebrowse.el b/lisp/progmodes/ebrowse.el
index 5ca2f09b141..37b3a5f190b 100644
--- a/lisp/progmodes/ebrowse.el
+++ b/lisp/progmodes/ebrowse.el
@@ -1,6 +1,6 @@
;;; ebrowse.el --- Emacs C++ class browser & tags facility -*- lexical-binding:t -*-
-;; Copyright (C) 1992-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1992-2024 Free Software Foundation, Inc.
;; Author: Gerd Moellmann <gerd@gnu.org>
;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/progmodes/eglot.el b/lisp/progmodes/eglot.el
index 65daa0941d5..d330e6e23cb 100644
--- a/lisp/progmodes/eglot.el
+++ b/lisp/progmodes/eglot.el
@@ -1,13 +1,13 @@
;;; eglot.el --- The Emacs Client for LSP servers -*- lexical-binding: t; -*-
-;; Copyright (C) 2018-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2018-2024 Free Software Foundation, Inc.
-;; Version: 1.15
+;; Version: 1.16
;; Author: João Távora <joaotavora@gmail.com>
;; Maintainer: João Távora <joaotavora@gmail.com>
;; URL: https://github.com/joaotavora/eglot
;; Keywords: convenience, languages
-;; Package-Requires: ((emacs "26.3") (jsonrpc "1.0.16") (flymake "1.2.1") (project "0.9.8") (xref "1.6.2") (eldoc "1.14.0") (seq "2.23") (external-completion "0.1"))
+;; Package-Requires: ((emacs "26.3") (jsonrpc "1.0.23") (flymake "1.2.1") (project "0.9.8") (xref "1.6.2") (eldoc "1.14.0") (seq "2.23") (external-completion "0.1"))
;; This is a GNU ELPA :core package. Avoid adding functionality
;; that is not available in the version of Emacs recorded above or any
@@ -108,19 +108,30 @@
(require 'filenotify)
(require 'ert)
(require 'text-property-search nil t)
+(require 'diff-mode)
+(require 'diff)
;; These dependencies are also GNU ELPA core packages. Because of
;; bug#62576, since there is a risk that M-x package-install, despite
;; having installed them, didn't correctly re-load them over the
;; built-in versions.
(eval-and-compile
- (load "project")
- (load "eldoc")
- (load "seq")
- (load "flymake")
- (load "xref")
- (load "jsonrpc")
- (load "external-completion"))
+ ;; For those packages that are preloaded, reload them if needed,
+ ;; since that's the best we can do anyway.
+ ;; FIXME: Maybe the ELPA packages for those preloaded packages should
+ ;; force-reload themselves eagerly when the package is activated!
+ (let ((reload (if (fboundp 'require-with-check) ;Emacs≥30
+ #'require-with-check
+ (lambda (feature &rest _)
+ ;; Just blindly reload like we used to do before
+ ;; `require-with-check'.
+ (load (symbol-name feature) nil 'nomessage)))))
+
+ (funcall reload 'eldoc nil 'reload)
+ (funcall reload 'seq nil 'reload)
+ ;; For those packages which are not preloaded OTOH, signal an error if
+ ;; the loaded file is not the one that should have been loaded.
+ (mapc reload '(project flymake xref jsonrpc external-completion))))
;; forward-declare, but don't require (Emacs 28 doesn't seem to care)
(defvar markdown-fontify-code-blocks-natively)
@@ -130,6 +141,37 @@
(defvar tramp-use-ssh-controlmaster-options)
+;;; Obsolete aliases
+;;;
+(make-obsolete-variable 'eglot--managed-mode-hook
+ 'eglot-managed-mode-hook "1.6")
+(define-obsolete-variable-alias 'eglot-confirm-server-initiated-edits
+ 'eglot-confirm-server-edits "1.16")
+(make-obsolete-variable 'eglot-events-buffer-size
+ 'eglot-events-buffer-config "1.16")
+(define-obsolete-function-alias 'eglot--uri-to-path #'eglot-uri-to-path "1.16")
+(define-obsolete-function-alias 'eglot--path-to-uri #'eglot-path-to-uri "1.16")
+(define-obsolete-function-alias 'eglot--range-region #'eglot-range-region "1.16")
+(define-obsolete-function-alias 'eglot--server-capable #'eglot-server-capable "1.16")
+(define-obsolete-function-alias 'eglot--server-capable-or-lose #'eglot-server-capable-or-lose "1.16")
+(define-obsolete-function-alias
+ 'eglot-lsp-abiding-column #'eglot-utf-16-linepos "1.12")
+(define-obsolete-function-alias
+ 'eglot-current-column #'eglot-utf-32-linepos "1.12")
+(define-obsolete-variable-alias
+ 'eglot-current-column-function 'eglot-current-linepos-function "1.12")
+(define-obsolete-function-alias
+ 'eglot-move-to-current-column #'eglot-move-to-utf-32-linepos "1.12")
+(define-obsolete-function-alias
+ 'eglot-move-to-lsp-abiding-column #'eglot-move-to-utf-16-linepos "1.12")
+(define-obsolete-variable-alias
+ 'eglot-move-to-column-function 'eglot-move-to-linepos-function "1.12")
+(define-obsolete-variable-alias 'eglot-ignored-server-capabilites
+ 'eglot-ignored-server-capabilities "1.8")
+;;;###autoload
+(define-obsolete-function-alias 'eglot-update #'eglot-upgrade-eglot "29.1")
+
+
;;; User tweakable stuff
(defgroup eglot nil
"Interaction with Language Server Protocol servers."
@@ -140,11 +182,12 @@
"Compute server-choosing function for `eglot-server-programs'.
Each element of ALTERNATIVES is a string PROGRAM or a list of
strings (PROGRAM ARGS...) where program names an LSP server
-program to start with ARGS. Returns a function of one argument.
-When invoked, that function will return a list (ABSPATH ARGS),
-where ABSPATH is the absolute path of the PROGRAM that was
-chosen (interactively or automatically)."
- (lambda (&optional interactive)
+program to start with ARGS. Returns a function to be invoked
+automatically by Eglot on startup. When invoked, that function
+will return a list (ABSPATH ARGS), where ABSPATH is the absolute
+path of the PROGRAM that was chosen (interactively or
+automatically)."
+ (lambda (&optional interactive _project)
;; JT@2021-06-13: This function is way more complicated than it
;; could be because it accounts for the fact that
;; `eglot--executable-find' may take much longer to execute on
@@ -154,7 +197,10 @@ chosen (interactively or automatically)."
(err (lambda ()
(error "None of '%s' are valid executables"
(mapconcat #'car listified ", ")))))
- (cond (interactive
+ (cond ((and interactive current-prefix-arg)
+ ;; A C-u always lets user input something manually,
+ nil)
+ (interactive
(let* ((augmented (mapcar (lambda (a)
(let ((found (eglot--executable-find
(car a) t)))
@@ -185,19 +231,23 @@ chosen (interactively or automatically)."
(vimrc-mode . ("vim-language-server" "--stdio"))
((python-mode python-ts-mode)
. ,(eglot-alternatives
- '("pylsp" "pyls" ("pyright-langserver" "--stdio") "jedi-language-server")))
+ '("pylsp" "pyls" ("pyright-langserver" "--stdio") "jedi-language-server" "ruff-lsp")))
((js-json-mode json-mode json-ts-mode)
. ,(eglot-alternatives '(("vscode-json-language-server" "--stdio")
("vscode-json-languageserver" "--stdio")
("json-languageserver" "--stdio"))))
- ((js-mode js-ts-mode tsx-ts-mode typescript-ts-mode typescript-mode)
+ (((js-mode :language-id "javascript")
+ (js-ts-mode :language-id "javascript")
+ (tsx-ts-mode :language-id "typescriptreact")
+ (typescript-ts-mode :language-id "typescript")
+ (typescript-mode :language-id "typescript"))
. ("typescript-language-server" "--stdio"))
((bash-ts-mode sh-mode) . ("bash-language-server" "start"))
((php-mode phps-mode)
. ,(eglot-alternatives
'(("phpactor" "language-server")
("php" "vendor/felixfbecker/language-server/bin/php-language-server.php"))))
- ((c-mode c-ts-mode c++-mode c++-ts-mode)
+ ((c-mode c-ts-mode c++-mode c++-ts-mode objc-mode)
. ,(eglot-alternatives
'("clangd" "ccls")))
(((caml-mode :language-id "ocaml")
@@ -237,8 +287,8 @@ chosen (interactively or automatically)."
(gdscript-mode . ("localhost" 6008))
((fortran-mode f90-mode) . ("fortls"))
(futhark-mode . ("futhark" "lsp"))
- (lua-mode . ,(eglot-alternatives
- '("lua-language-server" "lua-lsp")))
+ ((lua-mode lua-ts-mode) . ,(eglot-alternatives
+ '("lua-language-server" "lua-lsp")))
(zig-mode . ("zls"))
((css-mode css-ts-mode)
. ,(eglot-alternatives '(("vscode-css-language-server" "--stdio")
@@ -257,7 +307,9 @@ chosen (interactively or automatically)."
. ,(eglot-alternatives
'(("marksman" "server")
("vscode-markdown-language-server" "--stdio"))))
- (graphviz-dot-mode . ("dot-language-server" "--stdio")))
+ (graphviz-dot-mode . ("dot-language-server" "--stdio"))
+ (terraform-mode . ("terraform-ls" "serve"))
+ ((uiua-ts-mode uiua-mode) . ("uiua" "lsp")))
"How the command `eglot' guesses the server to start.
An association list of (MAJOR-MODE . CONTACT) pairs. MAJOR-MODE
identifies the buffers that are to be managed by a specific
@@ -313,16 +365,16 @@ CONTACT can be:
which you should see for the semantics of the mandatory
:PROCESS argument.
-* A function of a single argument producing any of the above
- values for CONTACT. The argument's value is non-nil if the
- connection was requested interactively (e.g. from the `eglot'
- command), and nil if it wasn't (e.g. from `eglot-ensure'). If
- the call is interactive, the function can ask the user for
- hints on finding the required programs, etc. Otherwise, it
- should not ask the user for any input, and return nil or signal
- an error if it can't produce a valid CONTACT. The helper
- function `eglot-alternatives' (which see) can be used to
- produce a function that offers more than one server for a given
+* A function of two arguments (INTERACTIVE PROJECT) producing any
+ of the above values for CONTACT. INTERACTIVE will be t if an
+ interactive `M-x eglot' was used, and nil otherwise (e.g. from
+ `eglot-ensure'). Interactive calls may ask the user for hints
+ on finding the required programs, etc. PROJECT is whatever
+ project Eglot discovered via `project-find-functions' (which
+ see). The function should return nil or signal an error if it
+ can't produce a valid CONTACT. The helper function
+ `eglot-alternatives' (which see) can be used to produce a
+ function that offers more than one server for a given
MAJOR-MODE.")
(defface eglot-highlight-symbol-face
@@ -376,22 +428,60 @@ as 0, i.e. don't block at all."
"Don't tell server of changes before Emacs's been idle for this many seconds."
:type 'number)
-(defcustom eglot-events-buffer-size 2000000
- "Control the size of the Eglot events buffer.
-If a number, don't let the buffer grow larger than that many
-characters. If 0, don't use an event's buffer at all. If nil,
-let the buffer grow forever.
-
-For changes on this variable to take effect on a connection
-already started, you need to restart the connection. That can be
-done by `eglot-reconnect'."
- :type '(choice (const :tag "No limit" nil)
- (integer :tag "Number of characters")))
-
-(defcustom eglot-confirm-server-initiated-edits 'confirm
- "Non-nil if server-initiated edits should be confirmed with user."
- :type '(choice (const :tag "Don't show confirmation prompt" nil)
- (const :tag "Show confirmation prompt" confirm)))
+(defcustom eglot-events-buffer-config
+ (list :size (or (bound-and-true-p eglot-events-buffer-size) 2000000)
+ :format 'full)
+ "Configure the Eglot events buffer.
+
+Value is a plist accepting the keys `:size', which controls the
+size in characters of the buffer (0 disables, nil means
+infinite), and `:format', which controls the shape of each log
+entry (`full' includes the original JSON, `lisp' uses
+pretty-printed Lisp).
+
+For changes on this variable to take effect, you need to restart
+the LSP connection. That can be done by `eglot-reconnect'."
+ :type '(plist :key-type (symbol :tag "Keyword")
+ :options (((const :tag "Size" :size)
+ (choice
+ (const :tag "No limit" nil)
+ (integer :tag "Number of characters")))
+ ((const :tag "Format" :format)
+ (choice
+ (const :tag "Full with original JSON" full)
+ (const :tag "Shortened" short)
+ (const :tag "Pretty-printed lisp" lisp))))))
+
+(defcustom eglot-confirm-server-edits '((eglot-rename . nil)
+ (t . maybe-summary))
+ "Control if changes proposed by LSP should be confirmed with user.
+
+If this variable's value is the symbol `diff', a diff buffer is
+pops up, allowing the user to apply each change individually. If
+the symbol `summary' or any other non-nil value, the user is
+prompted in the minibuffer with aa short summary of changes. The
+symbols `maybe-diff' and `maybe-summary' mean that the
+confirmation is offered to the user only if the changes target
+files visited in buffers. Finally, a nil value means all changes
+are applied directly without any confirmation.
+
+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
+ACTION is the default value for commands not in the alist."
+ :type (let ((basic-choices
+ '((const :tag "Use diff" diff)
+ (const :tag "Summarize and prompt" summary)
+ (const :tag "Maybe use diff" maybe-diff)
+ (const :tag "Maybe summarize and prompt" maybe-summary)
+ (const :tag "Don't confirm" nil))))
+ `(choice ,@basic-choices
+ (alist :tag "Per-command alist"
+ :key-type (choice (function :tag "Command")
+ (const :tag "Default" t))
+ :value-type (choice . ,basic-choices)))))
(defcustom eglot-extend-to-xref nil
"If non-nil, activate Eglot in cross-referenced non-project files."
@@ -409,17 +499,45 @@ done by `eglot-reconnect'."
"If non-nil, show progress of long running LSP server work.
If set to `messages', use *Messages* buffer, else use Eglot's
mode line indicator."
- :type 'boolean
+ :type '(choice (const :tag "Don't show progress" nil)
+ (const :tag "Show progress in *Messages*" messages)
+ (const :tag "Show progress in Eglot's mode line indicator" t))
:version "1.10")
+(defcustom eglot-ignored-server-capabilities (list)
+ "LSP server capabilities that Eglot could use, but won't.
+You could add, for instance, the symbol
+`:documentHighlightProvider' to prevent automatic highlighting
+under cursor."
+ :type '(set
+ :tag "Tick the ones you're not interested in"
+ (const :tag "Documentation on hover" :hoverProvider)
+ (const :tag "Code completion" :completionProvider)
+ (const :tag "Function signature help" :signatureHelpProvider)
+ (const :tag "Go to definition" :definitionProvider)
+ (const :tag "Go to type definition" :typeDefinitionProvider)
+ (const :tag "Go to implementation" :implementationProvider)
+ (const :tag "Go to declaration" :declarationProvider)
+ (const :tag "Find references" :referencesProvider)
+ (const :tag "Highlight symbols automatically" :documentHighlightProvider)
+ (const :tag "List symbols in buffer" :documentSymbolProvider)
+ (const :tag "List symbols in workspace" :workspaceSymbolProvider)
+ (const :tag "Execute code actions" :codeActionProvider)
+ (const :tag "Code lens" :codeLensProvider)
+ (const :tag "Format buffer" :documentFormattingProvider)
+ (const :tag "Format portion of buffer" :documentRangeFormattingProvider)
+ (const :tag "On-type formatting" :documentOnTypeFormattingProvider)
+ (const :tag "Rename symbol" :renameProvider)
+ (const :tag "Highlight links in document" :documentLinkProvider)
+ (const :tag "Decorate color references" :colorProvider)
+ (const :tag "Fold regions of buffer" :foldingRangeProvider)
+ (const :tag "Execute custom commands" :executeCommandProvider)
+ (const :tag "Inlay hints" :inlayHintProvider)))
+
(defvar eglot-withhold-process-id nil
"If non-nil, Eglot will not send the Emacs process id to the language server.
This can be useful when using docker to run a language server.")
-;; Customizable via `completion-category-overrides'.
-(when (assoc 'flex completion-styles-alist)
- (add-to-list 'completion-category-defaults '(eglot (styles flex basic))))
-
;;; Constants
;;;
@@ -456,6 +574,7 @@ It is nil if Eglot is not byte-complied.")
(2 . eglot-diagnostic-tag-deprecated-face)))
(defvaralias 'eglot-{} 'eglot--{})
+
(defconst eglot--{} (make-hash-table :size 1) "The empty JSON object.")
(defun eglot--executable-find (command &optional remote)
@@ -467,6 +586,12 @@ It is nil if Eglot is not byte-complied.")
(if (and (not eglot-prefer-plaintext) (fboundp 'gfm-view-mode))
["markdown" "plaintext"] ["plaintext"]))
+(defconst eglot--uri-path-allowed-chars
+ (let ((vec (copy-sequence url-path-allowed-chars)))
+ (aset vec ?: nil) ;; see github#639
+ vec)
+ "Like `url-path-allows-chars' but more restrictive.")
+
;;; Message verification helpers
;;;
@@ -660,7 +785,6 @@ Honor `eglot-strict-mode'."
(cl-destructuring-bind (&key ,@vars &allow-other-keys) ,object-once
(funcall ,fn-once ,@vars))))))))
-
(cl-defmacro eglot--lambda (cl-lambda-list &body body)
"Function of args CL-LAMBDA-LIST for processing INTERFACE objects.
Honor `eglot-strict-mode'."
@@ -709,9 +833,6 @@ treated as in `eglot--dbind'."
,obj-once
',(mapcar #'car clauses)))))))
-
-;;; API (WORK-IN-PROGRESS!)
-;;;
(cl-defmacro eglot--when-live-buffer (buf &rest body)
"Check BUF live, then do BODY in it." (declare (indent 1) (debug t))
(let ((b (cl-gensym)))
@@ -729,6 +850,9 @@ treated as in `eglot--dbind'."
"Save excursion and restriction. Widen. Then run BODY." (declare (debug t))
`(save-excursion (save-restriction (widen) ,@body)))
+
+;;; Public Elisp API
+;;;
(cl-defgeneric eglot-handle-request (server method &rest params)
"Handle SERVER's METHOD request with PARAMS.")
@@ -751,9 +875,9 @@ ACTION is an LSP object of either `CodeAction' or `Command' type."
(((Command)) (eglot--request server :workspace/executeCommand action))
(((CodeAction) edit command data)
(if (and (null edit) (null command) data
- (eglot--server-capable :codeActionProvider :resolveProvider))
+ (eglot-server-capable :codeActionProvider :resolveProvider))
(eglot-execute server (eglot--request server :codeAction/resolve action))
- (when edit (eglot--apply-workspace-edit edit))
+ (when edit (eglot--apply-workspace-edit edit this-command))
(when command (eglot--request server :workspace/executeCommand command)))))))
(cl-defgeneric eglot-initialization-options (server)
@@ -871,7 +995,7 @@ ACTION is an LSP object of either `CodeAction' or `Command' type."
(let ((project (eglot--project server)))
(vconcat
(mapcar (lambda (dir)
- (list :uri (eglot--path-to-uri dir)
+ (list :uri (eglot-path-to-uri dir)
:name (abbreviate-file-name dir)))
`(,(project-root project) ,@(project-external-roots project))))))
@@ -881,18 +1005,23 @@ ACTION is an LSP object of either `CodeAction' or `Command' type."
:accessor eglot--project-nickname
:reader eglot-project-nickname)
(languages
+ :initform nil
:documentation "Alist ((MODE . LANGUAGE-ID-STRING)...) of managed languages."
:accessor eglot--languages)
(capabilities
+ :initform nil
:documentation "JSON object containing server capabilities."
:accessor eglot--capabilities)
(server-info
+ :initform nil
:documentation "JSON object containing server info."
:accessor eglot--server-info)
(shutdown-requested
+ :initform nil
:documentation "Flag set when server is shutting down."
:accessor eglot--shutdown-requested)
(project
+ :initform nil
:documentation "Project associated with server."
:accessor eglot--project)
(progress-reporters
@@ -906,17 +1035,90 @@ ACTION is an LSP object of either `CodeAction' or `Command' type."
:documentation "Map (DIR -> (WATCH ID1 ID2...)) for `didChangeWatchedFiles'."
:initform (make-hash-table :test #'equal) :accessor eglot--file-watches)
(managed-buffers
+ :initform nil
:documentation "List of buffers managed by server."
:accessor eglot--managed-buffers)
(saved-initargs
:documentation "Saved initargs for reconnection purposes."
- :accessor eglot--saved-initargs)
- (inferior-process
- :documentation "Server subprocess started automatically."
- :accessor eglot--inferior-process))
+ :accessor eglot--saved-initargs))
:documentation
"Represents a server. Wraps a process for LSP communication.")
+(declare-function w32-long-file-name "w32proc.c" (fn))
+(defun eglot-uri-to-path (uri)
+ "Convert URI to file path, helped by `eglot--current-server'."
+ (when (keywordp uri) (setq uri (substring (symbol-name uri) 1)))
+ (let* ((server (eglot-current-server))
+ (remote-prefix (and server (eglot--trampish-p server)))
+ (url (url-generic-parse-url uri)))
+ ;; Only parse file:// URIs, leave other URI untouched as
+ ;; `file-name-handler-alist' should know how to handle them
+ ;; (bug#58790).
+ (if (string= "file" (url-type url))
+ (let* ((retval (url-unhex-string (url-filename url)))
+ ;; Remove the leading "/" for local MS Windows-style paths.
+ (normalized (if (and (not remote-prefix)
+ (eq system-type 'windows-nt)
+ (cl-plusp (length retval)))
+ (w32-long-file-name (substring retval 1))
+ retval)))
+ (concat remote-prefix normalized))
+ uri)))
+
+(defun eglot-path-to-uri (path)
+ "Convert PATH, a file name, to LSP URI string and return it."
+ (let ((truepath (file-truename path)))
+ (if (and (url-type (url-generic-parse-url path))
+ ;; It might be MS Windows path which includes a drive
+ ;; letter that looks like a URL scheme (bug#59338)
+ (not (and (eq system-type 'windows-nt)
+ (file-name-absolute-p truepath))))
+ ;; Path is already a URI, so forward it to the LSP server
+ ;; untouched. The server should be able to handle it, since
+ ;; it provided this URI to clients in the first place.
+ path
+ (concat "file://"
+ ;; Add a leading "/" for local MS Windows-style paths.
+ (if (and (eq system-type 'windows-nt)
+ (not (file-remote-p truepath)))
+ "/")
+ (url-hexify-string
+ ;; Again watch out for trampy paths.
+ (directory-file-name (file-local-name truepath))
+ eglot--uri-path-allowed-chars)))))
+
+(defun eglot-range-region (range &optional markers)
+ "Return a cons (BEG . END) of positions representing LSP RANGE.
+If optional MARKERS, make markers instead."
+ (let* ((st (plist-get range :start))
+ (beg (eglot--lsp-position-to-point st markers))
+ (end (eglot--lsp-position-to-point (plist-get range :end) markers)))
+ (cons beg end)))
+
+(defun eglot-server-capable (&rest feats)
+ "Determine if current server is capable of FEATS."
+ (unless (cl-some (lambda (feat)
+ (memq feat eglot-ignored-server-capabilities))
+ feats)
+ (cl-loop for caps = (eglot--capabilities (eglot--current-server-or-lose))
+ then (cadr probe)
+ for (feat . more) on feats
+ for probe = (plist-member caps feat)
+ if (not probe) do (cl-return nil)
+ if (eq (cadr probe) :json-false) do (cl-return nil)
+ if (not (listp (cadr probe))) do (cl-return (if more nil (cadr probe)))
+ finally (cl-return (or (cadr probe) t)))))
+
+(defun eglot-server-capable-or-lose (&rest feats)
+ "Like `eglot-server-capable', but maybe error out."
+ (let ((retval (apply #'eglot-server-capable feats)))
+ (unless retval
+ (eglot--error "Unsupported or ignored LSP capability `%s'"
+ (mapconcat #'symbol-name feats " ")))
+ retval))
+
+
+;;; Process/server management
(defun eglot--major-modes (s) "Major modes server S is responsible for."
(mapcar #'car (eglot--languages s)))
@@ -926,8 +1128,6 @@ ACTION is an LSP object of either `CodeAction' or `Command' type."
(cl-defmethod initialize-instance :before ((_server eglot-lsp-server) &optional args)
(cl-remf args :initializationOptions))
-
-;;; Process management
(defvar eglot--servers-by-project (make-hash-table :test #'equal)
"Keys are projects. Values are lists of processes.")
@@ -977,9 +1177,6 @@ PRESERVE-BUFFERS as in `eglot-shutdown', which see."
(maphash (lambda (_dir watch-and-ids)
(file-notify-rm-watch (car watch-and-ids)))
(eglot--file-watches server))
- ;; Kill any autostarted inferior processes
- (when-let (proc (eglot--inferior-process server))
- (delete-process proc))
;; Sever the project/server relationship for `server'
(setf (gethash (eglot--project server) eglot--servers-by-project)
(delq server
@@ -1048,7 +1245,8 @@ CONTACT-PROXY is the value of the corresponding
Return (MANAGED-MODES PROJECT CLASS CONTACT LANG-IDS). If INTERACTIVE is
non-nil, maybe prompt user, else error as soon as something can't
be guessed."
- (let* ((guessed-mode (if buffer-file-name major-mode))
+ (let* ((project (eglot--current-project))
+ (guessed-mode (if buffer-file-name major-mode))
(guessed-mode-name (and guessed-mode (symbol-name guessed-mode)))
(main-mode
(cond
@@ -1068,7 +1266,9 @@ be guessed."
(language-ids (mapcar #'cdr (car languages-and-contact)))
(guess (cdr languages-and-contact))
(guess (if (functionp guess)
- (funcall guess interactive)
+ (pcase (cdr (func-arity guess))
+ (1 (funcall guess interactive))
+ (_ (funcall guess interactive project)))
guess))
(class (or (and (consp guess) (symbolp (car guess))
(prog1 (unless current-prefix-arg (car guess))
@@ -1104,21 +1304,25 @@ be guessed."
"\n" base-prompt)
(eglot--error
(concat "`%s' not found in PATH, but can't form"
- " an interactive prompt for to fix %s!")
+ " an interactive prompt for help you fix"
+ " this.")
program guess))))))
+ (input (and prompt (read-shell-command prompt
+ full-program-invocation
+ 'eglot-command-history)))
(contact
- (or (and prompt
- (split-string-and-unquote
- (read-shell-command
- prompt
- full-program-invocation
- 'eglot-command-history)))
- guess)))
- (list managed-modes (eglot--current-project) class contact language-ids)))
-
-(defvar eglot-lsp-context)
-(put 'eglot-lsp-context 'variable-documentation
- "Dynamically non-nil when searching for projects in LSP context.")
+ (if input
+ (if (string-match
+ "^[\s\t]*\\(.*\\):\\([[:digit:]]+\\)[\s\t]*$" input)
+ ;; <host>:<port> special case (bug#67682)
+ (list (match-string 1 input)
+ (string-to-number (match-string 2 input)))
+ (split-string-and-unquote input))
+ guess)))
+ (list managed-modes project class contact language-ids)))
+
+(defvar eglot-lsp-context nil
+ "Dynamically non-nil when searching for projects in LSP context.")
(defun eglot--current-project ()
"Return a project object for Eglot's LSP purposes.
@@ -1131,6 +1335,9 @@ suitable root directory for a given LSP server's purposes."
(or (project-current)
`(transient . ,(expand-file-name default-directory)))))
+(cl-defmethod project-root ((project (head eglot--project)))
+ (cadr project))
+
;;;###autoload
(defun eglot (managed-major-modes project class contact language-ids
&optional _interactive)
@@ -1201,7 +1408,18 @@ INTERACTIVE is t if called interactively."
;;;###autoload
(defun eglot-ensure ()
- "Start Eglot session for current buffer if there isn't one."
+ "Start Eglot session for current buffer if there isn't one.
+
+Only use this function (in major mode hooks, etc) if you are
+confident that Eglot can be started safely and efficiently for
+*every* buffer visited where these hooks may execute.
+
+Since it is difficult to establish this confidence fully, it's
+often wise to use the interactive command `eglot' instead. This
+command only needs to be invoked once per project, as all other
+files of a given major mode visited within the same project will
+automatically become managed with no further user intervention
+needed."
(let ((buffer (current-buffer)))
(cl-labels
((maybe-connect
@@ -1209,7 +1427,9 @@ INTERACTIVE is t if called interactively."
(eglot--when-live-buffer buffer
(remove-hook 'post-command-hook #'maybe-connect t)
(unless eglot--managed-mode
- (apply #'eglot--connect (eglot--guess-contact))))))
+ (condition-case-unless-debug oops
+ (apply #'eglot--connect (eglot--guess-contact))
+ (error (eglot--warn (error-message-string oops))))))))
(when buffer-file-name
(add-hook 'post-command-hook #'maybe-connect 'append t)))))
@@ -1273,7 +1493,6 @@ This docstring appeases checkdoc, that's all."
(let* ((default-directory (project-root project))
(nickname (project-name project))
(readable-name (format "EGLOT (%s/%s)" nickname managed-modes))
- autostart-inferior-process
server-info
(contact (if (functionp contact) (funcall contact) contact))
(initargs
@@ -1286,16 +1505,16 @@ This docstring appeases checkdoc, that's all."
readable-name nil
(car contact) (cadr contact)
(cddr contact)))))
- ((and (stringp (car contact)) (memq :autoport contact))
+ ((and (stringp (car contact))
+ (cl-find-if (lambda (x)
+ (or (eq x :autoport)
+ (eq (car-safe x) :autoport)))
+ contact))
(setq server-info (list "<inferior process>"))
- `(:process ,(lambda ()
- (pcase-let ((`(,connection . ,inferior)
- (eglot--inferior-bootstrap
+ `(:process ,(jsonrpc-autoport-bootstrap
readable-name
contact
- '(:noquery t))))
- (setq autostart-inferior-process inferior)
- connection))))
+ :connect-args '(:noquery t))))
((stringp (car contact))
(let* ((probe (cl-position-if #'keywordp contact))
(more-initargs (and probe (cl-subseq contact probe)))
@@ -1328,7 +1547,7 @@ This docstring appeases checkdoc, that's all."
(apply
#'make-instance class
:name readable-name
- :events-buffer-scrollback-size eglot-events-buffer-size
+ :events-buffer-config eglot-events-buffer-config
:notification-dispatcher (funcall spread #'eglot-handle-notification)
:request-dispatcher (funcall spread #'eglot-handle-request)
:on-shutdown #'eglot--on-shutdown
@@ -1344,7 +1563,6 @@ This docstring appeases checkdoc, that's all."
(setf (eglot--languages server)
(cl-loop for m in managed-modes for l in language-ids
collect (cons m l)))
- (setf (eglot--inferior-process server) autostart-inferior-process)
(run-hook-with-args 'eglot-server-initialized-hook server)
;; Now start the handshake. To honor `eglot-sync-connect'
;; maybe-sync-maybe-async semantics we use `jsonrpc-async-request'
@@ -1369,7 +1587,7 @@ This docstring appeases checkdoc, that's all."
;; into `/path/to/baz.py', so LSP groks it.
:rootPath (file-local-name
(expand-file-name default-directory))
- :rootUri (eglot--path-to-uri default-directory)
+ :rootUri (eglot-path-to-uri default-directory)
:initializationOptions (eglot-initialization-options
server)
:capabilities (eglot-client-capabilities server)
@@ -1437,55 +1655,6 @@ in project `%s'."
(quit (jsonrpc-shutdown server) (setq canceled 'quit)))
(setq tag nil))))
-(defun eglot--inferior-bootstrap (name contact &optional connect-args)
- "Use CONTACT to start a server, then connect to it.
-Return a cons of two process objects (CONNECTION . INFERIOR).
-Name both based on NAME.
-CONNECT-ARGS are passed as additional arguments to
-`open-network-stream'."
- (let* ((port-probe (make-network-process :name "eglot-port-probe-dummy"
- :server t
- :host "localhost"
- :service 0))
- (port-number (unwind-protect
- (process-contact port-probe :service)
- (delete-process port-probe)))
- inferior connection)
- (unwind-protect
- (progn
- (setq inferior
- (make-process
- :name (format "autostart-inferior-%s" name)
- :stderr (format "*%s stderr*" name)
- :noquery t
- :command (cl-subst
- (format "%s" port-number) :autoport contact)))
- (setq connection
- (cl-loop
- repeat 10 for i from 1
- do (accept-process-output nil 0.5)
- while (process-live-p inferior)
- do (eglot--message
- "Trying to connect to localhost and port %s (attempt %s)"
- port-number i)
- thereis (ignore-errors
- (apply #'open-network-stream
- (format "autoconnect-%s" name)
- nil
- "localhost" port-number connect-args))))
- (cons connection inferior))
- (cond ((and (process-live-p connection)
- (process-live-p inferior))
- (eglot--message "Done, connected to %s!" port-number))
- (t
- (when inferior (delete-process inferior))
- (when connection (delete-process connection))
- (eglot--error "Could not start and connect to server%s"
- (if inferior
- (format " started with %s"
- (process-command inferior))
- "!")))))))
-
;;; Helpers (move these to API?)
;;;
@@ -1524,13 +1693,6 @@ Unless IMMEDIATE, send pending changes before making request."
;;; Encoding fever
;;;
-(define-obsolete-function-alias
- 'eglot-lsp-abiding-column 'eglot-utf-16-linepos "1.12")
-(define-obsolete-function-alias
- 'eglot-current-column 'eglot-utf-32-linepos "1.12")
-(define-obsolete-variable-alias
- 'eglot-current-column-function 'eglot-current-linepos-function "1.12")
-
(defvar eglot-current-linepos-function #'eglot-utf-16-linepos
"Function calculating position relative to line beginning.
@@ -1569,13 +1731,6 @@ LBP defaults to `eglot--bol'."
:character (progn (when pos (goto-char pos))
(funcall eglot-current-linepos-function)))))
-(define-obsolete-function-alias
- 'eglot-move-to-current-column 'eglot-move-to-utf-32-linepos "1.12")
-(define-obsolete-function-alias
- 'eglot-move-to-lsp-abiding-column 'eglot-move-to-utf-16-linepos "1.12")
-(define-obsolete-variable-alias
-'eglot-move-to-column-function 'eglot-move-to-linepos-function "1.12")
-
(defvar eglot-move-to-linepos-function #'eglot-move-to-utf-16-linepos
"Function to move to a position within a line reported by the LSP server.
@@ -1642,55 +1797,6 @@ If optional MARKER, return a marker instead"
;;; More helpers
-(defconst eglot--uri-path-allowed-chars
- (let ((vec (copy-sequence url-path-allowed-chars)))
- (aset vec ?: nil) ;; see github#639
- vec)
- "Like `url-path-allows-chars' but more restrictive.")
-
-(defun eglot--path-to-uri (path)
- "URIfy PATH."
- (let ((truepath (file-truename path)))
- (if (and (url-type (url-generic-parse-url path))
- ;; It might be MS Windows path which includes a drive
- ;; letter that looks like a URL scheme (bug#59338)
- (not (and (eq system-type 'windows-nt)
- (file-name-absolute-p truepath))))
- ;; Path is already a URI, so forward it to the LSP server
- ;; untouched. The server should be able to handle it, since
- ;; it provided this URI to clients in the first place.
- path
- (concat "file://"
- ;; Add a leading "/" for local MS Windows-style paths.
- (if (and (eq system-type 'windows-nt)
- (not (file-remote-p truepath)))
- "/")
- (url-hexify-string
- ;; Again watch out for trampy paths.
- (directory-file-name (file-local-name truepath))
- eglot--uri-path-allowed-chars)))))
-
-(declare-function w32-long-file-name "w32proc.c" (fn))
-(defun eglot--uri-to-path (uri)
- "Convert URI to file path, helped by `eglot--current-server'."
- (when (keywordp uri) (setq uri (substring (symbol-name uri) 1)))
- (let* ((server (eglot-current-server))
- (remote-prefix (and server (eglot--trampish-p server)))
- (url (url-generic-parse-url uri)))
- ;; Only parse file:// URIs, leave other URI untouched as
- ;; `file-name-handler-alist' should know how to handle them
- ;; (bug#58790).
- (if (string= "file" (url-type url))
- (let* ((retval (url-unhex-string (url-filename url)))
- ;; Remove the leading "/" for local MS Windows-style paths.
- (normalized (if (and (not remote-prefix)
- (eq system-type 'windows-nt)
- (cl-plusp (length retval)))
- (w32-long-file-name (substring retval 1))
- retval)))
- (concat remote-prefix normalized))
- uri)))
-
(defun eglot--snippet-expansion-fn ()
"Compute a function to expand snippets.
Doubles as an indicator of snippet support."
@@ -1725,69 +1831,6 @@ Doubles as an indicator of snippet support."
(prop-match-end match)))))
(string-trim (buffer-string))))))
-(define-obsolete-variable-alias 'eglot-ignored-server-capabilites
- 'eglot-ignored-server-capabilities "1.8")
-
-(defcustom eglot-ignored-server-capabilities (list)
- "LSP server capabilities that Eglot could use, but won't.
-You could add, for instance, the symbol
-`:documentHighlightProvider' to prevent automatic highlighting
-under cursor."
- :type '(set
- :tag "Tick the ones you're not interested in"
- (const :tag "Documentation on hover" :hoverProvider)
- (const :tag "Code completion" :completionProvider)
- (const :tag "Function signature help" :signatureHelpProvider)
- (const :tag "Go to definition" :definitionProvider)
- (const :tag "Go to type definition" :typeDefinitionProvider)
- (const :tag "Go to implementation" :implementationProvider)
- (const :tag "Go to declaration" :declarationProvider)
- (const :tag "Find references" :referencesProvider)
- (const :tag "Highlight symbols automatically" :documentHighlightProvider)
- (const :tag "List symbols in buffer" :documentSymbolProvider)
- (const :tag "List symbols in workspace" :workspaceSymbolProvider)
- (const :tag "Execute code actions" :codeActionProvider)
- (const :tag "Code lens" :codeLensProvider)
- (const :tag "Format buffer" :documentFormattingProvider)
- (const :tag "Format portion of buffer" :documentRangeFormattingProvider)
- (const :tag "On-type formatting" :documentOnTypeFormattingProvider)
- (const :tag "Rename symbol" :renameProvider)
- (const :tag "Highlight links in document" :documentLinkProvider)
- (const :tag "Decorate color references" :colorProvider)
- (const :tag "Fold regions of buffer" :foldingRangeProvider)
- (const :tag "Execute custom commands" :executeCommandProvider)
- (const :tag "Inlay hints" :inlayHintProvider)))
-
-(defun eglot--server-capable (&rest feats)
- "Determine if current server is capable of FEATS."
- (unless (cl-some (lambda (feat)
- (memq feat eglot-ignored-server-capabilities))
- feats)
- (cl-loop for caps = (eglot--capabilities (eglot--current-server-or-lose))
- then (cadr probe)
- for (feat . more) on feats
- for probe = (plist-member caps feat)
- if (not probe) do (cl-return nil)
- if (eq (cadr probe) :json-false) do (cl-return nil)
- if (not (listp (cadr probe))) do (cl-return (if more nil (cadr probe)))
- finally (cl-return (or (cadr probe) t)))))
-
-(defun eglot--server-capable-or-lose (&rest feats)
- "Like `eglot--server-capable', but maybe error out."
- (let ((retval (apply #'eglot--server-capable feats)))
- (unless retval
- (eglot--error "Unsupported or ignored LSP capability `%s'"
- (mapconcat #'symbol-name feats " ")))
- retval))
-
-(defun eglot--range-region (range &optional markers)
- "Return region (BEG . END) that represents LSP RANGE.
-If optional MARKERS, make markers."
- (let* ((st (plist-get range :start))
- (beg (eglot--lsp-position-to-point st markers))
- (end (eglot--lsp-position-to-point (plist-get range :end) markers)))
- (cons beg end)))
-
(defun eglot--read-server (prompt &optional dont-if-just-the-one)
"Read a running Eglot server from minibuffer using PROMPT.
If DONT-IF-JUST-THE-ONE and there's only one server, don't prompt
@@ -1892,23 +1935,23 @@ Use `eglot-managed-p' to determine if current buffer is managed.")
("utf-8"
(eglot--setq-saving eglot-current-linepos-function #'eglot-utf-8-linepos)
(eglot--setq-saving eglot-move-to-linepos-function #'eglot-move-to-utf-8-linepos)))
- (add-hook 'after-change-functions 'eglot--after-change nil t)
- (add-hook 'before-change-functions 'eglot--before-change nil t)
+ (add-hook 'after-change-functions #'eglot--after-change nil t)
+ (add-hook 'before-change-functions #'eglot--before-change nil t)
(add-hook 'kill-buffer-hook #'eglot--managed-mode-off nil t)
;; Prepend "didClose" to the hook after the "nonoff", so it will run first
- (add-hook 'kill-buffer-hook 'eglot--signal-textDocument/didClose nil t)
- (add-hook 'before-revert-hook 'eglot--signal-textDocument/didClose nil t)
- (add-hook 'after-revert-hook 'eglot--after-revert-hook nil t)
- (add-hook 'before-save-hook 'eglot--signal-textDocument/willSave nil t)
- (add-hook 'after-save-hook 'eglot--signal-textDocument/didSave nil t)
+ (add-hook 'kill-buffer-hook #'eglot--signal-textDocument/didClose nil t)
+ (add-hook 'before-revert-hook #'eglot--signal-textDocument/didClose nil t)
+ (add-hook 'after-revert-hook #'eglot--after-revert-hook nil t)
+ (add-hook 'before-save-hook #'eglot--signal-textDocument/willSave nil t)
+ (add-hook 'after-save-hook #'eglot--signal-textDocument/didSave nil t)
(unless (eglot--stay-out-of-p 'xref)
- (add-hook 'xref-backend-functions 'eglot-xref-backend nil t))
+ (add-hook 'xref-backend-functions #'eglot-xref-backend nil t))
(add-hook 'completion-at-point-functions #'eglot-completion-at-point nil t)
(add-hook 'completion-in-region-mode-hook #'eglot--capf-session-flush nil t)
(add-hook 'company-after-completion-hook #'eglot--capf-session-flush nil t)
(add-hook 'change-major-mode-hook #'eglot--managed-mode-off nil t)
- (add-hook 'post-self-insert-hook 'eglot--post-self-insert-hook nil t)
- (add-hook 'pre-command-hook 'eglot--pre-command-hook nil t)
+ (add-hook 'post-self-insert-hook #'eglot--post-self-insert-hook nil t)
+ (add-hook 'pre-command-hook #'eglot--pre-command-hook nil t)
(eglot--setq-saving xref-prompt-for-identifier nil)
(eglot--setq-saving flymake-diagnostic-functions '(eglot-flymake-backend))
(eglot--setq-saving company-backends '(company-capf))
@@ -1927,21 +1970,21 @@ Use `eglot-managed-p' to determine if current buffer is managed.")
(eldoc-mode 1))
(cl-pushnew (current-buffer) (eglot--managed-buffers (eglot-current-server))))
(t
- (remove-hook 'after-change-functions 'eglot--after-change t)
- (remove-hook 'before-change-functions 'eglot--before-change t)
+ (remove-hook 'after-change-functions #'eglot--after-change t)
+ (remove-hook 'before-change-functions #'eglot--before-change t)
(remove-hook 'kill-buffer-hook #'eglot--managed-mode-off t)
- (remove-hook 'kill-buffer-hook 'eglot--signal-textDocument/didClose t)
- (remove-hook 'before-revert-hook 'eglot--signal-textDocument/didClose t)
- (remove-hook 'after-revert-hook 'eglot--after-revert-hook t)
- (remove-hook 'before-save-hook 'eglot--signal-textDocument/willSave t)
- (remove-hook 'after-save-hook 'eglot--signal-textDocument/didSave t)
- (remove-hook 'xref-backend-functions 'eglot-xref-backend t)
+ (remove-hook 'kill-buffer-hook #'eglot--signal-textDocument/didClose t)
+ (remove-hook 'before-revert-hook #'eglot--signal-textDocument/didClose t)
+ (remove-hook 'after-revert-hook #'eglot--after-revert-hook t)
+ (remove-hook 'before-save-hook #'eglot--signal-textDocument/willSave t)
+ (remove-hook 'after-save-hook #'eglot--signal-textDocument/didSave t)
+ (remove-hook 'xref-backend-functions #'eglot-xref-backend t)
(remove-hook 'completion-at-point-functions #'eglot-completion-at-point t)
(remove-hook 'completion-in-region-mode-hook #'eglot--capf-session-flush t)
(remove-hook 'company-after-completion-hook #'eglot--capf-session-flush t)
(remove-hook 'change-major-mode-hook #'eglot--managed-mode-off t)
- (remove-hook 'post-self-insert-hook 'eglot--post-self-insert-hook t)
- (remove-hook 'pre-command-hook 'eglot--pre-command-hook t)
+ (remove-hook 'post-self-insert-hook #'eglot--post-self-insert-hook t)
+ (remove-hook 'pre-command-hook #'eglot--pre-command-hook t)
(remove-hook 'eldoc-documentation-functions #'eglot-hover-eldoc-function t)
(remove-hook 'eldoc-documentation-functions #'eglot-signature-eldoc-function t)
(cl-loop for (var . saved-binding) in eglot--saved-bindings
@@ -1969,13 +2012,15 @@ Use `eglot-managed-p' to determine if current buffer is managed.")
"Return logical Eglot server for current buffer, nil if none."
(setq eglot--cached-server
(or eglot--cached-server
- (cl-find-if #'eglot--languageId
- (gethash (eglot--current-project)
- eglot--servers-by-project))
- (and eglot-extend-to-xref
- buffer-file-name
- (gethash (expand-file-name buffer-file-name)
- eglot--servers-by-xrefed-file)))))
+ (and (not (eq major-mode 'fundamental-mode)) ; gh#1330
+ (or
+ (cl-find-if #'eglot--languageId
+ (gethash (eglot--current-project)
+ eglot--servers-by-project))
+ (and eglot-extend-to-xref
+ buffer-file-name
+ (gethash (expand-file-name buffer-file-name)
+ eglot--servers-by-xrefed-file)))))))
(defun eglot--current-server-or-lose ()
"Return current logical Eglot server connection or error."
@@ -2006,7 +2051,7 @@ If it is activated, also signal textDocument/didOpen."
(eglot-inlay-hints-mode 1)
(run-hooks 'eglot-managed-mode-hook))))
-(add-hook 'after-change-major-mode-hook 'eglot--maybe-activate-editing-mode)
+(add-hook 'after-change-major-mode-hook #'eglot--maybe-activate-editing-mode)
(defun eglot-clear-status (server)
"Clear the last JSONRPC error for SERVER."
@@ -2046,9 +2091,6 @@ If it is activated, also signal textDocument/didOpen."
(package-delete existing t))
(package-install (cadr (assoc 'eglot package-archive-contents)))))
-;;;###autoload
-(define-obsolete-function-alias 'eglot-update 'eglot-upgrade-eglot "29.1")
-
(easy-menu-define eglot-menu nil "Eglot"
`("Eglot"
;; Commands for getting information and customization.
@@ -2057,47 +2099,47 @@ If it is activated, also signal textDocument/didOpen."
;; xref like commands.
["Find definitions" xref-find-definitions
:help "Find definitions of identifier at point"
- :active (eglot--server-capable :definitionProvider)]
+ :active (eglot-server-capable :definitionProvider)]
["Find references" xref-find-references
:help "Find references to identifier at point"
- :active (eglot--server-capable :referencesProvider)]
+ :active (eglot-server-capable :referencesProvider)]
["Find symbols in workspace (apropos)" xref-find-apropos
:help "Find symbols matching a query"
- :active (eglot--server-capable :workspaceSymbolProvider)]
+ :active (eglot-server-capable :workspaceSymbolProvider)]
["Find declaration" eglot-find-declaration
:help "Find declaration for identifier at point"
- :active (eglot--server-capable :declarationProvider)]
+ :active (eglot-server-capable :declarationProvider)]
["Find implementation" eglot-find-implementation
:help "Find implementation for identifier at point"
- :active (eglot--server-capable :implementationProvider)]
+ :active (eglot-server-capable :implementationProvider)]
["Find type definition" eglot-find-typeDefinition
:help "Find type definition for identifier at point"
- :active (eglot--server-capable :typeDefinitionProvider)]
+ :active (eglot-server-capable :typeDefinitionProvider)]
"--"
;; LSP-related commands (mostly Eglot's own commands).
["Rename symbol" eglot-rename
- :active (eglot--server-capable :renameProvider)]
+ :active (eglot-server-capable :renameProvider)]
["Format buffer" eglot-format-buffer
- :active (eglot--server-capable :documentFormattingProvider)]
+ :active (eglot-server-capable :documentFormattingProvider)]
["Format active region" eglot-format
:active (and (region-active-p)
- (eglot--server-capable :documentRangeFormattingProvider))]
+ (eglot-server-capable :documentRangeFormattingProvider))]
["Show Flymake diagnostics for buffer" flymake-show-buffer-diagnostics]
["Show Flymake diagnostics for project" flymake-show-project-diagnostics]
["Show Eldoc documentation at point" eldoc-doc-buffer]
"--"
["All possible code actions" eglot-code-actions
- :active (eglot--server-capable :codeActionProvider)]
+ :active (eglot-server-capable :codeActionProvider)]
["Organize imports" eglot-code-action-organize-imports
- :visible (eglot--server-capable :codeActionProvider)]
+ :visible (eglot-server-capable :codeActionProvider)]
["Extract" eglot-code-action-extract
- :visible (eglot--server-capable :codeActionProvider)]
+ :visible (eglot-server-capable :codeActionProvider)]
["Inline" eglot-code-action-inline
- :visible (eglot--server-capable :codeActionProvider)]
+ :visible (eglot-server-capable :codeActionProvider)]
["Rewrite" eglot-code-action-rewrite
- :visible (eglot--server-capable :codeActionProvider)]
+ :visible (eglot-server-capable :codeActionProvider)]
["Quickfix" eglot-code-action-quickfix
- :visible (eglot--server-capable :codeActionProvider)]))
+ :visible (eglot-server-capable :codeActionProvider)]))
(easy-menu-define eglot-server-menu nil "Monitor server communication"
'("Debugging the server communication"
@@ -2129,8 +2171,7 @@ Uses THING, FACE, DEFS and PREPEND."
"Compose Eglot's mode-line."
(let* ((server (eglot-current-server))
(nick (and server (eglot-project-nickname server)))
- (pending (and server (hash-table-count
- (jsonrpc--request-continuations server))))
+ (pending (and server (jsonrpc-continuation-count server)))
(last-error (and server (jsonrpc-last-error server))))
(append
`(,(propertize
@@ -2183,12 +2224,12 @@ still unanswered LSP requests to the server\n")))
(put 'eglot-warning 'flymake-category 'flymake-warning)
(put 'eglot-error 'flymake-category 'flymake-error)
-(defalias 'eglot--make-diag 'flymake-make-diagnostic)
-(defalias 'eglot--diag-data 'flymake-diagnostic-data)
+(defalias 'eglot--make-diag #'flymake-make-diagnostic)
+(defalias 'eglot--diag-data #'flymake-diagnostic-data)
(defvar eglot-diagnostics-map
(let ((map (make-sparse-keymap)))
- (define-key map [mouse-2] 'eglot-code-actions-at-mouse)
+ (define-key map [mouse-2] #'eglot-code-actions-at-mouse)
map)
"Keymap active in Eglot-backed Flymake diagnostic overlays.")
@@ -2291,7 +2332,7 @@ still unanswered LSP requests to the server\n")))
(t 'eglot-note)))
(mess (source code message)
(concat source (and code (format " [%s]" code)) ": " message)))
- (if-let* ((path (expand-file-name (eglot--uri-to-path uri)))
+ (if-let* ((path (expand-file-name (eglot-uri-to-path uri)))
(buffer (find-buffer-visiting path)))
(with-current-buffer buffer
(cl-loop
@@ -2303,7 +2344,7 @@ still unanswered LSP requests to the server\n")))
diag-spec
(setq message (mess source code message))
(pcase-let
- ((`(,beg . ,end) (eglot--range-region range)))
+ ((`(,beg . ,end) (eglot-range-region range)))
;; Fallback to `flymake-diag-region' if server
;; botched the range
(when (= beg end)
@@ -2379,7 +2420,7 @@ THINGS are either registrations or unregisterations (sic)."
(cl-defmethod eglot-handle-request
(_server (_method (eql workspace/applyEdit)) &key _label edit)
"Handle server request workspace/applyEdit."
- (eglot--apply-workspace-edit edit eglot-confirm-server-initiated-edits)
+ (eglot--apply-workspace-edit edit last-command)
`(:applied t))
(cl-defmethod eglot-handle-request
@@ -2395,7 +2436,7 @@ THINGS are either registrations or unregisterations (sic)."
(filename))
(cond
((eq external t) (browse-url uri))
- ((file-readable-p (setq filename (eglot--uri-to-path uri)))
+ ((file-readable-p (setq filename (eglot-uri-to-path uri)))
;; Use run-with-timer to avoid nested client requests like the
;; "synchronous imenu" floated in bug#62116 presumably caused by
;; which-func-mode.
@@ -2408,7 +2449,7 @@ THINGS are either registrations or unregisterations (sic)."
(select-frame-set-input-focus (selected-frame)))
((display-buffer (current-buffer))))
(when selection
- (pcase-let ((`(,beg . ,end) (eglot--range-region selection)))
+ (pcase-let ((`(,beg . ,end) (eglot-range-region selection)))
;; FIXME: it is very naughty to use someone else's `--'
;; function, but `xref--goto-char' happens to have
;; exactly the semantics we want vis-a-vis widening.
@@ -2419,7 +2460,7 @@ THINGS are either registrations or unregisterations (sic)."
(defun eglot--TextDocumentIdentifier ()
"Compute TextDocumentIdentifier object for current buffer."
- `(:uri ,(eglot--path-to-uri (or buffer-file-name
+ `(:uri ,(eglot-path-to-uri (or buffer-file-name
(ignore-errors
(buffer-file-name
(buffer-base-buffer)))))))
@@ -2460,7 +2501,7 @@ buffer."
(defun eglot--post-self-insert-hook ()
"Set `eglot--last-inserted-char', maybe call on-type-formatting."
(setq eglot--last-inserted-char last-command-event)
- (let ((ot-provider (eglot--server-capable :documentOnTypeFormattingProvider)))
+ (let ((ot-provider (eglot-server-capable :documentOnTypeFormattingProvider)))
(when (and ot-provider
(ignore-errors ; github#906, some LS's send empty strings
(or (eq eglot--last-inserted-char
@@ -2484,7 +2525,7 @@ buffer."
`(:context
,(if-let (trigger (and (characterp eglot--last-inserted-char)
(cl-find eglot--last-inserted-char
- (eglot--server-capable :completionProvider
+ (eglot-server-capable :completionProvider
:triggerCharacters)
:key (lambda (str) (aref str 0))
:test #'char-equal)))
@@ -2586,7 +2627,7 @@ root of the current project. It should return an object of the
format described above.")
;;;###autoload
-(put 'eglot-workspace-configuration 'safe-local-variable 'listp)
+(put 'eglot-workspace-configuration 'safe-local-variable #'listp)
(defun eglot-show-workspace-configuration (&optional server)
"Dump `eglot-workspace-configuration' as JSON for debugging."
@@ -2608,8 +2649,10 @@ local value of the `eglot-workspace-configuration' variable, else
use the root of SERVER's `eglot--project'."
(let ((val (with-temp-buffer
(setq default-directory
- (if path
- (file-name-directory path)
+ ;; See github#1281
+ (if path (if (file-directory-p path)
+ (file-name-as-directory path)
+ (file-name-directory path))
(project-root (eglot--project server))))
;; Set the major mode to be the first of the managed
;; modes. This is the one the user started eglot in.
@@ -2643,7 +2686,7 @@ When called interactively, use the currently active server"
(mapcar
(eglot--lambda ((ConfigurationItem) scopeUri section)
(cl-loop
- with scope-uri-path = (and scopeUri (eglot--uri-to-path scopeUri))
+ with scope-uri-path = (and scopeUri (eglot-uri-to-path scopeUri))
for (wsection o)
on (eglot--workspace-configuration-plist server scope-uri-path)
by #'cddr
@@ -2659,7 +2702,7 @@ When called interactively, use the currently active server"
"Send textDocument/didChange to server."
(when eglot--recent-changes
(let* ((server (eglot--current-server-or-lose))
- (sync-capability (eglot--server-capable :textDocumentSync))
+ (sync-capability (eglot-server-capable :textDocumentSync))
(sync-kind (if (numberp sync-capability) sync-capability
(plist-get sync-capability :change)))
(full-sync-p (or (eq sync-kind 1)
@@ -2704,9 +2747,9 @@ When called interactively, use the currently active server"
"Maybe send textDocument/willSave to server."
(let ((server (eglot--current-server-or-lose))
(params `(:reason 1 :textDocument ,(eglot--TextDocumentIdentifier))))
- (when (eglot--server-capable :textDocumentSync :willSave)
+ (when (eglot-server-capable :textDocumentSync :willSave)
(jsonrpc-notify server :textDocument/willSave params))
- (when (eglot--server-capable :textDocumentSync :willSaveWaitUntil)
+ (when (eglot-server-capable :textDocumentSync :willSaveWaitUntil)
(ignore-errors
(eglot--apply-text-edits
(eglot--request server :textDocument/willSaveWaitUntil params
@@ -2715,7 +2758,7 @@ When called interactively, use the currently active server"
(defun eglot--signal-textDocument/didSave ()
"Maybe send textDocument/didSave to server."
(eglot--signal-textDocument/didChange)
- (when (eglot--server-capable :textDocumentSync :save)
+ (when (eglot-server-capable :textDocumentSync :save)
(jsonrpc-notify
(eglot--current-server-or-lose)
:textDocument/didSave
@@ -2774,12 +2817,12 @@ may be called multiple times (respecting the protocol of
"Like `xref-make-match' but with LSP's NAME, URI and RANGE.
Try to visit the target file for a richer summary line."
(pcase-let*
- ((file (eglot--uri-to-path uri))
+ ((file (eglot-uri-to-path uri))
(visiting (or (find-buffer-visiting file)
(gethash uri eglot--temp-location-buffers)))
(collect (lambda ()
(eglot--widening
- (pcase-let* ((`(,beg . ,end) (eglot--range-region range))
+ (pcase-let* ((`(,beg . ,end) (eglot-range-region range))
(bol (progn (goto-char beg) (eglot--bol)))
(substring (buffer-substring bol (line-end-position)))
(hi-beg (- beg bol))
@@ -2810,7 +2853,7 @@ Try to visit the target file for a richer summary line."
"Ask for :workspace/symbol on PAT, return list of formatted strings.
If BUFFER, switch to it before."
(with-current-buffer (or buffer (current-buffer))
- (eglot--server-capable-or-lose :workspaceSymbolProvider)
+ (eglot-server-capable-or-lose :workspaceSymbolProvider)
(mapcar
(lambda (wss)
(eglot--dbind ((WorkspaceSymbol) name containerName kind) wss
@@ -2872,7 +2915,7 @@ If BUFFER, switch to it before."
(cl-defun eglot--lsp-xrefs-for-method (method &key extra-params capability)
"Make `xref''s for METHOD, EXTRA-PARAMS, check CAPABILITY."
- (eglot--server-capable-or-lose
+ (eglot-server-capable-or-lose
(or capability
(intern
(format ":%sProvider"
@@ -2936,7 +2979,7 @@ If BUFFER, switch to it before."
:textDocument/references :extra-params `(:context (:includeDeclaration t)))))
(cl-defmethod xref-backend-apropos ((_backend (eql eglot)) pattern)
- (when (eglot--server-capable :workspaceSymbolProvider)
+ (when (eglot-server-capable :workspaceSymbolProvider)
(eglot--collecting-xrefs (collect)
(mapc
(eglot--lambda ((SymbolInformation) name location)
@@ -2974,7 +3017,7 @@ for which LSP on-type-formatting should be requested."
:end (eglot--pos-to-lsp-position end)))))
(t
'(:textDocument/formatting :documentFormattingProvider nil)))))
- (eglot--server-capable-or-lose cap)
+ (eglot-server-capable-or-lose cap)
(eglot--apply-text-edits
(eglot--request
(eglot--current-server-or-lose)
@@ -2996,11 +3039,33 @@ for which LSP on-type-formatting should be requested."
(defun eglot--capf-session-flush (&optional _) (setq eglot--capf-session :none))
+(defun eglot--dumb-flex (pat comp ignorecase)
+ "Return destructively fontified COMP iff PAT matches it."
+ (cl-loop with lcomp = (length comp)
+ with case-fold-search = ignorecase
+ initially (remove-list-of-text-properties 0 lcomp '(face) comp)
+ for x across pat
+ for i = (cl-loop for j from (if i (1+ i) 0) below lcomp
+ when (char-equal x (aref comp j)) return j)
+ unless i do (cl-return nil)
+ ;; FIXME: could do much better here and coalesce intervals
+ do (add-face-text-property i (1+ i) 'completions-common-part
+ nil comp)
+ finally (cl-return comp)))
+
+(defun eglot--dumb-allc (pat table pred _point) (funcall table pat pred t))
+
+(add-to-list 'completion-category-defaults '(eglot-capf (styles eglot--dumb-flex)))
+(add-to-list 'completion-styles-alist '(eglot--dumb-flex ignore eglot--dumb-allc))
+
(defun eglot-completion-at-point ()
"Eglot's `completion-at-point' function."
;; Commit logs for this function help understand what's going on.
- (when-let (completion-capability (eglot--server-capable :completionProvider))
+ (when-let (completion-capability (eglot-server-capable :completionProvider))
(let* ((server (eglot--current-server-or-lose))
+ (bounds (or (bounds-of-thing-at-point 'symbol)
+ (cons (point) (point))))
+ (bounds-string (buffer-substring (car bounds) (cdr bounds)))
(sort-completions
(lambda (completions)
(cl-sort completions
@@ -3009,10 +3074,9 @@ for which LSP on-type-formatting should be requested."
(plist-get
(get-text-property 0 'eglot--lsp-item c)
:sortText)))))
- (metadata `(metadata (category . eglot)
+ (metadata `(metadata (category . eglot-capf)
(display-sort-function . ,sort-completions)))
(local-cache :none)
- (bounds (bounds-of-thing-at-point 'symbol))
(orig-pos (point))
(resolved (make-hash-table))
(proxies
@@ -3028,9 +3092,7 @@ for which LSP on-type-formatting should be requested."
(cachep (and (listp resp) items
eglot-cache-session-completions
(eq (plist-get resp :isIncomplete) :json-false)))
- (bounds (or bounds
- (cons (point) (point))))
- (proxies
+ (retval
(mapcar
(jsonrpc-lambda
(&rest item &key label insertText insertTextFormat
@@ -3053,8 +3115,8 @@ for which LSP on-type-formatting should be requested."
items)))
;; (trace-values "Requested" (length proxies) cachep bounds)
(setq eglot--capf-session
- (if cachep (list bounds proxies resolved orig-pos) :none))
- (setq local-cache proxies)))))
+ (if cachep (list bounds retval resolved orig-pos) :none))
+ (setq local-cache retval)))))
(resolve-maybe
;; Maybe completion/resolve JSON object `lsp-comp' into
;; another JSON object, if at all possible. Otherwise,
@@ -3062,13 +3124,12 @@ for which LSP on-type-formatting should be requested."
(lambda (lsp-comp)
(or (gethash lsp-comp resolved)
(setf (gethash lsp-comp resolved)
- (if (and (eglot--server-capable :completionProvider
+ (if (and (eglot-server-capable :completionProvider
:resolveProvider)
(plist-get lsp-comp :data))
(eglot--request server :completionItem/resolve
lsp-comp :cancel-on-input t)
lsp-comp))))))
- (unless bounds (setq bounds (cons (point) (point))))
(when (and (consp eglot--capf-session)
(= (car bounds) (car (nth 0 eglot--capf-session)))
(>= (cdr bounds) (cdr (nth 0 eglot--capf-session))))
@@ -3080,24 +3141,26 @@ for which LSP on-type-formatting should be requested."
(list
(car bounds)
(cdr bounds)
- (lambda (probe pred action)
+ (lambda (pattern pred action)
(cond
((eq action 'metadata) metadata) ; metadata
((eq action 'lambda) ; test-completion
- (test-completion probe (funcall proxies)))
+ (test-completion pattern (funcall proxies)))
((eq (car-safe action) 'boundaries) nil) ; boundaries
((null action) ; try-completion
- (try-completion probe (funcall proxies)))
+ (try-completion pattern (funcall proxies)))
((eq action t) ; all-completions
- (all-completions
- ""
- (funcall proxies)
- (lambda (proxy)
- (let* ((item (get-text-property 0 'eglot--lsp-item proxy))
- (filterText (plist-get item :filterText)))
- (and (or (null pred) (funcall pred proxy))
- (string-prefix-p
- probe (or filterText proxy) completion-ignore-case))))))))
+ (let ((comps (funcall proxies)))
+ (dolist (c comps) (eglot--dumb-flex pattern c t))
+ (all-completions
+ ""
+ comps
+ (lambda (proxy)
+ (let* ((item (get-text-property 0 'eglot--lsp-item proxy))
+ (filterText (plist-get item :filterText)))
+ (and (or (null pred) (funcall pred proxy))
+ (eglot--dumb-flex
+ pattern (or filterText proxy) completion-ignore-case)))))))))
:annotation-function
(lambda (proxy)
(eglot--dbind ((CompletionItem) detail kind)
@@ -3185,12 +3248,13 @@ for which LSP on-type-formatting should be requested."
;; Revert buffer back to state when the edit
;; was obtained from server. If a `proxy'
;; "bar" was obtained from a buffer with
- ;; "foo.b", the LSP edit applies to that'
+ ;; "foo.b", the LSP edit applies to that
;; state, _not_ the current "foo.bar".
(delete-region orig-pos (point))
+ (insert (substring bounds-string (- orig-pos (car bounds))))
(eglot--dbind ((TextEdit) range newText) textEdit
(pcase-let ((`(,beg . ,end)
- (eglot--range-region range)))
+ (eglot-range-region range)))
(delete-region beg end)
(goto-char beg)
(funcall (or snippet-fn #'insert) newText))))
@@ -3273,7 +3337,7 @@ for which LSP on-type-formatting should be requested."
(defun eglot-signature-eldoc-function (cb)
"A member of `eldoc-documentation-functions', for signatures."
- (when (eglot--server-capable :signatureHelpProvider)
+ (when (eglot-server-capable :signatureHelpProvider)
(let ((buf (current-buffer)))
(jsonrpc-async-request
(eglot--current-server-or-lose)
@@ -3297,7 +3361,7 @@ for which LSP on-type-formatting should be requested."
(defun eglot-hover-eldoc-function (cb)
"A member of `eldoc-documentation-functions', for hover."
- (when (eglot--server-capable :hoverProvider)
+ (when (eglot-server-capable :hoverProvider)
(let ((buf (current-buffer)))
(jsonrpc-async-request
(eglot--current-server-or-lose)
@@ -3319,7 +3383,7 @@ for which LSP on-type-formatting should be requested."
;; FIXME: Obviously, this is just piggy backing on eldoc's calls for
;; convenience, as shown by the fact that we just ignore cb.
(let ((buf (current-buffer)))
- (when (eglot--server-capable :documentHighlightProvider)
+ (when (eglot-server-capable :documentHighlightProvider)
(jsonrpc-async-request
(eglot--current-server-or-lose)
:textDocument/documentHighlight (eglot--TextDocumentPositionParams)
@@ -3331,7 +3395,7 @@ for which LSP on-type-formatting should be requested."
(mapcar
(eglot--lambda ((DocumentHighlight) range)
(pcase-let ((`(,beg . ,end)
- (eglot--range-region range)))
+ (eglot-range-region range)))
(let ((ov (make-overlay beg end)))
(overlay-put ov 'face 'eglot-highlight-symbol-face)
(overlay-put ov 'modification-hooks
@@ -3351,7 +3415,7 @@ for which LSP on-type-formatting should be requested."
(pcase-lambda (`(,container . ,objs))
(let ((elems (mapcar
(eglot--lambda ((SymbolInformation) kind name location)
- (let ((reg (eglot--range-region
+ (let ((reg (eglot-range-region
(plist-get location :range)))
(kind (alist-get kind eglot--symbol-kind-names)))
(cons (propertize name
@@ -3367,7 +3431,7 @@ for which LSP on-type-formatting should be requested."
(defun eglot--imenu-DocumentSymbol (res)
"Compute `imenu--index-alist' for RES vector of DocumentSymbol."
(cl-labels ((dfs (&key name children range kind &allow-other-keys)
- (let* ((reg (eglot--range-region range))
+ (let* ((reg (eglot-range-region range))
(kind (alist-get kind eglot--symbol-kind-names))
(name (propertize name
'breadcrumb-region reg
@@ -3381,7 +3445,7 @@ for which LSP on-type-formatting should be requested."
(cl-defun eglot-imenu ()
"Eglot's `imenu-create-index-function'.
Returns a list as described in docstring of `imenu--index-alist'."
- (unless (eglot--server-capable :documentSymbolProvider)
+ (unless (eglot-server-capable :documentSymbolProvider)
(cl-return-from eglot-imenu))
(let* ((res (eglot--request (eglot--current-server-or-lose)
:textDocument/documentSymbol
@@ -3423,39 +3487,106 @@ If SILENT, don't echo progress in mode-line."
(when reporter
(eglot--reporter-update reporter (cl-incf done))))))))
(mapcar (eglot--lambda ((TextEdit) range newText)
- (cons newText (eglot--range-region range 'markers)))
+ (cons newText (eglot-range-region range 'markers)))
(reverse edits)))
(undo-amalgamate-change-group change-group)
(when reporter
(progress-reporter-done reporter)))))
-(defun eglot--apply-workspace-edit (wedit &optional confirm)
- "Apply the workspace edit WEDIT. If CONFIRM, ask user first."
+(defun eglot--confirm-server-edits (origin _prepared)
+ "Helper for `eglot--apply-workspace-edit.
+ORIGIN is a symbol designating a command. Reads the
+`eglot-confirm-server-edits' user option and returns a symbol
+like `diff', `summary' or nil."
+ (let (v)
+ (cond ((symbolp eglot-confirm-server-edits) eglot-confirm-server-edits)
+ ((setq v (assoc origin eglot-confirm-server-edits)) (cdr v))
+ ((setq v (assoc t eglot-confirm-server-edits)) (cdr v)))))
+
+(defun eglot--propose-changes-as-diff (prepared)
+ "Helper for `eglot--apply-workspace-edit'.
+Goal is to popup a `diff-mode' buffer containing all the changes
+of PREPARED, ready to apply with C-c C-a. PREPARED is a
+list ((FILENAME EDITS VERSION)...)."
+ (with-current-buffer (get-buffer-create "*EGLOT proposed server changes*")
+ (buffer-disable-undo (current-buffer))
+ (let ((inhibit-read-only t)
+ (target (current-buffer)))
+ (diff-mode)
+ (erase-buffer)
+ (pcase-dolist (`(,path ,edits ,_) prepared)
+ (with-temp-buffer
+ (let* ((diff (current-buffer))
+ (existing-buf (find-buffer-visiting path))
+ (existing-buf-label (prin1-to-string existing-buf)))
+ (with-temp-buffer
+ (if existing-buf
+ (insert-buffer-substring existing-buf)
+ (insert-file-contents path))
+ (eglot--apply-text-edits edits nil t)
+ (diff-no-select (or existing-buf path) (current-buffer) nil t diff)
+ (when existing-buf
+ ;; Here we have to pretend the label of the unsaved
+ ;; buffer is the actual file, just so that we can
+ ;; diff-apply without troubles. If there's a better
+ ;; way, it probably involves changes to `diff.el'.
+ (with-current-buffer diff
+ (goto-char (point-min))
+ (while (search-forward existing-buf-label nil t)
+ (replace-match (buffer-file-name existing-buf))))))
+ (with-current-buffer target
+ (insert-buffer-substring diff))))))
+ (setq-local buffer-read-only t)
+ (buffer-enable-undo (current-buffer))
+ (goto-char (point-min))
+ (pop-to-buffer (current-buffer))
+ (font-lock-ensure)))
+
+(defun eglot--apply-workspace-edit (wedit origin)
+ "Apply (or offer to apply) the workspace edit WEDIT.
+ORIGIN is a symbol designating the command that originated this
+edit proposed by the server."
(eglot--dbind ((WorkspaceEdit) changes documentChanges) wedit
(let ((prepared
(mapcar (eglot--lambda ((TextDocumentEdit) textDocument edits)
(eglot--dbind ((VersionedTextDocumentIdentifier) uri version)
textDocument
- (list (eglot--uri-to-path uri) edits version)))
+ (list (eglot-uri-to-path uri) edits version)))
documentChanges)))
(unless (and changes documentChanges)
;; We don't want double edits, and some servers send both
;; changes and documentChanges. This unless ensures that we
;; prefer documentChanges over changes.
(cl-loop for (uri edits) on changes by #'cddr
- do (push (list (eglot--uri-to-path uri) edits) prepared)))
- (if (or confirm
- (cl-notevery #'find-buffer-visiting
- (mapcar #'car prepared)))
- (unless (y-or-n-p
- (format "[eglot] Server wants to edit:\n %s\n Proceed? "
- (mapconcat #'identity (mapcar #'car prepared) "\n ")))
- (jsonrpc-error "User canceled server edit")))
- (cl-loop for edit in prepared
- for (path edits version) = edit
- do (with-current-buffer (find-file-noselect path)
- (eglot--apply-text-edits edits version))
- finally (eldoc) (eglot--message "Edit successful!")))))
+ do (push (list (eglot-uri-to-path uri) edits) prepared)))
+ (cl-flet ((notevery-visited-p ()
+ (cl-notevery #'find-buffer-visiting
+ (mapcar #'car prepared)))
+ (accept-p ()
+ (y-or-n-p
+ (format "[eglot] Server wants to edit:\n%sProceed? "
+ (cl-loop
+ for (f eds _) in prepared
+ concat (format
+ " %s (%d change%s)\n"
+ f (length eds)
+ (if (> (length eds) 1) "s" ""))))))
+ (apply ()
+ (cl-loop for edit in prepared
+ for (path edits version) = edit
+ do (with-current-buffer (find-file-noselect path)
+ (eglot--apply-text-edits edits version))
+ finally (eldoc) (eglot--message "Edit successful!"))))
+ (let ((decision (eglot--confirm-server-edits origin prepared)))
+ (cond
+ ((or (eq decision 'diff)
+ (and (eq decision 'maybe-diff) (notevery-visited-p)))
+ (eglot--propose-changes-as-diff prepared))
+ ((or (memq decision '(t summary))
+ (and (eq decision 'maybe-summary) (notevery-visited-p)))
+ (when (accept-p) (apply)))
+ (t
+ (apply))))))))
(defun eglot-rename (newname)
"Rename the current symbol to NEWNAME."
@@ -3465,18 +3596,25 @@ If SILENT, don't echo progress in mode-line."
"unknown symbol"))
nil nil nil nil
(symbol-name (symbol-at-point)))))
- (eglot--server-capable-or-lose :renameProvider)
+ (eglot-server-capable-or-lose :renameProvider)
(eglot--apply-workspace-edit
(eglot--request (eglot--current-server-or-lose)
:textDocument/rename `(,@(eglot--TextDocumentPositionParams)
:newName ,newname))
- current-prefix-arg))
-
-(defun eglot--region-bounds ()
- "Region bounds if active, else bounds of things at point."
- (if (use-region-p) `(,(region-beginning) ,(region-end))
- (let ((boftap (bounds-of-thing-at-point 'sexp)))
- (list (car boftap) (cdr boftap)))))
+ this-command))
+
+(defun eglot--code-action-bounds ()
+ "Calculate appropriate bounds depending on region and point."
+ (let (diags)
+ (cond ((use-region-p) `(,(region-beginning) ,(region-end)))
+ ((setq diags (flymake-diagnostics (point)))
+ (cl-loop for d in diags
+ minimizing (flymake-diagnostic-beg d) into beg
+ maximizing (flymake-diagnostic-end d) into end
+ finally (cl-return (list beg end))))
+ (t
+ (let ((boftap (bounds-of-thing-at-point 'sexp)))
+ (list (car boftap) (cdr boftap)))))))
(defun eglot-code-actions (beg &optional end action-kind interactive)
"Find LSP code actions of type ACTION-KIND between BEG and END.
@@ -3486,13 +3624,13 @@ Interactively, default BEG and END to region's bounds else BEG is
point and END is nil, which results in a request for code actions
at point. With prefix argument, prompt for ACTION-KIND."
(interactive
- `(,@(eglot--region-bounds)
+ `(,@(eglot--code-action-bounds)
,(and current-prefix-arg
(completing-read "[eglot] Action kind: "
'("quickfix" "refactor.extract" "refactor.inline"
"refactor.rewrite" "source.organizeImports")))
t))
- (eglot--server-capable-or-lose :codeActionProvider)
+ (eglot-server-capable-or-lose :codeActionProvider)
(let* ((server (eglot--current-server-or-lose))
(actions
(eglot--request
@@ -3511,7 +3649,8 @@ at point. With prefix argument, prompt for ACTION-KIND."
;; Redo filtering, in case the `:only' didn't go through.
(actions (cl-loop for a across actions
when (or (not action-kind)
- (equal action-kind (plist-get a :kind)))
+ ;; github#847
+ (string-prefix-p action-kind (plist-get a :kind)))
collect a)))
(if interactive
(eglot--read-execute-code-action actions server action-kind)
@@ -3549,7 +3688,7 @@ at point. With prefix argument, prompt for ACTION-KIND."
"Define NAME to execute KIND code action."
`(defun ,name (beg &optional end)
,(format "Execute `%s' code actions between BEG and END." kind)
- (interactive (eglot--region-bounds))
+ (interactive (eglot--code-action-bounds))
(eglot-code-actions beg end ,kind t)))
(eglot--code-action eglot-code-action-organize-imports "source.organizeImports")
@@ -3592,7 +3731,7 @@ at point. With prefix argument, prompt for ACTION-KIND."
(funcall glob file))))
(jsonrpc-notify
server :workspace/didChangeWatchedFiles
- `(:changes ,(vector `(:uri ,(eglot--path-to-uri file)
+ `(:changes ,(vector `(:uri ,(eglot-path-to-uri file)
:type ,action-type))))
(when (and (eq action 'created)
(file-directory-p file))
@@ -3859,7 +3998,7 @@ If NOERROR, return predicate, else erroring function."
"Minor mode for annotating buffers with LSP server's inlay hints."
:global nil
(cond (eglot-inlay-hints-mode
- (if (eglot--server-capable :inlayHintProvider)
+ (if (eglot-server-capable :inlayHintProvider)
(jit-lock-register #'eglot--update-hints 'contextual)
(eglot-inlay-hints-mode -1)))
(t
@@ -3886,11 +4025,7 @@ If NOERROR, return predicate, else erroring function."
"https://github.com/joaotavora/eglot/issues/%s"
"https://debbugs.gnu.org/%s")
(match-string 3))))
-;;; Obsolete
-;;;
-(make-obsolete-variable 'eglot--managed-mode-hook
- 'eglot-managed-mode-hook "1.6")
(provide 'eglot)
diff --git a/lisp/progmodes/elisp-mode.el b/lisp/progmodes/elisp-mode.el
index 3e1803fcc98..00910fb67c7 100644
--- a/lisp/progmodes/elisp-mode.el
+++ b/lisp/progmodes/elisp-mode.el
@@ -1,6 +1,6 @@
;;; elisp-mode.el --- Emacs Lisp mode -*- lexical-binding:t -*-
-;; Copyright (C) 1985-1986, 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1985-1986, 1999-2024 Free Software Foundation, Inc.
;; Maintainer: emacs-devel@gnu.org
;; Keywords: lisp, languages
@@ -85,10 +85,10 @@ All commands in `lisp-mode-shared-map' are inherited by this map."
["Byte-recompile Directory..." byte-recompile-directory
:help "Recompile every `.el' file in DIRECTORY that needs recompilation"]
["Native-compile This File" emacs-lisp-native-compile
- :help "Compile the current file containing the current buffer to native code"
+ :help "Compile this buffer's file to native code"
:active (native-comp-available-p)]
["Native-compile and Load" emacs-lisp-native-compile-and-load
- :help "Compile the current file to native code, then load compiled native code"
+ :help "Compile this buffer's file to native code, then load compiled native code"
:active (native-comp-available-p)]
["Disassemble Byte Compiled Object..." disassemble
:help "Print disassembled code for OBJECT in a buffer"]
@@ -224,7 +224,9 @@ All commands in `lisp-mode-shared-map' are inherited by this map."
(declare-function comp-write-bytecode-file "comp")
(defun emacs-lisp-native-compile ()
- "Native-compile synchronously the current file (if it has changed)."
+ "Native-compile the current buffer's file (if it has changed).
+This invokes a synchronous native-compilation of the file that is
+visited by the current buffer."
(interactive nil emacs-lisp-mode)
(emacs-lisp--before-compile-buffer)
(let* ((byte+native-compile t)
@@ -234,12 +236,14 @@ All commands in `lisp-mode-shared-map' are inherited by this map."
(comp-write-bytecode-file eln))))
(defun emacs-lisp-native-compile-and-load ()
- "Native-compile synchronously the current file (if it has changed).
-Load the compiled code when finished.
+ "Native-compile the current buffer's file (if it has changed), then load it.
+This invokes a synchronous native-compilation of the file that is
+visited by the current buffer, then loads the compiled native code
+when the compilation is finished.
Use `emacs-lisp-byte-compile-and-load' in combination with
`native-comp-jit-compilation' set to t to achieve asynchronous
-native compilation."
+native compilation of the current buffer's file."
(interactive nil emacs-lisp-mode)
(when-let ((byte-file (emacs-lisp-native-compile)))
(load (file-name-sans-extension byte-file))))
@@ -429,6 +433,14 @@ be used instead.
(defvar warning-minimum-log-level)
+(defvar elisp--local-macroenv
+ `((cl-eval-when . ,(lambda (&rest args) `(progn . ,(cdr args))))
+ (eval-when-compile . ,(lambda (&rest args) `(progn . ,args)))
+ (eval-and-compile . ,(lambda (&rest args) `(progn . ,args))))
+ "Environment to use while tentatively expanding macros.
+This is used to try and avoid the most egregious problems linked to the
+use of `macroexpand-all' as a way to find the \"underlying raw code\".")
+
(defun elisp--local-variables ()
"Return a list of locally let-bound variables at point."
(save-excursion
@@ -444,16 +456,22 @@ be used instead.
(car (read-from-string
(concat txt "elisp--witness--lisp" closer)))
((invalid-read-syntax end-of-file) nil)))
- (macroexpand-advice (lambda (expander form &rest args)
- (condition-case nil
- (apply expander form args)
- (error form))))
+ (macroexpand-advice
+ (lambda (expander form &rest args)
+ (condition-case err
+ (apply expander form args)
+ (error
+ (message "Ignoring macroexpansion error: %S" err) form))))
(sexp
(unwind-protect
- (let ((warning-minimum-log-level :emergency))
- (advice-add 'macroexpand :around macroexpand-advice)
- (macroexpand-all sexp))
- (advice-remove 'macroexpand macroexpand-advice)))
+ ;; Silence any macro expansion errors when
+ ;; attempting completion at point (bug#58148).
+ (let ((inhibit-message t)
+ (macroexp-inhibit-compiler-macros t)
+ (warning-minimum-log-level :emergency))
+ (advice-add 'macroexpand-1 :around macroexpand-advice)
+ (macroexpand-all sexp elisp--local-macroenv))
+ (advice-remove 'macroexpand-1 macroexpand-advice)))
(vars (elisp--local-variables-1 nil sexp)))
(delq nil
(mapcar (lambda (var)
@@ -1380,9 +1398,9 @@ BEG and END are the start and end of the output in current buffer.
VALUE is the Lisp value printed, ALT1 and ALT2 are strings for the
alternative printed representations that can be displayed."
(let ((map (make-sparse-keymap)))
- (define-key map "\C-m" 'elisp-last-sexp-toggle-display)
- (define-key map [down-mouse-2] 'mouse-set-point)
- (define-key map [mouse-2] 'elisp-last-sexp-toggle-display)
+ (define-key map "\C-m" #'elisp-last-sexp-toggle-display)
+ (define-key map [down-mouse-2] #'mouse-set-point)
+ (define-key map [mouse-2] #'elisp-last-sexp-toggle-display)
(add-text-properties
beg end
`(printed-value (,value ,alt1 ,alt2)
@@ -1439,7 +1457,7 @@ If CHAR is not a character, return nil."
(lambda (modif)
(cond ((eq modif 'super) "\\s-")
(t (string ?\\ (upcase (aref (symbol-name modif) 0)) ?-))))
- mods "")
+ mods)
(cond
((memq c '(?\; ?\( ?\) ?\{ ?\} ?\[ ?\] ?\" ?\' ?\\)) (string ?\\ c))
((eq c 127) "\\C-?")
@@ -1515,7 +1533,7 @@ If CHAR is not a character, return nil."
`(call-interactively
(lambda (&rest args) ,expr args))))
expr)))))
-(define-obsolete-function-alias 'preceding-sexp 'elisp--preceding-sexp "25.1")
+(define-obsolete-function-alias 'preceding-sexp #'elisp--preceding-sexp "25.1")
(defun elisp--eval-last-sexp (eval-last-sexp-arg-internal)
"Evaluate sexp before point; print value in the echo area.
@@ -1643,9 +1661,8 @@ Reinitialize the face according to the `defface' specification."
;; The second arg is an expression that evaluates to
;; an expression. The second evaluation is the one
;; normally performed not by normal execution but by
- ;; custom-initialize-set (for example), which does not
- ;; use lexical-binding.
- (eval (eval (nth 2 form) lexical-binding))))
+ ;; custom-initialize-set (for example).
+ (eval (eval (nth 2 form) lexical-binding) t)))
form)
;; `defface' is macroexpanded to `custom-declare-face'.
((eq (car form) 'custom-declare-face)
@@ -1785,7 +1802,7 @@ Elements are as follows:
(or (progn (elisp-eldoc-var-docstring callback) str)
(progn (elisp-eldoc-funcall callback) str))))
-(defalias 'elisp-eldoc-documentation-function 'elisp--documentation-one-liner
+(defalias 'elisp-eldoc-documentation-function #'elisp--documentation-one-liner
"Return Elisp documentation for the thing at point as one-line string.
This is meant as a backward compatibility aide to the \"old\"
Elisp eldoc behavior. Consider variable docstrings and function
diff --git a/lisp/progmodes/elixir-ts-mode.el b/lisp/progmodes/elixir-ts-mode.el
index 7175fe4bff8..b493195eedd 100644
--- a/lisp/progmodes/elixir-ts-mode.el
+++ b/lisp/progmodes/elixir-ts-mode.el
@@ -1,6 +1,6 @@
;;; elixir-ts-mode.el --- Major mode for Elixir with tree-sitter support -*- lexical-binding: t; -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;; Author: Wilhelm H Kirschbaum <wkirschbaum@gmail.com>
;; Created: November 2022
@@ -53,6 +53,7 @@
(declare-function treesit-parser-language "treesit.c")
(declare-function treesit-parser-included-ranges "treesit.c")
(declare-function treesit-parser-list "treesit.c")
+(declare-function treesit-node-p "treesit.c")
(declare-function treesit-node-parent "treesit.c")
(declare-function treesit-node-start "treesit.c")
(declare-function treesit-node-end "treesit.c")
@@ -73,17 +74,47 @@
:safe 'integerp
:group 'elixir-ts)
-(defface elixir-ts-font-comment-doc-identifier-face
+;; 'define-derived-mode' doesn't expose the generated mode hook
+;; variable to Custom, because we are not smart enough to provide the
+;; ':options' for hook variables. Also, some packages modify hook
+;; variables. The below is done because users of this mode explicitly
+;; requested the hook to be customizable via Custom.
+(defcustom elixir-ts-mode-hook nil
+ "Hook run after entering `elixir-ts-mode'."
+ :type 'hook
+ :options '(eglot-ensure)
+ :group 'elixir-ts
+ :version "30.1")
+
+(defface elixir-ts-comment-doc-identifier
'((t (:inherit font-lock-doc-face)))
- "Face used for @comment.doc tags in Elixir files.")
+ "Face used for doc identifiers in Elixir files."
+ :group 'elixir-ts)
-(defface elixir-ts-font-comment-doc-attribute-face
+(defface elixir-ts-comment-doc-attribute
'((t (:inherit font-lock-doc-face)))
- "Face used for @comment.doc.__attribute__ tags in Elixir files.")
+ "Face used for doc attributes in Elixir files."
+ :group 'elixir-ts)
-(defface elixir-ts-font-sigil-name-face
+(defface elixir-ts-sigil-name
'((t (:inherit font-lock-string-face)))
- "Face used for @__name__ tags in Elixir files.")
+ "Face used for sigils in Elixir files."
+ :group 'elixir-ts)
+
+(defface elixir-ts-atom
+ '((t (:inherit font-lock-constant-face)))
+ "Face used for atoms in Elixir files."
+ :group 'elixir-ts)
+
+(defface elixir-ts-keyword-key
+ '((t (:inherit elixir-ts-atom)))
+ "Face used for keyword keys in Elixir files."
+ :group 'elixir-ts)
+
+(defface elixir-ts-attribute
+ '((t (:inherit font-lock-preprocessor-face)))
+ "Face used for attributes in Elixir files."
+ :group 'elixir-ts)
(defconst elixir-ts--sexp-regexp
(rx bol
@@ -101,7 +132,10 @@
"defoverridable" "defp" "defprotocol" "defstruct"))
(defconst elixir-ts--definition-keywords-re
- (concat "^" (regexp-opt elixir-ts--definition-keywords) "$"))
+ (concat "^" (regexp-opt
+ (append elixir-ts--definition-keywords
+ elixir-ts--test-definition-keywords))
+ "$"))
(defconst elixir-ts--kernel-keywords
'("alias" "case" "cond" "else" "for" "if" "import" "quote"
@@ -312,56 +346,82 @@
((parent-is "^catch_block$") parent ,offset)
((parent-is "^keywords$") parent-bol 0)
((node-is "^call$") parent-bol ,offset)
- ((node-is "^comment$") parent-bol ,offset)))))
+ ((node-is "^comment$") parent-bol ,offset)
+ ((node-is "\"\"\"") parent-bol 0)
+ ;; Handle quoted_content indentation on the last
+ ;; line before the closing \"\"\", where it might
+ ;; see it as no-node outside a HEEx tag.
+ (no-node (lambda (_n _p _bol)
+ (treesit-node-start
+ (treesit-node-parent
+ (treesit-node-at (point) 'elixir))))
+ 0)))))
(defvar elixir-ts--font-lock-settings
(treesit-font-lock-rules
:language 'elixir
- :feature 'elixir-comment
- '((comment) @font-lock-comment-face)
-
- :language 'elixir
- :feature 'elixir-string
- :override t
- '([(string) (charlist)] @font-lock-string-face)
-
+ :feature 'elixir-function-name
+ `((call target: (identifier) @target-identifier
+ (arguments (identifier) @font-lock-function-name-face)
+ (:match ,elixir-ts--definition-keywords-re @target-identifier))
+ (call target: (identifier) @target-identifier
+ (arguments
+ (call target: (identifier) @font-lock-function-name-face))
+ (:match ,elixir-ts--definition-keywords-re @target-identifier))
+ (call target: (identifier) @target-identifier
+ (arguments
+ (binary_operator
+ left: (call target: (identifier) @font-lock-function-name-face)))
+ (:match ,elixir-ts--definition-keywords-re @target-identifier))
+ (call target: (identifier) @target-identifier
+ (arguments (identifier) @font-lock-function-name-face)
+ (do_block)
+ (:match ,elixir-ts--definition-keywords-re @target-identifier))
+ (call target: (identifier) @target-identifier
+ (arguments
+ (call target: (identifier) @font-lock-function-name-face))
+ (do_block)
+ (:match ,elixir-ts--definition-keywords-re @target-identifier))
+ (call target: (identifier) @target-identifier
+ (arguments
+ (binary_operator
+ left: (call target: (identifier) @font-lock-function-name-face)))
+ (do_block)
+ (:match ,elixir-ts--definition-keywords-re @target-identifier))
+ (unary_operator
+ operator: "@"
+ (call (arguments
+ (binary_operator
+ left: (call target: (identifier) @font-lock-function-name-face))))))
+
+ ;; A function definition like "def _foo" is valid, but we should
+ ;; not apply the comment-face unless its a non-function identifier, so
+ ;; the comment matches has to be after the function matches.
:language 'elixir
- :feature 'elixir-string-interpolation
- :override t
- '((string
- [
- quoted_end: _ @font-lock-string-face
- quoted_start: _ @font-lock-string-face
- (quoted_content) @font-lock-string-face
- (interpolation
- "#{" @font-lock-regexp-grouping-backslash "}"
- @font-lock-regexp-grouping-backslash)
- ])
- (charlist
- [
- quoted_end: _ @font-lock-string-face
- quoted_start: _ @font-lock-string-face
- (quoted_content) @font-lock-string-face
- (interpolation
- "#{" @font-lock-regexp-grouping-backslash "}"
- @font-lock-regexp-grouping-backslash)
- ]))
+ :feature 'elixir-comment
+ '((comment) @font-lock-comment-face
+ ((identifier) @font-lock-comment-face
+ (:match "^_[a-z]\\|^_$" @font-lock-comment-face)))
:language 'elixir
- :feature 'elixir-keyword
- `(,elixir-ts--reserved-keywords-vector
- @font-lock-keyword-face
- (binary_operator
- operator: _ @font-lock-keyword-face
- (:match ,elixir-ts--reserved-keywords-re @font-lock-keyword-face)))
+ :feature 'elixir-variable
+ `((call target: (identifier)
+ (arguments
+ (binary_operator
+ (call target: (identifier)
+ (arguments ((identifier) @font-lock-variable-use-face))))))
+ (call target: (identifier)
+ (arguments
+ (call target: (identifier)
+ (arguments ((identifier)) @font-lock-variable-use-face))))
+ (dot left: (identifier) @font-lock-variable-use-face operator: "." ))
:language 'elixir
:feature 'elixir-doc
- :override t
`((unary_operator
- operator: "@" @elixir-ts-font-comment-doc-attribute-face
+ operator: "@" @elixir-ts-comment-doc-attribute
operand: (call
- target: (identifier) @elixir-ts-font-comment-doc-identifier-face
+ target: (identifier) @elixir-ts-comment-doc-identifier
;; Arguments can be optional, so adding another
;; entry without arguments.
;; If we don't handle then we don't apply font
@@ -373,110 +433,128 @@
(charlist) @font-lock-doc-face
(sigil) @font-lock-doc-face
(boolean) @font-lock-doc-face
+ (keywords) @font-lock-doc-face
]))
(:match ,elixir-ts--doc-keywords-re
- @elixir-ts-font-comment-doc-identifier-face))
+ @elixir-ts-comment-doc-identifier))
(unary_operator
- operator: "@" @elixir-ts-font-comment-doc-attribute-face
+ operator: "@" @elixir-ts-comment-doc-attribute
operand: (call
- target: (identifier) @elixir-ts-font-comment-doc-identifier-face)
+ target: (identifier) @elixir-ts-comment-doc-identifier)
(:match ,elixir-ts--doc-keywords-re
- @elixir-ts-font-comment-doc-identifier-face)))
+ @elixir-ts-comment-doc-identifier)))
:language 'elixir
- :feature 'elixir-unary-operator
- `((unary_operator operator: "@" @font-lock-preprocessor-face
- operand: [
- (identifier) @font-lock-preprocessor-face
- (call target: (identifier)
- @font-lock-preprocessor-face)
- (boolean) @font-lock-preprocessor-face
- (nil) @font-lock-preprocessor-face
- ])
+ :feature 'elixir-string
+ '((interpolation
+ "#{" @font-lock-escape-face
+ "}" @font-lock-escape-face)
+ (string (quoted_content) @font-lock-string-face)
+ (quoted_keyword (quoted_content) @font-lock-string-face)
+ (charlist (quoted_content) @font-lock-string-face)
+ ["\"" "'" "\"\"\""] @font-lock-string-face)
- (unary_operator operator: "&") @font-lock-function-name-face
- (operator_identifier) @font-lock-operator-face)
+ :language 'elixir
+ :feature 'elixir-sigil
+ `((sigil
+ (sigil_name) @elixir-ts-sigil-name
+ (quoted_content) @font-lock-string-face
+ ;; HEEx and Surface templates will handled by
+ ;; heex-ts-mode if its available.
+ (:match "^[^HF]$" @elixir-ts-sigil-name))
+ @font-lock-string-face
+ (sigil
+ (sigil_name) @font-lock-regexp-face
+ (:match "^[rR]$" @font-lock-regexp-face))
+ @font-lock-regexp-face
+ (sigil
+ "~" @font-lock-string-face
+ (sigil_name) @font-lock-string-face
+ quoted_start: _ @font-lock-string-face
+ quoted_end: _ @font-lock-string-face))
:language 'elixir
:feature 'elixir-operator
- '((binary_operator operator: _ @font-lock-operator-face)
- (dot operator: _ @font-lock-operator-face)
- (stab_clause operator: _ @font-lock-operator-face)
-
- [(boolean) (nil)] @font-lock-constant-face
- [(integer) (float)] @font-lock-number-face
- (alias) @font-lock-type-face
- (call target: (dot left: (atom) @font-lock-type-face))
- (char) @font-lock-constant-face
- [(atom) (quoted_atom)] @font-lock-type-face
- [(keyword) (quoted_keyword)] @font-lock-builtin-face)
+ `(["!"] @font-lock-negation-char-face
+ ["%"] @font-lock-bracket-face
+ ["," ";"] @font-lock-operator-face
+ ["(" ")" "[" "]" "{" "}" "<<" ">>"] @font-lock-bracket-face)
:language 'elixir
- :feature 'elixir-call
- `((call
- target: (identifier) @font-lock-keyword-face
- (:match ,elixir-ts--definition-keywords-re @font-lock-keyword-face))
- (call
- target: (identifier) @font-lock-keyword-face
- (:match ,elixir-ts--kernel-keywords-re @font-lock-keyword-face))
- (call
- target: [(identifier) @font-lock-function-name-face
- (dot right: (identifier) @font-lock-keyword-face)])
+ :feature 'elixir-data-type
+ '([(atom) (alias)] @font-lock-type-face
+ (keywords (pair key: (keyword) @elixir-ts-keyword-key))
+ [(keyword) (quoted_keyword)] @elixir-ts-atom
+ [(boolean) (nil)] @elixir-ts-atom
+ (unary_operator operator: "@" @elixir-ts-attribute
+ operand: [
+ (identifier) @elixir-ts-attribute
+ (call target: (identifier)
+ @elixir-ts-attribute)
+ (boolean) @elixir-ts-attribute
+ (nil) @elixir-ts-attribute
+ ])
+ (operator_identifier) @font-lock-operator-face)
+
+ :language 'elixir
+ :feature 'elixir-keyword
+ `(,elixir-ts--reserved-keywords-vector
+ @font-lock-keyword-face
+ (binary_operator
+ operator: _ @font-lock-keyword-face
+ (:match ,elixir-ts--reserved-keywords-re @font-lock-keyword-face))
+ (binary_operator operator: _ @font-lock-operator-face)
(call
target: (identifier) @font-lock-keyword-face
- (arguments
- [
- (identifier) @font-lock-keyword-face
- (binary_operator
- left: (identifier) @font-lock-keyword-face
- operator: "when")
- ])
(:match ,elixir-ts--definition-keywords-re @font-lock-keyword-face))
(call
target: (identifier) @font-lock-keyword-face
- (arguments
- (binary_operator
- operator: "|>"
- right: (identifier)))
- (:match ,elixir-ts--definition-keywords-re @font-lock-keyword-face)))
+ (:match ,elixir-ts--kernel-keywords-re @font-lock-keyword-face)))
:language 'elixir
- :feature 'elixir-constant
- `((binary_operator operator: "|>" right: (identifier)
- @font-lock-function-name-face)
- ((identifier) @font-lock-keyword-face
- (:match ,elixir-ts--builtin-keywords-re
- @font-lock-keyword-face))
- ((identifier) @font-lock-comment-face
- (:match "^_" @font-lock-comment-face))
- (identifier) @font-lock-function-name-face
- ["%"] @font-lock-keyward-face
- ["," ";"] @font-lock-keyword-face
- ["(" ")" "[" "]" "{" "}" "<<" ">>"] @font-lock-keyword-face)
+ :feature 'elixir-function-call
+ '((call target: (identifier) @font-lock-function-call-face)
+ (unary_operator operator: "&" @font-lock-operator-face
+ operand: (binary_operator
+ left: (identifier)
+ @font-lock-function-call-face
+ operator: "/" right: (integer)))
+ (call
+ target: (dot right: (identifier) @font-lock-function-call-face))
+ (unary_operator operator: "&" @font-lock-variable-name-face
+ operand: (integer) @font-lock-variable-name-face)
+ (unary_operator operator: "&" @font-lock-operator-face
+ operand: (list)))
:language 'elixir
- :feature 'elixir-sigil
+ :feature 'elixir-string-escape
:override t
- `((sigil
- (sigil_name) @elixir-ts-font-sigil-name-face
- (:match "^[sSwWpPUD]$" @elixir-ts-font-sigil-name-face))
- @font-lock-string-face
- (sigil
- "~" @font-lock-string-face
- (sigil_name) @elixir-ts-font-sigil-name-face
- (:match "^[rR]$" @elixir-ts-font-sigil-name-face))
- @font-lock-regexp-face
- (sigil
- "~" @font-lock-string-face
- (sigil_name) @elixir-ts-font-sigil-name-face
- quoted_start: _ @font-lock-string-face
- quoted_end: _ @font-lock-string-face
- (:match "^[HF]$" @elixir-ts-font-sigil-name-face)))
+ `((escape_sequence) @font-lock-escape-face)
:language 'elixir
- :feature 'elixir-string-escape
+ :feature 'elixir-number
+ '([(integer) (float)] @font-lock-number-face)
+
+ :language 'elixir
+ :feature 'elixir-variable
+ '((binary_operator left: (identifier) @font-lock-variable-name-face)
+ (binary_operator right: (identifier) @font-lock-variable-name-face)
+ (arguments ( (identifier) @font-lock-variable-name-face))
+ (tuple (identifier) @font-lock-variable-name-face)
+ (list (identifier) @font-lock-variable-name-face)
+ (pair value: (identifier) @font-lock-variable-name-face)
+ (body (identifier) @font-lock-variable-name-face)
+ (unary_operator operand: (identifier) @font-lock-variable-name-face)
+ (interpolation (identifier) @font-lock-variable-name-face)
+ (do_block (identifier) @font-lock-variable-name-face))
+
+ :language 'elixir
+ :feature 'elixir-builtin
:override t
- `((escape_sequence) @font-lock-regexp-grouping-backslash))
+ `(((identifier) @font-lock-builtin-face
+ (:match ,elixir-ts--builtin-keywords-re
+ @font-lock-builtin-face))))
+
"Tree-sitter font-lock settings.")
(defvar elixir-ts--treesit-range-rules
@@ -510,21 +588,15 @@ With ARG, do it many times. Negative ARG means move backward."
(defun elixir-ts--treesit-language-at-point (point)
"Return the language at POINT."
- (let* ((range nil)
- (language-in-range
- (cl-loop
- for parser in (treesit-parser-list)
- do (setq range
- (cl-loop
- for range in (treesit-parser-included-ranges parser)
- if (and (>= point (car range)) (<= point (cdr range)))
- return parser))
- if range
- return (treesit-parser-language parser))))
- (if (null language-in-range)
- (when-let ((parser (car (treesit-parser-list))))
- (treesit-parser-language parser))
- language-in-range)))
+ (let ((node (treesit-node-at point 'elixir)))
+ (if (and (equal (treesit-node-type node) "quoted_content")
+ (let ((prev-sibling (treesit-node-prev-sibling node t)))
+ (and (treesit-node-p prev-sibling)
+ (string-match-p
+ (rx bos (or "H" "F") eos)
+ (treesit-node-text prev-sibling)))))
+ 'heex
+ 'elixir)))
(defun elixir-ts--defun-p (node)
"Return non-nil when NODE is a defun."
@@ -625,10 +697,12 @@ Return nil if NODE is not a defun node or doesn't have a name."
;; Font-lock.
(setq-local treesit-font-lock-settings elixir-ts--font-lock-settings)
(setq-local treesit-font-lock-feature-list
- '(( elixir-comment elixir-constant elixir-doc )
- ( elixir-string elixir-keyword elixir-unary-operator
- elixir-call elixir-operator )
- ( elixir-sigil elixir-string-escape elixir-string-interpolation)))
+ '(( elixir-comment elixir-doc elixir-function-name)
+ ( elixir-string elixir-keyword elixir-data-type)
+ ( elixir-sigil elixir-variable elixir-builtin
+ elixir-string-escape)
+ ( elixir-function-call elixir-operator elixir-number )))
+
;; Imenu.
(setq-local treesit-simple-imenu-settings
@@ -660,13 +734,13 @@ Return nil if NODE is not a defun node or doesn't have a name."
heex-ts--indent-rules))
(setq-local treesit-font-lock-feature-list
- '(( elixir-comment elixir-constant elixir-doc
+ '(( elixir-comment elixir-doc elixir-function-name
heex-comment heex-keyword heex-doctype )
- ( elixir-string elixir-keyword elixir-unary-operator
- elixir-call elixir-operator
- heex-component heex-tag heex-attribute heex-string)
- ( elixir-sigil elixir-string-escape
- elixir-string-interpolation ))))
+ ( elixir-string elixir-keyword elixir-data-type
+ heex-component heex-tag heex-attribute heex-string )
+ ( elixir-sigil elixir-variable elixir-builtin
+ elixir-string-escape)
+ ( elixir-function-call elixir-operator elixir-number ))))
(treesit-major-mode-setup)
(setq-local syntax-propertize-function #'elixir-ts--syntax-propertize)))
diff --git a/lisp/progmodes/erts-mode.el b/lisp/progmodes/erts-mode.el
index 8dce93eae7e..0cb77b30a75 100644
--- a/lisp/progmodes/erts-mode.el
+++ b/lisp/progmodes/erts-mode.el
@@ -1,6 +1,6 @@
;;; erts-mode.el --- major mode to edit erts files -*- lexical-binding: t; -*-
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
;; Keywords: tools
@@ -181,7 +181,8 @@ expected results and the actual results in a separate buffer."
(ert-test--erts-test
(list (cons 'dummy t)
(cons 'code (car (read-from-string test-function)))
- (cons 'point-char (erts-mode--preceding-spec "Point-Char")))
+ (cons 'point-char (save-match-data
+ (erts-mode--preceding-spec "Point-Char"))))
(buffer-file-name))
(:success (message "Test successful"))
(ert-test-failed
diff --git a/lisp/progmodes/etags.el b/lisp/progmodes/etags.el
index cb95f29b5fe..b9bd772ddfc 100644
--- a/lisp/progmodes/etags.el
+++ b/lisp/progmodes/etags.el
@@ -1,6 +1,6 @@
;;; etags.el --- etags facility for Emacs -*- lexical-binding: t -*-
-;; Copyright (C) 1985-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1985-2024 Free Software Foundation, Inc.
;; Author: Roland McGrath <roland@gnu.org>
;; Maintainer: emacs-devel@gnu.org
@@ -732,6 +732,7 @@ Returns t if it visits a tags table, or nil if there are no more in the list."
"File %s does not exist")
local-tags-file-name)))))
+;;;###autoload
(defun tags-reset-tags-tables ()
"Reset tags state to cancel effect of any previous \\[visit-tags-table] or \\[find-tag]."
(interactive)
@@ -1729,6 +1730,21 @@ if the file was newly read in, the value is the filename."
(fileloop-next-file novisit)
(switch-to-buffer (current-buffer)))
+(defun etags--ensure-file (file)
+ "Ensure FILE can be visited.
+
+FILE should be an expanded file name.
+This function tries to locate FILE, possibly adding it a suffix
+present in `tags-compression-info-list'. If the file can't be found,
+signals an error.
+Else, returns the filename that can be visited for sure."
+ (let ((f (locate-file file nil (if auto-compression-mode
+ tags-compression-info-list
+ '("")))))
+ (unless f
+ (signal 'file-missing (list "Cannot locate file in TAGS" file)))
+ f))
+
(defun tags--all-files ()
(save-excursion
(let ((cbuf (current-buffer))
@@ -1750,7 +1766,7 @@ if the file was newly read in, the value is the filename."
;; list later returned by (tags-table-files).
(setf (if tail (cdr tail) files)
(mapcar #'expand-file-name (tags-table-files)))))
- files)))
+ (mapcar #'etags--ensure-file files))))
(make-obsolete-variable 'tags-loop-operate 'fileloop-initialize "27.1")
(defvar tags-loop-operate nil
@@ -2137,7 +2153,7 @@ file name, add `tag-partial-file-name-match-p' to the list value.")
(beginning-of-line)
(pcase-let* ((tag-info (etags-snarf-tag))
(`(,hint ,line . _) tag-info))
- (let* ((file (file-of-tag))
+ (let* ((file (etags--ensure-file (file-of-tag)))
(mark-key (cons file line)))
(unless (gethash mark-key marks)
(let ((loc (xref-make-etags-location
diff --git a/lisp/progmodes/executable.el b/lisp/progmodes/executable.el
index c15997dce3a..cb4a5eedb80 100644
--- a/lisp/progmodes/executable.el
+++ b/lisp/progmodes/executable.el
@@ -1,6 +1,6 @@
;;; executable.el --- base functionality for executable interpreter scripts -*- lexical-binding: t -*-
-;; Copyright (C) 1994-1996, 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1994-1996, 2000-2024 Free Software Foundation, Inc.
;; Author: Daniel Pfeiffer <occitan@esperanto.org>
;; Keywords: languages, unix
diff --git a/lisp/progmodes/f90.el b/lisp/progmodes/f90.el
index deccc75b156..ec9d1995547 100644
--- a/lisp/progmodes/f90.el
+++ b/lisp/progmodes/f90.el
@@ -1,6 +1,6 @@
;;; f90.el --- Fortran-90 mode (free format) -*- lexical-binding: t -*-
-;; Copyright (C) 1995-1997, 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1995-1997, 2000-2024 Free Software Foundation, Inc.
;; Author: Torbjörn Einarsson <Torbjorn.Einarsson@era.ericsson.se>
;; Maintainer: emacs-devel@gnu.org
@@ -159,7 +159,6 @@
;; 3. Labels for "else" statements (F2003)?
(defvar comment-auto-fill-only-comments)
-(defvar font-lock-keywords)
;; User options
diff --git a/lisp/progmodes/flymake-cc.el b/lisp/progmodes/flymake-cc.el
index eb17006fbeb..60e7da5d617 100644
--- a/lisp/progmodes/flymake-cc.el
+++ b/lisp/progmodes/flymake-cc.el
@@ -1,6 +1,6 @@
;;; flymake-cc.el --- Flymake support for GNU tools for C/C++ -*- lexical-binding: t; -*-
-;; Copyright (C) 2018-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2018-2024 Free Software Foundation, Inc.
;; Author: João Távora <joaotavora@gmail.com>
;; Keywords: languages, c
diff --git a/lisp/progmodes/flymake-proc.el b/lisp/progmodes/flymake-proc.el
index f640e7f32bf..2c7bb542489 100644
--- a/lisp/progmodes/flymake-proc.el
+++ b/lisp/progmodes/flymake-proc.el
@@ -1,6 +1,6 @@
;;; flymake-proc.el --- Flymake backend for external tools -*- lexical-binding: t; -*-
-;; Copyright (C) 2003-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003-2024 Free Software Foundation, Inc.
;; Author: Pavel Kobyakov <pk_at_work@yahoo.com>
;; Maintainer: João Távora <joaotavora@gmail.com>
@@ -607,6 +607,9 @@ Create parent directories as needed."
(process-put proc 'flymake-proc--unprocessed-mark
(point-marker))))))))
+(defvar-local flymake-proc--temp-source-file-name nil)
+(defvar-local flymake-proc--temp-master-file-name nil)
+
(defun flymake-proc--process-sentinel (proc _event)
"Sentinel for syntax check buffers."
(let (debug
@@ -910,9 +913,7 @@ can also be executed interactively independently of
(file-truename (expand-file-name suffix temp-dir)))
(setq suffix (file-name-directory suffix)))))
-(defvar-local flymake-proc--temp-source-file-name nil)
(defvar-local flymake-proc--master-file-name nil)
-(defvar-local flymake-proc--temp-master-file-name nil)
(defvar-local flymake-proc--base-dir nil)
(defun flymake-proc-init-create-temp-buffer-copy (create-temp-f)
diff --git a/lisp/progmodes/flymake.el b/lisp/progmodes/flymake.el
index b4c0e4db6ac..3f8aec27833 100644
--- a/lisp/progmodes/flymake.el
+++ b/lisp/progmodes/flymake.el
@@ -1,10 +1,10 @@
;;; flymake.el --- A universal on-the-fly syntax checker -*- lexical-binding: t; -*-
-;; Copyright (C) 2003-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003-2024 Free Software Foundation, Inc.
;; Author: Pavel Kobyakov <pk_at_work@yahoo.com>
;; Maintainer: João Távora <joaotavora@gmail.com>
-;; Version: 1.3.4
+;; Version: 1.3.7
;; Keywords: c languages tools
;; Package-Requires: ((emacs "26.1") (eldoc "1.14.0") (project "0.7.1"))
@@ -114,7 +114,7 @@
(require 'thingatpt) ; end-of-thing
(require 'warnings) ; warning-numeric-level, display-warning
(require 'compile) ; for some faces
-;; We need the next require to avoid compiler warnings and run-time
+;; We need the next `require' to avoid compiler warnings and run-time
;; errors about mouse-wheel-up/down-event in builds --without-x, where
;; mwheel is not preloaded.
(require 'mwheel)
@@ -354,8 +354,13 @@ the diagnostic's type symbol."
If neither BEG or END is supplied, use whole accessible buffer,
otherwise if BEG is non-nil and END is nil, consider only
diagnostics at BEG."
- (mapcar (lambda (ov) (overlay-get ov 'flymake-diagnostic))
- (flymake--overlays :beg beg :end end)))
+ (save-restriction
+ (widen)
+ (cl-loop for o in
+ (cond (end (overlays-in beg end))
+ (beg (overlays-at beg))
+ (t (overlays-in (point-min) (point-max))))
+ when (overlay-get o 'flymake-diagnostic) collect it)))
(defmacro flymake--diag-accessor (public internal thing)
"Make PUBLIC an alias for INTERNAL, add doc using THING."
@@ -385,7 +390,7 @@ type."
(flymake--lookup-type-property
(flymake-diagnostic-type diag) 'echo-face 'flymake-error)))))
-(cl-defun flymake--overlays (&key beg end filter compare key)
+(cl-defun flymake--really-all-overlays ()
"Get flymake-related overlays.
If BEG is non-nil and END is nil, consider only `overlays-at'
BEG. Otherwise consider `overlays-in' the region comprised by BEG
@@ -393,19 +398,8 @@ and END, defaulting to the whole buffer. Remove all that do not
verify FILTER, a function, and sort them by COMPARE (using KEY)."
(save-restriction
(widen)
- (let ((ovs (cl-remove-if-not
- (lambda (ov)
- (and (overlay-get ov 'flymake-diagnostic)
- (or (not filter)
- (funcall filter ov))))
- (if (and beg (null end))
- (overlays-at beg t)
- (overlays-in (or beg (point-min))
- (or end (point-max)))))))
- (if compare
- (cl-sort ovs compare :key (or key
- #'identity))
- ovs))))
+ (cl-remove-if-not (lambda (o) (overlay-get o 'flymake-overlay))
+ (overlays-in (point-min) (point-max)))))
(defface flymake-error
'((((supports :underline (:style wave)))
@@ -442,7 +436,7 @@ verify FILTER, a function, and sort them by COMPARE (using KEY)."
:package-version '(Flymake . "1.3.4"))
(defface flymake-note-echo
- '((t :inherit flymake-note))
+ '((t :inherit compilation-info))
"Face used for showing summarized descriptions of notes."
:package-version '(Flymake . "1.3.4"))
@@ -463,14 +457,26 @@ See variable `flymake-show-diagnostics-at-end-of-line'."
:package-version '(Flymake . "1.3.5"))
(defface flymake-note-echo-at-eol
- '((t :inherit (flymake-end-of-line-diagnostics-face flymake-note)))
+ '((t :inherit (flymake-end-of-line-diagnostics-face compilation-info)))
"Face like `flymake-note-echo', but for end-of-line overlays."
:package-version '(Flymake . "1.3.5"))
+(defface flymake-eol-information-face
+ '((t :inherit (flymake-end-of-line-diagnostics-face)
+ :box nil
+ :slant italic))
+ "Face used for information about end-of-line diagnostics."
+ :package-version '(Flymake . "1.3.6"))
+
(defcustom flymake-show-diagnostics-at-end-of-line nil
- "If non-nil, add diagnostic summary messages at end-of-line."
- :type 'boolean
- :package-version '(Flymake . "1.3.4"))
+ "If non-nil, add diagnostic summary messages at end-of-line.
+The value `short' means that only the most severe diagnostic
+shall be shown. Any other non-nil value means show all
+diagnostic summaries at end-of-line."
+ :type '(choice (const :tag "Display most severe diagnostic" short)
+ (const :tag "Display all diagnostics" t)
+ (const :tag "Don't display diagnostics at end-of-line" nil))
+ :package-version '(Flymake . "1.3.6"))
(define-obsolete-face-alias 'flymake-warnline 'flymake-warning "26.1")
(define-obsolete-face-alias 'flymake-errline 'flymake-error "26.1")
@@ -703,9 +709,49 @@ associated `flymake-category' return DEFAULT."
(defun flymake--delete-overlay (ov)
"Like `delete-overlay', delete OV, but do some more stuff."
(let ((eolov (overlay-get ov 'eol-ov)))
- (when eolov (delete-overlay eolov))
+ (when eolov
+ (let ((src-ovs (delq ov (overlay-get eolov 'flymake-eol-source-overlays))))
+ (overlay-put eolov 'flymake-eol-source-overlays src-ovs)))
(delete-overlay ov)))
+(defun flymake--eol-overlay-summary (src-ovs)
+ "Helper function for `flymake--eol-overlay-update'."
+ (cl-flet ((summarize (d)
+ (propertize (flymake-diagnostic-oneliner d t) 'face
+ (flymake--lookup-type-property (flymake--diag-type d)
+ 'eol-face))))
+ (let* ((diags
+ (cl-sort
+ (mapcar (lambda (o) (overlay-get o 'flymake-diagnostic)) src-ovs)
+ #'>
+ :key (lambda (d) (flymake--severity (flymake-diagnostic-type d)))))
+ (summary
+ (concat
+ " "
+ (cond ((eq flymake-show-diagnostics-at-end-of-line 'short)
+ (concat
+ (summarize (car diags))
+ (and (cdr diags)
+ (concat
+ " "
+ (propertize (format "and %s more"
+ (1- (length diags)))
+ 'face 'flymake-eol-information-face)))))
+ (t
+ (mapconcat #'summarize diags " "))))))
+ (put-text-property 0 1 'cursor t summary)
+ summary)))
+
+(defun flymake--update-eol-overlays ()
+ "Update the `before-string' property of end-of-line overlays."
+ (save-excursion
+ (widen)
+ (dolist (o (overlays-in (point-min) (point-max)))
+ (when (overlay-get o 'flymake--eol-overlay)
+ (if-let ((src-ovs (overlay-get o 'flymake-eol-source-overlays)))
+ (overlay-put o 'before-string (flymake--eol-overlay-summary src-ovs))
+ (delete-overlay o))))))
+
(cl-defun flymake--highlight-line (diagnostic &optional foreign)
"Attempt to overlay DIAGNOSTIC in current buffer.
@@ -741,9 +787,9 @@ Return nil or the overlay created."
(setq beg a end b))))
(setf (flymake--diag-beg diagnostic) beg
(flymake--diag-end diagnostic) end)
- ;; Try to fix the remedy the situation if there is the same
- ;; diagnostic is already registered in the same place, which only
- ;; happens for clashes between domestic and foreign diagnostics
+ ;; Try to remedy the situation if the same diagnostic is already
+ ;; registered in the same place. This happens for clashes between
+ ;; domestic and foreign diagnostics
(cl-loop for e in (flymake-diagnostics beg end)
for eov = (flymake--diag-overlay e)
when (flymake--equal-diagnostic-p e diagnostic)
@@ -762,7 +808,13 @@ Return nil or the overlay created."
(flymake--diag-end e)
(flymake--diag-orig-end e))
(flymake--delete-overlay eov)))
- (setq ov (make-overlay end beg))
+ (setq ov (make-overlay beg end))
+ (setf (flymake--diag-overlay diagnostic) ov)
+ (when (= (overlay-start ov) (overlay-end ov))
+ ;; Some backends report diagnostics with invalid bounds. Don't
+ ;; bother.
+ (delete-overlay ov)
+ (cl-return-from flymake--highlight-line nil))
(setf (flymake--diag-beg diagnostic) (overlay-start ov)
(flymake--diag-end diagnostic) (overlay-end ov))
;; First set `category' in the overlay
@@ -779,39 +831,6 @@ Return nil or the overlay created."
(flymake--lookup-type-property type 'flymake-overlay-control))
(alist-get type flymake-diagnostic-types-alist))
do (overlay-put ov ov-prop value))
- ;; Handle `flymake-show-diagnostics-at-end-of-line'
- ;;
- (when-let ((eol-face (and flymake-show-diagnostics-at-end-of-line
- (flymake--lookup-type-property type 'eol-face))))
- (save-excursion
- (goto-char (overlay-start ov))
- (let* ((start (line-end-position))
- (end (min (1+ start) (point-max)))
- (eolov (car
- (cl-remove-if-not
- (lambda (o) (overlay-get o 'flymake-eol-source-region))
- (overlays-at start))))
- (bs (flymake-diagnostic-oneliner diagnostic t)))
- (setq bs (propertize bs 'face eol-face))
- ;; FIXME: 1. no checking if there are unexpectedly more than
- ;; one eolov at point. 2. The first regular source ov to
- ;; die also kills the eolov (very rare this matters, but
- ;; could be improved).
- (cond (eolov
- (overlay-put eolov 'before-string
- (concat (overlay-get eolov 'before-string) " " bs))
- (let ((e (overlay-get eolov 'flymake-eol-source-region)))
- (setcar e (min (car e) (overlay-start ov)))
- (setcdr e (max (cdr e) (overlay-end ov)))))
- (t
- (setq eolov (make-overlay start end nil t nil))
- (setq bs (concat " " bs))
- (put-text-property 0 1 'cursor t bs)
- (overlay-put eolov 'before-string bs)
- (overlay-put eolov 'evaporate (not (= start end)))
- (overlay-put eolov 'flymake-eol-source-region
- (cons (overlay-start ov) (overlay-end ov)))
- (overlay-put ov 'eol-ov eolov))))))
;; Now ensure some essential defaults are set
;;
(cl-flet ((default-maybe
@@ -843,8 +862,29 @@ Return nil or the overlay created."
;; Some properties can't be overridden.
;;
(overlay-put ov 'evaporate t)
+ (overlay-put ov 'flymake-overlay t)
(overlay-put ov 'flymake-diagnostic diagnostic)
- (setf (flymake--diag-overlay diagnostic) ov)
+ ;; Handle `flymake-show-diagnostics-at-end-of-line'
+ ;;
+ (when flymake-show-diagnostics-at-end-of-line
+ (save-excursion
+ (goto-char (overlay-start ov))
+ (let* ((start (line-end-position))
+ (end (min (1+ start) (point-max)))
+ (eolov (car
+ (cl-remove-if-not
+ (lambda (o) (overlay-get o 'flymake-eol-source-overlays))
+ (overlays-in start end)))))
+ ;; FIXME: 1. no checking if there are unexpectedly more than
+ ;; one eolov at point.
+ (if eolov
+ (push ov (overlay-get eolov 'flymake-eol-source-overlays))
+ (setq eolov (make-overlay start end nil t nil))
+ (overlay-put eolov 'flymake-overlay t)
+ (overlay-put eolov 'flymake--eol-overlay t)
+ (overlay-put eolov 'flymake-eol-source-overlays (list ov))
+ (overlay-put eolov 'evaporate (not (= start end)))) ; FIXME: fishy
+ (overlay-put ov 'eol-ov eolov))))
ov))
;; Nothing in Flymake uses this at all any more, so this is just for
@@ -953,6 +993,14 @@ report applies to that region."
(float-time
(time-since flymake-check-start-time))))))
(setf (flymake--state-reported-p state) t)
+ ;; All of the above might have touched the eol overlays, so issue
+ ;; a call to update them. But check running and reporting
+ ;; backends first to flickering when multiple backends touch the
+ ;; same eol overlays.
+ (when (and flymake-show-diagnostics-at-end-of-line
+ (not (cl-set-difference (flymake-running-backends)
+ (flymake-reporting-backends))))
+ (flymake--update-eol-overlays))
(flymake--update-diagnostics-listings (current-buffer))))
(defun flymake--clear-foreign-diags (state)
@@ -965,6 +1013,9 @@ report applies to that region."
(defvar-local flymake-mode nil)
+(defvar-local flymake--mode-line-counter-cache nil
+ "A cache used in `flymake-mode-line-counters'.")
+
(cl-defun flymake--publish-diagnostics (diags &key backend state region)
"Helper for `flymake--handle-report'.
Publish DIAGS, which contain diagnostics for the current buffer
@@ -1025,7 +1076,9 @@ and other buffers."
(setf (flymake--diag-locus d) (buffer-file-name))))
(cl-assert (stringp (flymake--diag-locus d)))
(push d (gethash (flymake--diag-locus d)
- (flymake--state-foreign-diags state))))))))
+ (flymake--state-foreign-diags state))))))
+ ;; Finally, flush some caches
+ (setq flymake--mode-line-counter-cache nil)))
(defun flymake-make-report-fn (backend &optional token)
"Make a suitable anonymous report function for BACKEND.
@@ -1094,15 +1147,7 @@ with a report function."
(setf (flymake--state-running state) run-token
(flymake--state-disabled state) nil
(flymake--state-reported-p state) nil))
- ;; FIXME: Should use `condition-case-unless-debug' here, but don't
- ;; for two reasons: (1) that won't let me catch errors from inside
- ;; `ert-deftest' where `debug-on-error' appears to be always
- ;; t. (2) In cases where the user is debugging elisp somewhere
- ;; else, and using flymake, the presence of a frequently
- ;; misbehaving backend in the global hook (most likely the legacy
- ;; backend) will trigger an annoying backtrace.
- ;;
- (condition-case err
+ (condition-case-unless-debug err
(apply backend (flymake-make-report-fn backend run-token)
args)
(error
@@ -1172,6 +1217,11 @@ Interactively, with a prefix arg, FORCE is t."
(run-hook-wrapped
'flymake-diagnostic-functions
(lambda (backend)
+ (flymake--with-backend-state backend state
+ (setf (flymake--state-reported-p state) nil))))
+ (run-hook-wrapped
+ 'flymake-diagnostic-functions
+ (lambda (backend)
(cond
((and (not force)
(flymake--with-backend-state backend state
@@ -1239,7 +1289,7 @@ special *Flymake log* buffer." :group 'flymake :lighter
;; existing diagnostic overlays, lest we forget them by blindly
;; reinitializing `flymake--state' in the next line.
;; See https://github.com/joaotavora/eglot/issues/223.
- (mapc #'flymake--delete-overlay (flymake--overlays))
+ (mapc #'flymake--delete-overlay (flymake--really-all-overlays))
(setq flymake--state (make-hash-table))
(setq flymake--recent-changes nil)
@@ -1286,13 +1336,13 @@ special *Flymake log* buffer." :group 'flymake :lighter
(when flymake-timer
(cancel-timer flymake-timer)
(setq flymake-timer nil))
- (mapc #'flymake--delete-overlay (flymake--overlays))
+ (mapc #'flymake--delete-overlay (flymake--really-all-overlays))
(when flymake--state
(maphash (lambda (_backend state)
(flymake--clear-foreign-diags state))
- flymake--state)))
+ flymake--state))))
;; turning Flymake on or off has consequences for listings
- (flymake--update-diagnostics-listings (current-buffer))))
+ (flymake--update-diagnostics-listings (current-buffer)))
(defun flymake--schedule-timer-maybe ()
"(Re)schedule an idle timer for checking the buffer.
@@ -1346,8 +1396,10 @@ START and STOP and LEN are as in `after-change-functions'."
(when-let* ((probe (search-forward "\n" stop t))
(eolovs (cl-remove-if-not
(lambda (o)
- (let ((reg (overlay-get o 'flymake-eol-source-region)))
- (and reg (< (car reg) (1- probe)))))
+ (let ((lbound
+ (cl-loop for s in (overlay-get o 'flymake-eol-source-overlays)
+ minimizing (overlay-start s))))
+ (and lbound (< lbound (1- probe)))))
(overlays-at (line-end-position)))))
(goto-char start)
(let ((newend (line-end-position)))
@@ -1396,20 +1448,17 @@ default) no filter is applied."
'(:error :warning))
t))
(let* ((n (or n 1))
- (ovs (flymake--overlays :filter
- (lambda (ov)
- (let ((diag (overlay-get
- ov
- 'flymake-diagnostic)))
- (and diag
- (or
- (not filter)
- (cl-find
- (flymake--severity
- (flymake-diagnostic-type diag))
- filter :key #'flymake--severity)))))
- :compare (if (cl-plusp n) #'< #'>)
- :key #'overlay-start))
+ (ovs (cl-loop
+ for o in (overlays-in (point-min) (point-max))
+ for diag = (overlay-get o 'flymake-diagnostic)
+ when (and diag (or (not filter) (cl-find
+ (flymake--severity
+ (flymake-diagnostic-type diag))
+ filter :key #'flymake--severity)))
+ collect o into retval
+ finally (cl-return
+ (cl-sort retval (if (cl-plusp n) #'< #'>)
+ :key #'overlay-start))))
(tail (cl-member-if (lambda (ov)
(if (cl-plusp n)
(> (overlay-start ov)
@@ -1501,7 +1550,7 @@ The counters are only placed if some Flymake backend initialized
correctly.")
(defvar flymake-mode-line-error-counter
- `(:eval (flymake--mode-line-counter :error t)))
+ `(:eval (flymake--mode-line-counter :error)))
(defvar flymake-mode-line-warning-counter
`(:eval (flymake--mode-line-counter :warning)))
(defvar flymake-mode-line-note-counter
@@ -1598,9 +1647,8 @@ correctly.")
#'flymake--mode-line-counter-scroll-next)
map))
-(defun flymake--mode-line-counter (type &optional no-space)
- "Compute number of diagnostics in buffer with TYPE's severity.
-TYPE is usually keyword `:error', `:warning' or `:note'."
+(defun flymake--mode-line-counter-1 (type)
+ "Helper for `flymake--mode-line-counter'."
(let ((count 0)
(face (flymake--lookup-type-property type
'mode-line-face
@@ -1617,7 +1665,7 @@ TYPE is usually keyword `:error', `:warning' or `:note'."
(warning-numeric-level
flymake-suppress-zero-counters)))
(t t)))
- `(,(if no-space "" '(:propertize " "))
+ `(,(if (eq type :error) "" '(:propertize " "))
(:propertize
,(format "%d" count)
face ,face
@@ -1631,6 +1679,15 @@ TYPE is usually keyword `:error', `:warning' or `:note'."
flymake--diagnostic-type ,type
keymap ,flymake--mode-line-counter-map)))))
+(defun flymake--mode-line-counter (type)
+ "Compute number of diagnostics in buffer with TYPE's severity.
+TYPE is usually keyword `:error', `:warning' or `:note'."
+ (let ((probe (alist-get type flymake--mode-line-counter-cache 'none)))
+ (if (eq probe 'none)
+ (setf (alist-get type flymake--mode-line-counter-cache)
+ (flymake--mode-line-counter-1 type))
+ probe)))
+
;;; Per-buffer diagnostic listing
(defvar-local flymake--diagnostics-buffer-source nil)
@@ -1920,6 +1977,4 @@ some of this variable's contents the diagnostic listings.")
(provide 'flymake)
-(require 'flymake-proc)
-
;;; flymake.el ends here
diff --git a/lisp/progmodes/fortran.el b/lisp/progmodes/fortran.el
index 32cb56ababd..8a726dfe66e 100644
--- a/lisp/progmodes/fortran.el
+++ b/lisp/progmodes/fortran.el
@@ -1,6 +1,6 @@
;;; fortran.el --- Fortran mode for GNU Emacs -*- lexical-binding: t -*-
-;; Copyright (C) 1986-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1986-2024 Free Software Foundation, Inc.
;; Author: Michael D. Prange <prange@erl.mit.edu>
;; Maintainer: emacs-devel@gnu.org
@@ -37,7 +37,7 @@
;; We acknowledge many contributions and valuable suggestions by
;; Lawrence R. Dodd, Ralf Fassel, Ralph Finch, Stephen Gildea,
-;; Dr. Anil Gokhale, Ulrich Mueller, Mark Neale, Eric Prestemon,
+;; Dr. Anil Gokhale, Ulrich Müller, Mark Neale, Eric Prestemon,
;; Gary Sabot and Richard Stallman.
;;; Code:
diff --git a/lisp/progmodes/gdb-mi.el b/lisp/progmodes/gdb-mi.el
index a1091de43e9..e08653f7f9e 100644
--- a/lisp/progmodes/gdb-mi.el
+++ b/lisp/progmodes/gdb-mi.el
@@ -1,6 +1,6 @@
;;; gdb-mi.el --- User Interface for running GDB -*- lexical-binding: t -*-
-;; Copyright (C) 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2024 Free Software Foundation, Inc.
;; Author: Nick Roberts <nickrob@gnu.org>
;; Maintainer: emacs-devel@gnu.org
@@ -222,7 +222,6 @@ address for root variables.")
Only used for files that Emacs can't find.")
(defvar gdb-active-process nil
"GUD tooltips display variable values when t, and macro definitions otherwise.")
-(defvar gdb-error "Non-nil when GDB is reporting an error.")
(defvar gdb-macro-info nil
"Non-nil if GDB knows that the inferior includes preprocessor macro info.")
(defvar gdb-register-names nil "List of register names.")
@@ -717,6 +716,13 @@ that GDB starts to reuse existing source windows."
:group 'gdb
:version "28.1")
+(defcustom gdb-display-io-buffer t
+ "When non-nil, display the separate `gdb-inferior-io' buffer.
+Otherwise, send program output to the GDB buffer."
+ :type 'boolean
+ :group 'gdb-buffers
+ :version "30.1")
+
(defvar gdbmi-debug-mode nil
"When non-nil, print the messages sent/received from GDB/MI in *Messages*.")
@@ -811,6 +817,42 @@ NOARG must be t when this macro is used outside `gud-def'."
(defvar gdb-control-level 0)
+(defun gdb-load-history ()
+ "Load GDB history from a history file.
+The name of the history file is given by environment variable GDBHISTFILE,
+falling back to \".gdb_history\" and \".gdbinit\"."
+ (when (ring-empty-p comint-input-ring) ; cf shell-mode
+ (let ((hfile (expand-file-name (or (getenv "GDBHISTFILE")
+ (if (eq system-type 'ms-dos)
+ "_gdb_history"
+ ".gdb_history"))))
+ ;; gdb defaults to 256, but we'll default to comint-input-ring-size.
+ (hsize (getenv "HISTSIZE")))
+ (dolist (file (append '("~/.gdbinit")
+ (unless (string-equal (expand-file-name ".")
+ (expand-file-name "~"))
+ '(".gdbinit"))))
+ (if (file-readable-p (setq file (expand-file-name file)))
+ (with-temp-buffer
+ (insert-file-contents file)
+ ;; TODO? check for "set history save\\( *on\\)?" and do
+ ;; not use history otherwise?
+ (while (re-search-forward
+ "^ *set history \\(filename\\|size\\) *\\(.*\\)" nil t)
+ (cond ((string-equal (match-string 1) "filename")
+ (setq hfile (expand-file-name
+ (match-string 2)
+ (file-name-directory file))))
+ ((string-equal (match-string 1) "size")
+ (setq hsize (match-string 2))))))))
+ (and (stringp hsize)
+ (integerp (setq hsize (string-to-number hsize)))
+ (> hsize 0)
+ (setq-local comint-input-ring-size hsize))
+ (if (stringp hfile)
+ (setq-local comint-input-ring-file-name hfile))
+ (comint-read-input-ring t))))
+
;;;###autoload
(defun gdb (command-line)
"Run gdb passing it COMMAND-LINE as arguments.
@@ -896,39 +938,10 @@ detailed description of this mode.
(setq-local gud-minor-mode 'gdbmi)
(setq-local gdb-control-level 0)
(setq comint-input-sender 'gdb-send)
- (when (ring-empty-p comint-input-ring) ; cf shell-mode
- (let ((hfile (expand-file-name (or (getenv "GDBHISTFILE")
- (if (eq system-type 'ms-dos)
- "_gdb_history"
- ".gdb_history"))))
- ;; gdb defaults to 256, but we'll default to comint-input-ring-size.
- (hsize (getenv "HISTSIZE")))
- (dolist (file (append '("~/.gdbinit")
- (unless (string-equal (expand-file-name ".")
- (expand-file-name "~"))
- '(".gdbinit"))))
- (if (file-readable-p (setq file (expand-file-name file)))
- (with-temp-buffer
- (insert-file-contents file)
- ;; TODO? check for "set history save\\( *on\\)?" and do
- ;; not use history otherwise?
- (while (re-search-forward
- "^ *set history \\(filename\\|size\\) *\\(.*\\)" nil t)
- (cond ((string-equal (match-string 1) "filename")
- (setq hfile (expand-file-name
- (match-string 2)
- (file-name-directory file))))
- ((string-equal (match-string 1) "size")
- (setq hsize (match-string 2))))))))
- (and (stringp hsize)
- (integerp (setq hsize (string-to-number hsize)))
- (> hsize 0)
- (setq-local comint-input-ring-size hsize))
- (if (stringp hfile)
- (setq-local comint-input-ring-file-name hfile))
- (comint-read-input-ring t)))
+ (gdb-load-history)
+
(gud-def gud-tbreak "tbreak %f:%l" "\C-t"
- "Set temporary breakpoint at current line.")
+ "Set temporary breakpoint at current line." t)
(gud-def gud-jump
(progn (gud-call "tbreak %f:%l" arg) (gud-call "jump %f:%l"))
"\C-j" "Set execution address to current line.")
@@ -959,7 +972,7 @@ detailed description of this mode.
"Finish executing current function.")
(gud-def gud-run "-exec-run"
nil
- "Run the program.")
+ "Run the program." t)
(gud-def gud-break (if (not (string-match "Disassembly" mode-name))
(gud-call "break %f:%l" arg)
@@ -967,7 +980,7 @@ detailed description of this mode.
(beginning-of-line)
(forward-char 2)
(gud-call "break *%a" arg)))
- "\C-b" "Set breakpoint at current line or address.")
+ "\C-b" "Set breakpoint at current line or address." t)
(gud-def gud-remove (if (not (string-match "Disassembly" mode-name))
(gud-call "clear %f:%l" arg)
@@ -975,7 +988,7 @@ detailed description of this mode.
(beginning-of-line)
(forward-char 2)
(gud-call "clear *%a" arg)))
- "\C-d" "Remove breakpoint at current line or address.")
+ "\C-d" "Remove breakpoint at current line or address." t)
;; -exec-until doesn't support --all yet
(gud-def gud-until (if (not (string-match "Disassembly" mode-name))
@@ -1000,9 +1013,10 @@ detailed description of this mode.
(gud-def gud-pp
(gud-call
(concat
- "pp " (if (eq (buffer-local-value
- 'major-mode (window-buffer)) 'speedbar-mode)
- (gdb-find-watch-expression) "%e")) arg)
+ "pp " (if (eq (buffer-local-value 'major-mode (window-buffer))
+ 'speedbar-mode)
+ (gdb-find-watch-expression) "%e"))
+ arg)
nil "Print the Emacs s-expression.")
(define-key gud-minor-mode-map [left-margin mouse-1]
@@ -1044,6 +1058,7 @@ detailed description of this mode.
(setq gdb-first-prompt t)
(setq gud-running nil)
+ (setq gud-async-running nil)
(gdb-update)
@@ -1098,9 +1113,10 @@ detailed description of this mode.
(if gdb-debuginfod-enable "on" "off"))
'gdb-debuginfod-message)
- (gdb-get-buffer-create 'gdb-inferior-io)
- (gdb-clear-inferior-io)
- (gdb-inferior-io--init-proc (get-process "gdb-inferior"))
+ (when gdb-display-io-buffer
+ (gdb-get-buffer-create 'gdb-inferior-io)
+ (gdb-clear-inferior-io)
+ (gdb-inferior-io--init-proc (get-process "gdb-inferior")))
(when (eq system-type 'windows-nt)
;; Don't create a separate console window for the debuggee.
@@ -1952,19 +1968,23 @@ static char *magick[] = {
:group 'gdb)
-(defvar gdb-python-guile-commands-regexp
- "python\\|python-interactive\\|pi\\|guile\\|guile-repl\\|gr"
- "Regexp that matches Python and Guile commands supported by GDB.")
-
(defvar gdb-control-commands-regexp
- (concat
- "^\\("
- "comm\\(a\\(n\\(ds?\\)?\\)?\\)?\\|if\\|while"
- "\\|def\\(i\\(ne?\\)?\\)?\\|doc\\(u\\(m\\(e\\(nt?\\)?\\)?\\)?\\)?\\|"
- gdb-python-guile-commands-regexp
- "\\|while-stepping\\|stepp\\(i\\(ng?\\)?\\)?\\|ws\\|actions"
- "\\|expl\\(o\\(re?\\)?\\)?"
- "\\)\\([[:blank:]]+\\([^[:blank:]]*\\)\\)*$")
+ (rx bol
+ (or
+ (or "comm" "comma" "comman" "command" "commands"
+ "if" "while"
+ "def" "defi" "defin" "define"
+ "doc" "docu" "docum" "docume" "documen" "document"
+ "while-stepping"
+ "stepp" "steppi" "steppin" "stepping"
+ "ws" "actions"
+ "expl" "explo" "explor" "explore")
+ (group ; group 1: Python and Guile commands
+ (or "python" "python-interactive" "pi" "guile" "guile-repl" "gr")))
+ (? (+ blank)
+ (group ; group 2: command arguments
+ (* nonl)))
+ eol)
"Regexp matching GDB commands that enter a recursive reading loop.
As long as GDB is in the recursive reading loop, it does not expect
commands to be prefixed by \"-interpreter-exec console\".")
@@ -2024,15 +2044,13 @@ commands to be prefixed by \"-interpreter-exec console\".")
(setq gdb-continuation nil)))
;; Python and Guile commands that have an argument don't enter the
;; recursive reading loop.
- (let* ((control-command-p (string-match gdb-control-commands-regexp string))
- (command-arg (and control-command-p (match-string 3 string)))
- (python-or-guile-p (string-match gdb-python-guile-commands-regexp
- string)))
- (if (and control-command-p
- (or (not python-or-guile-p)
- (null command-arg)
- (zerop (length command-arg))))
- (setq gdb-control-level (1+ gdb-control-level)))))
+ (when (string-match gdb-control-commands-regexp string)
+ (let ((python-or-guile-p (match-beginning 1))
+ (command-arg (match-string 2 string)))
+ (when (or (not python-or-guile-p)
+ (null command-arg)
+ (zerop (length command-arg)))
+ (setq gdb-control-level (1+ gdb-control-level))))))
(defun gdb-mi-quote (string)
"Return STRING quoted properly as an MI argument.
@@ -2671,9 +2689,11 @@ Sets `gdb-thread-number' to new id."
;; Set `gdb-non-stop' when `gdb-last-command' is a CLI background
;; running command e.g. "run &", attach &" or a MI command
;; e.g. "-exec-run" or "-exec-attach".
- (when (or (string-match "&\s*$" gdb-last-command)
- (string-match "^-" gdb-last-command))
- (gdb-try-check-target-async-support))
+ (if (or (string-match "&\s*$" gdb-last-command)
+ (string-match "^-" gdb-last-command))
+ (progn (gdb-try-check-target-async-support)
+ (setq gud-async-running t))
+ (setq gud-async-running nil))
(gdb-force-mode-line-update
(propertize gdb-inferior-status 'face font-lock-type-face))
@@ -4574,7 +4594,8 @@ left-to-right display order of the properties."
(gdb-set-window-buffer
(gdb-get-buffer-create
'gdb-registers-buffer
- gdb-thread-number) t)))
+ gdb-thread-number)
+ t)))
map))
(define-derived-mode gdb-locals-mode gdb-parent-mode "Locals"
@@ -4694,7 +4715,8 @@ executes FUNCTION."
(gdb-set-window-buffer
(gdb-get-buffer-create
'gdb-locals-buffer
- gdb-thread-number) t)))
+ gdb-thread-number)
+ t)))
(define-key map "f" #'gdb-registers-toggle-filter)
map))
@@ -5094,7 +5116,7 @@ Function buffers are locals buffer, registers buffer, etc, but
not including main command buffer (the one where you type GDB
commands) or source buffers (that display program source code)."
(with-current-buffer buffer
- (derived-mode-p 'gdb-parent-mode 'gdb-inferior-io-mode)))
+ (derived-mode-p '(gdb-parent-mode gdb-inferior-io-mode))))
(defun gdb--buffer-type (buffer)
"Return the type of BUFFER if it is a function buffer.
diff --git a/lisp/progmodes/glasses.el b/lisp/progmodes/glasses.el
index efa191786db..92de2a2581f 100644
--- a/lisp/progmodes/glasses.el
+++ b/lisp/progmodes/glasses.el
@@ -1,6 +1,6 @@
;;; glasses.el --- make cantReadThis readable -*- lexical-binding: t; -*-
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
;; Author: Milan Zamazal <pdm@zamazal.org>
;; Keywords: tools
diff --git a/lisp/progmodes/go-ts-mode.el b/lisp/progmodes/go-ts-mode.el
index 46b631e5af2..65adc1c55ea 100644
--- a/lisp/progmodes/go-ts-mode.el
+++ b/lisp/progmodes/go-ts-mode.el
@@ -1,6 +1,6 @@
;;; go-ts-mode.el --- tree-sitter support for Go -*- lexical-binding: t; -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;; Author : Randy Taylor <dev@rjt.dev>
;; Maintainer : Randy Taylor <dev@rjt.dev>
diff --git a/lisp/progmodes/grep.el b/lisp/progmodes/grep.el
index 5f9da352f77..657349cbdff 100644
--- a/lisp/progmodes/grep.el
+++ b/lisp/progmodes/grep.el
@@ -1,6 +1,6 @@
;;; grep.el --- run `grep' and display the results -*- lexical-binding:t -*-
-;; Copyright (C) 1985-1987, 1993-1999, 2001-2023 Free Software
+;; Copyright (C) 1985-1987, 1993-1999, 2001-2024 Free Software
;; Foundation, Inc.
;; Author: Roland McGrath <roland@gnu.org>
diff --git a/lisp/progmodes/gud.el b/lisp/progmodes/gud.el
index 09860a4cbde..be6357f4139 100644
--- a/lisp/progmodes/gud.el
+++ b/lisp/progmodes/gud.el
@@ -1,6 +1,6 @@
;;; gud.el --- Grand Unified Debugger mode for running GDB and other debuggers -*- lexical-binding:t -*-
-;; Copyright (C) 1992-1996, 1998, 2000-2023 Free Software Foundation,
+;; Copyright (C) 1992-1996, 1998, 2000-2024 Free Software Foundation,
;; Inc.
;; Author: Eric S. Raymond <esr@thyrsus.com>
@@ -80,7 +80,7 @@
(defgroup gud nil
"The \"Grand Unified Debugger\" interface.
-Supported debuggers include gdb, sdb, dbx, xdb, perldb,
+Supported debuggers include gdb, lldb, sdb, dbx, xdb, perldb,
pdb (Python), and jdb."
:group 'processes
:group 'tools)
@@ -128,6 +128,10 @@ If SOFT is non-nil, returns nil if the symbol doesn't already exist."
"Non-nil if debugged program is running.
Used to gray out relevant toolbar icons.")
+(defvar gud-async-running nil
+ "Non-nil if debugged program is running in async mode.
+Check it when `gud-running' is t")
+
(defvar gud-target-name "--unknown--"
"The apparent name of the program being debugged in a gud buffer.")
@@ -169,13 +173,13 @@ Used to gray out relevant toolbar icons.")
"<next>" `(,(propertize "next" 'face 'font-lock-doc-face) . gud-next)
"<until>" `(menu-item
,(propertize "until" 'face 'font-lock-doc-face) gud-until
- :visible (memq gud-minor-mode '(gdbmi gdb perldb)))
+ :visible (memq gud-minor-mode '(gdbmi gdb lldb perldb)))
"<cont>" `(menu-item
,(propertize "cont" 'face 'font-lock-doc-face) gud-cont
:visible (not (eq gud-minor-mode 'gdbmi)))
"<run>" `(menu-item
,(propertize "run" 'face 'font-lock-doc-face) gud-run
- :visible (memq gud-minor-mode '(gdbmi gdb dbx jdb)))
+ :visible (memq gud-minor-mode '(gdbmi gdb lldb dbx jdb)))
"<go>" `(menu-bar-item
,(propertize " go " 'face 'font-lock-doc-face) gud-go
:visible (and (eq gud-minor-mode 'gdbmi)
@@ -227,13 +231,13 @@ Used to gray out relevant toolbar icons.")
:enable (not gud-running)]
["Next Instruction" gud-nexti
:enable (not gud-running)
- :visible (memq gud-minor-mode '(gdbmi gdb dbx))]
+ :visible (memq gud-minor-mode '(gdbmi gdb lldb dbx))]
["Step Instruction" gud-stepi
:enable (not gud-running)
- :visible (memq gud-minor-mode '(gdbmi gdb dbx))]
+ :visible (memq gud-minor-mode '(gdbmi gdb lldb dbx))]
["Finish Function" gud-finish
:enable (not gud-running)
- :visible (memq gud-minor-mode '(gdbmi gdb guiler xdb jdb pdb))]
+ :visible (memq gud-minor-mode '(gdbmi gdb lldb guiler xdb jdb pdb))]
["Watch Expression" gud-watch
:enable (not gud-running)
:visible (eq gud-minor-mode 'gdbmi)]
@@ -244,7 +248,7 @@ Used to gray out relevant toolbar icons.")
"Dump object"
"Print Dereference")
:enable (not gud-running)
- :visible (memq gud-minor-mode '(gdbmi gdb jdb))]
+ :visible (memq gud-minor-mode '(gdbmi gdb lldb jdb))]
["Print S-expression" gud-pp
:enable (and (not gud-running)
(bound-and-true-p gdb-active-process))
@@ -255,23 +259,23 @@ Used to gray out relevant toolbar icons.")
(eq gud-minor-mode 'gdbmi))]
["Down Stack" gud-down
:enable (not gud-running)
- :visible (memq gud-minor-mode '(gdbmi gdb guiler dbx xdb jdb pdb))]
+ :visible (memq gud-minor-mode '(gdbmi gdb lldb guiler dbx xdb jdb pdb))]
["Up Stack" gud-up
:enable (not gud-running)
:visible (memq gud-minor-mode
- '(gdbmi gdb guiler dbx xdb jdb pdb))]
+ '(gdbmi gdb lldb guiler dbx xdb jdb pdb))]
["Set Breakpoint" gud-break
- :enable (not gud-running)
+ :enable (or (not gud-running) gud-async-running)
:visible (gud-tool-bar-item-visible-no-fringe)]
["Temporary Breakpoint" gud-tbreak
- :enable (not gud-running)
- :visible (memq gud-minor-mode '(gdbmi gdb sdb xdb))]
+ :enable (or (not gud-running) gud-async-running)
+ :visible (memq gud-minor-mode '(gdbmi gdb lldb sdb xdb))]
["Remove Breakpoint" gud-remove
- :enable (not gud-running)
+ :enable (or (not gud-running) gud-async-running)
:visible (gud-tool-bar-item-visible-no-fringe)]
["Continue to selection" gud-until
:enable (not gud-running)
- :visible (and (memq gud-minor-mode '(gdbmi gdb perldb))
+ :visible (and (memq gud-minor-mode '(gdbmi gdb lldb perldb))
(gud-tool-bar-item-visible-no-fringe))]
["Stop" gud-stop-subjob
:visible (or (not (memq gud-minor-mode '(gdbmi pdb)))
@@ -283,8 +287,8 @@ Used to gray out relevant toolbar icons.")
:visible (and (eq gud-minor-mode 'gdbmi)
(gdb-show-run-p))]
["Run" gud-run
- :enable (not gud-running)
- :visible (or (memq gud-minor-mode '(gdb dbx jdb))
+ :enable (or (not gud-running) gud-async-running)
+ :visible (or (memq gud-minor-mode '(gdb lldb dbx jdb))
(and (eq gud-minor-mode 'gdbmi)
(or (not (gdb-show-run-p))
(bound-and-true-p
@@ -295,7 +299,7 @@ Used to gray out relevant toolbar icons.")
(display-graphic-p)
(fboundp 'x-show-tip))
:visible (memq gud-minor-mode
- '(gdbmi guiler dbx sdb xdb pdb))
+ '(gdbmi lldb guiler dbx sdb xdb pdb))
:button (:toggle . gud-tooltip-mode)]
["Info (debugger)" gud-goto-info]))
@@ -403,13 +407,15 @@ Uses `gud-<MINOR-MODE>-directories' to find the source files."
;; Of course you may use `gud-def' with any other debugger command, including
;; user defined ones.
-;; A macro call like (gud-def FUNC CMD KEY DOC) expands to a form
+;; A macro call like (gud-def FUNC CMD KEY DOC ASYNC-OK) expands to a form
;; which defines FUNC to send the command CMD to the debugger, gives
;; it the docstring DOC, and binds that function to KEY in the GUD
-;; major mode. The function is also bound in the global keymap with the
+;; major mode. The FUNC still sends CMD when both ASYNC-OK and
+;; `gud-async-running' are t even `gud-running' is t.
+;; The function is also bound in the global keymap with the
;; GUD prefix.
-(defmacro gud-def (func cmd key &optional doc)
+(defmacro gud-def (func cmd key &optional doc async-ok)
"Define FUNC to be a command sending CMD and bound to KEY, with
optional doc string DOC. Certain %-escapes in the string arguments
are interpreted specially if present. These are:
@@ -434,7 +440,7 @@ we're in the GUD buffer)."
(defalias ',func (lambda (arg)
,@(if doc (list doc))
(interactive "p")
- (if (not gud-running)
+ (if (or (not gud-running) (and ,async-ok gud-async-running))
,(if (stringp cmd)
`(gud-call ,cmd arg)
;; Unused lexical warning if cmd does not use "arg".
@@ -702,7 +708,7 @@ The option \"--fullname\" must be included in this value."
(setq gud-marker-acc (concat gud-marker-acc string))
(let ((output ""))
- ;; Process all the complete markers in this chunk.
+ ;; Processn all the complete markers in this chunk.
(while (string-match gud-gdb-marker-regexp gud-marker-acc)
(setq
@@ -967,6 +973,7 @@ It is passed through `gud-gdb-marker-filter' before we look at it."
(setq gud-gdb-fetch-lines-string string)
"")))
+
;; gdb speedbar functions
;; Part of the macro expansion of dframe-with-attached-buffer.
@@ -2696,10 +2703,12 @@ gud, see `gud-mode'."
(define-derived-mode gud-mode comint-mode "Debugger"
"Major mode for interacting with an inferior debugger process.
- You start it up with one of the commands \\[gdb], \\[sdb], \\[dbx],
-\\[perldb], \\[xdb], or \\[jdb]. Each entry point finishes by executing a
-hook; `gdb-mode-hook', `sdb-mode-hook', `dbx-mode-hook',
-`perldb-mode-hook', `xdb-mode-hook', or `jdb-mode-hook' respectively.
+ You start it up with one of the commands \\[gdb], \\[lldb],
+\\[sdb], \\[dbx], \\[perldb], \\[xdb], or \\[jdb]. Each entry
+point finishes by executing a hook; `gdb-mode-hook',
+`lldb-mode-hook' `sdb-mode-hook', `dbx-mode-hook',
+`perldb-mode-hook', `xdb-mode-hook', or `jdb-mode-hook'
+respectively.
After startup, the following commands are available in both the GUD
interaction buffer and any source buffer GUD visits due to a breakpoint stop
@@ -2729,11 +2738,11 @@ Under gdb, sdb and xdb, \\[gud-tbreak] behaves exactly like \\[gud-break],
except that the breakpoint is temporary; that is, it is removed when
execution stops on it.
-Under gdb, dbx, and xdb, \\[gud-up] pops up through an enclosing stack
-frame. \\[gud-down] drops back down through one.
+Under gdb, lldb, dbx, and xdb, \\[gud-up] pops up through an
+enclosing stack frame. \\[gud-down] drops back down through one.
-If you are using gdb or xdb, \\[gud-finish] runs execution to the return from
-the current function and stops.
+If you are using gdb, lldb, or xdb, \\[gud-finish] runs execution
+to the return from the current function and stops.
All the keystrokes above are accessible in the GUD buffer
with the prefix C-c, and in all buffers through the prefix C-x C-a.
@@ -2936,6 +2945,10 @@ It is saved for when this flag is not set.")
(declare-function speedbar-change-initial-expansion-list "speedbar" (new))
(defvar speedbar-previously-used-expansion-list-name)
+(defvar gud-highlight-current-line-overlay nil
+ "Overlay created for `gud-highlight-current-line'.
+It is nil if not yet present.")
+
(defun gud-sentinel (proc msg)
(cond ((null (buffer-name (process-buffer proc)))
;; buffer killed
@@ -2952,6 +2965,10 @@ It is saved for when this flag is not set.")
((memq (process-status proc) '(signal exit))
;; Stop displaying an arrow in a source file.
(setq gud-overlay-arrow-position nil)
+ ;; And any highlight overlays.
+ (when gud-highlight-current-line-overlay
+ (delete-overlay gud-highlight-current-line-overlay)
+ (setq gud-highlight-current-line-overlay nil))
(if (eq (buffer-local-value 'gud-minor-mode gud-comint-buffer)
'gdbmi)
(gdb-reset)
@@ -3003,7 +3020,12 @@ Obeying it means displaying in another window the specified file and line."
(interactive)
(when gud-last-frame
(gud-set-buffer)
- (gud-display-line (car gud-last-frame) (cdr gud-last-frame))
+ ;; Support either (file . line) or (file line column).
+ (if (consp (cdr gud-last-frame))
+ (let ((line (cadr gud-last-frame))
+ (column (caddr gud-last-frame)))
+ (gud-display-line (car gud-last-frame) line column))
+ (gud-display-line (car gud-last-frame) (cdr gud-last-frame)))
(setq gud-last-last-frame gud-last-frame
gud-last-frame nil)))
@@ -3018,7 +3040,25 @@ Obeying it means displaying in another window the specified file and line."
;; region-restriction if that's possible. We use an explicit display-buffer
;; to get around the fact that this is called inside a save-excursion.
-(defun gud-display-line (true-file line)
+(defcustom gud-highlight-current-line nil
+ "Whether Gud should highlight the source line being debugged.
+If non-nil, Gud will accentuate the source code line previously
+executed upon each pause in the debugee's execution with an
+overlay in the face `gud-highlight-current-line-face'.
+
+If nil, yet one of `hl-line-mode' or `global-hl-line-mode' (which
+see) is enabled, then the emphasis imposed by either of those
+major modes is instead momentarily moved to the aforesaid source
+line, until it is displaced by subsequent cursor motion."
+ :version "30.1"
+ :type 'boolean)
+
+(defface gud-highlight-current-line-face
+ '((t :inherit highlight :extend t))
+ "Face for highlighting the source code line being executed."
+ :version "30.1")
+
+(defun gud-display-line (true-file line &optional column)
(let* ((last-nonmenu-event t) ; Prevent use of dialog box for questions.
(buffer
(with-current-buffer gud-comint-buffer
@@ -3044,17 +3084,37 @@ Obeying it means displaying in another window the specified file and line."
(goto-char (point-min))
(forward-line (1- line))
(setq pos (point))
+ (when column
+ (forward-char (1- column)))
(or gud-overlay-arrow-position
(setq gud-overlay-arrow-position (make-marker)))
(set-marker gud-overlay-arrow-position (point) (current-buffer))
- ;; If they turned on hl-line, move the hl-line highlight to
- ;; the arrow's line.
- (when (featurep 'hl-line)
- (cond
- (global-hl-line-mode
- (global-hl-line-highlight))
- ((and hl-line-mode hl-line-sticky-flag)
- (hl-line-highlight)))))
+ (if gud-highlight-current-line
+ (progn
+ (unless gud-highlight-current-line-overlay
+ ;; Create the highlight overlay if it does not yet
+ ;; exist.
+ (let ((overlay (make-overlay (point) (point))))
+ (overlay-put overlay 'priority -45) ; 5 less than hl-line.
+ (overlay-put overlay 'face 'gud-highlight-current-line-face)
+ (setq gud-highlight-current-line-overlay overlay)))
+ ;; Next, move the overlay to the current line.
+ (move-overlay gud-highlight-current-line-overlay
+ (line-beginning-position)
+ (line-beginning-position 2)
+ (current-buffer)))
+ ;; Delete any overlay introduced if g-h-c-l-f has changed.
+ (when gud-highlight-current-line-overlay
+ (delete-overlay gud-highlight-current-line-overlay)
+ (setq gud-highlight-current-line-overlay nil))
+ ;; If they turned on hl-line, move the hl-line highlight to
+ ;; the arrow's line.
+ (when (featurep 'hl-line)
+ (cond
+ (global-hl-line-mode
+ (global-hl-line-highlight))
+ ((and hl-line-mode hl-line-sticky-flag)
+ (hl-line-highlight))))))
(cond ((or (< pos (point-min)) (> pos (point-max)))
(widen)
(goto-char pos))))
@@ -3717,13 +3777,17 @@ With arg, dereference expr if ARG is positive, otherwise do not dereference."
; gdb-mi.el gets around this problem.
(defun gud-tooltip-process-output (process output)
"Process debugger output and show it in a tooltip window."
- (remove-function (process-filter process) #'gud-tooltip-process-output)
- (tooltip-show (tooltip-strip-prompt process output)
- (or gud-tooltip-echo-area (not tooltip-mode))))
+ ;; First line is the print command itself.
+ (unless (string-search (gud-tooltip-print-command "") output)
+ (remove-function (process-filter process)
+ #'gud-tooltip-process-output)
+ (tooltip-show (tooltip-strip-prompt process output)
+ (or gud-tooltip-echo-area (not tooltip-mode)))))
(defun gud-tooltip-print-command (expr)
"Return a suitable command to print the expression EXPR."
(pcase gud-minor-mode
+ ('lldb (format "dwim-print -- %s" expr))
('gdbmi (concat "-data-evaluate-expression \"" expr "\""))
('guiler expr)
('dbx (concat "print " expr))
@@ -3785,11 +3849,312 @@ so they have been disabled."))
(gdb-input
(concat cmd "\n")
(lambda () (gdb-tooltip-print expr))))
+ ;; Not gdbmi.
(add-function :override (process-filter process)
#'gud-tooltip-process-output)
(gud-basic-call cmd))
expr))))))))
+
+;; 'gud-lldb-history' and 'gud-gud-lldb-command-name' are required
+;; because 'gud-symbol' uses their values if they are present. Their
+;; names are deduced from the minor-mode name.
+(defvar gud-lldb-history nil)
+
+(defcustom gud-gud-lldb-command-name "lldb"
+ "Default command to invoke LLDB in order to debug a program with it."
+ :type 'string
+ :version "30.1")
+
+(defun gud-lldb-marker-filter (string)
+ "Deduce interesting stuff from process output STRING."
+
+ ;; Pick information from our own frame info line "!gud LINE:COL:FILE"
+ ;; because the file name in the standard LLDB frame-format doesn't have
+ ;; a directory.
+ (setq string
+ (replace-regexp-in-string
+ (rx bol "!gud "
+ (group (+ digit)) ":" ; 1: line
+ (group (* digit)) ":" ; 2: column
+ (group (+ (not (in "\n\r")))) ; 3: file
+ (* "\r") "\n")
+ (lambda (m)
+ (let ((line (string-to-number (match-string 1 m)))
+ (col (string-to-number (match-string 2 m)))
+ (file (match-string 3 m)))
+ (setq gud-last-frame (list file line col)))
+ ;; Remove the line so that the user won't see it.
+ "")
+ string t t))
+
+ (when (string-match (rx "Process " (1+ digit) " exited with status")
+ string)
+ ;; Process 72874 exited with status = 9 (0x00000009) killed.
+ ;; Doesn't seem to be changeable as of LLDB 17.0.2.
+ (setq gud-last-last-frame nil)
+ (setq gud-overlay-arrow-position nil))
+
+ ;; LLDB sometimes emits certain ECMA-48 sequences even if TERM is "dumb":
+ ;; CHA (Character Horizontal Absolute) and ED (Erase in Display),
+ ;; seemingly to undo previous output on the same line.
+ ;; Filter out these sequences here while carrying out their edits.
+ (let ((bol (pos-bol)))
+ (when (> (point) bol)
+ ;; Move the current line to the string, so that control sequences
+ ;; can delete parts of it.
+ (setq string (concat (buffer-substring-no-properties bol (point))
+ string))
+ (let ((inhibit-read-only t))
+ (delete-region bol (point)))))
+ (let ((ofs 0))
+ (while (string-match (rx (group (* (not (in "\e\n")))) ; preceding chars
+ "\e[" ; CSI
+ (? (group (+ digit))) ; argument
+ (group (in "GJ"))) ; CHA or ED
+ string ofs)
+ (let* ((start (match-beginning 1))
+ (prefix-end (match-end 1))
+ (op (aref string (match-beginning 3)))
+ (end (match-end 0))
+ (keep-end
+ (if (eq op ?G)
+ ;; Move to absolute column (CHA)
+ (min prefix-end
+ (+ start
+ (if (match-beginning 2)
+ (1- (string-to-number (match-string 2 string)))
+ 0)))
+ ;; Erase in display (ED): no further action.
+ prefix-end)))
+ ;; Delete the control sequence and possibly part of the preceding chars.
+ (setq string (concat (substring string 0 keep-end)
+ (substring string end)))
+ (setq ofs start))))
+ string)
+
+;; According to SBCommandInterpreter.cpp, the return value of
+;; HandleCompletions is as follows:
+;;
+;; Index 1 to the end contain all the completions.
+;;
+;; At index 0:
+;;
+;; If all completions have a common prefix, this is the shortest
+;; completion, with the common prefix removed from it.
+;;
+;; If it is the completion for a whole word, a space is added at the
+;; end.
+;;
+;; So, the prefix is what could be added to make the command partially
+;; complete.
+;;
+;; If there is no common prefix, index 0 has an empty string "".
+
+(defcustom gud-lldb-max-completions 20
+ "Maximum number of completions to request from LLDB."
+ :type 'integer
+ :version "30.1")
+
+(defconst gud--lldb-python-init-string
+ "\
+deb = lldb.debugger
+inst = deb.GetInstanceName()
+ff = deb.GetInternalVariableValue('frame-format', inst).GetStringAtIndex(0)
+ff = ff[:-1] + '!gud ${line.number}:${line.column}:${line.file.fullpath}\\\\n\"'
+_ = deb.SetInternalVariable('frame-format', ff, inst)
+def gud_complete(s, max):
+ interpreter = lldb.debugger.GetCommandInterpreter()
+ string_list = lldb.SBStringList()
+ interpreter.HandleCompletion(s, len(s), len(s), max, string_list)
+ print('gud-completions: ##(')
+ # Specifying a max count doesn't seem to work in LLDB 17.
+ max = min(max, string_list.GetSize())
+ for i in range(max):
+ print(f'\"{string_list.GetStringAtIndex(i)}\" ')
+ print(')##')
+"
+ "Python code sent to LLDB for gud-specific initialization.")
+
+(defun gud-lldb-fetch-completions (context command)
+ "Return the data to complete the LLDB command before point.
+This is what the Python function we installed at initialization
+time returns, as a Lisp list.
+Maximum number of completions requested from LLDB is controlled
+by `gud-lldb-max-completions', which see."
+ (let* ((process (get-buffer-process gud-comint-buffer))
+ (to-complete (concat context command))
+ (output-buffer (get-buffer-create "*lldb-completions*")))
+ ;; Send the completion command with output to our buffer
+ (with-current-buffer output-buffer
+ (erase-buffer))
+ (comint-redirect-send-command-to-process
+ (format "script --language python -- gud_complete('%s', %d)"
+ to-complete gud-lldb-max-completions)
+ output-buffer process nil t)
+ ;; Wait for output
+ (unwind-protect
+ (while (not comint-redirect-completed)
+ (accept-process-output process 2))
+ (comint-redirect-cleanup))
+ ;; Process the completion output.
+ (with-current-buffer output-buffer
+ (goto-char (point-min))
+ (when (search-forward "gud-completions: ##" nil t)
+ (read (current-buffer))))))
+
+(defun gud-lldb-completions (context command)
+ "Completion table for LLDB commands."
+ (let ((completions (gud-lldb-fetch-completions context command)))
+ ;; If this is a cmpletion for w whole word, return a completion
+ ;; list that contains that word only, with a space appended.
+ (if (string-suffix-p " " (car completions))
+ (list (concat (cadr completions) " "))
+ (cdr completions))))
+
+(defun gud-lldb-completion-at-point ()
+ "Return the data to complete the LLDB command before point."
+ (let* ((end (point))
+ (line-start (comint-line-beginning-position))
+ (start (save-excursion
+ (skip-chars-backward "^ " line-start)
+ (point)))
+ (context (buffer-substring line-start start)))
+ (list (copy-marker start t)
+ end
+ (completion-table-dynamic
+ (apply-partially #'gud-lldb-completions context)))))
+
+(defun gud-lldb-send-python (python)
+ (gud-basic-call "script --language python --")
+ (mapc #'gud-basic-call (split-string python "\n"))
+ (gud-basic-call "exit()"))
+
+(defun gud-lldb-initialize ()
+ "Initialize the LLDB process as needed for this debug session."
+ (gud-lldb-send-python gud--lldb-python-init-string)
+ (gud-basic-call "settings set stop-line-count-before 0")
+ (gud-basic-call "settings set stop-line-count-after 0"))
+
+;;;###autoload
+(defun lldb (command-line)
+ "Run LLDB passing it COMMAND-LINE as arguments.
+If COMMAND-LINE names a program FILE to debug, LLDB will run in
+a buffer named *gud-FILE*, and the directory containing FILE
+becomes the initial working directory and source-file directory
+for the debug session. If you don't want `default-directory' to
+change to the directory of FILE, specify FILE without leading
+directories, in which case FILE should reside either in the
+directory of the buffer from which this command is invoked, or
+it can be found by searching PATH.
+
+If COMMAND-LINE requests that LLDB attaches to a process PID, LLDB
+will run in *gud-PID*, otherwise it will run in *gud*; in these
+cases the initial working directory is the `default-directory' of
+the buffer in which this command was invoked.
+
+Please note that completion framework that complete while you
+type, like Corfu, do not work well with this mode. You should
+consider to turn them off in this mode.
+
+This command runs functions from `lldb-mode-hook'."
+ (interactive (list (gud-query-cmdline 'lldb)))
+
+ (when (and gud-comint-buffer
+ (buffer-name gud-comint-buffer)
+ (get-buffer-process gud-comint-buffer)
+ (with-current-buffer gud-comint-buffer (eq gud-minor-mode 'gud-lldb)))
+ (gdb-restore-windows)
+ ;; FIXME: Copied from gud-gdb, but what does that even say?
+ (error "Multiple debugging requires restarting in text command mode"))
+
+ (gud-common-init command-line nil 'gud-lldb-marker-filter)
+ (setq-local gud-minor-mode 'lldb)
+
+ (gud-def gud-break
+ "breakpoint set --joint-specifier %f:%l"
+ "\C-b"
+ "Set breakpoint at current line.")
+ (gud-def gud-tbreak
+ "_regexp-break %f:%l"
+ "\C-t"
+ "Set temporary breakpoint at current line.")
+ (gud-def gud-remove
+ "breakpoint clear --line %l --file %f"
+ "\C-d"
+ "Remove breakpoint at current line")
+ (gud-def gud-step "thread step-in --count %p"
+ "\C-s"
+ "Step one source line with display.")
+ (gud-def gud-stepi
+ "thread step-inst --count %p"
+ "\C-i"
+ "Step one instruction with display.")
+ (gud-def gud-next
+ "thread step-over --count %p"
+ "\C-n"
+ "Step one line (skip functions).")
+ (gud-def gud-nexti
+ "thread step-inst-over --count %p"
+ nil
+ "Step one instruction (skip functions).")
+ (gud-def gud-cont
+ "process continue --ignore-count %p"
+ "\C-r"
+ "Continue with display.")
+ (gud-def gud-finish
+ "thread step-out"
+ "\C-f"
+ "Finish executing current function.")
+ (gud-def gud-jump
+ (progn
+ (gud-call "_regexp-break %f:%l" arg)
+ (gud-call "_regexp-jump %f:%l"))
+ "\C-j"
+ "Set execution address to current line.")
+ (gud-def gud-up
+ "_regexp-up %p"
+ "<"
+ "Up N stack frames (numeric arg).")
+ (gud-def gud-down
+ "_regexp-down %p"
+ ">"
+ "Down N stack frames (numeric arg).")
+ (gud-def gud-print
+ "dwim-print %e"
+ "\C-p"
+ "Evaluate C expression at point.")
+ (gud-def gud-pstar
+ "dwim-print *%e"
+ nil
+ "Evaluate C dereferenced pointer expression at point.")
+ (gud-def gud-pv
+ "xprint %e"
+ "\C-v"
+ "Print value of lisp variable (for debugging Emacs only).")
+ (gud-def gud-until
+ "thread until %l"
+ "\C-u"
+ "Continue to current line.")
+ (gud-def gud-run
+ ;; Extension for process launch --tty?
+ "process launch -X true"
+ nil
+ "Run the program.")
+
+ (add-hook 'completion-at-point-functions
+ #'gud-lldb-completion-at-point
+ nil 'local)
+ (keymap-local-set "<tab>" #'completion-at-point)
+
+ (gud-set-repeat-map-property 'gud-gdb-repeat-map)
+ (setq comint-prompt-regexp (rx line-start "(lldb)" (0+ blank)))
+ (setq comint-process-echoes t)
+ (setq paragraph-start comint-prompt-regexp)
+ (setq gud-running nil)
+ (gud-lldb-initialize)
+ (run-hooks 'lldb-mode-hook))
+
(provide 'gud)
;;; gud.el ends here
diff --git a/lisp/progmodes/heex-ts-mode.el b/lisp/progmodes/heex-ts-mode.el
index 68a537b9229..7b53a44deb2 100644
--- a/lisp/progmodes/heex-ts-mode.el
+++ b/lisp/progmodes/heex-ts-mode.el
@@ -1,6 +1,6 @@
;;; heex-ts-mode.el --- Major mode for Heex with tree-sitter support -*- lexical-binding: t; -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;; Author: Wilhelm H Kirschbaum <wkirschbaum@gmail.com>
;; Created: November 2022
@@ -149,8 +149,9 @@ With ARG, do it many times. Negative ARG means move backward."
(treesit-parser-create 'heex)
;; Comments
- (setq-local treesit-text-type-regexp
- (regexp-opt '("comment" "text")))
+ (setq-local treesit-thing-settings
+ `((heex
+ (text ,(regexp-opt '("comment" "text"))))))
(setq-local forward-sexp-function #'heex-ts--forward-sexp)
diff --git a/lisp/progmodes/hideif.el b/lisp/progmodes/hideif.el
index 836db83c2f3..3b7eb393561 100644
--- a/lisp/progmodes/hideif.el
+++ b/lisp/progmodes/hideif.el
@@ -1,6 +1,6 @@
;;; hideif.el --- hides selected code within ifdef -*- lexical-binding:t -*-
-;; Copyright (C) 1988, 1994, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1988, 1994, 2001-2024 Free Software Foundation, Inc.
;; Author: Brian Marick
;; Daniel LaLiberte <liberte@holonexus.org>
@@ -1801,7 +1801,7 @@ and `+='...)."
actual-parms nil)))
(t
- (error "Interal error: impossible case."))))
+ (error "Internal error: impossible case"))))
(pop actual-parms)
while actual-parms) ; end cl-loop
diff --git a/lisp/progmodes/hideshow.el b/lisp/progmodes/hideshow.el
index b878986d7a4..b181b21118f 100644
--- a/lisp/progmodes/hideshow.el
+++ b/lisp/progmodes/hideshow.el
@@ -1,6 +1,6 @@
;;; hideshow.el --- minor mode cmds to selectively display code/comment blocks -*- lexical-binding:t -*-
-;; Copyright (C) 1994-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1994-2024 Free Software Foundation, Inc.
;; Author: Thien-Thi Nguyen <ttn@gnu.org>
;; Dan Nicolaescu <dann@gnu.org>
@@ -264,6 +264,7 @@ This has effect only if `search-invisible' is set to `open'."
(java-ts-mode "{" "}" "/[*/]" nil nil)
(js-mode "{" "}" "/[*/]" nil)
(js-ts-mode "{" "}" "/[*/]" nil)
+ (lua-ts-mode "{\\|\\[\\[" "}\\|\\]\\]" "--" nil)
(mhtml-mode "{\\|<[^/>]*?" "}\\|</[^/>]*[^/]>" "<!--" mhtml-forward nil)
;; Add more support here.
))
diff --git a/lisp/progmodes/icon.el b/lisp/progmodes/icon.el
index e1f9049c364..d4816b416df 100644
--- a/lisp/progmodes/icon.el
+++ b/lisp/progmodes/icon.el
@@ -1,6 +1,6 @@
;;; icon.el --- mode for editing Icon code -*- lexical-binding: t -*-
-;; Copyright (C) 1989, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1989, 2001-2024 Free Software Foundation, Inc.
;; Author: Chris Smith <csmith@convex.com>
;; Created: 15 Feb 89
diff --git a/lisp/progmodes/idlw-complete-structtag.el b/lisp/progmodes/idlw-complete-structtag.el
index cbc94ac0ba4..bcc2ee2f005 100644
--- a/lisp/progmodes/idlw-complete-structtag.el
+++ b/lisp/progmodes/idlw-complete-structtag.el
@@ -1,6 +1,6 @@
;;; idlw-complete-structtag.el --- Completion of structure tags. -*- lexical-binding: t; -*-
-;; Copyright (C) 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2024 Free Software Foundation, Inc.
;; Author: Carsten Dominik <dominik@astro.uva.nl>
;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/progmodes/idlw-help.el b/lisp/progmodes/idlw-help.el
index 2d08714b7cf..217b2ab6691 100644
--- a/lisp/progmodes/idlw-help.el
+++ b/lisp/progmodes/idlw-help.el
@@ -1,6 +1,6 @@
;;; idlw-help.el --- HTML Help code for IDLWAVE -*- lexical-binding: t; -*-
-;; Copyright (C) 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2000-2024 Free Software Foundation, Inc.
;;
;; Authors: JD Smith <jd.smith@utoledo.edu>
;; Carsten Dominik <dominik@science.uva.nl>
@@ -1141,7 +1141,6 @@ When DING is non-nil, ring the bell as well."
(goto-char pos)
(recenter 0)))))
-(defvar font-lock-verbose)
(defvar idlwave-mode-syntax-table)
(defvar idlwave-font-lock-defaults)
(defun idlwave-help-fontify ()
diff --git a/lisp/progmodes/idlw-shell.el b/lisp/progmodes/idlw-shell.el
index e50e1226b43..b5470b5490d 100644
--- a/lisp/progmodes/idlw-shell.el
+++ b/lisp/progmodes/idlw-shell.el
@@ -1,6 +1,6 @@
;;; idlw-shell.el --- run IDL as an inferior process of Emacs. -*- lexical-binding:t -*-
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
;; Authors: JD Smith <jd.smith@utoledo.edu>
;; Carsten Dominik <dominik@astro.uva.nl>
@@ -1454,9 +1454,7 @@ and then calls `idlwave-shell-send-command' for any pending commands."
(concat idlwave-shell-accumulation string)))
(setq idlwave-shell-accumulation
(substring string
- (progn (string-match "\\(.*[\n\r]+\\)*"
- string)
- (match-end 0)))))
+ (string-match "[^\n\r]*\\'" string))))
(setq idlwave-shell-accumulation
(concat idlwave-shell-accumulation string)))
diff --git a/lisp/progmodes/idlw-toolbar.el b/lisp/progmodes/idlw-toolbar.el
index 4319bba0e63..c6cb47baa40 100644
--- a/lisp/progmodes/idlw-toolbar.el
+++ b/lisp/progmodes/idlw-toolbar.el
@@ -1,6 +1,6 @@
;;; idlw-toolbar.el --- a debugging toolbar for IDLWAVE -*- lexical-binding: t; -*-
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
;; Author: Carsten Dominik <dominik@astro.uva.nl>
;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/progmodes/idlwave.el b/lisp/progmodes/idlwave.el
index 7bdaa6b1b6f..4b96461d773 100644
--- a/lisp/progmodes/idlwave.el
+++ b/lisp/progmodes/idlwave.el
@@ -1,6 +1,6 @@
;;; idlwave.el --- IDL editing mode for GNU Emacs -*- lexical-binding: t; -*-
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
;; Authors: JD Smith <jd.smith@utoledo.edu>
;; Carsten Dominik <dominik@science.uva.nl>
@@ -309,7 +309,7 @@ beginning with a \";\". Expressions for comments at the beginning of
the line should begin with \"^\"."
:group 'idlwave-code-formatting
:type '(choice (const :tag "Any line beginning with `;'" nil)
- 'regexp))
+ regexp))
(defcustom idlwave-code-comment ";;[^;]"
"A comment that starts with this regular expression on a line by
@@ -5335,7 +5335,6 @@ directories and save the routine info.
(idlwave-path-alist-remove-flag dir-entry 'user)))
(idlwave-scan-user-lib-files path-alist)))
-(defvar font-lock-mode)
(defun idlwave-scan-user-lib-files (path-alist)
;; Scan the PRO files in PATH-ALIST and store the info in the user catalog
(let* ((idlwave-scanning-lib t)
@@ -6893,7 +6892,7 @@ If these don't exist, a letter in the string is automatically selected."
;; Display prompt and wait for quick reply
(message "%s[%s]" prompt
(mapconcat (lambda(x) (char-to-string (car x)))
- keys-alist ""))
+ keys-alist))
(if (sit-for delay)
;; No quick reply: Show help
(save-window-excursion
@@ -7959,7 +7958,7 @@ demand _EXTRA in the keyword list."
;; If this is the OBJ_NEW function, try to figure out the class and use
;; the keywords from the corresponding INIT method.
(if (and (equal (upcase name) "OBJ_NEW")
- (derived-mode-p 'idlwave-mode 'idlwave-shell-mode))
+ (derived-mode-p '(idlwave-mode idlwave-shell-mode)))
(let* ((bos (save-excursion (idlwave-beginning-of-statement) (point)))
(string (buffer-substring bos (point)))
(case-fold-search t)
@@ -8751,11 +8750,12 @@ This expects NAME TYPE IDLWAVE-TWIN-CLASS to be bound to the right values."
(defun idlwave-count-eq (elt list)
"How often is ELT in LIST?"
- (length (delq nil (mapcar (lambda (x) (eq x elt)) list))))
+ (declare (obsolete nil "30.1"))
+ (seq-count (lambda (x) (eq x elt)) list))
(defun idlwave-count-memq (elt alist)
"How often is ELT a key in ALIST?"
- (length (delq nil (mapcar (lambda (x) (eq (car x) elt)) alist))))
+ (seq-count (lambda (x) (eq (car x) elt)) alist))
(defun idlwave-syslib-p (file)
"Non-nil if FILE is in the system library."
diff --git a/lisp/progmodes/inf-lisp.el b/lisp/progmodes/inf-lisp.el
index e98e00dee7a..141bd18cf1e 100644
--- a/lisp/progmodes/inf-lisp.el
+++ b/lisp/progmodes/inf-lisp.el
@@ -1,6 +1,6 @@
;;; inf-lisp.el --- an inferior-lisp mode -*- lexical-binding: t -*-
-;; Copyright (C) 1988-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1988-2024 Free Software Foundation, Inc.
;; Author: Olin Shivers <shivers@cs.cmu.edu>
;; Keywords: processes, lisp
diff --git a/lisp/progmodes/java-ts-mode.el b/lisp/progmodes/java-ts-mode.el
index 121c8550be0..0b1ac49b99f 100644
--- a/lisp/progmodes/java-ts-mode.el
+++ b/lisp/progmodes/java-ts-mode.el
@@ -1,6 +1,6 @@
;;; java-ts-mode.el --- tree-sitter support for Java -*- lexical-binding: t; -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;; Author : Theodor Thornhill <theo@thornhill.no>
;; Maintainer : Theodor Thornhill <theo@thornhill.no>
@@ -99,6 +99,8 @@
((parent-is "field_declaration") parent-bol java-ts-mode-indent-offset)
((parent-is "return_statement") parent-bol java-ts-mode-indent-offset)
((parent-is "variable_declarator") parent-bol java-ts-mode-indent-offset)
+ ((match ">" "type_arguments") parent-bol 0)
+ ((parent-is "type_arguments") parent-bol java-ts-mode-indent-offset)
((parent-is "method_invocation") parent-bol java-ts-mode-indent-offset)
((parent-is "switch_rule") parent-bol java-ts-mode-indent-offset)
((parent-is "switch_label") parent-bol java-ts-mode-indent-offset)
@@ -303,6 +305,13 @@ Return nil if there is no name or if NODE is not a defun node."
(treesit-node-child-by-field-name node "name")
t))))
+
+(defvar java-ts-mode--feature-list
+ '(( comment definition )
+ ( constant keyword string type)
+ ( annotation expression literal)
+ ( bracket delimiter operator)))
+
;;;###autoload
(define-derived-mode java-ts-mode prog-mode "Java"
"Major mode for editing Java, powered by tree-sitter."
@@ -317,11 +326,6 @@ Return nil if there is no name or if NODE is not a defun node."
;; Comments.
(c-ts-common-comment-setup)
- (setq-local treesit-text-type-regexp
- (regexp-opt '("line_comment"
- "block_comment"
- "text_block")))
-
;; Indent.
(setq-local c-ts-common-indent-type-regexp-alist
`((block . ,(rx (or "class_body"
@@ -360,36 +364,34 @@ Return nil if there is no name or if NODE is not a defun node."
"constructor_declaration")))
(setq-local treesit-defun-name-function #'java-ts-mode--defun-name)
- (setq-local treesit-sentence-type-regexp
- (regexp-opt '("statement"
- "local_variable_declaration"
- "field_declaration"
- "module_declaration"
- "package_declaration"
- "import_declaration")))
-
- (setq-local treesit-sexp-type-regexp
- (regexp-opt '("annotation"
- "parenthesized_expression"
- "argument_list"
- "identifier"
- "modifiers"
- "block"
- "body"
- "literal"
- "access"
- "reference"
- "_type"
- "true"
- "false")))
+ (setq-local treesit-thing-settings
+ `((java
+ (sexp ,(rx (or "annotation"
+ "parenthesized_expression"
+ "argument_list"
+ "identifier"
+ "modifiers"
+ "block"
+ "body"
+ "literal"
+ "access"
+ "reference"
+ "_type"
+ "true"
+ "false")))
+ (sentence ,(rx (or "statement"
+ "local_variable_declaration"
+ "field_declaration"
+ "module_declaration"
+ "package_declaration"
+ "import_declaration")))
+ (text ,(regexp-opt '("line_comment"
+ "block_comment"
+ "text_block"))))))
;; Font-lock.
(setq-local treesit-font-lock-settings java-ts-mode--font-lock-settings)
- (setq-local treesit-font-lock-feature-list
- '(( comment definition )
- ( constant keyword string type)
- ( annotation expression literal)
- ( bracket delimiter operator)))
+ (setq-local treesit-font-lock-feature-list java-ts-mode--feature-list)
;; Imenu.
(setq-local treesit-simple-imenu-settings
diff --git a/lisp/progmodes/js.el b/lisp/progmodes/js.el
index 1d89b35aa2d..0115feb0e97 100644
--- a/lisp/progmodes/js.el
+++ b/lisp/progmodes/js.el
@@ -1,6 +1,6 @@
;;; js.el --- Major mode for editing JavaScript -*- lexical-binding: t -*-
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
;; Author: Karl Landstrom <karl.landstrom@brgeight.se>
;; Daniel Colascione <dancol@dancol.org>
@@ -672,15 +672,6 @@ This variable is like `sgml-attribute-offset'."
:type 'integer
:safe 'integerp)
-;;; Keymap
-
-(defvar-keymap js-mode-map
- :doc "Keymap for `js-mode'."
- "M-." #'js-find-symbol)
-
-(defvar js-ts-mode-map (copy-keymap js-mode-map)
- "Keymap used in `js-ts-mode'.")
-
;;; Syntax table and parsing
(defvar js-mode-syntax-table
@@ -3472,6 +3463,11 @@ Check if a node type is available, then return the right indent rules."
((parent-is "class_body") parent-bol js-indent-level)
((parent-is ,switch-case) parent-bol js-indent-level)
((parent-is "statement_block") parent-bol js-indent-level)
+ ((match "while" "do_statement") parent-bol 0)
+ ((match "else" "if_statement") parent-bol 0)
+ ((parent-is ,(rx (or (seq (or "if" "for" "for_in" "while" "do") "_statement")
+ "else_clause")))
+ parent-bol js-indent-level)
;; JSX
,@(js-jsx--treesit-indent-compatibility-bb1f97b)
@@ -3506,7 +3502,7 @@ Check if a node type is available, then return the right indent rules."
:language 'javascript
:feature 'comment
- '((comment) @font-lock-comment-face)
+ '([(comment) (hash_bang_line)] @font-lock-comment-face)
:language 'javascript
:feature 'constant
@@ -3545,14 +3541,10 @@ Check if a node type is available, then return the right indent rules."
(method_definition
name: (property_identifier) @font-lock-function-name-face)
- (method_definition
- parameters: (formal_parameters (identifier) @font-lock-variable-name-face))
-
- (arrow_function
- parameters: (formal_parameters (identifier) @font-lock-variable-name-face))
-
- (function_declaration
- parameters: (formal_parameters (identifier) @font-lock-variable-name-face))
+ (formal_parameters
+ [(identifier) @font-lock-variable-name-face
+ (array_pattern (identifier) @font-lock-variable-name-face)
+ (object_pattern (shorthand_property_identifier_pattern) @font-lock-variable-name-face)])
(variable_declarator
name: (identifier) @font-lock-variable-name-face)
@@ -3580,16 +3572,6 @@ Check if a node type is available, then return the right indent rules."
(import_clause (namespace_import (identifier) @font-lock-variable-name-face)))
:language 'javascript
- :feature 'property
- '(((property_identifier) @font-lock-property-use-face
- (:pred js--treesit-property-not-function-p
- @font-lock-property-use-face))
-
- (pair value: (identifier) @font-lock-variable-use-face)
-
- ((shorthand_property_identifier) @font-lock-property-use-face))
-
- :language 'javascript
:feature 'assignment
'((assignment_expression
left: (_) @js--treesit-fontify-assignment-lhs))
@@ -3600,13 +3582,7 @@ Check if a node type is available, then return the right indent rules."
function: [(identifier) @font-lock-function-call-face
(member_expression
property:
- (property_identifier) @font-lock-function-call-face)])
- (method_definition
- name: (property_identifier) @font-lock-function-name-face)
- (function_declaration
- name: (identifier) @font-lock-function-call-face)
- (function
- name: (identifier) @font-lock-function-name-face))
+ (property_identifier) @font-lock-function-call-face)]))
:language 'javascript
:feature 'jsx
@@ -3616,6 +3592,12 @@ Check if a node type is available, then return the right indent rules."
(jsx_attribute (property_identifier) @font-lock-constant-face))
:language 'javascript
+ :feature 'property
+ '(((property_identifier) @font-lock-property-use-face)
+ (pair value: (identifier) @font-lock-variable-use-face)
+ ((shorthand_property_identifier) @font-lock-property-use-face))
+
+ :language 'javascript
:feature 'number
'((number) @font-lock-number-face
((identifier) @font-lock-number-face
@@ -3666,18 +3648,11 @@ OVERRIDE is the override flag described in
(setq font-beg (treesit-node-end child)
child (treesit-node-next-sibling child)))))
-(defun js--treesit-property-not-function-p (node)
- "Check that NODE, a property_identifier, is not used as a function."
- (not (equal (treesit-node-type
- (treesit-node-parent ; Maybe call_expression.
- (treesit-node-parent ; Maybe member_expression.
- node)))
- "call_expression")))
-
(defvar js--treesit-lhs-identifier-query
(when (treesit-available-p)
(treesit-query-compile 'javascript '((identifier) @id
- (property_identifier) @id)))
+ (property_identifier) @id
+ (shorthand_property_identifier_pattern) @id)))
"Query that captures identifier and query_identifier.")
(defun js--treesit-fontify-assignment-lhs (node override start end &rest _)
@@ -3689,7 +3664,8 @@ For OVERRIDE, START, END, see `treesit-font-lock-rules'."
(treesit-node-start node) (treesit-node-end node)
(pcase (treesit-node-type node)
("identifier" 'font-lock-variable-use-face)
- ("property_identifier" 'font-lock-property-use-face))
+ ("property_identifier" 'font-lock-property-use-face)
+ ("shorthand_property_identifier_pattern" 'font-lock-variable-use-face))
override start end)))
(defun js--treesit-defun-name (node)
@@ -3831,7 +3807,7 @@ Currently there are `js-mode' and `js-ts-mode'."
"jsx_element"
"jsx_self_closing_element")
"Nodes that designate sentences in JavaScript.
-See `treesit-sentence-type-regexp' for more information.")
+See `treesit-thing-settings' for more information.")
(defvar js--treesit-sexp-nodes
'("expression"
@@ -3854,7 +3830,7 @@ See `treesit-sentence-type-regexp' for more information.")
"pair"
"jsx")
"Nodes that designate sexps in JavaScript.
-See `treesit-sexp-type-regexp' for more information.")
+See `treesit-thing-settings' for more information.")
;;;###autoload
(define-derived-mode js-ts-mode js-base-mode "JavaScript"
@@ -3873,15 +3849,12 @@ See `treesit-sexp-type-regexp' for more information.")
(c-ts-common-comment-setup)
(setq-local comment-multi-line t)
- (setq-local treesit-text-type-regexp
- (regexp-opt '("comment"
- "template_string")))
-
;; Electric-indent.
(setq-local electric-indent-chars
(append "{}():;,<>/" electric-indent-chars)) ;FIXME: js2-mode adds "[]*".
(setq-local electric-layout-rules
'((?\; . after) (?\{ . after) (?\} . before)))
+ (setq-local syntax-propertize-function #'js-ts--syntax-propertize)
;; Tree-sitter setup.
(treesit-parser-create 'javascript)
@@ -3896,11 +3869,12 @@ See `treesit-sexp-type-regexp' for more information.")
"lexical_declaration")))
(setq-local treesit-defun-name-function #'js--treesit-defun-name)
- (setq-local treesit-sentence-type-regexp
- (regexp-opt js--treesit-sentence-nodes))
-
- (setq-local treesit-sexp-type-regexp
- (regexp-opt js--treesit-sexp-nodes))
+ (setq-local treesit-thing-settings
+ `((javascript
+ (sexp ,(regexp-opt js--treesit-sexp-nodes))
+ (sentence ,(regexp-opt js--treesit-sentence-nodes))
+ (text ,(regexp-opt '("comment"
+ "template_string"))))))
;; Fontification.
(setq-local treesit-font-lock-settings js--treesit-font-lock-settings)
@@ -3924,6 +3898,31 @@ See `treesit-sexp-type-regexp' for more information.")
(add-to-list 'auto-mode-alist
'("\\(\\.js[mx]\\|\\.har\\)\\'" . js-ts-mode))))
+(defvar js-ts--s-p-query
+ (when (treesit-available-p)
+ (treesit-query-compile 'javascript
+ '(((regex pattern: (regex_pattern) @regexp))
+ ((variable_declarator value: (jsx_element) @jsx))
+ ((assignment_expression right: (jsx_element) @jsx))
+ ((arguments (jsx_element) @jsx))
+ ((parenthesized_expression (jsx_element) @jsx))
+ ((return_statement (jsx_element) @jsx))))))
+
+(defun js-ts--syntax-propertize (beg end)
+ (let ((captures (treesit-query-capture 'javascript js-ts--s-p-query beg end)))
+ (pcase-dolist (`(,name . ,node) captures)
+ (let* ((ns (treesit-node-start node))
+ (ne (treesit-node-end node))
+ (syntax (pcase-exhaustive name
+ ('regexp
+ (cl-decf ns)
+ (cl-incf ne)
+ (string-to-syntax "\"/"))
+ ('jsx
+ (string-to-syntax "|")))))
+ (put-text-property ns (1+ ns) 'syntax-table syntax)
+ (put-text-property (1- ne) ne 'syntax-table syntax)))))
+
;;;###autoload
(define-derived-mode js-json-mode js-mode "JSON"
(setq-local js-enabled-frameworks nil)
diff --git a/lisp/progmodes/json-ts-mode.el b/lisp/progmodes/json-ts-mode.el
index f56d118c0fe..32bc10bbda9 100644
--- a/lisp/progmodes/json-ts-mode.el
+++ b/lisp/progmodes/json-ts-mode.el
@@ -1,6 +1,6 @@
;;; json-ts-mode.el --- tree-sitter support for JSON -*- lexical-binding: t; -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;; Author : Theodor Thornhill <theo@thornhill.no>
;; Maintainer : Theodor Thornhill <theo@thornhill.no>
@@ -147,7 +147,9 @@ Return nil if there is no name or if NODE is not a defun node."
(rx (or "pair" "object")))
(setq-local treesit-defun-name-function #'json-ts-mode--defun-name)
- (setq-local treesit-sentence-type-regexp "pair")
+ (setq-local treesit-thing-settings
+ `((json
+ (sentence "pair"))))
;; Font-lock.
(setq-local treesit-font-lock-settings json-ts-mode--font-lock-settings)
diff --git a/lisp/progmodes/ld-script.el b/lisp/progmodes/ld-script.el
index 01e8fd9e5e2..0b5ef6edeab 100644
--- a/lisp/progmodes/ld-script.el
+++ b/lisp/progmodes/ld-script.el
@@ -1,6 +1,6 @@
;;; ld-script.el --- GNU linker script editing mode for Emacs -*- lexical-binding:t -*-
-;; Copyright (C) 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2024 Free Software Foundation, Inc.
;; Author: Masatake YAMATO <yamato@redhat.com>
;; Keywords: languages, faces
diff --git a/lisp/progmodes/lua-ts-mode.el b/lisp/progmodes/lua-ts-mode.el
new file mode 100644
index 00000000000..3b600f59521
--- /dev/null
+++ b/lisp/progmodes/lua-ts-mode.el
@@ -0,0 +1,765 @@
+;;; lua-ts-mode.el --- Major mode for editing Lua files -*- lexical-binding: t -*-
+
+;; Copyright (C) 2023-2024 Free Software Foundation, Inc.
+
+;; Author: John Muhl <jm@pub.pink>
+;; Created: June 27, 2023
+;; Keywords: lua languages tree-sitter
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; This package provides `lua-ts-mode' which is a major mode for Lua
+;; files that uses Tree Sitter to parse the language.
+;;
+;; This package is compatible with and tested against the grammar
+;; for Lua found at https://github.com/MunifTanjim/tree-sitter-lua
+
+;;; Code:
+
+(require 'comint)
+(require 'treesit)
+
+(eval-when-compile
+ (require 'cl-lib)
+ (require 'rx))
+
+(declare-function treesit-induce-sparse-tree "treesit.c")
+(declare-function treesit-node-child-by-field-name "treesit.c")
+(declare-function treesit-node-child-count "treesit.c")
+(declare-function treesit-node-first-child-for-pos "treesit.c")
+(declare-function treesit-node-parent "treesit.c")
+(declare-function treesit-node-start "treesit.c")
+(declare-function treesit-node-end "treesit.c")
+(declare-function treesit-node-type "treesit.c")
+(declare-function treesit-parser-create "treesit.c")
+(declare-function treesit-search-subtree "treesit.c")
+
+(defgroup lua-ts nil
+ "Major mode for editing Lua files."
+ :prefix "lua-ts-"
+ :group 'languages)
+
+(defcustom lua-ts-mode-hook nil
+ "Hook run after entering `lua-ts-mode'."
+ :type 'hook
+ :options '(flymake-mode
+ hs-minor-mode
+ outline-minor-mode)
+ :group 'lua-ts
+ :version "30.1")
+
+(defcustom lua-ts-indent-offset 4
+ "Number of spaces for each indentation step in `lua-ts-mode'."
+ :type 'natnum
+ :safe 'natnump
+ :group 'lua-ts
+ :version "30.1")
+
+(defcustom lua-ts-luacheck-program "luacheck"
+ "Location of the Luacheck program."
+ :type '(choice (const :tag "None" nil) string)
+ :group 'lua-ts
+ :version "30.1")
+
+(defcustom lua-ts-inferior-buffer "*Lua*"
+ "Name of the inferior Lua buffer."
+ :type 'string
+ :safe 'stringp
+ :group 'lua-ts
+ :version "30.1")
+
+(defcustom lua-ts-inferior-program "lua"
+ "Program to run in the inferior Lua process."
+ :type '(choice (const :tag "None" nil) string)
+ :group 'lua-ts
+ :version "30.1")
+
+(defcustom lua-ts-inferior-options '("-i")
+ "Command line options for the inferior Lua process."
+ :type '(repeat string)
+ :group 'lua-ts
+ :version "30.1")
+
+(defcustom lua-ts-inferior-startfile nil
+ "File to load into the inferior Lua process at startup."
+ :type '(choice (const :tag "None" nil) (file :must-match t))
+ :group 'lua-ts
+ :version "30.1")
+
+(defcustom lua-ts-inferior-prompt ">"
+ "Prompt used by the inferior Lua process."
+ :type 'string
+ :safe 'stringp
+ :group 'lua-ts
+ :version "30.1")
+
+(defcustom lua-ts-inferior-prompt-continue ">>"
+ "Continuation prompt used by the inferior Lua process."
+ :type 'string
+ :safe 'stringp
+ :group 'lua-ts
+ :version "30.1")
+
+(defcustom lua-ts-inferior-history nil
+ "File used to save command history of the inferior Lua process."
+ :type '(choice (const :tag "None" nil) file)
+ :safe 'string-or-null-p
+ :group 'lua-ts
+ :version "30.1")
+
+(defvar lua-ts--builtins
+ '("assert" "bit32" "collectgarbage" "coroutine" "debug" "dofile"
+ "error" "getmetatable" "io" "ipairs" "load" "loadfile"
+ "math" "next" "os" "package" "pairs" "pcall" "print"
+ "rawequal" "rawget" "rawlen" "rawset" "require" "select"
+ "setmetatable" "string" "table" "tonumber" "tostring"
+ "type" "utf8" "warn" "xpcall" "_G" "_VERSION"
+ ;; methods for file handlers
+ "close" "flush" "lines" "read" "seek" "setvbuf" "write")
+ "Lua built-in functions for tree-sitter font-locking.")
+
+(defvar lua-ts--keywords
+ '("and" "do" "else" "elseif" "end" "for" "function" "goto" "if"
+ "in" "local" "not" "or" "repeat" "return" "then" "until" "while")
+ "Lua keywords for tree-sitter font-locking and navigation.")
+
+(defun lua-ts--comment-font-lock (node override start end &rest _)
+ "Apply font lock to comment NODE within START and END.
+Applies `font-lock-comment-delimiter-face' and
+`font-lock-comment-face'. See `treesit-fontify-with-override' for
+values of OVERRIDE."
+ (let* ((node-start (treesit-node-start node))
+ (node-end (treesit-node-end node))
+ (node-text (treesit-node-text node t))
+ (delimiter-end (+ 2 node-start)))
+ (when (and (>= node-start start)
+ (<= delimiter-end end)
+ (string-match "\\`--" node-text))
+ (treesit-fontify-with-override node-start
+ delimiter-end
+ font-lock-comment-delimiter-face
+ override))
+ (treesit-fontify-with-override (max delimiter-end start)
+ (min node-end end)
+ font-lock-comment-face
+ override)))
+
+(defvar lua-ts--font-lock-settings
+ (treesit-font-lock-rules
+ :default-language 'lua
+ :feature 'bracket
+ '(["(" ")" "[" "]" "{" "}"] @font-lock-bracket-face)
+
+ :feature 'delimiter
+ '(["," ";"] @font-lock-delimiter-face)
+
+ :feature 'constant
+ '([(variable_list
+ attribute: (attribute (["<" ">"] (identifier))))
+ (label_statement)
+ (true) (false) (nil)]
+ @font-lock-constant-face)
+
+ :feature 'operator
+ '(["+" "-" "*" "/" "%" "^" "#" "==" "~=" "<=" ">="
+ "<" ">" "=" "&" "~" "|" "<<" ">>" "//" ".."
+ (vararg_expression)]
+ @font-lock-operator-face)
+
+ :feature 'builtin
+ `(((identifier) @font-lock-builtin-face
+ (:match ,(regexp-opt lua-ts--builtins 'symbols)
+ @font-lock-builtin-face)))
+
+ :feature 'function
+ '((function_call name: (identifier) @font-lock-function-call-face)
+ (function_call
+ (method_index_expression
+ method: (identifier) @font-lock-function-call-face))
+ (function_call
+ (dot_index_expression
+ field: (identifier) @font-lock-function-call-face)))
+
+ :feature 'punctuation
+ '(["." ":"] @font-lock-punctuation-face)
+
+ :feature 'variable
+ '((function_call
+ (arguments (identifier) @font-lock-variable-use-face))
+ (function_call
+ (arguments
+ (binary_expression (identifier) @font-lock-variable-use-face)))
+ (function_call
+ (arguments
+ (bracket_index_expression (identifier) @font-lock-variable-use-face)))
+ (function_declaration
+ (parameters name: (identifier) @font-lock-variable-name-face)))
+
+ :feature 'number
+ '((number) @font-lock-number-face)
+
+ :feature 'keyword
+ `([(break_statement)
+ ,(vconcat lua-ts--keywords)]
+ @font-lock-keyword-face
+ (goto_statement ((identifier) @font-lock-constant-face)))
+
+ :feature 'string
+ '((string) @font-lock-string-face)
+
+ :feature 'escape
+ :override t
+ '((escape_sequence) @font-lock-escape-face)
+
+ :feature 'comment
+ '((comment) @lua-ts--comment-font-lock
+ (hash_bang_line) @font-lock-comment-face)
+
+ :feature 'definition
+ '((function_declaration
+ (identifier) @font-lock-function-name-face)
+ (function_declaration
+ (dot_index_expression
+ field: (identifier) @font-lock-function-name-face))
+ (function_declaration
+ (method_index_expression
+ method: (identifier) @font-lock-function-name-face))
+ (assignment_statement
+ (variable_list
+ (identifier) @font-lock-function-name-face)
+ (expression_list value: (function_definition)))
+ (field
+ name: (identifier) @font-lock-function-name-face
+ value: (function_definition))
+ (assignment_statement
+ (variable_list
+ (dot_index_expression
+ field: (identifier) @font-lock-function-name-face))
+ (expression_list
+ value:
+ (function_definition))))
+
+ :feature 'assignment
+ '((variable_list (identifier) @font-lock-variable-name-face)
+ (variable_list
+ (bracket_index_expression
+ field: (identifier) @font-lock-variable-name-face))
+ (variable_list
+ (dot_index_expression
+ field: (identifier) @font-lock-variable-name-face))
+ (for_numeric_clause name: (identifier) @font-lock-variable-name-face))
+
+ :feature 'property
+ '((field name: (identifier) @font-lock-property-name-face)
+ (dot_index_expression
+ field: (identifier) @font-lock-property-use-face))
+
+ :feature 'error
+ :override t
+ '((ERROR) @font-lock-warning-face))
+ "Tree-sitter font-lock settings for `lua-ts-mode'.")
+
+(defvar lua-ts--simple-indent-rules
+ `((lua
+ ((or (node-is "comment")
+ (parent-is "comment_content")
+ (parent-is "string_content")
+ (node-is "]]"))
+ no-indent 0)
+ ((and (n-p-gp "field" "table_constructor" "arguments")
+ lua-ts--multi-arg-function-call-matcher)
+ parent lua-ts-indent-offset)
+ ((and (n-p-gp "}" "table_constructor" "arguments")
+ lua-ts--multi-arg-function-call-matcher)
+ parent 0)
+ ((or (node-is "do")
+ (node-is "then")
+ (node-is "elseif_statement")
+ (node-is "else_statement")
+ (node-is "until")
+ (node-is ")")
+ (node-is "}"))
+ standalone-parent 0)
+ ((or (and (parent-is "arguments") lua-ts--first-child-matcher)
+ (and (parent-is "parameters") lua-ts--first-child-matcher)
+ (and (parent-is "table_constructor") lua-ts--first-child-matcher))
+ standalone-parent lua-ts-indent-offset)
+ ((or (parent-is "arguments")
+ (parent-is "parameters")
+ (parent-is "table_constructor"))
+ (nth-sibling 1) 0)
+ ((and (n-p-gp "block" "function_definition" "parenthesized_expression")
+ lua-ts--nested-function-block-matcher
+ lua-ts--nested-function-block-include-matcher)
+ parent lua-ts-indent-offset)
+ ((and (n-p-gp "block" "function_definition" "arguments")
+ lua-ts--nested-function-argument-matcher)
+ parent lua-ts-indent-offset)
+ ((match "function_definition" "parenthesized_expression")
+ standalone-parent lua-ts-indent-offset)
+ ((node-is "block") standalone-parent lua-ts-indent-offset)
+ ((parent-is "block") parent 0)
+ ((and (node-is "end") lua-ts--end-line-matcher)
+ standalone-parent lua-ts--end-indent-offset)
+ ((match "end" "function_declaration") parent 0)
+ ((and (n-p-gp "end" "function_definition" "parenthesized_expression")
+ lua-ts--nested-function-end-argument-matcher)
+ parent 0)
+ ((and (n-p-gp "end" "function_definition" "parenthesized_expression")
+ lua-ts--nested-function-block-matcher
+ lua-ts--nested-function-end-matcher
+ lua-ts--nested-function-last-function-matcher)
+ parent 0)
+ ((n-p-gp "end" "function_definition" "arguments") parent 0)
+ ((or (match "end" "function_definition")
+ (node-is "end"))
+ standalone-parent 0)
+ ((or (parent-is "function_declaration")
+ (parent-is "function_definition")
+ (parent-is "do_statement")
+ (parent-is "for_statement")
+ (parent-is "repeat_statement")
+ (parent-is "while_statement")
+ (parent-is "if_statement")
+ (parent-is "else_statement")
+ (parent-is "elseif_statement"))
+ standalone-parent lua-ts-indent-offset)
+ ((parent-is "chunk") column-0 0)
+ ((parent-is "ERROR") no-indent 0))))
+
+(defun lua-ts--end-line-matcher (&rest _)
+ "Matches if there is more than one `end' on the current line."
+ (> (lua-ts--end-count) 1))
+
+(defun lua-ts--end-indent-offset (&rest _)
+ "Calculate indent offset based on `end' count."
+ (- (* (1- (lua-ts--end-count)) lua-ts-indent-offset)))
+
+(defun lua-ts--end-count ()
+ "Count the number of `end's on the current line."
+ (count-matches "end" (line-beginning-position) (line-end-position)))
+
+(defun lua-ts--first-child-matcher (node &rest _)
+ "Matches if NODE is the first among its siblings."
+ (= (treesit-node-index node) 1))
+
+(defun lua-ts--function-definition-p (node)
+ "Return t if NODE is a function_definition."
+ (equal "function_definition" (treesit-node-type node)))
+
+(defun lua-ts--g-g-g-parent (node)
+ "Return the great-great-grand-parent of NODE."
+ (let* ((parent (treesit-node-parent node))
+ (g-parent (treesit-node-parent parent))
+ (g-g-parent (treesit-node-parent g-parent)))
+ (treesit-node-parent g-g-parent)))
+
+(defun lua-ts--multi-arg-function-call-matcher (_n parent &rest _)
+ "Matches if PARENT has multiple arguments."
+ (> (treesit-node-child-count (treesit-node-parent parent)) 3))
+
+(defun lua-ts--nested-function-argument-matcher (node &rest _)
+ "Matches if NODE is in a nested function argument."
+ (save-excursion
+ (goto-char (treesit-node-start node))
+ (treesit-beginning-of-defun)
+ (backward-char 2)
+ (not (looking-at ")("))))
+
+(defun lua-ts--nested-function-block-matcher (node &rest _)
+ "Matches if NODE is in a nested function block."
+ (let* ((g-g-g-parent (lua-ts--g-g-g-parent node))
+ (g-g-g-type (treesit-node-type g-g-g-parent)))
+ (not (equal g-g-g-type "chunk"))))
+
+(defun lua-ts--nested-function-block-include-matcher (node _p bol &rest _)
+ "Matches if NODE's child at BOL is not another block."
+ (let* ((child (treesit-node-first-child-for-pos node bol))
+ (child-type (treesit-node-type child))
+ (g-g-g-type (treesit-node-type (lua-ts--g-g-g-parent node))))
+ (or (equal child-type "assignment_statement")
+ (and (equal child-type "return_statement")
+ (or (equal g-g-g-type "arguments")
+ (and (equal g-g-g-type "expression_list")
+ (not (treesit-search-subtree child "function_call"))))))))
+
+(defun lua-ts--nested-function-end-matcher (node &rest _)
+ "Matches if NODE is the `end' of a nested function."
+ (save-excursion
+ (goto-char (treesit-node-start node))
+ (treesit-beginning-of-defun)
+ (looking-at "function[[:space:]]*")))
+
+(defun lua-ts--nested-function-end-argument-matcher (node &rest _)
+ "Matches if great-great-grandparent of NODE is arguments."
+ (equal "arguments" (treesit-node-type (lua-ts--g-g-g-parent node))))
+
+(defun lua-ts--nested-function-last-function-matcher (_n parent &rest _)
+ "Matches if PARENT is the last nested function."
+ (let ((sparse-tree
+ (treesit-induce-sparse-tree parent #'lua-ts--function-definition-p)))
+ (= 1 (length (cadr sparse-tree)))))
+
+(defvar lua-ts--syntax-table
+ (let ((table (make-syntax-table)))
+ (modify-syntax-entry ?+ "." table)
+ (modify-syntax-entry ?- ". 12" table)
+ (modify-syntax-entry ?= "." table)
+ (modify-syntax-entry ?% "." table)
+ (modify-syntax-entry ?^ "." table)
+ (modify-syntax-entry ?~ "." table)
+ (modify-syntax-entry ?< "." table)
+ (modify-syntax-entry ?> "." table)
+ (modify-syntax-entry ?/ "." table)
+ (modify-syntax-entry ?* "." table)
+ (modify-syntax-entry ?\n ">" table)
+ (modify-syntax-entry ?\' "\"" table)
+ (modify-syntax-entry ?\" "\"" table)
+ table)
+ "Syntax table for `lua-ts-mode'.")
+
+(defun lua-ts--defun-name-function (node)
+ "Return the defun name of NODE.
+Return nil if there is no name or if NODE is not a defun node."
+ (let ((child (treesit-node-child-by-field-name node "name")))
+ (pcase (treesit-node-type node)
+ ((or "function_declaration" "function_definition")
+ (treesit-node-text child t))
+ ("variable_declaration"
+ (if child
+ (treesit-node-text child t)
+ (treesit-node-text
+ (treesit-node-child-by-field-name
+ (treesit-search-subtree node "assignment_statement" nil nil 1)
+ "name"))))
+ ("field"
+ (and (treesit-search-subtree node "function_definition" nil nil 1)
+ (treesit-node-text child t))))))
+
+(defun lua-ts--named-function-p (node)
+ "Matches if NODE is a named function."
+ (let ((type (treesit-node-type node)))
+ (or (equal "function_declaration" type)
+ (and (equal "field" type)
+ (equal "function_definition"
+ (treesit-node-type
+ (treesit-node-child-by-field-name
+ node "value")))
+ (treesit-node-child-by-field-name node "name")))))
+
+(defun lua-ts--require-name-function (node)
+ "Return name of NODE to use for requires in imenu."
+ (when-let* (((lua-ts--require-p node))
+ (parent (treesit-node-parent node))
+ (parent-type (treesit-node-type parent)))
+ (if (equal "expression_list" parent-type)
+ (let* ((g-parent (treesit-node-parent parent))
+ (name (treesit-node-child-by-field-name g-parent "name")))
+ (treesit-node-text name t))
+ (treesit-node-text (treesit-search-subtree node "string_content") t))))
+
+(defun lua-ts--require-p (node)
+ "Matches if NODE is a require statement."
+ (let ((name (treesit-node-child-by-field-name node "name")))
+ (equal "require" (treesit-node-text name t))))
+
+(defvar-local lua-ts--flymake-process nil)
+
+(defun lua-ts-flymake-luacheck (report-fn &rest _args)
+ "Luacheck backend for Flymake.
+Calls REPORT-FN directly."
+ (when (process-live-p lua-ts--flymake-process)
+ (kill-process lua-ts--flymake-process))
+ (let ((source (current-buffer)))
+ (save-restriction
+ (widen)
+ (setq lua-ts--flymake-process
+ (make-process
+ :name "lua-ts-flymake-luacheck"
+ :noquery t
+ :connection-type 'pipe
+ :buffer (generate-new-buffer " *lua-ts-flymake-luacheck*")
+ :command `(,lua-ts-luacheck-program
+ "--codes" "--ranges" "--formatter" "plain" "-")
+ :sentinel
+ (lambda (proc _event)
+ (when (eq 'exit (process-status proc))
+ (unwind-protect
+ (if (with-current-buffer source
+ (eq proc lua-ts--flymake-process))
+ (with-current-buffer (process-buffer proc)
+ (goto-char (point-min))
+ (cl-loop
+ while (search-forward-regexp
+ (rx (seq bol
+ (0+ alnum) ":"
+ (group (1+ digit)) ":"
+ (group (1+ digit)) "-"
+ (group (1+ digit)) ": "
+ (group (0+ nonl))
+ eol))
+ nil t)
+ for (beg . end) = (flymake-diag-region
+ source
+ (string-to-number (match-string 1))
+ (string-to-number (match-string 2)))
+ for msg = (match-string 4)
+ for type = (if (string-match "^(W" msg)
+ :warning
+ :error)
+ when (and beg end)
+ collect (flymake-make-diagnostic source
+ beg
+ end
+ type
+ msg)
+ into diags
+ finally (funcall report-fn diags)))
+ (flymake-log :warning "Canceling obsolete check %s" proc))
+ (kill-buffer (process-buffer proc)))))))
+ (process-send-region lua-ts--flymake-process (point-min) (point-max))
+ (process-send-eof lua-ts--flymake-process))))
+
+;;;###autoload
+(defun lua-ts-inferior-lua ()
+ "Run a Lua interpreter in an inferior process."
+ (interactive)
+ (unless (comint-check-proc lua-ts-inferior-buffer)
+ (apply #'make-comint-in-buffer
+ (string-replace "*" "" lua-ts-inferior-buffer)
+ lua-ts-inferior-buffer
+ lua-ts-inferior-program
+ lua-ts-inferior-startfile
+ lua-ts-inferior-options)
+ (when lua-ts-inferior-history
+ (set-process-sentinel (get-buffer-process lua-ts-inferior-buffer)
+ 'lua-ts-inferior--write-history))
+ (with-current-buffer lua-ts-inferior-buffer
+ (setq-local comint-input-ignoredups t
+ comint-input-ring-file-name lua-ts-inferior-history
+ comint-prompt-read-only t
+ comint-prompt-regexp (rx-to-string `(: bol
+ ,lua-ts-inferior-prompt
+ (1+ space))))
+ (comint-read-input-ring t)
+ (add-hook 'comint-preoutput-filter-functions
+ (lambda (string)
+ (if (equal string (concat lua-ts-inferior-prompt-continue " "))
+ string
+ (concat
+ ;; Filter out the extra prompt characters that
+ ;; accumulate in the output when sending regions
+ ;; to the inferior process.
+ (replace-regexp-in-string (rx-to-string
+ `(: bol
+ (* ,lua-ts-inferior-prompt
+ (? ,lua-ts-inferior-prompt)
+ (1+ space))
+ (group (* nonl))))
+ "\\1" string)
+ ;; Re-add the prompt for the next line.
+ lua-ts-inferior-prompt " ")))
+ nil t)))
+ (select-window (display-buffer lua-ts-inferior-buffer
+ '((display-buffer-reuse-window
+ display-buffer-pop-up-frame)
+ (reusable-frames . t))))
+ (get-buffer-process (current-buffer)))
+
+(defun lua-ts-send-buffer ()
+ "Send current buffer to the inferior Lua process."
+ (interactive)
+ (lua-ts-send-region (point-min) (point-max)))
+
+(defun lua-ts-send-file (file)
+ "Send contents of FILE to the inferior Lua process."
+ (interactive "f")
+ (with-temp-buffer
+ (insert-file-contents-literally file)
+ (lua-ts-send-region (point-min) (point-max))))
+
+(defun lua-ts-send-region (beg end)
+ "Send region between BEG and END to the inferior Lua process."
+ (interactive "r")
+ (let ((string (buffer-substring-no-properties beg end))
+ (proc-buffer (lua-ts-inferior-lua)))
+ (comint-send-string proc-buffer "print()") ; Prevent output from
+ (comint-send-string proc-buffer "\n") ; appearing at prompt.
+ (comint-send-string proc-buffer string)
+ (comint-send-string proc-buffer "\n")))
+
+(defun lua-ts-show-process-buffer ()
+ "Show the inferior Lua process buffer."
+ (interactive)
+ (display-buffer lua-ts-inferior-buffer))
+
+(defun lua-ts-hide-process-buffer ()
+ "Hide the inferior Lua process buffer."
+ (interactive)
+ (delete-windows-on lua-ts-inferior-buffer))
+
+(defun lua-ts-kill-process ()
+ "Kill the inferior Lua process."
+ (interactive)
+ (with-current-buffer lua-ts-inferior-buffer
+ (kill-buffer-and-window)))
+
+(defun lua-ts-inferior--write-history (process _)
+ "Write history file for inferior Lua PROCESS."
+ ;; Depending on how the process is killed the buffer may not be
+ ;; around anymore; e.g. `kill-buffer'.
+ (when-let* ((buffer (process-buffer process))
+ ((buffer-live-p (process-buffer process))))
+ (with-current-buffer buffer (comint-write-input-ring))))
+
+(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)
+ map)
+ "Keymap for `lua-ts-mode' buffers.")
+
+(easy-menu-define lua-ts-mode-menu lua-ts-mode-map
+ "Menu bar entry for `lua-ts-mode'."
+ `("Lua"
+ ["Evaluate Buffer" lua-ts-send-buffer]
+ ["Evaluate File" lua-ts-send-file]
+ ["Evaluate Region" lua-ts-send-region]
+ "--"
+ ["Start Process" lua-ts-inferior-lua]
+ ["Show Process Buffer" lua-ts-show-process-buffer]
+ ["Hide Process Buffer" lua-ts-hide-process-buffer]
+ ["Kill Process" lua-ts-kill-process]
+ "--"
+ ["Customize" (lambda () (interactive) (customize-group "lua-ts"))]))
+
+;;;###autoload
+(define-derived-mode lua-ts-mode prog-mode "Lua"
+ "Major mode for editing Lua files, powered by tree-sitter.
+
+\\{lua-ts-mode-map}"
+ :syntax-table lua-ts--syntax-table
+ (use-local-map lua-ts-mode-map)
+
+ (when (treesit-ready-p 'lua)
+ (treesit-parser-create 'lua)
+
+ ;; Comments.
+ (setq-local comment-start "--")
+ (setq-local comment-start-skip "--\\s-*")
+ (setq-local comment-end "")
+
+ ;; Font-lock.
+ (setq-local treesit-font-lock-settings lua-ts--font-lock-settings)
+ (setq-local treesit-font-lock-feature-list
+ '((comment definition)
+ (keyword string)
+ (assignment builtin constant number)
+ (bracket
+ delimiter
+ escape
+ function
+ operator
+ property
+ punctuation
+ variable)))
+
+ ;; Indent.
+ (setq-local treesit-simple-indent-rules lua-ts--simple-indent-rules)
+
+ ;; Navigation.
+ (setq-local treesit-defun-name-function #'lua-ts--defun-name-function)
+ (setq-local treesit-defun-type-regexp
+ (rx (or "function_declaration" "function_definition")))
+ (setq-local treesit-thing-settings
+ `((lua
+ (function ,(rx (or "function_declaration"
+ "function_definition")))
+ (keyword ,(regexp-opt lua-ts--keywords
+ 'symbols))
+ (loop-statement ,(rx (or "do_statement"
+ "for_statement"
+ "repeat_statement"
+ "while_statement")))
+ (sentence (or function
+ loop-statement
+ ,(rx (or "assignment_statement"
+ "comment"
+ "field"
+ "function_call"
+ "if_statement"
+ "return_statement"
+ "variable_declaration"))))
+ (sexp (or function
+ keyword
+ loop-statement
+ ,(rx (or "arguments"
+ "break_statement"
+ "expression_list"
+ "false"
+ "identifier"
+ "nil"
+ "number"
+ "parameters"
+ "parenthesized_expression"
+ "string"
+ "table_constructor"
+ "true"
+ "vararg_expression"))))
+ (text "comment"))))
+
+ ;; Imenu.
+ (setq-local treesit-simple-imenu-settings
+ `(("Requires"
+ "\\`function_call\\'"
+ lua-ts--require-p
+ lua-ts--require-name-function)
+ ("Variables" "\\`variable_declaration\\'" nil nil)
+ (nil
+ "\\`\\(?:f\\(?:ield\\|unction_declaration\\)\\)\\'"
+ lua-ts--named-function-p
+ nil)))
+
+ ;; Which-function.
+ (setq-local which-func-functions (treesit-defun-at-point))
+
+ ;; Outline.
+ (setq-local outline-regexp
+ (rx (seq (0+ space)
+ (or (seq "--[[" (0+ space) eol)
+ (seq symbol-start
+ (or "do" "for" "if" "repeat" "while"
+ (seq (? (seq "local" (1+ space)))
+ "function"))
+ symbol-end)))))
+
+ ;; Align.
+ (setq-local align-indent-before-aligning t)
+
+ (treesit-major-mode-setup))
+
+ (add-hook 'flymake-diagnostic-functions #'lua-ts-flymake-luacheck nil 'local))
+
+(when (treesit-ready-p 'lua)
+ (add-to-list 'auto-mode-alist '("\\.lua\\'" . lua-ts-mode)))
+
+(provide 'lua-ts-mode)
+
+;;; lua-ts-mode.el ends here
diff --git a/lisp/progmodes/m4-mode.el b/lisp/progmodes/m4-mode.el
index 2291fe60919..ec632ada98c 100644
--- a/lisp/progmodes/m4-mode.el
+++ b/lisp/progmodes/m4-mode.el
@@ -1,6 +1,6 @@
;;; m4-mode.el --- m4 code editing commands for Emacs -*- lexical-binding:t -*-
-;; Copyright (C) 1996-1997, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-1997, 2001-2024 Free Software Foundation, Inc.
;; Author: Andrew Csillag <drew@thecsillags.com>
;; Keywords: languages, faces
diff --git a/lisp/progmodes/make-mode.el b/lisp/progmodes/make-mode.el
index 017a551bc05..be5884604da 100644
--- a/lisp/progmodes/make-mode.el
+++ b/lisp/progmodes/make-mode.el
@@ -1,6 +1,6 @@
;;; make-mode.el --- makefile editing commands for Emacs -*- lexical-binding:t -*-
-;; Copyright (C) 1992-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1992-2024 Free Software Foundation, Inc.
;; Author: Thomas Neumann <tom@smart.bo.open.de>
;; Eric S. Raymond <esr@thyrsus.com>
@@ -44,10 +44,6 @@
;; prerequisites, which targets are out-of-date, and which have no
;; prerequisites.
;;
-;; The command C-c C-b pops up a browser window listing all target and
-;; macro names. You can mark or unmark items with C-c SPC, and insert
-;; all marked items back in the Makefile with C-c TAB.
-;;
;; The command C-c TAB in the makefile buffer inserts a GNU make builtin.
;; You will be prompted for the builtin's arguments.
;;
@@ -66,17 +62,9 @@
;; interact with font-lock.
;; * Would be nice to edit the commands in ksh-mode and have
;; indentation and slashification done automatically. Hard.
-;; * Consider removing browser mode. It seems useless.
;; * ":" should notice when a new target is made and add it to the
;; list (or at least set `makefile-need-target-pickup').
-;; * Make browser into a major mode.
;; * Clean up macro insertion stuff. It is a mess.
-;; * Browser entry and exit is weird. Normalize.
-;; * Browser needs to be rewritten. Right now it is kind of a crock.
-;; Should at least:
-;; * Act more like dired/buffer menu/whatever.
-;; * Highlight as mouse traverses.
-;; * B2 inserts.
;; * Update documentation above.
;; * Update texinfo manual.
;; * Update files.el.
@@ -118,6 +106,7 @@
"Face to use for additionally highlighting Perl code in Font-Lock mode."
:version "22.1")
+(make-obsolete-variable 'makefile-browser-buffer-name nil "30.1")
(defcustom makefile-browser-buffer-name "*Macros and Targets*"
"Name of the macro- and target browser buffer."
:type 'string)
@@ -152,10 +141,12 @@ Otherwise, a space is inserted.
The default is t."
:type 'boolean)
+(make-obsolete-variable 'makefile-browser-leftmost-column nil "30.1")
(defcustom makefile-browser-leftmost-column 10
"Number of blanks to the left of the browser selection mark."
:type 'integer)
+(make-obsolete-variable 'makefile-browser-cursor-column nil "30.1")
(defcustom makefile-browser-cursor-column 10
"Column the cursor goes to when it moves up or down in the Makefile browser."
:type 'integer)
@@ -168,14 +159,17 @@ The default is t."
"If non-nil, `makefile-backslash-region' will align backslashes."
:type 'boolean)
+(make-obsolete-variable 'makefile-browser-selected-mark nil "30.1")
(defcustom makefile-browser-selected-mark "+ "
"String used to mark selected entries in the Makefile browser."
:type 'string)
+(make-obsolete-variable 'makefile-browser-unselected-mark nil "30.1")
(defcustom makefile-browser-unselected-mark " "
"String used to mark unselected entries in the Makefile browser."
:type 'string)
+(make-obsolete-variable 'makefile-browser-auto-advance-after-selection-p nil "30.1")
(defcustom makefile-browser-auto-advance-after-selection-p t
"If non-nil, cursor will move after item is selected in Makefile browser."
:type 'boolean)
@@ -198,6 +192,7 @@ to MODIFY A FILE WITHOUT YOUR CONFIRMATION when \"it seems necessary\"."
"Normal hook run by `makefile-mode'."
:type 'hook)
+(make-obsolete-variable 'makefile-browser-hook nil "30.1")
(defvar makefile-browser-hook '())
;;
@@ -611,9 +606,6 @@ The function must satisfy this calling convention:
;; Other.
["Up To Date Overview" makefile-create-up-to-date-overview
:help "Create a buffer containing an overview of the state of all known targets"]
- ["Pop up Makefile Browser" makefile-switch-to-browser
- ;; XXX: this needs a better string, the function is not documented...
- :help "Pop up Makefile Browser"]
("Switch Makefile Type"
["GNU make" makefile-gmake-mode
:help "An adapted `makefile-mode' that knows about GNU make"
@@ -641,6 +633,7 @@ The function must satisfy this calling convention:
:selected (eq major-mode 'makefile-makepp-mode)])))
+(make-obsolete-variable 'makefile-browser-map nil "30.1")
(defvar-keymap makefile-browser-map
:doc "The keymap that is used in the macro- and target browser."
"n" #'makefile-browser-next-line
@@ -695,9 +688,11 @@ The function must satisfy this calling convention:
"Table of all macro names known for this buffer.")
(put 'makefile-macro-table 'risky-local-variable t)
-(defvar makefile-browser-client
+(make-obsolete-variable 'makefile-browser-client nil "30.1")
+(defvar makefile-browser-client nil
"A buffer in Makefile mode that is currently using the browser.")
+(make-obsolete-variable 'makefile-browser-selection-vector nil "30.1")
(defvar makefile-browser-selection-vector nil)
(defvar makefile-has-prereqs nil)
(defvar makefile-need-target-pickup t)
@@ -757,15 +752,8 @@ dependency, despite the colon.
\\{makefile-mode-map}
-In the browser, use the following keys:
-
-\\{makefile-browser-map}
-
Makefile mode can be configured by modifying the following variables:
-`makefile-browser-buffer-name':
- Name of the macro- and target browser buffer.
-
`makefile-target-colon':
The string that gets appended to all target names
inserted by `makefile-insert-target'.
@@ -783,24 +771,6 @@ Makefile mode can be configured by modifying the following variables:
If you want a TAB (instead of a space) to be appended after the
target colon, then set this to a non-nil value.
-`makefile-browser-leftmost-column':
- Number of blanks to the left of the browser selection mark.
-
-`makefile-browser-cursor-column':
- Column in which the cursor is positioned when it moves
- up or down in the browser.
-
-`makefile-browser-selected-mark':
- String used to mark selected entries in the browser.
-
-`makefile-browser-unselected-mark':
- String used to mark unselected entries in the browser.
-
-`makefile-browser-auto-advance-after-selection-p':
- If this variable is set to a non-nil value the cursor
- will automagically advance to the next line after an item
- has been selected in the browser.
-
`makefile-pickup-everything-picks-up-filenames-p':
If this variable is set to a non-nil value then
`makefile-pickup-everything' also picks up filenames as targets
@@ -816,10 +786,6 @@ Makefile mode can be configured by modifying the following variables:
IMPORTANT: Please note that enabling this option causes Makefile mode
to MODIFY A FILE WITHOUT YOUR CONFIRMATION when \"it seems necessary\".
-`makefile-browser-hook':
- A function or list of functions to be called just before the
- browser is entered. This is executed in the makefile buffer.
-
`makefile-special-targets-list':
List of special targets. You will be offered to complete
on one of those in the minibuffer whenever you enter a `.'.
@@ -1306,6 +1272,7 @@ Fill comments, backslashed lines, and variable definitions specially."
;;; ------------------------------------------------------------
(defun makefile-browser-format-target-line (target selected)
+ (declare (obsolete nil "30.1"))
(format
(concat (make-string makefile-browser-leftmost-column ?\ )
(if selected
@@ -1315,6 +1282,7 @@ Fill comments, backslashed lines, and variable definitions specially."
target makefile-target-colon))
(defun makefile-browser-format-macro-line (macro selected)
+ (declare (obsolete nil "30.1"))
(format
(concat (make-string makefile-browser-leftmost-column ?\ )
(if selected
@@ -1323,14 +1291,21 @@ Fill comments, backslashed lines, and variable definitions specially."
(makefile-format-macro-ref macro))))
(defun makefile-browser-fill (targets macros)
+ (declare (obsolete nil "30.1"))
(let ((inhibit-read-only t))
(goto-char (point-min))
(erase-buffer)
(mapc
- (lambda (item) (insert (makefile-browser-format-target-line (car item) nil) "\n"))
+ (lambda (item) (insert (with-suppressed-warnings
+ ((obsolete makefile-browser-format-target-line))
+ (makefile-browser-format-target-line (car item) nil))
+ "\n"))
targets)
(mapc
- (lambda (item) (insert (makefile-browser-format-macro-line (car item) nil) "\n"))
+ (lambda (item) (insert (with-suppressed-warnings
+ ((obsolete makefile-browser-format-macro-line))
+ (makefile-browser-format-macro-line (car item) nil))
+ "\n"))
macros)
(sort-lines nil (point-min) (point-max))
(goto-char (1- (point-max)))
@@ -1344,6 +1319,7 @@ Fill comments, backslashed lines, and variable definitions specially."
(defun makefile-browser-next-line ()
"Move the browser selection cursor to the next line."
+ (declare (obsolete nil "30.1"))
(interactive)
(unless (makefile-last-line-p)
(forward-line 1)
@@ -1351,6 +1327,7 @@ Fill comments, backslashed lines, and variable definitions specially."
(defun makefile-browser-previous-line ()
"Move the browser selection cursor to the previous line."
+ (declare (obsolete nil "30.1"))
(interactive)
(unless (makefile-first-line-p)
(forward-line -1)
@@ -1362,6 +1339,7 @@ Fill comments, backslashed lines, and variable definitions specially."
(defun makefile-browser-quit ()
"Leave the browser and return to the makefile buffer."
+ (declare (obsolete nil "30.1"))
(interactive)
(let ((my-client makefile-browser-client))
(setq makefile-browser-client nil) ; we quit, so NO client!
@@ -1375,6 +1353,7 @@ Fill comments, backslashed lines, and variable definitions specially."
(defun makefile-browser-toggle ()
"Toggle the selection state of the browser item at the cursor position."
+ (declare (obsolete nil "30.1"))
(interactive)
(let ((this-line (count-lines (point-min) (point))))
(setq this-line (max 1 this-line))
@@ -1387,19 +1366,24 @@ Fill comments, backslashed lines, and variable definitions specially."
(let ((macro-name (makefile-browser-this-line-macro-name)))
(delete-region (point) (progn (end-of-line) (point)))
(insert
- (makefile-browser-format-macro-line
- macro-name
- (makefile-browser-get-state-for-line this-line))))
+ (with-suppressed-warnings
+ ((obsolete makefile-browser-format-macro-line))
+ (makefile-browser-format-macro-line
+ macro-name
+ (makefile-browser-get-state-for-line this-line)))))
(let ((target-name (makefile-browser-this-line-target-name)))
(delete-region (point) (progn (end-of-line) (point)))
(insert
- (makefile-browser-format-target-line
- target-name
- (makefile-browser-get-state-for-line this-line))))))
+ (with-suppressed-warnings
+ ((obsolete makefile-browser-format-target-line))
+ (makefile-browser-format-target-line
+ target-name
+ (makefile-browser-get-state-for-line this-line)))))))
(beginning-of-line)
(forward-char makefile-browser-cursor-column)
(if makefile-browser-auto-advance-after-selection-p
- (makefile-browser-next-line))))
+ (with-suppressed-warnings ((obsolete makefile-browser-next-line))
+ (makefile-browser-next-line)))))
;;;
;;; Making insertions into the client buffer
@@ -1412,6 +1396,7 @@ character, insert a new blank line, go to that line and indent by one TAB.
This is most useful in the process of creating continued lines when copying
large dependencies from the browser to the client buffer.
\(point) advances accordingly in the client buffer."
+ (declare (obsolete nil "30.1"))
(interactive)
(with-current-buffer makefile-browser-client
(end-of-line)
@@ -1420,6 +1405,7 @@ large dependencies from the browser to the client buffer.
(defun makefile-browser-insert-selection ()
"Insert all selected targets and/or macros in the makefile buffer.
Insertion takes place at point."
+ (declare (obsolete nil "30.1"))
(interactive)
(save-excursion
(goto-char (point-min))
@@ -1431,11 +1417,15 @@ Insertion takes place at point."
(setq current-line (1+ current-line))))))
(defun makefile-browser-insert-selection-and-quit ()
+ (declare (obsolete nil "30.1"))
(interactive)
- (makefile-browser-insert-selection)
- (makefile-browser-quit))
+ (with-suppressed-warnings ((obsolete makefile-browser-insert-selection)
+ (obsolete makefile-browser-quit))
+ (makefile-browser-insert-selection)
+ (makefile-browser-quit)))
(defun makefile-browser-send-this-line-item ()
+ (declare (obsolete nil "30.1"))
(if (makefile-browser-on-macro-line-p)
(save-excursion
(let ((macro-name (makefile-browser-this-line-macro-name)))
@@ -1447,10 +1437,12 @@ Insertion takes place at point."
(insert target-name " ")))))
(defun makefile-browser-start-interaction ()
+ (declare (obsolete nil "30.1"))
(use-local-map makefile-browser-map)
(setq buffer-read-only t))
(defun makefile-browse (targets macros)
+ (declare (obsolete imenu "30.1"))
(if (zerop (+ (length targets) (length macros)))
(progn
(beep)
@@ -1460,19 +1452,23 @@ Insertion takes place at point."
"Consider running \\[makefile-pickup-everything]"))))
(let ((browser-buffer (get-buffer-create makefile-browser-buffer-name)))
(pop-to-buffer browser-buffer)
- (makefile-browser-fill targets macros)
+ (with-suppressed-warnings ((obsolete makefile-browser-fill))
+ (makefile-browser-fill targets macros))
(shrink-window-if-larger-than-buffer)
(setq-local makefile-browser-selection-vector
(make-vector (+ (length targets) (length macros)) nil))
- (makefile-browser-start-interaction))))
+ (with-suppressed-warnings ((obsolete makefile-browser-start-interaction))
+ (makefile-browser-start-interaction)))))
(defun makefile-switch-to-browser ()
+ (declare (obsolete imenu "30.1"))
(interactive)
(run-hooks 'makefile-browser-hook)
(setq makefile-browser-client (current-buffer))
(makefile-pickup-targets)
(makefile-pickup-macros)
- (makefile-browse makefile-target-table makefile-macro-table))
+ (with-suppressed-warnings ((obsolete makefile-browse))
+ (makefile-browse makefile-target-table makefile-macro-table)))
@@ -1724,12 +1720,14 @@ This acts according to the value of `makefile-tab-after-target-colon'."
(defun makefile-browser-on-macro-line-p ()
"Determine if point is on a macro line in the browser."
+ (declare (obsolete nil "30.1"))
(save-excursion
(beginning-of-line)
(re-search-forward "\\$[{(]" (line-end-position) t)))
(defun makefile-browser-this-line-target-name ()
"Extract the target name from a line in the browser."
+ (declare (obsolete nil "30.1"))
(save-excursion
(end-of-line)
(skip-chars-backward "^ \t")
@@ -1737,6 +1735,7 @@ This acts according to the value of `makefile-tab-after-target-colon'."
(defun makefile-browser-this-line-macro-name ()
"Extract the macro name from a line in the browser."
+ (declare (obsolete nil "30.1"))
(save-excursion
(beginning-of-line)
(re-search-forward "\\$[{(]" (line-end-position) t)
@@ -1755,13 +1754,18 @@ Uses `makefile-use-curly-braces-for-macros-p'."
(format "$(%s)" macro-name))))
(defun makefile-browser-get-state-for-line (n)
+ (declare (obsolete nil "30.1"))
(aref makefile-browser-selection-vector (1- n)))
(defun makefile-browser-set-state-for-line (n to-state)
+ (declare (obsolete nil "30.1"))
(aset makefile-browser-selection-vector (1- n) to-state))
(defun makefile-browser-toggle-state-for-line (n)
- (makefile-browser-set-state-for-line n (not (makefile-browser-get-state-for-line n))))
+ (declare (obsolete nil "30.1"))
+ (with-suppressed-warnings ((obsolete makefile-browser-set-state-for-line)
+ (obsolete makefile-browser-get-state-for-line))
+ (makefile-browser-set-state-for-line n (not (makefile-browser-get-state-for-line n)))))
(defun makefile-last-line-p ()
(= (line-end-position) (point-max)))
diff --git a/lisp/progmodes/meta-mode.el b/lisp/progmodes/meta-mode.el
index eb83be3e317..6b34997799f 100644
--- a/lisp/progmodes/meta-mode.el
+++ b/lisp/progmodes/meta-mode.el
@@ -1,6 +1,6 @@
;;; meta-mode.el --- major mode for editing Metafont or MetaPost sources -*- lexical-binding:t -*-
-;; Copyright (C) 1997, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997, 2001-2024 Free Software Foundation, Inc.
;; Author: Ulrik Vieth <vieth@thphy.uni-duesseldorf.de>
;; Version: 1.0
diff --git a/lisp/progmodes/mixal-mode.el b/lisp/progmodes/mixal-mode.el
index ecf29ddffaf..7dd233479f0 100644
--- a/lisp/progmodes/mixal-mode.el
+++ b/lisp/progmodes/mixal-mode.el
@@ -1,6 +1,6 @@
;;; mixal-mode.el --- Major mode for the mix asm language. -*- lexical-binding:t -*-
-;; Copyright (C) 2003-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003-2024 Free Software Foundation, Inc.
;; Author: Pieter E.J. Pareit <pieter.pareit@gmail.com>
;; Maintainer: Jose A Ortega Ruiz <jao@gnu.org>
diff --git a/lisp/progmodes/octave.el b/lisp/progmodes/octave.el
index f45490ef6c3..cc47880bcbb 100644
--- a/lisp/progmodes/octave.el
+++ b/lisp/progmodes/octave.el
@@ -1,6 +1,6 @@
;;; octave.el --- editing octave source files under emacs -*- lexical-binding: t; -*-
-;; Copyright (C) 1997-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997-2024 Free Software Foundation, Inc.
;; Author: Kurt Hornik <Kurt.Hornik@wu-wien.ac.at>
;; John Eaton <jwe@octave.org>
@@ -768,7 +768,7 @@ Key bindings:
(setq-local comint-prompt-read-only inferior-octave-prompt-read-only)
(add-hook 'comint-input-filter-functions
'inferior-octave-directory-tracker nil t)
- ;; http://thread.gmane.org/gmane.comp.gnu.octave.general/48572
+ ;; http://thread.gmane.org/gmane.comp.gnu.octave.general/48572 [dead link]
(add-hook 'window-configuration-change-hook
'inferior-octave-track-window-width-change nil t)
(setq-local compilation-error-regexp-alist inferior-octave-error-regexp-alist)
@@ -1007,7 +1007,7 @@ directory and makes this the current buffer's default directory."
(defvar inferior-octave-last-column-width nil)
(defun inferior-octave-track-window-width-change ()
- ;; http://thread.gmane.org/gmane.comp.gnu.octave.general/48572
+ ;; http://thread.gmane.org/gmane.comp.gnu.octave.general/48572 [dead link]
(let ((width (max inferior-octave-minimal-columns (window-width))))
(unless (eq inferior-octave-last-column-width width)
(setq-local inferior-octave-last-column-width width)
diff --git a/lisp/progmodes/opascal.el b/lisp/progmodes/opascal.el
index 0c503ab0fab..5e8263cb646 100644
--- a/lisp/progmodes/opascal.el
+++ b/lisp/progmodes/opascal.el
@@ -1,6 +1,6 @@
;;; opascal.el --- major mode for editing Object Pascal source in Emacs -*- lexical-binding: t -*-
-;; Copyright (C) 1998-1999, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-1999, 2001-2024 Free Software Foundation, Inc.
;; Authors: Ray Blaak <blaak@infomatch.com>,
;; Simon South <ssouth@member.fsf.org>
diff --git a/lisp/progmodes/pascal.el b/lisp/progmodes/pascal.el
index 0c73ea086a4..bd39b64aefc 100644
--- a/lisp/progmodes/pascal.el
+++ b/lisp/progmodes/pascal.el
@@ -1,6 +1,6 @@
;;; pascal.el --- major mode for editing pascal source in Emacs -*- lexical-binding: t -*-
-;; Copyright (C) 1993-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1993-2024 Free Software Foundation, Inc.
;; Author: Espen Skoglund <esk@gnu.org>
;; Keywords: languages
diff --git a/lisp/progmodes/perl-mode.el b/lisp/progmodes/perl-mode.el
index ab6333e4b23..f74390841fe 100644
--- a/lisp/progmodes/perl-mode.el
+++ b/lisp/progmodes/perl-mode.el
@@ -1,6 +1,6 @@
;;; perl-mode.el --- Perl code editing commands for GNU Emacs -*- lexical-binding:t -*-
-;; Copyright (C) 1990, 1994, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1990, 1994, 2001-2024 Free Software Foundation, Inc.
;; Author: William F. Mann
;; Maintainer: emacs-devel@gnu.org
@@ -47,10 +47,6 @@
;; comment; move to end of line; create an empty comment; tell you that
;; the line ends in a quoted string, or has a # which should be a \#.
-;; If your machine is slow, you may want to remove some of the bindings
-;; to perl-electric-terminator. I changed the indenting defaults to be
-;; what Larry Wall uses in perl/lib, but left in all the options.
-
;; I also tuned a few things: comments and labels starting in column
;; zero are left there by perl-indent-exp; perl-beginning-of-function
;; goes back to the first open brace/paren in column zero, the open brace
@@ -227,7 +223,10 @@
"\\|=>"
"\\|[?:.,;|&*=!~({[]"
"\\|[^-+][-+]" ;Bug#42168: `+' is intro but `++' isn't!
- "\\|\\(^\\)\\)[ \t\n]*")))
+ "\\|\\(^\\)\\)[ \t\n]*"))
+
+ (defconst perl--format-regexp "^[ \t]*format.*=[ \t]*\\(\n\\)"
+ "Regexp to match the start of a format declaration."))
(defun perl-syntax-propertize-function (start end)
(let ((case-fold-search nil))
@@ -256,7 +255,7 @@
;; Handle funny names like $DB'stop.
("\\$ ?{?\\^?[_[:alpha:]][_[:alnum:]]*\\('\\)[_[:alpha:]]" (1 "_"))
;; format statements
- ("^[ \t]*format.*=[ \t]*\\(\n\\)"
+ (perl--format-regexp
(1 (prog1 "\"" (perl-syntax-propertize-special-constructs end))))
;; Propertize perl prototype chars `$%&*;+@\[]' as punctuation
;; in `sub' arg-specs like `sub myfun ($)' and `sub ($)'. But
@@ -469,7 +468,7 @@
(scan-error (goto-char startpos) nil))
(not (or (nth 8 (parse-partial-sexp
;; Since we don't know if point is within
- ;; the first or the scond arg, we have to
+ ;; the first or the second arg, we have to
;; start from the beginning.
(if twoargs (1+ (nth 8 state)) (point))
limit nil nil state 'syntax-table))
@@ -515,7 +514,7 @@
(string-to-syntax "|e")
(string-to-syntax "\"e")))
(forward-char 1)
- ;; Re-use perl-syntax-propertize-special-constructs to handle the
+ ;; Reuse perl-syntax-propertize-special-constructs to handle the
;; second part (the first delimiter of second part can't be
;; preceded by "s" or "tr" or "y", so it will not be considered
;; as twoarg).
@@ -950,6 +949,17 @@ changed by, or (parse-state) if line starts in a quoted string."
(goto-char (- (point-max) pos)))
shift-amt))
+(defun perl--end-of-format-p ()
+ "Non-nil if point is at the end of a format declaration, skipping whitespace."
+ (save-excursion
+ (skip-chars-backward " \t\n")
+ (beginning-of-line)
+ (when-let ((comm (and (looking-at "^\\.$")
+ (nth 8 (syntax-ppss)))))
+ (goto-char comm)
+ (beginning-of-line)
+ (looking-at perl--format-regexp))))
+
(defun perl-continuation-line-p ()
"Move to end of previous line and return non-nil if continued."
;; Statement level. Is it a continuation or a new statement?
@@ -963,12 +973,13 @@ changed by, or (parse-state) if line starts in a quoted string."
(beginning-of-line)
(perl-backward-to-noncomment))
;; Now we get the answer.
- (unless (memq (preceding-char) '(?\; ?\} ?\{))
+ (unless (or (memq (preceding-char) '(?\; ?\} ?\{))
+ (perl--end-of-format-p))
(preceding-char)))
(defun perl-hanging-paren-p ()
"Non-nil if we are right after a hanging parenthesis-like char."
- (and (looking-at "[ \t]*$")
+ (and (looking-at "[ \t]*\\(?:#.*\\)?$")
(save-excursion
(skip-syntax-backward " (") (not (bolp)))))
@@ -1003,7 +1014,9 @@ Returns (parse-state) if line starts inside a string."
(state (syntax-ppss))
(containing-sexp (nth 1 state))
;; Don't auto-indent in a quoted string or a here-document.
- (unindentable (or (nth 3 state) (eq 2 (nth 7 state)))))
+ (unindentable (or (nth 3 state) (eq 2 (nth 7 state))))
+ (format (and (nth 3 state)
+ (char-equal (nth 3 state) ?\n))))
(when (and (eq t (nth 3 state))
(save-excursion
(goto-char (nth 8 state))
@@ -1013,7 +1026,7 @@ Returns (parse-state) if line starts inside a string."
(setq unindentable nil)
(setq containing-sexp (nth 8 state)))
(cond
- (unindentable 'noindent)
+ (unindentable (if format 0 'noindent))
((null containing-sexp) ; Line is at top level.
(skip-chars-forward " \t\f")
(if (memq (following-char)
@@ -1022,7 +1035,8 @@ Returns (parse-state) if line starts inside a string."
;; indent a little if this is a continuation line
(perl-backward-to-noncomment)
(if (or (bobp)
- (memq (preceding-char) '(?\; ?\})))
+ (memq (preceding-char) '(?\; ?\}))
+ (perl--end-of-format-p))
0 perl-continued-statement-offset)))
((/= (char-after containing-sexp) ?{)
;; line is expression, not statement:
diff --git a/lisp/progmodes/prog-mode.el b/lisp/progmodes/prog-mode.el
index 16497097061..d4e0514a6c3 100644
--- a/lisp/progmodes/prog-mode.el
+++ b/lisp/progmodes/prog-mode.el
@@ -1,6 +1,6 @@
;;; prog-mode.el --- Generic major mode for programming -*- lexical-binding: t -*-
-;; Copyright (C) 2013-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2024 Free Software Foundation, Inc.
;; Maintainer: emacs-devel@gnu.org
;; Keywords: internal
@@ -37,6 +37,7 @@
(declare-function treesit-parser-list "treesit.c")
(declare-function treesit-node-type "treesit.c")
(declare-function treesit-node-at "treesit.c")
+(declare-function treesit-node-match-p "treesit.c")
(defgroup prog-mode nil
"Generic programming mode, from which others derive."
@@ -160,9 +161,8 @@ or follows point."
(let ((treesit-text-node
(and (treesit-available-p)
(treesit-parser-list)
- (string-match-p
- treesit-text-type-regexp
- (treesit-node-type (treesit-node-at (point)))))))
+ (treesit-node-match-p
+ (treesit-node-at (point)) 'text t))))
(if (or treesit-text-node
(nth 8 (syntax-ppss))
(re-search-forward "\\s-*\\s<" (line-end-position) t))
@@ -248,7 +248,10 @@ If set to the symbol `right-edge', also unprettify if point
is immediately after the symbol. The prettification will be
reapplied as soon as point moves away from the symbol. If
set to nil, the prettification persists even when point is
-on the symbol."
+on the symbol.
+
+This will only have an effect if it is set to a non-nil value
+before `prettify-symbols-mode' is activated."
:version "25.1"
:type '(choice (const :tag "Never unprettify" nil)
(const :tag "Unprettify when point is inside" t)
diff --git a/lisp/progmodes/project.el b/lisp/progmodes/project.el
index 6f35b3cc1b1..a6f14a0865c 100644
--- a/lisp/progmodes/project.el
+++ b/lisp/progmodes/project.el
@@ -1,11 +1,11 @@
;;; project.el --- Operations on the current project -*- lexical-binding: t; -*-
-;; Copyright (C) 2015-2023 Free Software Foundation, Inc.
-;; Version: 0.9.8
+;; Copyright (C) 2015-2024 Free Software Foundation, Inc.
+;; Version: 0.10.0
;; Package-Requires: ((emacs "26.1") (xref "1.4.0"))
-;; This is a GNU ELPA :core package. Avoid using functionality that
-;; not compatible with the version of Emacs recorded above.
+;; This is a GNU ELPA :core package. Avoid functionality that is not
+;; compatible with the version of Emacs recorded above.
;; This file is part of GNU Emacs.
@@ -245,7 +245,12 @@ of the project instance object."
pr))
(defun project--find-in-directory (dir)
- (run-hook-with-args-until-success 'project-find-functions dir))
+ ;; Use 'ignore-error' when 27.1 is the minimum supported.
+ (condition-case nil
+ (run-hook-with-args-until-success 'project-find-functions dir)
+ ;; Maybe we'd like to continue to the next backend instead? Let's
+ ;; see if somebody ever ends up in that situation.
+ (permission-denied nil)))
(defvar project--within-roots-fallback nil)
@@ -410,7 +415,8 @@ the buffer's value of `default-directory'."
(defcustom project-vc-ignores nil
"List of patterns to add to `project-ignores'."
:type '(repeat string))
-;;;###autoload(put 'project-vc-ignores 'safe-local-variable #'listp)
+;; Change to `list-of-strings-p' when support for Emacs 28 is dropped.
+;;;###autoload(put 'project-vc-ignores 'safe-local-variable (lambda (val) (and (listp val) (not (memq nil (mapcar #'stringp val))))))
(defcustom project-vc-merge-submodules t
"Non-nil to consider submodules part of the parent project.
@@ -465,6 +471,7 @@ variables, such as `project-vc-ignores' or `project-vc-name'."
:type '(repeat string)
:version "29.1"
:package-version '(project . "0.9.0"))
+;; Change to `list-of-strings-p' when support for Emacs 28 is dropped.
;;;###autoload(put 'project-vc-extra-root-markers 'safe-local-variable (lambda (val) (and (listp val) (not (memq nil (mapcar #'stringp val))))))
;; FIXME: Using the current approach, major modes are supposed to set
@@ -565,6 +572,12 @@ See `project-vc-extra-root-markers' for the marker value format.")
(let* ((parent (file-name-directory (directory-file-name root))))
(setq root (vc-call-backend 'Git 'root parent))))
(when root
+ (when (not backend)
+ (let* ((project-vc-extra-root-markers nil)
+ ;; Avoid submodules scan.
+ (enable-dir-local-variables nil)
+ (parent (project-try-vc root)))
+ (and parent (setq backend (nth 1 parent)))))
(setq project (list 'vc backend root))
;; FIXME: Cache for a shorter time.
(vc-file-setprop dir 'project-vc project)
@@ -639,6 +652,7 @@ See `project-vc-extra-root-markers' for the marker value format.")
(include-untracked (project--value-in-dir
'project-vc-include-untracked
dir))
+ (submodules (project--git-submodules))
files)
(setq args (append args
'("-c" "--exclude-standard")
@@ -670,23 +684,25 @@ See `project-vc-extra-root-markers' for the marker value format.")
i)))
extra-ignores)))))
(setq files
- (mapcar
- (lambda (file) (concat default-directory file))
- (split-string
- (apply #'vc-git--run-command-string nil "ls-files" args)
- "\0" t)))
+ (delq nil
+ (mapcar
+ (lambda (file)
+ (unless (member file submodules)
+ (concat default-directory file)))
+ (split-string
+ (apply #'vc-git--run-command-string nil "ls-files" args)
+ "\0" t))))
(when (project--vc-merge-submodules-p default-directory)
;; Unfortunately, 'ls-files --recurse-submodules' conflicts with '-o'.
- (let* ((submodules (project--git-submodules))
- (sub-files
- (mapcar
- (lambda (module)
- (when (file-directory-p module)
- (project--vc-list-files
- (concat default-directory module)
- backend
- extra-ignores)))
- submodules)))
+ (let ((sub-files
+ (mapcar
+ (lambda (module)
+ (when (file-directory-p module)
+ (project--vc-list-files
+ (concat default-directory module)
+ backend
+ extra-ignores)))
+ submodules)))
(setq files
(apply #'nconc files sub-files))))
;; 'git ls-files' returns duplicate entries for merge conflicts.
@@ -731,11 +747,10 @@ See `project-vc-extra-root-markers' for the marker value format.")
(cl-defmethod project-ignores ((project (head vc)) dir)
(let* ((root (nth 2 project))
- backend)
+ (backend (cadr project)))
(append
(when (and backend
(file-equal-p dir root))
- (setq backend (cadr project))
(delq
nil
(mapcar
@@ -840,6 +855,7 @@ DIRS must contain directory names."
(define-key map "G" 'project-or-external-find-regexp)
(define-key map "r" 'project-query-replace-regexp)
(define-key map "x" 'project-execute-extended-command)
+ (define-key map "o" 'project-any-command)
(define-key map "\C-b" 'project-list-buffers)
map)
"Keymap for project commands.")
@@ -873,6 +889,17 @@ DIRS must contain directory names."
(call-interactively cmd)
(user-error "%s is undefined" (key-description key)))))
+(defun project--other-place-prefix (place &optional extra-keymap)
+ (cl-assert (member place '(window frame tab)))
+ (prefix-command-preserve-state)
+ (let ((inhibit-message t)) (funcall (intern (format "other-%s-prefix" place))))
+ (message "Display next project command buffer in a new %s..." place)
+ ;; Should return exitfun from set-transient-map
+ (set-transient-map (if extra-keymap
+ (make-composed-keymap project-prefix-map
+ extra-keymap)
+ project-prefix-map)))
+
;;;###autoload
(defun project-other-window-command ()
"Run project command, displaying resultant buffer in another window.
@@ -882,9 +909,11 @@ The following commands are available:
\\{project-prefix-map}
\\{project-other-window-map}"
(interactive)
- (project--other-place-command '((display-buffer-pop-up-window)
- (inhibit-same-window . t))
- project-other-window-map))
+ (if (< emacs-major-version 30)
+ (project--other-place-command '((display-buffer-pop-up-window)
+ (inhibit-same-window . t))
+ project-other-window-map)
+ (project--other-place-prefix 'window project-other-window-map)))
;;;###autoload (define-key ctl-x-4-map "p" #'project-other-window-command)
@@ -897,8 +926,10 @@ The following commands are available:
\\{project-prefix-map}
\\{project-other-frame-map}"
(interactive)
- (project--other-place-command '((display-buffer-pop-up-frame))
- project-other-frame-map))
+ (if (< emacs-major-version 30)
+ (project--other-place-command '((display-buffer-pop-up-frame))
+ project-other-frame-map)
+ (project--other-place-prefix 'frame project-other-frame-map)))
;;;###autoload (define-key ctl-x-5-map "p" #'project-other-frame-command)
@@ -910,7 +941,9 @@ The following commands are available:
\\{project-prefix-map}"
(interactive)
- (project--other-place-command '((display-buffer-in-new-tab))))
+ (if (< emacs-major-version 30)
+ (project--other-place-command '((display-buffer-in-new-tab)))
+ (project--other-place-prefix 'tab)))
;;;###autoload
(when (bound-and-true-p tab-prefix-map)
@@ -989,6 +1022,23 @@ pattern to search for."
(read-regexp "Find regexp" (and sym (regexp-quote sym))
project-regexp-history-variable)))
+(defun project--find-default-from (filename project)
+ "Ensure FILENAME is in PROJECT.
+
+Usually, just return FILENAME. But if
+`project-current-directory-override' is set, adjust it to be
+relative to PROJECT instead.
+
+This supports using a relative file name from the current buffer
+when switching projects with `project-switch-project' and then
+using a command like `project-find-file'."
+ (if-let (filename-proj (and project-current-directory-override
+ (project-current nil default-directory)))
+ ;; file-name-concat requires Emacs 28+
+ (concat (file-name-as-directory (project-root project))
+ (file-relative-name filename (project-root filename-proj)))
+ filename))
+
;;;###autoload
(defun project-find-file (&optional include-all)
"Visit a file (with completion) in the current project.
@@ -1006,16 +1056,7 @@ for VCS directories listed in `vc-directory-exclusion-list'."
(dirs (list root)))
(project-find-file-in
(or (thing-at-point 'filename)
- (and buffer-file-name
- (if-let (buffer-proj (and project-current-directory-override
- (project-current nil default-directory)))
- ;; Allow using the relative file name of the current
- ;; buffer in "other project" as well.
- (let ((buffer-root (project-root buffer-proj)))
- ;; file-name-concat requires Emacs 28+
- (concat (file-name-as-directory root)
- (file-relative-name buffer-file-name buffer-root)))
- buffer-file-name)))
+ (and buffer-file-name (project--find-default-from buffer-file-name pr)))
dirs pr include-all)))
;;;###autoload
@@ -1023,17 +1064,23 @@ for VCS directories listed in `vc-directory-exclusion-list'."
"Visit a file (with completion) in the current project or external roots.
The filename at point (determined by `thing-at-point'), if any,
-is available as part of \"future history\".
+is available as part of \"future history\". If none, the current
+buffer's file name is used.
If INCLUDE-ALL is non-nil, or with prefix argument when called
interactively, include all files under the project root, except
for VCS directories listed in `vc-directory-exclusion-list'."
(interactive "P")
+ (defvar project-file-history-behavior)
(let* ((pr (project-current t))
(dirs (cons
(project-root pr)
- (project-external-roots pr))))
- (project-find-file-in (thing-at-point 'filename) dirs pr include-all)))
+ (project-external-roots pr)))
+ (project-file-history-behavior t))
+ (project-find-file-in
+ (or (thing-at-point 'filename)
+ (and buffer-file-name (project--find-default-from buffer-file-name pr)))
+ dirs pr include-all)))
(defcustom project-read-file-name-function #'project--read-file-cpd-relative
"Function to call to read a file name from a list.
@@ -1046,6 +1093,27 @@ For the arguments list, see `project--read-file-cpd-relative'."
:group 'project
:version "27.1")
+(defcustom project-file-history-behavior t
+ "If `relativize', entries in `file-name-history' are adjusted.
+
+History entries shown in `project-find-file', `project-find-dir',
+(from `file-name-history') are adjusted to be relative to the
+current project root, instead of the project which added those
+paths. This only affects history entries added by earlier calls
+to `project-find-file' or `project-find-dir'.
+
+This has the effect of sharing more history between projects."
+ :type '(choice (const :tag "Default behavior" t)
+ (const :tag "Adjust to be relative to current" relativize))
+ :group 'project
+ :version "30.1")
+
+(defun project--transplant-file-name (filename project)
+ (when-let ((old-root (get-text-property 0 'project filename)))
+ (expand-file-name
+ (file-relative-name filename old-root)
+ (project-root project))))
+
(defun project--read-file-cpd-relative (prompt
all-files &optional predicate
hist mb-default)
@@ -1077,23 +1145,22 @@ by the user at will."
(_ (when included-cpd
(setq substrings (cons "./" substrings))))
(new-collection (project--file-completion-table substrings))
- (abbr-cpd (abbreviate-file-name common-parent-directory))
- (abbr-cpd-length (length abbr-cpd))
- (relname (cl-letf ((history-add-new-input nil)
- ((symbol-value hist)
- (mapcan
- (lambda (s)
- (and (string-prefix-p abbr-cpd s)
- (not (eq abbr-cpd-length (length s)))
- (list (substring s abbr-cpd-length))))
- (symbol-value hist))))
+ (abs-cpd (expand-file-name common-parent-directory))
+ (abs-cpd-length (length abs-cpd))
+ (relname (cl-letf* ((non-essential t) ;Avoid new Tramp connections.
+ ((symbol-value hist)
+ (mapcan
+ (lambda (s)
+ (setq s (expand-file-name s))
+ (and (string-prefix-p abs-cpd s)
+ (not (eq abs-cpd-length (length s)))
+ (list (substring s abs-cpd-length))))
+ (symbol-value hist))))
(project--completing-read-strict prompt
new-collection
predicate
hist mb-default)))
(absname (expand-file-name relname common-parent-directory)))
- (when (and hist history-add-new-input)
- (add-to-history hist (abbreviate-file-name absname)))
absname))
(defun project--read-file-absolute (prompt
@@ -1104,6 +1171,29 @@ by the user at will."
predicate
hist mb-default))
+(defun project--read-file-name ( project prompt
+ all-files &optional predicate
+ hist mb-default)
+ "Call `project-read-file-name-function' with appropriate history.
+
+Depending on `project-file-history-behavior', entries are made
+project-relative where possible."
+ (let ((file
+ (cl-letf ((history-add-new-input nil)
+ ((symbol-value hist)
+ (if (eq project-file-history-behavior 'relativize)
+ (mapcar
+ (lambda (f)
+ (or (project--transplant-file-name f project) f))
+ (symbol-value hist))
+ (symbol-value hist))))
+ (funcall project-read-file-name-function
+ prompt all-files predicate hist mb-default))))
+ (when (and hist history-add-new-input)
+ (add-to-history hist
+ (propertize file 'project (project-root project))))
+ file))
+
(defun project-find-file-in (suggested-filename dirs project &optional include-all)
"Complete a file name in DIRS in PROJECT and visit the result.
@@ -1124,9 +1214,10 @@ directories listed in `vc-directory-exclusion-list'."
dirs)
(project-files project dirs)))
(completion-ignore-case read-file-name-completion-ignore-case)
- (file (funcall project-read-file-name-function
- "Find file" all-files nil 'file-name-history
- suggested-filename)))
+ (file (project--read-file-name
+ project "Find file"
+ all-files nil 'file-name-history
+ suggested-filename)))
(if (string= file "")
(user-error "You didn't specify the file")
(find-file file))))
@@ -1147,7 +1238,10 @@ directories listed in `vc-directory-exclusion-list'."
;;;###autoload
(defun project-find-dir ()
- "Start Dired in a directory inside the current project."
+ "Start Dired in a directory inside the current project.
+
+The current buffer's `default-directory' is available as part of
+\"future history\"."
(interactive)
(let* ((project (project-current t))
(all-files (project-files project))
@@ -1158,11 +1252,13 @@ directories listed in `vc-directory-exclusion-list'."
;; https://stackoverflow.com/a/50685235/615245 for possible
;; implementation.
(all-dirs (mapcar #'file-name-directory all-files))
- (dir (funcall project-read-file-name-function
- "Dired"
- ;; Some completion UIs show duplicates.
- (delete-dups all-dirs)
- nil 'file-name-history)))
+ (dir (project--read-file-name
+ project "Dired"
+ ;; Some completion UIs show duplicates.
+ (delete-dups all-dirs)
+ nil 'file-name-history
+ (and default-directory
+ (project--find-default-from default-directory project)))))
(dired dir)))
;;;###autoload
@@ -1240,8 +1336,7 @@ command \\[fileloop-continue]."
(interactive "sSearch (regexp): ")
(fileloop-initialize-search
regexp
- ;; XXX: See the comment in project-query-replace-regexp.
- (cl-delete-if-not #'file-regular-p (project-files (project-current t)))
+ (project-files (project-current t))
'default)
(fileloop-continue))
@@ -1262,10 +1357,7 @@ If you exit the `query-replace', you can later continue the
(list from to))))
(fileloop-initialize-replace
from to
- ;; XXX: Filter out Git submodules, which are not regular files.
- ;; `project-files' can return those, which is arguably suboptimal,
- ;; but removing them eagerly has performance cost.
- (cl-delete-if-not #'file-regular-p (project-files (project-current t)))
+ (project-files (project-current t))
'default)
(fileloop-continue))
@@ -1551,7 +1643,7 @@ Also see the `project-kill-buffers-display-buffer-list' variable."
(yes-or-no-p
(format "Kill %d buffers in %s? "
(length bufs)
- (project-root pr))))))
+ (project-name pr))))))
(cond (no-confirm
(mapc #'kill-buffer bufs))
((null bufs)
@@ -1597,7 +1689,12 @@ With some possible metadata (to be decided).")
(when (file-exists-p filename)
(with-temp-buffer
(insert-file-contents filename)
- (read (current-buffer)))))
+ (mapcar
+ (lambda (elem)
+ (let ((name (car elem)))
+ (list (if (file-remote-p name) name
+ (abbreviate-file-name name)))))
+ (read (current-buffer))))))
(unless (seq-every-p
(lambda (elt) (stringp (car-safe elt)))
project--list)
@@ -1617,16 +1714,20 @@ With some possible metadata (to be decided).")
(insert ";;; -*- lisp-data -*-\n")
(let ((print-length nil)
(print-level nil))
- (pp project--list (current-buffer)))
+ (pp (mapcar (lambda (elem)
+ (let ((name (car elem)))
+ (list (if (file-remote-p name) name
+ (expand-file-name name)))))
+ project--list)
+ (current-buffer)))
(write-region nil nil filename nil 'silent))))
-;;;###autoload
-(defun project-remember-project (pr &optional no-write)
- "Add project PR to the front of the project list.
+(defun project--remember-dir (root &optional no-write)
+ "Add project root ROOT to the front of the project list.
Save the result in `project-list-file' if the list of projects
has changed, and NO-WRITE is nil."
(project--ensure-read-project-list)
- (let ((dir (project-root pr)))
+ (let ((dir (abbreviate-file-name root)))
(unless (equal (caar project--list) dir)
(dolist (ent project--list)
(when (equal dir (car ent))
@@ -1635,6 +1736,13 @@ has changed, and NO-WRITE is nil."
(unless no-write
(project--write-project-list)))))
+;;;###autoload
+(defun project-remember-project (pr &optional no-write)
+ "Add project PR to the front of the project list.
+Save the result in `project-list-file' if the list of projects
+has changed, and NO-WRITE is nil."
+ (project--remember-dir (project-root pr) no-write))
+
(defun project--remove-from-project-list (project-root report-message)
"Remove directory PROJECT-ROOT of a missing project from the project list.
If the directory was in the list before the removal, save the
@@ -1642,7 +1750,7 @@ result in `project-list-file'. Announce the project's removal
from the list using REPORT-MESSAGE, which is a format string
passed to `message' as its first argument."
(project--ensure-read-project-list)
- (when-let ((ent (assoc project-root project--list)))
+ (when-let ((ent (assoc (abbreviate-file-name project-root) project--list)))
(setq project--list (delq ent project--list))
(message report-message project-root)
(project--write-project-list)))
@@ -1656,6 +1764,8 @@ the project list."
(project--remove-from-project-list
project-root "Project `%s' removed from known projects"))
+(defvar project--dir-history)
+
(defun project-prompt-project-dir ()
"Prompt the user for a directory that is one of the known project roots.
The project is chosen among projects known from the project list,
@@ -1668,28 +1778,38 @@ It's also possible to enter an arbitrary directory not in the list."
;; completion style).
(project--file-completion-table
(append project--list `(,dir-choice))))
+ (project--dir-history (project-known-project-roots))
(pr-dir ""))
(while (equal pr-dir "")
;; If the user simply pressed RET, do this again until they don't.
- (setq pr-dir (completing-read "Select project: " choices nil t)))
+ (setq pr-dir
+ (let (history-add-new-input)
+ (completing-read "Select project: " choices nil t nil 'project--dir-history))))
(if (equal pr-dir dir-choice)
(read-directory-name "Select directory: " default-directory nil t)
pr-dir)))
+(defvar project--name-history)
+
(defun project-prompt-project-name ()
"Prompt the user for a project, by name, that is one of the known project roots.
The project is chosen among projects known from the project list,
see `project-list-file'.
It's also possible to enter an arbitrary directory not in the list."
(let* ((dir-choice "... (choose a dir)")
+ project--name-history
(choices
(let (ret)
- (dolist (dir (project-known-project-roots))
- ;; we filter out directories that no longer map to a project,
+ ;; Iterate in reverse order so project--name-history is in
+ ;; the same order as project--list.
+ (dolist (dir (reverse (project-known-project-roots)))
+ ;; We filter out directories that no longer map to a project,
;; since they don't have a clean project-name.
- (if-let (proj (project--find-in-directory dir))
- (push (cons (project-name proj) proj) ret)))
- ret))
+ (when-let ((proj (project--find-in-directory dir))
+ (name (project-name proj)))
+ (push name project--name-history)
+ (push (cons name proj) ret)))
+ (reverse ret)))
;; XXX: Just using this for the category (for the substring
;; completion style).
(table (project--file-completion-table
@@ -1697,7 +1817,9 @@ It's also possible to enter an arbitrary directory not in the list."
(pr-name ""))
(while (equal pr-name "")
;; If the user simply pressed RET, do this again until they don't.
- (setq pr-name (completing-read "Select project: " table nil t)))
+ (setq pr-name
+ (let (history-add-new-input)
+ (completing-read "Select project: " table nil t nil 'project--name-history))))
(if (equal pr-name dir-choice)
(read-directory-name "Select directory: " default-directory nil t)
(let ((proj (assoc pr-name choices)))
@@ -1717,6 +1839,44 @@ It's also possible to enter an arbitrary directory not in the list."
(let ((default-directory (project-root (project-current t))))
(call-interactively #'execute-extended-command)))
+;;;###autoload
+(defun project-any-command (&optional overriding-map prompt-format)
+ "Run the next command in the current project.
+
+If the command name starts with `project-', or its symbol has
+property `project-aware', it gets passed the project to use
+with the variable `project-current-directory-override'.
+Otherwise, `default-directory' is temporarily set to the current
+project's root.
+
+If OVERRIDING-MAP is non-nil, it will be used as
+`overriding-local-map' to provide shorter bindings from that map
+which will take priority over the global ones."
+ (interactive)
+ (let* ((pr (project-current t))
+ (prompt-format (or prompt-format "[execute in %s]:"))
+ (command (let ((overriding-local-map overriding-map))
+ (key-binding (read-key-sequence
+ (format prompt-format (project-root pr)))
+ t)))
+ (root (project-root pr)))
+ (when command
+ (if (when (symbolp command)
+ (or (string-prefix-p "project-" (symbol-name command))
+ (get command 'project-aware)))
+ (let ((project-current-directory-override root))
+ (call-interactively command))
+ (let ((default-directory root))
+ (call-interactively command))))))
+
+;;;###autoload
+(defun project-prefix-or-any-command ()
+ "Run the next command in the current project.
+Works like `project-any-command', but also mixes in the shorter
+bindings from `project-prefix-map'."
+ (interactive)
+ (project-any-command project-prefix-map "[execute in %s]:"))
+
(defun project-remember-projects-under (dir &optional recursive)
"Index all projects below a directory DIR.
If RECURSIVE is non-nil, recurse into all subdirectories to find
@@ -1725,35 +1885,28 @@ the progress. The function returns the number of detected
projects."
(interactive "DDirectory: \nP")
(project--ensure-read-project-list)
- (let ((queue (list dir))
- (count 0)
- (known (make-hash-table
- :size (* 2 (length project--list))
- :test #'equal )))
+ (let ((dirs (if recursive
+ (directory-files-recursively dir "" t)
+ (directory-files dir t)))
+ (known (make-hash-table :size (* 2 (length project--list))
+ :test #'equal))
+ (count 0))
(dolist (project (mapcar #'car project--list))
(puthash project t known))
- (while queue
- (when-let ((subdir (pop queue))
- ((file-directory-p subdir)))
- (when-let ((project (project--find-in-directory subdir))
- (project-root (project-root project))
- ((not (gethash project-root known))))
- (project-remember-project project t)
- (puthash project-root t known)
- (message "Found %s..." project-root)
- (setq count (1+ count)))
- (when (and recursive (file-directory-p subdir))
- (setq queue
- (nconc
- (directory-files
- subdir t directory-files-no-dot-files-regexp t)
- queue)))))
- (unless (eq recursive 'in-progress)
- (if (zerop count)
- (message "No projects were found")
- (project--write-project-list)
- (message "%d project%s were found"
- count (if (= count 1) "" "s"))))
+ (dolist (subdir dirs)
+ (when-let (((file-directory-p subdir))
+ (project (project--find-in-directory subdir))
+ (project-root (project-root project))
+ ((not (gethash project-root known))))
+ (project-remember-project project t)
+ (puthash project-root t known)
+ (message "Found %s..." project-root)
+ (setq count (1+ count))))
+ (if (zerop count)
+ (message "No projects were found")
+ (project--write-project-list)
+ (message "%d project%s were found"
+ count (if (= count 1) "" "s")))
count))
(defun project-forget-zombie-projects ()
@@ -1795,7 +1948,8 @@ forgotten projects."
(project-find-regexp "Find regexp")
(project-find-dir "Find directory")
(project-vc-dir "VC-Dir")
- (project-eshell "Eshell"))
+ (project-eshell "Eshell")
+ (project-any-command "Other"))
"Alist mapping commands to descriptions.
Used by `project-switch-project' to construct a dispatch menu of
commands available upon \"switching\" to another project.
@@ -1819,7 +1973,9 @@ invoked immediately without any dispatch menu."
(choice :tag "Key to press"
(const :tag "Infer from the keymap" nil)
(character :tag "Explicit key"))))
- (symbol :tag "Single command")))
+ (const :tag "Use both short keys and global bindings"
+ project-prefix-or-any-command)
+ (symbol :tag "Custom command")))
(defcustom project-switch-use-entire-map nil
"Whether `project-switch-project' will use the entire `project-prefix-map'.
@@ -1832,7 +1988,28 @@ listed in the dispatch menu produced from `project-switch-commands'."
:group 'project
:version "28.1")
+(defcustom project-key-prompt-style (if (facep 'help-key-binding)
+ t
+ 'brackets)
+ "Which presentation to use when asking to choose a command by key.
+
+When `brackets', use text brackets and `bold' for the character.
+Otherwise, use the face `help-key-binding' in the prompt."
+ :type '(choice (const :tag "Using help-key-binding face" t)
+ (const :tag "Using bold face and brackets" brackets))
+ :group 'project
+ :version "30.1")
+
(defun project--keymap-prompt ()
+ "Return a prompt for the project switching using the prefix map."
+ (let (keys)
+ (map-keymap
+ (lambda (evt _)
+ (when (characterp evt) (push evt keys)))
+ project-prefix-map)
+ (mapconcat (lambda (key) (help-key-description (string key) nil)) keys " ")))
+
+(defun project--menu-prompt ()
"Return a prompt for the project switching dispatch menu."
(mapconcat
(pcase-lambda (`(,cmd ,label ,key))
@@ -1844,7 +2021,7 @@ listed in the dispatch menu produced from `project-switch-commands'."
(let ((key (if key
(vector key)
(where-is-internal cmd (list project-prefix-map) t))))
- (if (facep 'help-key-binding)
+ (if (not (eq project-key-prompt-style 'brackets))
(format "%s %s"
(propertize (key-description key) 'face 'help-key-binding)
label)
@@ -1871,20 +2048,30 @@ listed in the dispatch menu produced from `project-switch-commands'."
(when-let ((cmd (nth 0 row))
(keychar (nth 2 row)))
(define-key temp-map (vector keychar) cmd)))))
- command)
+ command
+ choice)
(while (not command)
(let* ((overriding-local-map commands-map)
- (choice (read-key-sequence (project--keymap-prompt))))
+ (prompt (if project-switch-use-entire-map
+ (project--keymap-prompt)
+ (project--menu-prompt))))
+ (when choice
+ (setq prompt (concat prompt
+ (format " %s: %s"
+ (propertize "Unrecognized input"
+ 'face 'warning)
+ (help-key-description choice nil)))))
+ (setq choice (read-key-sequence (concat "Choose: " prompt)))
(when (setq command (lookup-key commands-map choice))
+ (when (numberp command) (setq command nil))
(unless (or project-switch-use-entire-map
(assq command commands-menu))
- ;; TODO: Add some hint to the prompt, like "key not
- ;; recognized" or something.
(setq command nil)))
(let ((global-command (lookup-key (current-global-map) choice)))
(when (memq global-command
'(keyboard-quit keyboard-escape-quit))
(call-interactively global-command)))))
+ (message nil)
command))
;;;###autoload
@@ -1896,11 +2083,17 @@ made from `project-switch-commands'.
When called in a program, it will use the project corresponding
to directory DIR."
(interactive (list (funcall project-prompter)))
+ (project--remember-dir dir)
(let ((command (if (symbolp project-switch-commands)
project-switch-commands
- (project--switch-project-command))))
- (let ((project-current-directory-override dir))
- (call-interactively command))))
+ (project--switch-project-command)))
+ (buffer (current-buffer)))
+ (unwind-protect
+ (progn
+ (setq-local project-current-directory-override dir)
+ (call-interactively command))
+ (with-current-buffer buffer
+ (kill-local-variable 'project-current-directory-override)))))
;;;###autoload
(defun project-uniquify-dirname-transform (dirname)
@@ -1919,5 +2112,50 @@ would otherwise have the same name."
(file-relative-name dirname root))))
dirname))
+;;; Project mode-line
+
+;;;###autoload
+(defcustom project-mode-line nil
+ "Whether to show current project name and Project menu on the mode line.
+This feature requires the presence of the following item in
+`mode-line-format': `(project-mode-line project-mode-line-format)'; it
+is part of the default mode line beginning with Emacs 30."
+ :type 'boolean
+ :group 'project
+ :version "30.1")
+
+(defvar project-menu-entry
+ `(menu-item "Project" ,(bound-and-true-p menu-bar-project-menu)))
+
+(defvar project-mode-line-map
+ (let ((map (make-sparse-keymap)))
+ (define-key map [mode-line down-mouse-1] project-menu-entry)
+ map))
+
+(defvar project-mode-line-face nil
+ "Face name to use for the project name on the mode line.")
+
+(defvar project-mode-line-format '(:eval (project-mode-line-format)))
+(put 'project-mode-line-format 'risky-local-variable t)
+
+(defun project-mode-line-format ()
+ "Compose the project mode-line."
+ (when-let ((project (project-current)))
+ ;; Preserve the global value of 'last-coding-system-used'
+ ;; that 'write-region' needs to set for 'basic-save-buffer',
+ ;; but updating the mode line might occur at the same time
+ ;; during saving the buffer and 'project-name' can change
+ ;; 'last-coding-system-used' when reading the project name
+ ;; from .dir-locals.el also enables flyspell-mode (bug#66825).
+ (let ((last-coding-system-used last-coding-system-used))
+ (concat
+ " "
+ (propertize
+ (project-name project)
+ 'face project-mode-line-face
+ 'mouse-face 'mode-line-highlight
+ 'help-echo "mouse-1: Project menu"
+ 'local-map project-mode-line-map)))))
+
(provide 'project)
;;; project.el ends here
diff --git a/lisp/progmodes/prolog.el b/lisp/progmodes/prolog.el
index 66dea8803b3..a65943a48eb 100644
--- a/lisp/progmodes/prolog.el
+++ b/lisp/progmodes/prolog.el
@@ -1,6 +1,6 @@
;;; prolog.el --- major mode for Prolog (and Mercury) -*- lexical-binding:t -*-
-;; Copyright (C) 1986-1987, 1997-1999, 2002-2003, 2011-2023 Free
+;; Copyright (C) 1986-1987, 1997-1999, 2002-2003, 2011-2024 Free
;; Software Foundation, Inc.
;; Authors: Emil Åström <emil_astrom(at)hotmail(dot)com>
diff --git a/lisp/progmodes/ps-mode.el b/lisp/progmodes/ps-mode.el
index 1147db816bb..7fa6d9dca8c 100644
--- a/lisp/progmodes/ps-mode.el
+++ b/lisp/progmodes/ps-mode.el
@@ -1,6 +1,6 @@
;;; ps-mode.el --- PostScript mode for GNU Emacs -*- lexical-binding: t; -*-
-;; Copyright (C) 1999, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999, 2001-2024 Free Software Foundation, Inc.
;; Author: Peter Kleiweg <p.c.j.kleiweg@rug.nl>
;; Created: 20 Aug 1997
@@ -97,11 +97,9 @@ When the figure is finished these values should be replaced."
(const :tag "archC" (1296 1728))
(const :tag "archB" (864 1296))
(const :tag "archA" (648 864))
- (const :tag "flsa" (612 936))
- (const :tag "flse" (612 936))
+ (const :tag "flsa, flse" (612 936))
(const :tag "halfletter" (396 612))
- (const :tag "11x17" (792 1224))
- (const :tag "tabloid" (792 1224))
+ (const :tag "11x17, tabloid" (792 1224))
(const :tag "ledger" (1224 792))
(const :tag "csheet" (1224 1584))
(const :tag "dsheet" (1584 2448))
diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el
index 4b940b3f13b..1148da11a06 100644
--- a/lisp/progmodes/python.el
+++ b/lisp/progmodes/python.el
@@ -1,6 +1,6 @@
;;; python.el --- Python's flying circus support for Emacs -*- lexical-binding: t -*-
-;; Copyright (C) 2003-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003-2024 Free Software Foundation, Inc.
;; Author: Fabián E. Gallina <fgallina@gnu.org>
;; URL: https://github.com/fgallina/python.el
@@ -10,6 +10,9 @@
;; Created: Jul 2010
;; Keywords: languages
+;; This is a GNU ELPA :core package. Avoid functionality that is not
+;; compatible with the version of Emacs recorded above.
+
;; This file is part of GNU Emacs.
;; GNU Emacs is free software: you can redistribute it and/or modify
@@ -976,19 +979,30 @@ It makes underscores and dots word constituent chars.")
"raise" "return" "try" "while" "with" "yield"
;; These are technically operators, but we fontify them as
;; keywords.
- "and" "in" "is" "not" "or"))
+ "and" "in" "is" "not" "or" "not in" "is not"))
+
+(defvar python--treesit-builtin-types
+ '("int" "float" "complex" "bool" "list" "tuple" "range" "str"
+ "bytes" "bytearray" "memoryview" "set" "frozenset" "dict"))
+
+(defvar python--treesit-type-regex
+ (rx-to-string `(seq bol (or
+ ,@python--treesit-builtin-types
+ (seq (? "_") (any "A-Z") (+ (any "a-zA-Z_0-9"))))
+ eol)))
(defvar python--treesit-builtins
- '("abs" "all" "any" "ascii" "bin" "bool" "breakpoint" "bytearray"
- "bytes" "callable" "chr" "classmethod" "compile" "complex"
- "delattr" "dict" "dir" "divmod" "enumerate" "eval" "exec"
- "filter" "float" "format" "frozenset" "getattr" "globals"
- "hasattr" "hash" "help" "hex" "id" "input" "int" "isinstance"
- "issubclass" "iter" "len" "list" "locals" "map" "max"
- "memoryview" "min" "next" "object" "oct" "open" "ord" "pow"
- "print" "property" "range" "repr" "reversed" "round" "set"
- "setattr" "slice" "sorted" "staticmethod" "str" "sum" "super"
- "tuple" "type" "vars" "zip" "__import__"))
+ (append python--treesit-builtin-types
+ '("abs" "all" "any" "ascii" "bin" "breakpoint"
+ "callable" "chr" "classmethod" "compile"
+ "delattr" "dir" "divmod" "enumerate" "eval" "exec"
+ "filter" "format" "getattr" "globals"
+ "hasattr" "hash" "help" "hex" "id" "input" "isinstance"
+ "issubclass" "iter" "len" "locals" "map" "max"
+ "min" "next" "object" "oct" "open" "ord" "pow"
+ "print" "property" "repr" "reversed" "round"
+ "setattr" "slice" "sorted" "staticmethod" "sum" "super"
+ "type" "vars" "zip" "__import__")))
(defvar python--treesit-constants
'("Ellipsis" "False" "None" "NotImplemented" "True" "__debug__"
@@ -1039,9 +1053,7 @@ NODE is the string node. Do not fontify the initial f for
f-strings. OVERRIDE is the override flag described in
`treesit-font-lock-rules'. START and END mark the region to be
fontified."
- (let* ((string-beg (treesit-node-start node))
- (string-end (treesit-node-end node))
- (maybe-expression (treesit-node-parent node))
+ (let* ((maybe-expression (treesit-node-parent node))
(grandparent (treesit-node-parent
(treesit-node-parent
maybe-expression)))
@@ -1069,28 +1081,92 @@ fontified."
(equal (treesit-node-type maybe-expression)
"expression_statement"))
'font-lock-doc-face
- 'font-lock-string-face)))
- ;; Don't highlight string prefixes like f/r/b.
- (save-excursion
- (goto-char string-beg)
- (when (re-search-forward "[\"']" string-end t)
- (setq string-beg (match-beginning 0))))
- (treesit-fontify-with-override
- string-beg string-end face override start end)))
-
-(defun python--treesit-fontify-string-interpolation
- (node _ start end &rest _)
- "Fontify string interpolation.
-NODE is the string node. Do not fontify the initial f for
-f-strings. START and END mark the region to be
+ 'font-lock-string-face))
+
+ (ignore-interpolation (not
+ (seq-some
+ (lambda (feats) (memq 'string-interpolation feats))
+ (seq-take treesit-font-lock-feature-list treesit-font-lock-level))))
+ ;; If interpolation is enabled, highlight only
+ ;; string_start/string_content/string_end children. Do not
+ ;; touch interpolation node that can occur inside of the
+ ;; string.
+ (string-nodes (if ignore-interpolation
+ (list node)
+ (treesit-filter-child
+ node
+ (lambda (ch) (member (treesit-node-type ch)
+ '("string_start"
+ "string_content"
+ "string_end")))
+ t))))
+
+ (dolist (string-node string-nodes)
+ (let ((string-beg (treesit-node-start string-node))
+ (string-end (treesit-node-end string-node)))
+ (when (or ignore-interpolation
+ (equal (treesit-node-type string-node) "string_start"))
+ ;; Don't highlight string prefixes like f/r/b.
+ (save-excursion
+ (goto-char string-beg)
+ (when (re-search-forward "[\"']" string-end t)
+ (setq string-beg (match-beginning 0)))))
+
+ (treesit-fontify-with-override
+ string-beg string-end face override start end)))))
+
+(defun python--treesit-fontify-union-types (node override start end &optional type-regex &rest _)
+ "Fontify nested union types in the type hints.
+For examlpe, 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
+binary_operator node. OVERRIDE is the override flag described in
+`treesit-font-lock-rules'. START and END mark the region to be
+fontified."
+ (dolist (child (treesit-node-children node t))
+ (let (font-node)
+ (pcase (treesit-node-type child)
+ ((or "identifier" "none")
+ (setq font-node child))
+ ("attribute"
+ (when-let ((type-node (treesit-node-child-by-field-name child "attribute")))
+ (setq font-node type-node)))
+ ((or "binary_operator" "subscript")
+ (python--treesit-fontify-union-types child override start end type-regex)))
+
+ (when (and font-node
+ (or (null type-regex)
+ (let ((case-fold-search nil))
+ (string-match-p type-regex (treesit-node-text font-node)))))
+ (treesit-fontify-with-override
+ (treesit-node-start font-node) (treesit-node-end font-node)
+ 'font-lock-type-face override start end)))))
+
+(defun python--treesit-fontify-union-types-strict (node override start end &rest _)
+ "Fontify nested union types.
+Same as `python--treesit-fontify-union-types' but type identifier
+should match against `python--treesit-type-regex'. For NODE,
+OVERRIDE, START and END description see
+`python--treesit-fontify-union-types'."
+ (python--treesit-fontify-union-types node override start end python--treesit-type-regex))
+
+(defun python--treesit-fontify-dotted-decorator (node override start end &rest _)
+ "Fontify dotted decorators.
+For example @pytes.mark.skip. Iterate over all nested attribute
+nodes and highlight identifier nodes. NODE is the first attribute
+node. OVERRIDE is the override flag described in
+`treesit-font-lock-rules'. START and END mark the region to be
fontified."
- ;; This is kind of a hack, it basically removes the face applied by
- ;; the string feature, so that following features can apply their
- ;; face.
- (let ((n-start (treesit-node-start node))
- (n-end (treesit-node-end node)))
- (remove-text-properties
- (max start n-start) (min end n-end) '(face))))
+ (dolist (child (treesit-node-children node t))
+ (pcase (treesit-node-type child)
+ ("identifier"
+ (treesit-fontify-with-override
+ (treesit-node-start child) (treesit-node-end child)
+ 'font-lock-type-face override start end))
+ ("attribute"
+ (python--treesit-fontify-dotted-decorator child override start end)))))
(defvar python--treesit-settings
(treesit-font-lock-rules
@@ -1100,14 +1176,9 @@ fontified."
:feature 'string
:language 'python
- '((string) @python--treesit-fontify-string)
+ '((string) @python--treesit-fontify-string
+ (interpolation ["{" "}"] @font-lock-misc-punctuation-face))
- ;; HACK: This feature must come after the string feature and before
- ;; other features. Maybe we should make string-interpolation an
- ;; option rather than a feature.
- :feature 'string-interpolation
- :language 'python
- '((interpolation) @python--treesit-fontify-string-interpolation)
:feature 'keyword
:language 'python
@@ -1121,13 +1192,8 @@ fontified."
name: (identifier) @font-lock-function-name-face)
(class_definition
name: (identifier) @font-lock-type-face)
- (parameters (identifier) @font-lock-variable-name-face))
-
- :feature 'function
- :language 'python
- '((call function: (identifier) @font-lock-function-call-face)
- (call function: (attribute
- attribute: (identifier) @font-lock-function-call-face)))
+ (parameters (identifier) @font-lock-variable-name-face)
+ (parameters (default_parameter name: (identifier) @font-lock-variable-name-face)))
:feature 'builtin
:language 'python
@@ -1139,6 +1205,19 @@ fontified."
eol))
@font-lock-builtin-face)))
+ :feature 'decorator
+ :language 'python
+ '((decorator "@" @font-lock-type-face)
+ (decorator (call function: (identifier) @font-lock-type-face))
+ (decorator (identifier) @font-lock-type-face)
+ (decorator [(attribute) (call (attribute))] @python--treesit-fontify-dotted-decorator))
+
+ :feature 'function
+ :language 'python
+ '((call function: (identifier) @font-lock-function-call-face)
+ (call function: (attribute
+ attribute: (identifier) @font-lock-function-call-face)))
+
:feature 'constant
:language 'python
'([(true) (false) (none)] @font-lock-constant-face)
@@ -1150,30 +1229,71 @@ fontified."
@font-lock-variable-name-face)
(assignment left: (attribute
attribute: (identifier)
- @font-lock-property-use-face))
- (pattern_list (identifier)
+ @font-lock-variable-name-face))
+ (augmented_assignment left: (identifier)
+ @font-lock-variable-name-face)
+ (named_expression name: (identifier)
+ @font-lock-variable-name-face)
+ (pattern_list [(identifier)
+ (list_splat_pattern (identifier))]
@font-lock-variable-name-face)
- (tuple_pattern (identifier)
+ (tuple_pattern [(identifier)
+ (list_splat_pattern (identifier))]
@font-lock-variable-name-face)
- (list_pattern (identifier)
- @font-lock-variable-name-face)
- (list_splat_pattern (identifier)
- @font-lock-variable-name-face))
+ (list_pattern [(identifier)
+ (list_splat_pattern (identifier))]
+ @font-lock-variable-name-face))
- :feature 'decorator
- :language 'python
- '((decorator "@" @font-lock-type-face)
- (decorator (call function: (identifier) @font-lock-type-face))
- (decorator (identifier) @font-lock-type-face))
:feature 'type
:language 'python
+ ;; Override built-in faces when dict/list are used for type hints.
+ :override t
`(((identifier) @font-lock-type-face
(:match ,(rx-to-string
`(seq bol (or ,@python--treesit-exceptions)
- eol))
+ eol))
@font-lock-type-face))
- (type (identifier) @font-lock-type-face))
+ (type [(identifier) (none)] @font-lock-type-face)
+ (type (attribute attribute: (identifier) @font-lock-type-face))
+ ;; We don't want to highlight a package of the type
+ ;; (e.g. pack.ClassName). So explicitly exclude patterns with
+ ;; attribute, since we handle dotted type name in the previous
+ ;; rule. The following rule handle
+ ;; generic_type/list/tuple/splat_type nodes.
+ (type (_ !attribute [[(identifier) (none)] @font-lock-type-face
+ (attribute attribute: (identifier) @font-lock-type-face) ]))
+ ;; collections.abc.Iterator[T] case.
+ (type (subscript (attribute attribute: (identifier) @font-lock-type-face)))
+ ;; Nested optional type hints, e.g. val: Lvl1 | Lvl2[Lvl3[Lvl4]].
+ (type (binary_operator) @python--treesit-fontify-union-types)
+ ;;class Type(Base1, Sequence[T]).
+ (class_definition
+ superclasses:
+ (argument_list [(identifier) @font-lock-type-face
+ (attribute attribute: (identifier) @font-lock-type-face)
+ (subscript (identifier) @font-lock-type-face)
+ (subscript (attribute attribute: (identifier) @font-lock-type-face))]))
+
+ ;; Patern matching: case [str(), pack0.Type0()]. Take only the
+ ;; last identifier.
+ (class_pattern (dotted_name (identifier) @font-lock-type-face :anchor))
+
+ ;; Highlight the second argument as a type in isinstance/issubclass.
+ ((call function: (identifier) @func-name
+ (argument_list :anchor (_)
+ [(identifier) @font-lock-type-face
+ (attribute attribute: (identifier) @font-lock-type-face)
+ (tuple (identifier) @font-lock-type-face)
+ (tuple (attribute attribute: (identifier) @font-lock-type-face))]
+ (:match ,python--treesit-type-regex @font-lock-type-face)))
+ (:match "^is\\(?:instance\\|subclass\\)$" @func-name))
+
+ ;; isinstance(t, int|float).
+ ((call function: (identifier) @func-name
+ (argument_list :anchor (_)
+ (binary_operator) @python--treesit-fontify-union-types-strict))
+ (:match "^is\\(?:instance\\|subclass\\)$" @func-name)))
:feature 'escape-sequence
:language 'python
@@ -1232,7 +1352,22 @@ For NODE, OVERRIDE, START, END, and ARGS, see
(when (python--treesit-variable-p node)
(treesit-fontify-with-override
(treesit-node-start node) (treesit-node-end node)
- 'font-lock-variable-name-face override start end)))
+ 'font-lock-variable-use-face override start end)))
+
+(defun python--treesit-syntax-propertize (start end)
+ "Propertize triple-quote strings between START and END."
+ (save-excursion
+ (goto-char start)
+ (while (re-search-forward (rx (or "\"\"\"" "'''")) end t)
+ (let ((node (treesit-node-at (point))))
+ ;; The triple quotes surround a non-empty string.
+ (when (equal (treesit-node-type node) "string_content")
+ (let ((start (treesit-node-start node))
+ (end (treesit-node-end node)))
+ (put-text-property (1- start) start
+ 'syntax-table (string-to-syntax "|"))
+ (put-text-property end (min (1+ end) (point-max))
+ 'syntax-table (string-to-syntax "|"))))))))
;;; Indentation
@@ -6839,8 +6974,8 @@ implementations: `python-mode' and `python-ts-mode'."
'(( comment definition)
( keyword string type)
( assignment builtin constant decorator
- escape-sequence number property string-interpolation )
- ( bracket delimiter function operator variable)))
+ escape-sequence number string-interpolation )
+ ( bracket delimiter function operator variable property)))
(setq-local treesit-font-lock-settings python--treesit-settings)
(setq-local imenu-create-index-function
#'python-imenu-treesit-create-index)
@@ -6850,6 +6985,8 @@ implementations: `python-mode' and `python-ts-mode'."
#'python--treesit-defun-name)
(treesit-major-mode-setup)
+ (setq-local syntax-propertize-function #'python--treesit-syntax-propertize)
+
(python-skeleton-add-menu-items)
(when python-indent-guess-indent-offset
diff --git a/lisp/progmodes/ruby-mode.el b/lisp/progmodes/ruby-mode.el
index 9d80bbd72dd..999fbebfb08 100644
--- a/lisp/progmodes/ruby-mode.el
+++ b/lisp/progmodes/ruby-mode.el
@@ -1,6 +1,6 @@
;;; ruby-mode.el --- Major mode for editing Ruby files -*- lexical-binding: t -*-
-;; Copyright (C) 1994-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1994-2024 Free Software Foundation, Inc.
;; Authors: Yukihiro Matsumoto
;; Nobuyoshi Nakada
@@ -516,7 +516,9 @@ is customizable via `ruby-encoding-magic-comment-style'.
When set to `always-utf8' an utf-8 comment will always be added,
even if it's not required."
- :type 'boolean :group 'ruby)
+ :type '(choice (const :tag "Don't insert" nil)
+ (const :tag "Insert utf-8 comment always" always-utf8)
+ (const :tag "Insert only when required" t)))
(defcustom ruby-encoding-magic-comment-style 'ruby
"The style of the magic encoding comment to use."
@@ -2104,12 +2106,6 @@ or `gem' statement around point."
"\\(%\\)[qQrswWxIi]?\\([[:punct:]]\\)"
"Regexp to match the beginning of percent literal.")
- (defconst ruby-syntax-methods-before-regexp
- '("gsub" "gsub!" "sub" "sub!" "scan" "split" "split!" "index" "match"
- "assert_match" "Given" "Then" "When")
- "Methods that can take regexp as the first argument.
-It will be properly highlighted even when the call omits parens.")
-
(defvar ruby-syntax-before-regexp-re
(concat
;; Special tokens that can't be followed by a division operator.
@@ -2121,11 +2117,9 @@ It will be properly highlighted even when the call omits parens.")
"\\|\\(?:^\\|\\s \\)"
(regexp-opt '("if" "elsif" "unless" "while" "until" "when" "and"
"or" "not" "&&" "||"))
- ;; Method name from the list.
- "\\|\\_<"
- (regexp-opt ruby-syntax-methods-before-regexp)
"\\)\\s *")
- "Regexp to match text that can be followed by a regular expression."))
+ "Regexp to match text that disambiguates a regular expression.
+A slash character after any of these should begin a regexp."))
(defun ruby-syntax-propertize (start end)
"Syntactic keywords for Ruby mode. See `syntax-propertize-function'."
@@ -2185,10 +2179,14 @@ It will be properly highlighted even when the call omits parens.")
(when (or
;; Beginning of a regexp.
(and (null (nth 8 state))
- (save-excursion
- (forward-char -1)
- (looking-back ruby-syntax-before-regexp-re
- (line-beginning-position))))
+ (or (not
+ ;; Looks like division.
+ (or (eql (char-after) ?\s)
+ (not (eql (char-before (1- (point))) ?\s))))
+ (save-excursion
+ (forward-char -1)
+ (looking-back ruby-syntax-before-regexp-re
+ (line-beginning-position)))))
;; End of regexp. We don't match the whole
;; regexp at once because it can have
;; string interpolation inside, or span
diff --git a/lisp/progmodes/ruby-ts-mode.el b/lisp/progmodes/ruby-ts-mode.el
index adbf18786cb..598eaa461ff 100644
--- a/lisp/progmodes/ruby-ts-mode.el
+++ b/lisp/progmodes/ruby-ts-mode.el
@@ -1,6 +1,6 @@
;;; ruby-ts-mode.el --- Major mode for editing Ruby files using tree-sitter -*- lexical-binding: t; -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;; Author: Perry Smith <pedz@easesoftware.com>
;; Created: December 2022
@@ -25,7 +25,7 @@
;;; Commentary:
;; This file defines ruby-ts-mode which is a major mode for editing
-;; Ruby files that uses Tree Sitter to parse the language. More
+;; Ruby files that uses Tree Sitter to parse the language. More
;; information about Tree Sitter can be found in the ELisp Info pages
;; as well as this website: https://tree-sitter.github.io/tree-sitter/
@@ -197,8 +197,8 @@
(defun ruby-ts--comment-font-lock (node override start end &rest _)
"Apply font lock to comment NODE within START and END.
Applies `font-lock-comment-delimiter-face' and
-`font-lock-comment-face' See `treesit-fontify-with-override' for
-values of OVERRIDE"
+`font-lock-comment-face'. See `treesit-fontify-with-override' for
+values of OVERRIDE."
;; Empirically it appears as if (treesit-node-start node) will be
;; where the # character is at and (treesit-node-end node) will be
;; the end of the line
@@ -601,7 +601,7 @@ a statement container is a node that matches
;; case expression: when, in_clause, and else are all
;; children of case. when and in_clause have pattern and
- ;; body as fields. body has "then" and then the statemets.
+ ;; body as fields. body has "then" and then the statements.
;; i.e. the statements are not children of when but then.
;; But for the statements are children of else.
((match "when" "case")
@@ -753,8 +753,9 @@ a statement container is a node that matches
((match "}" "hash") ruby-ts--parent-call-or-bol 0)
((parent-is "hash") ruby-ts--parent-call-or-bol ruby-indent-level)
- ((match "]" "array") ruby-ts--parent-call-or-bol 0)
- ((parent-is "array") ruby-ts--parent-call-or-bol ruby-indent-level)
+ ((match "]" "^array") ruby-ts--parent-call-or-bol 0)
+ ((parent-is "^array") ruby-ts--parent-call-or-bol ruby-indent-level)
+ ((match ")" "string_array") ruby-ts--parent-call-or-bol 0)
((parent-is "pair") ruby-ts--parent-call-or-bol 0)
@@ -1063,8 +1064,9 @@ leading double colon is not added."
('heredoc
(put-text-property (treesit-node-start node) (1+ (treesit-node-start node))
'syntax-table (string-to-syntax "\""))
- (put-text-property (treesit-node-end node) (1+ (treesit-node-end node))
- 'syntax-table (string-to-syntax "\"")))
+ (when (< (treesit-node-end node) (point-max))
+ (put-text-property (treesit-node-end node) (1+ (treesit-node-end node))
+ 'syntax-table (string-to-syntax "\""))))
('percent
;; FIXME: Put the first one on the first paren in both %Q{} and %().
;; That would stop electric-pair-mode from pairing, though. Hmm.
@@ -1122,44 +1124,53 @@ leading double colon is not added."
;; Navigation.
(setq-local treesit-defun-type-regexp ruby-ts--method-regex)
- (setq-local treesit-sexp-type-regexp
- (cons (rx
- bol
- (or
- "class"
- "module"
- "method"
- "array"
- "hash"
- "parenthesized_statements"
- "method_parameters"
- "array_pattern"
- "hash_pattern"
- "if"
- "unless"
- "case"
- "case_match"
- "when"
- "block"
- "do_block"
- "begin"
- "integer"
- "identifier"
- "constant"
- "simple_symbol"
- "hash_key_symbol"
- "symbol_array"
- "string"
- "string_array"
- "heredoc_body"
- "regex"
- "argument_list"
- "interpolation"
- "instance_variable"
- "global_variable"
- )
- eol)
- #'ruby-ts--sexp-p))
+ (setq-local treesit-thing-settings
+ `((ruby
+ (sexp ,(cons (rx
+ bol
+ (or
+ "class"
+ "singleton_class"
+ "module"
+ "method"
+ "array"
+ "hash"
+ "parenthesized_statements"
+ "method_parameters"
+ "array_pattern"
+ "hash_pattern"
+ "if"
+ "else"
+ "then"
+ "unless"
+ "case"
+ "case_match"
+ "when"
+ "while"
+ "until"
+ "for"
+ "block"
+ "do_block"
+ "begin"
+ "integer"
+ "identifier"
+ "self"
+ "super"
+ "constant"
+ "simple_symbol"
+ "hash_key_symbol"
+ "symbol_array"
+ "string"
+ "string_array"
+ "heredoc_body"
+ "regex"
+ "argument_list"
+ "interpolation"
+ "instance_variable"
+ "global_variable"
+ )
+ eol)
+ #'ruby-ts--sexp-p)))))
;; AFAIK, Ruby can not nest methods
(setq-local treesit-defun-prefer-top-level nil)
@@ -1183,20 +1194,8 @@ leading double colon is not added."
(treesit-major-mode-setup)
- (treesit-parser-add-notifier (car (treesit-parser-list))
- #'ruby-ts--parser-after-change)
-
(setq-local syntax-propertize-function #'ruby-ts--syntax-propertize))
-(defun ruby-ts--parser-after-change (ranges parser)
- ;; Make sure we re-syntax-propertize the full node that is being
- ;; edited. This is most pertinent to multi-line complex nodes such
- ;; as heredocs.
- (when ranges
- (with-current-buffer (treesit-parser-buffer parser)
- (syntax-ppss-flush-cache (cl-loop for r in ranges
- minimize (car r))))))
-
(if (treesit-ready-p 'ruby)
;; Copied from ruby-mode.el.
(add-to-list 'auto-mode-alist
diff --git a/lisp/progmodes/rust-ts-mode.el b/lisp/progmodes/rust-ts-mode.el
index 999c1d7ae96..c5fc57cc374 100644
--- a/lisp/progmodes/rust-ts-mode.el
+++ b/lisp/progmodes/rust-ts-mode.el
@@ -1,6 +1,6 @@
;;; rust-ts-mode.el --- tree-sitter support for Rust -*- lexical-binding: t; -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;; Author : Randy Taylor <dev@rjt.dev>
;; Maintainer : Randy Taylor <dev@rjt.dev>
@@ -48,6 +48,12 @@
:safe 'integerp
:group 'rust)
+(defvar rust-ts-mode-prettify-symbols-alist
+ '(("&&" . ?∧) ("||" . ?∨)
+ ("<=" . ?≤) (">=" . ?≥) ("!=" . ?≠)
+ ("INFINITY" . ?∞) ("->" . ?→) ("=>" . ?⇒))
+ "Value for `prettify-symbols-alist' in `rust-ts-mode'.")
+
(defvar rust-ts-mode--syntax-table
(let ((table (make-syntax-table)))
(modify-syntax-entry ?+ "." table)
@@ -147,7 +153,7 @@
:language 'rust
:feature 'comment
- '(([(block_comment) (line_comment)]) @font-lock-comment-face)
+ '(([(block_comment) (line_comment)]) @rust-ts-mode--comment-docstring)
:language 'rust
:feature 'delimiter
@@ -287,6 +293,18 @@
'((ERROR) @font-lock-warning-face))
"Tree-sitter font-lock settings for `rust-ts-mode'.")
+(defun rust-ts-mode--comment-docstring (node override start end &rest _args)
+ "Use the comment or documentation face appropriately for comments."
+ (let* ((beg (treesit-node-start node))
+ (face (save-excursion
+ (goto-char beg)
+ (if (looking-at-p
+ "/\\(?:/\\(?:/[^/]\\|!\\)\\|\\*\\(?:\\*[^*/]\\|!\\)\\)")
+ 'font-lock-doc-face
+ 'font-lock-comment-face))))
+ (treesit-fontify-with-override beg (treesit-node-end node)
+ face override start end)))
+
(defun rust-ts-mode--fontify-scope (node override start end &optional tail-p)
(let* ((case-fold-search nil)
(face
@@ -386,6 +404,19 @@ delimiters < and >'s."
(?< '(4 . ?>))
(?> '(5 . ?<))))))))
+(defun rust-ts-mode--prettify-symbols-compose-p (start end match)
+ "Return true iff 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)
+ ;; Make sure || is not a closure with 0 arguments and && is not
+ ;; a double reference.
+ (pcase match
+ ((or "||" "&&")
+ (string= (treesit-node-field-name (treesit-node-at (point)))
+ "operator"))
+ (_ t))))
+
;;;###autoload
(define-derived-mode rust-ts-mode prog-mode "Rust"
"Major mode for editing Rust, powered by tree-sitter."
@@ -411,6 +442,11 @@ delimiters < and >'s."
number type)
( bracket delimiter error function operator property variable)))
+ ;; Prettify configuration
+ (setq prettify-symbols-alist rust-ts-mode-prettify-symbols-alist)
+ (setq prettify-symbols-compose-predicate
+ #'rust-ts-mode--prettify-symbols-compose-p)
+
;; Imenu.
(setq-local treesit-simple-imenu-settings
`(("Module" "\\`mod_item\\'" nil nil)
@@ -424,6 +460,10 @@ delimiters < and >'s."
(setq-local indent-tabs-mode nil
treesit-simple-indent-rules rust-ts-mode--indent-rules)
+ ;; Electric
+ (setq-local electric-indent-chars
+ (append "{}():;,#" electric-indent-chars))
+
;; Navigation.
(setq-local treesit-defun-type-regexp
(regexp-opt '("enum_item"
diff --git a/lisp/progmodes/scheme.el b/lisp/progmodes/scheme.el
index e6fcc684729..67abab6913d 100644
--- a/lisp/progmodes/scheme.el
+++ b/lisp/progmodes/scheme.el
@@ -1,6 +1,6 @@
;;; scheme.el --- Scheme (and DSSSL) editing mode -*- lexical-binding: t; -*-
-;; Copyright (C) 1986-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1986-2024 Free Software Foundation, Inc.
;; Author: Bill Rozas <jinx@martigny.ai.mit.edu>
;; Adapted-by: Dave Love <d.love@dl.ac.uk>
diff --git a/lisp/progmodes/sh-script.el b/lisp/progmodes/sh-script.el
index cfc10878922..0562415b4e5 100644
--- a/lisp/progmodes/sh-script.el
+++ b/lisp/progmodes/sh-script.el
@@ -1,6 +1,6 @@
;;; sh-script.el --- shell-script editing commands for Emacs -*- lexical-binding:t -*-
-;; Copyright (C) 1993-1997, 1999, 2001-2023 Free Software Foundation,
+;; Copyright (C) 1993-1997, 1999, 2001-2024 Free Software Foundation,
;; Inc.
;; Author: Daniel Pfeiffer <occitan@esperanto.org>
@@ -158,10 +158,6 @@
(autoload 'shell-command-completion "shell")
(autoload 'shell-environment-variable-completion "shell")
-(defvar font-lock-comment-face)
-(defvar font-lock-set-defaults)
-(defvar font-lock-string-face)
-
(defgroup sh nil
"Shell programming utilities."
@@ -874,7 +870,7 @@ See `sh-feature'.")
"Default expressions to highlight in Shell Script modes. See `sh-feature'.")
(defvar sh-font-lock-keywords-var-1
- '((sh "[ \t]in\\>"))
+ '((sh "[ \t]\\(in\\|do\\)\\>"))
"Subdued level highlighting for Shell Script modes.")
(defvar sh-font-lock-keywords-var-2 ()
@@ -1634,10 +1630,11 @@ not written in Bash or sh."
( bracket delimiter misc-punctuation operator)))
(setq-local treesit-font-lock-settings
sh-mode--treesit-settings)
- (setq-local treesit-text-type-regexp
- (regexp-opt '("comment"
- "heredoc_start"
- "heredoc_body")))
+ (setq-local treesit-thing-settings
+ `((bash
+ (sentence ,(regexp-opt '("comment"
+ "heredoc_start"
+ "heredoc_body"))))))
(setq-local treesit-defun-type-regexp "function_definition")
(treesit-major-mode-setup)))
@@ -1813,8 +1810,8 @@ before the newline and in that case point should be just before the token."
(concat "\\(?:^\\|[^\\]\\)\\(?:\\\\\\\\\\)*"
"\\(" sh-smie--sh-operators-re "\\)"))
-(defun sh-smie--sh-keyword-in-p ()
- "Assuming we're looking at \"in\", return non-nil if it's a keyword.
+(defun sh-smie--sh-keyword-in/do-p (tok)
+ "When looking at TOK (either \"in\" or \"do\"), non-nil if TOK is a keyword.
Does not preserve point."
(let ((forward-sexp-function nil)
(words nil) ;We've seen words.
@@ -1836,7 +1833,10 @@ Does not preserve point."
((equal prev ";")
(if words (setq newline t)
(setq res 'keyword)))
- ((member prev '("case" "for" "select")) (setq res 'keyword))
+ ((member prev (if (string= tok "in")
+ '("case" "for" "select")
+ '("for" "select")))
+ (setq res 'keyword))
((assoc prev smie-grammar) (setq res 'word))
(t
(if newline
@@ -1848,7 +1848,7 @@ Does not preserve point."
"Non-nil if TOK (at which we're looking) really is a keyword."
(cond
((looking-at "[[:alnum:]_]+=") nil)
- ((equal tok "in") (sh-smie--sh-keyword-in-p))
+ ((member tok '("in" "do")) (sh-smie--sh-keyword-in/do-p tok))
(t (sh-smie--keyword-p))))
(defun sh-smie--default-forward-token ()
diff --git a/lisp/progmodes/simula.el b/lisp/progmodes/simula.el
index d3061169981..94b18d32c09 100644
--- a/lisp/progmodes/simula.el
+++ b/lisp/progmodes/simula.el
@@ -1,6 +1,6 @@
;;; simula.el --- SIMULA 87 code editing commands for Emacs -*- lexical-binding: t; -*-
-;; Copyright (C) 1992-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1992-2024 Free Software Foundation, Inc.
;; Author: Hans Henrik Eriksen <hhe@ifi.uio.no>
;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/progmodes/sql.el b/lisp/progmodes/sql.el
index 61c8525b77a..604f04a3d57 100644
--- a/lisp/progmodes/sql.el
+++ b/lisp/progmodes/sql.el
@@ -1,6 +1,6 @@
;;; sql.el --- specialized comint.el for SQL interpreters -*- lexical-binding: t -*-
-;; Copyright (C) 1998-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-2024 Free Software Foundation, Inc.
;; Author: Alex Schroeder <alex@gnu.org>
;; Maintainer: Michael Mauger <michael@mauger.com>
@@ -235,10 +235,6 @@
(require 'view)
(eval-when-compile (require 'subr-x)) ; string-empty-p
-(defvar font-lock-keyword-face)
-(defvar font-lock-set-defaults)
-(defvar font-lock-string-face)
-
;;; Allow customization
(defgroup SQL nil
@@ -1191,12 +1187,11 @@ Starts `sql-interactive-mode' after doing some setup."
(defcustom sql-postgres-options '("-P" "pager=off")
"List of additional options for `sql-postgres-program'.
-The default setting includes the -P option which breaks older versions
-of the psql client (such as version 6.5.3). The -P option is equivalent
-to the --pset option. If you want the psql to prompt you for a user
-name, add the string \"-u\" to the list of options. If you want to
-provide a user name on the command line (newer versions such as 7.1),
-add your name with a \"-U\" prefix (such as \"-Umark\") to the list."
+The default -P option is equivalent to the --pset option. If you
+want psql to prompt you for a user name, add the string \"-u\" to
+the list of options. If you want to provide a user name on the
+command line, add your name with a \"-U\" prefix (such as
+\"-Umark\") to the list."
:type '(repeat string)
:version "20.8")
diff --git a/lisp/progmodes/subword.el b/lisp/progmodes/subword.el
index 18ccdd0e66e..52b2cd07cdd 100644
--- a/lisp/progmodes/subword.el
+++ b/lisp/progmodes/subword.el
@@ -1,6 +1,6 @@
;;; subword.el --- Handling capitalized subwords in a nomenclature -*- lexical-binding: t -*-
-;; Copyright (C) 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2004-2024 Free Software Foundation, Inc.
;; Author: Masatake YAMATO
diff --git a/lisp/progmodes/tcl.el b/lisp/progmodes/tcl.el
index ba0cbc8b066..dc11f456cd0 100644
--- a/lisp/progmodes/tcl.el
+++ b/lisp/progmodes/tcl.el
@@ -1,6 +1,6 @@
;;; tcl.el --- Tcl code editing commands for Emacs -*- lexical-binding: t; -*-
-;; Copyright (C) 1994, 1998-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1994, 1998-2024 Free Software Foundation, Inc.
;; Author: Tom Tromey <tromey@redhat.com>
;; Chris Lindblad <cjl@lcs.mit.edu>
@@ -1340,7 +1340,7 @@ to update the alist.")
If FLAG is nil, just uses `current-word'.
Otherwise scans backward for most likely Tcl command word."
(if (and flag
- (derived-mode-p 'tcl-mode 'inferior-tcl-mode))
+ (derived-mode-p '(tcl-mode inferior-tcl-mode)))
(condition-case nil
(save-excursion
;; Look backward for first word actually in alist.
@@ -1575,7 +1575,7 @@ The first line is assumed to look like \"#!.../program ...\"."
(if (memq char '(?\[ ?\] ?{ ?} ?\\ ?\" ?$ ?\s ?\;))
(concat "\\" (char-to-string char))
(char-to-string char)))
- string ""))
+ string))
diff --git a/lisp/progmodes/typescript-ts-mode.el b/lisp/progmodes/typescript-ts-mode.el
index 3f8e232b71f..e9c6afff440 100644
--- a/lisp/progmodes/typescript-ts-mode.el
+++ b/lisp/progmodes/typescript-ts-mode.el
@@ -1,6 +1,6 @@
;;; typescript-ts-mode.el --- tree sitter support for TypeScript -*- lexical-binding: t; -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;; Author : Theodor Thornhill <theo@thornhill.no>
;; Maintainer : Theodor Thornhill <theo@thornhill.no>
@@ -32,8 +32,11 @@
(eval-when-compile (require 'rx))
(require 'c-ts-common) ; For comment indent and filling.
+(declare-function treesit-node-start "treesit.c")
+(declare-function treesit-node-end "treesit.c")
(declare-function treesit-parser-create "treesit.c")
(declare-function treesit-query-capture "treesit.c")
+(declare-function treesit-query-compile "treesit.c")
(defcustom typescript-ts-mode-indent-offset 2
"Number of spaces for each indentation step in `typescript-ts-mode'."
@@ -84,7 +87,7 @@ Check if a node type is available, then return the right indent rules."
(progn (treesit-query-capture 'tsx '((jsx_fragment) @capture))
`(((match "<" "jsx_fragment") parent 0)
((parent-is "jsx_fragment") parent typescript-ts-mode-indent-offset)))
- (error
+ (treesit-query-error
`(((match "<" "jsx_text") parent 0)
((parent-is "jsx_text") parent typescript-ts-mode-indent-offset)))))
@@ -104,6 +107,9 @@ Argument LANGUAGE is either `typescript' or `tsx'."
((parent-is "member_expression") parent-bol typescript-ts-mode-indent-offset)
((parent-is "named_imports") parent-bol typescript-ts-mode-indent-offset)
((parent-is "statement_block") parent-bol typescript-ts-mode-indent-offset)
+ ((or (node-is "case")
+ (node-is "default"))
+ parent-bol typescript-ts-mode-indent-offset)
((parent-is "switch_case") parent-bol typescript-ts-mode-indent-offset)
((parent-is "switch_default") parent-bol typescript-ts-mode-indent-offset)
((parent-is "type_arguments") parent-bol typescript-ts-mode-indent-offset)
@@ -121,6 +127,11 @@ Argument LANGUAGE is either `typescript' or `tsx'."
((parent-is "arrow_function") parent-bol typescript-ts-mode-indent-offset)
((parent-is "parenthesized_expression") parent-bol typescript-ts-mode-indent-offset)
((parent-is "binary_expression") parent-bol typescript-ts-mode-indent-offset)
+ ((match "while" "do_statement") parent-bol 0)
+ ((match "else" "if_statement") parent-bol 0)
+ ((parent-is ,(rx (or (seq (or "if" "for" "for_in" "while" "do") "_statement")
+ "else_clause")))
+ parent-bol typescript-ts-mode-indent-offset)
,@(when (eq language 'tsx)
(append (tsx-ts-mode--indent-compatibility-b893426)
@@ -163,7 +174,7 @@ Argument LANGUAGE is either `typescript' or `tsx'."
;; but then raises an error if the wrong node type is used. So it is
;; important to check with the new node type (member_expression)
(condition-case nil
- (progn (treesit-query-capture language '((member_expression) @capture))
+ (progn (treesit-query-capture language '((jsx_opening_element (member_expression) @capture)))
'((jsx_opening_element
[(member_expression (identifier)) (identifier)]
@typescript-ts-jsx-tag-face)
@@ -175,7 +186,8 @@ Argument LANGUAGE is either `typescript' or `tsx'."
(jsx_self_closing_element
[(member_expression (identifier)) (identifier)]
@typescript-ts-jsx-tag-face)))
- (error '((jsx_opening_element
+ (treesit-query-error
+ '((jsx_opening_element
[(nested_identifier (identifier)) (identifier)]
@typescript-ts-jsx-tag-face)
@@ -193,7 +205,7 @@ Argument LANGUAGE is either `typescript' or `tsx'."
(treesit-font-lock-rules
:language language
:feature 'comment
- `((comment) @font-lock-comment-face)
+ `([(comment) (hash_bang_line)] @font-lock-comment-face)
:language language
:feature 'constant
@@ -387,7 +399,7 @@ Argument LANGUAGE is either `typescript' or `tsx'."
"lexical_declaration"
"property_signature")
"Nodes that designate sentences in TypeScript.
-See `treesit-sentence-type-regexp' for more information.")
+See `treesit-thing-settings' for more information.")
(defvar typescript-ts-mode--sexp-nodes
'("expression"
@@ -409,11 +421,13 @@ See `treesit-sentence-type-regexp' for more information.")
"arguments"
"pair")
"Nodes that designate sexps in TypeScript.
-See `treesit-sexp-type-regexp' for more information.")
+See `treesit-thing-settings' for more information.")
;;;###autoload
(define-derived-mode typescript-ts-base-mode prog-mode "TypeScript"
- "Major mode for editing TypeScript."
+ "Generic major mode for editing TypeScript.
+
+This mode is intended to be inherited by concrete major modes."
:group 'typescript
:syntax-table typescript-ts-mode--syntax-table
@@ -421,10 +435,6 @@ See `treesit-sexp-type-regexp' for more information.")
(c-ts-common-comment-setup)
(setq-local treesit-defun-prefer-top-level t)
- (setq-local treesit-text-type-regexp
- (regexp-opt '("comment"
- "template_string")))
-
;; Electric
(setq-local electric-indent-chars
(append "{}():;,<>/" electric-indent-chars))
@@ -438,11 +448,13 @@ See `treesit-sexp-type-regexp' for more information.")
"lexical_declaration")))
(setq-local treesit-defun-name-function #'js--treesit-defun-name)
- (setq-local treesit-sentence-type-regexp
- (regexp-opt typescript-ts-mode--sentence-nodes))
-
- (setq-local treesit-sexp-type-regexp
- (regexp-opt typescript-ts-mode--sexp-nodes))
+ (setq-local treesit-thing-settings
+ `((typescript
+ (sexp ,(regexp-opt typescript-ts-mode--sexp-nodes))
+ (sentence ,(regexp-opt
+ typescript-ts-mode--sentence-nodes))
+ (text ,(regexp-opt '("comment"
+ "template_string"))))))
;; Imenu (same as in `js-ts-mode').
(setq-local treesit-simple-imenu-settings
@@ -474,7 +486,8 @@ See `treesit-sexp-type-regexp' for more information.")
'((comment declaration)
(keyword string escape-sequence)
(constant expression identifier number pattern property)
- (function bracket delimiter)))
+ (operator function bracket delimiter)))
+ (setq-local syntax-propertize-function #'typescript-ts--syntax-propertize)
(treesit-major-mode-setup)))
@@ -513,17 +526,15 @@ at least 3 (which is the default value)."
(setq-local treesit-simple-indent-rules
(typescript-ts-mode--indent-rules 'tsx))
- ;; Navigation
- (setq-local treesit-sentence-type-regexp
- (regexp-opt (append
- typescript-ts-mode--sentence-nodes
- '("jsx_element"
- "jsx_self_closing_element"))))
-
- (setq-local treesit-sexp-type-regexp
- (regexp-opt (append
- typescript-ts-mode--sexp-nodes
- '("jsx"))))
+ (setq-local treesit-thing-settings
+ `((tsx
+ (sexp ,(regexp-opt
+ (append typescript-ts-mode--sexp-nodes
+ '("jsx"))))
+ (sentence ,(regexp-opt
+ (append typescript-ts-mode--sentence-nodes
+ '("jsx_element"
+ "jsx_self_closing_element")))))))
;; Font-lock.
(setq-local treesit-font-lock-settings
@@ -533,9 +544,47 @@ at least 3 (which is the default value)."
(keyword string escape-sequence)
(constant expression identifier jsx number pattern property)
(function bracket delimiter)))
+ (setq-local syntax-propertize-function #'tsx-ts--syntax-propertize)
(treesit-major-mode-setup)))
+(defvar typescript-ts--s-p-query
+ (when (treesit-available-p)
+ (treesit-query-compile 'typescript
+ '(((regex pattern: (regex_pattern) @regexp))))))
+
+(defvar tsx-ts--s-p-query
+ (when (treesit-available-p)
+ (treesit-query-compile 'tsx
+ '(((regex pattern: (regex_pattern) @regexp))
+ ((variable_declarator value: (jsx_element) @jsx))
+ ((assignment_expression right: (jsx_element) @jsx))
+ ((arguments (jsx_element) @jsx))
+ ((parenthesized_expression (jsx_element) @jsx))
+ ((return_statement (jsx_element) @jsx))))))
+
+(defun typescript-ts--syntax-propertize (beg end)
+ (let ((captures (treesit-query-capture 'typescript typescript-ts--s-p-query beg end)))
+ (tsx-ts--syntax-propertize-captures captures)))
+
+(defun tsx-ts--syntax-propertize (beg end)
+ (let ((captures (treesit-query-capture 'tsx tsx-ts--s-p-query beg end)))
+ (tsx-ts--syntax-propertize-captures captures)))
+
+(defun tsx-ts--syntax-propertize-captures (captures)
+ (pcase-dolist (`(,name . ,node) captures)
+ (let* ((ns (treesit-node-start node))
+ (ne (treesit-node-end node))
+ (syntax (pcase-exhaustive name
+ ('regexp
+ (cl-decf ns)
+ (cl-incf ne)
+ (string-to-syntax "\"/"))
+ ('jsx
+ (string-to-syntax "|")))))
+ (put-text-property ns (1+ ns) 'syntax-table syntax)
+ (put-text-property (1- ne) ne 'syntax-table syntax))))
+
(if (treesit-ready-p 'tsx)
(add-to-list 'auto-mode-alist '("\\.tsx\\'" . tsx-ts-mode)))
diff --git a/lisp/progmodes/vera-mode.el b/lisp/progmodes/vera-mode.el
index 07d3ef07d7b..184cce66ae4 100644
--- a/lisp/progmodes/vera-mode.el
+++ b/lisp/progmodes/vera-mode.el
@@ -1,11 +1,11 @@
;;; vera-mode.el --- major mode for editing Vera files -*- lexical-binding: t; -*-
-;; Copyright (C) 1997-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997-2024 Free Software Foundation, Inc.
;; Author: Reto Zimmermann <reto@gnu.org>
;; Version: 2.28
;; Keywords: languages vera
-;; WWW: https://guest.iis.ee.ethz.ch/~zimmi/emacs/vera-mode.html
+;; URL: https://iis-people.ee.ethz.ch/~zimmi/emacs/vera-mode.html
;; Yoni Rabkin <yoni@rabkins.net> contacted the maintainer of this
;; file on 18/3/2008, and the maintainer agreed that when a bug is
diff --git a/lisp/progmodes/verilog-mode.el b/lisp/progmodes/verilog-mode.el
index 855ba4b50cf..6081372af33 100644
--- a/lisp/progmodes/verilog-mode.el
+++ b/lisp/progmodes/verilog-mode.el
@@ -1,6 +1,6 @@
;;; verilog-mode.el --- major mode for editing verilog source in Emacs -*- lexical-binding: t; -*-
-;; Copyright (C) 1996-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-2024 Free Software Foundation, Inc.
;; Author: Michael McNamara <mac@verilog.com>
;; Wilson Snyder <wsnyder@wsnyder.org>
@@ -5374,10 +5374,7 @@ primitive or interface named NAME."
(goto-char (match-end 0))
(setq there (point))
(setq err nil)
- (setq str (concat " // " cntx (verilog-get-expr))))
-
- (;-- otherwise...
- (setq str " // auto-endcomment confused "))))
+ (setq str (concat " // " cntx (verilog-get-expr))))))
((and
(verilog-in-case-region-p) ;-- handle case item differently
diff --git a/lisp/progmodes/vhdl-mode.el b/lisp/progmodes/vhdl-mode.el
index 77d862f1a17..060880d7cf2 100644
--- a/lisp/progmodes/vhdl-mode.el
+++ b/lisp/progmodes/vhdl-mode.el
@@ -1,12 +1,12 @@
;;; vhdl-mode.el --- major mode for editing VHDL code -*- lexical-binding: t; -*-
-;; Copyright (C) 1992-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1992-2024 Free Software Foundation, Inc.
;; Authors: Reto Zimmermann <reto@gnu.org>
;; Rodney J. Whitby <software.vhdl-mode@rwhitby.net>
;; Maintainer: Reto Zimmermann <reto@gnu.org>
;; Keywords: languages vhdl
-;; WWW: https://guest.iis.ee.ethz.ch/~zimmi/emacs/vhdl-mode.html
+;; URL: https://iis-people.ee.ethz.ch/~zimmi/emacs/vhdl-mode.html
;; Yoni Rabkin <yoni@rabkins.net> contacted the maintainer of this
;; file on 18/3/2008, and the maintainer agreed that when a bug is
@@ -11769,8 +11769,8 @@ reflected in a subsequent paste operation."
(setq comment (substring type (match-beginning 2)))
(setq type (substring type 0 (match-beginning 1))))
;; strip of trailing group-comment
- (string-match "\\(\\(\\s-*\\S-+\\)+\\)\\s-*" type)
- (setq type (substring type 0 (match-end 1)))
+ (when (string-match "\\S-\\s-*\\'" type)
+ (setq type (substring type 0 (1+ (match-beginning 0)))))
;; parse initialization expression
(setq init nil)
(when (vhdl-parse-string ":=[ \t\n\r\f]*" t)
@@ -11844,8 +11844,8 @@ reflected in a subsequent paste operation."
(setq comment (substring type (match-beginning 2)))
(setq type (substring type 0 (match-beginning 1))))
;; strip of trailing group-comment
- (string-match "\\(\\(\\s-*\\S-+\\)+\\)\\s-*" type)
- (setq type (substring type 0 (match-end 1)))
+ (when (string-match "\\S-\\s-*\\'" type)
+ (setq type (substring type 0 (1+ (match-beginning 0)))))
(vhdl-forward-syntactic-ws)
(setq end-of-list (vhdl-parse-string ")" t))
(vhdl-parse-string "\\s-*;\\s-*")
@@ -12580,8 +12580,8 @@ reflected in a subsequent paste operation."
(setq comment (substring type (match-beginning 2)))
(setq type (substring type 0 (match-beginning 1))))
;; strip off trailing group-comment
- (string-match "\\(\\(\\s-*\\S-+\\)+\\)\\s-*" type)
- (setq type (substring type 0 (match-end 1)))
+ (when (string-match "\\S-\\s-*\\'" type)
+ (setq type (substring type 0 (1+ (match-beginning 0)))))
;; parse initialization expression
(setq init nil)
(when (vhdl-parse-string ":=[ \t\n\r\f]*" t)
@@ -12621,8 +12621,9 @@ reflected in a subsequent paste operation."
(setq return-comment (substring return-type (match-beginning 2)))
(setq return-type (substring return-type 0 (match-beginning 1))))
;; strip of trailing group-comment
- (string-match "\\(\\(\\s-*\\S-+\\)+\\)\\s-*" return-type)
- (setq return-type (substring return-type 0 (match-end 1)))
+ (when (string-match "\\S-\\s-*\\'" return-type)
+ (setq return-type
+ (substring return-type 0 (1+ (match-beginning 0)))))
;; parse return comment
(unless return-comment
(setq return-comment (and (vhdl-parse-string "--\\s-*\\([^\n]*\\)" t)
diff --git a/lisp/progmodes/which-func.el b/lisp/progmodes/which-func.el
index 09d0250515f..bd68672f905 100644
--- a/lisp/progmodes/which-func.el
+++ b/lisp/progmodes/which-func.el
@@ -1,6 +1,6 @@
;;; which-func.el --- print current function in mode line -*- lexical-binding:t -*-
-;; Copyright (C) 1994-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1994-2024 Free Software Foundation, Inc.
;; Author: Alex Rezinsky <alexr@msil.sps.mot.com>
;; Maintainer: emacs-devel@gnu.org
@@ -208,21 +208,28 @@ non-nil.")
(add-hook 'after-change-major-mode-hook #'which-func-ff-hook t)
(defun which-func-try-to-enable ()
- (unless (or (not which-function-mode)
- (local-variable-p 'which-func-mode))
- (setq which-func-mode (or (eq which-func-modes t)
- (member major-mode which-func-modes)))
- (setq which-func--use-mode-line
- (member which-func-display '(mode mode-and-header)))
- (setq which-func--use-header-line
- (member which-func-display '(header mode-and-header)))
- (when (and which-func-mode which-func--use-header-line)
+ (when which-function-mode
+ (unless (local-variable-p 'which-func-mode)
+ (setq which-func-mode (or (eq which-func-modes t)
+ (member major-mode which-func-modes)))
+ (setq which-func--use-mode-line
+ (member which-func-display '(mode mode-and-header)))
+ (setq which-func--use-header-line
+ (member which-func-display '(header mode-and-header))))
+ ;; We might need to re-add which-func-format to the header line,
+ ;; if which-function-mode was toggled off and on.
+ (when (and which-func-mode which-func--use-header-line
+ (listp header-line-format))
(add-to-list 'header-line-format '("" which-func-format " ")))))
-(defun which-func--disable ()
- (when (and which-func-mode which-func--use-header-line)
+(defun which-func--header-line-remove ()
+ (when (and which-func-mode which-func--use-header-line
+ (listp header-line-format))
(setq header-line-format
- (delete '("" which-func-format " ") header-line-format)))
+ (delete '("" which-func-format " ") header-line-format))))
+
+(defun which-func--disable ()
+ (which-func--header-line-remove)
(setq which-func-mode nil))
(defun which-func-ff-hook ()
@@ -288,9 +295,11 @@ in certain major modes."
(when which-function-mode
;;Turn it on.
(setq which-func-update-timer
- (run-with-idle-timer idle-update-delay t #'which-func-update))
- (dolist (buf (buffer-list))
- (with-current-buffer buf (which-func-try-to-enable)))))
+ (run-with-idle-timer idle-update-delay t #'which-func-update)))
+ (dolist (buf (buffer-list))
+ (with-current-buffer buf
+ (which-func--header-line-remove)
+ (which-func-ff-hook))))
(defvar which-function-imenu-failed nil
"Locally t in a buffer if `imenu--make-index-alist' found nothing there.")
diff --git a/lisp/progmodes/xref.el b/lisp/progmodes/xref.el
index 3f75f8d7132..717b837a2e5 100644
--- a/lisp/progmodes/xref.el
+++ b/lisp/progmodes/xref.el
@@ -1,6 +1,6 @@
;;; xref.el --- Cross-referencing commands -*-lexical-binding:t-*-
-;; Copyright (C) 2014-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2014-2024 Free Software Foundation, Inc.
;; Version: 1.6.3
;; Package-Requires: ((emacs "26.1"))
@@ -281,9 +281,10 @@ current project's main and external roots."
(xref-references-in-directory identifier dir)
(message "Searching %s... done" dir)))
(let ((pr (project-current t)))
- (cons
- (xref--project-root pr)
- (project-external-roots pr)))))
+ (project-combine-directories
+ (cons
+ (xref--project-root pr)
+ (project-external-roots pr))))))
(cl-defgeneric xref-backend-apropos (backend pattern)
"Find all symbols that match PATTERN string.
@@ -638,6 +639,18 @@ If SELECT is non-nil, select the target window."
"Face used to highlight matches in the xref buffer."
:version "28.1")
+(defvar-local xref-num-matches-found 0)
+
+(defvar xref-num-matches-face 'compilation-info
+ "Face name to show the number of matches on the mode line.")
+
+(defconst xref-mode-line-matches
+ `(" [" (:propertize (:eval (int-to-string xref-num-matches-found))
+ face ,xref-num-matches-face
+ help-echo "Number of matches so far")
+ "]"))
+(put 'xref-mode-line-matches 'risky-local-variable t)
+
(defmacro xref--with-dedicated-window (&rest body)
`(let* ((xref-w (get-buffer-window xref-buffer-name))
(xref-w-dedicated (window-dedicated-p xref-w)))
@@ -1235,6 +1248,8 @@ Return an alist of the form ((GROUP . (XREF ...)) ...)."
(xref--ensure-default-directory dd (current-buffer))
(xref--xref-buffer-mode)
(xref--show-common-initialize xref-alist fetcher alist)
+ (setq xref-num-matches-found (length xrefs))
+ (setq mode-line-process (list xref-mode-line-matches))
(pop-to-buffer (current-buffer))
(setq buf (current-buffer)))
(xref--auto-jump-first buf (assoc-default 'auto-jump alist))
@@ -1468,7 +1483,6 @@ The meanings of both arguments are the same as documented in
(xref--show-xrefs fetcher display-action))
(defun xref--show-xrefs (fetcher display-action &optional _always-show-list)
- (xref--push-markers)
(unless (functionp fetcher)
;; Old convention.
(let ((xrefs fetcher))
@@ -1479,21 +1493,32 @@ The meanings of both arguments are the same as documented in
(prog1
xrefs
(setq xrefs 'called-already)))))))
- (funcall xref-show-xrefs-function fetcher
- `((window . ,(selected-window))
- (display-action . ,display-action)
- (auto-jump . ,xref-auto-jump-to-first-xref))))
+ (let ((cb (current-buffer))
+ (pt (point)))
+ (prog1
+ (funcall xref-show-xrefs-function fetcher
+ `((window . ,(selected-window))
+ (display-action . ,display-action)
+ (auto-jump . ,xref-auto-jump-to-first-xref)))
+ (xref--push-markers cb pt))))
(defun xref--show-defs (xrefs display-action)
- (xref--push-markers)
- (funcall xref-show-definitions-function xrefs
- `((window . ,(selected-window))
- (display-action . ,display-action)
- (auto-jump . ,xref-auto-jump-to-first-definition))))
-
-(defun xref--push-markers ()
- (unless (region-active-p) (push-mark nil t))
- (xref-push-marker-stack))
+ (let ((cb (current-buffer))
+ (pt (point)))
+ (prog1
+ (funcall xref-show-definitions-function xrefs
+ `((window . ,(selected-window))
+ (display-action . ,display-action)
+ (auto-jump . ,xref-auto-jump-to-first-definition)))
+ (xref--push-markers cb pt))))
+
+(defun xref--push-markers (buf pt)
+ (when (buffer-live-p buf)
+ (save-excursion
+ (with-no-warnings (set-buffer buf))
+ (goto-char pt)
+ (unless (region-active-p) (push-mark nil t))
+ (xref-push-marker-stack))))
(defun xref--prompt-p (command)
(or (eq xref-prompt-for-identifier t)
@@ -1638,7 +1663,9 @@ This command is intended to be bound to a mouse event."
(mouse-set-point event)
(xref-backend-identifier-at-point (xref-find-backend)))))
(if identifier
- (xref-find-definitions identifier)
+ (progn
+ (mouse-set-point event)
+ (xref-find-definitions identifier))
(user-error "No identifier here"))))
;;;###autoload
@@ -1652,6 +1679,7 @@ This command is intended to be bound to a mouse event."
(xref-backend-identifier-at-point (xref-find-backend)))))
(if identifier
(let ((xref-prompt-for-identifier nil))
+ (mouse-set-point event)
(xref-find-references identifier))
(user-error "No identifier here"))))
diff --git a/lisp/progmodes/xscheme.el b/lisp/progmodes/xscheme.el
index 402f0fc09b1..598328dddea 100644
--- a/lisp/progmodes/xscheme.el
+++ b/lisp/progmodes/xscheme.el
@@ -1,6 +1,6 @@
;;; xscheme.el --- run MIT Scheme under Emacs -*- lexical-binding: t; -*-
-;; Copyright (C) 1986-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1986-2024 Free Software Foundation, Inc.
;; Maintainer: emacs-devel@gnu.org
;; Keywords: languages, lisp
diff --git a/lisp/ps-bdf.el b/lisp/ps-bdf.el
index bdc28f927ab..ee754077009 100644
--- a/lisp/ps-bdf.el
+++ b/lisp/ps-bdf.el
@@ -1,6 +1,6 @@
;;; ps-bdf.el --- BDF font file handler for ps-print -*- lexical-binding: t; -*-
-;; Copyright (C) 1998-1999, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-1999, 2001-2024 Free Software Foundation, Inc.
;; Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
;; 2008, 2009, 2010, 2011
;; National Institute of Advanced Industrial Science and Technology (AIST)
@@ -11,7 +11,7 @@
;; Author: Kenichi Handa <handa@gnu.org>
;; (according to ack.texi)
-;; Keywords: wp, BDF, font, PostScript
+;; Keywords: text, BDF, font, PostScript
;; Package: ps-print
;; This file is part of GNU Emacs.
diff --git a/lisp/ps-mule.el b/lisp/ps-mule.el
index a4784954627..1ea4d8f7097 100644
--- a/lisp/ps-mule.el
+++ b/lisp/ps-mule.el
@@ -1,10 +1,10 @@
;;; ps-mule.el --- provide multi-byte character facility to ps-print -*- lexical-binding: t; -*-
-;; Copyright (C) 1998-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-2024 Free Software Foundation, Inc.
;; Author: Vinicius Jose Latorre <viniciusjl.gnu@gmail.com>
;; Kenichi Handa <handa@gnu.org> (multi-byte characters)
-;; Keywords: wp, print, PostScript, multibyte, mule
+;; Keywords: text, print, PostScript, multibyte, mule
;; Package: ps-print
;; This file is part of GNU Emacs.
diff --git a/lisp/ps-print.el b/lisp/ps-print.el
index b54f09b2bdd..b73d28280ef 100644
--- a/lisp/ps-print.el
+++ b/lisp/ps-print.el
@@ -1,13 +1,13 @@
;;; ps-print.el --- print text from the buffer as PostScript -*- lexical-binding: t -*-
-;; Copyright (C) 1993-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1993-2024 Free Software Foundation, Inc.
;; Author: Jim Thompson (was <thompson@wg2.waii.com>)
;; Jacques Duthen (was <duthen@cegelec-red.fr>)
;; Vinicius Jose Latorre <viniciusjl.gnu@gmail.com>
;; Kenichi Handa <handa@gnu.org> (multi-byte characters)
;; Maintainer: Vinicius Jose Latorre <viniciusjl.gnu@gmail.com>
-;; Keywords: wp, print, PostScript
+;; Keywords: text, print, PostScript
;; Old-Version: 7.3.5
;; URL: https://www.emacswiki.org/cgi-bin/wiki/ViniciusJoseLatorre
@@ -4850,17 +4850,6 @@ page-height == ((floor print-height ((th + ls) * zh)) * ((th + ls) * zh)) - th
(and has-local-background (ps-output "}def\n"))))
-;; Return a list of the distinct elements of LIST.
-;; Elements are compared with `equal'.
-(defun ps-remove-duplicates (list)
- (let (new (tail list))
- (while tail
- (or (member (car tail) new)
- (setq new (cons (car tail) new)))
- (setq tail (cdr tail)))
- (nreverse new)))
-
-
;; Find the first occurrence of ITEM in LIST.
;; Return the index of the matching item, or nil if not found.
;; Elements are compared with `eq'.
@@ -5342,7 +5331,7 @@ XSTART YSTART are the relative position for the first page in a sheet.")
(if ps-landscape-mode "Landscape" "Portrait")
"\n%%DocumentNeededResources: font Times-Roman Times-Italic\n%%+ font "
(mapconcat 'identity
- (ps-remove-duplicates
+ (seq-uniq
(append (ps-fonts 'ps-font-for-text)
(list (ps-font 'ps-font-for-header 'normal)
(ps-font 'ps-font-for-header 'bold)
@@ -5491,7 +5480,7 @@ XSTART YSTART are the relative position for the first page in a sheet.")
"\n%%IncludeResource: font Times-Italic"
"\n%%IncludeResource: font "
(mapconcat 'identity
- (ps-remove-duplicates
+ (seq-uniq
(append (ps-fonts 'ps-font-for-text)
(list (ps-font 'ps-font-for-header 'normal)
(ps-font 'ps-font-for-header 'bold)
@@ -6548,6 +6537,7 @@ Please send all bug fixes and enhancements to
(make-obsolete-variable 'ps-print-version 'emacs-version "29.1")
(define-obsolete-function-alias 'ps-print-ensure-fontified #'font-lock-ensure "29.1")
+(define-obsolete-function-alias 'ps-remove-duplicates #'seq-uniq "30.1")
(provide 'ps-print)
diff --git a/lisp/ps-samp.el b/lisp/ps-samp.el
index d66d1939801..828a9eb5f08 100644
--- a/lisp/ps-samp.el
+++ b/lisp/ps-samp.el
@@ -1,13 +1,13 @@
;;; ps-samp.el --- ps-print sample setup code -*- lexical-binding: t -*-
-;; Copyright (C) 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2024 Free Software Foundation, Inc.
;; Author: Jim Thompson (was <thompson@wg2.waii.com>)
;; Jacques Duthen (was <duthen@cegelec-red.fr>)
;; Vinicius Jose Latorre <viniciusjl.gnu@gmail.com>
;; Kenichi Handa <handa@gnu.org> (multi-byte characters)
;; Maintainer: Vinicius Jose Latorre <viniciusjl.gnu@gmail.com>
-;; Keywords: wp, print, PostScript
+;; Keywords: text, print, PostScript
;; URL: https://www.emacswiki.org/cgi-bin/wiki/ViniciusJoseLatorre
;; Package: ps-print
diff --git a/lisp/recentf.el b/lisp/recentf.el
index 94ae871763b..2529424b8eb 100644
--- a/lisp/recentf.el
+++ b/lisp/recentf.el
@@ -1,6 +1,6 @@
;;; recentf.el --- keep track of recently opened files -*- lexical-binding: t -*-
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
;; Author: David Ponce <david@dponce.com>
;; Created: July 19 1999
@@ -805,25 +805,31 @@ Filenames are relative to the `default-directory'."
;;; Rule based menu filters
;;
(defcustom recentf-arrange-rules
- '(
- ("Elisp files (%d)" ".\\.el\\'")
- ("Java files (%d)" ".\\.java\\'")
- ("C/C++ files (%d)" "c\\(pp\\)?\\'")
+ `(
+ ("Elisp files (%d)" ,(rx nonl ".el" eos))
+ ("C/C++ files (%d)" ,(rx nonl "."
+ (or "c" "cc" "cpp" "h" "hpp" "cxx" "hxx")
+ eos))
+ ("Python files (%d)" ,(rx nonl ".py" eos))
+ ("Java files (%d)" ,(rx nonl ".java" eos))
)
"List of rules used by `recentf-arrange-by-rule' to build sub-menus.
+
A rule is a pair (SUB-MENU-TITLE . MATCHER). SUB-MENU-TITLE is the
displayed title of the sub-menu where a `%d' `format' pattern is
replaced by the number of items in the sub-menu. MATCHER is a regexp
or a list of regexps. Items matching one of the regular expressions in
MATCHER are added to the corresponding sub-menu.
-SUB-MENU-TITLE can be a function. It is passed every items that
+
+SUB-MENU-TITLE can be a function. It is passed every item that
matched the corresponding MATCHER, and it must return a
pair (SUB-MENU-TITLE . ITEM). SUB-MENU-TITLE is a computed sub-menu
title that can be another function. ITEM is the received item which
may have been modified to match another rule."
:group 'recentf-filters
:type '(repeat (cons (choice string function)
- (repeat regexp))))
+ (repeat regexp)))
+ :version "30.1")
(defcustom recentf-arrange-by-rule-others "Other files (%d)"
"Title of the `recentf-arrange-by-rule' sub-menu.
diff --git a/lisp/rect.el b/lisp/rect.el
index 8dc188b1de0..0212dedcb48 100644
--- a/lisp/rect.el
+++ b/lisp/rect.el
@@ -1,6 +1,6 @@
;;; rect.el --- rectangle functions for GNU Emacs -*- lexical-binding:t -*-
-;; Copyright (C) 1985, 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1985, 1999-2024 Free Software Foundation, Inc.
;; Maintainer: Didier Verna <didier@didierverna.net>
;; Keywords: internal
@@ -212,7 +212,10 @@ The returned value has the form of (WIDTH . HEIGHT)."
(cons width height))))
(defun delete-rectangle-line (startcol endcol fill)
- (when (= (move-to-column startcol (if fill t 'coerce)) startcol)
+ ;; We use >= here, not =, for characters that use more than one
+ ;; column on display, when STARTCOL is in the middle of such a
+ ;; character.
+ (when (>= (move-to-column startcol (if fill t 'coerce)) startcol)
(delete-region (point)
(progn (move-to-column endcol 'coerce)
(point)))))
@@ -279,7 +282,8 @@ When called from a program the rectangle's corners are START and END.
With a prefix (or a FILL) argument, also fill lines where nothing has
to be deleted."
(interactive "*r\nP")
- (apply-on-rectangle 'delete-rectangle-line start end fill))
+ (let (indent-tabs-mode)
+ (apply-on-rectangle 'delete-rectangle-line start end fill)))
;;;###autoload
(defun delete-extract-rectangle (start end &optional fill)
@@ -334,7 +338,8 @@ you can use this command to copy text from a read-only buffer.
even beep.)"
(interactive "r\nP")
(condition-case nil
- (setq killed-rectangle (delete-extract-rectangle start end fill))
+ (let (indent-tabs-mode)
+ (setq killed-rectangle (delete-extract-rectangle start end fill)))
((buffer-read-only text-read-only)
(setq deactivate-mark t)
(setq killed-rectangle (extract-rectangle start end))
diff --git a/lisp/register.el b/lisp/register.el
index ca6de450993..baad2c2a05d 100644
--- a/lisp/register.el
+++ b/lisp/register.el
@@ -1,6 +1,6 @@
;;; register.el --- register commands for Emacs -*- lexical-binding: t; -*-
-;; Copyright (C) 1985, 1993-1994, 2001-2023 Free Software Foundation,
+;; Copyright (C) 1985, 1993-1994, 2001-2024 Free Software Foundation,
;; Inc.
;; Maintainer: emacs-devel@gnu.org
@@ -35,6 +35,8 @@
;; FIXME: Clean up namespace usage!
+(declare-function frameset-register-p "frameset")
+
(cl-defstruct
(registerv (:constructor nil)
(:constructor registerv--make (&optional data print-func
@@ -94,17 +96,69 @@ of the marked text."
(defcustom register-preview-delay 1
"If non-nil, time to wait in seconds before popping up register preview window.
If nil, do not show register previews, unless `help-char' (or a member of
-`help-event-list') is pressed."
+`help-event-list') is pressed.
+
+This variable has no effect when `register-use-preview' is set to any
+value except \\='traditional."
:version "24.4"
:type '(choice number (const :tag "No preview unless requested" nil))
:group 'register)
+(defcustom register-preview-default-keys (mapcar #'string (number-sequence ?a ?z))
+ "Default keys for setting a new register."
+ :type '(repeat string)
+ :version "30.1")
+
+(defvar register--read-with-preview-function nil
+ "Function to use for reading a register name with preview.
+Two functions are provided, one that provide navigation and highlighting
+of the selected register, filtering of register according to command in
+use, defaults register to use when setting a new register, confirmation
+and notification when you are about to overwrite a register, and generic
+functions to configure how each existing command behaves. Use the
+function `register-read-with-preview-fancy' for this. The other
+provided function, `register-read-with-preview-traditional', behaves
+the same as in Emacs 29 and before: no filtering, no navigation,
+and no defaults.")
+
+(defvar register-preview-function nil
+ "Function to format a register for previewing.
+Called with one argument, a cons (NAME . CONTENTS), as found
+in `register-alist'. The function should return a string, the
+description of the argument. The function to use is set according
+to the value of `register--read-with-preview-function'.")
+
+(defcustom register-use-preview 'traditional
+ "Whether to show register preview when modifying registers.
+
+When set to `t', show a preview buffer with navigation and highlighting.
+When nil, show a preview buffer without navigation and highlighting, and
+exit the minibuffer immediately after inserting response in minibuffer.
+When set to \\='never, behave as with nil, but with no preview buffer at
+all; the preview buffer is still accessible with `help-char' (C-h).
+When set to \\='traditional (the default), provide a more basic preview
+according to `register-preview-delay'; this preserves the traditional
+behavior of Emacs 29 and before."
+ :type '(choice
+ (const :tag "Use preview" t)
+ (const :tag "Use quick preview" nil)
+ (const :tag "Never use preview" never)
+ (const :tag "Basic preview like Emacs-29" traditional))
+ :version "30.1"
+ :set (lambda (var val)
+ (set var val)
+ (setq register--read-with-preview-function
+ (if (eq val 'traditional)
+ #'register-read-with-preview-traditional
+ #'register-read-with-preview-fancy))
+ (setq register-preview-function nil)))
+
(defun get-register (register)
"Return contents of Emacs register named REGISTER, or nil if none."
(alist-get register register-alist))
(defun set-register (register value)
- "Set contents of Emacs register named REGISTER to VALUE. Return VALUE.
+ "Set contents of Emacs register named REGISTER to VALUE, return VALUE.
See the documentation of the variable `register-alist' for possible VALUEs."
(setf (alist-get register register-alist) value))
@@ -117,21 +171,220 @@ See the documentation of the variable `register-alist' for possible VALUEs."
(substring d (match-end 0))
d)))
+(defun register-preview-default-1 (r)
+ "Function used to format a register for fancy previewing.
+This is used as the value of the variable `register-preview-function'
+when `register-use-preview' is set to t or nil."
+ (format "%s: %s\n"
+ (propertize (string (car r))
+ 'display (single-key-description (car r)))
+ (register-describe-oneline (car r))))
+
(defun register-preview-default (r)
- "Function that is the default value of the variable `register-preview-function'."
+ "Function used to format a register for traditional preview.
+This is the default value of the variable `register-preview-function',
+and is used when `register-use-preview' is set to \\='traditional."
(format "%s: %s\n"
(single-key-description (car r))
(register-describe-oneline (car r))))
-(defvar register-preview-function #'register-preview-default
- "Function to format a register for previewing.
-Called with one argument, a cons (NAME . CONTENTS) as found in `register-alist'.
-The function should return a string, the description of the argument.")
+(cl-defgeneric register--preview-function (read-preview-function)
+ "Return a function to format registers for previewing by READ-PREVIEW-FUNCTION.")
+(cl-defmethod register--preview-function ((_read-preview-function
+ (eql register-read-with-preview-traditional)))
+ #'register-preview-default)
+(cl-defmethod register--preview-function ((_read-preview-function
+ (eql register-read-with-preview-fancy)))
+ #'register-preview-default-1)
+
+(cl-defstruct register-preview-info
+ "Store data for a specific register command.
+TYPES are the supported types of registers.
+MSG is the minibuffer message to show when a register is selected.
+ACT is the type of action the command is doing on register.
+SMATCH accept a boolean value to say if the command accepts non-matching
+registers.
+If NOCONFIRM is non-nil, request confirmation of register name by RET."
+ types msg act smatch noconfirm)
+
+(cl-defgeneric register-command-info (command)
+ "Return a `register-preview-info' object storing data for COMMAND."
+ (ignore command))
+(cl-defmethod register-command-info ((_command (eql insert-register)))
+ (make-register-preview-info
+ :types '(string number)
+ :msg "Insert register `%s'"
+ :act 'insert
+ :smatch t
+ :noconfirm (memq register-use-preview '(nil never))))
+(cl-defmethod register-command-info ((_command (eql jump-to-register)))
+ (make-register-preview-info
+ :types '(window frame marker kmacro
+ file buffer file-query)
+ :msg "Jump to register `%s'"
+ :act 'jump
+ :smatch t
+ :noconfirm (memq register-use-preview '(nil never))))
+(cl-defmethod register-command-info ((_command (eql view-register)))
+ (make-register-preview-info
+ :types '(all)
+ :msg "View register `%s'"
+ :act 'view
+ :noconfirm (memq register-use-preview '(nil never))
+ :smatch t))
+(cl-defmethod register-command-info ((_command (eql append-to-register)))
+ (make-register-preview-info
+ :types '(string number)
+ :msg "Append to register `%s'"
+ :act 'modify
+ :noconfirm (memq register-use-preview '(nil never))
+ :smatch t))
+(cl-defmethod register-command-info ((_command (eql prepend-to-register)))
+ (make-register-preview-info
+ :types '(string number)
+ :msg "Prepend to register `%s'"
+ :act 'modify
+ :noconfirm (memq register-use-preview '(nil never))
+ :smatch t))
+(cl-defmethod register-command-info ((_command (eql increment-register)))
+ (make-register-preview-info
+ :types '(string number)
+ :msg "Increment register `%s'"
+ :act 'modify
+ :noconfirm (memq register-use-preview '(nil never))
+ :smatch t))
+(cl-defmethod register-command-info ((_command (eql copy-to-register)))
+ (make-register-preview-info
+ :types '(all)
+ :msg "Copy to register `%s'"
+ :act 'set
+ :noconfirm (memq register-use-preview '(nil never))))
+(cl-defmethod register-command-info ((_command (eql point-to-register)))
+ (make-register-preview-info
+ :types '(all)
+ :msg "Point to register `%s'"
+ :act 'set
+ :noconfirm (memq register-use-preview '(nil never))))
+(cl-defmethod register-command-info ((_command (eql number-to-register)))
+ (make-register-preview-info
+ :types '(all)
+ :msg "Number to register `%s'"
+ :act 'set
+ :noconfirm (memq register-use-preview '(nil never))))
+(cl-defmethod register-command-info
+ ((_command (eql window-configuration-to-register)))
+ (make-register-preview-info
+ :types '(all)
+ :msg "Window configuration to register `%s'"
+ :act 'set
+ :noconfirm (memq register-use-preview '(nil never))))
+(cl-defmethod register-command-info ((_command (eql frameset-to-register)))
+ (make-register-preview-info
+ :types '(all)
+ :msg "Frameset to register `%s'"
+ :act 'set
+ :noconfirm (memq register-use-preview '(nil never))))
+(cl-defmethod register-command-info ((_command (eql copy-rectangle-to-register)))
+ (make-register-preview-info
+ :types '(all)
+ :msg "Copy rectangle to register `%s'"
+ :act 'set
+ :noconfirm (memq register-use-preview '(nil never))
+ :smatch t))
+
+(defun register-preview-forward-line (arg)
+ "Move to next or previous line in register preview buffer.
+If ARG is positive, go to next line; if negative, go to previous line.
+Do nothing when defining or executing kmacros."
+ ;; Ensure user enter manually key in minibuffer when recording a macro.
+ (unless (or defining-kbd-macro executing-kbd-macro
+ (not (get-buffer-window "*Register Preview*" 'visible)))
+ (let ((fn (if (> arg 0) #'eobp #'bobp))
+ (posfn (if (> arg 0)
+ #'point-min
+ (lambda () (1- (point-max)))))
+ str)
+ (with-current-buffer "*Register Preview*"
+ (let ((ovs (overlays-in (point-min) (point-max)))
+ pos)
+ (goto-char (if ovs
+ (overlay-start (car ovs))
+ (point-min)))
+ (setq pos (point))
+ (and ovs (forward-line arg))
+ (when (and (funcall fn)
+ (or (> arg 0) (eql pos (point))))
+ (goto-char (funcall posfn)))
+ (setq str (buffer-substring-no-properties
+ (pos-bol) (1+ (pos-bol))))
+ (remove-overlays)
+ (with-selected-window (minibuffer-window)
+ (delete-minibuffer-contents)
+ (insert str)))))))
+
+(defun register-preview-next ()
+ "Go to next line in the register preview buffer."
+ (interactive)
+ (register-preview-forward-line 1))
+
+(defun register-preview-previous ()
+ "Go to previous line in the register preview buffer."
+ (interactive)
+ (register-preview-forward-line -1))
+
+(defun register-type (register)
+ "Return REGISTER type.
+Register type that can be returned is one of the following:
+ - string
+ - number
+ - marker
+ - buffer
+ - file
+ - file-query
+ - window
+ - frame
+ - kmacro
+
+One can add new types to a specific command by defining a new `cl-defmethod'
+matching that command. Predicates for type in new `cl-defmethod' should
+satisfy `cl-typep', otherwise the new type should be defined with
+`cl-deftype'."
+ ;; Call register--type against the register value.
+ (register--type (if (consp (cdr register))
+ (cadr register)
+ (cdr register))))
+
+(cl-defgeneric register--type (regval)
+ "Return the type of register value REGVAL."
+ (ignore regval))
+
+(cl-defmethod register--type ((_regval string)) 'string)
+(cl-defmethod register--type ((_regval number)) 'number)
+(cl-defmethod register--type ((_regval marker)) 'marker)
+(cl-defmethod register--type ((_regval (eql buffer))) 'buffer)
+(cl-defmethod register--type ((_regval (eql file))) 'file)
+(cl-defmethod register--type ((_regval (eql file-query))) 'file-query)
+(cl-defmethod register--type ((_regval window-configuration)) 'window)
+(cl-deftype frame-register () '(satisfies frameset-register-p))
+(cl-defmethod register--type :extra "frame-register" (_regval) 'frame)
+(cl-deftype kmacro-register () '(satisfies kmacro-register-p))
+(cl-defmethod register--type :extra "kmacro-register" (_regval) 'kmacro)
+
+(defun register-of-type-alist (types)
+ "Filter `register-alist' according to TYPES."
+ (if (memq 'all types)
+ register-alist
+ (cl-loop for register in register-alist
+ when (memq (register-type register) types)
+ collect register)))
(defun register-preview (buffer &optional show-empty)
- "Pop up a window showing the registers preview in BUFFER.
-If SHOW-EMPTY is non-nil, show the window even if no registers.
+ "Pop up a window showing the preview of registers in BUFFER.
+If SHOW-EMPTY is non-nil, show the preview window even if no registers.
Format of each entry is controlled by the variable `register-preview-function'."
+ (unless register-preview-function
+ (setq register-preview-function (register--preview-function
+ register--read-with-preview-function)))
(when (or show-empty (consp register-alist))
(with-current-buffer-window
buffer
@@ -146,13 +399,61 @@ Format of each entry is controlled by the variable `register-preview-function'."
(insert (funcall register-preview-function elem))))
register-alist)))))
+(defun register-preview-1 (buffer &optional show-empty types)
+ "Pop up a window showing the preview of registers in BUFFER.
+
+This is the preview function used with the `register-read-with-preview-fancy'
+function.
+If SHOW-EMPTY is non-nil, show the preview window even if no registers.
+Optional argument TYPES (a list) specifies the types of register to show;
+if it is nil, show all the registers. See `register-type' for suitable types.
+Format of each entry is controlled by the variable `register-preview-function'."
+ (unless register-preview-function
+ (setq register-preview-function (register--preview-function
+ register--read-with-preview-function)))
+ (let ((registers (register-of-type-alist (or types '(all)))))
+ (when (or show-empty (consp registers))
+ (with-current-buffer-window
+ buffer
+ (cons 'display-buffer-below-selected
+ '((window-height . fit-window-to-buffer)
+ (preserve-size . (nil . t))))
+ nil
+ (with-current-buffer standard-output
+ (setq cursor-in-non-selected-windows nil)
+ (mapc (lambda (elem)
+ (when (get-register (car elem))
+ (insert (funcall register-preview-function elem))))
+ registers))))))
+
+(cl-defgeneric register-preview-get-defaults (action)
+ "Return default registers according to ACTION."
+ (ignore action))
+(cl-defmethod register-preview-get-defaults ((_action (eql set)))
+ (cl-loop for s in register-preview-default-keys
+ unless (assoc (string-to-char s) register-alist)
+ collect s))
+
(defun register-read-with-preview (prompt)
- "Read and return a register name, possibly showing existing registers.
-Prompt with the string PROMPT. If `register-alist' and
-`register-preview-delay' are both non-nil, display a window
-listing existing registers after `register-preview-delay' seconds.
+ "Read register name, prompting with PROMPT; possibly show existing registers.
+This reads and returns the name of a register. PROMPT should be a string
+to prompt the user for the name.
If `help-char' (or a member of `help-event-list') is pressed,
-display such a window regardless."
+display preview window unconditionally.
+This calls the function specified by `register--read-with-preview-function'."
+ (funcall register--read-with-preview-function prompt))
+
+(defun register-read-with-preview-traditional (prompt)
+ "Read register name, prompting with PROMPT; possibly show existing registers.
+This reads and returns the name of a register. PROMPT should be a string
+to prompt the user for the name.
+If `register-alist' and `register-preview-delay' are both non-nil, display
+a window listing existing registers after `register-preview-delay' seconds.
+If `help-char' (or a member of `help-event-list') is pressed,
+display preview window unconditionally.
+
+This function is used as the value of `register--read-with-preview-function'
+when `register-use-preview' is set to \\='traditional."
(let* ((buffer "*Register Preview*")
(timer (when (numberp register-preview-delay)
(run-with-timer register-preview-delay nil
@@ -179,6 +480,118 @@ display such a window regardless."
(and (window-live-p w) (delete-window w)))
(and (get-buffer buffer) (kill-buffer buffer)))))
+(defun register-read-with-preview-fancy (prompt)
+ "Read register name, prompting with PROMPT; possibly show existing registers.
+This reads and returns the name of a register. PROMPT should be a string
+to prompt the user for the name.
+If `help-char' (or a member of `help-event-list') is pressed,
+display preview window regardless.
+
+This function is used as the value of `register--read-with-preview-function'
+when `register-use-preview' is set to any value other than \\='traditional
+or \\='never."
+ (let* ((buffer "*Register Preview*")
+ (buffer1 "*Register quick preview*")
+ (buf (if register-use-preview buffer buffer1))
+ (pat "")
+ (map (let ((m (make-sparse-keymap)))
+ (set-keymap-parent m minibuffer-local-map)
+ m))
+ (data (register-command-info this-command))
+ (enable-recursive-minibuffers t)
+ types msg result act win strs smatch noconfirm)
+ (if data
+ (setq types (register-preview-info-types data)
+ msg (register-preview-info-msg data)
+ act (register-preview-info-act data)
+ smatch (register-preview-info-smatch data)
+ noconfirm (register-preview-info-noconfirm data))
+ (setq types '(all)
+ msg "Overwrite register `%s'"
+ act 'set))
+ (setq strs (mapcar (lambda (x)
+ (string (car x)))
+ (register-of-type-alist types)))
+ (when (and (memq act '(insert jump view)) (null strs))
+ (error "No register suitable for `%s'" act))
+ (dolist (k (cons help-char help-event-list))
+ (define-key map (vector k)
+ (lambda ()
+ (interactive)
+ ;; Do nothing when buffer1 is in use.
+ (unless (get-buffer-window buf)
+ (with-selected-window (minibuffer-selected-window)
+ (register-preview-1 buffer 'show-empty types))))))
+ (define-key map (kbd "<down>") 'register-preview-next)
+ (define-key map (kbd "<up>") 'register-preview-previous)
+ (define-key map (kbd "C-n") 'register-preview-next)
+ (define-key map (kbd "C-p") 'register-preview-previous)
+ (unless (or executing-kbd-macro (eq register-use-preview 'never))
+ (register-preview-1 buf nil types))
+ (unwind-protect
+ (let ((setup
+ (lambda ()
+ (with-selected-window (minibuffer-window)
+ (let ((input (minibuffer-contents)))
+ (when (> (length input) 1)
+ (let ((new (substring input 1))
+ (old (substring input 0 1)))
+ (setq input (if (or (null smatch)
+ (member new strs))
+ new old))
+ (delete-minibuffer-contents)
+ (insert input)))
+ (when (and smatch (not (string= input ""))
+ (not (member input strs)))
+ (setq input "")
+ (delete-minibuffer-contents)
+ (minibuffer-message "Not matching"))
+ (when (not (string= input pat))
+ (setq pat input))))
+ (if (setq win (get-buffer-window buffer))
+ (with-selected-window win
+ (let ((ov (make-overlay
+ (point-min) (point-min)))
+ ;; Allow upper-case and lower-case letters
+ ;; to refer to different registers.
+ (case-fold-search nil))
+ (goto-char (point-min))
+ (remove-overlays)
+ (unless (string= pat "")
+ (if (re-search-forward (concat "^" pat) nil t)
+ (progn (move-overlay
+ ov
+ (match-beginning 0) (pos-eol))
+ (overlay-put ov 'face 'match)
+ (when msg
+ (with-selected-window
+ (minibuffer-window)
+ (minibuffer-message msg pat))))
+ (with-selected-window (minibuffer-window)
+ (minibuffer-message
+ "Register `%s' is empty" pat))))))
+ (unless (string= pat "")
+ (with-selected-window (minibuffer-window)
+ (if (and (member pat strs)
+ (null noconfirm))
+ (with-selected-window (minibuffer-window)
+ (minibuffer-message msg pat))
+ ;; `:noconfirm' is specified explicitly, don't ask for
+ ;; confirmation and exit immediately (bug#66394).
+ (setq result pat)
+ (exit-minibuffer))))))))
+ (minibuffer-with-setup-hook
+ (lambda () (add-hook 'post-command-hook setup nil 'local))
+ (setq result (read-from-minibuffer
+ prompt nil map nil nil
+ (register-preview-get-defaults act))))
+ (cl-assert (and result (not (string= result "")))
+ nil "No register specified")
+ (string-to-char result))
+ (let ((w (get-buffer-window buf)))
+ (and (window-live-p w) (delete-window w)))
+ (and (get-buffer buf) (kill-buffer buf)))))
+
(defun point-to-register (register &optional arg)
"Store current location of point in REGISTER.
With prefix argument ARG, store current frame configuration (a.k.a. \"frameset\").
diff --git a/lisp/registry.el b/lisp/registry.el
index c5f11714975..bd901b8a849 100644
--- a/lisp/registry.el
+++ b/lisp/registry.el
@@ -1,6 +1,6 @@
;;; registry.el --- Track and remember data items by various fields -*- lexical-binding: t; -*-
-;; Copyright (C) 2011-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2011-2024 Free Software Foundation, Inc.
;; Author: Teodor Zlatanov <tzz@lifelogs.com>
;; Keywords: data
diff --git a/lisp/repeat.el b/lisp/repeat.el
index 2fcac4d2ce3..0a59494c097 100644
--- a/lisp/repeat.el
+++ b/lisp/repeat.el
@@ -1,6 +1,6 @@
;;; repeat.el --- convenient way to repeat the previous command -*- lexical-binding: t -*-
-;; Copyright (C) 1998, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998, 2001-2024 Free Software Foundation, Inc.
;; Author: Will Mengarini <seldon@eskimo.com>
;; Created: Mo 02 Mar 98
diff --git a/lisp/replace.el b/lisp/replace.el
index eeac734f3bd..fa460a16063 100644
--- a/lisp/replace.el
+++ b/lisp/replace.el
@@ -1,6 +1,6 @@
;;; replace.el --- replace commands for Emacs -*- lexical-binding: t -*-
-;; Copyright (C) 1985-1987, 1992, 1994, 1996-1997, 2000-2023 Free
+;; Copyright (C) 1985-1987, 1992, 1994, 1996-1997, 2000-2024 Free
;; Software Foundation, Inc.
;; Maintainer: emacs-devel@gnu.org
@@ -1667,13 +1667,15 @@ A positive number means to include that many lines both before and after."
(defcustom list-matching-lines-face 'match
"Face used by \\[list-matching-lines] to show the text that matches.
If the value is nil, don't highlight the matching portions specially."
- :type 'face
+ :type '(choice (const :tag "Don't highlight matching portions" nil)
+ face)
:group 'matching)
(defcustom list-matching-lines-buffer-name-face 'underline
"Face used by \\[list-matching-lines] to show the names of buffers.
If the value is nil, don't highlight the buffer names specially."
- :type 'face
+ :type '(choice (const :tag "Don't highlight buffer names" nil)
+ face)
:group 'matching)
(defcustom list-matching-lines-current-line-face 'lazy-highlight
@@ -2640,10 +2642,6 @@ passed in. If LITERAL is set, no checking is done, anyway."
noedit nil)))
(set-match-data match-data)
(replace-match newtext fixedcase literal)
- ;; `query-replace' undo feature needs the beginning of the match position,
- ;; but `replace-match' may change it, for instance, with a regexp like "^".
- ;; Ensure that this function preserves the match data (Bug#31492).
- (set-match-data match-data)
;; `replace-match' leaves point at the end of the replacement text,
;; so move point to the beginning when replacing backward.
(when backward (goto-char (nth 0 match-data)))
@@ -2757,6 +2755,7 @@ to a regexp that is actually used for the search.")
(isearch-regexp-lax-whitespace
replace-regexp-lax-whitespace)
(isearch-case-fold-search case-fold)
+ (isearch-invisible search-invisible)
(isearch-forward (not backward))
(isearch-other-end match-beg)
(isearch-error nil)
diff --git a/lisp/reposition.el b/lisp/reposition.el
index a422c3d88ae..83900e95f77 100644
--- a/lisp/reposition.el
+++ b/lisp/reposition.el
@@ -1,6 +1,6 @@
;;; reposition.el --- center a Lisp function or comment on the screen -*- lexical-binding: t -*-
-;; Copyright (C) 1991, 1994, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1991, 1994, 2001-2024 Free Software Foundation, Inc.
;; Author: Michael D. Ernst <mernst@theory.lcs.mit.edu>
;; Created: Jan 1991
diff --git a/lisp/reveal.el b/lisp/reveal.el
index 5ebc5f7c6c3..055667aa343 100644
--- a/lisp/reveal.el
+++ b/lisp/reveal.el
@@ -1,6 +1,6 @@
;;; reveal.el --- Automatically reveal hidden text at point -*- lexical-binding: t -*-
-;; Copyright (C) 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2000-2024 Free Software Foundation, Inc.
;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
;; Keywords: outlines
diff --git a/lisp/rfn-eshadow.el b/lisp/rfn-eshadow.el
index 75c407fd3d0..5cf483bf0b1 100644
--- a/lisp/rfn-eshadow.el
+++ b/lisp/rfn-eshadow.el
@@ -1,6 +1,6 @@
;;; rfn-eshadow.el --- Highlight `shadowed' part of read-file-name input text -*- lexical-binding: t; -*-
;;
-;; Copyright (C) 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2000-2024 Free Software Foundation, Inc.
;;
;; Author: Miles Bader <miles@gnu.org>
;; Keywords: convenience minibuffer
diff --git a/lisp/rot13.el b/lisp/rot13.el
index 2d2ed904a7c..1eb027cea68 100644
--- a/lisp/rot13.el
+++ b/lisp/rot13.el
@@ -1,6 +1,6 @@
;;; rot13.el --- display a buffer in ROT13 -*- lexical-binding: t -*-
-;; Copyright (C) 1988, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1988, 2001-2024 Free Software Foundation, Inc.
;; Author: Howard Gayle
;; Simon Josefsson
diff --git a/lisp/rtree.el b/lisp/rtree.el
index 4749629cd59..be2a6da4cfa 100644
--- a/lisp/rtree.el
+++ b/lisp/rtree.el
@@ -1,6 +1,6 @@
;;; rtree.el --- functions for manipulating range trees -*- lexical-binding:t -*-
-;; Copyright (C) 2010-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2010-2024 Free Software Foundation, Inc.
;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
diff --git a/lisp/ruler-mode.el b/lisp/ruler-mode.el
index db8b891dc62..bce6a1805bc 100644
--- a/lisp/ruler-mode.el
+++ b/lisp/ruler-mode.el
@@ -1,6 +1,6 @@
;;; ruler-mode.el --- display a ruler in the header line -*- lexical-binding: t -*-
-;; Copyright (C) 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001-2024 Free Software Foundation, Inc.
;; Author: David Ponce <david@dponce.com>
;; Created: 24 Mar 2001
diff --git a/lisp/savehist.el b/lisp/savehist.el
index ea8968c771b..5ae8a5e0340 100644
--- a/lisp/savehist.el
+++ b/lisp/savehist.el
@@ -1,6 +1,6 @@
;;; savehist.el --- Save minibuffer history -*- lexical-binding:t -*-
-;; Copyright (C) 1997-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997-2024 Free Software Foundation, Inc.
;; Author: Hrvoje Nikšić <hrvoje.niksic@avl.com>
;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/saveplace.el b/lisp/saveplace.el
index a28de6f63a8..a4942cb484b 100644
--- a/lisp/saveplace.el
+++ b/lisp/saveplace.el
@@ -1,6 +1,6 @@
;;; saveplace.el --- automatically save place in files -*- lexical-binding:t -*-
-;; Copyright (C) 1993-1994, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1993-1994, 2001-2024 Free Software Foundation, Inc.
;; Author: Karl Fogel <kfogel@red-bean.com>
;; Maintainer: emacs-devel@gnu.org
@@ -156,7 +156,9 @@ either `setopt' or M-x customize-variable to set this option."
:set (lambda (sym val)
(set-default sym val)
(or save-place-loaded (save-place-load-alist-from-file))
- (let ((fun (if val #'abbreviate-file-name #'expand-file-name)))
+ (let ((fun (if val #'abbreviate-file-name #'expand-file-name))
+ ;; Don't expand file names for non-existing remote connections.
+ (non-essential t))
(setq save-place-alist
(cl-delete-duplicates
(cl-loop for (k . v) in save-place-alist
@@ -196,12 +198,13 @@ removable and network volumes."
(defcustom save-place-ignore-files-regexp
"\\(?:COMMIT_EDITMSG\\|hg-editor-[[:alnum:]]+\\.txt\\|svn-commit\\.tmp\\|bzr_log\\.[[:alnum:]]+\\)$"
- "Regexp matching files for which no position should be recorded.
-Useful for temporary file such as commit message files that are
-automatically created by the VCS. If set to nil, this feature is
-disabled, i.e., the position is recorded for all files."
+ "Regexp matching files whose positions should not be recorded.
+Useful to exclude temporary files, such as commit message files that are
+automatically created by VCSes. If set to nil, this feature is
+disabled, i.e., no files are excluded."
:version "24.1"
- :type 'regexp)
+ :type '(choice (const :tag "Don't exclude any files" nil)
+ regexp))
(declare-function dired-current-directory "dired" (&optional localp))
diff --git a/lisp/scroll-all.el b/lisp/scroll-all.el
index 518dd3fb6cc..dc561f9115e 100644
--- a/lisp/scroll-all.el
+++ b/lisp/scroll-all.el
@@ -1,6 +1,6 @@
;;; scroll-all.el --- scroll all buffers together minor mode -*- lexical-binding: t -*-
-;; Copyright (C) 1997, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997, 2001-2024 Free Software Foundation, Inc.
;; Author: Gary D. Foster <Gary.Foster@corp.sun.com>
;; Keywords: convenience scroll lock
diff --git a/lisp/scroll-bar.el b/lisp/scroll-bar.el
index f4c1217a5a9..1358bff6da8 100644
--- a/lisp/scroll-bar.el
+++ b/lisp/scroll-bar.el
@@ -1,6 +1,6 @@
;;; scroll-bar.el --- window system-independent scroll bar support -*- lexical-binding: t; -*-
-;; Copyright (C) 1993-1995, 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1993-1995, 1999-2024 Free Software Foundation, Inc.
;; Maintainer: emacs-devel@gnu.org
;; Keywords: hardware
diff --git a/lisp/scroll-lock.el b/lisp/scroll-lock.el
index 12cdf2d0723..a9281c4bd61 100644
--- a/lisp/scroll-lock.el
+++ b/lisp/scroll-lock.el
@@ -1,6 +1,6 @@
;;; scroll-lock.el --- Scroll lock scrolling. -*- lexical-binding:t -*-
-;; Copyright (C) 2005-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2005-2024 Free Software Foundation, Inc.
;; Author: Ralf Angeli <angeli@iwi.uni-sb.de>
;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/select.el b/lisp/select.el
index 09c678867d0..ab78e88478b 100644
--- a/lisp/select.el
+++ b/lisp/select.el
@@ -1,6 +1,6 @@
;;; select.el --- lisp portion of standard selection support -*- lexical-binding:t -*-
-;; Copyright (C) 1993-1994, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1993-1994, 2001-2024 Free Software Foundation, Inc.
;; Maintainer: emacs-devel@gnu.org
;; Keywords: internal
@@ -49,27 +49,28 @@ the current system default encoding on 9x/Me, `utf-16le-dos'
\(Unicode) on NT/W2K/XP, and `iso-latin-1-dos' on MS-DOS.
For X Windows:
-When sending text via selection and clipboard, if the target
-data-type matches this coding system according to the table
-below, it is used for encoding the text. Otherwise (including
-the case that this variable is nil), a proper coding system is
-selected as below:
-
-data-type coding system
---------- -------------
-UTF8_STRING utf-8
-COMPOUND_TEXT compound-text-with-extensions
-STRING iso-latin-1
-C_STRING raw-text-unix
-
-When receiving text, if this coding system is non-nil, it is used
-for decoding regardless of the data-type. If this is nil, a
-proper coding system is used according to the data-type as above.
-See also the documentation of the variable `x-select-request-type' how
-to control which data-type to request for receiving text.
+This coding system replaces that of the default coding system
+selection text is encoded by in reaction to a request for the
+polymorphic `TEXT' selection target when its base coding system
+is compatible with `compound-text' and the text being encoded
+cannot be rendered Latin-1 without loss of information.
+
+It also replaces the coding system by which calls to
+`gui-get-selection' decode selection requests for text data
+types, which are enumerated below beside their respective coding
+systems otherwise used.
+
+DATA TYPE CODING SYSTEM
+-------------------------- -------------
+UTF8_STRING utf-8
+text/plain\\;charset=utf-8 utf-8
+COMPOUND_TEXT compound-text-with-extensions
+STRING iso-latin-1
+C_STRING raw-text-unix
-The default value is nil."
+See also the documentation of the variable `x-select-request-type' how
+to control which data-type to request for receiving text."
:type 'coding-system
:group 'mule
;; Default was compound-text-with-extensions in 22.x (pre-unicode).
diff --git a/lisp/server.el b/lisp/server.el
index 10f15598221..f75e9cb4fe5 100644
--- a/lisp/server.el
+++ b/lisp/server.el
@@ -1,6 +1,6 @@
;;; server.el --- Lisp code for GNU Emacs running as server process -*- lexical-binding: t -*-
-;; Copyright (C) 1986-1987, 1992, 1994-2023 Free Software Foundation,
+;; Copyright (C) 1986-1987, 1992, 1994-2024 Free Software Foundation,
;; Inc.
;; Author: William Sommerfeld <wesommer@athena.mit.edu>
@@ -1199,6 +1199,7 @@ The following commands are accepted by the client:
parent-id ; Window ID for XEmbed
dontkill ; t if client should not be killed.
commands
+ evalexprs
dir
use-current-frame
frame-parameters ;parameters for newly created frame
@@ -1287,9 +1288,12 @@ The following commands are accepted by the client:
;; choice there.) In daemon mode on Windows, we can't
;; make tty frames, so force the frame type to GUI
;; there too.
- (when (and (eq system-type 'windows-nt)
- (or (daemonp)
- (eq window-system 'w32)))
+ (when (or (and (eq system-type 'windows-nt)
+ (or (daemonp)
+ (eq window-system 'w32)))
+ ;; Client runs on Windows, but the server
+ ;; runs on a Posix host.
+ (equal tty-name "CONOUT$"))
(push "-window-system" args-left)))
;; -position +LINE[:COLUMN]: Set point to the given
@@ -1329,8 +1333,7 @@ The following commands are accepted by the client:
(let ((expr (pop args-left)))
(if coding-system
(setq expr (decode-coding-string expr coding-system)))
- (push (lambda () (server-eval-and-print expr proc))
- commands)
+ (push expr evalexprs)
(setq filepos nil)))
;; -env NAME=VALUE: An environment variable.
@@ -1355,7 +1358,7 @@ The following commands are accepted by the client:
;; arguments, use an existing frame.
(and nowait
(not (eq tty-name 'window-system))
- (or files commands)
+ (or files commands evalexprs)
(setq use-current-frame t))
(setq frame
@@ -1404,7 +1407,7 @@ The following commands are accepted by the client:
(let ((default-directory
(if (and dir (file-directory-p dir))
dir default-directory)))
- (server-execute proc files nowait commands
+ (server-execute proc files nowait commands evalexprs
dontkill frame tty-name)))))
(when (or frame files)
@@ -1414,22 +1417,35 @@ The following commands are accepted by the client:
;; condition-case
(t (server-return-error proc err))))
-(defun server-execute (proc files nowait commands dontkill frame tty-name)
+(defvar server-eval-args-left nil
+ "List of eval args not yet processed.
+
+Adding or removing strings from this variable while the Emacs
+server is processing a series of eval requests will affect what
+Emacs evaluates.
+
+See also `argv' for a similar variable which works for
+invocations of \"emacs\".")
+
+(defun server-execute (proc files nowait commands evalexprs dontkill frame tty-name)
;; This is run from timers and process-filters, i.e. "asynchronously".
;; But w.r.t the user, this is not really asynchronous since the timer
;; is run after 0s and the process-filter is run in response to the
;; user running `emacsclient'. So it is OK to override the
- ;; inhibit-quit flag, which is good since `commands' (as well as
+ ;; inhibit-quit flag, which is good since `evalexprs' (as well as
;; find-file-noselect via the major-mode) can run arbitrary code,
;; including code that needs to wait.
(with-local-quit
(condition-case err
(let ((buffers (server-visit-files files proc nowait)))
(mapc 'funcall (nreverse commands))
+ (let ((server-eval-args-left (nreverse evalexprs)))
+ (while server-eval-args-left
+ (server-eval-and-print (pop server-eval-args-left) proc)))
;; If we were told only to open a new client, obey
;; `initial-buffer-choice' if it specifies a file
;; or a function.
- (unless (or files commands)
+ (unless (or files commands evalexprs)
(let ((buf
(cond ((stringp initial-buffer-choice)
(find-file-noselect initial-buffer-choice))
diff --git a/lisp/ses.el b/lisp/ses.el
index 30bf33e47bf..fcbb0567901 100644
--- a/lisp/ses.el
+++ b/lisp/ses.el
@@ -1,6 +1,6 @@
;;; ses.el --- Simple Emacs Spreadsheet -*- lexical-binding:t -*-
-;; Copyright (C) 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2024 Free Software Foundation, Inc.
;; Author: Jonathan Yavner <jyavner@member.fsf.org>
;; Maintainer: Vincent Belaïche <vincentb1@users.sourceforge.net>
@@ -69,6 +69,8 @@
(require 'macroexp)
(eval-when-compile (require 'cl-lib))
+;; Autoloaded, but we have not loaded cl-loaddefs yet.
+(declare-function cl-member "cl-seq" (cl-item cl-list &rest cl-keys))
;;----------------------------------------------------------------------------
;; User-customizable variables
@@ -556,13 +558,15 @@ the corresponding cell with name PROPERTY-NAME."
(defun ses-is-cell-sym-p (sym)
"Check whether SYM point at a cell of this spread sheet."
- (let ((rowcol (get sym 'ses-cell)))
- (and rowcol
- (if (eq rowcol :ses-named)
- (and ses--named-cell-hashmap (gethash sym ses--named-cell-hashmap))
- (and (< (car rowcol) ses--numrows)
- (< (cdr rowcol) ses--numcols)
- (eq (ses-cell-symbol (car rowcol) (cdr rowcol)) sym))))))
+ (and (symbolp sym)
+ (local-variable-p sym)
+ (let ((rowcol (get sym 'ses-cell)))
+ (and rowcol
+ (if (eq rowcol :ses-named)
+ (and ses--named-cell-hashmap (gethash sym ses--named-cell-hashmap))
+ (and (< (car rowcol) ses--numrows)
+ (< (cdr rowcol) ses--numcols)
+ (eq (ses-cell-symbol (car rowcol) (cdr rowcol)) sym)))))))
(defun ses--cell (sym value formula printer references)
"Load a cell SYM from the spreadsheet file.
@@ -735,10 +739,8 @@ checking that it is a valid printer function."
(defun ses-formula-record (formula)
"If FORMULA is of the form \\='SYMBOL, add it to the list of symbolic formulas
for this spreadsheet."
- (when (and (eq (car-safe formula) 'quote)
- (symbolp (cadr formula)))
- (add-to-list 'ses--symbolic-formulas
- (list (symbol-name (cadr formula))))))
+ (and (ses-is-cell-sym-p formula)
+ (cl-pushnew (symbol-name formula) ses--symbolic-formulas :test #'string=)))
(defun ses-column-letter (col)
"Return the alphabetic name of column number COL.
@@ -884,33 +886,36 @@ means Emacs will crash if FORMULA contains a circular list."
(newref (ses-formula-references formula))
(inhibit-quit t)
not-a-cell-ref-list
- x xrow xcol)
+ x xref xrow xcol)
(cl-pushnew sym ses--deferred-recalc)
;;Delete old references from this cell. Skip the ones that are also
;;in the new list.
(dolist (ref oldref)
(unless (memq ref newref)
- ;; because we do not cancel edit when the user provides a
+ ;; Because we do not cancel edit when the user provides a
;; false reference in it, then we need to check that ref
;; points to a cell that is within the spreadsheet.
- (setq x (ses-sym-rowcol ref))
- (and x
- (< (setq xrow (car x)) ses--numrows)
- (< (setq xcol (cdr x)) ses--numcols)
- (ses-set-cell xrow xcol 'references
- (delq sym (ses-cell-references xrow xcol))))))
+ (when
+ (and (setq x (ses-sym-rowcol ref))
+ (< (setq xrow (car x)) ses--numrows)
+ (< (setq xcol (cdr x)) ses--numcols))
+ ;; Cell reference has to be re-written to data area as its
+ ;; reference list is changed.
+ (cl-pushnew x ses--deferred-write :test #'equal)
+ (ses-set-cell xrow xcol 'references
+ (delq sym (ses-cell-references xrow xcol))))))
;;Add new ones. Skip ones left over from old list
(dolist (ref newref)
- (setq x (ses-sym-rowcol ref))
;;Do not trust the user, the reference may be outside the spreadsheet
(if (and
- x
+ (setq x (ses-sym-rowcol ref))
(< (setq xrow (car x)) ses--numrows)
(< (setq xcol (cdr x)) ses--numcols))
- (progn
- (setq x (ses-cell-references xrow xcol))
- (or (memq sym x)
- (ses-set-cell xrow xcol 'references (cons sym x))))
+ (unless (memq sym (setq xref (ses-cell-references xrow xcol)))
+ ;; Cell reference has to be re-written to data area as
+ ;; its reference list is changed.
+ (cl-pushnew x ses--deferred-write :test #'equal)
+ (ses-set-cell xrow xcol 'references (cons sym xref)))
(cl-pushnew ref not-a-cell-ref-list)))
(ses-formula-record formula)
(ses-set-cell row col 'formula formula)
@@ -2245,7 +2250,7 @@ Based on the current set of columns and `window-hscroll' position."
;; Redisplay and recalculation
;;----------------------------------------------------------------------------
(defun ses-jump-prefix (prefix-int)
- "Convert an integer (unversal prefix) into a (ROW . COL).
+ "Convert an integer (universal prefix) into a (ROW . COL).
Does it by numbering cells starting from 0 from top left to bottom right,
going row by row."
(and (>= prefix-int 0)
@@ -2762,6 +2767,18 @@ See `ses-read-cell-printer' for input forms."
;;----------------------------------------------------------------------------
;; Spreadsheet size adjustments
;;----------------------------------------------------------------------------
+(defun ses--blank-line-needs-printing-p ()
+ "Returns `t' when blank new line print-out needs to be initialized
+by calling the printers on it, `nil' otherwise."
+ (let (ret
+ printer
+ (printers (append ses--col-printers (list ses--default-printer))))
+ (while printers
+ (if (and (setq printer (pop printers))
+ (null (string= "" (ses-call-printer printer))))
+ (setq ret t
+ printers nil)))
+ ret))
(defun ses-insert-row (count)
"Insert a new row before the current one.
@@ -2794,15 +2811,13 @@ With prefix, insert COUNT rows before current one."
(ses-goto-data row 0)
(insert (make-string (* (1+ ses--numcols) count) ?\n))
(ses-relocate-all row 0 count 0)
- ;;If any cell printers insert constant text, insert that text
- ;;into the line.
- (let ((cols (mapconcat #'ses-call-printer ses--col-printers nil))
- (global (ses-call-printer ses--default-printer)))
- (if (or (> (length cols) 0) (> (length global) 0))
- (dotimes (x count)
- (dotimes (col ses--numcols)
- ;;These cells are always nil, only constant formatting printed
- (1value (ses-print-cell (+ x row) col))))))
+ ;;If any cell printers insert constant text, insert that text into
+ ;;the line.
+ (if (ses--blank-line-needs-printing-p)
+ (dotimes (x count)
+ (dotimes (col ses--numcols)
+ ;;These cells are always nil, only constant formatting printed
+ (1value (ses-print-cell (+ x row) col)))))
(when (> ses--header-row row)
;;Inserting before header
(ses-set-parameter 'ses--header-row (+ ses--header-row count))
@@ -3667,9 +3682,8 @@ highlighted range in the spreadsheet."
"Rename current cell."
(interactive "*SEnter new name: ")
(or
- (and (local-variable-p new-name)
- (ses-is-cell-sym-p new-name)
- (error "Already a cell name"))
+ (and (ses-is-cell-sym-p new-name)
+ (error "Already a cell name"))
(and (boundp new-name)
(null (yes-or-no-p
(format-message
diff --git a/lisp/shadowfile.el b/lisp/shadowfile.el
index 33340a371f1..877b2c8b5ee 100644
--- a/lisp/shadowfile.el
+++ b/lisp/shadowfile.el
@@ -1,6 +1,6 @@
;;; shadowfile.el --- automatic file copying -*- lexical-binding: t; -*-
-;; Copyright (C) 1993-1994, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1993-1994, 2001-2024 Free Software Foundation, Inc.
;; Author: Boris Goldowsky <boris@gnu.org>
;; Keywords: comm files
diff --git a/lisp/shell.el b/lisp/shell.el
index b554ee5add9..c5cfbd985ed 100644
--- a/lisp/shell.el
+++ b/lisp/shell.el
@@ -1,6 +1,6 @@
;;; shell.el --- specialized comint.el for running the shell -*- lexical-binding: t -*-
-;; Copyright (C) 1988, 1993-1997, 2000-2023 Free Software Foundation,
+;; Copyright (C) 1988, 1993-1997, 2000-2024 Free Software Foundation,
;; Inc.
;; Author: Olin Shivers <shivers@cs.cmu.edu>
@@ -327,9 +327,8 @@ and syntax highlighting is set up with `sh-mode'. In addition to
buffer as the current buffer after its setup is done. This can
be used to further customize fontification and other behavior of
the indirect buffer."
- :type 'boolean
+ :type 'hook
:group 'shell
- :safe 'booleanp
:version "29.1")
(defcustom shell-highlight-undef-enable nil
@@ -596,7 +595,8 @@ Shell buffers. It implements `shell-completion-execonly' for
;; shell-dynamic-complete-functions instead.
(setq-local pcomplete-default-completion-function #'ignore)
;; Do not expand remote file names.
- (setq-local pcomplete-remote-file-ignore t)
+ (setq-local pcomplete-remote-file-ignore
+ (not (file-remote-p default-directory)))
(setq-local comint-input-autoexpand shell-input-autoexpand)
;; Not needed in shell-mode because it's inherited from comint-mode, but
;; placed here for read-shell-command.
@@ -1637,15 +1637,15 @@ Returns t if successful."
"Whether to inhibit cache for fontifying shell commands in remote buffers.
When fontification of non-existent commands is enabled in a
remote shell buffer, use a cache to speed up searching for
-executable files on the remote machine. This options is used to
-control expiry of this cache. See `remote-file-name-inhibit-cache'
-for description."
+executable files on the remote machine. This option controls
+expiry of the cache. See `remote-file-name-inhibit-cache' for
+a description of the possible options."
:group 'faces
:type '(choice
- (const :tag "Do not inhibit file name cache" nil)
- (const :tag "Do not use file name cache" t)
- (integer :tag "Do not use file name cache"
- :format "Do not use file name cache older than %v seconds"
+ (const :tag "Do not cache remote executables" t)
+ (const :tag "Cache remote executables" nil)
+ (integer :tag "Cache remote executables with expiration"
+ :format "Cache expiry in seconds: %v"
:value 10))
:version "29.1")
@@ -1658,7 +1658,7 @@ EXECUTABLES is a hash table with keys being the base-names of
executable files.
Cache expiry is controlled by the user option
-`remote-file-name-inhibit-cache'.")
+`shell-highlight-undef-remote-file-name-inhibit-cache'.")
(defvar shell--highlight-undef-face 'shell-highlight-undef-defined-face)
diff --git a/lisp/simple.el b/lisp/simple.el
index 05a3c4b93d6..4f6d2ee12c3 100644
--- a/lisp/simple.el
+++ b/lisp/simple.el
@@ -1,6 +1,6 @@
;;; simple.el --- basic editing commands for Emacs -*- lexical-binding: t -*-
-;; Copyright (C) 1985-1987, 1993-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1985-1987, 1993-2024 Free Software Foundation, Inc.
;; Maintainer: emacs-devel@gnu.org
;; Keywords: internal
@@ -1029,7 +1029,7 @@ that if you use overwrite mode as your normal editing mode, you can use
this function to insert characters when necessary.
In binary overwrite mode, this function does overwrite, and octal
-(or decimal or hex) digits are interpreted as a character code. This
+\(or decimal or hex) digits are interpreted as a character code. This
is intended to be useful for editing binary files."
(interactive "*p")
(let* ((char
@@ -2427,9 +2427,7 @@ BUFFER."
"Say whether MODES are in action in BUFFER.
This is the case if either the major mode is derived from one of MODES,
or (if one of MODES is a minor mode), if it is switched on in BUFFER."
- (or (apply #'provided-mode-derived-p
- (buffer-local-value 'major-mode buffer)
- modes)
+ (or (provided-mode-derived-p (buffer-local-value 'major-mode buffer) modes)
;; It's a minor mode.
(seq-intersection modes
(buffer-local-value 'local-minor-modes buffer)
@@ -2504,7 +2502,7 @@ Equivalent key-bindings are also shown in the completion list of
:group 'keyboard
:type '(choice (const :tag "off" nil)
(natnum :tag "time" 2)
- (other :tag "on")))
+ (other :tag "on" t)))
(defcustom extended-command-suggest-shorter t
"If non-nil, show a shorter \\[execute-extended-command] invocation \
@@ -2989,11 +2987,17 @@ this by calling a function defined by `minibuffer-default-add-function'.")
(defun minibuffer-default-add-completions ()
"Return a list of all completions without the default value.
This function is used to add all elements of the completion table to
-the end of the list of defaults just after the default value."
+the end of the list of defaults just after the default value.
+If you don't want to add initial completions to the default value,
+use either `minibuffer-setup-hook' or `minibuffer-with-setup-hook'
+to set the value of `minibuffer-default-add-function' to nil."
(let ((def minibuffer-default)
- (all (all-completions ""
- minibuffer-completion-table
- minibuffer-completion-predicate)))
+ ;; Avoid some popular completions with undefined order
+ (all (unless (memq minibuffer-completion-table
+ `(help--symbol-completion-table ,obarray))
+ (all-completions ""
+ minibuffer-completion-table
+ minibuffer-completion-predicate))))
(if (listp def)
(append def all)
(cons def (delete def all)))))
@@ -4269,19 +4273,19 @@ This buffer is used when `shell-command' or `shell-command-on-region'
is run interactively. A value of nil means that output to stderr and
stdout will be intermixed in the output stream.")
-(declare-function mailcap-file-default-commands "mailcap" (files))
(declare-function dired-get-filename "dired" (&optional localp no-error-if-not-filep))
+(declare-function shell-command-guess "dired-aux" (files))
(defun minibuffer-default-add-shell-commands ()
"Return a list of all commands associated with the current file.
-This function is used to add all related commands retrieved by `mailcap'
-to the end of the list of defaults just after the default value."
- (interactive)
+This function is used to add all related commands retrieved by
+`shell-command-guess' to the end of the list of defaults just
+after the default value."
(let* ((filename (if (listp minibuffer-default)
(car minibuffer-default)
minibuffer-default))
- (commands (and filename (require 'mailcap nil t)
- (mailcap-file-default-commands (list filename)))))
+ (commands (and filename (require 'dired-aux)
+ (shell-command-guess (list filename)))))
(setq commands (mapcar (lambda (command)
(concat command " " filename))
commands))
@@ -4899,7 +4903,7 @@ appears at the end of the output.
Optional fourth arg OUTPUT-BUFFER specifies where to put the
command's output. If the value is a buffer or buffer name,
erase that buffer and insert the output there; a non-nil value of
-`shell-command-dont-erase-buffer' prevent to erase the buffer.
+`shell-command-dont-erase-buffer' prevents erasing the buffer.
If the value is nil, use the buffer specified by `shell-command-buffer-name'.
Any other non-nil value means to insert the output in the
current buffer after START.
@@ -5094,7 +5098,16 @@ characters."
exit-status))
(defun shell-command-to-string (command)
- "Execute shell command COMMAND and return its output as a string."
+ "Execute shell command COMMAND and return its output as a string.
+Use `shell-quote-argument' to quote dangerous characters in
+COMMAND before passing it as an argument to this function.
+
+Use this function only when a shell interpreter is needed. In
+other cases, consider alternatives such as `call-process' or
+`process-lines', which do not invoke the shell. Consider using
+built-in functions like `rename-file' instead of the external
+command \"mv\". For more information, see Info node
+`(elisp)Security Considerations'."
(with-output-to-string
(with-current-buffer standard-output
(shell-command command t))))
@@ -5146,7 +5159,7 @@ never with `setq'.")
(defcustom process-file-return-signal-string nil
"Whether to return a string describing the signal interrupting a process.
When a process returns an exit code greater than 128, it is
-interpreted as a signal. `process-file' requires to return a
+interpreted as a signal. `process-file' requires returning a
string describing this signal.
Since there are processes violating this rule, returning exit
codes greater than 128 which are not bound to a signal,
@@ -6460,9 +6473,9 @@ If non-nil, the kill ring is rotated after selecting previously killed text."
(defun yank-from-kill-ring (string &optional arg)
"Select a stretch of previously killed text and insert (\"paste\") it.
-This command allows to choose one of the stretches of text killed
-or yanked by previous commands, which are recorded in `kill-ring',
-and reinsert the chosen kill at point.
+This command allows you to select one of the stretches of text
+killed or yanked by previous commands, which are recorded in
+`kill-ring', and reinsert the chosen kill at point.
This command prompts for a previously-killed text in the minibuffer.
Use the minibuffer history and search commands, or the minibuffer
@@ -8263,7 +8276,11 @@ rests."
(let ((newpos
(save-excursion
(let ((goal-column 0)
- (line-move-visual nil))
+ (line-move-visual nil)
+ ;; Always move to eol when invoking `C-e' from
+ ;; within the minibuffer's prompt string (see
+ ;; bug#65980).
+ (inhibit-field-text-motion (minibufferp)))
(and (line-move arg t)
;; With bidi reordering, we may not be at bol,
;; so make sure we are.
@@ -8440,7 +8457,7 @@ even beep.)"
(and (= (cdr (nth 6 (posn-at-point))) orig-vlnum)
;; Make sure we delete the character where the line wraps
;; under visual-line-mode, be it whitespace or a
- ;; character whose category set allows to wrap at it.
+ ;; character whose category set permits wrapping at it.
(or (looking-at-p "[ \t]")
(and word-wrap-by-category
(aref (char-category-set (following-char)) ?\|)))
@@ -8566,12 +8583,12 @@ variables `truncate-lines' and `truncate-partial-width-windows'."
"Interchange characters around point, moving forward one character.
With prefix arg ARG, effect is to take character before point
and drag it forward past ARG other characters (backward if ARG negative).
-If no argument and at end of line, the previous two chars are exchanged."
- (interactive "*P")
- (when (and (null arg) (eolp) (not (bobp))
+If at end of line, the previous two chars are exchanged."
+ (interactive "*p")
+ (when (and (eolp) (not (bobp))
(not (get-text-property (1- (point)) 'read-only)))
(forward-char -1))
- (transpose-subr 'forward-char (prefix-numeric-value arg)))
+ (transpose-subr #'forward-char arg))
(defun transpose-words (arg)
"Interchange words around point, leaving point at end of them.
@@ -8739,7 +8756,7 @@ node `(elisp) Word Motion' for details."
(defun mark-word (&optional arg allow-extend)
"Set mark ARG words from point or move mark one word.
-When called from Lisp with ALLOW-EXTEND ommitted or nil, mark is
+When called from Lisp with ALLOW-EXTEND omitted or nil, mark is
set ARG words from point.
With ARG and ALLOW-EXTEND both non-nil (interactively, with prefix
argument), the place to which mark goes is the same place \\[forward-word]
@@ -9807,6 +9824,8 @@ makes it easier to edit it."
(define-key map "\C-m" 'choose-completion)
(define-key map "\e\e\e" 'delete-completion-window)
(define-key map [remap keyboard-quit] #'delete-completion-window)
+ (define-key map [up] 'previous-line-completion)
+ (define-key map [down] 'next-line-completion)
(define-key map [left] 'previous-completion)
(define-key map [right] 'next-completion)
(define-key map [?\t] 'next-completion)
@@ -9868,8 +9887,9 @@ Go to the window from which completion was requested."
(select-window (get-buffer-window buf))))))
(defcustom completion-auto-wrap t
- "Non-nil means to wrap around when selecting completion options.
-This affects the commands `next-completion' and `previous-completion'.
+ "Non-nil means to wrap around when selecting completion candidates.
+This affects the commands `next-completion', `previous-completion',
+`next-line-completion' and `previous-line-completion'.
When `completion-auto-select' is t, it wraps through the minibuffer
for the commands bound to the TAB key."
:type 'boolean
@@ -9877,12 +9897,12 @@ for the commands bound to the TAB key."
:group 'completion)
(defcustom completion-auto-select nil
- "Non-nil means to automatically select the *Completions* buffer.
+ "If non-nil, automatically select the window showing the *Completions* buffer.
When the value is t, pressing TAB will switch to the completion list
buffer when Emacs pops up a window showing that buffer.
If the value is `second-tab', then the first TAB will pop up the
window showing the completions list buffer, and the next TAB will
-switch to that window.
+select that window.
See `completion-auto-help' for controlling when the window showing
the completions is popped up and down."
:type '(choice (const :tag "Don't auto-select completions window" nil)
@@ -9893,7 +9913,7 @@ the completions is popped up and down."
:group 'completion)
(defun first-completion ()
- "Move to the first item in the completion list."
+ "Move to the first item in the completions buffer."
(interactive)
(goto-char (point-min))
(if (get-text-property (point) 'mouse-face)
@@ -9905,7 +9925,7 @@ the completions is popped up and down."
(goto-char pos))))
(defun last-completion ()
- "Move to the last item in the completion list."
+ "Move to the last item in the completions buffer."
(interactive)
(goto-char (previous-single-property-change
(point-max) 'mouse-face nil (point-min)))
@@ -9915,7 +9935,7 @@ the completions is popped up and down."
(goto-char pos))))
(defun previous-completion (n)
- "Move to the previous item in the completion list.
+ "Move to the previous item in the completions buffer.
With prefix argument N, move back N items (negative N means move
forward).
@@ -9924,7 +9944,7 @@ Also see the `completion-auto-wrap' variable."
(next-completion (- n)))
(defun next-completion (n)
- "Move to the next item in the completion list.
+ "Move to the next item in the completions buffer.
With prefix argument N, move N items (negative N means move
backward).
@@ -9987,6 +10007,98 @@ Also see the `completion-auto-wrap' variable."
(when (/= 0 n)
(switch-to-minibuffer))))
+(defun previous-line-completion (&optional n)
+ "Move to completion candidate on the previous line in the completions buffer.
+With prefix argument N, move back N lines (negative N means move forward).
+
+Also see the `completion-auto-wrap' variable."
+ (interactive "p")
+ (next-line-completion (- n)))
+
+(defun next-line-completion (&optional n)
+ "Move to completion candidate on the next line in the completions buffer.
+With prefix argument N, move N lines forward (negative N means move backward).
+
+Also see the `completion-auto-wrap' variable."
+ (interactive "p")
+ (let (line column pos found)
+ (when (and (bobp)
+ (> n 0)
+ (get-text-property (point) 'mouse-face)
+ (not (get-text-property (point) 'first-completion)))
+ (let ((inhibit-read-only t))
+ (add-text-properties (point) (1+ (point)) '(first-completion t)))
+ (setq n (1- n)))
+
+ (if (get-text-property (point) 'mouse-face)
+ ;; If in a completion, move to the start of it.
+ (when (and (not (bobp))
+ (get-text-property (1- (point)) 'mouse-face))
+ (goto-char (previous-single-property-change (point) 'mouse-face)))
+ ;; Try to move to the previous completion.
+ (setq pos (previous-single-property-change (point) 'mouse-face))
+ (if pos
+ ;; Move to the start of the previous completion.
+ (progn
+ (goto-char pos)
+ (unless (get-text-property (point) 'mouse-face)
+ (goto-char (previous-single-property-change
+ (point) 'mouse-face nil (point-min)))))
+ (cond ((> n 0) (setq n (1- n)) (first-completion))
+ ((< n 0) (first-completion)))))
+
+ (while (> n 0)
+ (setq found nil pos nil column (current-column) line (line-number-at-pos))
+ (while (and (not found)
+ (eq (forward-line 1) 0)
+ (not (eobp))
+ (eq (move-to-column column) column))
+ (when (get-text-property (point) 'mouse-face)
+ (setq found t)))
+ (when (not found)
+ (if (not completion-auto-wrap)
+ (last-completion)
+ (save-excursion
+ (goto-char (point-min))
+ (when (and (eq (move-to-column column) column)
+ (get-text-property (point) 'mouse-face))
+ (setq pos (point)))
+ (while (and (not pos) (> line (line-number-at-pos)))
+ (forward-line 1)
+ (when (and (eq (move-to-column column) column)
+ (get-text-property (point) 'mouse-face))
+ (setq pos (point)))))
+ (if pos (goto-char pos))))
+ (setq n (1- n)))
+
+ (while (< n 0)
+ (setq found nil pos nil column (current-column) line (line-number-at-pos))
+ (while (and (not found)
+ (eq (forward-line -1) 0)
+ (eq (move-to-column column) column))
+ (when (get-text-property (point) 'mouse-face)
+ (setq found t)))
+ (when (not found)
+ (if (not completion-auto-wrap)
+ (first-completion)
+ (save-excursion
+ (goto-char (point-max))
+ (when (and (eq (move-to-column column) column)
+ (get-text-property (point) 'mouse-face))
+ (setq pos (point)))
+ (while (and (not pos) (< line (line-number-at-pos)))
+ (forward-line -1)
+ (when (and (eq (move-to-column column) column)
+ (get-text-property (point) 'mouse-face))
+ (setq pos (point)))))
+ (if pos (goto-char pos))))
+ (setq n (1+ n)))))
+
+(defvar choose-completion-deselect-if-after nil
+ "If non-nil, don't choose a completion candidate if point is right after it.
+
+This makes `completions--deselect' effective.")
+
(defun choose-completion (&optional event no-exit no-quit)
"Choose the completion at point.
If EVENT, use EVENT's position to determine the starting position.
@@ -10007,6 +10119,10 @@ minibuffer, but don't quit the completions window."
(insert-function completion-list-insert-choice-function)
(completion-no-auto-exit (if no-exit t completion-no-auto-exit))
(choice
+ (if choose-completion-deselect-if-after
+ (if-let ((str (get-text-property (posn-point (event-start event)) 'completion--string)))
+ (substring-no-properties str)
+ (error "No completion here"))
(save-excursion
(goto-char (posn-point (event-start event)))
(let (beg)
@@ -10022,7 +10138,7 @@ minibuffer, but don't quit the completions window."
beg 'completion--string)
beg))
(substring-no-properties
- (get-text-property beg 'completion--string))))))
+ (get-text-property beg 'completion--string)))))))
(unless (buffer-live-p buffer)
(error "Destination buffer is dead"))
@@ -10658,10 +10774,10 @@ See also `normal-erase-is-backspace'."
(t
(if enabled
(progn
- (keyboard-translate ?\C-h ?\C-?)
- (keyboard-translate ?\C-? ?\C-d))
- (keyboard-translate ?\C-h ?\C-h)
- (keyboard-translate ?\C-? ?\C-?))))
+ (key-translate "C-h" "DEL")
+ (key-translate "DEL" "C-d"))
+ (key-translate "C-h" "C-h")
+ (key-translate "DEL" "DEL"))))
(if (called-interactively-p 'interactive)
(message "Delete key deletes %s"
@@ -10978,6 +11094,10 @@ If the buffer doesn't exist, create it first."
(pop-to-buffer-same-window (get-scratch-buffer-create)))
(defun kill-buffer--possibly-save (buffer)
+ "Ask the user to confirm killing of a modified BUFFER.
+
+If the user confirms, optionally save BUFFER that is about to be
+killed."
(let ((response
(cadr
(read-multiple-choice
@@ -11058,10 +11178,10 @@ For each insertion:
enabled.
- Look for the deletion of a single electric pair character,
- and delete the adjascent pair if
+ and delete the adjacent pair if
`electric-pair-delete-adjacent-pairs'.
- - Run `post-self-insert-functions' for the last character of
+ - Run `post-self-insert-hook' for the last character of
any inserted text so that modes such as `electric-pair-mode'
can work.
@@ -11074,7 +11194,12 @@ place. If undo information is being recorded, make sure
`undo-auto-current-boundary-timer' will run within the next 5
seconds."
(interactive)
- (let ((any-nonephemeral nil))
+ ;; One important consideration to bear in mind when adjusting this
+ ;; code is to _never_ move point in reaction to an edit so long as
+ ;; the additional processing undertaken by this function does not
+ ;; also edit the buffer text.
+ (let ((any-nonephemeral nil)
+ point-moved)
;; The list must be processed in reverse.
(dolist (edit (reverse text-conversion-edits))
;; Filter out ephemeral edits and deletions after point. Here, we
@@ -11082,6 +11207,9 @@ seconds."
;; can be identified.
(when (stringp (nth 3 edit))
(with-current-buffer (car edit)
+ ;; Record that the point hasn't been moved by the execution
+ ;; of a post command or text conversion hook.
+ (setq point-moved nil)
(if (not (eq (nth 1 edit) (nth 2 edit)))
;; Process this insertion. (nth 3 edit) is the text which
;; was inserted.
@@ -11097,15 +11225,20 @@ seconds."
;; Save the current undo list to figure out
;; whether or not auto-fill has actually taken
;; place.
- (old-undo-list buffer-undo-list))
+ (old-undo-list buffer-undo-list)
+ ;; Save the point position to return it there
+ ;; later.
+ (old-point (point)))
(save-excursion
(if (and auto-fill-function newline-p)
(progn (goto-char (nth 2 edit))
(previous-logical-line)
- (funcall auto-fill-function))
+ (funcall auto-fill-function)
+ (setq old-point (point)))
(when (and auto-fill-function auto-fill-p)
- (progn (goto-char (nth 2 edit))
- (funcall auto-fill-function))))
+ (goto-char (nth 2 edit))
+ (funcall auto-fill-function)
+ (setq old-point (point))))
;; Record whether or not this edit should result in
;; an undo boundary being added.
(setq any-nonephemeral
@@ -11116,10 +11249,22 @@ seconds."
(not (eq old-undo-list
buffer-undo-list)))))
(goto-char (nth 2 edit))
- (let ((last-command-event end))
+ (let ((last-command-event end)
+ (point (point)))
(unless (run-hook-with-args-until-success
'post-text-conversion-hook)
- (run-hooks 'post-self-insert-hook))))
+ (run-hooks 'post-self-insert-hook))
+ (when (not (eq (point) point))
+ (setq point-moved t)))
+ ;; If post-self-insert-hook doesn't move the point,
+ ;; restore it to its previous location. Generally,
+ ;; the call to goto-char upon processing the last edit
+ ;; recorded text-conversion-edit will see to this, but
+ ;; if the input method sets point expressly, no edit
+ ;; will be recorded, and point will wind up away from
+ ;; where the input method believes it is.
+ (unless point-moved
+ (goto-char old-point)))
;; Process this deletion before point. (nth 2 edit) is the
;; text which was deleted. Input methods typically prefer
;; to edit words instead of deleting characters off their
diff --git a/lisp/skeleton.el b/lisp/skeleton.el
index b633490ecca..89cb11b0fe2 100644
--- a/lisp/skeleton.el
+++ b/lisp/skeleton.el
@@ -1,6 +1,6 @@
;;; skeleton.el --- Lisp language extension for writing statement skeletons -*- lexical-binding: t; -*-
-;; Copyright (C) 1993-1996, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1993-1996, 2001-2024 Free Software Foundation, Inc.
;; Author: Daniel Pfeiffer <occitan@esperanto.org>
;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/so-long.el b/lisp/so-long.el
index b93b047ce55..0208f3fddef 100644
--- a/lisp/so-long.el
+++ b/lisp/so-long.el
@@ -1,6 +1,6 @@
;;; so-long.el --- Say farewell to performance problems with minified code. -*- lexical-binding:t -*-
;;
-;; Copyright (C) 2015-2016, 2018-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2016, 2018-2024 Free Software Foundation, Inc.
;; Author: Phil Sainty <psainty@orcon.net.nz>
;; Maintainer: Phil Sainty <psainty@orcon.net.nz>
@@ -310,7 +310,7 @@
;; possibly also `so-long-max-lines' and `so-long-skip-leading-comments' (these
;; latter two are not used by default starting from Emacs 28.1). E.g.:
;;
-;; (add-hook 'js-mode-hook 'my-js-mode-hook)
+;; (add-hook 'js-mode-hook #'my-js-mode-hook)
;;
;; (defun my-js-mode-hook ()
;; "Custom `js-mode' behaviors."
@@ -324,7 +324,7 @@
;; set `bidi-inhibit-bpa' in XML files, on the basis that XML files with long
;; lines are less likely to trigger BPA-related performance problems:
;;
-;; (add-hook 'nxml-mode-hook 'my-nxml-mode-hook)
+;; (add-hook 'nxml-mode-hook #'my-nxml-mode-hook)
;;
;; (defun my-nxml-mode-hook ()
;; "Custom `nxml-mode' behaviors."
@@ -366,7 +366,7 @@
;; variable. Refer to M-: (info "(emacs) Specifying File Variables") RET
;;
;; `so-long-minor-mode' can also be called directly if desired. e.g.:
-;; (add-hook 'FOO-mode-hook 'so-long-minor-mode)
+;; (add-hook 'FOO-mode-hook #'so-long-minor-mode)
;;
;; In Emacs 26.1 or later (see "Caveats" below) you also have the option of
;; using file-local and directory-local variables to determine how `so-long'
@@ -783,8 +783,7 @@ an example."
:package-version '(so-long . "1.0"))
(make-variable-buffer-local 'so-long-file-local-mode-function)
-;; `provided-mode-derived-p' was added in 26.1
-(unless (fboundp 'provided-mode-derived-p)
+(unless (fboundp 'provided-mode-derived-p) ;Only in Emacs≥26.1
(defun provided-mode-derived-p (mode &rest modes)
"Non-nil if MODE is derived from one of MODES.
Uses the `derived-mode-parent' property of the symbol to trace backwards.
@@ -1320,8 +1319,8 @@ This minor mode is a standard `so-long-action' option."
(so-long--ensure-enabled)
(setq so-long--active t
so-long-detected-p t
- so-long-function 'turn-on-so-long-minor-mode
- so-long-revert-function 'turn-off-so-long-minor-mode)
+ so-long-function #'turn-on-so-long-minor-mode
+ so-long-revert-function #'turn-off-so-long-minor-mode)
(so-long-remember-all :reset)
(unless (derived-mode-p 'so-long-mode)
(setq so-long-mode-line-info (so-long-mode-line-info))))
@@ -1345,7 +1344,7 @@ This minor mode is a standard `so-long-action' option."
(defvar so-long-mode-map
(let ((map (make-sparse-keymap)))
- (define-key map (kbd "C-c C-c") 'so-long-revert)
+ (define-key map (kbd "C-c C-c") #'so-long-revert)
;; Define the major mode menu. We have an awkward issue whereby
;; [menu-bar so-long] is already defined in the global map and is
;; :visible so-long-detected-p, but we also want this to be
@@ -1396,12 +1395,12 @@ configure the behavior."
(so-long--ensure-enabled)
(setq so-long--active t
so-long-detected-p t
- so-long-function 'so-long-mode
- so-long-revert-function 'so-long-mode-revert))
+ so-long-function #'so-long-mode
+ so-long-revert-function #'so-long-mode-revert))
;; Use `after-change-major-mode-hook' to disable minor modes and override
;; variables. Append, to act after any globalized modes have acted.
(add-hook 'after-change-major-mode-hook
- 'so-long-after-change-major-mode :append :local)
+ #'so-long-after-change-major-mode :append :local)
;; Override variables. This is the first of two instances where we do this
;; (the other being `so-long-after-change-major-mode'). It is desirable to
;; set variables here in order to cover cases where the setting of a variable
@@ -1591,8 +1590,8 @@ because we do not want to downgrade the major mode in that scenario."
(when (and (symbolp (so-long-function))
(provided-mode-derived-p (so-long-function) 'so-long-mode))
;; Downgrade from `so-long-mode' to the `so-long-minor-mode' behavior.
- (setq so-long-function 'turn-on-so-long-minor-mode
- so-long-revert-function 'turn-off-so-long-minor-mode))))
+ (setq so-long-function #'turn-on-so-long-minor-mode
+ so-long-revert-function #'turn-off-so-long-minor-mode))))
(defun so-long-inhibit (&optional _mode)
"Prevent `global-so-long-mode' from having any effect.
@@ -1717,7 +1716,7 @@ major mode is a member (or derivative of a member) of `so-long-target-modes'.
(not so-long--inhibited)
(not so-long--calling)
(or (eq so-long-target-modes t)
- (apply #'derived-mode-p so-long-target-modes))
+ (derived-mode-p so-long-target-modes))
(setq so-long-detected-p (funcall so-long-predicate))
;; `so-long' should be called; but only if and when the buffer is
;; displayed in a window. Long lines in invisible buffers are generally
@@ -1897,7 +1896,6 @@ Use \\[so-long-commentary] for more information.
Use \\[so-long-customize] to open the customization group `so-long' to
configure the behavior."
:global t
- :group 'so-long
(if global-so-long-mode
;; Enable
(progn
@@ -2030,7 +2028,7 @@ If it appears in `%s', you should remove it."
;; Update to version 1.0 from earlier versions:
(when (version< so-long-version "1.0")
(remove-hook 'change-major-mode-hook 'so-long-change-major-mode)
- (eval-and-compile (require 'advice)) ;; Both macros and functions.
+ (require 'advice) ;; It should already be loaded, but just in case.
(declare-function ad-find-advice "advice")
(declare-function ad-remove-advice "advice")
(declare-function ad-activate "advice")
diff --git a/lisp/sort.el b/lisp/sort.el
index a9686f92d48..2ee76b6e1e3 100644
--- a/lisp/sort.el
+++ b/lisp/sort.el
@@ -1,6 +1,6 @@
;;; sort.el --- commands to sort text in an Emacs buffer -*- lexical-binding: t -*-
-;; Copyright (C) 1986-1987, 1994-1995, 2001-2023 Free Software
+;; Copyright (C) 1986-1987, 1994-1995, 2001-2024 Free Software
;; Foundation, Inc.
;; Author: Howie Kaye
@@ -257,18 +257,15 @@ the sort order."
(lambda () (skip-chars-forward "\n"))
'forward-page))))
-(defvar sort-fields-syntax-table nil)
-(if sort-fields-syntax-table nil
- (let ((table (make-syntax-table))
- (i 0))
- (while (< i 256)
- (modify-syntax-entry i "w" table)
- (setq i (1+ i)))
+(defvar sort-fields-syntax-table
+ (let ((table (make-syntax-table)))
+ (dotimes (i 256)
+ (modify-syntax-entry i "w" table))
(modify-syntax-entry ?\s " " table)
(modify-syntax-entry ?\t " " table)
(modify-syntax-entry ?\n " " table)
(modify-syntax-entry ?\. "_" table) ; for floating pt. numbers. -wsr
- (setq sort-fields-syntax-table table)))
+ table))
(defcustom sort-numeric-base 10
"The default base used by `sort-numeric-fields'."
diff --git a/lisp/soundex.el b/lisp/soundex.el
index 2cffec18d8e..b2988997ee2 100644
--- a/lisp/soundex.el
+++ b/lisp/soundex.el
@@ -1,6 +1,6 @@
;;; soundex.el --- implement Soundex algorithm -*- lexical-binding: t -*-
-;; Copyright (C) 1993, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1993, 2001-2024 Free Software Foundation, Inc.
;; Author: Christian Plaunt <chris@bliss.berkeley.edu>
;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/speedbar.el b/lisp/speedbar.el
index f56c3915521..1cb72dc23e6 100644
--- a/lisp/speedbar.el
+++ b/lisp/speedbar.el
@@ -1,6 +1,6 @@
;;; speedbar.el --- quick access to files and tags in a frame -*- lexical-binding: t; -*-
-;; Copyright (C) 1996-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
;; Keywords: file, tags, tools
@@ -631,7 +631,7 @@ function `speedbar-extension-list-to-regex'.")
(append '(".[ch]\\(\\+\\+\\|pp\\|c\\|h\\|xx\\)?" ".tex\\(i\\(nfo\\)?\\)?"
".el" ".emacs" ".l" ".lsp" ".p" ".java" ".js" ".f\\(90\\|77\\|or\\)?")
(if speedbar-use-imenu-flag
- '(".ad[abs]" ".p[lm]" ".tcl" ".m" ".scm" ".pm" ".py" ".g"
+ '(".ad[abs]" ".p[lm]" ".tcl" ".m" ".scm" ".pm" ".py" ".g" ".lua"
;; html is not supported by default, but an imenu tags package
;; is available. Also, html files are nice to be able to see.
".s?html"
@@ -662,7 +662,7 @@ the dot should NOT be quoted in with \\. Other regular expression
matchers are allowed however. EXTENSION may be a single string or a
list of strings."
(interactive "sExtension: ")
- (if (not (listp extension)) (setq extension (list extension)))
+ (setq extension (ensure-list extension))
(while extension
(if (member (car extension) speedbar-supported-extension-expressions)
nil
@@ -677,8 +677,7 @@ list of strings."
This function will modify `speedbar-ignored-directory-regexp' and add
DIRECTORY-EXPRESSION to `speedbar-ignored-directory-expressions'."
(interactive "sDirectory regex: ")
- (if (not (listp directory-expression))
- (setq directory-expression (list directory-expression)))
+ (setq directory-expression (ensure-list directory-expression))
(while directory-expression
(if (member (car directory-expression) speedbar-ignored-directory-expressions)
nil
diff --git a/lisp/sqlite-mode.el b/lisp/sqlite-mode.el
index 8cb94485369..7b1a9ce2e88 100644
--- a/lisp/sqlite-mode.el
+++ b/lisp/sqlite-mode.el
@@ -1,6 +1,6 @@
;;; sqlite-mode.el --- Mode for examining sqlite3 database files -*- lexical-binding: t; -*-
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -33,6 +33,7 @@
(declare-function sqlite-finalize "sqlite.c")
(declare-function sqlite-select "sqlite.c")
(declare-function sqlite-open "sqlite.c")
+(declare-function sqlite-close "sqlite.c")
(defvar-keymap sqlite-mode-map
"g" #'sqlite-mode-list-tables
@@ -63,6 +64,7 @@
(setq-local sqlite--db (sqlite-open file))
(unless (sqlitep sqlite--db)
(error "`sqlite-open' failed to open SQLite file"))
+ (add-hook 'kill-buffer-hook (lambda () (sqlite-close sqlite--db)) nil t)
(sqlite-mode-list-tables))
(defun sqlite-mode-list-tables ()
@@ -135,22 +137,7 @@
(defun sqlite-mode--column-names (table)
"Return a list of the column names for TABLE."
- (let ((sql
- (caar
- (sqlite-select
- sqlite--db
- "select sql from sqlite_master where tbl_name = ? AND type = 'table'"
- (list table)))))
- (with-temp-buffer
- (insert sql)
- (mapcar #'string-trim
- (split-string
- ;; Extract the args to CREATE TABLE. Point is
- ;; currently at its end.
- (buffer-substring
- (1- (point)) ; right before )
- (1+ (progn (backward-sexp) (point)))) ; right after (
- ",")))))
+ (mapcar (lambda (row) (nth 1 row)) (sqlite-select sqlite--db (format "pragma table_info(%s)" table))))
(defun sqlite-mode-list-data ()
"List the data from the table under point."
diff --git a/lisp/sqlite.el b/lisp/sqlite.el
index aad0aa40fa4..46e35ac18d8 100644
--- a/lisp/sqlite.el
+++ b/lisp/sqlite.el
@@ -1,6 +1,6 @@
;;; sqlite.el --- Functions for interacting with sqlite3 databases -*- lexical-binding: t; -*-
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -23,20 +23,33 @@
;;; Code:
+(declare-function sqlite-transaction "sqlite.c")
+(declare-function sqlite-commit "sqlite.c")
+(declare-function sqlite-rollback "sqlite.c")
+
(defmacro with-sqlite-transaction (db &rest body)
- "Execute BODY while holding a transaction for DB."
+ "Execute BODY while holding a transaction for DB.
+If BODY completes normally, commit the changes and return
+the value of BODY.
+If BODY signals an error, or transaction commit fails, roll
+back the transaction changes."
(declare (indent 1) (debug (form body)))
(let ((db-var (gensym))
- (func-var (gensym)))
+ (func-var (gensym))
+ (res-var (gensym))
+ (commit-var (gensym)))
`(let ((,db-var ,db)
- (,func-var (lambda () ,@body)))
+ (,func-var (lambda () ,@body))
+ ,res-var ,commit-var)
(if (sqlite-available-p)
(unwind-protect
(progn
(sqlite-transaction ,db-var)
- (funcall ,func-var))
- (sqlite-commit ,db-var))
- (funcall ,func-var)))))
+ (setq ,res-var (funcall ,func-var))
+ (setq ,commit-var (sqlite-commit ,db-var))
+ ,res-var)
+ (or ,commit-var (sqlite-rollback ,db-var))))
+ (funcall ,func-var))))
(provide 'sqlite)
diff --git a/lisp/startup.el b/lisp/startup.el
index b46341a7bdd..b0669af7e24 100644
--- a/lisp/startup.el
+++ b/lisp/startup.el
@@ -1,6 +1,6 @@
;;; startup.el --- process Emacs shell arguments -*- lexical-binding: t -*-
-;; Copyright (C) 1985-1986, 1992, 1994-2023 Free Software Foundation,
+;; Copyright (C) 1985-1986, 1992, 1994-2024 Free Software Foundation,
;; Inc.
;; Maintainer: emacs-devel@gnu.org
@@ -120,7 +120,10 @@ the remaining command-line args are in the variable `command-line-args-left'.")
"List of command-line args not yet processed.
This is a convenience alias, so that one can write (pop argv)
inside of --eval command line arguments in order to access
-following arguments."))
+following arguments.
+
+See also `server-eval-args-left' for a similar variable which
+works for invocations of \"emacsclient --eval\"."))
(internal-make-var-non-special 'argv)
(defvar command-line-args-left nil
@@ -638,7 +641,24 @@ It is the default value of the variable `top-level'."
(setq eol-mnemonic-dos "(DOS)"
eol-mnemonic-mac "(Mac)")))
- (set-locale-environment nil)
+ (if (and (featurep 'android)
+ (eq system-type 'android)
+ (fboundp 'android-locale-for-system-language)
+ initial-window-system)
+ ;; If Android windowing is enabled, derive a proper locale
+ ;; from the system's language preferences. On Android, LANG
+ ;; and LC_* must be set to one of the two locales the C
+ ;; library supports, but, by contrast with other systems, the
+ ;; C library locale does not reflect the configured system
+ ;; language.
+ ;;
+ ;; For this reason, the locale from which Emacs derives a
+ ;; default language environment is computed from such
+ ;; preferences, rather than environment variables that the C
+ ;; library refers to.
+ (set-locale-environment
+ (funcall 'android-locale-for-system-language))
+ (set-locale-environment nil))
;; Decode all default-directory's (probably, only *scratch* exists
;; at this point). default-directory of *scratch* is the basis
;; for many other file-name variables and directory lists, so it
@@ -1687,7 +1707,7 @@ Changed settings will be marked as \"CHANGED outside of Customize\"."
(defcustom initial-scratch-message (purecopy "\
;; This buffer is for text that is not saved, and for Lisp evaluation.
-;; To create a file, visit it with \\[find-file] and enter text in its buffer.
+;; To create a file, visit it with `\\[find-file]' and enter text in its buffer.
")
"Initial documentation displayed in *scratch* buffer at startup.
@@ -2038,7 +2058,10 @@ a face or button specification."
(call-interactively
'recover-session)))
" to recover the files you were editing."))))
-
+ ;; Insert the permissions notice if the user has yet to grant Emacs
+ ;; storage permissions.
+ (when (fboundp 'android-after-splash-screen)
+ (funcall 'android-after-splash-screen t))
(when concise
(fancy-splash-insert
:face 'variable-pitch "\n"
@@ -2240,6 +2263,11 @@ splash screen in another window."
"type M-x recover-session RET\nto recover"
" the files you were editing.\n"))
+ ;; Insert the permissions notice if the user has yet to grant
+ ;; Emacs storage permissions.
+ (when (fboundp 'android-after-splash-screen)
+ (funcall 'android-after-splash-screen nil))
+
(use-local-map splash-screen-keymap)
;; Display the input that we set up in the buffer.
diff --git a/lisp/strokes.el b/lisp/strokes.el
index 293bdf0f369..50920229d9d 100644
--- a/lisp/strokes.el
+++ b/lisp/strokes.el
@@ -1,6 +1,6 @@
;;; strokes.el --- control Emacs through mouse strokes -*- lexical-binding: t; -*-
-;; Copyright (C) 1997, 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997, 2000-2024 Free Software Foundation, Inc.
;; Author: David Bakhash <cadet@alum.mit.edu>
;; Maintainer: emacs-devel@gnu.org
@@ -266,6 +266,14 @@ able to see the strokes. This be helpful for people who don't like
the delay in switching to the strokes buffer."
:type 'boolean)
+(defvar strokes-no-match-function 'strokes-no-match-default
+ "Function run by `strokes-execute-stroke' when no stroke matches.
+The function is called with two arguments, the stroke and the
+closest match returned by `strokes-match-stroke'. It can be used
+to show detailed information about the unmatched stroke or
+perform some fallback action. The default function
+`strokes-no-match-default' simply signals an error.")
+
;;; internal variables...
(defvar strokes-window-configuration nil
@@ -838,14 +846,16 @@ Optional EVENT is acceptable as the starting event of the stroke."
(goto-char (point-min))
(bury-buffer)))))))
+(defun strokes-no-match-default (&rest _)
+ "Signal an error when no stroke matches."
+ (error
+ "No stroke matches; see variable `strokes-minimum-match-score'"))
+
(defun strokes-execute-stroke (stroke)
"Given STROKE, execute the command which corresponds to it.
The command will be executed provided one exists for that stroke,
-based on the variable `strokes-minimum-match-score'.
-If no stroke matches, nothing is done and return value is nil."
- ;; FIXME: Undocument return value. It is not documented for all cases,
- ;; and doesn't allow differentiating between no stroke matches and
- ;; command-execute returning nil, anyway.
+based on the variable `strokes-minimum-match-score'. If no
+stroke matches, `strokes-no-match-function' is called."
(let* ((match (strokes-match-stroke stroke strokes-global-map))
(command (car match))
(score (cdr match)))
@@ -859,10 +869,7 @@ If no stroke matches, nothing is done and return value is nil."
strokes-file))
(strokes-load-user-strokes))
(error "No strokes defined; use `strokes-global-set-stroke'")))
- (t
- (error
- "No stroke matches; see variable `strokes-minimum-match-score'")
- nil))))
+ (t (funcall strokes-no-match-function stroke match)))))
;;;###autoload
(defun strokes-do-stroke (event)
@@ -1211,12 +1218,7 @@ the stroke as a character in some language."
;;\\{edit-strokes-mode-map}"
;; (setq truncate-lines nil
;; auto-show-mode nil ; don't want problems here either
-;; mode-popup-menu edit-strokes-menu) ; what about extent-specific stuff?
-;; (and (featurep 'menubar)
-;; current-menubar
-;; (setq-local current-menubar
-;; (copy-sequence current-menubar))
-;; (add-submenu nil edit-strokes-menu)))
+;; mode-popup-menu edit-strokes-menu)) ; what about extent-specific stuff?
;;(let ((map edit-strokes-mode-map))
;; (define-key map "<" 'beginning-of-buffer)
diff --git a/lisp/subr.el b/lisp/subr.el
index 47fcbc2f317..d2b8ea17f74 100644
--- a/lisp/subr.el
+++ b/lisp/subr.el
@@ -1,6 +1,6 @@
;;; subr.el --- basic lisp subroutines for Emacs -*- lexical-binding:t -*-
-;; Copyright (C) 1985-1986, 1992, 1994-1995, 1999-2023 Free Software
+;; Copyright (C) 1985-1986, 1992, 1994-1995, 1999-2024 Free Software
;; Foundation, Inc.
;; Maintainer: emacs-devel@gnu.org
@@ -277,6 +277,21 @@ change the list."
(macroexp-let2 macroexp-copyable-p x getter
`(prog1 ,x ,(funcall setter `(cdr ,x))))))))
+;; Note: `static-if' can be copied into a package to enable it to be
+;; used in Emacsen older than Emacs 30.1. If the package is used in
+;; very old Emacsen or XEmacs (in which `eval' takes exactly one
+;; argument) the copy will need amending.
+(defmacro static-if (condition then-form &rest else-forms)
+ "A conditional compilation macro.
+Evaluate CONDITION at macro-expansion time. If it is non-nil,
+expand the macro to THEN-FORM. Otherwise expand it to ELSE-FORMS
+enclosed in a `progn' form. ELSE-FORMS may be empty."
+ (declare (indent 2)
+ (debug (sexp sexp &rest sexp)))
+ (if (eval condition lexical-binding)
+ then-form
+ (cons 'progn else-forms)))
+
(defmacro when (cond &rest body)
"If COND yields non-nil, do BODY, else return nil.
When COND yields non-nil, eval BODY forms sequentially and return
@@ -445,6 +460,10 @@ Also see `ignore'."
Errors cause entry to the debugger when `debug-on-error' is non-nil.
This can be overridden by `debug-ignored-errors'.
+When `noninteractive' is non-nil (in particular, in batch mode), an
+unhandled error calls `kill-emacs', which terminates the Emacs
+session with a non-zero exit code.
+
To signal with MESSAGE without interpreting format characters
like `%', `\\=`' and `\\='', use (error \"%s\" MESSAGE).
In Emacs, the convention is that error messages start with a capital
@@ -539,8 +558,10 @@ If COUNT is negative, shifting is actually to the right.
In this case, if VALUE is a negative fixnum treat it as unsigned,
i.e., subtract 2 * `most-negative-fixnum' from VALUE before shifting it.
-This function is provided for compatibility. In new code, use `ash'
-instead."
+Most uses of this function turn out to be mistakes. We recommend
+to use `ash' instead, unless COUNT could ever be negative, and
+if, when COUNT is negative, your program really needs the special
+treatment of negative COUNT provided by this function."
(declare (compiler-macro
(lambda (form)
(macroexp-warn-and-return
@@ -978,11 +999,11 @@ SEQ must be a list, vector, or string. The comparison is done with `equal'.
Contrary to `delete', this does not use side-effects, and the argument
SEQ is not modified."
(declare (side-effect-free t))
- (if (nlistp seq)
- ;; If SEQ isn't a list, there's no need to copy SEQ because
- ;; `delete' will return a new object.
- (delete elt seq)
- (delete elt (copy-sequence seq))))
+ (delete elt (if (nlistp seq)
+ ;; If SEQ isn't a list, there's no need to copy SEQ because
+ ;; `delete' will return a new object.
+ seq
+ (copy-sequence seq))))
(defun remq (elt list)
"Return LIST with all occurrences of ELT removed.
@@ -1942,6 +1963,7 @@ be a list of the form returned by `event-start' and `event-end'."
(set-advertised-calling-convention 'redirect-frame-focus '(frame focus-frame) "24.3")
(set-advertised-calling-convention 'libxml-parse-xml-region '(&optional start end base-url) "27.1")
(set-advertised-calling-convention 'libxml-parse-html-region '(&optional start end base-url) "27.1")
+(set-advertised-calling-convention 'sleep-for '(seconds) "30.1")
(set-advertised-calling-convention 'time-convert '(time form) "29.1")
;;;; Obsolescence declarations for variables, and aliases.
@@ -2021,6 +2043,7 @@ instead; it will indirectly limit the specpdl stack size as well.")
(defalias 'store-match-data #'set-match-data)
(defalias 'chmod #'set-file-modes)
(defalias 'mkdir #'make-directory)
+(defalias 'wholenump #'natnump)
;; These were the XEmacs names, now obsolete:
(defalias 'point-at-eol #'line-end-position)
@@ -2659,28 +2682,154 @@ The variable list SPEC is the same as in `if-let*'."
;; PUBLIC: find if the current mode derives from another.
-(defun provided-mode-derived-p (mode &rest modes)
- "Non-nil if MODE is derived from one of MODES.
-Uses the `derived-mode-parent' property of the symbol to trace backwards.
-If you just want to check `major-mode', use `derived-mode-p'."
- ;; If MODE is an alias, then look up the real mode function first.
- (declare (side-effect-free t))
- (when-let ((alias (symbol-function mode)))
- (when (symbolp alias)
- (setq mode alias)))
- (while
- (and
- (not (memq mode modes))
- (let* ((parent (get mode 'derived-mode-parent))
- (parentfn (symbol-function parent)))
- (setq mode (if (and parentfn (symbolp parentfn)) parentfn parent)))))
- mode)
-
-(defun derived-mode-p (&rest modes)
- "Non-nil if the current major mode is derived from one of MODES.
-Uses the `derived-mode-parent' property of the symbol to trace backwards."
- (declare (side-effect-free t))
- (apply #'provided-mode-derived-p major-mode modes))
+(defun merge-ordered-lists (lists &optional error-function)
+ "Merge LISTS in a consistent order.
+LISTS is a list of lists of elements.
+Merge them into a single list containing the same elements (removing
+duplicates), obeying their relative positions in each list.
+The order of the (sub)lists determines the final order in those cases where
+the order within the sublists does not impose a unique choice.
+Equality of elements is tested with `eql'.
+
+If a consistent order does not exist, call ERROR-FUNCTION with
+a remaining list of lists that we do not know how to merge.
+It should return the candidate to use to continue the merge, which
+has to be the head of one of the lists.
+By default we choose the head of the first list."
+ ;; Algorithm inspired from
+ ;; [C3](https://en.wikipedia.org/wiki/C3_linearization)
+ (let ((result '()))
+ (setq lists (remq nil lists)) ;Don't mutate the original `lists' argument.
+ (while (cdr (setq lists (delq nil lists)))
+ ;; Try to find the next element of the result. This
+ ;; is achieved by considering the first element of each
+ ;; (non-empty) input list and accepting a candidate if it is
+ ;; consistent with the rests of the input lists.
+ (let* ((next nil)
+ (tail lists))
+ (while tail
+ (let ((candidate (caar tail))
+ (other-lists lists))
+ ;; Ensure CANDIDATE is not in any position but the first
+ ;; in any of the element lists of LISTS.
+ (while other-lists
+ (if (not (memql candidate (cdr (car other-lists))))
+ (setq other-lists (cdr other-lists))
+ (setq candidate nil)
+ (setq other-lists nil)))
+ (if (not candidate)
+ (setq tail (cdr tail))
+ (setq next candidate)
+ (setq tail nil))))
+ (unless next ;; The graph is inconsistent.
+ (setq next (funcall (or error-function #'caar) lists))
+ (unless (assoc next lists #'eql)
+ (error "Invalid candidate returned by error-function: %S" next)))
+ ;; The graph is consistent so far, add NEXT to result and
+ ;; merge input lists, dropping NEXT from their heads where
+ ;; applicable.
+ (push next result)
+ (setq lists
+ (mapcar (lambda (l) (if (eql (car l) next) (cdr l) l))
+ lists))))
+ (if (null result) (car lists) ;; Common case.
+ (append (nreverse result) (car lists)))))
+
+(defun derived-mode-all-parents (mode &optional known-children)
+ "Return all the parents of MODE, starting with MODE.
+The returned list is not fresh, don't modify it.
+\n(fn MODE)" ;`known-children' is for internal use only.
+ ;; Can't use `with-memoization' :-(
+ (let ((ps (get mode 'derived-mode--all-parents)))
+ (cond
+ (ps ps)
+ ((memq mode known-children)
+ ;; These things happen, better not get all worked up about it.
+ ;;(error "Cycle in the major mode hierarchy: %S" mode)
+ ;; But do try to return something meaningful.
+ (memq mode (reverse known-children)))
+ (t
+ ;; The mode hierarchy (or DAG, actually), is very static, but we
+ ;; need to react to changes because `parent' may not be defined
+ ;; yet (e.g. it's still just an autoload), so the recursive call
+ ;; to `derived-mode-all-parents' may return an
+ ;; invalid/incomplete result which we'll need to update when the
+ ;; mode actually gets loaded.
+ (let* ((new-children (cons mode known-children))
+ (get-all-parents
+ (lambda (parent)
+ ;; Can't use `cl-lib' here (nor `gv') :-(
+ ;;(cl-assert (not (equal parent mode)))
+ ;;(cl-pushnew mode (get parent 'derived-mode--followers))
+ (let ((followers (get parent 'derived-mode--followers)))
+ (unless (memq mode followers)
+ (put parent 'derived-mode--followers
+ (cons mode followers))))
+ (derived-mode-all-parents parent new-children)))
+ (parent (or (get mode 'derived-mode-parent)
+ ;; If MODE is an alias, then follow the alias.
+ (let ((alias (symbol-function mode)))
+ (and (symbolp alias) alias))))
+ (extras (get mode 'derived-mode-extra-parents))
+ (all-parents
+ (merge-ordered-lists
+ (cons (if (and parent (not (memq parent extras)))
+ (funcall get-all-parents parent))
+ (mapcar get-all-parents extras)))))
+ ;; Cache the result unless it was affected by `known-children'
+ ;; because of a cycle.
+ (if (and (memq mode all-parents) known-children)
+ (cons mode (remq mode all-parents))
+ (put mode 'derived-mode--all-parents (cons mode all-parents))))))))
+
+(defun provided-mode-derived-p (mode &optional modes &rest old-modes)
+ "Non-nil if MODE is derived from a mode that is a member of the list MODES.
+MODES can also be a single mode instead of a list.
+If you just want to check `major-mode', use `derived-mode-p'.
+We also still support the deprecated calling convention:
+\(provided-mode-derived-p MODE &rest MODES)."
+ (declare (side-effect-free t)
+ (advertised-calling-convention (mode modes) "30.1"))
+ (cond
+ (old-modes (setq modes (cons modes old-modes)))
+ ((not (listp modes)) (setq modes (list modes))))
+ (let ((ps (derived-mode-all-parents mode)))
+ (while (and modes (not (memq (car modes) ps)))
+ (setq modes (cdr modes)))
+ (car modes)))
+
+(defun derived-mode-p (&optional modes &rest old-modes)
+ "Non-nil if the current major mode is derived from one of MODES.
+MODES should be a list of symbols or a single mode symbol instead of a list.
+We also still support the deprecated calling convention:
+\(derived-mode-p &rest MODES)."
+ (declare (side-effect-free t)
+ ;; FIXME: It's cumbersome for external packages to write code which
+ ;; accommodates both the old and the new calling conventions *and*
+ ;; doesn't cause spurious warnings. So let's be more lenient
+ ;; for now and maybe remove `deprecated-args' for Emacs-31.
+ (advertised-calling-convention (modes &rest deprecated-args) "30.1"))
+ (provided-mode-derived-p major-mode (if old-modes (cons modes old-modes)
+ modes)))
+
+(defun derived-mode-set-parent (mode parent)
+ "Declare PARENT to be the parent of MODE."
+ (put mode 'derived-mode-parent parent)
+ (derived-mode--flush mode))
+
+(defun derived-mode-add-parents (mode extra-parents)
+ "Add EXTRA-PARENTS to the parents of MODE.
+Declares the parents of MODE to be its main parent (as defined
+in `define-derived-mode') plus EXTRA-PARENTS."
+ (put mode 'derived-mode-extra-parents extra-parents)
+ (derived-mode--flush mode))
+
+(defun derived-mode--flush (mode)
+ (put mode 'derived-mode--all-parents nil)
+ (let ((followers (get mode 'derived-mode--followers)))
+ (when followers ;; Common case.
+ (put mode 'derived-mode--followers nil)
+ (mapc #'derived-mode--flush followers))))
(defvar-local major-mode--suspended nil)
(put 'major-mode--suspended 'permanent-local t)
@@ -3187,22 +3336,30 @@ only unbound fallback disabled is downcasing of the last event."
(message nil)
(use-global-map old-global-map))))
+(defvar touch-screen-events-received nil
+ "Whether a touch screen event has ever been translated.
+The value of this variable governs whether
+`read--potential-mouse-event' calls read-key or read-event.")
+
;; FIXME: Once there's a safe way to transition away from read-event,
;; callers to this function should be updated to that way and this
;; function should be deleted.
(defun read--potential-mouse-event ()
- "Read an event that might be a mouse event.
+ "Read an event that might be a mouse event.
This function exists for backward compatibility in code packaged
with Emacs. Do not call it directly in your own packages."
- ;; `xterm-mouse-mode' events must go through `read-key' as they
- ;; are decoded via `input-decode-map'.
- (if xterm-mouse-mode
- (read-key nil
- ;; Normally `read-key' discards all mouse button
- ;; down events. However, we want them here.
- t)
- (read-event)))
+ ;; `xterm-mouse-mode' events must go through `read-key' as they
+ ;; are decoded via `input-decode-map'.
+ (if (or xterm-mouse-mode
+ ;; If a touch screen is being employed, then mouse events
+ ;; are subject to translation as well.
+ touch-screen-events-received)
+ (read-key nil
+ ;; Normally `read-key' discards all mouse button
+ ;; down events. However, we want them here.
+ t)
+ (read-event)))
(defvar read-passwd-map
;; BEWARE: `defconst' would purecopy it, breaking the sharing with
@@ -3390,7 +3547,7 @@ causes it to evaluate `help-form' and display the result."
(message "%s%s" prompt (char-to-string char))
char))
-(defun sit-for (seconds &optional nodisp obsolete)
+(defun sit-for (seconds &optional nodisp)
"Redisplay, then wait for SECONDS seconds. Stop when input is available.
SECONDS may be a floating-point value.
\(On operating systems that do not support waiting for fractions of a
@@ -3399,29 +3556,11 @@ second, floating-point values are rounded down to the nearest integer.)
If optional arg NODISP is t, don't redisplay, just wait for input.
Redisplay does not happen if input is available before it starts.
-Value is t if waited the full time with no input arriving, and nil otherwise.
-
-An obsolete, but still supported form is
-\(sit-for SECONDS &optional MILLISECONDS NODISP)
-where the optional arg MILLISECONDS specifies an additional wait period,
-in milliseconds; this was useful when Emacs was built without
-floating point support."
- (declare (advertised-calling-convention (seconds &optional nodisp) "22.1")
- (compiler-macro
- (lambda (form)
- (if (not (or (numberp nodisp) obsolete)) form
- (macroexp-warn-and-return
- (format-message "Obsolete calling convention for `sit-for'")
- `(,(car form) (+ ,seconds (/ (or ,nodisp 0) 1000.0)) ,obsolete)
- '(obsolete sit-for))))))
+Value is t if waited the full time with no input arriving, and nil otherwise."
;; This used to be implemented in C until the following discussion:
;; https://lists.gnu.org/r/emacs-devel/2006-07/msg00401.html
;; Then it was moved here using an implementation based on an idle timer,
;; which was then replaced by the use of read-event.
- (if (numberp nodisp)
- (setq seconds (+ seconds (* 1e-3 nodisp))
- nodisp obsolete)
- (if obsolete (setq nodisp obsolete)))
(cond
(noninteractive
(sleep-for seconds)
@@ -3483,7 +3622,7 @@ If there is a natural number at point, use it as default."
(let ((map (make-sparse-keymap)))
(set-keymap-parent map minibuffer-local-map)
- (define-key map [remap self-insert-command] #'read-char-from-minibuffer-insert-char)
+ ;; (define-key map [remap self-insert-command] #'read-char-from-minibuffer-insert-char)
(define-key map [remap exit-minibuffer] #'read-char-from-minibuffer-insert-other)
(define-key map [remap recenter-top-bottom] #'minibuffer-recenter-top-bottom)
@@ -3514,7 +3653,7 @@ allowed to type into the minibuffer. When the user types any
such key, this command discard all minibuffer input and displays
an error message."
(interactive)
- (when (minibufferp)
+ (when (minibufferp) ;;FIXME: Why?
(delete-minibuffer-contents)
(ding)
(discard-input)
@@ -3562,6 +3701,10 @@ There is no need to explicitly add `help-char' to CHARS;
(interactive)
(let ((help-form msg)) ; lexically bound msg
(help-form-show)))))
+ ;; FIXME: We use `read-char-from-minibuffer-insert-char'
+ ;; here only as a kind of alias of `self-insert-command'
+ ;; to prevent those keys from being remapped to
+ ;; `read-char-from-minibuffer-insert-other'.
(dolist (char chars)
(define-key map (vector char)
#'read-char-from-minibuffer-insert-char))
@@ -3573,7 +3716,15 @@ There is no need to explicitly add `help-char' to CHARS;
read-char-from-minibuffer-map))
;; Protect this-command when called from pre-command-hook (bug#45029)
(this-command this-command)
- (result (progn
+ (result (minibuffer-with-setup-hook
+ (lambda ()
+ (add-hook 'post-command-hook
+ (lambda ()
+ ;; FIXME: Should we use `<='?
+ (if (= (1+ (minibuffer-prompt-end))
+ (point-max))
+ (exit-minibuffer)))
+ nil 'local))
;; Disable text conversion if it is enabled.
;; (bug#65370)
(when (fboundp 'set-text-conversion-style)
@@ -5669,9 +5820,11 @@ See also `string-equal'."
(eq t (compare-strings string1 0 nil string2 0 nil t)))
(defun string-prefix-p (prefix string &optional ignore-case)
- "Return non-nil if PREFIX is a prefix of STRING.
+ "Return non-nil if STRING begins with PREFIX.
+PREFIX should be a string; the function returns non-nil if the
+characters at the beginning of STRING compare equal with PREFIX.
If IGNORE-CASE is non-nil, the comparison is done without paying attention
-to case differences."
+to letter-case differences."
(declare (side-effect-free t))
(let ((prefix-length (length prefix)))
(if (> prefix-length (length string)) nil
@@ -5679,9 +5832,11 @@ to case differences."
0 prefix-length ignore-case)))))
(defun string-suffix-p (suffix string &optional ignore-case)
- "Return non-nil if SUFFIX is a suffix of STRING.
+ "Return non-nil if STRING ends with SUFFIX.
+SUFFIX should be a string; the function returns non-nil if the
+characters at end of STRING compare equal with SUFFIX.
If IGNORE-CASE is non-nil, the comparison is done without paying
-attention to case differences."
+attention to letter-case differences."
(declare (side-effect-free t))
(let ((start-pos (- (length string) (length suffix))))
(and (>= start-pos 0)
@@ -5738,8 +5893,8 @@ Return nil if there isn't one."
(load-elt (and loads (car loads))))
(save-match-data
(while (and loads
- (or (null (car load-elt))
- (not (string-match file-regexp (car load-elt)))))
+ (not (and (car load-elt)
+ (string-match file-regexp (car load-elt)))))
(setq loads (cdr loads)
load-elt (and loads (car loads)))))
load-elt))
@@ -6023,7 +6178,7 @@ by `find-word-boundary-function-table'. It is also not interactive."
With argument ARG, do this that many times.
If ARG is omitted or nil, move point backward one word.
-This function is like `forward-word', but it is not affected
+This function is like `backward-word', but it is not affected
by `find-word-boundary-function-table'. It is also not interactive."
(let ((find-word-boundary-function-table
(if (char-table-p word-move-empty-char-table)
@@ -6229,13 +6384,14 @@ If non-nil, BASE should be a function, and frames before its
nearest activation frame are discarded."
(let ((frames nil))
(mapbacktrace (lambda (&rest frame) (push frame frames))
- (or base 'backtrace-frames))
+ (or base #'backtrace-frames))
(nreverse frames)))
(defun backtrace-frame (nframes &optional base)
"Return the function and arguments NFRAMES up from current execution point.
If non-nil, BASE should be a function, and NFRAMES counts from its
-nearest activation frame.
+nearest activation frame. BASE can also be of the form (OFFSET . FUNCTION)
+in which case OFFSET will be added to NFRAMES.
If the frame has not evaluated the arguments yet (or is a special form),
the value is (nil FUNCTION ARG-FORMS...).
If the frame has evaluated its arguments and called its function already,
@@ -6246,7 +6402,7 @@ or a lambda expression for macro calls.
If NFRAMES is more than the number of frames, the value is nil."
(backtrace-frame--internal
(lambda (evald func args _) `(,evald ,func ,@args))
- nframes (or base 'backtrace-frame)))
+ nframes (or base #'backtrace-frame)))
(defvar called-interactively-p-functions nil
@@ -6312,7 +6468,7 @@ command is called from a keyboard macro?"
;; Skip special forms (from non-compiled code).
(and frame (null (car frame)))
;; Skip also `interactive-p' (because we don't want to know if
- ;; interactive-p was called interactively but if it's caller was).
+ ;; interactive-p was called interactively but if its caller was).
(eq (nth 1 frame) 'interactive-p)
;; Skip package-specific stack-frames.
(let ((skip (run-hook-with-args-until-success
@@ -6557,7 +6713,6 @@ effectively rounded up."
(unless min-time
(setq min-time 0.2))
(let ((reporter
- ;; Force a call to `message' now
(cons (or min-value 0)
(vector (if (>= min-time 0.02)
(float-time) nil)
@@ -6568,6 +6723,7 @@ effectively rounded up."
min-time
;; SUFFIX
nil))))
+ ;; Force a call to `message' now.
(progress-reporter-update reporter (or current-value min-value))
reporter))
@@ -7261,13 +7417,15 @@ lines."
(setq start (length string)))))
(nreverse lines))))
-(defun buffer-match-p (condition buffer-or-name &optional arg)
+(defvar buffer-match-p--past-warnings nil)
+
+(defun buffer-match-p (condition buffer-or-name &rest args)
"Return non-nil if BUFFER-OR-NAME matches CONDITION.
CONDITION is either:
- the symbol t, to always match,
- the symbol nil, which never matches,
- a regular expression, to match a buffer name,
-- a predicate function that takes BUFFER-OR-NAME and ARG as
+- a predicate function that takes BUFFER-OR-NAME plus ARGS as
arguments, and returns non-nil if the buffer matches,
- a cons-cell, where the car describes how to interpret the cdr.
The car can be one of the following:
@@ -7292,9 +7450,18 @@ CONDITION is either:
((pred stringp)
(string-match-p condition (buffer-name buffer)))
((pred functionp)
- (if (eq 1 (cdr (func-arity condition)))
- (funcall condition buffer-or-name)
- (funcall condition buffer-or-name arg)))
+ (if (cdr args)
+ ;; New in Emacs>29.1. no need for compatibility hack.
+ (apply condition buffer-or-name args)
+ (condition-case-unless-debug err
+ (apply condition buffer-or-name args)
+ (wrong-number-of-arguments
+ (unless (member condition
+ buffer-match-p--past-warnings)
+ (message "%s" (error-message-string err))
+ (push condition buffer-match-p--past-warnings))
+ (apply condition buffer-or-name
+ (if args nil '(nil)))))))
(`(major-mode . ,mode)
(eq
(buffer-local-value 'major-mode buffer)
@@ -7316,17 +7483,17 @@ CONDITION is either:
(throw 'match t)))))))
(funcall match (list condition))))
-(defun match-buffers (condition &optional buffers arg)
+(defun match-buffers (condition &optional buffers &rest args)
"Return a list of buffers that match CONDITION, or nil if none match.
See `buffer-match-p' for various supported CONDITIONs.
By default all buffers are checked, but the optional
argument BUFFERS can restrict that: its value should be
an explicit list of buffers to check.
-Optional argument ARG is passed to `buffer-match-p', for
+Optional arguments ARGS are passed to `buffer-match-p', for
predicate conditions in CONDITION."
(let (bufs)
(dolist (buf (or buffers (buffer-list)))
- (when (buffer-match-p condition (get-buffer buf) arg)
+ (when (apply #'buffer-match-p condition (get-buffer buf) args)
(push buf bufs)))
bufs))
diff --git a/lisp/svg.el b/lisp/svg.el
index 15004357811..f2eb2ec66dd 100644
--- a/lisp/svg.el
+++ b/lisp/svg.el
@@ -1,6 +1,6 @@
;;; svg.el --- SVG image creation functions -*- lexical-binding: t -*-
-;; Copyright (C) 2014-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2014-2024 Free Software Foundation, Inc.
;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
;; Felix E. Klee <felix.klee@inka.de>
@@ -8,6 +8,9 @@
;; Version: 1.1
;; Package-Requires: ((emacs "25"))
+;; This is a GNU ELPA :core package. Avoid functionality that is not
+;; compatible with the version of Emacs recorded above.
+
;; This file is part of GNU Emacs.
;; GNU Emacs is free software: you can redistribute it and/or modify
diff --git a/lisp/t-mouse.el b/lisp/t-mouse.el
index c461743b0f1..6bd3168ab7c 100644
--- a/lisp/t-mouse.el
+++ b/lisp/t-mouse.el
@@ -4,7 +4,7 @@
;; Maintainer: emacs-devel@gnu.org
;; Keywords: mouse gpm linux
-;; Copyright (C) 1994-1995, 1998, 2006-2023 Free Software Foundation,
+;; Copyright (C) 1994-1995, 1998, 2006-2024 Free Software Foundation,
;; Inc.
;; This file is part of GNU Emacs.
diff --git a/lisp/tab-bar.el b/lisp/tab-bar.el
index e9ce7735229..219f42848ef 100644
--- a/lisp/tab-bar.el
+++ b/lisp/tab-bar.el
@@ -1,6 +1,6 @@
;;; tab-bar.el --- frame-local tabs with named persistent window configurations -*- lexical-binding: t; -*-
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
;; Author: Juri Linkov <juri@linkov.net>
;; Keywords: frames tabs
@@ -31,13 +31,8 @@
;;; Code:
-(eval-when-compile
- (require 'cl-lib)
- (require 'seq)
- (require 'icons))
-
-(autoload 'cl--set-substring "cl-lib")
-
+(eval-when-compile (require 'icons))
+(eval-when-compile (require 'cl-lib))
(defgroup tab-bar nil
"Frame-local tabs."
@@ -164,7 +159,9 @@ For easier selection of tabs by their numbers, consider customizing
(declare-function icons--register "icons")
(unless (iconp 'tab-bar-new)
(define-icon tab-bar-new nil
- `((image "tabs/new.xpm"
+ `((image "symbols/plus_16.svg" "tabs/new.xpm"
+ :face shadow
+ :height (1 . em)
:margin ,tab-bar-button-margin
:ascent center)
;; (emoji "➕")
@@ -177,7 +174,9 @@ For easier selection of tabs by their numbers, consider customizing
(unless (iconp 'tab-bar-close)
(define-icon tab-bar-close nil
- `((image "tabs/close.xpm"
+ `((image "symbols/cross_16.svg" "tabs/close.xpm"
+ :face shadow
+ :height (1 . em)
:margin ,tab-bar-button-margin
:ascent center)
;; (emoji " ❌")
@@ -191,7 +190,11 @@ For easier selection of tabs by their numbers, consider customizing
(unless (iconp 'tab-bar-menu-bar)
(define-icon tab-bar-menu-bar nil
- '(;; (emoji "🍔")
+ `((image "symbols/menu_16.svg"
+ :height (1 . em)
+ :margin ,tab-bar-button-margin
+ :ascent center)
+ ;; (emoji "🍔")
(symbol "☰")
(text "Menu" :face tab-bar-tab-inactive))
"Icon for the menu bar."
@@ -413,6 +416,8 @@ Beep, then throw to `context-menu' and return."
(beep)
(throw 'context-menu 'context-menu))
+(defvar touch-screen-delay)
+
(defun tab-bar-touchscreen-begin (event)
"Handle a touchscreen begin EVENT on the tab bar.
@@ -776,6 +781,31 @@ Return its existing value or a new value."
(set-frame-parameter frame 'tabs tabs))
+(defun tab-bar-tab-name-format-truncated (name _tab _i)
+ "Truncate the tab name.
+The maximal length is specified by `tab-bar-tab-name-truncated-max'.
+Append ellipsis `tab-bar-tab-name-ellipsis' at the end."
+ (if (< (length name) tab-bar-tab-name-truncated-max)
+ name
+ (truncate-string-to-width
+ name tab-bar-tab-name-truncated-max nil nil
+ tab-bar-tab-name-ellipsis)))
+
+(defun tab-bar-tab-name-format-hints (name _tab i)
+ "Show absolute numbers on tabs in the tab bar before the tab name.
+It has effect when `tab-bar-tab-hints' is non-nil."
+ (if tab-bar-tab-hints (concat (format "%d " i) name) name))
+
+(defun tab-bar-tab-name-format-close-button (name tab _i)
+ "Show the tab close button.
+The variable `tab-bar-close-button-show' defines when to show it."
+ (if (and tab-bar-close-button-show
+ (not (eq tab-bar-close-button-show
+ (if (eq (car tab) 'current-tab) 'non-selected 'selected)))
+ tab-bar-close-button)
+ (concat name tab-bar-close-button)
+ name))
+
(defcustom tab-bar-tab-face-function #'tab-bar-tab-face-default
"Function to define a tab face.
Function gets one argument: a tab."
@@ -786,6 +816,38 @@ Function gets one argument: a tab."
(defun tab-bar-tab-face-default (tab)
(if (eq (car tab) 'current-tab) 'tab-bar-tab 'tab-bar-tab-inactive))
+(defun tab-bar-tab-name-format-face (name tab _i)
+ "Apply the face to the tab name.
+It uses the function `tab-bar-tab-face-function'."
+ (add-face-text-property
+ 0 (length name) (funcall tab-bar-tab-face-function tab) t name)
+ name)
+
+(defcustom tab-bar-tab-name-format-functions
+ '(tab-bar-tab-name-format-hints
+ tab-bar-tab-name-format-close-button
+ tab-bar-tab-name-format-face)
+ "Functions called to modify the tab name.
+Each function is called with three arguments: the name returned
+by the previously called modifier, the tab and its number.
+It should return the formatted tab name to display in the tab bar."
+ :type '(repeat
+ (choice (function-item tab-bar-tab-name-format-truncated)
+ (function-item tab-bar-tab-name-format-hints)
+ (function-item tab-bar-tab-name-format-close-button)
+ (function-item tab-bar-tab-name-format-face)
+ (function :tag "Custom function")))
+ :group 'tab-bar
+ :version "30.1")
+
+(defun tab-bar-tab-name-format-default (tab i)
+ (let ((name (copy-sequence (alist-get 'name tab))))
+ (run-hook-wrapped 'tab-bar-tab-name-format-functions
+ (lambda (fun)
+ (setq name (funcall fun name tab i))
+ nil))
+ name))
+
(defcustom tab-bar-tab-name-format-function #'tab-bar-tab-name-format-default
"Function to format a tab name.
Function gets two arguments, the tab and its number, and should return
@@ -798,18 +860,6 @@ the formatted tab name to display in the tab bar."
:group 'tab-bar
:version "28.1")
-(defun tab-bar-tab-name-format-default (tab i)
- (let ((current-p (eq (car tab) 'current-tab)))
- (propertize
- (concat (if tab-bar-tab-hints (format "%d " i) "")
- (alist-get 'name tab)
- (or (and tab-bar-close-button-show
- (not (eq tab-bar-close-button-show
- (if current-p 'non-selected 'selected)))
- tab-bar-close-button)
- ""))
- 'face (funcall tab-bar-tab-face-function tab))))
-
(defcustom tab-bar-format '(tab-bar-format-history
tab-bar-format-tabs
tab-bar-separator
@@ -867,7 +917,7 @@ Used by `tab-bar-format-menu-bar'."
(defun tab-bar-format-menu-bar ()
"Produce the Menu button for the tab bar that shows the menu bar."
`((menu-bar menu-item ,tab-bar-menu-bar-button
- tab-bar-menu-bar :help "Menu Bar")))
+ tab-bar-menu-bar :help "Menu bar")))
(defun tab-bar-format-history ()
"Produce back and forward buttons for the tab bar.
@@ -894,13 +944,13 @@ You can hide these buttons by customizing `tab-bar-format' and removing
menu-item
,(funcall tab-bar-tab-name-format-function tab i)
ignore
- :help "Current tab")))
+ :help ,(alist-get 'name tab))))
(t
`((,(intern (format "tab-%i" i))
menu-item
,(funcall tab-bar-tab-name-format-function tab i)
,(alist-get 'binding tab)
- :help "Click to visit tab"))))
+ :help ,(alist-get 'name tab)))))
(when (alist-get 'close-binding tab)
`((,(if (eq (car tab) 'current-tab) 'C-current-tab
(intern (format "C-tab-%i" i)))
@@ -1179,15 +1229,16 @@ tab bar might wrap to the second line when it shouldn't.")
((< prev-width width)
(let* ((space (apply #'propertize " "
(text-properties-at 0 name)))
- (ins-pos (- len (if close-p 1 0)))
+ (ins-pos (- len (if close-p
+ (length tab-bar-close-button)
+ 0)))
(prev-name name))
(while continue
(setq name (concat (substring name 0 ins-pos)
space
(substring name ins-pos)))
(setq curr-width (string-pixel-width name))
- (if (and (< curr-width width)
- (> curr-width prev-width))
+ (if (< curr-width width)
(setq prev-width curr-width
prev-name name)
;; Set back a shorter name
@@ -1201,8 +1252,7 @@ tab bar might wrap to the second line when it shouldn't.")
(and del-pos2
(substring name del-pos2))))
(setq curr-width (string-pixel-width name))
- (if (and (> curr-width width)
- (< curr-width prev-width))
+ (if (> curr-width width)
(setq prev-width curr-width)
(setq continue nil)))
(let* ((len (length name))
@@ -2233,7 +2283,8 @@ and can restore them."
(unless (iconp 'tab-bar-back)
(define-icon tab-bar-back nil
- `((image "tabs/left-arrow.xpm"
+ `((image "symbols/chevron_left_16.svg" "tabs/left-arrow.xpm"
+ :height (1 . em)
:margin ,tab-bar-button-margin
:ascent center)
(text " < "))
@@ -2243,7 +2294,8 @@ and can restore them."
(unless (iconp 'tab-bar-forward)
(define-icon tab-bar-forward nil
- `((image "tabs/right-arrow.xpm"
+ `((image "symbols/chevron_right_16.svg" "tabs/right-arrow.xpm"
+ :height (1 . em)
:margin ,tab-bar-button-margin
:ascent center)
(text " > "))
diff --git a/lisp/tab-line.el b/lisp/tab-line.el
index d7c3049270a..cc60f94c9c5 100644
--- a/lisp/tab-line.el
+++ b/lisp/tab-line.el
@@ -1,6 +1,6 @@
;;; tab-line.el --- window-local tabs with window buffers -*- lexical-binding: t; -*-
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
;; Author: Juri Linkov <juri@linkov.net>
;; Keywords: windows tabs
@@ -28,7 +28,8 @@
;;; Code:
(require 'cl-lib)
-(require 'seq) ; tab-line.el is not pre-loaded so it's safe to use it here
+(require 'seq)
+(require 'icons)
(defgroup tab-line nil
@@ -190,12 +191,20 @@ If the value is a function, call it with no arguments."
:group 'tab-line
:version "27.1")
+(define-icon tab-line-new nil
+ `((image "symbols/plus_16.svg" "tabs/new.xpm"
+ :face shadow
+ :height (1 . em)
+ :margin (2 . 0)
+ :ascent center)
+ (text " + "))
+ "Icon for creating a new tab."
+ :version "30.1"
+ :help-echo "New tab")
+
(defvar tab-line-new-button
- (propertize " + "
- 'display '(image :type xpm
- :file "tabs/new.xpm"
- :margin (2 . 0)
- :ascent center)
+ (propertize (icon-string 'tab-line-new)
+ 'rear-nonsticky nil
'keymap tab-line-add-map
'mouse-face 'tab-line-highlight
'help-echo "Click to add tab")
@@ -218,34 +227,56 @@ If nil, don't show it at all."
:group 'tab-line
:version "27.1")
+(define-icon tab-line-close nil
+ `((image "symbols/cross_16.svg" "tabs/close.xpm"
+ :face shadow
+ :height (1 . em)
+ :margin (2 . 0)
+ :ascent center)
+ (text " x"))
+ "Icon for closing the clicked tab."
+ :version "30.1"
+ :help-echo "Click to close tab")
+
(defvar tab-line-close-button
- (propertize " x"
- 'display '(image :type xpm
- :file "tabs/close.xpm"
- :margin (2 . 0)
- :ascent center)
+ (propertize (icon-string 'tab-line-close)
+ 'rear-nonsticky nil ;; important to not break auto-scroll
'keymap tab-line-tab-close-map
'mouse-face 'tab-line-close-highlight
'help-echo "Click to close tab")
"Button for closing the clicked tab.")
+(define-icon tab-line-left nil
+ `((image "symbols/chevron_left_16.svg" "tabs/left-arrow.xpm"
+ :face shadow
+ :height (1 . em)
+ :margin (2 . 0)
+ :ascent center)
+ (text " <"))
+ "Icon for scrolling horizontally to the left."
+ :version "30.1")
+
(defvar tab-line-left-button
- (propertize " <"
- 'display '(image :type xpm
- :file "tabs/left-arrow.xpm"
- :margin (2 . 0)
- :ascent center)
+ (propertize (icon-string 'tab-line-left)
+ 'rear-nonsticky nil
'keymap tab-line-left-map
'mouse-face 'tab-line-highlight
'help-echo "Click to scroll left")
"Button for scrolling horizontally to the left.")
+(define-icon tab-line-right nil
+ `((image "symbols/chevron_right_16.svg" "tabs/right-arrow.xpm"
+ :face shadow
+ :height (1 . em)
+ :margin (2 . 0)
+ :ascent center)
+ (text "> "))
+ "Icon for scrolling horizontally to the right."
+ :version "30.1")
+
(defvar tab-line-right-button
- (propertize "> "
- 'display '(image :type xpm
- :file "tabs/right-arrow.xpm"
- :margin (2 . 0)
- :ascent center)
+ (propertize (icon-string 'tab-line-right)
+ 'rear-nonsticky nil
'keymap tab-line-right-map
'mouse-face 'tab-line-highlight
'help-echo "Click to scroll right")
@@ -331,48 +362,6 @@ or by `tab-line-tabs-buffer-groups'."
"Function to return a global list of buffers.
Used only for `tab-line-tabs-mode-buffers' and `tab-line-tabs-buffer-groups'.")
-
-
-;;; Touch screen support.
-
-(defun tab-line-track-tap (event &optional function)
- "Track a tap starting from EVENT.
-If EVENT is not a `touchscreen-begin' event, return t.
-Otherwise, return t if the tap completes successfully, and nil if
-the tap should be ignored.
-
-If FUNCTION is specified and the tap does not complete within
-`touch-screen-delay' seconds, display the appropriate context
-menu by calling FUNCTION with EVENT, and return nil."
- (if (not (eq (car-safe event) 'touchscreen-begin))
- t
- (let ((result (catch 'context-menu
- (let (timer)
- (unwind-protect
- (progn
- (when function
- (setq timer
- (run-at-time touch-screen-delay t
- #'throw 'context-menu
- 'context-menu)))
- (touch-screen-track-tap event))
- (when timer
- (cancel-timer timer)))))))
- (cond ((eq result 'context-menu)
- (prog1 nil
- (funcall function event)))
- (result t)))))
-
-(defun tab-line-event-start (event)
- "Like `event-start'.
-However, return the correct mouse position list if EVENT is a
-`touchscreen-begin' event."
- (or (and (eq (car-safe event) 'touchscreen-begin)
- (cdadr event))
- (event-start event)))
-
-
-
(defun tab-line-tabs-buffer-list ()
(seq-filter (lambda (b) (and (buffer-live-p b)
(/= (aref (buffer-name b) 0) ?\s)))
@@ -531,21 +520,27 @@ which the tab will represent."
(setf face (funcall fn tab tabs face buffer-p selected-p)))
(apply 'propertize
(concat (propertize (string-replace "%" "%%" name) ;; (bug#57848)
+ 'face face
'keymap tab-line-tab-map
'help-echo (if selected-p "Current tab"
"Click to select tab")
;; Don't turn mouse-1 into mouse-2 (bug#49247)
'follow-link 'ignore)
- (or (and (or buffer-p (assq 'buffer tab) (assq 'close tab))
- tab-line-close-button-show
- (not (eq tab-line-close-button-show
- (if selected-p 'non-selected 'selected)))
- tab-line-close-button)
- ""))
+ (let ((close (or (and (or buffer-p (assq 'buffer tab)
+ (assq 'close tab))
+ tab-line-close-button-show
+ (not (eq tab-line-close-button-show
+ (if selected-p 'non-selected
+ 'selected)))
+ tab-line-close-button)
+ "")))
+ (setq close (copy-sequence close))
+ ;; Don't overwrite the icon face
+ (add-face-text-property 0 (length close) face t close)
+ close))
`(
tab ,tab
,@(if selected-p '(selected t))
- face ,face
mouse-face tab-line-highlight))))
(defun tab-line-format-template (tabs)
@@ -684,7 +679,7 @@ the selected tab visible."
(erase-buffer)
(apply 'insert strings)
(goto-char (point-min))
- (add-face-text-property (point-min) (point-max) 'tab-line)
+ (add-face-text-property (point-min) (point-max) 'tab-line t)
;; Continuation means tab-line doesn't fit completely,
;; thus scroll arrows are needed for scrolling.
(setq show-arrows (> (vertical-motion 1) 0))
@@ -961,6 +956,47 @@ sight of the tab line."
(popup-menu menu event)))
+;;; Touch screen support.
+
+(defvar touch-screen-delay)
+
+(defun tab-line-track-tap (event &optional function)
+ "Track a tap starting from EVENT.
+If EVENT is not a `touchscreen-begin' event, return t.
+Otherwise, return t if the tap completes successfully, and nil if
+the tap should be ignored.
+
+If FUNCTION is specified and the tap does not complete within
+`touch-screen-delay' seconds, display the appropriate context
+menu by calling FUNCTION with EVENT, and return nil."
+ (if (not (eq (car-safe event) 'touchscreen-begin))
+ t
+ (let ((result (catch 'context-menu
+ (let (timer)
+ (unwind-protect
+ (progn
+ (when function
+ (setq timer
+ (run-at-time touch-screen-delay t
+ #'throw 'context-menu
+ 'context-menu)))
+ (touch-screen-track-tap event))
+ (when timer
+ (cancel-timer timer)))))))
+ (cond ((eq result 'context-menu)
+ (prog1 nil
+ (funcall function event)))
+ (result t)))))
+
+(defun tab-line-event-start (event)
+ "Like `event-start'.
+However, return the correct mouse position list if EVENT is a
+`touchscreen-begin' event."
+ (or (and (eq (car-safe event) 'touchscreen-begin)
+ (cdadr event))
+ (event-start event)))
+
+
;;;###autoload
(define-minor-mode tab-line-mode
"Toggle display of tab line in the windows displaying the current buffer."
diff --git a/lisp/tabify.el b/lisp/tabify.el
index 019c83cf7df..37a3ec65c4b 100644
--- a/lisp/tabify.el
+++ b/lisp/tabify.el
@@ -1,6 +1,6 @@
;;; tabify.el --- tab conversion commands for Emacs -*- lexical-binding: t -*-
-;; Copyright (C) 1985, 1994, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1985, 1994, 2001-2024 Free Software Foundation, Inc.
;; Maintainer: emacs-devel@gnu.org
;; Package: emacs
diff --git a/lisp/talk.el b/lisp/talk.el
index 46c36c0b6e5..b19b1f46378 100644
--- a/lisp/talk.el
+++ b/lisp/talk.el
@@ -1,6 +1,6 @@
;;; talk.el --- allow several users to talk to each other through Emacs -*- lexical-binding: t -*-
-;; Copyright (C) 1995, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1995, 2001-2024 Free Software Foundation, Inc.
;; Maintainer: emacs-devel@gnu.org
;; Keywords: comm, frames
diff --git a/lisp/tar-mode.el b/lisp/tar-mode.el
index 2b6329fecc3..375191a8167 100644
--- a/lisp/tar-mode.el
+++ b/lisp/tar-mode.el
@@ -1,6 +1,6 @@
;;; tar-mode.el --- simple editing of tar files from GNU Emacs -*- lexical-binding:t -*-
-;; Copyright (C) 1990-1991, 1993-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1990-1991, 1993-2024 Free Software Foundation, Inc.
;; Author: Jamie Zawinski <jwz@lucid.com>
;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/tempo.el b/lisp/tempo.el
index b59342b2c9d..df78690bd31 100644
--- a/lisp/tempo.el
+++ b/lisp/tempo.el
@@ -1,6 +1,6 @@
;;; tempo.el --- Flexible template insertion -*- lexical-binding: t; -*-
-;; Copyright (C) 1994-1995, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1994-1995, 2001-2024 Free Software Foundation, Inc.
;; Author: David Kågedal <davidk@lysator.liu.se>
;; Created: 16 Feb 1994
@@ -116,8 +116,7 @@
"Prompt user for strings in templates.
If this variable is non-nil, `tempo-insert' prompts the
user for text to insert in the templates."
- :type 'boolean
- :group 'tempo)
+ :type 'boolean)
(defcustom tempo-insert-region nil
"Automatically insert current region when there is a `r' in the template
@@ -126,20 +125,17 @@ elements, unless the template function is given a prefix (or a non-nil
argument). If this variable is non-nil, the behavior is reversed.
In Transient Mark mode, this option is unused."
- :type 'boolean
- :group 'tempo)
+ :type 'boolean)
(defcustom tempo-show-completion-buffer t
"If non-nil, show a buffer with possible completions, when only
a partial completion can be found."
- :type 'boolean
- :group 'tempo)
+ :type 'boolean)
(defcustom tempo-leave-completion-buffer nil
"If nil, a completion buffer generated by \\[tempo-complete-tag]
disappears at the next keypress; otherwise, it remains forever."
- :type 'boolean
- :group 'tempo)
+ :type 'boolean)
;;; Internal variables
@@ -189,11 +185,12 @@ returns a pair of the form (STRING . POS), where STRING is the string
used for matching and POS is the buffer position after which text
should be replaced with a template.")
-(defvar tempo-user-elements nil
+(define-obsolete-variable-alias 'tempo-user-elements 'tempo-user-element-functions "30.1")
+(defvar tempo-user-element-functions nil
"Element handlers for user-defined elements.
-A list of symbols which are bound to functions that take one argument.
-This function should return something to be sent to `tempo-insert' if
-it recognizes the argument, and nil otherwise.")
+This is an abnormal hook where the functions are called with one argument
+\(an element in a template) and they should return something to be sent to
+`tempo-insert' if they recognize the argument, and nil otherwise.")
(defvar-local tempo-named-insertions nil
"Temporary storage for named insertions.")
@@ -262,7 +259,7 @@ The elements in ELEMENTS can be of several types:
- `n>': Inserts a newline and indents line.
- `o': Like `%' but leaves the point before the newline.
- nil: It is ignored.
- - Anything else: Each function in `tempo-user-elements' is called
+ - Anything else: Each function in `tempo-user-element-functions' is called
with it as argument until one of them returns non-nil, and the
result is inserted. If all of them return nil, it is evaluated and
the result is treated as an element to be inserted. One additional
@@ -274,14 +271,13 @@ The elements in ELEMENTS can be of several types:
name)))
(command-name template-name))
(set template-name elements)
- (fset command-name (list 'lambda (list '&optional 'arg)
- (or documentation
- (concat "Insert a " name "."))
- (list 'interactive "*P")
- (list 'tempo-insert-template (list 'quote
- template-name)
- (list 'if 'tempo-insert-region
- (list 'not 'arg) 'arg))))
+ (fset command-name (lambda (&optional arg)
+ (:documentation
+ (or documentation (concat "Insert a " name ".")))
+ (interactive "*P")
+ (tempo-insert-template template-name
+ (if tempo-insert-region
+ (not arg) arg))))
(and tag
(tempo-add-tag tag template-name taglist))
command-name))
@@ -325,72 +321,57 @@ elements are replaced with the current region.
See documentation for `tempo-define-template' for the kind of elements
possible."
- (cond ((stringp element) (tempo-process-and-insert-string element))
- ((and (consp element)
- (eq (car element) 'p)) (tempo-insert-prompt-compat
- (cdr element)))
- ((and (consp element)
- (eq (car element) 'P)) (let ((tempo-interactive t))
- (tempo-insert-prompt-compat
- (cdr element))))
-;;; ((and (consp element)
-;;; (eq (car element) 'v)) (tempo-save-named
-;;; (nth 1 element)
-;;; nil
-;;; (nth 2 element)))
- ((and (consp element)
- (eq (car element) 'r)) (if on-region
- (goto-char tempo-region-stop)
- (tempo-insert-prompt-compat
- (cdr element))))
- ((and (consp element)
- (eq (car element) 'r>)) (if on-region
- (progn
- (goto-char tempo-region-stop)
- (indent-region (mark) (point) nil))
- (tempo-insert-prompt-compat
- (cdr element))))
- ((and (consp element)
- (eq (car element) 's)) (tempo-insert-named (car (cdr element))))
- ((and (consp element)
- (eq (car element) 'l)) (mapcar (lambda (elt)
- (tempo-insert elt on-region))
- (cdr element)))
- ((eq element 'p) (tempo-insert-mark (point-marker)))
- ((eq element 'r) (if on-region
- (goto-char tempo-region-stop)
- (tempo-insert-mark (point-marker))))
- ((eq element 'r>) (if on-region
- (progn
- (goto-char tempo-region-stop)
- (indent-region (mark) (point) nil))
- (tempo-insert-mark (point-marker))))
- ((eq element '>) (indent-according-to-mode))
- ((eq element '&) (if (not (or (= (current-column) 0)
- (save-excursion
- (re-search-backward
- "^\\s-*\\=" nil t))))
- (insert "\n")))
- ((eq element '%) (if (not (or (eolp)
- (save-excursion
- (re-search-forward
- "\\=\\s-*$" nil t))))
- (insert "\n")))
- ((eq element 'n) (insert "\n"))
- ((eq element 'n>) (insert "\n") (indent-according-to-mode))
- ;; Bug: If the 'o is the first element in a template, strange
- ;; things can happen when the template is inserted at the
- ;; beginning of a line.
- ((eq element 'o) (if (not (or on-region
- (eolp)
- (save-excursion
- (re-search-forward
- "\\=\\s-*$" nil t))))
- (open-line 1)))
- ((null element))
- (t (tempo-insert (or (tempo-is-user-element element)
- (eval element))
- on-region))))
+ (pcase element
+ ((pred stringp) (tempo-process-and-insert-string element))
+ (`(p . ,rest) (tempo-insert-prompt-compat rest))
+ (`(P . ,rest) (let ((tempo-interactive t))
+ (tempo-insert-prompt-compat rest)))
+ ;; (`(v ,name ,data) (tempo-save-named name nil data))
+ (`(r . ,rest) (if on-region
+ (goto-char tempo-region-stop)
+ (tempo-insert-prompt-compat rest)))
+ (`(r> . ,rest) (if on-region
+ (progn
+ (goto-char tempo-region-stop)
+ (indent-region (mark) (point) nil))
+ (tempo-insert-prompt-compat rest)))
+ (`(s ,name) (tempo-insert-named name))
+ (`(l . ,rest) (dolist (elt rest) (tempo-insert elt on-region)))
+ ('p (tempo-insert-mark (point-marker)))
+ ('r (if on-region
+ (goto-char tempo-region-stop)
+ (tempo-insert-mark (point-marker))))
+ ('r> (if on-region
+ (progn
+ (goto-char tempo-region-stop)
+ (indent-region (mark) (point) nil))
+ (tempo-insert-mark (point-marker))))
+ ('> (indent-according-to-mode))
+ ('& (if (not (or (= (current-column) 0)
+ (save-excursion
+ (re-search-backward
+ "^\\s-*\\=" nil t))))
+ (insert "\n")))
+ ('% (if (not (or (eolp)
+ (save-excursion
+ (re-search-forward
+ "\\=\\s-*$" nil t))))
+ (insert "\n")))
+ ('n (insert "\n"))
+ ('n> (insert "\n") (indent-according-to-mode))
+ ;; Bug: If the 'o is the first element in a template, strange
+ ;; things can happen when the template is inserted at the
+ ;; beginning of a line.
+ ('o (if (not (or on-region
+ (eolp)
+ (save-excursion
+ (re-search-forward
+ "\\=\\s-*$" nil t))))
+ (open-line 1)))
+ ('nil nil)
+ (_ (tempo-insert (or (tempo-is-user-element element)
+ (eval element t))
+ on-region))))
;;;
;;; tempo-insert-prompt
@@ -400,7 +381,7 @@ possible."
PROMPT can be either a prompt string, or a list of arguments to
`tempo-insert-prompt', or nil."
(if (consp prompt) ; not nil either
- (apply 'tempo-insert-prompt prompt)
+ (apply #'tempo-insert-prompt prompt)
(tempo-insert-prompt prompt)))
(defun tempo-insert-prompt (prompt &optional save-name no-insert)
@@ -445,14 +426,8 @@ never prompted."
;;; tempo-is-user-element
(defun tempo-is-user-element (element)
- "Try all the user-defined element handlers in `tempo-user-elements'."
- ;; Sigh... I need (some list)
- (catch 'found
- (mapc (lambda (handler)
- (let ((result (funcall handler element)))
- (if result (throw 'found result))))
- tempo-user-elements)
- (throw 'found nil)))
+ "Try all the user-defined element handlers in `tempo-user-element-functions'."
+ (run-hook-with-args-until-success 'tempo-user-element-functions element))
;;;
;;; tempo-forget-insertions
@@ -636,12 +611,12 @@ If `tempo-dirty-collection' is nil, the old collection is reused."
(or (and (not tempo-dirty-collection)
tempo-collection)
(setq tempo-collection
- (apply (function append)
+ (apply #'append
(mapcar (lambda (tag-list)
; If the format for
; tempo-local-tags changes,
; change this
- (eval (car tag-list)))
+ (eval (car tag-list) t))
tempo-local-tags))))
(setq tempo-dirty-collection nil)))
@@ -653,16 +628,10 @@ If `tempo-dirty-collection' is nil, the old collection is reused."
FINDER is a function or a string. Returns (STRING . POS), or nil
if no reasonable string is found."
(cond ((stringp finder)
- (let (successful)
- (save-excursion
- (or (setq successful (re-search-backward finder nil t))
- 0))
- (if successful
- (cons (buffer-substring (match-beginning 1)
- (match-end 1)) ; This seems to be a
- ; bug in emacs
- (match-beginning 1))
- nil)))
+ (if (save-excursion (re-search-backward finder nil t))
+ (cons (match-string 1) ; This seems to be a bug in Emacs (?)
+ (match-beginning 1))
+ nil))
(t
(funcall finder))))
diff --git a/lisp/term.el b/lisp/term.el
index b8466b21332..1857c9ed9e3 100644
--- a/lisp/term.el
+++ b/lisp/term.el
@@ -1,6 +1,6 @@
;;; term.el --- general command interpreter in a window stuff -*- lexical-binding: t -*-
-;; Copyright (C) 1988, 1990, 1992, 1994-1995, 2001-2023 Free Software
+;; Copyright (C) 1988, 1990, 1992, 1994-1995, 2001-2024 Free Software
;; Foundation, Inc.
;; Author: Per Bothner <per@bothner.com>
@@ -486,7 +486,7 @@ Customize this option to nil if you want the previous behavior."
(defcustom term-scroll-to-bottom-on-output nil
"Controls whether interpreter output causes window to scroll.
-If nil, then do not scroll. If t or `all', scroll all windows showing buffer.
+If nil, then do not scroll. If t, scroll all windows showing buffer.
If `this', scroll only the selected window.
If `others', scroll only those that are not the selected window.
@@ -494,7 +494,12 @@ The default is nil.
See variable `term-scroll-show-maximum-output'.
This variable is buffer-local."
- :type 'boolean
+ :type '(choice (const :tag "Don't scroll" nil)
+ (const :tag "Scroll selected window only" this)
+ (const :tag "Scroll unselected windows" others)
+ ;; We also recognize `all', but we don't advertise it
+ ;; anymore. (Bug#66071)
+ (other :tag "Scroll all windows" t))
:group 'term)
(defcustom term-scroll-snap-to-bottom t
@@ -1080,6 +1085,8 @@ underlying shell."
(setq term-ansi-current-invisible nil)
(setq term-ansi-current-bg-color 0))
+(defvar touch-screen-display-keyboard)
+
(define-derived-mode term-mode fundamental-mode "Term"
"Major mode for interacting with an inferior interpreter.
The interpreter name is same as buffer name, sans the asterisks.
@@ -1386,10 +1393,15 @@ Entry to this mode runs the hooks on `term-mode-hook'."
(interactive)
(term-send-raw-string (current-kill 0)))
-(defun term--xterm-paste ()
+(defun term--xterm-paste (event)
"Insert the text pasted in an XTerm bracketed paste operation."
- (interactive)
- (term-send-raw-string (xterm--pasted-text)))
+ (interactive "e")
+ (unless (eq (car-safe event) 'xterm-paste)
+ (error "term--xterm-paste must be found to xterm-paste event"))
+ (let ((str (nth 1 event)))
+ (unless (stringp str)
+ (error "term--xterm-paste provided event does not contain paste text"))
+ (term-send-raw-string str)))
(declare-function xterm--pasted-text "term/xterm" ())
diff --git a/lisp/term/AT386.el b/lisp/term/AT386.el
index 541b7c5aad0..6592fd3da45 100644
--- a/lisp/term/AT386.el
+++ b/lisp/term/AT386.el
@@ -1,6 +1,6 @@
;;; AT386.el --- terminal support package for IBM AT keyboards -*- lexical-binding: t -*-
-;; Copyright (C) 1992, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1992, 2001-2024 Free Software Foundation, Inc.
;; Author: Eric S. Raymond <esr@thyrsus.com>
;; Keywords: terminals
diff --git a/lisp/term/README b/lisp/term/README
index 6940e30c002..32aab4af00d 100644
--- a/lisp/term/README
+++ b/lisp/term/README
@@ -1,4 +1,4 @@
-Copyright (C) 1993, 2001-2023 Free Software Foundation, Inc.
+Copyright (C) 1993, 2001-2024 Free Software Foundation, Inc.
See the end of the file for license conditions.
diff --git a/lisp/term/android-win.el b/lisp/term/android-win.el
index d425ea401a9..51163e5b9b2 100644
--- a/lisp/term/android-win.el
+++ b/lisp/term/android-win.el
@@ -1,6 +1,6 @@
-;;; x-win.el --- parse relevant switches and set up for Android -*- lexical-binding:t -*-
+;;; android-win.el --- terminal set up for Android -*- lexical-binding:t -*-
-;; Copyright (C) 2023 Free Software Foundation, Inc.
+;; Copyright (C) 2023-2024 Free Software Foundation, Inc.
;; Author: FSF
;; Keywords: terminals, i18n, android
@@ -75,19 +75,28 @@ DISPLAY is ignored on Android."
(defvar android-primary-selection nil
"The last string placed in the primary selection.
-Nil if there was no such string.
+nil if there was no such string.
-Android does not have a primary selection of its own, so Emacs
-emulates one inside Lisp.")
+Android is not equipped with a primary selection of its own, so
+Emacs emulates one in Lisp.")
+
+(defvar android-secondary-selection nil
+ "The last string placed in the secondary selection.
+nil if there was no such string.
+
+Android is not equipped with a secondary selection of its own, so
+Emacs emulates one in Lisp.")
(defun android-get-clipboard-1 (data-type)
- "Return the clipboard data.
-DATA-TYPE is a selection conversion target. `STRING' means to
-return the contents of the clipboard as a string. `TARGETS'
-means to return supported data types as a vector.
+ "Return data saved from the clipboard.
+DATA-TYPE is a selection conversion target.
+
+`STRING' means return the contents of the clipboard as a string,
+while `TARGETS' means return the types of all data present within
+the clipboard as a vector.
-Interpret any other symbol as a MIME type, and return its
-corresponding data."
+Interpret any other symbol as a MIME type for which any clipboard
+data is returned"
(or (and (eq data-type 'STRING)
(android-get-clipboard))
(and (eq data-type 'TARGETS)
@@ -95,7 +104,8 @@ corresponding data."
(vconcat [TARGETS STRING]
(let ((i nil))
(dolist (type (android-get-clipboard-targets))
- ;; Don't report plain text as a valid target.
+ ;; Don't report plain text as a valid target
+ ;; since it is addressed by STRING.
(unless (equal type "text/plain")
(push (intern type) i)))
(nreverse i))))
@@ -109,7 +119,16 @@ Return nil if DATA-TYPE is anything other than STRING or TARGETS."
(or (and (eq data-type 'STRING)
android-primary-selection)
(and (eq data-type 'TARGETS)
- [TARGETS]))))
+ [TARGETS STRING]))))
+
+(defun android-get-secondary (data-type)
+ "Return the last string placed in the secondary selection, or nil.
+Return nil if DATA-TYPE is anything other than STRING or TARGETS."
+ (when android-secondary-selection
+ (or (and (eq data-type 'STRING)
+ android-secondary-selection)
+ (and (eq data-type 'TARGETS)
+ [TARGETS STRING]))))
(defun android-selection-bounds (value)
"Return bounds of selection value VALUE.
@@ -152,26 +171,34 @@ VALUE should be something suitable for passing to
(cond ((eq type 'CLIPBOARD)
(android-get-clipboard-1 data-type))
((eq type 'PRIMARY)
- (android-get-primary data-type))))
+ (android-get-primary data-type))
+ ((eq type 'SECONDARY)
+ (android-get-secondary data-type))))
(cl-defmethod gui-backend-selection-exists-p (selection
&context (window-system android))
(cond ((eq selection 'CLIPBOARD)
(android-clipboard-exists-p))
((eq selection 'PRIMARY)
- (not (null android-primary-selection)))))
+ (not (null android-primary-selection)))
+ ((eq selection 'SECONDARY)
+ (not (null android-secondary-selection)))))
(cl-defmethod gui-backend-selection-owner-p (selection
&context (window-system android))
(cond ((eq selection 'CLIPBOARD)
(let ((ownership (android-clipboard-owner-p)))
- ;; If ownership is `lambda', then Emacs couldn't determine
+ ;; If ownership is `lambda', then Emacs couldn't establish
;; whether or not it owns the clipboard.
(and (not (eq ownership 'lambda)) ownership)))
((eq selection 'PRIMARY)
;; Emacs always owns its own primary selection as long as it
;; exists.
- (not (null android-primary-selection)))))
+ (not (null android-primary-selection)))
+ ((eq selection 'SECONDARY)
+ ;; Emacs always owns its own secondary selection as long as
+ ;; it exists.
+ (not (null android-secondary-selection)))))
(cl-defmethod gui-backend-set-selection (type value
&context (window-system android))
@@ -181,7 +208,9 @@ VALUE should be something suitable for passing to
(cond ((eq type 'CLIPBOARD)
(android-set-clipboard string))
((eq type 'PRIMARY)
- (setq android-primary-selection string)))))
+ (setq android-primary-selection string))
+ ((eq type 'SECONDARY)
+ (setq android-secondary-selection string)))))
;;; Character composition display.
@@ -233,5 +262,223 @@ EVENT is a preedit-text event."
(defconst x-pointer-invisible 0)
+;; Drag-and-drop. There are two formats of drag and drop event under
+;; Android. The data field of the first is set to a cons of X and Y,
+;; which represent a position within a frame that something is being
+;; dragged over, whereas that of the second is a cons of either symbol
+;; `uri' or `text' and a list of URIs or text to insert.
+;;
+;; If a content:// URI is encountered, then it in turn designates a
+;; file within the special-purpose /content/by-authority directory,
+;; which facilitates accessing such atypical files.
+
+(declare-function url-type "url-parse")
+(declare-function url-host "url-parse")
+(declare-function url-filename "url-parse")
+
+(defun android-handle-dnd-event (event)
+ "Respond to a drag-and-drop event EVENT.
+If it reflects the motion of an item above a frame, call
+`dnd-handle-movement' to move the cursor or scroll the window
+under the item pursuant to the pertinent user options.
+
+If it reflects dropped text, insert such text within window at
+the location of the drop.
+
+If it reflects a list of URIs, then open each URI, converting
+content:// URIs into the special file names which represent them."
+ (interactive "e")
+ (let ((message (caddr event))
+ (posn (event-start event)))
+ (cond ((fixnump (car message))
+ (dnd-handle-movement posn))
+ ((eq (car message) 'text)
+ (let ((window (posn-window posn)))
+ (with-selected-window window
+ (unless mouse-yank-at-point
+ (goto-char (posn-point (event-start event))))
+ (dnd-insert-text window 'copy (cdr message)))))
+ ((eq (car message) 'uri)
+ (let ((uri-list (split-string (cdr message)
+ "[\0\r\n]" t))
+ (new-uri-list nil)
+ (dnd-unescape-file-uris t))
+ (dolist (uri uri-list)
+ (ignore-errors
+ (let ((url (url-generic-parse-url uri)))
+ (when (equal (url-type url) "content")
+ ;; Replace URI with a matching /content file
+ ;; name.
+ (setq uri (format "file:/content/by-authority/%s%s"
+ (url-host url)
+ (url-filename url))
+ ;; And guarantee that this file URI is not
+ ;; subject to URI decoding, for it must be
+ ;; transformed back into a content URI.
+ dnd-unescape-file-uris nil))))
+ (push uri new-uri-list))
+ (dnd-handle-multiple-urls (posn-window posn)
+ new-uri-list
+ 'copy))))))
+
+(define-key special-event-map [drag-n-drop] 'android-handle-dnd-event)
+
+
+;; Bind keys sent by input methods to manipulate the state of the
+;; selection to commands which set or deactivate the mark.
+
+(defun android-deactivate-mark-command ()
+ "Deactivate the mark in this buffer.
+This command is generally invoked by input methods sending
+the `stop-selecting-text' editing key."
+ (interactive)
+ (deactivate-mark))
+
+(global-set-key [select-all] 'mark-whole-buffer)
+(global-set-key [start-selecting-text] 'set-mark-command)
+(global-set-key [stop-selecting-text] 'android-deactivate-mark-command)
+
+
+;; Splash screen notice. Users are frequently left scratching their
+;; heads when they overlook the Android appendix in the Emacs manual
+;; and discover that external storage is not accessible; worse yet,
+;; Android 11 and later veil the settings panel controlling such
+;; permissions behind layer upon layer of largely immaterial settings
+;; panels, such that several modified copies of the Android Settings
+;; app have omitted them altogether after their developers conducted
+;; their own interface simplifications. Display a button on the
+;; splash screen that instructs users on granting these permissions
+;; when they are denied.
+
+(declare-function android-external-storage-available-p "androidfns.c")
+(declare-function android-request-storage-access "androidfns.c")
+(declare-function android-request-directory-access "androidfns.c")
+
+(defun android-display-storage-permission-popup (&optional _ignored)
+ "Display a dialog regarding storage permissions.
+Display a buffer explaining the need for storage permissions and
+offering to grant them."
+ (interactive)
+ (with-current-buffer (get-buffer-create "*Android Permissions*")
+ (setq buffer-read-only nil)
+ (erase-buffer)
+ (insert (propertize "Storage Access Permissions"
+ 'face '(bold (:height 1.2))))
+ (insert "
+
+Before Emacs can access your device's external storage
+directories, such as /sdcard and /storage/emulated/0, you must
+grant it permission to do so.
+
+Alternatively, you can request access to a particular directory
+in external storage, whereafter it will be available under the
+directory /content/storage.
+
+")
+ (insert-button "Grant storage permissions"
+ 'action (lambda (_)
+ (android-request-storage-access)
+ (quit-window)))
+ (newline)
+ (newline)
+ (insert-button "Request access to directory"
+ 'action (lambda (_)
+ (android-request-directory-access)))
+ (newline)
+ (special-mode)
+ (setq buffer-read-only t))
+ (let ((window (display-buffer "*Android Permissions*")))
+ (when (windowp window)
+ (with-selected-window window
+ ;; Fill the text to the width of this window in columns if it
+ ;; does not exceed 72, that the text might not be wrapped or
+ ;; truncated.
+ (when (<= (window-width window) 72)
+ (let ((fill-column (window-width window))
+ (inhibit-read-only t))
+ (fill-region (point-min) (point-max))))))))
+
+(defun android-after-splash-screen (fancy-p)
+ "Insert a brief notice on the absence of storage permissions.
+If storage permissions are as yet denied to Emacs, insert a short
+notice to that effect, followed by a button that enables the user
+to grant such permissions.
+
+FANCY-P non-nil means the notice will be displayed with faces, in
+the style appropriate for its incorporation within the fancy splash
+screen display; see `francy-splash-insert'."
+ (unless (android-external-storage-available-p)
+ (if fancy-p
+ (fancy-splash-insert
+ :face '(variable-pitch
+ font-lock-function-call-face)
+ "\nPermissions necessary to access external storage directories have
+been denied. Click "
+ :link '("here" android-display-storage-permission-popup)
+ " to grant them.")
+ (insert
+ "Permissions necessary to access external storage directories have been
+denied. ")
+ (insert-button "Click here to grant them."
+ 'action #'android-display-storage-permission-popup
+ 'follow-link t)
+ (newline))))
+
+
+;;; Locale preferences.
+
+(defvar android-os-language)
+
+(defun android-locale-for-system-language ()
+ "Return a locale representing the system language.
+This locale reflects the system's language preferences in its
+language name and country variant fields, and always specifies
+the UTF-8 coding system."
+ ;; android-os-language is a list comprising four elements LANGUAGE,
+ ;; COUNTRY, SCRIPT, and VARIANT.
+ ;;
+ ;; LANGUAGE and COUNTRY are ISO language and country codes identical
+ ;; to those stored within POSIX locales.
+ ;;
+ ;; SCRIPT is an ISO 15924 script tag, representing the script used
+ ;; if available, or if required to disambiguate between distinct
+ ;; writing systems for the same combination of language and country.
+ ;;
+ ;; VARIANT is an arbitrary string representing the variant of the
+ ;; LANGUAGE or SCRIPT represented.
+ ;;
+ ;; Each of these fields might be empty, but the locale is invalid if
+ ;; LANGUAGE is empty, which if true "en_US.UTF-8" is returned as a
+ ;; placeholder.
+ (let ((language (or (nth 0 android-os-language) ""))
+ (country (or (nth 1 android-os-language) ""))
+ (script (or (nth 2 android-os-language) ""))
+ (variant (or (nth 3 android-os-language) ""))
+ locale-base locale-modifier)
+ (if (string-empty-p language)
+ (setq locale-base "en_US.UTF-8")
+ (if (string-empty-p country)
+ (setq locale-base (concat language ".UTF-8"))
+ (setq locale-base (concat language "_" country
+ ".UTF-8"))))
+ ;; No straightforward relation between Java script and variant
+ ;; combinations exist: Java permits both a script and a variant to
+ ;; be supplied at once, whereas POSIX's closest analog "modifiers"
+ ;; permit only either an alternative script or a variant to be
+ ;; supplied.
+ ;;
+ ;; Emacs disregards variants besides "EURO" and scripts besides
+ ;; "Cyrl", for these two never coexist in existing locales, and
+ ;; their POSIX equivalents are the sole modifiers recognized by
+ ;; Emacs.
+ (if (string-equal script "Cyrl")
+ (setq locale-modifier "@cyrillic")
+ (if (string-equal variant "EURO")
+ (setq locale-modifier "@euro")
+ (setq locale-modifier "")))
+ ;; Return the concatenation of both these values.
+ (concat locale-base locale-modifier)))
+
+
(provide 'android-win)
;; android-win.el ends here.
diff --git a/lisp/term/bobcat.el b/lisp/term/bobcat.el
index 983c8cded2f..0c2eba486a3 100644
--- a/lisp/term/bobcat.el
+++ b/lisp/term/bobcat.el
@@ -3,8 +3,8 @@
(defun terminal-init-bobcat ()
"Terminal initialization function for bobcat."
;; HP terminals usually encourage using ^H as the rubout character
- (keyboard-translate ?\177 ?\^h)
- (keyboard-translate ?\^h ?\177))
+ (key-translate "DEL" "C-h")
+ (key-translate "C-h" "DEL"))
(provide 'term/bobcat)
diff --git a/lisp/term/common-win.el b/lisp/term/common-win.el
index 38b3c580625..181dcc8e6d9 100644
--- a/lisp/term/common-win.el
+++ b/lisp/term/common-win.el
@@ -1,6 +1,6 @@
;;; common-win.el --- common part of handling window systems -*- lexical-binding: t; -*-
-;; Copyright (C) 1993-1994, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1993-1994, 2001-2024 Free Software Foundation, Inc.
;; Maintainer: emacs-devel@gnu.org
;; Keywords: terminals
diff --git a/lisp/term/fbterm.el b/lisp/term/fbterm.el
index d9981778dbe..834a45dac66 100644
--- a/lisp/term/fbterm.el
+++ b/lisp/term/fbterm.el
@@ -1,6 +1,6 @@
;;; fbterm.el -*- lexical-binding:t -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;; Note that, in some versions of fbterm, the TERM environment
;; variable is set to "linux". When that's the case, the code below
diff --git a/lisp/term/haiku-win.el b/lisp/term/haiku-win.el
index 50c9cb5b9d4..efc0a129062 100644
--- a/lisp/term/haiku-win.el
+++ b/lisp/term/haiku-win.el
@@ -1,6 +1,6 @@
;;; haiku-win.el --- set up windowing on Haiku -*- lexical-binding: t -*-
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -369,14 +369,15 @@ or a pair of markers) and turns it into a file system reference."
((posn-area (event-start event)))
((assoc "refs" string)
(with-selected-window window
- (dolist (filename (cddr (assoc "refs" string)))
- (dnd-handle-one-url window action
- (concat "file:" filename)))))
+ (dnd-handle-multiple-urls
+ window (mapcar
+ (lambda (name) (concat "file:" name))
+ (cddr (assoc "refs" string)))
+ action)))
((assoc "text/uri-list" string)
(dolist (text (cddr (assoc "text/uri-list" string)))
(let ((uri-list (split-string text "[\0\r\n]" t)))
- (dolist (bf uri-list)
- (dnd-handle-one-url window action bf)))))
+ (dnd-handle-multiple-urls window uri-list action))))
((assoc "text/plain" string)
(with-selected-window window
(dolist (text (cddr (assoc "text/plain" string)))
diff --git a/lisp/term/internal.el b/lisp/term/internal.el
index 14ebb0f6609..8c0e50e20b3 100644
--- a/lisp/term/internal.el
+++ b/lisp/term/internal.el
@@ -1,6 +1,6 @@
;;; internal.el --- support for PC internal terminal -*- lexical-binding: t -*-
-;; Copyright (C) 1993-1994, 1998-1999, 2001-2023 Free Software
+;; Copyright (C) 1993-1994, 1998-1999, 2001-2024 Free Software
;; Foundation, Inc.
;; Author: Morten Welinder <terra@diku.dk>
diff --git a/lisp/term/iris-ansi.el b/lisp/term/iris-ansi.el
index abe7282f823..a07927000e7 100644
--- a/lisp/term/iris-ansi.el
+++ b/lisp/term/iris-ansi.el
@@ -1,6 +1,6 @@
;;; iris-ansi.el --- configure Emacs for SGI xwsh and winterm apps -*- lexical-binding: t -*-
-;; Copyright (C) 1997, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997, 2001-2024 Free Software Foundation, Inc.
;; Author: Dan Nicolaescu <dann@ics.uci.edu>
diff --git a/lisp/term/konsole.el b/lisp/term/konsole.el
index 7db3695f5d0..1aff9df29ea 100644
--- a/lisp/term/konsole.el
+++ b/lisp/term/konsole.el
@@ -1,5 +1,5 @@
;;; konsole.el --- terminal initialization for konsole -*- lexical-binding:t -*-
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
(require 'term/xterm)
diff --git a/lisp/term/linux.el b/lisp/term/linux.el
index f24af3f1344..491649a053d 100644
--- a/lisp/term/linux.el
+++ b/lisp/term/linux.el
@@ -13,9 +13,13 @@
;; Compositions confuse cursor movement.
(setq-default auto-composition-mode "linux")
+ ;; Ensure additional terminal setup is done when `gpm-mouse-mode' is
+ ;; enabled.
+ (ignore-errors (when gpm-mouse-mode (gpm-mouse-mode 1)))
+
;; Don't translate ESC TAB to backtab as directed by ncurses-6.3.
(define-key input-decode-map "\e\t" nil)
-
+
;; Make Latin-1 input characters work, too.
;; Meta will continue to work, because the kernel turns that into Escape.
diff --git a/lisp/term/news.el b/lisp/term/news.el
index f2fd814d438..dfcfd8ac04b 100644
--- a/lisp/term/news.el
+++ b/lisp/term/news.el
@@ -1,6 +1,6 @@
;;; news.el --- keypad and function key bindings for the Sony NEWS keyboard -*- lexical-binding: t -*-
-;; Copyright (C) 1989, 1993, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1989, 1993, 2001-2024 Free Software Foundation, Inc.
;; Author: FSF
;; Keywords: terminals
diff --git a/lisp/term/ns-win.el b/lisp/term/ns-win.el
index 7525b9321ca..2a29457133e 100644
--- a/lisp/term/ns-win.el
+++ b/lisp/term/ns-win.el
@@ -1,6 +1,6 @@
;;; ns-win.el --- lisp side of interface with NeXT/Open/GNUstep/macOS window system -*- lexical-binding: t -*-
-;; Copyright (C) 1993-1994, 2005-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1993-1994, 2005-2024 Free Software Foundation, Inc.
;; Authors: Carl Edman
;; Christian Limpach
@@ -520,11 +520,12 @@ string dropped into the current buffer."
(goto-char (posn-point (event-start event)))
(cond ((or (memq 'ns-drag-operation-generic operations)
(memq 'ns-drag-operation-copy operations))
- ;; Perform the default/copy action.
- (dolist (data objects)
- (dnd-handle-one-url window 'private (if (eq type 'file)
- (concat "file:" data)
- data))))
+ (let ((urls (if (eq type 'file) (mapcar
+ (lambda (file)
+ (concat "file:" file))
+ objects)
+ objects)))
+ (dnd-handle-multiple-urls window urls 'private)))
(t
;; Insert the text as is.
(dnd-insert-text window 'private string))))))
diff --git a/lisp/term/pc-win.el b/lisp/term/pc-win.el
index 589a2dc85e0..02ad6b85c37 100644
--- a/lisp/term/pc-win.el
+++ b/lisp/term/pc-win.el
@@ -1,6 +1,6 @@
;;; pc-win.el --- setup support for `PC windows' (whatever that is) -*- lexical-binding:t -*-
-;; Copyright (C) 1994, 1996-1997, 1999, 2001-2023 Free Software
+;; Copyright (C) 1994, 1996-1997, 1999, 2001-2024 Free Software
;; Foundation, Inc.
;; Author: Morten Welinder <terra@diku.dk>
diff --git a/lisp/term/pgtk-win.el b/lisp/term/pgtk-win.el
index f2552d3b057..7999d348082 100644
--- a/lisp/term/pgtk-win.el
+++ b/lisp/term/pgtk-win.el
@@ -1,6 +1,6 @@
;;; pgtk-win.el --- parse relevant switches and set up for Pure-GTK -*- lexical-binding: t -*-
-;; Copyright (C) 1995, 2001-2020, 2022-2023 Free Software Foundation,
+;; Copyright (C) 1995, 2001-2020, 2022-2024 Free Software Foundation,
;; Inc.
;; Author: FSF
@@ -48,45 +48,6 @@
(declare-function pgtk-use-im-context "pgtkim.c")
-(defun pgtk-drag-n-drop (event &optional new-frame force-text)
- "Edit the files listed in the drag-n-drop EVENT.
-Switch to a buffer editing the last file dropped."
- (interactive "e")
- (let* ((window (posn-window (event-start event)))
- (arg (car (cdr (cdr event))))
- (type (car arg))
- (data (car (cdr arg)))
- (url-or-string (cond ((eq type 'file)
- (concat "file:" data))
- (t data))))
- (set-frame-selected-window nil window)
- (when new-frame
- (select-frame (make-frame)))
- (raise-frame)
- (setq window (selected-window))
- (if force-text
- (dnd-insert-text window 'private data)
- (dnd-handle-one-url window 'private url-or-string))))
-
-(defun pgtk-drag-n-drop-other-frame (event)
- "Edit the files listed in the drag-n-drop EVENT, in other frames.
-May create new frames, or reuse existing ones. The frame editing
-the last file dropped is selected."
- (interactive "e")
- (pgtk-drag-n-drop event t))
-
-(defun pgtk-drag-n-drop-as-text (event)
- "Drop the data in EVENT as text."
- (interactive "e")
- (pgtk-drag-n-drop event nil t))
-
-(defun pgtk-drag-n-drop-as-text-other-frame (event)
- "Drop the data in EVENT as text in a new frame."
- (interactive "e")
- (pgtk-drag-n-drop event t t))
-
-(global-set-key [drag-n-drop] 'pgtk-drag-n-drop)
-
(defun pgtk-suspend-error ()
"Don't allow suspending if any of the frames are PGTK frames."
(if (memq 'pgtk (mapcar 'window-system (frame-list)))
@@ -392,7 +353,6 @@ Users should not call this function; see `device-class' instead."
(defvaralias 'x-gtk-use-system-tooltips 'use-system-tooltips)
-
(define-key special-event-map [drag-n-drop] #'pgtk-dnd-handle-drag-n-drop-event)
(add-hook 'after-make-frame-functions #'pgtk-dnd-init-frame)
diff --git a/lisp/term/rxvt.el b/lisp/term/rxvt.el
index af1ea36ff7d..b16cf5ec189 100644
--- a/lisp/term/rxvt.el
+++ b/lisp/term/rxvt.el
@@ -1,6 +1,6 @@
;;; rxvt.el --- define function key sequences and standard colors for rxvt -*- lexical-binding: t -*-
-;; Copyright (C) 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2024 Free Software Foundation, Inc.
;; Author: Eli Zaretskii
;; Keywords: terminals
diff --git a/lisp/term/screen.el b/lisp/term/screen.el
index 912664f2bae..8ca0755d545 100644
--- a/lisp/term/screen.el
+++ b/lisp/term/screen.el
@@ -1,5 +1,5 @@
;;; screen.el --- terminal initialization for screen and tmux -*- lexical-binding: t -*-
-;; Copyright (C) 1995, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1995, 2001-2024 Free Software Foundation, Inc.
(require 'term/xterm)
diff --git a/lisp/term/st.el b/lisp/term/st.el
index 334acdba560..ba10134289f 100644
--- a/lisp/term/st.el
+++ b/lisp/term/st.el
@@ -1,6 +1,6 @@
;;; st.el --- terminal initialization for st -*- lexical-binding:t -*-
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
;;; Commentary:
diff --git a/lisp/term/sun.el b/lisp/term/sun.el
index 2189c394bfc..f9dc0ba5dd1 100644
--- a/lisp/term/sun.el
+++ b/lisp/term/sun.el
@@ -1,6 +1,6 @@
;;; sun.el --- keybinding for standard default sunterm keys -*- lexical-binding: t -*-
-;; Copyright (C) 1987, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1987, 2001-2024 Free Software Foundation, Inc.
;; Author: Jeff Peck <peck@sun.com>
;; Keywords: terminals
diff --git a/lisp/term/tmux.el b/lisp/term/tmux.el
index 5dba3aa4ebe..3776367b7ae 100644
--- a/lisp/term/tmux.el
+++ b/lisp/term/tmux.el
@@ -1,5 +1,5 @@
;;; tmux.el --- terminal initialization for tmux -*- lexical-binding: t -*-
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
(require 'term/xterm)
diff --git a/lisp/term/tty-colors.el b/lisp/term/tty-colors.el
index cb7ff385ce7..0ffd06f9099 100644
--- a/lisp/term/tty-colors.el
+++ b/lisp/term/tty-colors.el
@@ -1,6 +1,6 @@
;;; tty-colors.el --- color support for character terminals -*- lexical-binding: t; -*-
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
;; Author: Eli Zaretskii
;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/term/tvi970.el b/lisp/term/tvi970.el
index 5f6e1a20f85..63598c20f9f 100644
--- a/lisp/term/tvi970.el
+++ b/lisp/term/tvi970.el
@@ -1,6 +1,6 @@
;;; tvi970.el --- terminal support for the Televideo 970 -*- lexical-binding: t -*-
-;; Copyright (C) 1992, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1992, 2001-2024 Free Software Foundation, Inc.
;; Author: Jim Blandy <jimb@occs.cs.oberlin.edu>
;; Keywords: terminals
diff --git a/lisp/term/vt100.el b/lisp/term/vt100.el
index 1275556b9cb..e8c7a03844d 100644
--- a/lisp/term/vt100.el
+++ b/lisp/term/vt100.el
@@ -1,6 +1,6 @@
;;; vt100.el --- define VT100 function key sequences in function-key-map -*- lexical-binding:t -*-
-;; Copyright (C) 1989, 1993, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1989, 1993, 2001-2024 Free Software Foundation, Inc.
;; Author: FSF
;; Keywords: terminals
diff --git a/lisp/term/w32-win.el b/lisp/term/w32-win.el
index c9e25f4f83d..9b696475c34 100644
--- a/lisp/term/w32-win.el
+++ b/lisp/term/w32-win.el
@@ -1,6 +1,6 @@
;;; w32-win.el --- parse switches controlling interface with W32 window system -*- lexical-binding: t -*-
-;; Copyright (C) 1993-1994, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1993-1994, 2001-2024 Free Software Foundation, Inc.
;; Author: Kevin Gallo
;; Keywords: terminals
@@ -117,12 +117,14 @@
(split-string (encode-coding-string f coding)
"/")
"/")))
- (dnd-handle-one-url window 'private
- (concat
- (if (eq system-type 'cygwin)
- "file://"
- "file:")
- file-name)))
+ ;; FIXME: is the W32 build capable only of receiving a single file
+ ;; from each drop?
+ (dnd-handle-multiple-urls window (list (concat
+ (if (eq system-type 'cygwin)
+ "file://"
+ "file:")
+ file-name))
+ 'private))
(defun w32-drag-n-drop (event &optional new-frame)
"Edit the files listed in the drag-n-drop EVENT.
diff --git a/lisp/term/w32console.el b/lisp/term/w32console.el
index 396d80040ed..129452e5439 100644
--- a/lisp/term/w32console.el
+++ b/lisp/term/w32console.el
@@ -1,6 +1,6 @@
;;; w32console.el --- Setup w32 console keys and colors. -*- lexical-binding: t; -*-
-;; Copyright (C) 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2024 Free Software Foundation, Inc.
;; Author: FSF
;; Keywords: terminals
diff --git a/lisp/term/wyse50.el b/lisp/term/wyse50.el
index 5fe3e7fce31..a0b403e4044 100644
--- a/lisp/term/wyse50.el
+++ b/lisp/term/wyse50.el
@@ -1,6 +1,6 @@
;;; wyse50.el --- terminal support code for Wyse 50 -*- lexical-binding: t -*-
-;; Copyright (C) 1989, 1993-1994, 2001-2023 Free Software Foundation,
+;; Copyright (C) 1989, 1993-1994, 2001-2024 Free Software Foundation,
;; Inc.
;; Author: Daniel Pfeiffer <occitan@esperanto.org>,
diff --git a/lisp/term/x-win.el b/lisp/term/x-win.el
index a9af6bd6d1c..98dd576fea2 100644
--- a/lisp/term/x-win.el
+++ b/lisp/term/x-win.el
@@ -1,6 +1,6 @@
;;; x-win.el --- parse relevant switches and set up for X -*- lexical-binding:t -*-
-;; Copyright (C) 1993-1994, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1993-1994, 2001-2024 Free Software Foundation, Inc.
;; Author: FSF
;; Keywords: terminals, i18n
diff --git a/lisp/term/xterm.el b/lisp/term/xterm.el
index 295ef2b3f4c..82f9a60b53b 100644
--- a/lisp/term/xterm.el
+++ b/lisp/term/xterm.el
@@ -1,6 +1,6 @@
;;; xterm.el --- define function key sequences and standard colors for xterm -*- lexical-binding: t -*-
-;; Copyright (C) 1995, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1995, 2001-2024 Free Software Foundation, Inc.
;; Author: FSF
;; Keywords: terminals
@@ -725,7 +725,7 @@ Return the pasted text as a string."
;; `tty-set-up-initial-frame-faces' only once, but that
;; caused the light background faces to be computed
;; incorrectly. See:
- ;; http://permalink.gmane.org/gmane.emacs.devel/119627
+ ;; https://lists.gnu.org/r/emacs-devel/2010-01/msg00439.html
(when recompute-faces
(tty-set-up-initial-frame-faces))))))
diff --git a/lisp/textmodes/artist.el b/lisp/textmodes/artist.el
index 08613db600c..b6029dc1ffd 100644
--- a/lisp/textmodes/artist.el
+++ b/lisp/textmodes/artist.el
@@ -1,6 +1,6 @@
;;; artist.el --- draw ascii graphics with your mouse -*- lexical-binding: t -*-
-;; Copyright (C) 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2000-2024 Free Software Foundation, Inc.
;; Author: Tomas Abrahamsson <tab@lysator.liu.se>
;; Keywords: mouse
diff --git a/lisp/textmodes/bib-mode.el b/lisp/textmodes/bib-mode.el
index 7037cabffc5..ea5e02b25f6 100644
--- a/lisp/textmodes/bib-mode.el
+++ b/lisp/textmodes/bib-mode.el
@@ -1,6 +1,6 @@
;;; bib-mode.el --- major mode for editing bib files -*- lexical-binding: t -*-
-;; Copyright (C) 1989, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1989, 2001-2024 Free Software Foundation, Inc.
;; Author: Henry Kautz
;; (according to authors.el)
diff --git a/lisp/textmodes/bibtex-style.el b/lisp/textmodes/bibtex-style.el
index 649f1831558..78c53bfc37d 100644
--- a/lisp/textmodes/bibtex-style.el
+++ b/lisp/textmodes/bibtex-style.el
@@ -1,6 +1,6 @@
;;; bibtex-style.el --- Major mode for BibTeX Style files -*- lexical-binding: t -*-
-;; Copyright (C) 2005, 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2005, 2007-2024 Free Software Foundation, Inc.
;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
;; Keywords: tex
diff --git a/lisp/textmodes/bibtex.el b/lisp/textmodes/bibtex.el
index 394f80f47ee..a8e2f03bd70 100644
--- a/lisp/textmodes/bibtex.el
+++ b/lisp/textmodes/bibtex.el
@@ -1,6 +1,6 @@
;;; bibtex.el --- BibTeX mode for GNU Emacs -*- lexical-binding: t -*-
-;; Copyright (C) 1992-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1992-2024 Free Software Foundation, Inc.
;; Author: Stefan Schoef <schoef@offis.uni-oldenburg.de>
;; Bengt Martensson <bengt@mathematik.uni-Bremen.de>
@@ -1837,7 +1837,7 @@ Initialized by `bibtex-set-dialect'.")
(bibtex-font-lock-url) (bibtex-font-lock-crossref)
;; cite
,@(mapcar (lambda (matcher)
- `((lambda (bound) (bibtex-font-lock-cite ',matcher bound))))
+ `(,(lambda (bound) (bibtex-font-lock-cite matcher bound))))
bibtex-cite-matcher-alist))
"Default expressions to highlight in BibTeX mode.")
@@ -1845,7 +1845,7 @@ Initialized by `bibtex-set-dialect'.")
;; Assume that field names begin at the beginning of a line.
(concat "^[ \t]*"
(regexp-opt (delete-dups (mapcar #'caar bibtex-generate-url-list)) t)
- "[ \t]*=[ \t]*")
+ "[ \t\n]*=[ \t\n]*")
"Regexp for `bibtex-font-lock-url' derived from `bibtex-generate-url-list'.")
(defvar bibtex-string-empty-key nil
@@ -2760,7 +2760,7 @@ Formats current entry according to variable `bibtex-entry-format'."
(setq error-field-name
(car (last (aref alt-fields idx))))
(user-error "Alternative mandatory fields `%s' are missing"
- (mapconcat 'identity
+ (mapconcat #'identity
(reverse
(aref alt-expect idx))
", ")))
@@ -2768,7 +2768,7 @@ Formats current entry according to variable `bibtex-entry-format'."
(setq error-field-name
(car (last (aref alt-fields idx))))
(user-error "Fields `%s' are alternatives"
- (mapconcat 'identity
+ (mapconcat #'identity
(reverse
(aref alt-fields idx))
", ")))))))
@@ -3624,7 +3624,7 @@ if that value is non-nil.
(unless bibtex-parse-idle-timer
(setq bibtex-parse-idle-timer (run-with-idle-timer
bibtex-parse-keys-timeout t
- 'bibtex-parse-buffers-stealthily)))
+ #'bibtex-parse-buffers-stealthily)))
(setq-local paragraph-start "[ \f\n\t]*$")
(setq-local comment-column 0)
(setq-local defun-prompt-regexp "^[ \t]*@[[:alnum:]]+[ \t]*")
@@ -3829,7 +3829,7 @@ for the templates of `bibtex-entry', whereas entry validation performed by
(if (and (nth 3 elt)
(<= 0 (nth 3 elt)))
(push (nth 3 elt) alt-list)))
- (setq alt-list (sort alt-list '<))
+ (setq alt-list (sort alt-list #'<))
;; Skip aliases. If ELT is marked as "proper alternative", but all
;; alternatives for field ELT are aliases, we do not label ELT
;; as an alternative either.
@@ -4641,7 +4641,7 @@ Return t if test was successful, nil otherwise."
(let ((file (file-name-nondirectory (buffer-file-name)))
(dir default-directory)
(err-buf "*BibTeX validation errors*"))
- (setq error-list (sort error-list 'car-less-than-car))
+ (setq error-list (sort error-list #'car-less-than-car))
(with-current-buffer (get-buffer-create err-buf)
(setq default-directory dir)
(unless (eq major-mode 'compilation-mode) (compilation-mode))
@@ -4714,7 +4714,7 @@ Return t if test was successful, nil otherwise."
(delete-region (point-min) (point-max))
(insert (substitute-command-keys
"BibTeX mode command `bibtex-validate-globally'\n\n"))
- (dolist (err (sort error-list 'string-lessp)) (insert err))
+ (dolist (err (sort error-list #'string-lessp)) (insert err))
(set-buffer-modified-p nil))
(goto-char (point-min))
(forward-line 2)) ; first error message
diff --git a/lisp/textmodes/conf-mode.el b/lisp/textmodes/conf-mode.el
index 4d0dde7752b..5e1636033f6 100644
--- a/lisp/textmodes/conf-mode.el
+++ b/lisp/textmodes/conf-mode.el
@@ -1,6 +1,6 @@
;;; conf-mode.el --- Simple major mode for editing conf/ini/properties files -*- lexical-binding: t; -*-
-;; Copyright (C) 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2004-2024 Free Software Foundation, Inc.
;; Author: Daniel Pfeiffer <occitan@esperanto.org>
;; Keywords: conf ini windows java
diff --git a/lisp/textmodes/css-mode.el b/lisp/textmodes/css-mode.el
index f51edfb4c80..425f3ec8a30 100644
--- a/lisp/textmodes/css-mode.el
+++ b/lisp/textmodes/css-mode.el
@@ -1,6 +1,6 @@
;;; css-mode.el --- Major mode to edit CSS files -*- lexical-binding: t -*-
-;; Copyright (C) 2006-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2006-2024 Free Software Foundation, Inc.
;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
;; Maintainer: Simen Heggestøyl <simenheg@gmail.com>
diff --git a/lisp/textmodes/dns-mode.el b/lisp/textmodes/dns-mode.el
index 0167c757473..c801010d768 100644
--- a/lisp/textmodes/dns-mode.el
+++ b/lisp/textmodes/dns-mode.el
@@ -1,6 +1,6 @@
;;; dns-mode.el --- a mode for viewing/editing Domain Name System master files -*- lexical-binding: t -*-
-;; Copyright (C) 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2000-2024 Free Software Foundation, Inc.
;; Author: Simon Josefsson <simon@josefsson.org>
;; Keywords: DNS master zone file SOA comm
@@ -131,6 +131,8 @@ manually with \\[dns-mode-soa-increment-serial]."
(let ((table (make-syntax-table)))
(modify-syntax-entry ?\; "< " table)
(modify-syntax-entry ?\n "> " table)
+ (modify-syntax-entry ?\" "\"" table)
+ (modify-syntax-entry ?\\ "\\" table)
table)
"Syntax table in use in DNS master file buffers.")
diff --git a/lisp/textmodes/emacs-authors-mode.el b/lisp/textmodes/emacs-authors-mode.el
index 248234b1db1..4609f93869f 100644
--- a/lisp/textmodes/emacs-authors-mode.el
+++ b/lisp/textmodes/emacs-authors-mode.el
@@ -1,6 +1,6 @@
;;; emacs-authors-mode.el --- font-locking for etc/AUTHORS -*- lexical-binding: t -*-
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
;; Author: Stefan Kangas <stefankangas@gmail.com>
;; Keywords: internal
diff --git a/lisp/textmodes/emacs-news-mode.el b/lisp/textmodes/emacs-news-mode.el
index 773b07764aa..1dd017abb01 100644
--- a/lisp/textmodes/emacs-news-mode.el
+++ b/lisp/textmodes/emacs-news-mode.el
@@ -1,6 +1,6 @@
;;; emacs-news-mode.el --- major mode to edit and view the NEWS file -*- lexical-binding: t; -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;; Keywords: tools
diff --git a/lisp/textmodes/enriched.el b/lisp/textmodes/enriched.el
index 92be5a52bf2..385674f5b1a 100644
--- a/lisp/textmodes/enriched.el
+++ b/lisp/textmodes/enriched.el
@@ -1,9 +1,9 @@
;;; enriched.el --- read and save files in text/enriched format -*- lexical-binding: t; -*-
-;; Copyright (C) 1994-1996, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1994-1996, 2001-2024 Free Software Foundation, Inc.
;; Author: Boris Goldowsky <boris@gnu.org>
-;; Keywords: wp, faces
+;; Keywords: text, faces
;; This file is part of GNU Emacs.
@@ -146,7 +146,7 @@ them and their old values to `enriched-old-bindings'."
:type 'hook)
(defcustom enriched-allow-eval-in-display-props nil
- "If non-nil allow to evaluate arbitrary forms in display properties.
+ "If non-nil, allow evaluating arbitrary forms in display properties.
Enriched mode recognizes display properties of text stored using
an extension command to the text/enriched format, \"x-display\".
diff --git a/lisp/textmodes/fill.el b/lisp/textmodes/fill.el
index 2fde2ff6c4d..29c56f8feaf 100644
--- a/lisp/textmodes/fill.el
+++ b/lisp/textmodes/fill.el
@@ -1,10 +1,10 @@
;;; fill.el --- fill commands for Emacs -*- lexical-binding: t; -*-
-;; Copyright (C) 1985-1986, 1992, 1994-1997, 1999, 2001-2023 Free
+;; Copyright (C) 1985-1986, 1992, 1994-1997, 1999, 2001-2024 Free
;; Software Foundation, Inc.
;; Maintainer: emacs-devel@gnu.org
-;; Keywords: wp
+;; Keywords: text
;; Package: emacs
;; This file is part of GNU Emacs.
@@ -103,7 +103,7 @@ reinserts the fill prefix in each resulting line."
;; Added `%' for TeX comments.
;; RMS: deleted the code to match `1.' and `(1)'.
;; Update mail-mode's paragraph-separate if you change this.
- (purecopy "[ \t]*\\([-–!|#%;>*·•‣⁃◦]+[ \t]*\\)*")
+ (purecopy "[-–!|#%;>*·•‣⁃◦ \t]*")
"Regexp to match text at start of line that constitutes indentation.
If Adaptive Fill mode is enabled, a prefix matching this pattern
on the first and second lines of a paragraph is used as the
diff --git a/lisp/textmodes/flyspell.el b/lisp/textmodes/flyspell.el
index 84c207b8a48..de59294e9f0 100644
--- a/lisp/textmodes/flyspell.el
+++ b/lisp/textmodes/flyspell.el
@@ -1,6 +1,6 @@
;;; flyspell.el --- On-the-fly spell checker -*- lexical-binding:t -*-
-;; Copyright (C) 1998, 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998, 2000-2024 Free Software Foundation, Inc.
;; Author: Manuel Serrano <Manuel.Serrano@sophia.inria.fr>
;; Maintainer: emacs-devel@gnu.org
@@ -22,7 +22,7 @@
;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
;;; Commentary:
-;;
+
;; Flyspell is a minor Emacs mode performing on-the-fly spelling
;; checking.
;;
@@ -33,8 +33,7 @@
;; M-x flyspell-prog-mode.
;; In that mode only text inside comments and strings is checked.
;;
-;; Some user variables control the behavior of flyspell. They are
-;; those defined under the `User configuration' comment.
+;; Use `M-x customize-group RET flyspell RET' to customize flyspell.
;;; Code:
@@ -411,18 +410,6 @@ like <img alt=\"Some thing.\">."
(run-hooks 'flyspell-prog-mode-hook))
;;*---------------------------------------------------------------------*/
-;;* Overlay compatibility */
-;;*---------------------------------------------------------------------*/
-(autoload 'make-overlay "overlay" "Overlay compatibility kit." t)
-(autoload 'overlayp "overlay" "Overlay compatibility kit." t)
-(autoload 'overlays-in "overlay" "Overlay compatibility kit." t)
-(autoload 'delete-overlay "overlay" "Overlay compatibility kit." t)
-(autoload 'overlays-at "overlay" "Overlay compatibility kit." t)
-(autoload 'overlay-put "overlay" "Overlay compatibility kit." t)
-(autoload 'overlay-get "overlay" "Overlay compatibility kit." t)
-(autoload 'previous-overlay-change "overlay" "Overlay compatibility kit." t)
-
-;;*---------------------------------------------------------------------*/
;;* The minor mode declaration. */
;;*---------------------------------------------------------------------*/
(defvar-keymap flyspell-mouse-map
@@ -529,10 +516,10 @@ in your init file.
:group 'flyspell
(if flyspell-mode
(condition-case err
- (flyspell-mode-on (called-interactively-p 'interactive))
+ (flyspell--mode-on (called-interactively-p 'interactive))
(error (message "Error enabling Flyspell mode:\n%s" (cdr err))
(flyspell-mode -1)))
- (flyspell-mode-off)))
+ (flyspell--mode-off)))
;;;###autoload
(defun turn-on-flyspell ()
@@ -597,14 +584,14 @@ in your init file.
(kill-local-variable 'flyspell-word-cache-word))))
;; Make sure we flush our caches when needed. Do it here rather than in
-;; flyspell-mode-on, since flyspell-region may be used without ever turning
+;; flyspell--mode-on, since flyspell-region may be used without ever turning
;; on flyspell-mode.
(add-hook 'ispell-kill-ispell-hook 'flyspell-kill-ispell-hook)
;;*---------------------------------------------------------------------*/
-;;* flyspell-mode-on ... */
+;;* flyspell--mode-on ... */
;;*---------------------------------------------------------------------*/
-(defun flyspell-mode-on (&optional show-msg)
+(defun flyspell--mode-on (&optional show-msg)
"Turn Flyspell mode on. Do not use this; use `flyspell-mode' instead.
If optional argument SHOW-MSG is non-nil, show a welcome message
@@ -612,7 +599,6 @@ if `flyspell-issue-message-flag' and `flyspell-issue-welcome-flag'
are both non-nil."
(ispell-set-spellchecker-params) ; Initialize variables and dicts alists
(setq ispell-highlight-face 'flyspell-incorrect)
- ;; local dictionaries setup
(or ispell-local-dictionary ispell-dictionary
(if flyspell-default-dictionary
(ispell-change-dictionary flyspell-default-dictionary)))
@@ -622,24 +608,16 @@ are both non-nil."
;; Pass the `force' argument for the case where flyspell was active already
;; but the buffer's local-defs have been edited.
(flyspell-accept-buffer-local-defs 'force)
- ;; we put the `flyspell-delayed' property on some commands
(flyspell-delay-commands)
- ;; we put the `flyspell-deplacement' property on some commands
(flyspell-deplacement-commands)
- ;; we bound flyspell action to post-command hook
(add-hook 'post-command-hook (function flyspell-post-command-hook) t t)
- ;; we bound flyspell action to pre-command hook
(add-hook 'pre-command-hook (function flyspell-pre-command-hook) t t)
- ;; we bound flyspell action to after-change hook
(add-hook 'after-change-functions 'flyspell-after-change-function nil t)
- ;; we bound flyspell action to hack-local-variables-hook
(add-hook 'hack-local-variables-hook
(function flyspell-hack-local-variables-hook) t t)
- ;; set flyspell-generic-check-word-predicate based on the major mode
(let ((mode-predicate (get major-mode 'flyspell-mode-predicate)))
(if mode-predicate
(setq flyspell-generic-check-word-predicate mode-predicate)))
- ;; the welcome message
(if (and flyspell-issue-message-flag
flyspell-issue-welcome-flag
show-msg)
@@ -726,23 +704,19 @@ has been used, the current word is not checked."
(setq flyspell-pre-column (current-column)))
;;*---------------------------------------------------------------------*/
-;;* flyspell-mode-off ... */
+;;* flyspell--mode-off ... */
;;*---------------------------------------------------------------------*/
;;;###autoload
-(defun flyspell-mode-off ()
+(defun flyspell--mode-off ()
"Turn Flyspell mode off."
- ;; We remove the hooks.
(remove-hook 'post-command-hook (function flyspell-post-command-hook) t)
(remove-hook 'pre-command-hook (function flyspell-pre-command-hook) t)
(remove-hook 'after-change-functions 'flyspell-after-change-function t)
(remove-hook 'hack-local-variables-hook
(function flyspell-hack-local-variables-hook) t)
- ;; We remove all the flyspell highlightings.
(flyspell-delete-all-overlays)
- ;; We have to erase pre cache variables.
(setq flyspell-pre-buffer nil)
(setq flyspell-pre-point nil)
- ;; We mark the mode as killed.
(setq flyspell-mode nil))
;;*---------------------------------------------------------------------*/
@@ -2381,6 +2355,9 @@ This function is meant to be added to `flyspell-incorrect-hook'."
(defun flyspell-change-abbrev (table old new)
(set (abbrev-symbol old table) new))
+(define-obsolete-function-alias 'flyspell-mode-on 'flyspell--mode-on "30.1")
+(define-obsolete-function-alias 'flyspell-mode-off 'flyspell--mode-off "30.1")
+
(provide 'flyspell)
;;; flyspell.el ends here
diff --git a/lisp/textmodes/glyphless-mode.el b/lisp/textmodes/glyphless-mode.el
index 99bbb2769e4..6f8363a3b67 100644
--- a/lisp/textmodes/glyphless-mode.el
+++ b/lisp/textmodes/glyphless-mode.el
@@ -1,6 +1,6 @@
;;; glyphless-mode.el --- minor mode for displaying glyphless characters -*- lexical-binding: t; -*-
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
;; Maintainer: emacs-devel@gnu.org
@@ -30,7 +30,6 @@ The value can be any of the groups supported by
`all', for all glyphless characters."
:version "29.1"
:type '(repeat (choice (const :tag "All" all)
- (const :tag "No font" no-font)
(const :tag "C0 Control" c0-control)
(const :tag "C1 Control" c1-control)
(const :tag "Format Control" format-control)
diff --git a/lisp/textmodes/html-ts-mode.el b/lisp/textmodes/html-ts-mode.el
index 4c1f410a7ef..301f3e8791c 100644
--- a/lisp/textmodes/html-ts-mode.el
+++ b/lisp/textmodes/html-ts-mode.el
@@ -1,6 +1,6 @@
;;; html-ts-mode.el --- tree-sitter support for HTML -*- lexical-binding: t; -*-
-;; Copyright (C) 2023 Free Software Foundation, Inc.
+;; Copyright (C) 2023-2024 Free Software Foundation, Inc.
;; Author : Theodor Thornhill <theo@thornhill.no>
;; Maintainer : Theodor Thornhill <theo@thornhill.no>
@@ -94,10 +94,6 @@ Return nil if there is no name or if NODE is not a defun node."
(treesit-parser-create 'html)
- ;; Comments.
- (setq-local treesit-text-type-regexp
- (regexp-opt '("comment" "text")))
-
;; Indent.
(setq-local treesit-simple-indent-rules html-ts-mode--indent-rules)
@@ -106,13 +102,14 @@ Return nil if there is no name or if NODE is not a defun node."
(setq-local treesit-defun-name-function #'html-ts-mode--defun-name)
- (setq-local treesit-sentence-type-regexp "tag")
-
- (setq-local treesit-sexp-type-regexp
- (regexp-opt '("element"
- "text"
- "attribute"
- "value")))
+ (setq-local treesit-thing-settings
+ `((html
+ (sexp ,(regexp-opt '("element"
+ "text"
+ "attribute"
+ "value")))
+ (sentence "tag")
+ (text ,(regexp-opt '("comment" "text"))))))
;; Font-lock.
(setq-local treesit-font-lock-settings html-ts-mode--font-lock-settings)
diff --git a/lisp/textmodes/ispell.el b/lisp/textmodes/ispell.el
index 97c4ce9f32d..17af1f1d926 100644
--- a/lisp/textmodes/ispell.el
+++ b/lisp/textmodes/ispell.el
@@ -1,6 +1,6 @@
;;; ispell.el --- interface to spell checkers -*- lexical-binding:t -*-
-;; Copyright (C) 1994-1995, 1997-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1994-1995, 1997-2024 Free Software Foundation, Inc.
;; Author: Ken Stevens <k.stevens@ieee.org>
@@ -522,7 +522,12 @@ re-start Emacs."
"[^A-Za-z\345\344\366\351\340\374\350\346\370\347\305\304\326\311\300\334\310\306\330\307]"
"[']" nil ("-C") "~list" iso-8859-1)
("hebrew" "[\340\341\342\343\344\345\346\347\350\351\353\352\354\356\355\360\357\361\362\364\363\367\366\365\370\371\372]" "[^\340\341\342\343\344\345\346\347\350\351\353\352\354\356\355\360\357\361\362\364\363\367\366\365\370\371\372]" "" nil ("-B") nil cp1255))
- "Base value for `ispell-dictionary-alist'.")
+ "Base value for `ispell-dictionary-alist'.
+
+Note that when the speller program is \"aspell\" or \"hunspell\",
+some parts of the database, notably OTHERCHARS, will be overridden
+by parsing the dictionary data files, see `ispell-aspell-find-dictionary'
+and `ispell-parse-hunspell-affix-file'.")
(defvar ispell-dictionary-alist nil
"An alist of dictionaries and their associated parameters.
@@ -577,7 +582,11 @@ when the language uses non-ASCII characters.
Note that with \"ispell\" as the speller, the CASECHARS and
OTHERCHARS slots of the alist should contain the same character
set as casechars and otherchars in the LANGUAGE.aff file \(e.g.,
-english.aff). Aspell and Hunspell don't have this limitation.")
+english.aff). Aspell and Hunspell don't have this limitation.
+Also, when the speller program is \"aspell\" or \"hunspell\",
+some parts of the database, notably OTHERCHARS, will be determined
+by parsing the dictionary data files, see `ispell-aspell-find-dictionary'
+and `ispell-parse-hunspell-affix-file'.")
(defvar ispell-really-aspell nil
"Non-nil if we can use Aspell extensions.")
@@ -1747,6 +1756,7 @@ Ispell is then restarted because the local words could conflict.")
(defvar-local ispell-buffer-session-localwords nil
"List of words accepted for session in this buffer.")
+(put 'ispell-buffer-session-localwords 'safe-local-variable #'list-of-strings-p)
(defvar ispell-parser 'use-mode-name
"Indicates whether ispell should parse the current buffer as TeX Code.
@@ -2523,9 +2533,9 @@ this function signals an error."
(if lookup-dict
(unless (file-readable-p lookup-dict)
- (error "lookup-words error: Unreadable or missing plain word-list %s."
+ (error "ispell-lookup-words: Unreadable or missing plain word-list %s"
lookup-dict))
- (error (concat "lookup-words error: No plain word-list found at system"
+ (error (concat "ispell-lookup-words: No plain word-list found at system"
"default locations. "
"Customize `ispell-alternate-dictionary' to set yours.")))
@@ -3679,6 +3689,27 @@ If APPEND is non-nil, don't erase previous debugging output."
(if (>= column (- (window-width) 2))
(scroll-left (max (- column (window-width) -3) 10)))))))
+;;;###autoload
+(defun ispell-completion-at-point ()
+ "Word completion function for use in `completion-at-point-functions'."
+ (pcase (bounds-of-thing-at-point 'word)
+ (`(,beg . ,end)
+ (when (and (< beg (point)) (<= (point) end))
+ (let* ((word (buffer-substring-no-properties beg end))
+ (len (length word))
+ (inhibit-message t)
+ (all (cons word (ispell-lookup-words word)))
+ (cur all))
+ (while cur
+ (unless (string-prefix-p word (car cur))
+ (setcar cur (concat word (substring (car cur) len))))
+ (while (when-let ((next (cadr cur)))
+ (not (string-prefix-p word next t)))
+ (setcdr cur (cddr cur)))
+ (setq cur (cdr cur)))
+ (list beg end (cdr all)
+ :exclusive 'no))))))
+
;;; Interactive word completion.
;; Forces "previous-word" processing. Do we want to make this selectable?
@@ -3695,7 +3726,6 @@ This command uses a word-list file specified
by `ispell-alternate-dictionary' or by `ispell-complete-word-dict';
if none of those name an existing word-list file, this command
signals an error."
- ;; FIXME: completion-at-point-function.
(interactive "P")
(let ((case-fold-search-val case-fold-search)
(word (ispell-get-word nil "\\*")) ; force "previous-word" processing.
@@ -3973,7 +4003,8 @@ You can bind this to the key C-c i in GNUS or mail by adding to
(point-max)))
(t (min (point-max) (funcall ispell-message-text-end))))))
(default-prefix ; Vanilla cite prefix (just used for cite-regexp)
- (if (ispell-non-empty-string mail-yank-prefix)
+ (if mail-yank-prefix
+ (ispell-non-empty-string mail-yank-prefix)
" \\|\t"))
(cite-regexp ;Prefix of quoted text
(cond
diff --git a/lisp/textmodes/less-css-mode.el b/lisp/textmodes/less-css-mode.el
index 2e4d71fb631..198f067f1d8 100644
--- a/lisp/textmodes/less-css-mode.el
+++ b/lisp/textmodes/less-css-mode.el
@@ -1,6 +1,6 @@
;;; less-css-mode.el --- Major mode for editing Less CSS files -*- lexical-binding: t; -*-
-;; Copyright (C) 2011-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2011-2024 Free Software Foundation, Inc.
;; Author: Steve Purcell <steve@sanityinc.com>
;; Maintainer: Simen Heggestøyl <simenheg@gmail.com>
diff --git a/lisp/textmodes/makeinfo.el b/lisp/textmodes/makeinfo.el
index 16821944145..7e08111fddd 100644
--- a/lisp/textmodes/makeinfo.el
+++ b/lisp/textmodes/makeinfo.el
@@ -1,6 +1,6 @@
;;; makeinfo.el --- run makeinfo conveniently -*- lexical-binding: t; -*-
-;; Copyright (C) 1991, 1993, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1991, 1993, 2001-2024 Free Software Foundation, Inc.
;; Author: Robert J. Chassell
;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/textmodes/mhtml-mode.el b/lisp/textmodes/mhtml-mode.el
index ebb55ec279c..0b5c6756ab9 100644
--- a/lisp/textmodes/mhtml-mode.el
+++ b/lisp/textmodes/mhtml-mode.el
@@ -1,8 +1,8 @@
;;; mhtml-mode.el --- HTML editing mode that handles CSS and JS -*- lexical-binding:t -*-
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
-;; Keywords: wp, hypermedia, comm, languages
+;; Keywords: text, hypermedia, comm, languages
;; This file is part of GNU Emacs.
diff --git a/lisp/textmodes/nroff-mode.el b/lisp/textmodes/nroff-mode.el
index 7374fa63bec..026d37f1b74 100644
--- a/lisp/textmodes/nroff-mode.el
+++ b/lisp/textmodes/nroff-mode.el
@@ -1,9 +1,9 @@
;;; nroff-mode.el --- GNU Emacs major mode for editing nroff source -*- lexical-binding: t -*-
-;; Copyright (C) 1985-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1985-2024 Free Software Foundation, Inc.
;; Maintainer: emacs-devel@gnu.org
-;; Keywords: wp
+;; Keywords: text
;; This file is part of GNU Emacs.
diff --git a/lisp/textmodes/page-ext.el b/lisp/textmodes/page-ext.el
index 446112bce27..f5f59adb0cf 100644
--- a/lisp/textmodes/page-ext.el
+++ b/lisp/textmodes/page-ext.el
@@ -1,10 +1,10 @@
;;; page-ext.el --- extended page handling commands -*- lexical-binding:t -*-
-;; Copyright (C) 1990-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1990-2024 Free Software Foundation, Inc.
;; Author: Robert J. Chassell <bob@gnu.org>
;; (according to ack.texi)
-;; Keywords: wp data
+;; Keywords: text data
;; This file is part of GNU Emacs.
diff --git a/lisp/textmodes/page.el b/lisp/textmodes/page.el
index 86a2762b0ee..e8621ee0383 100644
--- a/lisp/textmodes/page.el
+++ b/lisp/textmodes/page.el
@@ -1,9 +1,9 @@
;;; page.el --- page motion commands for Emacs -*- lexical-binding: t; -*-
-;; Copyright (C) 1985, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1985, 2001-2024 Free Software Foundation, Inc.
;; Maintainer: emacs-devel@gnu.org
-;; Keywords: wp convenience
+;; Keywords: text convenience
;; Package: emacs
;; This file is part of GNU Emacs.
diff --git a/lisp/textmodes/paragraphs.el b/lisp/textmodes/paragraphs.el
index fd28bfe8016..af99a96e045 100644
--- a/lisp/textmodes/paragraphs.el
+++ b/lisp/textmodes/paragraphs.el
@@ -1,10 +1,10 @@
;;; paragraphs.el --- paragraph and sentence parsing -*- lexical-binding: t -*-
-;; Copyright (C) 1985-1987, 1991, 1994-1997, 1999-2023 Free Software
+;; Copyright (C) 1985-1987, 1991, 1994-1997, 1999-2024 Free Software
;; Foundation, Inc.
;; Maintainer: emacs-devel@gnu.org
-;; Keywords: wp
+;; Keywords: text
;; Package: emacs
;; This file is part of GNU Emacs.
diff --git a/lisp/textmodes/picture.el b/lisp/textmodes/picture.el
index f98c3963b6f..adb06cb6a29 100644
--- a/lisp/textmodes/picture.el
+++ b/lisp/textmodes/picture.el
@@ -1,10 +1,10 @@
;;; picture.el --- "Picture mode" -- editing using quarter-plane screen model -*- lexical-binding: t -*-
-;; Copyright (C) 1985-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1985-2024 Free Software Foundation, Inc.
;; Author: K. Shane Hartman
;; Maintainer: emacs-devel@gnu.org
-;; Keywords: convenience wp
+;; Keywords: convenience text
;; This file is part of GNU Emacs.
diff --git a/lisp/textmodes/pixel-fill.el b/lisp/textmodes/pixel-fill.el
index 9fd62d98fd6..25c0b46cee9 100644
--- a/lisp/textmodes/pixel-fill.el
+++ b/lisp/textmodes/pixel-fill.el
@@ -1,6 +1,6 @@
;;; pixel-fill.el --- variable pitch filling functions -*- lexical-binding: t; -*-
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
;; Maintainer: emacs-devel@gnu.org
;; Keywords: filling
diff --git a/lisp/textmodes/po.el b/lisp/textmodes/po.el
index f9d2198b7fc..a1ac5005bc0 100644
--- a/lisp/textmodes/po.el
+++ b/lisp/textmodes/po.el
@@ -1,6 +1,6 @@
;;; po.el --- basic support of PO translation files -*- lexical-binding:t -*-
-;; Copyright (C) 1995-1998, 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1995-1998, 2000-2024 Free Software Foundation, Inc.
;; Authors: François Pinard <pinard@iro.umontreal.ca>,
;; Greg McGary <gkm@magilla.cichlid.com>,
diff --git a/lisp/textmodes/refbib.el b/lisp/textmodes/refbib.el
index 8f187e745c8..dd548e00d9b 100644
--- a/lisp/textmodes/refbib.el
+++ b/lisp/textmodes/refbib.el
@@ -1,6 +1,6 @@
;;; refbib.el --- convert refer-style references to ones usable by Latex bib -*- lexical-binding: t; -*-
-;; Copyright (C) 1989, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1989, 2001-2024 Free Software Foundation, Inc.
;; Author: Henry Kautz <kautz@research.att.com>
;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/textmodes/refer.el b/lisp/textmodes/refer.el
index 9200c401226..0fbe4a30b11 100644
--- a/lisp/textmodes/refer.el
+++ b/lisp/textmodes/refer.el
@@ -1,6 +1,6 @@
;;; refer.el --- look up references in bibliography files -*- lexical-binding: t; -*-
-;; Copyright (C) 1992, 1996, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1992, 1996, 2001-2024 Free Software Foundation, Inc.
;; Author: Ashwin Ram <ashwin@cc.gatech.edu>
;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/textmodes/refill.el b/lisp/textmodes/refill.el
index bd8e7cd7435..bb6b6ebda0f 100644
--- a/lisp/textmodes/refill.el
+++ b/lisp/textmodes/refill.el
@@ -1,10 +1,10 @@
;;; refill.el --- `auto-fill' by refilling paragraphs on changes -*- lexical-binding: t -*-
-;; Copyright (C) 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2000-2024 Free Software Foundation, Inc.
;; Author: Dave Love <fx@gnu.org>
;; Maintainer: Miles Bader <miles@gnu.org>
-;; Keywords: wp
+;; Keywords: text
;; This file is part of GNU Emacs.
diff --git a/lisp/textmodes/reftex-auc.el b/lisp/textmodes/reftex-auc.el
index 680d9d28df9..1c8be18a06d 100644
--- a/lisp/textmodes/reftex-auc.el
+++ b/lisp/textmodes/reftex-auc.el
@@ -1,6 +1,6 @@
;;; reftex-auc.el --- RefTeX's interface to AUCTeX -*- lexical-binding: t; -*-
-;; Copyright (C) 1997-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997-2024 Free Software Foundation, Inc.
;; Author: Carsten Dominik <dominik@science.uva.nl>
;; Maintainer: auctex-devel@gnu.org
diff --git a/lisp/textmodes/reftex-cite.el b/lisp/textmodes/reftex-cite.el
index 6beae816257..f7b155874de 100644
--- a/lisp/textmodes/reftex-cite.el
+++ b/lisp/textmodes/reftex-cite.el
@@ -1,6 +1,6 @@
;;; reftex-cite.el --- creating citations with RefTeX -*- lexical-binding: t; -*-
-;; Copyright (C) 1997-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997-2024 Free Software Foundation, Inc.
;; Author: Carsten Dominik <dominik@science.uva.nl>
;; Maintainer: auctex-devel@gnu.org
@@ -566,7 +566,7 @@ If FORMAT is non-nil `format' entry accordingly."
(reftex-get-bib-field "booktitle" entry "in: %s"))
(t ""))))
(setq authors (reftex-truncate authors 30 t t))
- (when (reftex-use-fonts)
+ (when reftex-use-fonts
(put-text-property 0 (length key) 'face reftex-label-face
key)
(put-text-property 0 (length authors) 'face reftex-bib-author-face
@@ -609,7 +609,7 @@ If FORMAT is non-nil `format' entry accordingly."
(push text lines)
(setq text (mapconcat #'identity (nreverse lines) "\n "))
- (when (reftex-use-fonts)
+ (when reftex-use-fonts
(put-text-property 0 (length text) 'face reftex-bib-author-face text))
(concat key "\n " text "\n\n")))
diff --git a/lisp/textmodes/reftex-dcr.el b/lisp/textmodes/reftex-dcr.el
index c3ecea3acda..2c5e5cb7ce6 100644
--- a/lisp/textmodes/reftex-dcr.el
+++ b/lisp/textmodes/reftex-dcr.el
@@ -1,6 +1,6 @@
;;; reftex-dcr.el --- viewing cross references and citations with RefTeX -*- lexical-binding: t; -*-
-;; Copyright (C) 1997-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997-2024 Free Software Foundation, Inc.
;; Author: Carsten Dominik <dominik@science.uva.nl>
;; Maintainer: auctex-devel@gnu.org
diff --git a/lisp/textmodes/reftex-global.el b/lisp/textmodes/reftex-global.el
index b8b0ae6a061..0eaffec3b54 100644
--- a/lisp/textmodes/reftex-global.el
+++ b/lisp/textmodes/reftex-global.el
@@ -1,6 +1,6 @@
;;; reftex-global.el --- operations on entire documents with RefTeX -*- lexical-binding: t; -*-
-;; Copyright (C) 1997-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997-2024 Free Software Foundation, Inc.
;; Author: Carsten Dominik <dominik@science.uva.nl>
;; Maintainer: auctex-devel@gnu.org
diff --git a/lisp/textmodes/reftex-index.el b/lisp/textmodes/reftex-index.el
index c8a45f068d1..a93afd63855 100644
--- a/lisp/textmodes/reftex-index.el
+++ b/lisp/textmodes/reftex-index.el
@@ -1,6 +1,6 @@
;;; reftex-index.el --- index support with RefTeX -*- lexical-binding: t; -*-
-;; Copyright (C) 1997-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997-2024 Free Software Foundation, Inc.
;; Author: Carsten Dominik <dominik@science.uva.nl>
;; Maintainer: auctex-devel@gnu.org
@@ -536,7 +536,7 @@ SPC=view TAB=goto RET=goto+hide [e]dit [q]uit [r]escan [f]ollow [?]Help
(nth 2 (car reftex-index-restriction-data))
reftex-index-restriction-indicator)))
- (if (reftex-use-fonts)
+ (if reftex-use-fonts
(put-text-property (point-min) (point)
'face reftex-index-header-face))
(cursor-intangible-mode 1)
@@ -567,7 +567,7 @@ SPC=view TAB=goto RET=goto+hide [e]dit [q]uit [r]escan [f]ollow [?]Help
(context-indent (concat indent " "))
(section-chars (mapcar #'identity reftex-index-section-letters))
(this-section-char 0)
- (font (reftex-use-fonts))
+ (font reftex-use-fonts)
(bor (car reftex-index-restriction-data))
(eor (nth 1 reftex-index-restriction-data))
(mouse-face
diff --git a/lisp/textmodes/reftex-parse.el b/lisp/textmodes/reftex-parse.el
index e2b9a0d983e..9694a1364d3 100644
--- a/lisp/textmodes/reftex-parse.el
+++ b/lisp/textmodes/reftex-parse.el
@@ -1,6 +1,6 @@
;;; reftex-parse.el --- parser functions for RefTeX -*- lexical-binding: t; -*-
-;; Copyright (C) 1997-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997-2024 Free Software Foundation, Inc.
;; Author: Carsten Dominik <dominik@science.uva.nl>
;; Maintainer: auctex-devel@gnu.org
diff --git a/lisp/textmodes/reftex-ref.el b/lisp/textmodes/reftex-ref.el
index d0a44eca17c..8dab7e6c48f 100644
--- a/lisp/textmodes/reftex-ref.el
+++ b/lisp/textmodes/reftex-ref.el
@@ -1,6 +1,6 @@
;;; reftex-ref.el --- code to create labels and references with RefTeX -*- lexical-binding: t; -*-
-;; Copyright (C) 1997-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997-2024 Free Software Foundation, Inc.
;; Author: Carsten Dominik <dominik@science.uva.nl>
;; Maintainer: auctex-devel@gnu.org
@@ -781,7 +781,6 @@ When called with 2 \\[universal-argument] prefix args, disable magic word recogn
(funcall errorf "Label %s not found" label))
found)))
-(defvar font-lock-mode)
(defun reftex-show-entry (beg-hlt end-hlt)
;; Show entry if point is hidden
(let* ((n (/ (window-height) 2))
diff --git a/lisp/textmodes/reftex-sel.el b/lisp/textmodes/reftex-sel.el
index 3c9f9ca94c8..fa36543daf4 100644
--- a/lisp/textmodes/reftex-sel.el
+++ b/lisp/textmodes/reftex-sel.el
@@ -1,6 +1,6 @@
;;; reftex-sel.el --- the selection modes for RefTeX -*- lexical-binding: t; -*-
-;; Copyright (C) 1997-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997-2024 Free Software Foundation, Inc.
;; Author: Carsten Dominik <dominik@science.uva.nl>
;; Maintainer: auctex-devel@gnu.org
@@ -204,7 +204,7 @@ During a selection process, these are the local bindings.
;; a used member near to this one, as a possible starting point.
;; XR-PREFIX is the prefix to put in front of labels.
;; TOC-BUFFER means this is to fill the toc buffer.
- (let* ((font (reftex-use-fonts))
+ (let* ((font reftex-use-fonts)
(cnt 0)
(index -1)
(toc-indent " ")
diff --git a/lisp/textmodes/reftex-toc.el b/lisp/textmodes/reftex-toc.el
index de49b7c6c70..1cc6e27e780 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-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997-2000, 2003-2024 Free Software Foundation, Inc.
;; Author: Carsten Dominik <dominik@science.uva.nl>
;; Maintainer: auctex-devel@gnu.org
@@ -263,7 +263,7 @@ SPC=view TAB=goto RET=goto+hide [q]uit [r]escan [l]abels [f]ollow [x]r [?]Help
------------------------------------------------------------------------------
" (abbreviate-file-name reftex-last-toc-master)))
- (if (reftex-use-fonts)
+ (if reftex-use-fonts
(put-text-property (point-min) (point) 'font-lock-face reftex-toc-header-face))
(cursor-intangible-mode 1)
(add-text-properties (point-min) (point)
diff --git a/lisp/textmodes/reftex-vars.el b/lisp/textmodes/reftex-vars.el
index 60ee40180d1..a0bc5c11ece 100644
--- a/lisp/textmodes/reftex-vars.el
+++ b/lisp/textmodes/reftex-vars.el
@@ -1,6 +1,6 @@
;;; reftex-vars.el --- configuration variables for RefTeX -*- lexical-binding: t; -*-
-;; Copyright (C) 1997-1999, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997-1999, 2001-2024 Free Software Foundation, Inc.
;; Author: Carsten Dominik <dominik@science.uva.nl>
;; Maintainer: auctex-devel@gnu.org
@@ -1156,7 +1156,7 @@ immediately offer the correct label menu - otherwise it will prompt you for
a label type. If you set this variable to nil, RefTeX will always prompt."
:group 'reftex-referencing-labels
:type 'boolean)
-;;;###autoload(put 'reftex-guess-label-type 'safe-local-variable (lambda (x) (memq x '(nil t))))
+;;;###autoload(put 'reftex-guess-label-type 'safe-local-variable #'booleanp)
(defcustom reftex-format-ref-function nil
"Function which produces the string to insert as a reference.
@@ -1933,7 +1933,6 @@ The value of this variable will only have any effect when
(defcustom reftex-use-fonts t
"Non-nil means, use fonts in *toc* and selection buffers.
-Font-lock must be loaded as well to actually get fontified display.
When changing this option, a rescan may be necessary to activate the change."
:group 'reftex-fontification-configurations
:type 'boolean)
diff --git a/lisp/textmodes/reftex.el b/lisp/textmodes/reftex.el
index 50bec6ef172..6974a4be4a7 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-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997-2000, 2003-2024 Free Software Foundation, Inc.
;; Author: Carsten Dominik <dominik@science.uva.nl>
;; Maintainer: auctex-devel@gnu.org
@@ -250,9 +250,6 @@ on the menu bar.
(defvar LaTeX-label-function)
(defvar tex-main-file)
(defvar outline-minor-mode)
-(defvar font-lock-mode)
-(defvar font-lock-keywords)
-(defvar font-lock-fontify-region-function)
;;; =========================================================================
;;;
@@ -442,7 +439,7 @@ the label information is recompiled on next use."
;; When it is a symbol, remove all other symbols
(and (symbolp entry)
(not (memq entry list))
- (setq list (reftex-remove-symbols-from-list list)))
+ (setq list (seq-remove #'symbolp list)))
;; Add to list unless already member
(unless (member entry list)
(setq reftex-tables-dirty t
@@ -1823,15 +1820,6 @@ When DIE is non-nil, throw an error if file not found."
(push (pop list) rtn))
(nreverse rtn)))
-(defun reftex-remove-symbols-from-list (list)
- ;; Remove all symbols from list
- (let (rtn)
- (while list
- (unless (symbolp (car list))
- (push (car list) rtn))
- (setq list (cdr list)))
- (nreverse rtn)))
-
(defun reftex-uniquify (list &optional sort)
;; Return a list of all strings in LIST, but each only once, keeping order
;; unless SORT is set (faster!).
@@ -2027,21 +2015,14 @@ IGNORE-WORDS List of words which should be removed from the string."
;;;
;;; Fontification and Highlighting
-(defun reftex-use-fonts ()
- ;; Return t if we can and want to use fonts.
- (and ; window-system
- reftex-use-fonts
- (featurep 'font-lock)))
-
(defun reftex-refontify ()
;; Return t if we need to refontify context
- (and (reftex-use-fonts)
+ (and reftex-use-fonts
(or (eq t reftex-refontify-context)
(and (eq 1 reftex-refontify-context)
;; Test of we use the font-lock version of x-symbol
(and (featurep 'x-symbol-tex) (not (boundp 'x-symbol-mode)))))))
-(defvar font-lock-defaults-computed)
(defun reftex-fontify-select-label-buffer (parent-buffer)
;; Fontify the `*RefTeX Select*' buffer. Buffer is temporarily renamed to
;; start with none-SPC char, because Font-Lock otherwise refuses operation.
@@ -2342,6 +2323,14 @@ Your bug report will be posted to the AUCTeX bug reporting list.
(define-obsolete-function-alias 'reftex-window-height #'window-height "30.1")
+(defun reftex-use-fonts ()
+ (declare (obsolete "use variable `reftex-use-fonts' instead." "30.1"))
+ reftex-use-fonts)
+
+(defun reftex-remove-symbols-from-list (list)
+ (declare (obsolete seq-remove "30.1"))
+ (seq-remove #'symbolp list))
+
(provide 'reftex)
;;; reftex.el ends here
diff --git a/lisp/textmodes/remember.el b/lisp/textmodes/remember.el
index 84a0185f7b5..c75a9b758e7 100644
--- a/lisp/textmodes/remember.el
+++ b/lisp/textmodes/remember.el
@@ -1,6 +1,6 @@
;;; remember.el --- a mode for quickly jotting down things to remember -*- lexical-binding: t; -*-
-;; Copyright (C) 1999-2001, 2003-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2001, 2003-2024 Free Software Foundation, Inc.
;; Author: John Wiegley <johnw@gnu.org>
;; Maintainer: emacs-devel@gnu.org
@@ -185,7 +185,7 @@
(defcustom remember-mode-hook nil
"Functions run upon entering `remember-mode'."
:type 'hook
- :options '(flyspell-mode turn-on-auto-fill org-remember-apply-template))
+ :options '(flyspell-mode turn-on-auto-fill))
(defcustom remember-in-new-frame nil
"Non-nil means use a separate frame for capturing remember data."
@@ -210,8 +210,7 @@ recorded somewhere by that function."
:options '(remember-store-in-mailbox
remember-append-to-file
remember-store-in-files
- remember-diary-extract-entries
- org-remember-handler))
+ remember-diary-extract-entries))
(defcustom remember-all-handler-functions nil
"If non-nil every function in `remember-handler-functions' is called."
@@ -235,7 +234,7 @@ recorded somewhere by that function."
(defcustom remember-annotation-functions '(buffer-file-name)
"Hook that returns an annotation to be inserted into the remember buffer."
:type 'hook
- :options '(org-remember-annotation buffer-file-name))
+ :options '(buffer-file-name))
(defvar remember-annotation nil
"Current annotation.")
diff --git a/lisp/textmodes/rst.el b/lisp/textmodes/rst.el
index 6108e80363c..2cd78943883 100644
--- a/lisp/textmodes/rst.el
+++ b/lisp/textmodes/rst.el
@@ -1,6 +1,6 @@
;;; rst.el --- Mode for viewing and editing reStructuredText-documents -*- lexical-binding: t -*-
-;; Copyright (C) 2003-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003-2024 Free Software Foundation, Inc.
;; Maintainer: Stefan Merten <stefan at merten-home dot de>
;; Author: Stefan Merten <stefan at merten-home dot de>,
@@ -170,8 +170,7 @@ When FUN is called match data is just set by `looking-at' and
point is at the beginning of the line. Return nil if moving
forward failed or otherwise the return value of FUN. Preserve
global match data, point, mark and current buffer."
- (unless (listp rst-re-args)
- (setq rst-re-args (list rst-re-args)))
+ (setq rst-re-args (ensure-list rst-re-args))
(unless fun
(setq fun #'identity))
(save-match-data
diff --git a/lisp/textmodes/sgml-mode.el b/lisp/textmodes/sgml-mode.el
index 27f3b2acd1c..0e15f7e6062 100644
--- a/lisp/textmodes/sgml-mode.el
+++ b/lisp/textmodes/sgml-mode.el
@@ -1,13 +1,13 @@
;;; sgml-mode.el --- SGML- and HTML-editing modes -*- lexical-binding:t -*-
-;; Copyright (C) 1992, 1995-1996, 1998, 2001-2023 Free Software
+;; Copyright (C) 1992, 1995-1996, 1998, 2001-2024 Free Software
;; Foundation, Inc.
;; Author: James Clark <jjc@jclark.com>
;; Maintainer: emacs-devel@gnu.org
;; Adapted-By: ESR, Daniel Pfeiffer <occitan@esperanto.org>,
;; F.Potorti@cnuce.cnr.it
-;; Keywords: wp, hypermedia, comm, languages
+;; Keywords: text, hypermedia, comm, languages
;; This file is part of GNU Emacs.
@@ -923,7 +923,7 @@ With prefix argument, only self insert."
"Skip to beginning of tag or matching opening tag if present.
With prefix argument ARG, repeat this ARG times.
Return non-nil if we skipped over matched tags."
- (interactive "p")
+ (interactive "^p")
;; FIXME: use sgml-get-context or something similar.
(let ((return t))
(while (>= arg 1)
@@ -1036,7 +1036,7 @@ an opening markup tag automatically updates the closing tag."
"Skip to end of tag or matching closing tag if present.
With prefix argument ARG, repeat this ARG times.
Return t if after a closing tag."
- (interactive "p")
+ (interactive "^p")
;; FIXME: Use sgml-get-context or something similar.
;; It currently might jump to an unrelated </P> if the <P>
;; we're skipping has no matching </P>.
diff --git a/lisp/textmodes/string-edit.el b/lisp/textmodes/string-edit.el
index c366611f26e..03be426ac25 100644
--- a/lisp/textmodes/string-edit.el
+++ b/lisp/textmodes/string-edit.el
@@ -1,6 +1,6 @@
;;; string-edit.el --- editing long strings -*- lexical-binding: t; -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/textmodes/table.el b/lisp/textmodes/table.el
index 50c3f461bcc..19c6a8d7c4f 100644
--- a/lisp/textmodes/table.el
+++ b/lisp/textmodes/table.el
@@ -1,8 +1,8 @@
;;; table.el --- create and edit WYSIWYG text based embedded tables -*- lexical-binding: t -*-
-;; Copyright (C) 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2000-2024 Free Software Foundation, Inc.
-;; Keywords: wp, convenience
+;; Keywords: text, convenience
;; Author: Takaaki Ota <Takaaki.Ota@am.sony.com>
;; Created: Sat Jul 08 2000 13:28:45 (PST)
diff --git a/lisp/textmodes/tex-mode.el b/lisp/textmodes/tex-mode.el
index 294c9792f39..8968d8ec23b 100644
--- a/lisp/textmodes/tex-mode.el
+++ b/lisp/textmodes/tex-mode.el
@@ -1,6 +1,6 @@
;;; tex-mode.el --- TeX, LaTeX, and SliTeX mode commands -*- lexical-binding:t -*-
-;; Copyright (C) 1985-1986, 1989, 1992, 1994-1999, 2001-2023 Free
+;; Copyright (C) 1985-1986, 1989, 1992, 1994-1999, 2001-2024 Free
;; Software Foundation, Inc.
;; Maintainer: emacs-devel@gnu.org
@@ -33,9 +33,6 @@
(require 'cl-lib)
(require 'skeleton))
-(defvar font-lock-comment-face)
-(defvar font-lock-doc-face)
-
(require 'shell)
(require 'compile)
@@ -2137,6 +2134,7 @@ If NOT-ALL is non-nil, save the `.dvi' file."
t "%r.pdf"))
'("pdf" "xe" "lua"))
((concat tex-command
+ " " tex-start-options
" " (if (< 0 (length tex-start-commands))
(shell-quote-argument tex-start-commands))
" %f")
@@ -2677,17 +2675,17 @@ This function is more useful than \\[tex-buffer] when you need the
The last line of the buffer is displayed on
line LINE of the window, or centered if LINE is nil."
(interactive "P")
- (let ((tex-shell (get-buffer "*tex-shell*"))
- (window))
+ (let ((tex-shell (get-buffer "*tex-shell*")))
(if (null tex-shell)
(message "No TeX output buffer")
- (setq window (display-buffer tex-shell display-tex-shell-buffer-action))
- (with-selected-window window
- (bury-buffer tex-shell)
- (goto-char (point-max))
- (recenter (if linenum
- (prefix-numeric-value linenum)
- (/ (window-height) 2)))))))
+ (when-let ((window
+ (display-buffer tex-shell display-tex-shell-buffer-action)))
+ (with-selected-window window
+ (bury-buffer tex-shell)
+ (goto-char (point-max))
+ (recenter (if linenum
+ (prefix-numeric-value linenum)
+ (/ (window-height) 2))))))))
(defcustom tex-print-file-extension ".dvi"
"The TeX-compiled file extension for viewing and printing.
diff --git a/lisp/textmodes/texinfmt.el b/lisp/textmodes/texinfmt.el
index c8c493f5e31..e144a9c34a0 100644
--- a/lisp/textmodes/texinfmt.el
+++ b/lisp/textmodes/texinfmt.el
@@ -1,6 +1,6 @@
;;; texinfmt.el --- format Texinfo files into Info files -*- lexical-binding: t; -*-
-;; Copyright (C) 1985-1986, 1988, 1990-1998, 2000-2023 Free Software
+;; Copyright (C) 1985-1986, 1988, 1990-1998, 2000-2024 Free Software
;; Foundation, Inc.
;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/textmodes/texinfo.el b/lisp/textmodes/texinfo.el
index bedf9ec92a5..bd371514df0 100644
--- a/lisp/textmodes/texinfo.el
+++ b/lisp/textmodes/texinfo.el
@@ -1,6 +1,6 @@
;;; texinfo.el --- major mode for editing Texinfo files -*- lexical-binding: t; -*-
-;; Copyright (C) 1985, 1988-1993, 1996-1997, 2000-2023 Free Software
+;; Copyright (C) 1985, 1988-1993, 1996-1997, 2000-2024 Free Software
;; Foundation, Inc.
;; Author: Robert J. Chassell
diff --git a/lisp/textmodes/texnfo-upd.el b/lisp/textmodes/texnfo-upd.el
index 5961f5960bd..f4815c37181 100644
--- a/lisp/textmodes/texnfo-upd.el
+++ b/lisp/textmodes/texnfo-upd.el
@@ -1,6 +1,6 @@
;;; texnfo-upd.el --- utilities for updating nodes and menus in Texinfo files -*- lexical-binding: t; -*-
-;; Copyright (C) 1989-1992, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1989-1992, 2001-2024 Free Software Foundation, Inc.
;; Author: Robert J. Chassell
;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/textmodes/text-mode.el b/lisp/textmodes/text-mode.el
index ccba1b063ab..7d3b47a9c03 100644
--- a/lisp/textmodes/text-mode.el
+++ b/lisp/textmodes/text-mode.el
@@ -1,10 +1,10 @@
;;; text-mode.el --- text mode, and its idiosyncratic commands -*- lexical-binding: t -*-
-;; Copyright (C) 1985, 1992, 1994, 2001-2023 Free Software Foundation,
+;; Copyright (C) 1985, 1992, 1994, 2001-2024 Free Software Foundation,
;; Inc.
;; Maintainer: emacs-devel@gnu.org
-;; Keywords: wp
+;; Keywords: text
;; Package: emacs
;; This file is part of GNU Emacs.
@@ -73,8 +73,20 @@
(defvar-keymap text-mode-map
:doc "Keymap for `text-mode'.
Many other modes, such as `mail-mode' and `outline-mode', inherit
-all the commands defined in this map."
- "C-M-i" #'ispell-complete-word)
+all the commands defined in this map.")
+
+(defcustom text-mode-meta-tab-ispell-complete-word nil
+ "Whether M-TAB invokes `ispell-complete-word' in Text mode.
+
+This user option only takes effect when you customize it in
+Custom or with `setopt', not with `setq'."
+ :group 'text
+ :type 'boolean
+ :version "30.1"
+ :set (lambda (sym val)
+ (if (set sym val)
+ (keymap-set text-mode-map "C-M-i" #'ispell-complete-word)
+ (keymap-unset text-mode-map "C-M-i" t))))
(easy-menu-define text-mode-menu text-mode-map
"Menu for `text-mode'."
@@ -131,7 +143,8 @@ Turning on Text mode runs the normal hook `text-mode-hook'."
;; Enable text conversion in this buffer.
(setq-local text-conversion-style t)
- (add-hook 'context-menu-functions 'text-mode-context-menu 10 t))
+ (add-hook 'context-menu-functions 'text-mode-context-menu 10 t)
+ (add-hook 'completion-at-point-functions #'ispell-completion-at-point 10 t))
(define-derived-mode paragraph-indent-text-mode text-mode "Parindent"
"Major mode for editing text, with leading spaces starting a paragraph.
diff --git a/lisp/textmodes/tildify.el b/lisp/textmodes/tildify.el
index 18ba83e86e8..8bdb41a07b1 100644
--- a/lisp/textmodes/tildify.el
+++ b/lisp/textmodes/tildify.el
@@ -1,11 +1,11 @@
;;; tildify.el --- adding hard spaces into texts -*- lexical-binding: t -*-
-;; Copyright (C) 1997-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997-2024 Free Software Foundation, Inc.
;; Author: Milan Zamazal <pdm@zamazal.org>
;; Michal Nazarewicz <mina86@mina86.com>
;; Version: 4.6.1
-;; Keywords: text, TeX, SGML, wp
+;; Keywords: text, TeX, SGML
;; This file is part of GNU Emacs.
diff --git a/lisp/textmodes/toml-ts-mode.el b/lisp/textmodes/toml-ts-mode.el
index 193c83f9aec..1ba410045f5 100644
--- a/lisp/textmodes/toml-ts-mode.el
+++ b/lisp/textmodes/toml-ts-mode.el
@@ -1,6 +1,6 @@
;;; toml-ts-mode.el --- tree-sitter support for TOML -*- lexical-binding: t; -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;; Author : Jostein Kjønigsen <jostein@kjonigsen.net>
;; Maintainer : Jostein Kjønigsen <jostein@kjonigsen.net>
diff --git a/lisp/textmodes/two-column.el b/lisp/textmodes/two-column.el
index 23dcc7e5945..806d6c5e709 100644
--- a/lisp/textmodes/two-column.el
+++ b/lisp/textmodes/two-column.el
@@ -1,10 +1,10 @@
;;; two-column.el --- minor mode for editing of two-column text -*- lexical-binding: t; -*-
-;; Copyright (C) 1992-1995, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1992-1995, 2001-2024 Free Software Foundation, Inc.
;; Author: Daniel Pfeiffer <occitan@esperanto.org>
;; Adapted-By: ESR, Daniel Pfeiffer
-;; Keywords: wp
+;; Keywords: text
;; This file is part of GNU Emacs.
diff --git a/lisp/textmodes/underline.el b/lisp/textmodes/underline.el
index b22652b6824..b1157febc24 100644
--- a/lisp/textmodes/underline.el
+++ b/lisp/textmodes/underline.el
@@ -1,9 +1,9 @@
;;; underline.el --- insert/remove underlining (done by overstriking) in Emacs -*- lexical-binding: t -*-
-;; Copyright (C) 1985, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1985, 2001-2024 Free Software Foundation, Inc.
;; Maintainer: emacs-devel@gnu.org
-;; Keywords: wp
+;; Keywords: text
;; This file is part of GNU Emacs.
diff --git a/lisp/textmodes/word-wrap-mode.el b/lisp/textmodes/word-wrap-mode.el
index 28bca7e27ea..86724a193db 100644
--- a/lisp/textmodes/word-wrap-mode.el
+++ b/lisp/textmodes/word-wrap-mode.el
@@ -1,6 +1,6 @@
;;; word-wrap-mode.el --- minor mode for `word-wrap' tweaks -*- lexical-binding: t; -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/textmodes/yaml-ts-mode.el b/lisp/textmodes/yaml-ts-mode.el
index dfa8d22fb34..2b57b384300 100644
--- a/lisp/textmodes/yaml-ts-mode.el
+++ b/lisp/textmodes/yaml-ts-mode.el
@@ -1,6 +1,6 @@
;;; yaml-ts-mode.el --- tree-sitter support for YAML -*- lexical-binding: t; -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;; Author : Randy Taylor <dev@rjt.dev>
;; Maintainer : Randy Taylor <dev@rjt.dev>
diff --git a/lisp/thingatpt.el b/lisp/thingatpt.el
index 72acb0b749f..323d3d1cf6c 100644
--- a/lisp/thingatpt.el
+++ b/lisp/thingatpt.el
@@ -1,6 +1,6 @@
;;; thingatpt.el --- get the `thing' at point -*- lexical-binding:t -*-
-;; Copyright (C) 1991-1998, 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1991-1998, 2000-2024 Free Software Foundation, Inc.
;; Author: Mike Williams <mikew@gopher.dosli.govt.nz>
;; Maintainer: emacs-devel@gnu.org
@@ -52,7 +52,6 @@
;;; Code:
-(require 'cl-lib)
(provide 'thingatpt)
(defvar thing-at-point-provider-alist nil
@@ -175,11 +174,14 @@ See the file `thingatpt.el' for documentation on how to define
a symbol as a valid THING."
(let ((text
(cond
- ((cl-loop for (pthing . function) in thing-at-point-provider-alist
- when (eq pthing thing)
- for result = (funcall function)
- when result
- return result))
+ ((let ((alist thing-at-point-provider-alist)
+ elt result)
+ (while (and alist (null result))
+ (setq elt (car alist)
+ alist (cdr alist))
+ (and (eq (car elt) thing)
+ (setq result (funcall (cdr elt)))))
+ result))
((get thing 'thing-at-point)
(funcall (get thing 'thing-at-point)))
(t
@@ -565,9 +567,9 @@ looks like an email address, \"ftp://\" if it starts with
;; If it looks like ftp.example.com. treat it as ftp.
(if (string-match "\\`ftp\\." str)
(setq str (concat "ftp://" str)))
- ;; If it looks like www.example.com. treat it as http.
+ ;; If it looks like www.example.com. treat it as https.
(if (string-match "\\`www\\." str)
- (setq str (concat "http://" str)))
+ (setq str (concat "https://" str)))
;; Otherwise, it just isn't a URI.
(setq str nil)))
str)))
@@ -650,7 +652,7 @@ back from point."
;; Email addresses
(defvar thing-at-point-email-regexp
- "<?[-+_~a-zA-Z0-9][-+_.~:a-zA-Z0-9]*@[-a-zA-Z0-9]+[-.a-zA-Z0-9]*>?"
+ "<?[-+_~a-zA-Z0-9/][-+_.~:a-zA-Z0-9/]*@[-a-zA-Z0-9]+[-.a-zA-Z0-9]*>?"
"A regular expression probably matching an email address.
This does not match the real name portion, only the address, optionally
with angle brackets.")
diff --git a/lisp/thread.el b/lisp/thread.el
index 7363e9a06c8..4c428f30f71 100644
--- a/lisp/thread.el
+++ b/lisp/thread.el
@@ -1,6 +1,6 @@
;;; thread.el --- Thread support in Emacs Lisp -*- lexical-binding: t -*-
-;; Copyright (C) 2018-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2018-2024 Free Software Foundation, Inc.
;; Author: Gemini Lasswell <gazally@runbox.com>
;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/time-stamp.el b/lisp/time-stamp.el
index 1447b6b4368..8c28920d219 100644
--- a/lisp/time-stamp.el
+++ b/lisp/time-stamp.el
@@ -1,6 +1,6 @@
;;; time-stamp.el --- Maintain last change time stamps in files edited by Emacs -*- lexical-binding: t -*-
-;; Copyright (C) 1989, 1993-1995, 1997, 2000-2023 Free Software
+;; Copyright (C) 1989, 1993-1995, 1997, 2000-2024 Free Software
;; Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/lisp/time.el b/lisp/time.el
index 3f10deff5fd..e561f36398c 100644
--- a/lisp/time.el
+++ b/lisp/time.el
@@ -1,6 +1,6 @@
;;; time.el --- display time, load and mail indicator in mode line of Emacs -*- lexical-binding: t -*-
-;; Copyright (C) 1985-1987, 1993-1994, 1996, 2000-2023 Free Software
+;; Copyright (C) 1985-1987, 1993-1994, 1996, 2000-2024 Free Software
;; Foundation, Inc.
;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/timezone.el b/lisp/timezone.el
index 9a199f0939e..515bf87480b 100644
--- a/lisp/timezone.el
+++ b/lisp/timezone.el
@@ -1,6 +1,6 @@
;;; timezone.el --- time zone package for GNU Emacs -*- lexical-binding: t -*-
-;; Copyright (C) 1990-1993, 1996, 1999, 2001-2023 Free Software
+;; Copyright (C) 1990-1993, 1996, 1999, 2001-2024 Free Software
;; Foundation, Inc.
;; Author: Masanobu Umeda <umerin@mse.kyutech.ac.jp>
diff --git a/lisp/tmm.el b/lisp/tmm.el
index a4058594622..f52afb7e162 100644
--- a/lisp/tmm.el
+++ b/lisp/tmm.el
@@ -1,6 +1,6 @@
;;; tmm.el --- text mode access to menu-bar -*- lexical-binding: t -*-
-;; Copyright (C) 1994-1996, 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1994-1996, 2000-2024 Free Software Foundation, Inc.
;; Author: Ilya Zakharevich <ilya@math.mps.ohio-state.edu>
;; Maintainer: emacs-devel@gnu.org
@@ -79,7 +79,8 @@ See the documentation for `tmm-prompt'."
"String to insert between shortcut and menu item.
If nil, there will be no shortcuts. It should not consist only of spaces,
or else the correct item might not be found in the `*Completions*' buffer."
- :type 'string)
+ :type '(choice (const :tag "No shortcuts" nil)
+ string))
(defvar tmm-mb-map nil
"A place to store minibuffer map.")
diff --git a/lisp/tool-bar.el b/lisp/tool-bar.el
index ab81a21211d..4ca81fb01e0 100644
--- a/lisp/tool-bar.el
+++ b/lisp/tool-bar.el
@@ -1,6 +1,6 @@
;;; tool-bar.el --- setting up the tool bar -*- lexical-binding: t -*-
-;; Copyright (C) 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2000-2024 Free Software Foundation, Inc.
;; Author: Dave Love <fx@gnu.org>
;; Keywords: mouse frames
diff --git a/lisp/tooltip.el b/lisp/tooltip.el
index 6f8a489e60c..4537fdf8087 100644
--- a/lisp/tooltip.el
+++ b/lisp/tooltip.el
@@ -1,6 +1,6 @@
;;; tooltip.el --- show tooltip windows -*- lexical-binding:t -*-
-;; Copyright (C) 1997, 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997, 1999-2024 Free Software Foundation, Inc.
;; Author: Gerd Moellmann <gerd@acm.org>
;; Keywords: help c mouse tools
diff --git a/lisp/touch-screen.el b/lisp/touch-screen.el
index 577c993efcf..c2f8f8068d7 100644
--- a/lisp/touch-screen.el
+++ b/lisp/touch-screen.el
@@ -1,6 +1,6 @@
;;; touch-screen.el --- touch screen support for X and Android -*- lexical-binding: t; -*-
-;; Copyright (C) 2023 Free Software Foundation, Inc.
+;; Copyright (C) 2023-2024 Free Software Foundation, Inc.
;; Maintainer: emacs-devel@gnu.org
;; Package: emacs
@@ -33,15 +33,41 @@
(defvar touch-screen-current-tool nil
"The touch point currently being tracked, or nil.
-If non-nil, this is a list of nine elements: the ID of the touch
+If non-nil, this is a list of ten elements: the ID of the touch
point being tracked, the window where the touch began, a cons
-containing the last known position of the touch point, relative
+holding the last registered position of the touch point, relative
to that window, a field used to store data while tracking the
-touch point, the initial position of the touchpoint, and another
-four fields to used store data while tracking the touch point.
+touch point, the initial position of the touchpoint, another four
+fields to used store data while tracking the touch point, and the
+last known position of the touch point.
+
See `touch-screen-handle-point-update' and
`touch-screen-handle-point-up' for the meanings of the fourth
-element.")
+element.
+
+The third and last elements differ in that the former is not
+modified until after a gesture is recognized in reaction to an
+update, whereas the latter is updated upon each apposite
+`touchscreen-update' event.")
+
+(defvar touch-screen-aux-tool nil
+ "The ancillary tool being tracked, or nil.
+If non-nil, this is a vector of ten elements: the ID of the
+touch point being tracked, the window where the touch began, a
+cons holding the initial position of the touch point, and the
+last known position of the touch point, all in the same format as
+in `touch-screen-current-tool', the distance in pixels between
+the current tool and the aforementioned initial position, the
+center of the line formed between those two points, the ratio
+between the present distance between both tools and the aforesaid
+initial distance when a pinch gesture was last sent, and three
+elements into which commands can save data particular to a tool.
+
+The ancillary tool is a second tool whose movement is interpreted
+in unison with that of the current tool to recognize gestures
+comprising the motion of both such as \"pinch\" gestures, in
+which the text scale is adjusted in proportion to the distance
+between both tools.")
(defvar touch-screen-set-point-commands '(mouse-set-point)
"List of commands known to set the point.
@@ -58,25 +84,30 @@ This is always cleared upon any significant state change.")
If non-nil, the touch screen key event translation machinery
is being called from `read-sequence' or some similar function.")
+(defgroup touch-screen nil
+ "Interact with Emacs from touch screen devices."
+ :group 'mouse
+ :version "30.0")
+
(defcustom touch-screen-display-keyboard nil
"If non-nil, always display the on screen keyboard.
A buffer local value means to always display the on screen
keyboard when the buffer is selected."
:type 'boolean
- :group 'mouse
+ :group 'touch-screen
:version "30.1")
(defcustom touch-screen-delay 0.7
"Delay in seconds before Emacs considers a touch to be a long-press."
:type 'number
- :group 'mouse
+ :group 'touch-screen
:version "30.1")
(defcustom touch-screen-precision-scroll nil
"Whether or not to use precision scrolling for touch screens.
See `pixel-scroll-precision-mode' for more details."
:type 'boolean
- :group 'mouse
+ :group 'touch-screen
:version "30.1")
(defcustom touch-screen-word-select nil
@@ -84,7 +115,7 @@ See `pixel-scroll-precision-mode' for more details."
If non-nil, long-press events (see `touch-screen-delay') followed
by dragging will try to select entire words."
:type 'boolean
- :group 'mouse
+ :group 'touch-screen
:version "30.1")
(defcustom touch-screen-extend-selection nil
@@ -93,7 +124,7 @@ When enabled, tapping on the character containing the point or
mark will resume dragging where it left off while the region is
active."
:type 'boolean
- :group 'mouse
+ :group 'touch-screen
:version "30.1")
(defcustom touch-screen-preview-select nil
@@ -102,7 +133,15 @@ When enabled, a preview of the visible line within the window
will be displayed in the echo area while dragging combined with
an indication of the position of point within that line."
:type 'boolean
- :group 'mouse
+ :group 'touch-screen
+ :version "30.1")
+
+(defcustom touch-screen-enable-hscroll t
+ "If non-nil, hscroll can be changed from the touch screen.
+When enabled, tapping on a window and dragging your finger left
+or right will scroll that window horizontally."
+ :type 'boolean
+ :group 'touch-screen
:version "30.1")
(defvar-local touch-screen-word-select-bounds nil
@@ -216,7 +255,7 @@ horizontal scrolling according to the movement in DX."
(window (cadr touch-screen-current-tool))
(lines-vscrolled (or (nth 7 touch-screen-current-tool) 0))
(lines-hscrolled (or (nth 8 touch-screen-current-tool) 0)))
- (setq accumulator (+ accumulator dx)) ; Add dx;
+ (setq accumulator (+ accumulator dx)) ; Add dx.
;; Figure out how much it has scrolled and how much remains on the
;; left or right of the window. If a line has already been
;; vscrolled but no hscrolling has happened, don't hscroll, as
@@ -229,7 +268,12 @@ horizontal scrolling according to the movement in DX."
(>= (- accumulator) column-width))
(progn
(setq accumulator (+ accumulator column-width))
- (scroll-right 1)
+ ;; Maintain both hscroll counters even when
+ ;; it's disabled to prevent unintentional or
+ ;; patently horizontal gestures from
+ ;; scrolling the window vertically.
+ (when touch-screen-enable-hscroll
+ (scroll-right 1))
(setq lines-hscrolled (1+ lines-hscrolled))
(when (not (zerop accumulator))
;; If there is still an outstanding amount
@@ -238,7 +282,8 @@ horizontal scrolling according to the movement in DX."
(when (and (> accumulator 0)
(>= accumulator column-width))
(setq accumulator (- accumulator column-width))
- (scroll-left 1)
+ (when touch-screen-enable-hscroll
+ (scroll-left 1))
(setq lines-hscrolled (1+ lines-hscrolled))
(when (not (zerop accumulator))
;; If there is still an outstanding amount to
@@ -275,6 +320,7 @@ the event."
;;; Drag-to-select gesture.
+;;;###autoload
(defun touch-screen-hold (event)
"Handle a long press EVENT.
Ding and select the window at EVENT, then activate the mark. If
@@ -825,6 +871,101 @@ keeping the bounds of the region intact, and set up state for
+;; Pinch gesture.
+
+(defvar text-scale-mode)
+(defvar text-scale-mode-amount)
+(defvar text-scale-mode-step)
+
+(defun touch-screen-scroll-point-to-y (target-point target-y)
+ "Move the row surrounding TARGET-POINT to TARGET-Y.
+Scroll the current window such that the position of TARGET-POINT
+within it on the Y axis approaches TARGET-Y."
+ (condition-case nil
+ (let* ((last-point (point))
+ (current-y (cadr (pos-visible-in-window-p target-point
+ nil t)))
+ (direction (if (if current-y
+ (< target-y current-y)
+ (< (window-start) target-point))
+ -1 1)))
+ (while (< 0 (* direction (if current-y
+ (- target-y current-y)
+ (- (window-start) target-point))))
+ (scroll-down direction)
+ (setq last-point (point))
+ (setq current-y (cadr (pos-visible-in-window-p target-point nil t))))
+ (unless (and (< direction 0) current-y)
+ (scroll-up direction)
+ (goto-char last-point)))
+ ;; Ignore BOB and EOB.
+ ((beginning-of-buffer end-of-buffer) nil)))
+
+(defun touch-screen-pinch (event)
+ "Scroll the window in the touchscreen-pinch event EVENT.
+Pan the display by the pan deltas in EVENT, and adjust the
+text scale by the ratio therein."
+ (interactive "e")
+ (require 'face-remap)
+ (let* ((posn (cadr event))
+ (window (posn-window posn))
+ (scale (nth 2 event))
+ (ratio-diff (nth 5 event))
+ current-scale start-scale)
+ (when (windowp window)
+ (with-selected-window window
+ (setq current-scale (if text-scale-mode
+ text-scale-mode-amount
+ 0)
+ start-scale (or (aref touch-screen-aux-tool 7)
+ (aset touch-screen-aux-tool 7
+ current-scale)))
+ ;; Set the text scale.
+ (text-scale-set (+ start-scale
+ (round (log scale text-scale-mode-step))))
+ ;; Subsequently move the row which was at the centrum to its Y
+ ;; position.
+ (if (and (not (eq current-scale
+ text-scale-mode-amount))
+ (posn-point posn)
+ (cdr (posn-x-y posn)))
+ (touch-screen-scroll-point-to-y (posn-point posn)
+ (cdr (posn-x-y posn)))
+ ;; Rather than scroll POSN's point to its old row, scroll the
+ ;; display by the Y axis deltas within EVENT.
+ (let ((height (window-default-line-height))
+ (y-accumulator (or (aref touch-screen-aux-tool 8) 0)))
+ (setq y-accumulator (+ y-accumulator (nth 4 event)))
+ (when (or (> y-accumulator height)
+ (< y-accumulator (- height)))
+ (ignore-errors
+ (if (> y-accumulator 0)
+ (scroll-down 1)
+ (scroll-up 1)))
+ (setq y-accumulator 0))
+ (aset touch-screen-aux-tool 8 y-accumulator))
+ ;; Likewise for the X axis deltas.
+ (let ((width (frame-char-width))
+ (x-accumulator (or (aref touch-screen-aux-tool 9) 0)))
+ (setq x-accumulator (+ x-accumulator (nth 3 event)))
+ (when (or (> x-accumulator width)
+ (< x-accumulator (- width)))
+ ;; Do not hscroll if the ratio has shrunk, for that is
+ ;; generally attended by the centerpoint moving left,
+ ;; and Emacs can hscroll left even when no lines are
+ ;; truncated.
+ (unless (and (< x-accumulator 0)
+ (< ratio-diff 0))
+ (if (> x-accumulator 0)
+ (scroll-right 1)
+ (scroll-left 1)))
+ (setq x-accumulator 0))
+ (aset touch-screen-aux-tool 9 x-accumulator)))))))
+
+(define-key global-map [touchscreen-pinch] #'touch-screen-pinch)
+
+
+
;; Touch screen event translation. The code here translates raw touch
;; screen events into `touchscreen-scroll' events and mouse events in
;; a ``DWIM'' fashion, consulting the keymaps at the position of the
@@ -867,20 +1008,28 @@ Perform the editing operations or throw to the input translation
function with an input event tied to any gesture that is
recognized.
+Update the tenth element of `touch-screen-current-tool' with
+POINT relative to the window it was placed on. Update the third
+element in like fashion, once sufficient motion has accumulated
+that an event is generated.
+
POINT must be the touch point currently being tracked as
`touch-screen-current-tool'.
If the fourth element of `touch-screen-current-tool' is nil, then
-the touch has just begun. Determine how much POINT has moved.
-If POINT has moved upwards or downwards by a significant amount,
-then set the fourth element to `scroll'. Then, generate a
-`touchscreen-scroll' event with the window that POINT was
-initially placed upon, and pixel deltas describing how much point
-has moved relative to its previous position in the X and Y axes.
+the touch has just begun. In a related case, if it is
+`ancillary-tool', then the ancillary tool has been removed and
+gesture translation must be resumed. Determine how much POINT
+has moved. If POINT has moved upwards or downwards by a
+significant amount, then set the fourth element to `scroll'.
+Then, generate a `touchscreen-scroll' event with the window that
+POINT was initially placed upon, and pixel deltas describing how
+much point has moved relative to its previous position in the X
+and Y axes.
If the fourth element of `touchscreen-current-tool' is `scroll',
then generate a `touchscreen-scroll' event with the window that
-qPOINT was initially placed upon, and pixel deltas describing how
+POINT was initially placed upon, and pixel deltas describing how
much point has moved relative to its previous position in the X
and Y axes.
@@ -899,34 +1048,23 @@ If the fourth element of `touch-screen-current-tool' is
If the fourth element of `touch-screen-current-tool' is `drag',
then move point to the position of POINT."
- (let ((window (nth 1 touch-screen-current-tool))
- (what (nth 3 touch-screen-current-tool)))
- (cond ((null what)
- (let* ((posn (cdr point))
- (last-posn (nth 2 touch-screen-current-tool))
- (original-posn (nth 4 touch-screen-current-tool))
- ;; Now get the position of X and Y relative to
- ;; WINDOW.
- (relative-xy
- (touch-screen-relative-xy posn window))
- (col (and (not (posn-area original-posn))
- (car (posn-col-row original-posn
- (posn-window posn)))))
- ;; Don't start horizontal scrolling if the touch
- ;; point originated within two columns of the window
- ;; edges, as systems like Android use those two
- ;; columns to implement gesture navigation.
- (diff-x-eligible
- (and col (> col 2)
- (< col (- (window-width window) 2))))
+ (let* ((window (nth 1 touch-screen-current-tool))
+ (what (nth 3 touch-screen-current-tool))
+ (posn (cdr point))
+ ;; Now get the position of X and Y relative to WINDOW.
+ (relative-xy
+ (touch-screen-relative-xy posn window)))
+ ;; Update the 10th field of the tool list with RELATIVE-XY.
+ (setcar (nthcdr 9 touch-screen-current-tool) relative-xy)
+ (cond ((or (null what)
+ (eq what 'ancillary-tool))
+ (let* ((last-posn (nth 2 touch-screen-current-tool))
(diff-x (- (car last-posn) (car relative-xy)))
(diff-y (- (cdr last-posn) (cdr relative-xy))))
(when (or (> diff-y 10)
- (and diff-x-eligible
- (> diff-x (frame-char-width)))
+ (> diff-x (frame-char-width))
(< diff-y -10)
- (and diff-x-eligible
- (< diff-x (- (frame-char-width)))))
+ (< diff-x (- (frame-char-width))))
(setcar (nthcdr 3 touch-screen-current-tool)
'scroll)
(setcar (nthcdr 2 touch-screen-current-tool)
@@ -947,12 +1085,7 @@ then move point to the position of POINT."
(when touch-screen-current-timer
(cancel-timer touch-screen-current-timer)
(setq touch-screen-current-timer nil))
- (let* ((posn (cdr point))
- (last-posn (nth 2 touch-screen-current-tool))
- ;; Now get the position of X and Y relative to
- ;; WINDOW.
- (relative-xy
- (touch-screen-relative-xy posn window))
+ (let* ((last-posn (nth 2 touch-screen-current-tool))
(diff-x (- (car last-posn) (car relative-xy)))
(diff-y (- (cdr last-posn) (cdr relative-xy))))
(setcar (nthcdr 3 touch-screen-current-tool)
@@ -995,6 +1128,116 @@ then move point to the position of POINT."
;; Generate a (touchscreen-drag POSN) event.
(throw 'input-event (list 'touchscreen-drag posn)))))))
+(defsubst touch-screen-distance (pos1 pos2)
+ "Compute the distance in pixels between POS1 and POS2.
+Each is a coordinate whose car and cdr are respectively its X and
+Y values."
+ (let ((v1 (- (cdr pos2) (cdr pos1)))
+ (v2 (- (car pos2) (car pos1))))
+ (abs (sqrt (+ (* v1 v1) (* v2 v2))))))
+
+(defsubst touch-screen-centrum (pos1 pos2)
+ "Compute the center of a line between the points POS1 and POS2.
+Each, and value, is a coordinate whose car and cdr are
+respectively its X and Y values."
+ (let ((v1 (+ (cdr pos2) (cdr pos1)))
+ (v2 (+ (car pos2) (car pos1))))
+ (cons (/ v2 2) (/ v1 2))))
+
+(defun touch-screen-handle-aux-point-update (point number)
+ "Notice that a point being observed has moved.
+Register motion from either the current or ancillary tool while
+an ancillary tool is present.
+
+POINT must be the cdr of an element of a `touchscreen-update'
+event's list of touch points. NUMBER must be its touch ID.
+
+Calculate the distance between POINT's position and that of the
+other tool (which is to say the ancillary tool of POINT is the
+current tool, and vice versa). Compare this distance to that
+between both points at the time they were placed on the screen,
+and signal a pinch event to adjust the text scale and scroll the
+window by the factor so derived. Such events are lists formed as
+so illustrated:
+
+ (touchscreen-pinch CENTRUM RATIO PAN-X PAN-Y RATIO-DIFF)
+
+in which CENTRUM is a posn representing the midpoint of a line
+between the present locations of both tools, RATIO is the said
+factor, PAN-X is the number of pixels on the X axis that centrum
+has moved since the last event, PAN-Y is that on the Y axis, and
+RATIO-DIFF is the difference between RATIO and the ratio in the
+last such event."
+ (let (this-point-position
+ other-point-position
+ (window (cadr touch-screen-current-tool)))
+ (when (windowp window)
+ (if (eq number (aref touch-screen-aux-tool 0))
+ (progn
+ ;; The point pressed is the ancillary tool. Set
+ ;; other-point-position to that of the current tool.
+ (setq other-point-position (nth 9 touch-screen-current-tool))
+ ;; Update the position within touch-screen-aux-tool.
+ (aset touch-screen-aux-tool 3
+ (setq this-point-position
+ (touch-screen-relative-xy point window))))
+ (setq other-point-position (aref touch-screen-aux-tool 3))
+ (setcar (nthcdr 2 touch-screen-current-tool)
+ (setq this-point-position
+ (touch-screen-relative-xy point window)))
+ (setcar (nthcdr 9 touch-screen-current-tool)
+ this-point-position))
+ ;; Now compute, and take the absolute of, this distance.
+ (let ((distance (touch-screen-distance this-point-position
+ other-point-position))
+ (centrum (touch-screen-centrum this-point-position
+ other-point-position))
+ (initial-distance (aref touch-screen-aux-tool 4))
+ (initial-centrum (aref touch-screen-aux-tool 5)))
+ (let* ((ratio (/ distance initial-distance))
+ (ratio-diff (- ratio (aref touch-screen-aux-tool 6)))
+ (diff (abs (- ratio (aref touch-screen-aux-tool 6))))
+ (centrum-diff (+ (abs (- (car initial-centrum)
+ (car centrum)))
+ (abs (- (cdr initial-centrum)
+ (cdr centrum))))))
+ ;; If the difference in ratio has surpassed a threshold of
+ ;; 0.2 or the centrum difference exceeds the frame's char
+ ;; width, send a touchscreen-pinch event with this
+ ;; information and update that saved in
+ ;; touch-screen-aux-tool.
+ (when (or (> diff 0.2)
+ (> centrum-diff
+ (/ (frame-char-width) 2)))
+ (aset touch-screen-aux-tool 5 centrum)
+ (aset touch-screen-aux-tool 6 ratio)
+ (throw 'input-event
+ (list 'touchscreen-pinch
+ (if (or (<= (car centrum) 0)
+ (<= (cdr centrum) 0))
+ (list window nil centrum nil nil
+ nil nil nil nil nil)
+ (let ((posn (posn-at-x-y (car centrum)
+ (cdr centrum)
+ window)))
+ (if (eq (posn-window posn)
+ window)
+ posn
+ ;; Return a placeholder
+ ;; outside the window if
+ ;; the centrum has moved
+ ;; beyond the confines of
+ ;; the window where the
+ ;; gesture commenced.
+ (list window nil centrum nil nil
+ nil nil nil nil nil))))
+ ratio
+ (- (car centrum)
+ (car initial-centrum))
+ (- (cdr centrum)
+ (cdr initial-centrum))
+ ratio-diff))))))))
+
(defun touch-screen-window-selection-changed (frame)
"Notice that FRAME's selected window has changed.
Cancel any timer that is supposed to hide the keyboard in
@@ -1018,6 +1261,13 @@ POINT should be the point currently tracked as
PREFIX should be a virtual function key used to look up key
bindings.
+If an ancillary touch point is being observed, transfer touch
+information from `touch-screen-aux-tool' to
+`touch-screen-current-tool' and set it to nil, thereby resuming
+gesture recognition with that tool replacing the tool removed.
+
+Otherwise:
+
If the fourth element of `touch-screen-current-tool' is nil or
`restart-drag', move point to the position of POINT, selecting
the window under POINT as well, and deactivate the mark; if there
@@ -1034,127 +1284,167 @@ If the fourth element of `touch-screen-current-tool' is
original position of the tool to display its bound keymap as a
menu.
+If the fourth element of `touch-screen-current-tool' is `drag' or
+`held', the region is active, and the tool's initial window's
+selected buffer isn't read-only, display the on screen keyboard.
+
If the command being executed is listed in
`touch-screen-set-point-commands' also display the on-screen
keyboard if the current buffer and the character at the new point
is not read-only."
- (let ((what (nth 3 touch-screen-current-tool))
- (posn (cdr point)) window point)
- (cond ((or (null what)
- ;; If dragging has been restarted but the touch point
- ;; hasn't been moved, translate the sequence into a
- ;; regular mouse click.
- (eq what 'restart-drag))
- (when (windowp (posn-window posn))
- (setq point (posn-point posn)
- window (posn-window posn))
- ;; Select the window that was tapped given that it isn't
- ;; an inactive minibuffer window.
- (when (or (not (eq window
- (minibuffer-window
- (window-frame window))))
- (minibuffer-window-active-p window))
- (select-window window))
- ;; Now simulate a mouse click there. If there is a link
- ;; or a button, use mouse-2 to push it.
- (let* ((event (list (if (or (mouse-on-link-p posn)
- (and point (button-at point)))
- 'mouse-2
- 'mouse-1)
- posn))
- ;; Look for the command bound to this event.
- (command (key-binding (if prefix
- (vector prefix
- (car event))
- (vector (car event)))
- t nil posn)))
- (deactivate-mark)
- (when point
- ;; This is necessary for following links.
- (goto-char point))
- ;; Figure out if the on screen keyboard needs to be
- ;; displayed.
- (when command
- (if (memq command touch-screen-set-point-commands)
- (if touch-screen-translate-prompt
- ;; When a `mouse-set-point' command is
- ;; encountered and
- ;; `touch-screen-handle-touch' is being
- ;; called from the keyboard command loop,
- ;; call it immediately so that point is set
- ;; prior to the on screen keyboard being
- ;; displayed.
- (call-interactively command nil
- (vector event))
- (if (and (or (not buffer-read-only)
- touch-screen-display-keyboard)
- ;; Detect the splash screen and avoid
- ;; displaying the on screen keyboard
- ;; there.
- (not (equal (buffer-name) "*GNU Emacs*")))
- ;; Once the on-screen keyboard has been
- ;; opened, add
- ;; `touch-screen-window-selection-changed'
- ;; as a window selection change function
- ;; This then prevents it from being hidden
- ;; after exiting the minibuffer.
- (progn
- (add-hook 'window-selection-change-functions
- #'touch-screen-window-selection-changed)
- (frame-toggle-on-screen-keyboard (selected-frame)
- nil))
- ;; Otherwise, hide the on screen keyboard
- ;; now.
- (frame-toggle-on-screen-keyboard (selected-frame) t))
- ;; But if it's being called from `describe-key'
- ;; or some such, return it as a key sequence.
- (throw 'input-event event)))
- ;; If not, return the event.
- (throw 'input-event event)))))
- ((eq what 'mouse-drag)
- ;; Generate a corresponding `mouse-1' event.
- (let* ((new-window (posn-window posn))
- (new-point (posn-point posn))
- (old-posn (nth 4 touch-screen-current-tool))
- (old-window (posn-window posn))
- (old-point (posn-point posn)))
+ (if touch-screen-aux-tool
+ (progn
+ (let ((point-no (aref touch-screen-aux-tool 0))
+ (relative-xy (aref touch-screen-aux-tool 3)))
+ ;; Replace the current position of touch-screen-current-tool
+ ;; with relative-xy and its number with point-no, but leave
+ ;; other information (such as its starting position) intact:
+ ;; this touchpoint is meant to continue the gesture
+ ;; interrupted by the removal of the last, not to commence a
+ ;; new one.
+ (setcar touch-screen-current-tool point-no)
+ (setcar (nthcdr 2 touch-screen-current-tool)
+ relative-xy)
+ (setcar (nthcdr 9 touch-screen-current-tool)
+ relative-xy))
+ (setq touch-screen-aux-tool nil))
+ (let ((what (nth 3 touch-screen-current-tool))
+ (posn (cdr point)) window point)
+ (cond ((or (null what)
+ ;; If dragging has been restarted but the touch point
+ ;; hasn't been moved, translate the sequence into a
+ ;; regular mouse click.
+ (eq what 'restart-drag))
+ (when (windowp (posn-window posn))
+ (setq point (posn-point posn)
+ window (posn-window posn))
+ ;; Select the window that was tapped given that it
+ ;; isn't an inactive minibuffer window.
+ (when (or (not (eq window
+ (minibuffer-window
+ (window-frame window))))
+ (minibuffer-window-active-p window))
+ (select-window window))
+ ;; Now simulate a mouse click there. If there is a
+ ;; link or a button, use mouse-2 to push it.
+ (let* ((event (list (if (or (mouse-on-link-p posn)
+ (and point (button-at point)))
+ 'mouse-2
+ 'mouse-1)
+ posn))
+ ;; Look for the command bound to this event.
+ (command (key-binding (if prefix
+ (vector prefix
+ (car event))
+ (vector (car event)))
+ t nil posn)))
+ (deactivate-mark)
+ (when point
+ ;; This is necessary for following links.
+ (goto-char point))
+ ;; Figure out if the on screen keyboard needs to be
+ ;; displayed.
+ (when command
+ (if (memq command touch-screen-set-point-commands)
+ (if touch-screen-translate-prompt
+ ;; Forgo displaying the virtual keyboard
+ ;; should touch-screen-translate-prompt be
+ ;; set, for then the key won't be delivered
+ ;; to the command loop, but rather to a
+ ;; caller of read-key-sequence such as
+ ;; describe-key.
+ (throw 'input-event event)
+ (if (and (or (not buffer-read-only)
+ touch-screen-display-keyboard)
+ ;; Detect the splash screen and
+ ;; avoid displaying the on screen
+ ;; keyboard there.
+ (not (equal (buffer-name) "*GNU Emacs*")))
+ ;; Once the on-screen keyboard has been
+ ;; opened, add
+ ;; `touch-screen-window-selection-changed'
+ ;; as a window selection change function
+ ;; This then prevents it from being
+ ;; hidden after exiting the minibuffer.
+ (progn
+ (add-hook
+ 'window-selection-change-functions
+ #'touch-screen-window-selection-changed)
+ (frame-toggle-on-screen-keyboard
+ (selected-frame) nil))
+ ;; Otherwise, hide the on screen keyboard
+ ;; now.
+ (frame-toggle-on-screen-keyboard (selected-frame)
+ t))
+ ;; But if it's being called from `describe-key'
+ ;; or some such, return it as a key sequence.
+ (throw 'input-event event)))
+ ;; If not, return the event.
+ (throw 'input-event event)))))
+ ((eq what 'mouse-drag)
+ ;; Generate a corresponding `mouse-1' event.
+ (let* ((new-window (posn-window posn))
+ (new-point (posn-point posn))
+ (old-posn (nth 4 touch-screen-current-tool))
+ (old-window (posn-window posn))
+ (old-point (posn-point posn)))
+ (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))))))
+ ((eq what 'mouse-1-menu)
+ ;; Generate a `down-mouse-1' event at the position the tap
+ ;; took place.
(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 (cons old-window
- old-posn)
- (cons new-window 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 (cons old-window
- old-posn)
- (cons new-window posn)))))))
- ((eq what 'mouse-1-menu)
- ;; Generate a `down-mouse-1' event at the position the tap
- ;; took place.
- (throw 'input-event
- (list 'down-mouse-1
- (nth 4 touch-screen-current-tool)))))))
+ (list 'down-mouse-1
+ (nth 4 touch-screen-current-tool))))
+ ((or (eq what 'drag)
+ ;; Merely initiating a drag is sufficient to select a
+ ;; word if word selection is enabled.
+ (eq what 'held))
+ ;; Display the on screen keyboard if the region is now
+ ;; active. Check this within the window where the tool
+ ;; was first place.
+ (setq window (nth 1 touch-screen-current-tool))
+ (when window
+ (with-selected-window window
+ (when (and (region-active-p)
+ (not buffer-read-only))
+ ;; Once the on-screen keyboard has been opened, add
+ ;; `touch-screen-window-selection-changed' as a
+ ;; window selection change function. This then
+ ;; prevents it from being hidden after exiting the
+ ;; minibuffer.
+ (progn
+ (add-hook 'window-selection-change-functions
+ #'touch-screen-window-selection-changed)
+ (frame-toggle-on-screen-keyboard (selected-frame)
+ nil))))))))))
(defun touch-screen-handle-touch (event prefix &optional interactive)
"Handle a single touch EVENT, and perform associated actions.
@@ -1167,8 +1457,15 @@ If INTERACTIVE, execute the command associated with any event
generated instead of throwing `input-event'. Otherwise, throw
`input-event' with a single input event if that event should take
the place of EVENT within the key sequence being translated, or
-`nil' if all tools have been released."
+`nil' if all tools have been released.
+
+Set `touch-screen-events-received' to `t' to indicate that touch
+screen events have been received, and thus by extension require
+functions undertaking event management themselves to call
+`read-key' rather than `read-event'."
(interactive "e\ni\np")
+ (unless touch-screen-events-received
+ (setq touch-screen-events-received t))
(if interactive
;; Called interactively (probably from wid-edit.el.)
;; Add any event generated to `unread-command-events'.
@@ -1194,81 +1491,151 @@ the place of EVENT within the key sequence being translated, or
(when touch-screen-current-timer
(cancel-timer touch-screen-current-timer)
(setq touch-screen-current-timer nil))
- ;; Replace any previously ongoing gesture. If POSITION has no
- ;; window or position, make it nil instead.
- (setq tool-list (and (windowp window)
- (list touchpoint window
- (posn-x-y position)
- nil position
- nil nil nil nil))
- touch-screen-current-tool tool-list)
-
- ;; Select the window underneath the event as the checks below
- ;; will look up keymaps and markers inside its buffer.
- (save-selected-window
- ;; Check if `touch-screen-extend-selection' is enabled, the
- ;; tap lies on the point or the mark, and the region is
- ;; active. If that's the case, set the fourth element of
- ;; `touch-screen-current-tool' to `restart-drag', then
- ;; generate a `touchscreen-restart-drag' event.
- (when tool-list
- ;; tool-list is always non-nil where the selected window
- ;; matters.
- (select-window window)
- (when (and touch-screen-extend-selection
- (or (eq point (point))
- (eq point (mark)))
- (region-active-p)
- ;; Only restart drag-to-select if the tap falls
- ;; on the same row as the selection. This
- ;; prevents dragging from starting if the tap
- ;; is below the last window line with text and
- ;; `point' is at ZV, as the user most likely
- ;; meant to scroll the window instead.
- (when-let* ((posn-point (posn-at-point point))
- (posn-row (cdr (posn-col-row posn-point))))
- (eq (cdr (posn-col-row position)) posn-row)))
- ;; Indicate that a drag is about to restart.
- (setcar (nthcdr 3 tool-list) 'restart-drag)
- ;; 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.
- ;;
- ;; 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 (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)))
- ;; 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
- ;; displays it as a menu, that event could cause
- ;; unwanted commands to be run. Set what to
- ;; `mouse-1-menu' instead and wait for the up event
- ;; to display the menu.
- (setcar (nthcdr 3 tool-list) 'mouse-1-menu)
- (progn (setcar (nthcdr 3 tool-list) 'mouse-drag)
- (throw 'input-event (list 'down-mouse-1 position))))
- (and point
- ;; Start the long-press timer.
- (touch-screen-handle-timeout nil))))))
+ ;; If a tool already exists...
+ (if (and touch-screen-current-tool
+ ;; ..and the number of this tool is at variance with
+ ;; that of the current tool: if a `touchscreen-end'
+ ;; event is delivered that is somehow withheld from
+ ;; this function and the system does not assign
+ ;; monotonically increasing touch point identifiers,
+ ;; then the ancillary tool will be set to a tool
+ ;; bearing the same number as the current tool, and
+ ;; consequently the mechanism for detecting
+ ;; erroneously retained touch points upon the
+ ;; registration of `touchscreen-update' events will
+ ;; not be activated.
+ (not (eq touchpoint (car touch-screen-current-tool))))
+ ;; Then record this tool as the ``auxiliary tool''.
+ ;; Updates to the auxiliary tool are considered in unison
+ ;; with those to the current tool; the distance between
+ ;; both tools is measured and compared with that when the
+ ;; auxiliary tool was first pressed, then interpreted as a
+ ;; scale by which to adjust text within the current tool's
+ ;; window.
+ (when (eq (if (framep window) window (window-frame window))
+ ;; Verify that the new tool was placed on the
+ ;; same frame the current tool has, so as not to
+ ;; consider events distributed across distinct
+ ;; frames components of a single gesture.
+ (window-frame (nth 1 touch-screen-current-tool)))
+ ;; Set touch-screen-aux-tool as is proper. Mind that
+ ;; the last field is always relative to the current
+ ;; tool's window.
+ (let* ((window (nth 1 touch-screen-current-tool))
+ (relative-x-y (touch-screen-relative-xy position
+ window))
+ (initial-pos (nth 4 touch-screen-current-tool))
+ (initial-x-y (touch-screen-relative-xy initial-pos
+ window))
+ computed-distance computed-centrum)
+ ;; Calculate the distance and centrum from this point
+ ;; to the initial position of the current tool.
+ (setq computed-distance (touch-screen-distance relative-x-y
+ initial-x-y)
+ computed-centrum (touch-screen-centrum relative-x-y
+ initial-x-y))
+ ;; If computed-distance is zero, ignore this tap.
+ (unless (zerop computed-distance)
+ (setq touch-screen-aux-tool (vector touchpoint window
+ position relative-x-y
+ computed-distance
+ computed-centrum
+ 1.0 nil nil nil)))
+ ;; When an auxiliary tool is pressed, any gesture
+ ;; previously in progress must be terminated, so long
+ ;; as it represents a gesture recognized from the
+ ;; current tool's motion rather than ones detected by
+ ;; this function from circumstances surrounding its
+ ;; first press, such as the presence of a menu or
+ ;; down-mouse-1 button beneath its first press.
+ (unless (memq (nth 3 touch-screen-current-tool)
+ '(mouse-drag mouse-1-menu))
+ ;; Set the what field to the symbol `ancillary-tool'
+ ;; rather than nil, that mouse events may not be
+ ;; generated if no gesture is subsequently
+ ;; recognized; this, among others, prevents
+ ;; undesirable point movement (through the execution
+ ;; of `mouse-set-point') after both points are
+ ;; released without any gesture being detected.
+ (setcar (nthcdr 3 touch-screen-current-tool)
+ 'ancillary-tool))))
+ ;; Replace any previously ongoing gesture. If POSITION has no
+ ;; window or position, make it nil instead.
+ (setq tool-list (and (windowp window)
+ (list touchpoint window
+ (posn-x-y position)
+ nil position
+ nil nil nil nil
+ (posn-x-y position)))
+ touch-screen-current-tool tool-list)
+ ;; Select the window underneath the event as the checks below
+ ;; will look up keymaps and markers inside its buffer.
+ (save-selected-window
+ ;; Check if `touch-screen-extend-selection' is enabled,
+ ;; the tap lies on the point or the mark, and the region
+ ;; is active. If that's the case, set the fourth element
+ ;; of `touch-screen-current-tool' to `restart-drag', then
+ ;; generate a `touchscreen-restart-drag' event.
+ (when tool-list
+ ;; tool-list is always non-nil where the selected window
+ ;; matters.
+ (select-window window)
+ (when (and touch-screen-extend-selection
+ (or (eq point (point))
+ (eq point (mark)))
+ (region-active-p)
+ ;; Only restart drag-to-select if the tap
+ ;; falls on the same row as the selection.
+ ;; This prevents dragging from starting if
+ ;; the tap is below the last window line with
+ ;; text and `point' is at ZV, as the user
+ ;; most likely meant to scroll the window
+ ;; instead.
+ (when-let* ((posn-point (posn-at-point point))
+ (posn-row (cdr
+ (posn-col-row posn-point))))
+ (eq (cdr (posn-col-row position)) posn-row)))
+ ;; Indicate that a drag is about to restart.
+ (setcar (nthcdr 3 tool-list) 'restart-drag)
+ ;; 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.
+ ;;
+ ;; 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 (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)))
+ ;; 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
+ ;; displays it as a menu, that event could cause
+ ;; unwanted commands to be run. Set what to
+ ;; `mouse-1-menu' instead and wait for the up
+ ;; event to display the menu.
+ (setcar (nthcdr 3 tool-list) 'mouse-1-menu)
+ (progn (setcar (nthcdr 3 tool-list) 'mouse-drag)
+ (throw 'input-event (list 'down-mouse-1 position))))
+ (and point
+ ;; Start the long-press timer.
+ (touch-screen-handle-timeout nil)))))))
((eq (car event) 'touchscreen-update)
(unless touch-screen-current-tool
;; If a stray touchscreen-update event arrives (most likely
@@ -1277,10 +1644,35 @@ the place of EVENT within the key sequence being translated, or
;; The positions of tools currently pressed against the screen
;; have changed. If there is a tool being tracked as part of a
;; gesture, look it up in the list of tools.
- (let ((new-point (assq (car touch-screen-current-tool)
- (cadr event))))
- (when new-point
- (touch-screen-handle-point-update new-point))))
+ (if-let ((new-point (assq (car touch-screen-current-tool)
+ (cadr event))))
+ (if touch-screen-aux-tool
+ (touch-screen-handle-aux-point-update (cdr new-point)
+ (car new-point))
+ (touch-screen-handle-point-update new-point))
+ ;; If the current tool exists no longer, a touchscreen-end
+ ;; event is certain to have been disregarded. So that
+ ;; touchscreen gesture translation might continue as usual
+ ;; after this aberration to the normal flow of events, delete
+ ;; the current tool now.
+ (when touch-screen-current-timer
+ ;; Cancel the touch screen long-press timer, if it is still
+ ;; there by any chance.
+ (cancel-timer touch-screen-current-timer)
+ (setq touch-screen-current-timer nil))
+ ;; Don't call `touch-screen-handle-point-up' when terminating
+ ;; translation abnormally.
+ (setq touch-screen-current-tool nil
+ ;; Delete the ancillary tool while at it.
+ touch-screen-aux-tool nil)
+ (message "Current touch screen tool vanished!"))
+ ;; Check for updates to any ancillary point being monitored.
+ (when touch-screen-aux-tool
+ (let ((new-point (assq (aref touch-screen-aux-tool 0)
+ (cadr event))))
+ (when new-point
+ (touch-screen-handle-aux-point-update (cdr new-point)
+ (car new-point))))))
((eq (car event) 'touchscreen-end)
;; A tool has been removed from the screen. If it is the tool
;; currently being tracked, clear `touch-screen-current-tool'.
@@ -1290,15 +1682,38 @@ the place of EVENT within the key sequence being translated, or
(when touch-screen-current-timer
(cancel-timer touch-screen-current-timer)
(setq touch-screen-current-timer nil))
- (unwind-protect
- ;; Don't perform any actions associated with releasing the
- ;; tool if the touch sequence was intercepted by another
- ;; program.
- (unless (caddr event)
- (touch-screen-handle-point-up (cadr event) prefix))
- ;; Make sure the tool list is cleared even if
- ;; `touch-screen-handle-point-up' throws.
- (setq touch-screen-current-tool nil)))
+ (let ((old-aux-tool touch-screen-aux-tool))
+ (unwind-protect
+ ;; Don't perform any actions associated with releasing the
+ ;; tool if the touch sequence was intercepted by another
+ ;; program.
+ (if (caddr event)
+ (setq touch-screen-current-tool nil)
+ (touch-screen-handle-point-up (cadr event) prefix))
+ ;; If an ancillary tool is present the function call above
+ ;; will merely transfer information from it into the current
+ ;; tool list, thereby rendering it the new current tool,
+ ;; until such time as it too is released.
+ (when (not (and old-aux-tool (not touch-screen-aux-tool)))
+ ;; Make sure the tool list is cleared even if
+ ;; `touch-screen-handle-point-up' throws.
+ (setq touch-screen-current-tool nil)))))
+ ;; If it is rather the ancillary tool, delete its vector. No
+ ;; further action is required, for the next update received will
+ ;; resume regular gesture recognition.
+ ;;
+ ;; The what field in touch-screen-current-tool is set to a
+ ;; signal value when the ancillary tool is pressed, so gesture
+ ;; recognition will commence with a clean slate, save for when
+ ;; the first touch landed atop a menu or some other area
+ ;; down-mouse-1 was bound.
+ ;;
+ ;; Gesture recognition will be inhibited in that case, so that
+ ;; mouse menu or mouse motion events are generated in its place
+ ;; as they would be were no ancillary tool ever pressed.
+ (when (and touch-screen-aux-tool
+ (eq (caadr event) (aref touch-screen-aux-tool 0)))
+ (setq touch-screen-aux-tool nil))
;; Throw to the key translation function.
(throw 'input-event nil)))))
@@ -1499,7 +1914,8 @@ if POSN is on a link or a button, or `mouse-1' otherwise."
;; Exports. These functions are intended for use externally.
-(defun touch-screen-track-tap (event &optional update data)
+;;;###autoload
+(defun touch-screen-track-tap (event &optional update data threshold)
"Track a single tap starting from EVENT.
EVENT should be a `touchscreen-begin' event.
@@ -1509,16 +1925,45 @@ a `touchscreen-update' event is received in the mean time and
contains a touch point with the same ID as in EVENT, call UPDATE
with that event and DATA.
+If THRESHOLD is non-nil, enforce a threshold of movement that is
+either itself or 10 pixels when it is not a number. If the
+aforementioned touch point moves beyond that threshold on any
+axis, return nil immediately, and further resume mouse event
+translation for the touch point at hand.
+
Return nil immediately if any other kind of event is received;
otherwise, return t once the `touchscreen-end' event arrives."
- (let ((disable-inhibit-text-conversion t))
+ (let ((disable-inhibit-text-conversion t)
+ (threshold (and threshold (or (and (numberp threshold)
+ threshold)
+ 10)))
+ (original-x-y (posn-x-y (cdadr event)))
+ (original-window (posn-window (cdadr event))))
(catch 'finish
(while t
- (let ((new-event (read-event nil)))
+ (let ((new-event (read-event nil))
+ touch-point)
(cond
((eq (car-safe new-event) 'touchscreen-update)
- (when (and update (assq (caadr event) (cadr new-event)))
- (funcall update new-event data)))
+ (when (setq touch-point (assq (caadr event) (cadr new-event)))
+ (when update
+ (funcall update new-event data))
+ (when threshold
+ (setq touch-point (cdr touch-point))
+ ;; Detect the touch point moving past the threshold.
+ (let* ((x-y (touch-screen-relative-xy touch-point
+ original-window))
+ (x (car x-y)) (y (cdr x-y)))
+ (when (or (> (abs (- x (car original-x-y))) threshold)
+ (> (abs (- y (cdr original-x-y))) threshold))
+ ;; Resume normal touch-screen to mouse event
+ ;; translation for this touch sequence by
+ ;; supplying both the event starting it and the
+ ;; motion event that overstepped the threshold to
+ ;; touch-screen-handle-touch.
+ (touch-screen-handle-touch event nil t)
+ (touch-screen-handle-touch new-event nil t)
+ (throw 'finish nil))))))
((eq (car-safe new-event) 'touchscreen-end)
(throw 'finish
;; Now determine whether or not the `touchscreen-end'
@@ -1527,6 +1972,7 @@ otherwise, return t once the `touchscreen-end' event arrives."
(eq (caadr event) (caadr new-event))))
(t (throw 'finish nil))))))))
+;;;###autoload
(defun touch-screen-track-drag (event update &optional data)
"Track a single drag starting from EVENT.
EVENT should be a `touchscreen-begin' event.
@@ -1574,6 +2020,7 @@ touch point in EVENT did not move significantly, and t otherwise."
;;; Event handling exports. These functions are intended for use by
;;; Lisp commands bound to touch screen gesture events.
+;;;###autoload
(defun touch-screen-inhibit-drag ()
"Inhibit subsequent `touchscreen-drag' events from being sent.
Prevent `touchscreen-drag' and translated mouse events from being
diff --git a/lisp/transient.el b/lisp/transient.el
index 78496843284..f9060f5ba85 100644
--- a/lisp/transient.el
+++ b/lisp/transient.el
@@ -1,13 +1,11 @@
;;; transient.el --- Transient commands -*- lexical-binding:t -*-
-;; Copyright (C) 2018-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2018-2024 Free Software Foundation, Inc.
;; Author: Jonas Bernoulli <jonas@bernoul.li>
;; URL: https://github.com/magit/transient
;; Keywords: extensions
-
-;; Package-Version: 0.4.1
-;; Package-Requires: ((emacs "26.1"))
+;; Version: 0.5.2
;; SPDX-License-Identifier: GPL-3.0-or-later
@@ -28,27 +26,9 @@
;;; Commentary:
-;; Taking inspiration from prefix keys and prefix arguments, Transient
-;; implements a similar abstraction involving a prefix command, infix
-;; arguments and suffix commands. We could call this abstraction a
-;; "transient command", but because it always involves at least two
-;; commands (a prefix and a suffix) we prefer to call it just a
-;; "transient".
-
-;; When the user calls a transient prefix command, then a transient
-;; (temporary) keymap is activated, which binds the transient's infix
-;; and suffix commands, and functions that control the transient state
-;; are added to `pre-command-hook' and `post-command-hook'. The
-;; available suffix and infix commands and their state are shown in
-;; the echo area until the transient is exited by invoking a suffix
-;; command.
-
-;; Calling an infix command causes its value to be changed, possibly
-;; by reading a new value in the minibuffer.
-
-;; Calling a suffix command usually causes the transient to be exited
-;; but suffix commands can also be configured to not exit the
-;; transient state.
+;; Transient is the library used to implement the keyboard-driven menus
+;; in Magit. It is distributed as a separate package, so that it can be
+;; used to implement similar menus in other packages.
;;; Code:
@@ -56,7 +36,41 @@
(require 'eieio)
(require 'edmacro)
(require 'format-spec)
+
+(eval-and-compile
+ (when (and (featurep' seq)
+ (not (fboundp 'seq-keep)))
+ (unload-feature 'seq 'force)))
(require 'seq)
+(unless (fboundp 'seq-keep)
+ (display-warning 'transient (substitute-command-keys "\
+Transient requires `seq' >= 2.24,
+but due to bad defaults, Emacs' package manager, refuses to
+upgrade this and other built-in packages to higher releases
+from GNU Elpa, when a package specifies that this is needed.
+
+To fix this, you have to add this to your init file:
+
+ (setq package-install-upgrade-built-in t)
+
+Then evaluate that expression by placing the cursor after it
+and typing \\[eval-last-sexp].
+
+Once you have done that, you have to explicitly upgrade `seq':
+
+ \\[package-upgrade] seq \\`RET'
+
+Then you also must make sure the updated version is loaded,
+by evaluating this form:
+
+ (progn (unload-feature 'seq t) (require 'seq))
+
+Until you do this, you will get random errors about `seq-keep'
+being undefined while using Transient.
+
+If you don't use the `package' package manager but still get
+this warning, then your chosen package manager likely has a
+similar defect.") :emergency))
(eval-when-compile (require 'subr-x))
@@ -65,8 +79,19 @@
(declare-function Man-next-section "man" (n))
(declare-function Man-getpage-in-background "man" (topic))
-(defvar display-line-numbers) ; since Emacs 26.1
(defvar Man-notify-method)
+(defvar pp-default-function) ; since Emacs 29.1
+
+(defmacro static-if (condition then-form &rest else-forms)
+ "A conditional compilation macro.
+Evaluate CONDITION at macro-expansion time. If it is non-nil,
+expand the macro to THEN-FORM. Otherwise expand it to ELSE-FORMS
+enclosed in a `progn' form. ELSE-FORMS may be empty."
+ (declare (indent 2)
+ (debug (sexp sexp &rest sexp)))
+ (if (eval condition lexical-binding)
+ then-form
+ (cons 'progn else-forms)))
(defmacro transient--with-emergency-exit (&rest body)
(declare (indent defun))
@@ -197,21 +222,30 @@ If nil, then the buffer has no mode-line. If the buffer is not
displayed right above the echo area, then this probably is not
a good value.
-If `line' (the default), then the buffer also has no mode-line,
-but a thin line is drawn instead, using the background color of
-the face `transient-separator'. Termcap frames cannot display
-thin lines and therefore fallback to treating `line' like nil.
+If `line' (the default) or a natural number, then the buffer
+has no mode-line, but a line is drawn is drawn in its place.
+If a number is used, that specifies the thickness of the line.
+On termcap frames we cannot draw lines, so there `line' and
+numbers are synonyms for nil.
+
+The color of the line is used to indicate if non-suffixes are
+allowed and whether they exit the transient. The foreground
+color of `transient-key-noop' (if non-suffix are disallowed),
+`transient-key-stay' (if allowed and transient stays active), or
+`transient-key-exit' (if allowed and they exit the transient) is
+used to draw the line.
Otherwise this can be any mode-line format.
See `mode-line-format' for details."
:package-version '(transient . "0.2.0")
:group 'transient
- :type '(choice (const :tag "hide mode-line" nil)
- (const :tag "substitute thin line" line)
- (const :tag "name of prefix command"
- ("%e" mode-line-front-space
- mode-line-buffer-identification))
- (sexp :tag "custom mode-line format")))
+ :type '(choice (const :tag "hide mode-line" nil)
+ (const :tag "substitute thin line" line)
+ (number :tag "substitute line with thickness")
+ (const :tag "name of prefix command"
+ ("%e" mode-line-front-space
+ mode-line-buffer-identification))
+ (sexp :tag "custom mode-line format")))
(defcustom transient-show-common-commands nil
"Whether to show common transient suffixes in the popup buffer.
@@ -235,7 +269,7 @@ of this variable use \"C-x t\" when a transient is active."
This only affects infix arguments that represent command-line
arguments. When this option is non-nil, then the key binding
for infix argument are highlighted when only a long argument
-\(e.g. \"--verbose\") is specified but no shor-thand (e.g \"-v\").
+\(e.g., \"--verbose\") is specified but no shorthand (e.g., \"-v\").
In the rare case that a short-hand is specified but does not
match the key binding, then it is highlighted differently.
@@ -284,19 +318,14 @@ using a layout optimized for Lisp.
:group 'transient
:type '(choice (const :tag "Transform no keys (nil)" nil) function))
-(defcustom transient-semantic-coloring nil
- "Whether to color prefixes and suffixes in Hydra-like fashion.
-This feature is experimental.
+(defcustom transient-semantic-coloring t
+ "Whether to use colors to indicate transient behavior.
If non-nil, then the key binding of each suffix is colorized to
-indicate whether it exits the transient state or not. The color
-of the prefix is indicated using the line that is drawn when the
-value of `transient-mode-line-format' is `line'.
-
-For more information about how Hydra uses colors see
-https://github.com/abo-abo/hydra#color and
-https://oremacs.com/2015/02/19/hydra-colors-reloaded."
- :package-version '(transient . "0.3.0")
+indicate whether it exits the transient state or not, and the
+line that is drawn below the transient popup buffer is used to
+indicate the behavior of non-suffix commands."
+ :package-version '(transient . "0.5.0")
:group 'transient
:type 'boolean)
@@ -355,8 +384,8 @@ text and might otherwise have to scroll in two dimensions."
:group 'transient
:type 'boolean)
+(defconst transient--max-level 7)
(defconst transient--default-child-level 1)
-
(defconst transient--default-prefix-level 4)
(defcustom transient-default-level transient--default-prefix-level
@@ -435,22 +464,18 @@ give you as many additional suffixes as you hoped.)"
"Face used for headings."
:group 'transient-faces)
-(defface transient-key '((t :inherit font-lock-builtin-face))
- "Face used for keys."
- :group 'transient-faces)
-
-(defface transient-argument '((t :inherit font-lock-warning-face))
+(defface transient-argument '((t :inherit font-lock-string-face :weight bold))
"Face used for enabled arguments."
:group 'transient-faces)
-(defface transient-value '((t :inherit font-lock-string-face))
- "Face used for values."
- :group 'transient-faces)
-
(defface transient-inactive-argument '((t :inherit shadow))
"Face used for inactive arguments."
:group 'transient-faces)
+(defface transient-value '((t :inherit font-lock-string-face :weight bold))
+ "Face used for values."
+ :group 'transient-faces)
+
(defface transient-inactive-value '((t :inherit shadow))
"Face used for inactive values."
:group 'transient-faces)
@@ -459,28 +484,14 @@ give you as many additional suffixes as you hoped.)"
"Face used for suffixes unreachable from the current prefix sequence."
:group 'transient-faces)
-(defface transient-active-infix '((t :inherit secondary-selection))
- "Face used for the infix for which the value is being read."
- :group 'transient-faces)
-
-(defface transient-unreachable-key '((t :inherit (transient-key shadow)))
- "Face used for keys unreachable from the current prefix sequence."
- :group 'transient-faces)
-
-(defface transient-nonstandard-key '((t :underline t))
- "Face optionally used to highlight keys conflicting with short-argument.
-Also see option `transient-highlight-mismatched-keys'."
- :group 'transient-faces)
-
-(defface transient-mismatched-key '((t :underline t))
- "Face optionally used to highlight keys without a short-argument.
-Also see option `transient-highlight-mismatched-keys'."
- :group 'transient-faces)
-
(defface transient-inapt-suffix '((t :inherit shadow :italic t))
"Face used for suffixes that are inapt at this time."
:group 'transient-faces)
+(defface transient-active-infix '((t :inherit highlight))
+ "Face used for the infix for which the value is being read."
+ :group 'transient-faces)
+
(defface transient-enabled-suffix
'((t :background "green" :foreground "black" :weight bold))
"Face used for enabled levels while editing suffix levels.
@@ -493,63 +504,83 @@ See info node `(transient)Enabling and Disabling Suffixes'."
See info node `(transient)Enabling and Disabling Suffixes'."
:group 'transient-faces)
-(defface transient-higher-level '((t :underline t))
+(defface transient-higher-level
+ `((t :box ( :line-width ,(if (>= emacs-major-version 28) (cons -1 -1) -1)
+ :color ,(let ((color (face-attribute 'shadow :foreground nil t)))
+ (or (and (not (eq color 'unspecified)) color)
+ "grey60")))))
"Face optionally used to highlight suffixes on higher levels.
Also see option `transient-highlight-higher-levels'."
:group 'transient-faces)
-(defface transient-separator
- `((((class color) (background light))
- ,@(and (>= emacs-major-version 27) '(:extend t))
- :background "grey80")
- (((class color) (background dark))
- ,@(and (>= emacs-major-version 27) '(:extend t))
- :background "grey30"))
- "Face used to draw line below transient popup window.
-This is only used if `transient-mode-line-format' is `line'.
-Only the background color is significant."
+(defface transient-delimiter '((t :inherit shadow))
+ "Face used for delimiters and separators.
+This includes the parentheses around values and the pipe
+character used to separate possible values from each other."
:group 'transient-faces)
-(defgroup transient-color-faces
- '((transient-semantic-coloring custom-variable))
- "Faces used by Transient for Hydra-like command coloring.
-These faces are only used if `transient-semantic-coloring'
-\(which see) is non-nil."
+(defface transient-key '((t :inherit font-lock-builtin-face))
+ "Face used for keys."
:group 'transient-faces)
-(defface transient-red
- '((t :inherit transient-key :foreground "red"))
- "Face used for red prefixes and suffixes."
- :group 'transient-color-faces)
+(defface transient-key-stay
+ `((((class color) (background light))
+ :inherit transient-key
+ :foreground "#22aa22")
+ (((class color) (background dark))
+ :inherit transient-key
+ :foreground "#ddffdd"))
+ "Face used for keys of suffixes that don't exit transient state."
+ :group 'transient-faces)
-(defface transient-blue
- '((t :inherit transient-key :foreground "blue"))
- "Face used for blue prefixes and suffixes."
- :group 'transient-color-faces)
+(defface transient-key-noop
+ `((((class color) (background light))
+ :inherit transient-key
+ :foreground "grey80")
+ (((class color) (background dark))
+ :inherit transient-key
+ :foreground "grey30"))
+ "Face used for keys of suffixes that currently cannot be invoked."
+ :group 'transient-faces)
-(defface transient-amaranth
- '((t :inherit transient-key :foreground "#E52B50"))
- "Face used for amaranth prefixes."
- :group 'transient-color-faces)
+(defface transient-key-return
+ `((((class color) (background light))
+ :inherit transient-key
+ :foreground "#aaaa11")
+ (((class color) (background dark))
+ :inherit transient-key
+ :foreground "#ffffcc"))
+ "Face used for keys of suffixes that return to the parent transient."
+ :group 'transient-faces)
-(defface transient-pink
- '((t :inherit transient-key :foreground "#FF6EB4"))
- "Face used for pink prefixes."
- :group 'transient-color-faces)
+(defface transient-key-exit
+ `((((class color) (background light))
+ :inherit transient-key
+ :foreground "#aa2222")
+ (((class color) (background dark))
+ :inherit transient-key
+ :foreground "#ffdddd"))
+ "Face used for keys of suffixes that exit transient state."
+ :group 'transient-faces)
-(defface transient-teal
- '((t :inherit transient-key :foreground "#367588"))
- "Face used for teal prefixes."
- :group 'transient-color-faces)
+(defface transient-unreachable-key
+ '((t :inherit (shadow transient-key) :weight normal))
+ "Face used for keys unreachable from the current prefix sequence."
+ :group 'transient-faces)
-(defface transient-purple
- '((t :inherit transient-key :foreground "#a020f0"))
- "Face used for purple prefixes.
+(defface transient-nonstandard-key
+ `((t :box ( :line-width ,(if (>= emacs-major-version 28) (cons -1 -1) -1)
+ :color "cyan")))
+ "Face optionally used to highlight keys conflicting with short-argument.
+Also see option `transient-highlight-mismatched-keys'."
+ :group 'transient-faces)
-This is an addition to the colors supported by Hydra. It is
-used by suffixes that quit the current prefix but return to
-the previous prefix."
- :group 'transient-color-faces)
+(defface transient-mismatched-key
+ `((t :box ( :line-width ,(if (>= emacs-major-version 28) (cons -1 -1) -1)
+ :color "magenta")))
+ "Face optionally used to highlight keys without a short-argument.
+Also see option `transient-highlight-mismatched-keys'."
+ :group 'transient-faces)
;;; Persistence
@@ -565,7 +596,9 @@ the previous prefix."
(setq list (cl-sort (copy-sequence list) #'string< :key #'car))
(with-temp-file file
(let ((print-level nil)
- (print-length nil))
+ (print-length nil)
+ (pp-default-function 'pp-28)
+ (fill-column 999))
(pp list (current-buffer)))))
(defvar transient-values
@@ -630,6 +663,8 @@ If `transient-save-history' is nil, then do nothing."
(man-page :initarg :man-page :initform nil)
(transient-suffix :initarg :transient-suffix :initform nil)
(transient-non-suffix :initarg :transient-non-suffix :initform nil)
+ (transient-switch-frame :initarg :transient-switch-frame)
+ (refresh-suffixes :initarg :refresh-suffixes :initform nil)
(incompatible :initarg :incompatible :initform nil)
(suffix-description :initarg :suffix-description)
(variable-pitch :initarg :variable-pitch :initform nil)
@@ -695,7 +730,9 @@ slot is non-nil."
(transient :initarg :transient)
(format :initarg :format :initform " %k %d")
(description :initarg :description :initform nil)
+ (face :initarg :face :initform nil)
(show-help :initarg :show-help :initform nil)
+ (inapt-face :initarg :inapt-face :initform 'transient-inapt-suffix)
(inapt :initform nil)
(inapt-if
:initarg :inapt-if
@@ -731,6 +768,12 @@ slot is non-nil."
:documentation "Inapt if major-mode does not derive from value."))
"Superclass for suffix command.")
+(defclass transient-information (transient-suffix)
+ ((format :initform " %k %d")
+ (key :initform " "))
+ "Display-only information.
+A suffix object with no associated command.")
+
(defclass transient-infix (transient-suffix)
((transient :initform t)
(argument :initarg :argument)
@@ -785,8 +828,8 @@ They become the value of this argument.")
((suffixes :initarg :suffixes :initform nil)
(hide :initarg :hide :initform nil)
(description :initarg :description :initform nil)
- (setup-children :initarg :setup-children)
- (pad-keys :initarg :pad-keys))
+ (pad-keys :initarg :pad-keys :initform nil)
+ (setup-children :initarg :setup-children))
"Abstract superclass of all group classes."
:abstract t)
@@ -929,11 +972,11 @@ explicitly.
The function definitions is always:
- (lambda ()
- (interactive)
- (let ((obj (transient-suffix-object)))
- (transient-infix-set obj (transient-infix-read obj)))
- (transient--show))
+ (lambda ()
+ (interactive)
+ (let ((obj (transient-suffix-object)))
+ (transient-infix-set obj (transient-infix-read obj)))
+ (transient--show))
`transient-infix-read' and `transient-infix-set' are generic
functions. Different infix commands behave differently because
@@ -953,7 +996,7 @@ keyword.
(pcase-let ((`(,class ,slots ,_ ,docstr ,_)
(transient--expand-define-args args arglist)))
`(progn
- (defalias ',name ,(transient--default-infix-command))
+ (defalias ',name #'transient--default-infix-command)
(put ',name 'interactive-only t)
(put ',name 'command-modes (list 'not-a-mode))
(put ',name 'function-documentation ,docstr)
@@ -969,30 +1012,49 @@ example, sets a variable, use `transient-define-infix' instead.
\(fn NAME ARGLIST [DOCSTRING] [KEYWORD VALUE]...)")
-(defun transient--expand-define-args (args &optional arglist)
- (unless (listp arglist)
- (error "Mandatory ARGLIST is missing"))
- (let (class keys suffixes docstr)
- (when (stringp (car args))
- (setq docstr (pop args)))
- (while (keywordp (car args))
- (let ((k (pop args))
- (v (pop args)))
- (if (eq k :class)
- (setq class v)
- (push k keys)
- (push v keys))))
- (while (let ((arg (car args)))
- (or (vectorp arg)
- (and arg (symbolp arg))))
- (push (pop args) suffixes))
- (list (if (eq (car-safe class) 'quote)
- (cadr class)
- class)
- (nreverse keys)
- (nreverse suffixes)
- docstr
- args)))
+(defun transient--default-infix-command ()
+ ;; Most infix commands are but an alias for this command.
+ "Cannot show any documentation for this anonymous infix command.
+
+This infix command was defined anonymously, i.e., it was define
+inside a call to `transient-define-prefix'.
+
+When you request help for such an infix command, then we usually
+show the respective man-page and jump to the location where the
+respective argument is being described. This isn't possible in
+this case, because the `man-page' slot was not set in this case."
+ (interactive)
+ (let ((obj (transient-suffix-object)))
+ (transient-infix-set obj (transient-infix-read obj)))
+ (transient--show))
+(put 'transient--default-infix-command 'interactive-only t)
+(put 'transient--default-infix-command 'command-modes (list 'not-a-mode))
+
+(eval-and-compile
+ (defun transient--expand-define-args (args &optional arglist)
+ (unless (listp arglist)
+ (error "Mandatory ARGLIST is missing"))
+ (let (class keys suffixes docstr)
+ (when (stringp (car args))
+ (setq docstr (pop args)))
+ (while (keywordp (car args))
+ (let ((k (pop args))
+ (v (pop args)))
+ (if (eq k :class)
+ (setq class v)
+ (push k keys)
+ (push v keys))))
+ (while (let ((arg (car args)))
+ (or (vectorp arg)
+ (and arg (symbolp arg))))
+ (push (pop args) suffixes))
+ (list (if (eq (car-safe class) 'quote)
+ (cadr class)
+ class)
+ (nreverse keys)
+ (nreverse suffixes)
+ docstr
+ args))))
(defun transient--parse-child (prefix spec)
(cl-etypecase spec
@@ -1057,8 +1119,9 @@ example, sets a variable, use `transient-define-infix' instead.
(commandp (cadr spec)))
(setq args (plist-put args :description (macroexp-quote pop)))))
(cond
+ ((eq car :info))
((keywordp car)
- (error "Need command, got `%s'" car))
+ (error "Need command or `:info', got `%s'" car))
((symbolp car)
(setq args (plist-put args :command (macroexp-quote pop))))
((and (commandp car)
@@ -1071,11 +1134,19 @@ example, sets a variable, use `transient-define-infix' instead.
(if (and desc (or (stringp desc) (symbolp desc)))
desc
(plist-get args :key)))))))
- (setq args (plist-put args :command
- `(defalias ',sym ,(macroexp-quote cmd))))))
+ (setq args (plist-put
+ args :command
+ `(prog1 ',sym
+ (put ',sym 'interactive-only t)
+ (put ',sym 'command-modes (list 'not-a-mode))
+ (defalias ',sym
+ ,(if (eq (car-safe cmd) 'lambda)
+ cmd
+ (macroexp-quote cmd))))))))
((or (stringp car)
(and car (listp car)))
- (let ((arg pop))
+ (let ((arg pop)
+ (sym nil))
(cl-typecase arg
(list
(setq args (plist-put args :shortarg (car arg)))
@@ -1085,9 +1156,13 @@ example, sets a variable, use `transient-define-infix' instead.
(when-let ((shortarg (transient--derive-shortarg arg)))
(setq args (plist-put args :shortarg shortarg)))
(setq args (plist-put args :argument arg))))
- (setq args (plist-put args :command
- (list 'quote (intern (format "transient:%s:%s"
- prefix arg)))))
+ (setq sym (intern (format "transient:%s:%s" prefix arg)))
+ (setq args (plist-put
+ args :command
+ `(prog1 ',sym
+ (put ',sym 'interactive-only t)
+ (put ',sym 'command-modes (list 'not-a-mode))
+ (defalias ',sym #'transient--default-infix-command))))
(cond ((and car (not (keywordp car)))
(setq class 'transient-option)
(setq args (plist-put args :reader (macroexp-quote pop))))
@@ -1102,6 +1177,9 @@ example, sets a variable, use `transient-define-infix' instead.
(val pop))
(cond ((eq key :class) (setq class val))
((eq key :level) (setq level val))
+ ((eq key :info)
+ (setq class 'transient-information)
+ (setq args (plist-put args :description val)))
((eq (car-safe val) '\,)
(setq args (plist-put args key (cadr val))))
((or (symbolp val)
@@ -1116,26 +1194,6 @@ example, sets a variable, use `transient-define-infix' instead.
(macroexp-quote (or class 'transient-suffix))
(cons 'list args))))
-(defun transient--default-infix-command ()
- (cons 'lambda
- '(()
- (interactive)
- (let ((obj (transient-suffix-object)))
- (transient-infix-set obj (transient-infix-read obj)))
- (transient--show))))
-
-(defun transient--ensure-infix-command (obj)
- (let ((cmd (oref obj command)))
- (unless (or (commandp cmd)
- (get cmd 'transient--infix-command))
- (if (or (cl-typep obj 'transient-switch)
- (cl-typep obj 'transient-option))
- (put cmd 'transient--infix-command
- (transient--default-infix-command))
- ;; This is not an anonymous infix argument.
- (when (transient--use-suffix-p obj)
- (error "Suffix %s is not defined or autoloaded as a command" cmd))))))
-
(defun transient--derive-shortarg (arg)
(save-match-data
(and (string-match "\\`\\(-[a-zA-Z]\\)\\(\\'\\|=\\)" arg)
@@ -1190,11 +1248,11 @@ Intended for use in a group's `:setup-children' function."
(equal (transient--suffix-predicate suf)
(transient--suffix-predicate conflict)))))
(transient-remove-suffix prefix key))
- (cl-ecase action
- (insert (setcdr mem (cons elt (cdr mem)))
- (setcar mem suf))
- (append (setcdr mem (cons suf (cdr mem))))
- (replace (setcar mem suf)))))))
+ (pcase-exhaustive action
+ ('insert (setcdr mem (cons elt (cdr mem)))
+ (setcar mem suf))
+ ('append (setcdr mem (cons suf (cdr mem))))
+ ('replace (setcar mem suf)))))))
;;;###autoload
(defun transient-insert-suffix (prefix loc suffix &optional keep-other)
@@ -1305,7 +1363,7 @@ See info node `(transient)Modifying Existing Transients'."
(delq (car (transient--group-member loc layout))
(aref layout 3)))
nil)
- (t (transient--group-member loc layout))))
+ ((transient--group-member loc layout))))
(defun transient--group-member (loc group)
(cl-member-if (lambda (suffix)
@@ -1334,7 +1392,7 @@ See info node `(transient)Modifying Existing Transients'."
(plist-get plist :command)))))
(defun transient--command-key (cmd)
- (and-let* ((obj (get cmd 'transient--suffix)))
+ (and-let* ((obj (transient--suffix-prototype cmd)))
(cond ((slot-boundp obj 'key)
(oref obj key))
((slot-exists-p obj 'shortarg)
@@ -1375,11 +1433,15 @@ variable instead.")
(defconst transient--exit nil "Do exit the transient.")
(defvar transient--exitp nil "Whether to exit the transient.")
-(defvar transient--showp nil "Whether the transient is show in a popup buffer.")
+(defvar transient--showp nil "Whether to show the transient popup buffer.")
(defvar transient--helpp nil "Whether help-mode is active.")
(defvar transient--editp nil "Whether edit-mode is active.")
-(defvar transient--active-infix nil "The active infix awaiting user input.")
+(defvar transient--refreshp nil
+ "Whether to refresh the transient completely.")
+
+(defvar transient--all-levels-p nil
+ "Whether temporary display of suffixes on all levels is active.")
(defvar transient--timer nil)
@@ -1391,7 +1453,7 @@ variable instead.")
"Name of the transient buffer.")
(defvar transient--window nil
- "The window used to display the transient popup.")
+ "The window used to display the transient popup buffer.")
(defvar transient--original-window nil
"The window that was selected before the transient was invoked.
@@ -1401,7 +1463,24 @@ Usually it remains selected while the transient is active.")
"The buffer that was current before the transient was invoked.
Usually it remains current while the transient is active.")
-(defvar transient--debug nil "Whether put debug information into *Messages*.")
+(defvar transient--restore-winconf nil
+ "Window configuration to restore after exiting help.")
+
+(defvar transient--shadowed-buffer nil
+ "The buffer that is temporarily shadowed by the transient buffer.
+This is bound while the suffix predicate is being evaluated and while
+drawing in the transient buffer.")
+
+(defvar transient--pending-suffix nil
+ "The suffix that is currently being processed.
+This is bound while the suffix predicate is being evaluated.")
+
+(defvar transient--pending-group nil
+ "The group that is currently being processed.
+This is bound while the suffixes are drawn in the transient buffer.")
+
+(defvar transient--debug nil
+ "Whether to put debug information into *Messages*.")
(defvar transient--history nil)
@@ -1413,6 +1492,31 @@ Usually it remains current while the transient is active.")
;;; Identities
+(defun transient-prefix-object ()
+ "Return the current prefix as an object.
+
+While a transient is being setup or refreshed (which involves
+preparing its suffixes) the variable `transient--prefix' can be
+used to access the prefix object. Thus this is what has to be
+used in suffix methods such as `transient-format-description',
+and in object-specific functions that are stored in suffix slots
+such as `description'.
+
+When a suffix command is invoked (i.e., in its `interactive' form
+and function body) then the variable `transient-current-prefix'
+has to be used instead.
+
+Two distinct variables are needed, because any prefix may itself
+be used as a suffix of another prefix, and such sub-prefixes have
+to be able to tell themselves apart from the prefix they were
+invoked from.
+
+Regular suffix commands, which are not prefixes, do not have to
+concern themselves with this distinction, so they can use this
+function instead. In the context of a plain suffix, it always
+returns the value of the appropriate variable."
+ (or transient--prefix transient-current-prefix))
+
(defun transient-suffix-object (&optional command)
"Return the object associated with the current suffix command.
@@ -1420,15 +1524,15 @@ Each suffix commands is associated with an object, which holds
additional information about the suffix, such as its value (in
the case of an infix command, which is a kind of suffix command).
-This function is intended to be called by infix commands, whose
-command definition usually (at least when defined using
-`transient-define-infix') is this:
+This function is intended to be called by infix commands, which
+are usually aliases of `transient--default-infix-command', which
+is defined like this:
- (lambda ()
- (interactive)
- (let ((obj (transient-suffix-object)))
- (transient-infix-set obj (transient-infix-read obj)))
- (transient--show))
+ (defun transient--default-infix-command ()
+ (interactive)
+ (let ((obj (transient-suffix-object)))
+ (transient-infix-set obj (transient-infix-read obj)))
+ (transient--show))
\(User input is read outside of `interactive' to prevent the
command from being added to `command-history'. See #23.)
@@ -1441,7 +1545,7 @@ commands) may also need the object to guide their behavior.
This function attempts to return the object associated with the
current suffix command even if the suffix command was not invoked
from a transient. (For some suffix command that is a valid thing
-to do, for others it is not.) In that case nil may be returned
+to do, for others it is not.) In that case nil may be returned,
if the command was not defined using one of the macros intended
to define such commands.
@@ -1457,7 +1561,7 @@ probably use this instead:
(let ((suffixes
(cl-remove-if-not
(lambda (obj)
- (eq (transient--suffix-command obj)
+ (eq (oref obj command)
(or command
(if (eq this-command 'transient-set-level)
;; This is how it can look up for which
@@ -1473,44 +1577,17 @@ probably use this instead:
(listify-key-sequence (this-command-keys))))
suffixes))
(car suffixes)))
- (when-let* ((obj (get (or command this-command) 'transient--suffix))
- (obj (clone obj)))
- ;; Cannot use and-let* because of debbugs#31840.
- (transient-init-scope obj)
- (transient-init-value obj)
- obj)))
-
-(defun transient--suffix-command (object)
- "Return the command represented by OBJECT.
-
-If the value of OBJECT's `command' slot is a command, then return
-that. Otherwise it is a symbol whose `transient--infix-command'
-property holds an anonymous command, which is returned instead."
- (cl-check-type object transient-suffix)
- (let ((sym (oref object command)))
- (if (commandp sym)
- sym
- (get sym 'transient--infix-command))))
-
-(defun transient--suffix-symbol (arg)
- "Return a symbol representing ARG.
-
-ARG must be a command and/or a symbol. If it is a symbol,
-then just return it. Otherwise return the symbol whose
-`transient--infix-command' property's value is ARG."
- (or (cl-typep arg 'command)
- (cl-typep arg 'symbol)
- (signal 'wrong-type-argument `((command symbol) ,arg)))
- (if (symbolp arg)
- arg
- (let* ((obj (transient-suffix-object))
- (sym (oref obj command)))
- (if (eq (get sym 'transient--infix-command) arg)
- sym
- (catch 'found
- (mapatoms (lambda (sym)
- (when (eq (get sym 'transient--infix-command) arg)
- (throw 'found sym)))))))))
+ (and-let* ((obj (transient--suffix-prototype (or command this-command)))
+ (obj (clone obj)))
+ (progn ; work around debbugs#31840
+ (transient-init-scope obj)
+ (transient-init-value obj)
+ obj))))
+
+(defun transient--suffix-prototype (command)
+ (or (get command 'transient--suffix)
+ (seq-some (lambda (cmd) (get cmd 'transient--suffix))
+ (function-alias-p command))))
;;; Keymaps
@@ -1601,7 +1678,8 @@ to `transient-predicate-map'. Also see `transient-base-map'."
(if transient-show-common-commands
"Hide common commands"
"Show common permanently")))
- (list "C-x l" "Show/hide suffixes" #'transient-set-level))))))))
+ (list "C-x l" "Show/hide suffixes" #'transient-set-level)
+ (list "C-x a" #'transient-toggle-level-limit))))))))
(defvar-keymap transient-popup-navigation-map
:doc "One of the keymaps used when popup navigation is enabled.
@@ -1619,6 +1697,16 @@ See `transient-enable-popup-navigation'."
"<mouse-1>" #'transient-push-button
"<mouse-2>" #'transient-push-button)
+(defvar-keymap transient-resume-mode-map
+ :doc "Keymap for `transient-resume-mode'.
+
+This keymap remaps every command that would usually just quit the
+documentation buffer to `transient-resume', which additionally
+resumes the suspended transient."
+ "<remap> <Man-quit>" #'transient-resume
+ "<remap> <Info-exit>" #'transient-resume
+ "<remap> <quit-window>" #'transient-resume)
+
(defvar-keymap transient-predicate-map
:doc "Base keymap used to map common commands to their transient behavior.
@@ -1654,7 +1742,9 @@ of the corresponding object."
"<transient-update>" #'transient--do-stay
"<transient-toggle-common>" #'transient--do-stay
"<transient-set>" #'transient--do-call
+ "<transient-set-and-exit>" #'transient--do-exit
"<transient-save>" #'transient--do-call
+ "<transient-save-and-exit>" #'transient--do-exit
"<transient-reset>" #'transient--do-call
"<describe-key-briefly>" #'transient--do-stay
"<describe-key>" #'transient--do-stay
@@ -1709,7 +1799,7 @@ of the corresponding object."
(funcall transient-substitute-key-function obj)))
(oset obj key key))
(let ((kbd (kbd key))
- (cmd (transient--suffix-command obj)))
+ (cmd (oref obj command)))
(when-let ((conflict (and transient-detect-key-conflicts
(transient--lookup-key map kbd))))
(unless (eq cmd conflict)
@@ -1730,51 +1820,66 @@ of the corresponding object."
map))
(defun transient--make-predicate-map ()
- (let ((map (make-sparse-keymap)))
+ (let* ((default (transient--resolve-pre-command
+ (oref transient--prefix transient-suffix)))
+ (return (and transient-current-prefix (eq default t)))
+ (map (make-sparse-keymap)))
(set-keymap-parent map transient-predicate-map)
- (when (memq (oref transient--prefix transient-non-suffix)
- '(nil transient--do-warn transient--do-noop))
- (keymap-set map "<handle-switch-frame>" #'transient--do-suspend))
+ (when (or (and (slot-boundp transient--prefix 'transient-switch-frame)
+ (transient--resolve-pre-command
+ (not (oref transient--prefix transient-switch-frame))))
+ (memq (transient--resolve-pre-command
+ (oref transient--prefix transient-non-suffix))
+ '(nil transient--do-warn transient--do-noop)))
+ (define-key map [handle-switch-frame] #'transient--do-suspend))
(dolist (obj transient--suffixes)
(let* ((cmd (oref obj command))
- (sub-prefix (and (symbolp cmd) (get cmd 'transient--prefix) t))
- (sym (transient--suffix-symbol cmd)))
+ (kind (cond ((get cmd 'transient--prefix) 'prefix)
+ ((cl-typep obj 'transient-infix) 'infix)
+ (t 'suffix))))
(cond
((oref obj inapt)
- (define-key map (vector sym) #'transient--do-warn-inapt))
+ (define-key map (vector cmd) #'transient--do-warn-inapt))
((slot-boundp obj 'transient)
- (define-key map (vector sym)
- (let ((do (oref obj transient)))
- (pcase (list do sub-prefix)
- ('(t t) #'transient--do-recurse)
- ('(t nil) (if (cl-typep obj 'transient-infix)
- #'transient--do-stay
- #'transient--do-call))
- ('(nil t) #'transient--do-replace)
- ('(nil nil) #'transient--do-exit)
- (_ do)))))
- ((not (lookup-key transient-predicate-map (vector sym)))
- (define-key map (vector sym)
- (if sub-prefix
- #'transient--do-replace
- (or (oref transient--prefix transient-suffix)
- #'transient--do-exit)))))))
+ (define-key map (vector cmd)
+ (pcase (list kind
+ (transient--resolve-pre-command (oref obj transient))
+ return)
+ (`(prefix t ,_) #'transient--do-recurse)
+ (`(prefix nil ,_) #'transient--do-stack)
+ (`(infix t ,_) #'transient--do-stay)
+ (`(suffix t ,_) #'transient--do-call)
+ ('(suffix nil t) #'transient--do-return)
+ (`(,_ nil ,_) #'transient--do-exit)
+ (`(,_ ,do ,_) do))))
+ ((not (lookup-key transient-predicate-map (vector cmd)))
+ (define-key map (vector cmd)
+ (pcase (list kind default return)
+ (`(prefix ,(or 'transient--do-stay 'transient--do-call) ,_)
+ #'transient--do-recurse)
+ (`(prefix t ,_) #'transient--do-recurse)
+ (`(prefix ,_ ,_) #'transient--do-stack)
+ (`(infix ,_ ,_) #'transient--do-stay)
+ (`(suffix t ,_) #'transient--do-call)
+ ('(suffix nil t) #'transient--do-return)
+ (`(suffix nil ,_) #'transient--do-exit)
+ (`(suffix ,do ,_) do)))))))
map))
(defun transient--make-redisplay-map ()
(setq transient--redisplay-key
- (cl-case this-command
- (transient-update
+ (pcase this-command
+ ('transient-update
(setq transient--showp t)
(setq unread-command-events
(listify-key-sequence (this-single-command-raw-keys))))
- (transient-quit-seq
+ ('transient-quit-seq
(setq unread-command-events
(butlast (listify-key-sequence
(this-single-command-raw-keys))
2))
(butlast transient--redisplay-key))
- (t nil)))
+ (_ nil)))
(let ((topmap (make-sparse-keymap))
(submap (make-sparse-keymap)))
(when transient--redisplay-key
@@ -1818,7 +1923,7 @@ EDIT may be non-nil."
(setq params (list :scope (oref transient--prefix scope))))
(transient--prefix
;; Invoked as a ":transient-non-suffix 'transient--do-{stay,call}"
- ;; of an outer prefix. Unlike the usual `transient--do-replace',
+ ;; of an outer prefix. Unlike the usual `transient--do-stack',
;; these predicates fail to clean up after the outer prefix.
(transient--pop-keymap 'transient--transient-map)
(transient--pop-keymap 'transient--redisplay-map))
@@ -1829,10 +1934,8 @@ EDIT may be non-nil."
;; Returning from help to edit.
(setq transient--editp t)))
(transient--init-objects name layout params)
+ (transient--init-keymaps)
(transient--history-init transient--prefix)
- (setq transient--predicate-map (transient--make-predicate-map))
- (setq transient--transient-map (transient--make-transient-map))
- (setq transient--redisplay-map (transient--make-redisplay-map))
(setq transient--original-window (selected-window))
(setq transient--original-buffer (current-buffer))
(setq transient--minibuffer-depth (minibuffer-depth))
@@ -1849,8 +1952,16 @@ value. Otherwise return CHILDREN as is."
(funcall (oref group setup-children) children)
children))
-(defun transient--init-objects (name layout params)
- (setq transient--prefix (transient--init-prefix name params))
+(defun transient--init-keymaps ()
+ (setq transient--predicate-map (transient--make-predicate-map))
+ (setq transient--transient-map (transient--make-transient-map))
+ (setq transient--redisplay-map (transient--make-redisplay-map)))
+
+(defun transient--init-objects (&optional name layout params)
+ (if name
+ (setq transient--prefix (transient--init-prefix name params))
+ (setq name (oref transient--prefix command)))
+ (setq transient--refreshp (oref transient--prefix refresh-suffixes))
(setq transient--layout (or layout (transient--init-suffixes name)))
(setq transient--suffixes (transient--flatten-suffixes transient--layout)))
@@ -1877,10 +1988,11 @@ value. Otherwise return CHILDREN as is."
(cl-labels ((s (def)
(cond
((stringp def) nil)
+ ((cl-typep def 'transient-information) nil)
((listp def) (cl-mapcan #'s def))
- ((transient-group--eieio-childp def)
+ ((cl-typep def 'transient-group)
(cl-mapcan #'s (oref def suffixes)))
- ((transient-suffix--eieio-childp def)
+ ((cl-typep def 'transient-suffix)
(list def)))))
(cl-mapcan #'s layout)))
@@ -1892,19 +2004,21 @@ value. Otherwise return CHILDREN as is."
(defun transient--init-group (levels spec)
(pcase-let ((`(,level ,class ,args ,children) (append spec nil)))
- (when-let* ((- (transient--use-level-p level))
- (obj (apply class :level level args))
- (- (transient--use-suffix-p obj))
- (suffixes (cl-mapcan (lambda (c) (transient--init-child levels c))
- (transient-setup-children obj children))))
- ;; Cannot use and-let* because of debbugs#31840.
- (oset obj suffixes suffixes)
- (list obj))))
+ (and-let* ((- (transient--use-level-p level))
+ (obj (apply class :level level args))
+ (- (transient--use-suffix-p obj))
+ (suffixes (cl-mapcan (lambda (c) (transient--init-child levels c))
+ (transient-setup-children obj children))))
+ (progn ; work around debbugs#31840
+ (oset obj suffixes suffixes)
+ (list obj)))))
(defun transient--init-suffix (levels spec)
(pcase-let* ((`(,level ,class ,args) spec)
(cmd (plist-get args :command))
- (level (or (alist-get (transient--suffix-symbol cmd) levels)
+ (key (transient--kbd (plist-get args :key)))
+ (level (or (alist-get (cons cmd key) levels nil nil #'equal)
+ (alist-get cmd levels)
level)))
(let ((fn (and (symbolp cmd)
(symbol-function cmd))))
@@ -1912,13 +2026,25 @@ value. Otherwise return CHILDREN as is."
(transient--debug " autoload %s" cmd)
(autoload-do-load fn)))
(when (transient--use-level-p level)
- (let ((obj (if-let ((proto (and cmd
- (symbolp cmd)
- (get cmd 'transient--suffix))))
- (apply #'clone proto :level level args)
- (apply class :level level args))))
- (transient--init-suffix-key obj)
- (transient--ensure-infix-command obj)
+ (let ((obj (if (child-of-class-p class 'transient-information)
+ (apply class :level level args)
+ (unless (and cmd (symbolp cmd))
+ (error "BUG: Non-symbolic suffix command: %s" cmd))
+ (if-let ((proto (and cmd (transient--suffix-prototype cmd))))
+ (apply #'clone proto :level level args)
+ (apply class :command cmd :level level args)))))
+ (cond ((not cmd))
+ ((commandp cmd))
+ ((or (cl-typep obj 'transient-switch)
+ (cl-typep obj 'transient-option))
+ ;; As a temporary special case, if the package was compiled
+ ;; with an older version of Transient, then we must define
+ ;; "anonymous" switch and option commands here.
+ (defalias cmd #'transient--default-infix-command))
+ ((transient--use-suffix-p obj)
+ (error "Suffix command %s is not defined or autoloaded" cmd)))
+ (unless (cl-typep obj 'transient-information)
+ (transient--init-suffix-key obj))
(when (transient--use-suffix-p obj)
(if (transient--inapt-suffix-p obj)
(oset obj inapt t)
@@ -1942,33 +2068,38 @@ value. Otherwise return CHILDREN as is."
(error "No key for %s" (oref obj command))))))
(defun transient--use-level-p (level &optional edit)
- (or (and transient--editp (not edit))
+ (or transient--all-levels-p
+ (and transient--editp (not edit))
(and (>= level 1)
(<= level (oref transient--prefix level)))))
(defun transient--use-suffix-p (obj)
- (transient--do-suffix-p
- (oref obj if)
- (oref obj if-not)
- (oref obj if-nil)
- (oref obj if-non-nil)
- (oref obj if-mode)
- (oref obj if-not-mode)
- (oref obj if-derived)
- (oref obj if-not-derived)
- t))
+ (let ((transient--shadowed-buffer (current-buffer))
+ (transient--pending-suffix obj))
+ (transient--do-suffix-p
+ (oref obj if)
+ (oref obj if-not)
+ (oref obj if-nil)
+ (oref obj if-non-nil)
+ (oref obj if-mode)
+ (oref obj if-not-mode)
+ (oref obj if-derived)
+ (oref obj if-not-derived)
+ t)))
(defun transient--inapt-suffix-p (obj)
- (transient--do-suffix-p
- (oref obj inapt-if)
- (oref obj inapt-if-not)
- (oref obj inapt-if-nil)
- (oref obj inapt-if-non-nil)
- (oref obj inapt-if-mode)
- (oref obj inapt-if-not-mode)
- (oref obj inapt-if-derived)
- (oref obj inapt-if-not-derived)
- nil))
+ (let ((transient--shadowed-buffer (current-buffer))
+ (transient--pending-suffix obj))
+ (transient--do-suffix-p
+ (oref obj inapt-if)
+ (oref obj inapt-if-not)
+ (oref obj inapt-if-nil)
+ (oref obj inapt-if-non-nil)
+ (oref obj inapt-if-mode)
+ (oref obj inapt-if-not-mode)
+ (oref obj inapt-if-derived)
+ (oref obj inapt-if-not-derived)
+ nil)))
(defun transient--do-suffix-p
(if if-not if-nil if-non-nil if-mode if-not-mode if-derived if-not-derived
@@ -1984,13 +2115,15 @@ value. Otherwise return CHILDREN as is."
(if-not-mode (not (if (atom if-not-mode)
(eq major-mode if-not-mode)
(memq major-mode if-not-mode))))
- (if-derived (if (atom if-derived)
+ (if-derived (if (or (atom if-derived)
+ (>= emacs-major-version 30))
(derived-mode-p if-derived)
(apply #'derived-mode-p if-derived)))
- (if-not-derived (not (if (atom if-not-derived)
+ (if-not-derived (not (if (or (atom if-not-derived)
+ (>= emacs-major-version 30))
(derived-mode-p if-not-derived)
(apply #'derived-mode-p if-not-derived))))
- (t default)))
+ (default)))
(defun transient--suffix-predicate (spec)
(let ((plist (nth 2 spec)))
@@ -2021,6 +2154,17 @@ value. Otherwise return CHILDREN as is."
;; that we just added.
(setq transient--exitp 'replace)))
+(defun transient--refresh-transient ()
+ (transient--debug 'refresh-transient)
+ (transient--pop-keymap 'transient--predicate-map)
+ (transient--pop-keymap 'transient--transient-map)
+ (transient--pop-keymap 'transient--redisplay-map)
+ (transient--init-objects)
+ (transient--init-keymaps)
+ (transient--push-keymap 'transient--transient-map)
+ (transient--push-keymap 'transient--redisplay-map)
+ (transient--redisplay))
+
(defun transient--pre-command ()
(transient--debug 'pre-command)
(transient--with-emergency-exit
@@ -2029,8 +2173,8 @@ value. Otherwise return CHILDREN as is."
;; lead to a suffix being remapped to a non-suffix. We have to undo
;; the remapping in that case. However, remapping a non-suffix to
;; another should remain possible.
- (when (and (transient--get-predicate-for this-original-command 'suffix)
- (not (transient--get-predicate-for this-command 'suffix)))
+ (when (and (transient--get-pre-command this-original-command 'suffix)
+ (not (transient--get-pre-command this-command 'suffix)))
(setq this-command this-original-command))
(cond
((memq this-command '(transient-update transient-quit-seq))
@@ -2054,35 +2198,11 @@ value. Otherwise return CHILDREN as is."
(transient--wrap-command))
(t
(setq transient--exitp nil)
- (let ((exitp (eq (transient--do-pre-command) transient--exit)))
+ (let ((exitp (eq (transient--call-pre-command) transient--exit)))
(transient--wrap-command)
(when exitp
(transient--pre-exit)))))))
-(defun transient--do-pre-command ()
- (if-let ((fn (transient--get-predicate-for this-command)))
- (let ((action (funcall fn)))
- (when (eq action transient--exit)
- (setq transient--exitp (or transient--exitp t)))
- action)
- (if (let ((keys (this-command-keys-vector)))
- (eq (aref keys (1- (length keys))) ?\C-g))
- (setq this-command 'transient-noop)
- (unless (transient--edebug-command-p)
- (setq this-command 'transient-undefined)))
- transient--stay))
-
-(defun transient--get-predicate-for (cmd &optional suffix-only)
- (or (ignore-errors
- (lookup-key transient--predicate-map
- (vector (transient--suffix-symbol cmd))))
- (and (not suffix-only)
- (let ((pred (oref transient--prefix transient-non-suffix)))
- (pcase pred
- ('t #'transient--do-stay)
- ('nil #'transient--do-warn)
- (_ pred))))))
-
(defun transient--pre-exit ()
(transient--debug 'pre-exit)
(transient--delete-window)
@@ -2111,8 +2231,9 @@ value. Otherwise return CHILDREN as is."
(and (minibuffer-selected-window)
(selected-window)))
(buf (window-buffer transient--window)))
- ;; Only delete the window if it never showed another buffer.
- (unless (eq (car (window-parameter transient--window 'quit-restore)) 'other)
+ ;; Only delete the window if it has never shown another buffer.
+ (unless (eq (car (window-parameter transient--window 'quit-restore))
+ 'other)
(with-demoted-errors "Error while exiting transient: %S"
(delete-window transient--window)))
(kill-buffer buf)
@@ -2188,37 +2309,65 @@ value. Otherwise return CHILDREN as is."
(remove-hook 'minibuffer-exit-hook ,exit)))
,@body)))
-(defun transient--wrap-command ()
- (let* ((prefix transient--prefix)
- (suffix this-command))
- (letrec ((advice
- (lambda (fn &rest args)
- (interactive
- (lambda (spec)
- (let ((abort t))
+(static-if (>= emacs-major-version 30)
+ (defun transient--wrap-command ()
+ (cl-assert
+ (>= emacs-major-version 30) nil
+ "Emacs was downgraded, making it necessary to recompile Transient")
+ (letrec
+ ((prefix transient--prefix)
+ (suffix this-command)
+ (advice (lambda (fn &rest args)
+ (interactive
+ (lambda (spec)
+ (let ((abort t))
+ (unwind-protect
+ (prog1 (advice-eval-interactive-spec spec)
+ (setq abort nil))
+ (when abort
+ (when-let ((unwind (oref prefix unwind-suffix)))
+ (transient--debug 'unwind-interactive)
+ (funcall unwind suffix))
+ (advice-remove suffix advice)
+ (oset prefix unwind-suffix nil))))))
(unwind-protect
- (prog1 (advice-eval-interactive-spec spec)
- (setq abort nil))
- (when abort
- (when-let ((unwind (oref prefix unwind-suffix)))
- (transient--debug 'unwind-interactive)
- (funcall unwind suffix))
- (if (symbolp suffix)
- (advice-remove suffix advice)
- (remove-function suffix advice))
- (oset prefix unwind-suffix nil))))))
+ (apply fn args)
+ (when-let ((unwind (oref prefix unwind-suffix)))
+ (transient--debug 'unwind-command)
+ (funcall unwind suffix))
+ (advice-remove suffix advice)
+ (oset prefix unwind-suffix nil)))))
+ (advice-add suffix :around advice '((depth . -99)))))
+
+ (defun transient--wrap-command ()
+ (let* ((prefix transient--prefix)
+ (suffix this-command)
+ (advice nil)
+ (advice-interactive
+ (lambda (spec)
+ (let ((abort t))
(unwind-protect
- (apply fn args)
- (when-let ((unwind (oref prefix unwind-suffix)))
- (transient--debug 'unwind-command)
- (funcall unwind suffix))
- (if (symbolp suffix)
- (advice-remove suffix advice)
- (remove-function suffix advice))
- (oset prefix unwind-suffix nil)))))
- (if (symbolp suffix)
- (advice-add suffix :around advice '((depth . -99)))
- (add-function :around (var suffix) advice '((depth . -99)))))))
+ (prog1 (advice-eval-interactive-spec spec)
+ (setq abort nil))
+ (when abort
+ (when-let ((unwind (oref prefix unwind-suffix)))
+ (transient--debug 'unwind-interactive)
+ (funcall unwind suffix))
+ (advice-remove suffix advice)
+ (oset prefix unwind-suffix nil))))))
+ (advice-body
+ (lambda (fn &rest args)
+ (unwind-protect
+ (apply fn args)
+ (when-let ((unwind (oref prefix unwind-suffix)))
+ (transient--debug 'unwind-command)
+ (funcall unwind suffix))
+ (advice-remove suffix advice)
+ (oset prefix unwind-suffix nil)))))
+ (setq advice `(lambda (fn &rest args)
+ (interactive ,advice-interactive)
+ (apply ',advice-body fn args)))
+ (advice-add suffix :around advice '((depth . -99))))))
(defun transient--premature-post-command ()
(and (equal (this-command-keys-vector) [])
@@ -2239,7 +2388,21 @@ value. Otherwise return CHILDREN as is."
(transient--debug 'post-command)
(transient--with-emergency-exit
(cond (transient--exitp (transient--post-exit))
- ((eq this-command (oref transient--prefix command)))
+ ;; If `this-command' is the current transient prefix, then we
+ ;; have already taken care of updating the transient buffer...
+ ((and (eq this-command (oref transient--prefix command))
+ ;; ... but if `prefix-arg' is non-nil, then the values
+ ;; of `this-command' and `real-this-command' are untrue
+ ;; because `prefix-command-preserve-state' changes them.
+ ;; We cannot use `current-prefix-arg' because it is set
+ ;; too late (in `command-execute'), and if it were set
+ ;; earlier, then we likely still would not be able to
+ ;; rely on it and `prefix-command-preserve-state-hook'
+ ;; would have to be used to record that a universal
+ ;; argument is in effect.
+ (not prefix-arg)))
+ (transient--refreshp
+ (transient--refresh-transient))
((let ((old transient--redisplay-map)
(new (transient--make-redisplay-map)))
(unless (equal old new)
@@ -2279,6 +2442,7 @@ value. Otherwise return CHILDREN as is."
(setq transient--exitp nil)
(setq transient--helpp nil)
(setq transient--editp nil)
+ (setq transient--all-levels-p nil)
(setq transient--minibuffer-depth 0)
(run-hooks 'transient-exit-hook)
(when resume
@@ -2289,6 +2453,7 @@ value. Otherwise return CHILDREN as is."
(push (list (oref transient--prefix command)
transient--layout
transient--editp
+ :transient-suffix (oref transient--prefix transient-suffix)
:scope (oref transient--prefix scope))
transient--stack))
@@ -2339,7 +2504,7 @@ value. Otherwise return CHILDREN as is."
(if (symbolp arg)
(message "-- %-22s (cmd: %s, event: %S, exit: %s%s)"
arg
- (or (ignore-errors (transient--suffix-symbol this-command))
+ (or (and (symbolp this-command) this-command)
(if (byte-code-function-p this-command)
"#[...]"
this-command))
@@ -2349,12 +2514,12 @@ value. Otherwise return CHILDREN as is."
(concat ", " (apply #'format args)))
(args
(concat ", " (apply (car args) (cdr args))))
- (t "")))
+ ("")))
(apply #'message arg args)))))
(defun transient--emergency-exit ()
"Exit the current transient command after an error occurred.
-When no transient is active (i.e. when `transient--prefix' is
+When no transient is active (i.e., when `transient--prefix' is
nil) then do nothing."
(transient--debug 'emergency-exit)
(when transient--prefix
@@ -2365,6 +2530,36 @@ nil) then do nothing."
;;; Pre-Commands
+(defun transient--call-pre-command ()
+ (if-let ((fn (transient--get-pre-command this-command)))
+ (let ((action (funcall fn)))
+ (when (eq action transient--exit)
+ (setq transient--exitp (or transient--exitp t)))
+ action)
+ (if (let ((keys (this-command-keys-vector)))
+ (eq (aref keys (1- (length keys))) ?\C-g))
+ (setq this-command 'transient-noop)
+ (unless (transient--edebug-command-p)
+ (setq this-command 'transient-undefined)))
+ transient--stay))
+
+(defun transient--get-pre-command (&optional cmd enforce-type)
+ (or (and (not (eq enforce-type 'non-suffix))
+ (lookup-key transient--predicate-map (vector cmd)))
+ (and (not (eq enforce-type 'suffix))
+ (transient--resolve-pre-command
+ (oref transient--prefix transient-non-suffix)
+ t))))
+
+(defun transient--resolve-pre-command (pre &optional resolve-boolean)
+ (cond ((booleanp pre)
+ (if resolve-boolean
+ (if pre #'transient--do-stay #'transient--do-warn)
+ pre))
+ ((string-match-p "--do-" (symbol-name pre)) pre)
+ ((let ((sym (intern (format "transient--do-%s" pre))))
+ (if (functionp sym) sym pre)))))
+
(defun transient--do-stay ()
"Call the command without exporting variables and stay transient."
transient--stay)
@@ -2405,7 +2600,8 @@ If there is no parent prefix, then behave like `transient--do-exit'."
(defun transient--do-leave ()
"Call the command without exporting variables and exit the transient."
- transient--stay)
+ (transient--stack-zap)
+ transient--exit)
(defun transient--do-push-button ()
"Call the command represented by the activated button.
@@ -2420,26 +2616,35 @@ Use that command's pre-command to determine transient behavior."
(posn-point (event-start last-command-event))
(point))
'command)))
- (transient--do-pre-command)))
+ (transient--call-pre-command)))
(defun transient--do-recurse ()
"Call the transient prefix command, preparing for return to active transient.
If there is no parent prefix, then just call the command."
- (transient--do-replace))
+ (transient--do-stack))
(defun transient--setup-recursion (prefix-obj)
(when transient--stack
(let ((command (oref prefix-obj command)))
(when-let ((suffix-obj (transient-suffix-object command)))
- (when (and (slot-boundp suffix-obj 'transient)
- (memq (oref suffix-obj transient)
- (list t #'transient--do-recurse)))
- (oset prefix-obj transient-suffix 'transient--do-return))))))
+ (when (memq (if (slot-boundp suffix-obj 'transient)
+ (oref suffix-obj transient)
+ (oref transient-current-prefix transient-suffix))
+ (list t #'transient--do-recurse))
+ (oset prefix-obj transient-suffix t))))))
+
+(defun transient--do-stack ()
+ "Call the transient prefix command, stacking the active transient.
+Push the active transient to the transient stack."
+ (transient--export)
+ (transient--stack-push)
+ (setq transient--exitp 'replace)
+ transient--exit)
(defun transient--do-replace ()
- "Call the transient prefix command, replacing the active transient."
+ "Call the transient prefix command, replacing the active transient.
+Do not push the active transient to the transient stack."
(transient--export)
- (transient--stack-push)
(setq transient--exitp 'replace)
transient--exit)
@@ -2458,7 +2663,9 @@ If there is no parent prefix, then just call the command."
(setq transient--editp nil)
(transient-setup)
transient--stay)
- (t transient--exit)))
+ (prefix-arg
+ transient--stay)
+ (transient--exit)))
(defun transient--do-quit-all ()
"Exit all transients without saving the transient stack."
@@ -2470,7 +2677,7 @@ If there is no parent prefix, then just call the command."
In that case behave like `transient--do-stay', otherwise similar
to `transient--do-warn'."
(unless transient-enable-popup-navigation
- (setq this-command 'transient-popup-navigation-help))
+ (setq this-command 'transient-inhibit-move))
transient--stay)
(defun transient--do-minus ()
@@ -2481,22 +2688,27 @@ prefix argument and pivot to `transient-update'."
(setq this-command 'transient-update))
transient--stay)
-(put 'transient--do-stay 'transient-color 'transient-red)
-(put 'transient--do-noop 'transient-color 'transient-red)
-(put 'transient--do-warn 'transient-color 'transient-red)
-(put 'transient--do-warn-inapt 'transient-color 'transient-red)
-(put 'transient--do-call 'transient-color 'transient-red)
-(put 'transient--do-return 'transient-color 'transient-purple)
-(put 'transient--do-exit 'transient-color 'transient-blue)
-(put 'transient--do-recurse 'transient-color 'transient-red)
-(put 'transient--do-replace 'transient-color 'transient-blue)
-(put 'transient--do-suspend 'transient-color 'transient-blue)
-(put 'transient--do-quit-one 'transient-color 'transient-blue)
-(put 'transient--do-quit-all 'transient-color 'transient-blue)
-(put 'transient--do-move 'transient-color 'transient-red)
-(put 'transient--do-minus 'transient-color 'transient-red)
+(put 'transient--do-stay 'transient-face 'transient-key-stay)
+(put 'transient--do-noop 'transient-face 'transient-key-noop)
+(put 'transient--do-warn 'transient-face 'transient-key-noop)
+(put 'transient--do-warn-inapt 'transient-face 'transient-key-noop)
+(put 'transient--do-call 'transient-face 'transient-key-stay)
+(put 'transient--do-return 'transient-face 'transient-key-return)
+(put 'transient--do-exit 'transient-face 'transient-key-exit)
+(put 'transient--do-leave 'transient-face 'transient-key-exit)
+
+(put 'transient--do-recurse 'transient-face 'transient-key-stay)
+(put 'transient--do-stack 'transient-face 'transient-key-stay)
+(put 'transient--do-replace 'transient-face 'transient-key-exit)
+(put 'transient--do-suspend 'transient-face 'transient-key-exit)
+
+(put 'transient--do-quit-one 'transient-face 'transient-key-return)
+(put 'transient--do-quit-all 'transient-face 'transient-key-exit)
+(put 'transient--do-move 'transient-face 'transient-key-stay)
+(put 'transient--do-minus 'transient-face 'transient-key-stay)
;;; Commands
+;;;; Noop
(defun transient-noop ()
"Do nothing at all."
@@ -2522,12 +2734,9 @@ prefix argument and pivot to `transient-update'."
(propertize "?" 'face 'transient-key)
;; `this-command' is `transient-undefined' or `transient-inapt'.
;; Show the command (`this-original-command') the user actually
- ;; tried to invoke. For an anonymous inapt command that is a
- ;; lambda expression, which cannot be mapped to a symbol, so
- ;; forgo displaying the command.
- (if-let ((cmd (ignore-errors
- (symbol-name (transient--suffix-symbol
- this-original-command)))))
+ ;; tried to invoke.
+ (if-let ((cmd (or (ignore-errors (symbol-name this-original-command))
+ (ignore-errors (symbol-name this-command)))))
(format " [%s]" (propertize cmd 'face 'font-lock-warning-face))
""))
(unless (and transient--transient-map
@@ -2538,27 +2747,23 @@ prefix argument and pivot to `transient-update'."
(other-window 1)
(display-warning 'transient "Inconsistent transient state detected.
This should never happen.
-Please open an issue and post the shown command log.
-This is a heisenbug, so any additional details might help.
-Thanks!" :error)))
+Please open an issue and post the shown command log." :error)))
-(defun transient-toggle-common ()
- "Toggle whether common commands are always shown."
+(defun transient-inhibit-move ()
+ "Warn the user that popup navigation is disabled."
(interactive)
- (setq transient-show-common-commands (not transient-show-common-commands)))
+ (message "To enable use of `%s', please customize `%s'"
+ this-original-command
+ 'transient-enable-popup-navigation))
-(defun transient-suspend ()
- "Suspend the current transient.
-It can later be resumed using `transient-resume' while no other
-transient is active."
- (interactive))
+;;;; Core
(defun transient-quit-all ()
"Exit all transients without saving the transient stack."
(interactive))
(defun transient-quit-one ()
- "Exit the current transients, possibly returning to the previous."
+ "Exit the current transients, returning to outer transient, if any."
(interactive))
(defun transient-quit-seq ()
@@ -2568,17 +2773,48 @@ transient is active."
(defun transient-update ()
"Redraw the transient's state in the popup buffer."
(interactive)
- (when (equal this-original-command 'negative-argument)
- (setq prefix-arg current-prefix-arg)))
+ (setq prefix-arg current-prefix-arg))
(defun transient-show ()
"Show the transient's state in the popup buffer."
(interactive)
(setq transient--showp t))
-(defvar-local transient--restore-winconf nil)
+(defun transient-push-button ()
+ "Invoke the suffix command represented by this button."
+ (interactive))
+
+;;;; Suspend
+
+(defun transient-suspend ()
+ "Suspend the current transient.
+It can later be resumed using `transient-resume', while no other
+transient is active."
+ (interactive))
+
+(define-minor-mode transient-resume-mode
+ "Auxiliary minor-mode used to resume a transient after viewing help.")
+
+(defun transient-resume ()
+ "Resume a previously suspended stack of transients."
+ (interactive)
+ (cond (transient--stack
+ (let ((winconf transient--restore-winconf))
+ (kill-local-variable 'transient--restore-winconf)
+ (when transient-resume-mode
+ (transient-resume-mode -1)
+ (quit-window))
+ (when winconf
+ (set-window-configuration winconf)))
+ (transient--stack-pop))
+ (transient-resume-mode
+ (kill-local-variable 'transient--restore-winconf)
+ (transient-resume-mode -1)
+ (quit-window))
+ (t
+ (message "No suspended transient command"))))
-(defvar transient-resume-mode)
+;;;; Help
(defun transient-help (&optional interactive)
"Show help for the active transient or one of its suffixes.\n\n(fn)"
@@ -2595,12 +2831,15 @@ transient is active."
transient--prefix
(or (transient-suffix-object)
this-original-command)))
- (setq transient--restore-winconf winconf))
+ (setq-local transient--restore-winconf winconf))
(fit-window-to-buffer nil (frame-height) (window-height))
(transient-resume-mode)
- (message "Type \"q\" to resume transient command.")
+ (message (substitute-command-keys
+ "Type \\`q' to resume transient command."))
t))))
+;;;; Level
+
(defun transient-set-level (&optional command level)
"Set the level of the transient or one of its suffix commands."
(interactive
@@ -2612,13 +2851,11 @@ transient is active."
(list command
(let ((keys (this-single-command-raw-keys)))
(and (lookup-key transient--transient-map keys)
- (string-to-number
- (let ((transient--active-infix
- (transient-suffix-object command)))
- (transient--show)
+ (progn
+ (transient--show)
+ (string-to-number
(transient--read-number-N
- (format "Set level for `%s': "
- (transient--suffix-symbol command))
+ (format "Set level for `%s': " command)
nil nil (not (eq command prefix)))))))))))
(cond
((not command)
@@ -2627,32 +2864,64 @@ transient is active."
(level
(let* ((prefix (oref transient--prefix command))
(alist (alist-get prefix transient-levels))
- (sym (transient--suffix-symbol command)))
- (if (eq command prefix)
- (progn (oset transient--prefix level level)
- (setq sym t))
- (oset (transient-suffix-object command) level level))
- (setf (alist-get sym alist) level)
+ (akey command))
+ (cond ((eq command prefix)
+ (oset transient--prefix level level)
+ (setq akey t))
+ (t
+ (oset (transient-suffix-object command) level level)
+ (when (cdr (cl-remove-if-not (lambda (obj)
+ (eq (oref obj command) command))
+ transient--suffixes))
+ (setq akey (cons command (this-command-keys))))))
+ (setf (alist-get akey alist) level)
(setf (alist-get prefix transient-levels) alist))
(transient-save-levels)
(transient--show))
(t
(transient-undefined))))
+(transient-define-suffix transient-toggle-level-limit ()
+ "Toggle whether to temporarily displayed suffixes on all levels."
+ :description
+ (lambda ()
+ (cond
+ ((= transient-default-level transient--max-level)
+ "Always displaying all levels")
+ (transient--all-levels-p
+ (format "Hide suffix %s"
+ (propertize
+ (format "levels > %s" (oref (transient-prefix-object) level))
+ 'face 'transient-higher-level)))
+ ("Show all suffix levels")))
+ :inapt-if (lambda () (= transient-default-level transient--max-level))
+ :transient t
+ (interactive)
+ (setq transient--all-levels-p (not transient--all-levels-p))
+ (setq transient--refreshp t))
+
+;;;; Value
+
(defun transient-set ()
- "Save the value of the active transient for this Emacs session."
+ "Set active transient's value for this Emacs session."
(interactive)
- (transient-set-value (or transient--prefix transient-current-prefix)))
+ (transient-set-value (transient-prefix-object)))
+
+(defalias 'transient-set-and-exit 'transient-set
+ "Set active transient's value for this Emacs session and exit.")
(defun transient-save ()
- "Save the value of the active transient persistenly across Emacs sessions."
+ "Save active transient's value for this and future Emacs sessions."
(interactive)
- (transient-save-value (or transient--prefix transient-current-prefix)))
+ (transient-save-value (transient-prefix-object)))
+
+(defalias 'transient-save-and-exit 'transient-save
+ "Save active transient's value for this and future Emacs sessions and exit.")
(defun transient-reset ()
"Clear the set and saved values of the active transient."
(interactive)
- (transient-reset-value (or transient--prefix transient-current-prefix)))
+ (transient-reset-value (transient-prefix-object)))
(defun transient-history-next ()
"Switch to the next value used for the active transient."
@@ -2679,44 +2948,36 @@ transient is active."
(oset obj value (nth pos hst))
(mapc #'transient-init-value transient--suffixes))))
-(defun transient-scroll-up (&optional arg)
- "Scroll text of transient popup window upward ARG lines.
-If ARG is nil scroll near full screen. This is a wrapper
-around `scroll-up-command' (which see)."
- (interactive "^P")
- (with-selected-window transient--window
- (scroll-up-command arg)))
+;;;; Auxiliary
-(defun transient-scroll-down (&optional arg)
- "Scroll text of transient popup window down ARG lines.
-If ARG is nil scroll near full screen. This is a wrapper
-around `scroll-down-command' (which see)."
- (interactive "^P")
- (with-selected-window transient--window
- (scroll-down-command arg)))
-
-(defun transient-push-button ()
- "Invoke the suffix command represented by this button."
- (interactive))
+(defun transient-toggle-common ()
+ "Toggle whether common commands are permanently shown."
+ (interactive)
+ (setq transient-show-common-commands (not transient-show-common-commands)))
-(defun transient-resume ()
- "Resume a previously suspended stack of transients."
+(defun transient-toggle-debug ()
+ "Toggle debugging statements for transient commands."
(interactive)
- (cond (transient--stack
- (let ((winconf transient--restore-winconf))
- (kill-local-variable 'transient--restore-winconf)
- (when transient-resume-mode
- (transient-resume-mode -1)
- (quit-window))
- (when winconf
- (set-window-configuration winconf)))
- (transient--stack-pop))
- (transient-resume-mode
- (kill-local-variable 'transient--restore-winconf)
- (transient-resume-mode -1)
- (quit-window))
- (t
- (message "No suspended transient command"))))
+ (setq transient--debug (not transient--debug))
+ (message "Debugging transient %s"
+ (if transient--debug "enabled" "disabled")))
+
+(transient-define-suffix transient-echo-arguments (arguments)
+ "Show the transient's active ARGUMENTS in the echo area.
+Intended for use in prefixes used for demonstration purposes,
+such as when suggesting a new feature or reporting an issue."
+ :transient t
+ :description "Echo arguments"
+ :key "x"
+ (interactive (list (transient-args transient-current-command)))
+ (message "%s: %s"
+ (key-description (this-command-keys))
+ (mapconcat (lambda (arg)
+ (propertize (if (string-match-p " " arg)
+ (format "%S" arg)
+ arg)
+ 'face 'transient-argument))
+ arguments " ")))
;;; Value
;;;; Init
@@ -2822,28 +3083,18 @@ user using the reader specified by the `reader' slot (using the
`transient-infix' method described below).
For some infix classes the value is changed without reading
-anything in the minibuffer, i.e. the mere act of invoking the
+anything in the minibuffer, i.e., the mere act of invoking the
infix command determines what the new value should be, based
on the previous value.")
(cl-defmethod transient-infix-read :around ((obj transient-infix))
- "Highlight the infix in the popup buffer.
-
-This also wraps the call to `cl-call-next-method' with two
-macros.
-
-`transient--with-suspended-override' is necessary to allow
-reading user input using the minibuffer.
+ "Refresh the transient buffer buffer calling the next method.
-`transient--with-emergency-exit' arranges for the transient to
-be exited in case of an error because otherwise Emacs would get
-stuck in an inconsistent state, which might make it necessary to
-kill it from the outside.
-
-If you replace this method, then you must make sure to always use
-the latter macro and most likely also the former."
- (let ((transient--active-infix obj))
- (transient--show))
+Also wrap `cl-call-next-method' with two macros:
+- `transient--with-suspended-override' allows use of minibuffer.
+- `transient--with-emergency-exit' arranges for the transient to
+ be exited in case of an error."
+ (transient--show)
(transient--with-emergency-exit
(transient--with-suspended-override
(cl-call-next-method obj))))
@@ -2861,7 +3112,7 @@ the lack of history, for example.
Only for very simple classes that toggle or cycle through a very
limited number of possible values should you replace this with a
-simple method that does not handle history. (E.g. for a command
+simple method that does not handle history. (E.g., for a command
line switch the only possible values are \"use it\" and \"don't use
it\", in which case it is pointless to preserve history.)"
(with-slots (value multi-value always-read allow-empty choices) obj
@@ -2872,6 +3123,7 @@ it\", in which case it is pointless to preserve history.)"
(oset obj value nil)
(let* ((enable-recursive-minibuffers t)
(reader (oref obj reader))
+ (choices (if (functionp choices) (funcall choices) choices))
(prompt (transient-prompt obj))
(value (if multi-value (mapconcat #'identity value ",") value))
(history-key (or (oref obj history-key)
@@ -2894,7 +3146,7 @@ it\", in which case it is pointless to preserve history.)"
initial-input history))
(choices
(completing-read prompt choices nil t initial-input history))
- (t (read-string prompt initial-input history)))))
+ ((read-string prompt initial-input history)))))
(cond ((and (equal value "") (not allow-empty))
(setq value nil))
((and (equal value "\"\"") allow-empty)
@@ -2926,7 +3178,7 @@ The last value is \"don't use any of these switches\"."
Use this if you want to share an infix's history with a regular
stand-alone command."
(cl-letf (((symbol-function #'transient--show) #'ignore))
- (transient-infix-read (get command 'transient--suffix))))
+ (transient-infix-read (transient--suffix-prototype command))))
;;;; Readers
@@ -3017,8 +3269,6 @@ prompt."
;;;; Set
-(defvar transient--unset-incompatible t)
-
(cl-defgeneric transient-infix-set (obj value)
"Set the value of infix object OBJ to value.")
@@ -3026,29 +3276,32 @@ prompt."
"Set the value of infix object OBJ to value."
(oset obj value value))
-(cl-defmethod transient-infix-set :around ((obj transient-argument) value)
+(cl-defmethod transient-infix-set :after ((obj transient-argument) value)
"Unset incompatible infix arguments."
- (let ((arg (if (slot-boundp obj 'argument)
- (oref obj argument)
- (oref obj argument-regexp))))
- (if-let ((sic (and value arg transient--unset-incompatible))
- (spec (oref transient--prefix incompatible))
- (incomp (cl-mapcan (lambda (rule)
- (and (member arg rule)
- (remove arg rule)))
- spec)))
- (progn
- (cl-call-next-method obj value)
- (dolist (arg incomp)
- (when-let ((obj (cl-find-if
- (lambda (obj)
- (and (slot-exists-p obj 'argument)
- (slot-boundp obj 'argument)
- (equal (oref obj argument) arg)))
- transient--suffixes)))
- (let ((transient--unset-incompatible nil))
- (transient-infix-set obj nil)))))
- (cl-call-next-method obj value))))
+ (when-let* ((--- value)
+ (val (transient-infix-value obj))
+ (arg (if (slot-boundp obj 'argument)
+ (oref obj argument)
+ (oref obj argument-format)))
+ (spec (oref transient--prefix incompatible))
+ (filter (lambda (x rule)
+ (and (member x rule)
+ (remove x rule))))
+ (incomp (nconc
+ (cl-mapcan (apply-partially filter arg) spec)
+ (and (not (equal val arg))
+ (cl-mapcan (apply-partially filter val) spec)))))
+ (dolist (obj transient--suffixes)
+ (when-let* ((--- (cl-typep obj 'transient-argument))
+ (val (transient-infix-value obj))
+ (arg (if (slot-boundp obj 'argument)
+ (oref obj argument)
+ (oref obj argument-format)))
+ (--- (if (equal val arg)
+ (member arg incomp)
+ (or (member val incomp)
+ (member arg incomp)))))
+ (transient-infix-set obj nil)))))
(cl-defgeneric transient-set-value (obj)
"Set the value of the transient prefix OBJ.")
@@ -3111,11 +3364,11 @@ the set, saved or default value for PREFIX."
(defun transient--get-wrapped-value (obj)
(and-let* ((value (transient-infix-value obj)))
- (cl-ecase (and (slot-exists-p obj 'multi-value)
- (oref obj multi-value))
- ((nil) (list value))
- ((t rest) (list value))
- (repeat value))))
+ (pcase-exhaustive (and (slot-exists-p obj 'multi-value)
+ (oref obj multi-value))
+ ('nil (list value))
+ ((or 't 'rest) (list value))
+ ('repeat value))))
(cl-defgeneric transient-infix-value (obj)
"Return the value of the suffix object OBJ.
@@ -3150,17 +3403,17 @@ does nothing." nil)
"Return ARGUMENT and VALUE as a unit or nil if the latter is nil."
(and-let* ((value (oref obj value)))
(let ((arg (oref obj argument)))
- (cl-ecase (oref obj multi-value)
- ((nil) (concat arg value))
- ((t rest) (cons arg value))
- (repeat (mapcar (lambda (v) (concat arg v)) value))))))
+ (pcase-exhaustive (oref obj multi-value)
+ ('nil (concat arg value))
+ ((or 't 'rest) (cons arg value))
+ ('repeat (mapcar (lambda (v) (concat arg v)) value))))))
(cl-defmethod transient-infix-value ((_ transient-variable))
"Return nil, which means \"no value\".
Setting the value of a variable is done by, well, setting the
-value of the variable. I.e. this is a side-effect and does not
-contribute to the value of the transient."
+value of the variable. I.e., this is a side-effect and does
+not contribute to the value of the transient."
nil)
;;;; Utilities
@@ -3242,12 +3495,13 @@ have a history of their own.")
(list (propertize (oref suffix key) 'face 'transient-key)))))
transient--suffixes)
#'string<)
- (propertize "|" 'face 'transient-unreachable-key))))))
+ (propertize "|" 'face 'transient-delimiter))))))
(defun transient--show ()
(transient--timer-cancel)
(setq transient--showp t)
- (let ((buf (get-buffer-create transient--buffer-name))
+ (let ((transient--shadowed-buffer (current-buffer))
+ (buf (get-buffer-create transient--buffer-name))
(focus nil))
(with-current-buffer buf
(when transient-enable-popup-navigation
@@ -3260,9 +3514,11 @@ have a history of their own.")
(when (bound-and-true-p tab-line-format)
(setq tab-line-format nil))
(setq header-line-format nil)
- (setq mode-line-format (if (eq transient-mode-line-format 'line)
- nil
- transient-mode-line-format))
+ (setq mode-line-format
+ (if (or (natnump transient-mode-line-format)
+ (eq transient-mode-line-format 'line))
+ nil
+ transient-mode-line-format))
(setq mode-line-buffer-identification
(symbol-name (oref transient--prefix command)))
(if transient-enable-popup-navigation
@@ -3273,16 +3529,8 @@ have a history of their own.")
(transient--insert-groups)
(when (or transient--helpp transient--editp)
(transient--insert-help))
- (when (and (eq transient-mode-line-format 'line)
- window-system)
- (let ((face
- (if-let ((f (and (transient--semantic-coloring-p)
- (transient--prefix-color transient--prefix))))
- `(,@(and (>= emacs-major-version 27) '(:extend t))
- :background ,(face-foreground f))
- 'transient-separator)))
- (insert (propertize "__" 'face face 'display '(space :height (1))))
- (insert (propertize "\n" 'face face 'line-height t))))
+ (when-let ((line (transient--separator-line)))
+ (insert line))
(when transient-force-fixed-pitch
(transient--force-fixed-pitch)))
(unless (window-live-p transient--window)
@@ -3304,11 +3552,31 @@ have a history of their own.")
(fit-window-to-buffer window nil (window-height window))
(fit-window-to-buffer window nil 1))))
+(defun transient--separator-line ()
+ (and-let* ((height (cond ((not window-system) nil)
+ ((natnump transient-mode-line-format)
+ transient-mode-line-format)
+ ((eq transient-mode-line-format 'line) 1)))
+ (face `(,@(and (>= emacs-major-version 27) '(:extend t))
+ :background
+ ,(or (face-foreground (transient--key-face nil 'non-suffix)
+ nil t)
+ "#gray60"))))
+ (concat (propertize "__" 'face face 'display `(space :height (,height)))
+ (propertize "\n" 'face face 'line-height t))))
+
+(defmacro transient-with-shadowed-buffer (&rest body)
+ "While in the transient buffer, temporarily make the shadowed buffer current."
+ (declare (indent 0) (debug t))
+ `(with-current-buffer (or transient--shadowed-buffer (current-buffer))
+ ,@body))
+
(defun transient--insert-groups ()
(let ((groups (cl-mapcan (lambda (group)
(let ((hide (oref group hide)))
(and (not (and (functionp hide)
- (funcall hide)))
+ (transient-with-shadowed-buffer
+ (funcall hide))))
(list group))))
transient--layout))
group)
@@ -3324,23 +3592,25 @@ have a history of their own.")
(cl-defmethod transient--insert-group :around ((group transient-group))
"Insert GROUP's description, if any."
- (when-let ((desc (transient-format-description group)))
+ (when-let ((desc (transient-with-shadowed-buffer
+ (transient-format-description group))))
(insert desc ?\n))
(let ((transient--max-group-level
- (max (oref group level) transient--max-group-level)))
+ (max (oref group level) transient--max-group-level))
+ (transient--pending-group group))
(cl-call-next-method group)))
(cl-defmethod transient--insert-group ((group transient-row))
(transient--maybe-pad-keys group)
(dolist (suffix (oref group suffixes))
- (insert (transient-format suffix))
+ (insert (transient-with-shadowed-buffer (transient-format suffix)))
(insert " "))
(insert ?\n))
(cl-defmethod transient--insert-group ((group transient-column))
(transient--maybe-pad-keys group)
(dolist (suffix (oref group suffixes))
- (let ((str (transient-format suffix)))
+ (let ((str (transient-with-shadowed-buffer (transient-format suffix))))
(insert str)
(unless (string-match-p ".\n\\'" str)
(insert ?\n)))))
@@ -3350,10 +3620,11 @@ have a history of their own.")
(mapcar
(lambda (column)
(transient--maybe-pad-keys column group)
- (let ((rows (mapcar #'transient-format (oref column suffixes))))
- (when-let ((desc (transient-format-description column)))
- (push desc rows))
- (flatten-tree rows)))
+ (transient-with-shadowed-buffer
+ (let ((rows (mapcar #'transient-format (oref column suffixes))))
+ (when-let ((desc (transient-format-description column)))
+ (push desc rows))
+ (flatten-tree rows))))
(oref group suffixes)))
(vp (or (oref transient--prefix variable-pitch)
transient-align-variable-pitch))
@@ -3393,15 +3664,6 @@ have a history of their own.")
(when (= c (1- cs))
(insert ?\n))))))))
-(defun transient--pixel-width (string)
- (save-window-excursion
- (with-temp-buffer
- (insert string)
- (set-window-dedicated-p nil nil)
- (set-window-buffer nil (current-buffer))
- (car (window-text-pixel-size
- nil (line-beginning-position) (point))))))
-
(cl-defmethod transient--insert-group ((group transient-subgroups))
(let* ((subgroups (oref group suffixes))
(n (length subgroups)))
@@ -3432,36 +3694,31 @@ making `transient--original-buffer' current.")
"Return a string containing just the ARG character."
(char-to-string arg))
-(cl-defmethod transient-format :around ((obj transient-infix))
- "When reading user input for this infix, then highlight it."
+(cl-defmethod transient-format :around ((obj transient-suffix))
+ "Add additional formatting if appropriate.
+When reading user input for this infix, then highlight it.
+When edit-mode is enabled, then prepend the level information.
+When `transient-enable-popup-navigation' is non-nil then format
+as a button."
(let ((str (cl-call-next-method obj)))
- (when (eq obj transient--active-infix)
- (setq str (concat str "\n"))
- (add-face-text-property
- (if (eq this-command 'transient-set-level) 3 0)
- (length str)
- 'transient-active-infix nil str))
+ (when (and (cl-typep obj 'transient-infix)
+ (eq (oref obj command) this-original-command)
+ (active-minibuffer-window))
+ (setq str (transient--add-face str 'transient-active-infix)))
+ (when transient--editp
+ (setq str (concat (let ((level (oref obj level)))
+ (propertize (format " %s " level)
+ 'face (if (transient--use-level-p level t)
+ 'transient-enabled-suffix
+ 'transient-disabled-suffix)))
+ str)))
+ (when (and transient-enable-popup-navigation
+ (slot-boundp obj 'command))
+ (setq str (make-text-button str nil
+ 'type 'transient
+ 'command (oref obj command))))
str))
-(cl-defmethod transient-format :around ((obj transient-suffix))
- "When edit-mode is enabled, then prepend the level information.
-Optional support for popup buttons is also implemented here."
- (let ((str (concat
- (and transient--editp
- (let ((level (oref obj level)))
- (propertize (format " %s " level)
- 'face (if (transient--use-level-p level t)
- 'transient-enabled-suffix
- 'transient-disabled-suffix))))
- (cl-call-next-method obj))))
- (when (oref obj inapt)
- (add-face-text-property 0 (length str) 'transient-inapt-suffix nil str))
- (if transient-enable-popup-navigation
- (make-text-button str nil
- 'type 'transient
- 'command (transient--suffix-command obj))
- str)))
-
(cl-defmethod transient-format ((obj transient-infix))
"Return a string generated using OBJ's `format'.
%k is formatted using `transient-format-key'.
@@ -3483,10 +3740,19 @@ Optional support for popup buttons is also implemented here."
(cl-defgeneric transient-format-key (obj)
"Format OBJ's `key' for display and return the result.")
+(cl-defmethod transient-format-key :around ((obj transient-suffix))
+ "Add `transient-inapt-suffix' face if suffix is inapt."
+ (let ((str (cl-call-next-method)))
+ (if (oref obj inapt)
+ (transient--add-face str 'transient-inapt-suffix)
+ str)))
+
(cl-defmethod transient-format-key ((obj transient-suffix))
"Format OBJ's `key' for display and return the result."
- (let ((key (oref obj key))
- (cmd (oref obj command)))
+ (let ((key (if (slot-boundp obj 'key) (oref obj key) ""))
+ (cmd (and (slot-boundp obj 'command) (oref obj command))))
+ (when-let ((width (oref transient--pending-group pad-keys)))
+ (setq key (truncate-string-to-width key width nil ?\s)))
(if transient--redisplay-key
(let ((len (length transient--redisplay-key))
(seq (cl-coerce (edmacro-parse-keys key t) 'list)))
@@ -3503,7 +3769,7 @@ Optional support for popup buttons is also implemented here."
(setq pre (string-replace "TAB" "C-i" pre))
(setq suf (string-replace "RET" "C-m" suf))
(setq suf (string-replace "TAB" "C-i" suf))
- ;; We use e.g. "-k" instead of the more correct "- k",
+ ;; We use e.g., "-k" instead of the more correct "- k",
;; because the former is prettier. If we did that in
;; the definition, then we want to drop the space that
;; is reinserted above. False-positives are possible
@@ -3513,33 +3779,27 @@ Optional support for popup buttons is also implemented here."
(setq suf (string-replace " " "" suf)))
(concat (propertize pre 'face 'transient-unreachable-key)
(and (string-prefix-p (concat pre " ") key) " ")
- (transient--colorize-key suf cmd)
+ (propertize suf 'face (transient--key-face cmd))
(save-excursion
(and (string-match " +\\'" key)
(propertize (match-string 0 key)
'face 'fixed-pitch))))))
((transient--lookup-key transient-sticky-map (kbd key))
- (transient--colorize-key key cmd))
+ (propertize key 'face (transient--key-face cmd)))
(t
(propertize key 'face 'transient-unreachable-key))))
- (transient--colorize-key key cmd))))
-
-(defun transient--colorize-key (key command)
- (propertize key 'face
- (or (and (transient--semantic-coloring-p)
- (transient--suffix-color command))
- 'transient-key)))
+ (propertize key 'face (transient--key-face cmd)))))
(cl-defmethod transient-format-key :around ((obj transient-argument))
+ "Handle `transient-highlight-mismatched-keys'."
(let ((key (cl-call-next-method obj)))
- (cond ((not transient-highlight-mismatched-keys))
- ((not (slot-boundp obj 'shortarg))
- (add-face-text-property
- 0 (length key) 'transient-nonstandard-key nil key))
- ((not (string-equal key (oref obj shortarg)))
- (add-face-text-property
- 0 (length key) 'transient-mismatched-key nil key)))
- key))
+ (cond
+ ((not transient-highlight-mismatched-keys) key)
+ ((not (slot-boundp obj 'shortarg))
+ (transient--add-face key 'transient-nonstandard-key))
+ ((not (string-equal key (oref obj shortarg)))
+ (transient--add-face key 'transient-mismatched-key))
+ (key))))
(cl-defgeneric transient-format-description (obj)
"Format OBJ's `description' for display and return the result.")
@@ -3548,10 +3808,14 @@ Optional support for popup buttons is also implemented here."
"The `description' slot may be a function, in which case that is
called inside the correct buffer (see `transient--insert-group')
and its value is returned to the caller."
- (and-let* ((desc (oref obj description)))
- (if (functionp desc)
- (with-current-buffer transient--original-buffer
- (funcall desc))
+ (and-let* ((desc (oref obj description))
+ (desc (if (functionp desc)
+ (if (= (car (func-arity desc)) 1)
+ (funcall desc obj)
+ (funcall desc))
+ desc)))
+ (if-let* ((face (transient--get-face obj 'face)))
+ (transient--add-face desc face t)
desc)))
(cl-defmethod transient-format-description ((obj transient-group))
@@ -3573,16 +3837,19 @@ If the OBJ's `key' is currently unreachable, then apply the face
(funcall (oref transient--prefix suffix-description)
obj))
(propertize "(BUG: no description)" 'face 'error))))
- (cond ((transient--key-unreachable-p obj)
- (propertize desc 'face 'transient-unreachable))
- ((and transient-highlight-higher-levels
- (> (max (oref obj level) transient--max-group-level)
- transient--default-prefix-level))
- (add-face-text-property
- 0 (length desc) 'transient-higher-level nil desc)
- desc)
- (t
- desc))))
+ (when (if transient--all-levels-p
+ (> (oref obj level) transient--default-prefix-level)
+ (and transient-highlight-higher-levels
+ (> (max (oref obj level) transient--max-group-level)
+ transient--default-prefix-level)))
+ (setq desc (transient--add-face desc 'transient-higher-level)))
+ (when-let ((inapt-face (and (oref obj inapt)
+ (transient--get-face obj 'inapt-face))))
+ (setq desc (transient--add-face desc inapt-face)))
+ (when (and (slot-boundp obj 'key)
+ (transient--key-unreachable-p obj))
+ (setq desc (transient--add-face desc 'transient-unreachable)))
+ desc))
(cl-defgeneric transient-format-value (obj)
"Format OBJ's value for display and return the result.")
@@ -3596,24 +3863,32 @@ If the OBJ's `key' is currently unreachable, then apply the face
(cl-defmethod transient-format-value ((obj transient-option))
(let ((argument (oref obj argument)))
(if-let ((value (oref obj value)))
- (propertize
- (cl-ecase (oref obj multi-value)
- ((nil) (concat argument value))
- ((t rest) (concat argument
- (and (not (string-suffix-p " " argument)) " ")
- (mapconcat #'prin1-to-string value " ")))
- (repeat (mapconcat (lambda (v) (concat argument v)) value " ")))
- 'face 'transient-value)
- (propertize argument 'face 'transient-inactive-value))))
+ (pcase-exhaustive (oref obj multi-value)
+ ('nil
+ (concat (propertize argument 'face 'transient-argument)
+ (propertize value 'face 'transient-value)))
+ ((or 't 'rest)
+ (concat (propertize (if (string-suffix-p " " argument)
+ argument
+ (concat argument " "))
+ 'face 'transient-argument)
+ (propertize (mapconcat #'prin1-to-string value " ")
+ 'face 'transient-value)))
+ ('repeat
+ (mapconcat (lambda (value)
+ (concat (propertize argument 'face 'transient-argument)
+ (propertize value 'face 'transient-value)))
+ value " ")))
+ (propertize argument 'face 'transient-inactive-argument))))
(cl-defmethod transient-format-value ((obj transient-switches))
(with-slots (value argument-format choices) obj
(format (propertize argument-format
'face (if value
- 'transient-value
- 'transient-inactive-value))
- (concat
- (propertize "[" 'face 'transient-inactive-value)
+ 'transient-argument
+ 'transient-inactive-argument))
+ (format
+ (propertize "[%s]" 'face 'transient-delimiter)
(mapconcat
(lambda (choice)
(propertize choice 'face
@@ -3621,8 +3896,30 @@ If the OBJ's `key' is currently unreachable, then apply the face
'transient-value
'transient-inactive-value)))
choices
- (propertize "|" 'face 'transient-inactive-value))
- (propertize "]" 'face 'transient-inactive-value)))))
+ (propertize "|" 'face 'transient-delimiter))))))
+
+(defun transient--add-face (string face &optional append beg end)
+ (let ((str (copy-sequence string)))
+ (add-face-text-property (or beg 0) (or end (length str)) face append str)
+ str))
+
+(defun transient--get-face (obj slot)
+ (and-let* ((! (slot-exists-p obj slot))
+ (! (slot-boundp obj slot))
+ (face (slot-value obj slot)))
+ (if (and (not (facep face))
+ (functionp face))
+ (funcall face)
+ face)))
+
+(defun transient--key-face (&optional cmd enforce-type)
+ (or (and transient-semantic-coloring
+ (not transient--helpp)
+ (not transient--editp)
+ (or (and cmd (get cmd 'transient-face))
+ (get (transient--get-pre-command cmd enforce-type)
+ 'transient-face)))
+ (if cmd 'transient-key 'transient-key-noop)))
(defun transient--key-unreachable-p (obj)
(and transient--redisplay-key
@@ -3637,19 +3934,24 @@ If the OBJ's `key' is currently unreachable, then apply the face
(and val (not (integerp val)) val)))
(defun transient--maybe-pad-keys (group &optional parent)
- (when-let ((pad (if (slot-boundp group 'pad-keys)
- (oref group pad-keys)
- (and parent
- (slot-boundp parent 'pad-keys)
- (oref parent pad-keys)))))
- (let ((width (apply #'max
- (cons (if (integerp pad) pad 0)
- (mapcar (lambda (suffix)
- (length (oref suffix key)))
- (oref group suffixes))))))
- (dolist (suffix (oref group suffixes))
- (oset suffix key
- (truncate-string-to-width (oref suffix key) width nil ?\s))))))
+ (when-let ((pad (or (oref group pad-keys)
+ (and parent (oref parent pad-keys)))))
+ (oset group pad-keys
+ (apply #'max (cons (if (integerp pad) pad 0)
+ (seq-keep (lambda (suffix)
+ (and (eieio-object-p suffix)
+ (slot-boundp suffix 'key)
+ (length (oref suffix key))))
+ (oref group suffixes)))))))
+
+(defun transient--pixel-width (string)
+ (save-window-excursion
+ (with-temp-buffer
+ (insert string)
+ (set-window-dedicated-p nil nil)
+ (set-window-buffer nil (current-buffer))
+ (car (window-text-pixel-size
+ nil (line-beginning-position) (point))))))
(defun transient-command-summary-or-name (obj)
"Return the summary or name of the command represented by OBJ.
@@ -3659,7 +3961,7 @@ that, else its name.
Intended to be temporarily used as the `:suffix-description' of
a prefix command, while porting a regular keymap to a transient."
- (let ((command (transient--suffix-symbol (oref obj command))))
+ (let ((command (oref obj command)))
(if-let ((doc (documentation command)))
(propertize (car (split-string doc "\n")) 'face 'font-lock-doc-face)
(propertize (symbol-name command) 'face 'font-lock-function-name-face))))
@@ -3677,7 +3979,7 @@ if non-nil, else show the `man-page' if non-nil, else use
(cond (show-help (funcall show-help obj))
(info-manual (transient--show-manual info-manual))
(man-page (transient--show-manpage man-page))
- (t (transient--describe-function command)))))
+ ((transient--describe-function command)))))
(cl-defmethod transient-show-help ((obj transient-suffix))
"Call `show-help' if non-nil, else use `describe-function'.
@@ -3687,13 +3989,13 @@ prefix method."
(cond
((eq this-command 'transient-help)
(transient-show-help transient--prefix))
- ((let ((prefix (get (transient--suffix-command obj)
+ ((let ((prefix (get (oref obj command)
'transient--prefix)))
(and prefix (not (eq (oref transient--prefix command) this-command))
(prog1 t (transient-show-help prefix)))))
- (t (if-let ((show-help (oref obj show-help)))
- (funcall show-help obj)
- (transient--describe-function this-command)))))
+ ((if-let ((show-help (oref obj show-help)))
+ (funcall show-help obj)
+ (transient--describe-function this-command)))))
(cl-defmethod transient-show-help ((obj transient-infix))
"Call `show-help' if non-nil, else show the `man-page'
@@ -3713,7 +4015,7 @@ manpage, then try to jump to the correct location."
(transient--describe-function cmd))
(defun transient--describe-function (fn)
- (describe-function (if (symbolp fn) fn 'transient--anonymous-infix-argument))
+ (describe-function fn)
(unless (derived-mode-p 'help-mode)
(when-let* ((buf (get-buffer "*Help*"))
(win (or (and buf (get-buffer-window buf))
@@ -3723,21 +4025,6 @@ manpage, then try to jump to the correct location."
(window-list)))))
(select-window win))))
-(defun transient--anonymous-infix-argument ()
- "Cannot show any documentation for this anonymous infix command.
-
-The infix command in question was defined anonymously, i.e.,
-it was define when the prefix command that it belongs to was
-defined, which means that it gets no docstring and also that
-no symbol is bound to it.
-
-When you request help for an infix command, then we usually
-show the respective man-page and jump to the location where
-the respective argument is being described.
-
-Because the containing prefix command does not specify any
-man-page, we cannot do that in this case. Sorry about that.")
-
(defun transient--show-manual (manual)
(info manual))
@@ -3830,37 +4117,23 @@ Suffixes on levels %s and %s are unavailable.\n"
(propertize (format ">=%s" (1+ level))
'face 'transient-disabled-suffix))))))
-(defvar-keymap transient-resume-mode-map
- :doc "Keymap for `transient-resume-mode'.
-
-This keymap remaps every command that would usually just quit the
-documentation buffer to `transient-resume', which additionally
-resumes the suspended transient."
- "<remap> <Man-quit>" #'transient-resume
- "<remap> <Info-exit>" #'transient-resume
- "<remap> <quit-window>" #'transient-resume)
-
-(define-minor-mode transient-resume-mode
- "Auxiliary minor-mode used to resume a transient after viewing help.")
-
-(defun transient-toggle-debug ()
- "Toggle debugging statements for transient commands."
- (interactive)
- (setq transient--debug (not transient--debug))
- (message "Debugging transient %s"
- (if transient--debug "enabled" "disabled")))
-
;;; Popup Navigation
-(defun transient-popup-navigation-help ()
- "Inform the user how to enable popup navigation commands."
- (interactive)
- (message "This command is only available if `%s' is non-nil"
- 'transient-enable-popup-navigation))
+(defun transient-scroll-up (&optional arg)
+ "Scroll text of transient popup window upward ARG lines.
+If ARG is nil scroll near full screen. This is a wrapper
+around `scroll-up-command' (which see)."
+ (interactive "^P")
+ (with-selected-window transient--window
+ (scroll-up-command arg)))
-(define-button-type 'transient
- 'face nil
- 'keymap transient-button-map)
+(defun transient-scroll-down (&optional arg)
+ "Scroll text of transient popup window down ARG lines.
+If ARG is nil scroll near full screen. This is a wrapper
+around `scroll-down-command' (which see)."
+ (interactive "^P")
+ (with-selected-window transient--window
+ (scroll-down-command arg)))
(defun transient-backward-button (n)
"Move to the previous button in the transient popup buffer.
@@ -3876,6 +4149,10 @@ See `forward-button' for information about N."
(with-selected-window transient--window
(forward-button n t)))
+(define-button-type 'transient
+ 'face nil
+ 'keymap transient-button-map)
+
(defun transient--goto-button (command)
(cond
((stringp command)
@@ -3953,36 +4230,6 @@ search instead."
(select-window transient--original-window)
(transient--resume-override))
-;;;; Hydra Color Emulation
-
-(defun transient--semantic-coloring-p ()
- (and transient-semantic-coloring
- (not transient--helpp)
- (not transient--editp)))
-
-(defun transient--suffix-color (command)
- (or (get command 'transient-color)
- (get (transient--get-predicate-for command) 'transient-color)))
-
-(defun transient--prefix-color (command)
- (let* ((nonsuf (or (oref command transient-non-suffix)
- 'transient--do-warn))
- (nonsuf (if (memq nonsuf '(transient--do-noop transient--do-warn))
- 'disallow
- (get nonsuf 'transient-color)))
- (suffix (if-let ((pred (oref command transient-suffix)))
- (get pred 'transient-color)
- (if (eq nonsuf 'transient-red)
- 'transient-red
- 'transient-blue))))
- (pcase (list suffix nonsuf)
- (`(transient-purple ,_) 'transient-purple)
- ('(transient-red disallow) 'transient-amaranth)
- ('(transient-blue disallow) 'transient-teal)
- ('(transient-red transient-red) 'transient-pink)
- ('(transient-red transient-blue) 'transient-red)
- ('(transient-blue transient-blue) 'transient-blue))))
-
;;;; Edebug
(defun transient--edebug-command-p ()
@@ -4044,7 +4291,7 @@ we stop there."
(let ((key (oref obj key)))
(cond ((string-equal key "q") "Q")
((string-equal key "Q") "M-q")
- (t key))))
+ (key))))
(defun transient--force-fixed-pitch ()
(require 'face-remap)
@@ -4079,8 +4326,7 @@ we stop there."
(regexp-opt (list "transient-define-prefix"
"transient-define-infix"
"transient-define-argument"
- "transient-define-suffix"
- "transient-define-groups")
+ "transient-define-suffix")
t)
"\\_>[ \t'(]*"
"\\(\\(?:\\sw\\|\\s_\\)+\\)?")
diff --git a/lisp/tree-widget.el b/lisp/tree-widget.el
index 01091f5493b..9321bff0373 100644
--- a/lisp/tree-widget.el
+++ b/lisp/tree-widget.el
@@ -1,6 +1,6 @@
;;; tree-widget.el --- Tree widget -*- lexical-binding:t -*-
-;; Copyright (C) 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2004-2024 Free Software Foundation, Inc.
;; Author: David Ponce <david@dponce.com>
;; Created: 16 Feb 2001
diff --git a/lisp/treesit.el b/lisp/treesit.el
index a9761dbb38d..a68eed06e41 100644
--- a/lisp/treesit.el
+++ b/lisp/treesit.el
@@ -1,6 +1,6 @@
;;; treesit.el --- tree-sitter utilities -*- lexical-binding: t -*-
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
;; Maintainer: 付禹安 (Yuan Fu) <casouri@gmail.com>
;; Keywords: treesit, tree-sitter, languages
@@ -32,9 +32,8 @@
;;; Code:
-(eval-when-compile (require 'cl-lib))
(eval-when-compile (require 'subr-x)) ; For `string-join'.
-(require 'cl-seq)
+(require 'cl-lib)
(require 'font-lock)
(require 'seq)
@@ -56,6 +55,7 @@
(declare-function treesit-parser-list "treesit.c")
(declare-function treesit-parser-buffer "treesit.c")
(declare-function treesit-parser-language "treesit.c")
+(declare-function treesit-parser-tag "treesit.c")
(declare-function treesit-parser-root-node "treesit.c")
@@ -92,6 +92,8 @@
(declare-function treesit-available-p "treesit.c")
+(defvar treesit-thing-settings)
+
;;; Custom options
;; Tree-sitter always appear as treesit in symbols.
@@ -133,14 +135,26 @@ Return the root node of the syntax tree."
This is used by `treesit-language-at', which is used by various
functions to determine which parser to use at point.
-The function is called with one argument, the position of point.")
+The function is called with one argument, the position of point.
+
+In general, this function should call `treesit-node-at' with an
+explicit language (usually the host language), and determine the
+language at point using the type of the returned node.
+
+DO NOT derive the language at point from parser ranges. It's
+cumbersome and can't deal with some edge cases.")
(defun treesit-language-at (position)
"Return the language at POSITION.
+
This function assumes that parser ranges are up-to-date. It
returns the return value of `treesit-language-at-point-function'
if it's non-nil, otherwise it returns the language of the first
-parser in `treesit-parser-list', or nil if there is no parser."
+parser in `treesit-parser-list', or nil if there is no parser.
+
+In a multi-language buffer, make sure
+`treesit-language-at-point-function' is implemented! Otherwise
+`treesit-language-at' wouldn't return the correct result."
(if treesit-language-at-point-function
(funcall treesit-language-at-point-function position)
(when-let ((parser (car (treesit-parser-list))))
@@ -184,11 +198,20 @@ only look for named nodes.
If PARSER-OR-LANG is a parser, use that parser; if PARSER-OR-LANG
is a language, find the first parser for that language in the
current buffer, or create one if none exists; If PARSER-OR-LANG
-is nil, try to guess the language at POS using `treesit-language-at'."
+is nil, try to guess the language at POS using `treesit-language-at'.
+
+If there's a local parser at POS, the local parser takes priority
+unless PARSER-OR-LANG is a parser, or PARSER-OR-LANG is a
+language and doesn't match the language of the local parser."
(let* ((root (if (treesit-parser-p parser-or-lang)
(treesit-parser-root-node parser-or-lang)
- (treesit-buffer-root-node
- (or parser-or-lang (treesit-language-at pos)))))
+ (or (when-let ((parser
+ (car (treesit-local-parsers-at
+ pos parser-or-lang))))
+ (treesit-parser-root-node parser))
+ (treesit-buffer-root-node
+ (or parser-or-lang
+ (treesit-language-at pos))))))
(node root)
(node-before root)
(pos-1 (max (1- pos) (point-min)))
@@ -233,11 +256,20 @@ named node.
If PARSER-OR-LANG is a parser, use that parser; if PARSER-OR-LANG
is a language, find the first parser for that language in the
current buffer, or create one if none exists; If PARSER-OR-LANG
-is nil, try to guess the language at BEG using `treesit-language-at'."
- (let ((root (if (treesit-parser-p parser-or-lang)
- (treesit-parser-root-node parser-or-lang)
- (treesit-buffer-root-node
- (or parser-or-lang (treesit-language-at beg))))))
+is nil, try to guess the language at BEG using `treesit-language-at'.
+
+If there's a local parser between BEG and END, try to use that
+parser first."
+ (let* ((lang-at-point (treesit-language-at beg))
+ (root (if (treesit-parser-p parser-or-lang)
+ (treesit-parser-root-node parser-or-lang)
+ (or (when-let ((parser
+ (car (treesit-local-parsers-on
+ beg end (or parser-or-lang
+ lang-at-point)))))
+ (treesit-parser-root-node parser))
+ (treesit-buffer-root-node
+ (or parser-or-lang lang-at-point))))))
(treesit-node-descendant-for-range root beg (or end beg) named)))
(defun treesit-node-top-level (node &optional pred include-node)
@@ -257,19 +289,21 @@ If INCLUDE-NODE is non-nil, return NODE if it satisfies PRED."
(treesit-node-parent node))
then (treesit-node-parent cursor)
while cursor
- if (treesit-node-match-p cursor pred)
+ if (treesit-node-match-p cursor pred t)
do (setq result cursor))
result))
-(defun treesit-buffer-root-node (&optional language)
+(defun treesit-buffer-root-node (&optional language tag)
"Return the root node of the current buffer.
Use the first parser in the parser list if LANGUAGE is omitted.
-If LANGUAGE is non-nil, use the first parser for LANGUAGE in the
-parser list, or create one if none exists."
+
+If LANGUAGE is non-nil, use the first parser for LANGUAGE with
+TAG in the parser list, or create one if none exists. TAG
+defaults to nil."
(if-let ((parser
(if language
- (treesit-parser-create language)
+ (treesit-parser-create language nil nil tag)
(or (car (treesit-parser-list))
(signal 'treesit-no-parser (list (current-buffer)))))))
(treesit-parser-root-node parser)))
@@ -405,6 +439,41 @@ unlike in their original functions."
(treesit-node-prev-sibling node named)))))))
node)
+(defun treesit-node-enclosed-p (smaller larger &optional strict)
+ "Return non-nil if SMALLER is enclosed in LARGER.
+SMALLER and LARGER can be either (BEG . END) or a node.
+
+Return non-nil if LARGER's start <= SMALLER's start and LARGER's
+end <= SMALLER's end.
+
+If STRICT is t, compare with < rather than <=.
+
+If STRICT is \\='partial, consider LARGER encloses SMALLER when
+at least one side is strictly enclosing."
+ (unless (and (or (consp larger) (treesit-node-p larger))
+ (or (consp smaller) (treesit-node-p smaller)))
+ (signal 'wrong-type-argument '((or cons treesit-node))))
+ (let ((larger-start (if (consp larger)
+ (car larger)
+ (treesit-node-start larger)))
+ (larger-end (if (consp larger)
+ (cdr larger)
+ (treesit-node-end larger)))
+ (smaller-start (if (consp smaller)
+ (car smaller)
+ (treesit-node-start smaller)))
+ (smaller-end (if (consp smaller)
+ (cdr smaller)
+ (treesit-node-end smaller))))
+ (pcase strict
+ ('t (and (< larger-start smaller-start)
+ (< smaller-end larger-end)))
+ ('partial (and (or (not (eq larger-start smaller-start))
+ (not (eq larger-end smaller-end)))
+ (<= larger-start smaller-start
+ smaller-end larger-end)))
+ (_ (<= larger-start smaller-start smaller-end larger-end)))))
+
;;; Query API supplement
(defun treesit-query-string (string query language)
@@ -417,32 +486,40 @@ See `treesit-query-capture' for QUERY."
(treesit-parser-root-node parser)
query))))
-(defun treesit-query-range (node query &optional beg end)
+(defun treesit-query-range (node query &optional beg end offset)
"Query the current buffer and return ranges of captured nodes.
QUERY, NODE, BEG, END are the same as in `treesit-query-capture'.
This function returns a list of (START . END), where START and
-END specifics the range of each captured node. Capture names
-generally don't matter, but names that starts with an underscore
-are ignored."
- (cl-loop for capture
- in (treesit-query-capture node query beg end)
- for name = (car capture)
- for node = (cdr capture)
- if (not (string-prefix-p "_" (symbol-name name)))
- collect (cons (treesit-node-start node)
- (treesit-node-end node))))
+END specifics the range of each captured node. OFFSET is an
+optional pair of numbers (START-OFFSET . END-OFFSET). The
+respective offset values are added to each (START . END) range
+being returned. Capture names generally don't matter, but names
+that starts with an underscore are ignored."
+ (let ((offset-left (or (car offset) 0))
+ (offset-right (or (cdr offset) 0)))
+ (cl-loop for capture
+ in (treesit-query-capture node query beg end)
+ for name = (car capture)
+ for node = (cdr capture)
+ if (not (string-prefix-p "_" (symbol-name name)))
+ collect (cons (+ (treesit-node-start node) offset-left)
+ (+ (treesit-node-end node) offset-right)))))
;;; Range API supplement
(defvar-local treesit-range-settings nil
"A list of range settings.
-Each element of the list is of the form (QUERY LANGUAGE).
-When updating the range of each parser in the buffer,
+Each element of the list is of the form (QUERY LANGUAGE LOCAL-P
+OFFSET). When updating the range of each parser in the buffer,
`treesit-update-ranges' queries each QUERY, and sets LANGUAGE's
range to the range spanned by captured nodes. QUERY must be a
-compiled query.
+compiled query. If LOCAL-P is t, give each range a separate
+local parser rather than using a single parser for all the
+ranges. If OFFSET is non-nil, it should be a cons of
+numbers (START-OFFSET . END-OFFSET), where the start and end
+offset are added to each queried range to get the result ranges.
Capture names generally don't matter, but names that starts with
an underscore are ignored.
@@ -475,6 +552,7 @@ it. For example,
(treesit-range-rules
:embed \\='javascript
:host \\='html
+ :offset \\='(1 . -1)
\\='((script_element (raw_text) @cap)))
The `:embed' keyword specifies the embedded language, and the
@@ -483,15 +561,28 @@ this way: Emacs queries QUERY in the host language's parser,
computes the ranges spanned by the captured nodes, and applies
these ranges to parsers for the embedded language.
+If there's a `:local' keyword with value t, the range computed by
+this QUERY is given a dedicated local parser. Otherwise, the
+range shares the same parser with other ranges.
+
+If there's an `:offset' keyword with a pair of numbers, each
+captured range is offset by those numbers. For example, an
+offset of (1 . -1) will update a captured range of (2 . 8) to
+be (3 . 7). This can be used to exclude things like surrounding
+delimiters from being included in the range covered by an
+embedded parser.
+
QUERY can also be a function that takes two arguments, START and
END. If QUERY is a function, it doesn't need the :KEYWORD VALUE
pair preceding it. This function should set the ranges for
parsers in the current buffer in the region between START and
END. It is OK for this function to set ranges in a larger region
that encompasses the region between START and END."
- (let (host embed result)
+ (let (host embed offset result local)
(while query-specs
(pcase (pop query-specs)
+ (:local (when (eq t (pop query-specs))
+ (setq local t)))
(:host (let ((host-lang (pop query-specs)))
(unless (symbolp host-lang)
(signal 'treesit-error (list "Value of :host option should be a symbol" host-lang)))
@@ -500,6 +591,12 @@ that encompasses the region between START and END."
(unless (symbolp embed-lang)
(signal 'treesit-error (list "Value of :embed option should be a symbol" embed-lang)))
(setq embed embed-lang)))
+ (:offset (let ((range-offset (pop query-specs)))
+ (unless (and (consp range-offset)
+ (numberp (car range-offset))
+ (numberp (cdr range-offset)))
+ (signal 'treesit-error (list "Value of :offset option should be a pair of numbers" range-offset)))
+ (setq offset range-offset)))
(query (if (functionp query)
(push (list query nil nil) result)
(when (null embed)
@@ -507,9 +604,9 @@ that encompasses the region between START and END."
(when (null host)
(signal 'treesit-error (list "Value of :host option cannot be omitted")))
(push (list (treesit-query-compile host query)
- embed host)
+ embed local offset)
result))
- (setq host nil embed nil))))
+ (setq host nil embed nil offset nil))))
(nreverse result)))
(defun treesit--merge-ranges (old-ranges new-ranges start end)
@@ -558,6 +655,73 @@ those inside are kept."
if (<= start (car range) (cdr range) end)
collect range))
+(defun treesit-local-parsers-at (&optional pos language)
+ "Return all the local parsers at POS.
+
+POS defaults to point.
+Local parsers are those which only parse a limited region marked
+by an overlay with non-nil `treesit-parser' property.
+If LANGUAGE is non-nil, only return parsers for LANGUAGE."
+ (let ((res nil))
+ (dolist (ov (overlays-at (or pos (point))))
+ (when-let ((parser (overlay-get ov 'treesit-parser)))
+ (when (or (null language)
+ (eq (treesit-parser-language parser)
+ language))
+ (push parser res))))
+ (nreverse res)))
+
+(defun treesit-local-parsers-on (&optional beg end language)
+ "Return all the local parsers between BEG END.
+
+BEG and END default to the beginning and end of the buffer's
+accessible portion.
+Local parsers are those which have an `embedded' tag, and only parse
+a limited region marked by an overlay with a non-nil `treesit-parser'
+property. If LANGUAGE is non-nil, only return parsers for LANGUAGE."
+ (let ((res nil))
+ (dolist (ov (overlays-in (or beg (point-min)) (or end (point-max))))
+ (when-let ((parser (overlay-get ov 'treesit-parser)))
+ (when (or (null language)
+ (eq (treesit-parser-language parser)
+ language))
+ (push parser res))))
+ (nreverse res)))
+
+(defun treesit--update-ranges-local
+ (query embedded-lang &optional beg end)
+ "Update range for local parsers between BEG and END.
+Use QUERY to get the ranges, and make sure each range has a local
+parser for EMBEDDED-LANG."
+ ;; Clean up.
+ (dolist (ov (overlays-in (or beg (point-min)) (or end (point-max))))
+ (when-let ((parser (overlay-get ov 'treesit-parser)))
+ (when (eq (overlay-start ov) (overlay-end ov))
+ (delete-overlay ov)
+ (treesit-parser-delete parser))))
+ ;; Update range.
+ (let* ((host-lang (treesit-query-language query))
+ (ranges (treesit-query-range host-lang query beg end)))
+ (pcase-dolist (`(,beg . ,end) ranges)
+ (let ((has-parser nil))
+ (dolist (ov (overlays-in beg end))
+ ;; Update range of local parser.
+ (let ((embedded-parser (overlay-get ov 'treesit-parser)))
+ (when (and (treesit-parser-p embedded-parser)
+ (eq (treesit-parser-language embedded-parser)
+ embedded-lang))
+ (treesit-parser-set-included-ranges
+ embedded-parser `((,beg . ,end)))
+ (setq has-parser t))))
+ ;; Create overlay and local parser.
+ (when (not has-parser)
+ (let ((embedded-parser (treesit-parser-create
+ embedded-lang nil t 'embedded))
+ (ov (make-overlay beg end nil nil t)))
+ (overlay-put ov 'treesit-parser embedded-parser)
+ (treesit-parser-set-included-ranges
+ embedded-parser `((,beg . ,end)))))))))
+
(defun treesit-update-ranges (&optional beg end)
"Update the ranges for each language in the current buffer.
If BEG and END are non-nil, only update parser ranges in that
@@ -570,23 +734,32 @@ region."
(dolist (setting treesit-range-settings)
(let ((query (nth 0 setting))
(language (nth 1 setting))
+ (local (nth 2 setting))
+ (offset (nth 3 setting))
(beg (or beg (point-min)))
(end (or end (point-max))))
- (if (functionp query) (funcall query beg end)
+ (cond
+ ((functionp query) (funcall query beg end))
+ (local
+ (treesit--update-ranges-local query language beg end))
+ (t
(let* ((host-lang (treesit-query-language query))
(parser (treesit-parser-create language))
(old-ranges (treesit-parser-included-ranges parser))
(new-ranges (treesit-query-range
- host-lang query beg end))
+ host-lang query beg end offset))
(set-ranges (treesit--clip-ranges
(treesit--merge-ranges
old-ranges new-ranges beg end)
(point-min) (point-max))))
- (dolist (parser (treesit-parser-list))
- (when (eq (treesit-parser-language parser)
- language)
+ (dolist (parser (treesit-parser-list nil language))
(treesit-parser-set-included-ranges
- parser set-ranges))))))))
+ parser (or set-ranges
+ ;; When there's no range for the embedded
+ ;; language, set it's range to a dummy (1
+ ;; . 1), otherwise it would be set to the
+ ;; whole buffer, which is not what we want.
+ `((,(point-min) . ,(point-min))))))))))))
(defun treesit-parser-range-on (parser beg &optional end)
"Check if PARSER's range covers the portion between BEG and END.
@@ -754,6 +927,8 @@ Other keywords include:
`append' Append the new face to existing ones.
`prepend' Prepend the new face to existing ones.
`keep' Fill-in regions without an existing face.
+ :default-language LANGUAGE Every QUERY after this keyword
+ will use LANGUAGE by default.
Capture names in QUERY should be face names like
`font-lock-keyword-face'. The captured node will be fontified
@@ -783,12 +958,22 @@ name, it is ignored."
;; that following queries will apply to.
current-language current-override
current-feature
+ ;; DEFAULT-LANGUAGE will be chosen when current-language is
+ ;; not set.
+ default-language
;; The list this function returns.
(result nil))
(while query-specs
(let ((token (pop query-specs)))
(pcase token
;; (1) Process keywords.
+ (:default-language
+ (let ((lang (pop query-specs)))
+ (when (or (not (symbolp lang)) (null lang))
+ (signal 'treesit-font-lock-error
+ `("Value of :default-language should be a symbol"
+ ,lang)))
+ (setq default-language lang)))
(:language
(let ((lang (pop query-specs)))
(when (or (not (symbolp lang)) (null lang))
@@ -816,23 +1001,24 @@ name, it is ignored."
(setq current-feature var)))
;; (2) Process query.
((pred treesit-query-p)
- (when (null current-language)
- (signal 'treesit-font-lock-error
- `("Language unspecified, use :language keyword to specify a language for this query" ,token)))
- (when (null current-feature)
- (signal 'treesit-font-lock-error
- `("Feature unspecified, use :feature keyword to specify the feature name for this query" ,token)))
- (if (treesit-compiled-query-p token)
- (push `(,current-language token) result)
- (push `(,(treesit-query-compile current-language token)
- t
- ,current-feature
- ,current-override)
- result))
- ;; Clears any configurations set for this query.
- (setq current-language nil
- current-override nil
- current-feature nil))
+ (let ((lang (or default-language current-language)))
+ (when (null lang)
+ (signal 'treesit-font-lock-error
+ `("Language unspecified, use :language keyword or :default-language to specify a language for this query" ,token)))
+ (when (null current-feature)
+ (signal 'treesit-font-lock-error
+ `("Feature unspecified, use :feature keyword to specify the feature name for this query" ,token)))
+ (if (treesit-compiled-query-p token)
+ (push `(,lang token) result)
+ (push `(,(treesit-query-compile lang token)
+ t
+ ,current-feature
+ ,current-override)
+ result))
+ ;; Clears any configurations set for this query.
+ (setq current-language nil
+ current-override nil
+ current-feature nil)))
(_ (signal 'treesit-font-lock-error
`("Unexpected value" ,token))))))
(nreverse result))))
@@ -844,7 +1030,8 @@ name, it is ignored."
(defvar treesit--font-lock-verbose nil
"If non-nil, print debug messages when fontifying.")
-(defun treesit-font-lock-recompute-features (&optional add-list remove-list)
+(defun treesit-font-lock-recompute-features
+ (&optional add-list remove-list language)
"Enable/disable font-lock features.
Enable each feature in ADD-LIST, disable each feature in
@@ -859,7 +1046,10 @@ the features are disabled.
ADD-LIST and REMOVE-LIST are lists of feature symbols. The
same feature symbol cannot appear in both lists; the function
-signals the `treesit-font-lock-error' error if that happens."
+signals the `treesit-font-lock-error' error if that happens.
+
+If LANGUAGE is non-nil, only compute features for that language,
+and leave settings for other languages unchanged."
(when-let ((intersection (cl-intersection add-list remove-list)))
(signal 'treesit-font-lock-error
(list "ADD-LIST and REMOVE-LIST contain the same feature"
@@ -879,9 +1069,13 @@ signals the `treesit-font-lock-error' error if that happens."
(additive (or add-list remove-list)))
(cl-loop for idx = 0 then (1+ idx)
for setting in treesit-font-lock-settings
+ for lang = (treesit-query-language (nth 0 setting))
for feature = (nth 2 setting)
for current-value = (nth 1 setting)
- ;; Set the ENABLE flag for the setting.
+ ;; Set the ENABLE flag for the setting if its language is
+ ;; relevant.
+ if (or (null language)
+ (eq language lang))
do (setf (nth 1 (nth idx treesit-font-lock-settings))
(cond
((not additive)
@@ -1038,72 +1232,92 @@ If LOUDLY is non-nil, display some debugging information."
(message "Fontifying region: %s-%s" start end))
(treesit-update-ranges start end)
(font-lock-unfontify-region start end)
- (dolist (setting treesit-font-lock-settings)
- (let* ((query (nth 0 setting))
- (enable (nth 1 setting))
- (override (nth 3 setting))
- (language (treesit-query-language query)))
-
- ;; Use deterministic way to decide whether to turn on "fast
- ;; mode". (See bug#60691, bug#60223.)
- (when (eq treesit--font-lock-fast-mode 'unspecified)
- (pcase-let ((`(,max-depth ,max-width)
- (treesit-subtree-stat
- (treesit-buffer-root-node language))))
- (if (or (> max-depth 100) (> max-width 4000))
- (setq treesit--font-lock-fast-mode t)
- (setq treesit--font-lock-fast-mode nil))))
-
- (when-let* ((root (treesit-buffer-root-node language))
- (nodes (if (eq t treesit--font-lock-fast-mode)
- (treesit--children-covering-range-recurse
- root start end (* 4 jit-lock-chunk-size))
- (list (treesit-buffer-root-node language))))
- ;; Only activate if ENABLE flag is t.
- (activate (eq t enable)))
- (ignore activate)
-
- ;; Query each node.
- (dolist (sub-node nodes)
- (let* ((delta-start (car treesit--font-lock-query-expand-range))
- (delta-end (cdr treesit--font-lock-query-expand-range))
- (captures (treesit-query-capture
- sub-node query
- (max (- start delta-start) (point-min))
- (min (+ end delta-end) (point-max)))))
-
- ;; For each captured node, fontify that node.
- (with-silent-modifications
- (dolist (capture captures)
- (let* ((face (car capture))
- (node (cdr capture))
- (node-start (treesit-node-start node))
- (node-end (treesit-node-end node)))
-
- ;; If node is not in the region, take them out. See
- ;; comment #3 above for more detail.
- (if (and (facep face)
- (or (>= start node-end) (>= node-start end)))
- (when (or loudly treesit--font-lock-verbose)
- (message "Captured node %s(%s-%s) but it is outside of fontifing region" node node-start node-end))
-
- (cond
- ((facep face)
- (treesit-fontify-with-override
- (max node-start start) (min node-end end)
- face override))
- ((functionp face)
- (funcall face node override start end)))
-
- ;; Don't raise an error if FACE is neither a face nor
- ;; a function. This is to allow intermediate capture
- ;; names used for #match and #eq.
- (when (or loudly treesit--font-lock-verbose)
- (message "Fontifying text from %d to %d, Face: %s, Node: %s"
- (max node-start start) (min node-end end)
- face (treesit-node-type node))))))))))))
+ (let* ((local-parsers (treesit-local-parsers-on start end))
+ (global-parsers (treesit-parser-list))
+ (root-nodes
+ (mapcar #'treesit-parser-root-node
+ (append local-parsers global-parsers))))
+ (dolist (setting treesit-font-lock-settings)
+ (let* ((query (nth 0 setting))
+ (enable (nth 1 setting))
+ (override (nth 3 setting))
+ (language (treesit-query-language query))
+ (root-nodes (cl-remove-if-not
+ (lambda (node)
+ (eq (treesit-node-language node) language))
+ root-nodes)))
+
+ ;; Use deterministic way to decide whether to turn on "fast
+ ;; mode". (See bug#60691, bug#60223.)
+ (when (eq treesit--font-lock-fast-mode 'unspecified)
+ (pcase-let ((`(,max-depth ,max-width)
+ (treesit-subtree-stat
+ (treesit-buffer-root-node language))))
+ (if (or (> max-depth 100) (> max-width 4000))
+ (setq treesit--font-lock-fast-mode t)
+ (setq treesit--font-lock-fast-mode nil))))
+
+ ;; Only activate if ENABLE flag is t.
+ (when-let
+ ((activate (eq t enable))
+ (nodes (if (eq t treesit--font-lock-fast-mode)
+ (mapcan
+ (lambda (node)
+ (treesit--children-covering-range-recurse
+ node start end (* 4 jit-lock-chunk-size)))
+ root-nodes)
+ root-nodes)))
+ (ignore activate)
+
+ ;; Query each node.
+ (dolist (sub-node nodes)
+ (treesit--font-lock-fontify-region-1
+ sub-node query start end override loudly))))))
`(jit-lock-bounds ,start . ,end))
+(defun treesit--font-lock-fontify-region-1 (node query start end override loudly)
+ "Fontify the region between START and END by querying NODE with QUERY.
+
+If OVERRIDE is non-nil, override existing faces, if LOUDLY is
+non-nil, print debugging information."
+ (let* ((delta-start (car treesit--font-lock-query-expand-range))
+ (delta-end (cdr treesit--font-lock-query-expand-range))
+ (captures (treesit-query-capture
+ node query
+ (max (- start delta-start) (point-min))
+ (min (+ end delta-end) (point-max)))))
+
+ ;; For each captured node, fontify that node.
+ (with-silent-modifications
+ (dolist (capture captures)
+ (let* ((face (car capture))
+ (node (cdr capture))
+ (node-start (treesit-node-start node))
+ (node-end (treesit-node-end node)))
+
+ ;; If node is not in the region, take them out. See
+ ;; comment #3 above for more detail.
+ (if (and (facep face)
+ (or (>= start node-end) (>= node-start end)))
+ (when (or loudly treesit--font-lock-verbose)
+ (message "Captured node %s(%s-%s) but it is outside of fontifing region" node node-start node-end))
+
+ (cond
+ ((facep face)
+ (treesit-fontify-with-override
+ (max node-start start) (min node-end end)
+ face override))
+ ((functionp face)
+ (funcall face node override start end)))
+
+ ;; Don't raise an error if FACE is neither a face nor
+ ;; a function. This is to allow intermediate capture
+ ;; names used for #match and #eq.
+ (when (or loudly treesit--font-lock-verbose)
+ (message "Fontifying text from %d to %d, Face: %s, Node: %s"
+ (max node-start start) (min node-end end)
+ face (treesit-node-type node)))))))))
+
(defun treesit--font-lock-notifier (ranges parser)
"Ensures updated parts of the parse-tree are refontified.
RANGES is a list of (BEG . END) ranges, PARSER is the tree-sitter
@@ -1116,6 +1330,72 @@ parser notifying of the change."
(with-silent-modifications
(put-text-property (car range) (cdr range) 'fontified nil)))))
+(defvar-local treesit--syntax-propertize-start nil
+ "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.")
+
+(defun treesit--syntax-propertize-notifier (ranges parser)
+ "Sets `treesit--syntax-propertize-start' to the smallest start.
+Specifically, the smallest start position among all the ranges in
+RANGES for PARSER."
+ (with-current-buffer (treesit-parser-buffer parser)
+ (when-let* ((range-starts (mapcar #'car ranges))
+ (min-range-start
+ (seq-reduce
+ #'min (cdr range-starts) (car range-starts))))
+ (if (null treesit--syntax-propertize-start)
+ (setq treesit--syntax-propertize-start min-range-start)
+ (setq treesit--syntax-propertize-start
+ (min treesit--syntax-propertize-start min-range-start))))))
+
+(defvar-local treesit--pre-redisplay-tick nil
+ "The last `buffer-chars-modified-tick' that we've processed.
+Because `pre-redisplay-functions' could be called multiple times
+during a single command loop, we use this variable to debounce
+calls to `treesit--pre-redisplay'.")
+
+(defun treesit--pre-redisplay (&rest _)
+ "Force reparse and consequently run all notifiers.
+
+One of the notifiers is `treesit--font-lock-notifier', which will
+mark the region whose syntax has changed to \"need to refontify\".
+
+For example, when the user types the final slash of a C block
+comment /* xxx */, not only do we need to fontify the slash, but
+also the whole block comment, which previously wasn't fontified
+as comment due to incomplete parse tree."
+ (unless (eq treesit--pre-redisplay-tick (buffer-chars-modified-tick))
+ ;; `treesit-update-ranges' will force the host language's parser to
+ ;; reparse and set correct ranges for embedded parsers. Then
+ ;; `treesit-parser-root-node' will force those parsers to reparse.
+ (treesit-update-ranges)
+ ;; Force repase on _all_ the parsers might not be necessary, but
+ ;; this is probably the most robust way.
+ (dolist (parser (treesit-parser-list))
+ (treesit-parser-root-node parser))
+ (setq treesit--pre-redisplay-tick (buffer-chars-modified-tick))))
+
+(defun treesit--pre-syntax-ppss (start end)
+ "Force reparse and consequently run all notifiers.
+
+Similar to font-lock, we want to update the `syntax' text
+property before `syntax-ppss' starts working on the text. We
+also want to extend the to-be-propertized region to include the
+whole region affected by the last reparse.
+
+START and END mark the current to-be-propertized region."
+ (treesit--pre-redisplay)
+ (let ((new-start treesit--syntax-propertize-start))
+ (if (and new-start (< new-start start))
+ (progn
+ (setq treesit--syntax-propertize-start nil)
+ (cons new-start end))
+ nil)))
+
;;; Indent
(define-error 'treesit-indent-error
@@ -1246,8 +1526,10 @@ See `treesit-simple-indent-presets'.")
(goto-char bol)
(setq this-line-has-prefix
- (and (looking-at adaptive-fill-regexp)
- (match-string 1)))
+ (and (looking-at-p adaptive-fill-regexp)
+ (not (string-match-p
+ (rx bos (* whitespace) eos)
+ (match-string 0)))))
(forward-line -1)
(and (>= (point) comment-start-bol)
@@ -1255,7 +1537,7 @@ See `treesit-simple-indent-presets'.")
(looking-at adaptive-fill-regexp)
;; If previous line is an empty line, don't
;; indent.
- (not (looking-at (rx (* whitespace) eol)))
+ (not (looking-at-p (rx (* whitespace) eol)))
;; Return the anchor. If the indenting line
;; has a prefix and the previous line also
;; has a prefix, indent to the beginning of
@@ -1349,7 +1631,7 @@ MATCHER:
NODE's index in PARENT. Therefore, to match the first child
where PARENT is \"argument_list\", use
- (match nil \"argument_list\" nil nil 0 0).
+ (match nil \"argument_list\" nil 0 0).
NODE-TYPE, PARENT-TYPE, and NODE-FIELD are regexps.
NODE-TYPE can also be `null', which matches when NODE is nil.
@@ -1518,12 +1800,15 @@ Return (ANCHOR . OFFSET). This function is used by
(forward-line 0)
(skip-chars-forward " \t")
(point)))
+ (local-parsers (treesit-local-parsers-at bol))
(smallest-node
(cond ((null (treesit-parser-list)) nil)
- ((eq 1 (length (treesit-parser-list)))
+ (local-parsers (treesit-node-at
+ bol (car local-parsers)))
+ ((eq 1 (length (treesit-parser-list nil nil t)))
(treesit-node-at bol))
- ((treesit-language-at (point))
- (treesit-node-at bol (treesit-language-at (point))))
+ ((treesit-language-at bol)
+ (treesit-node-at bol (treesit-language-at bol)))
(t (treesit-node-at bol))))
(root (treesit-parser-root-node
(treesit-node-parser smallest-node)))
@@ -1701,12 +1986,28 @@ OFFSET."
(message "No matched rule"))
(cons nil nil))))))
-(defun treesit-check-indent (mode)
- "Check current buffer's indentation against a major mode MODE.
+(defun treesit--read-major-mode ()
+ "Read a major mode using completion.
+Helper function to use in the `interactive' spec of `treesit-check-indent'."
+ (let* ((default (and (symbolp major-mode) (symbol-name major-mode)))
+ (mode
+ (completing-read
+ (format-prompt "Target major mode" default)
+ obarray
+ (lambda (sym)
+ (and (string-suffix-p "-mode" (symbol-name sym))
+ (not (or (memq sym minor-mode-list)
+ (string-suffix-p "-minor-mode"
+ (symbol-name sym))))))
+ nil nil nil default nil)))
+ (cond
+ ((equal mode "nil") nil)
+ ((and (stringp mode) (fboundp (intern mode))) (intern mode))
+ (t mode))))
-Pop up a diff buffer showing the difference. Correct
-indentation (target) is in green, current indentation is in red."
- (interactive "CTarget major mode: ")
+(defun treesit-check-indent (mode)
+ "Compare the current buffer with how major mode MODE would indent it."
+ (interactive (list (treesit--read-major-mode)))
(let ((source-buf (current-buffer)))
(with-temp-buffer
(insert-buffer-substring source-buf)
@@ -1799,6 +2100,9 @@ BACKWARD and ALL are the same as in `treesit-search-forward'."
(goto-char current-pos)))
node))
+(make-obsolete 'treesit-sexp-type-regexp
+ "`treesit-sexp-type-regexp' will be removed soon, use `treesit-thing-settings' instead." "30.1")
+
(defvar-local treesit-sexp-type-regexp nil
"A regexp that matches the node type of sexp nodes.
@@ -1816,7 +2120,7 @@ like `forward-sexp' does. If point is already at top-level,
return nil without moving point."
(interactive "^p")
(let ((arg (or arg 1))
- (pred treesit-sexp-type-regexp))
+ (pred (or treesit-sexp-type-regexp 'sexp)))
(or (if (> arg 0)
(treesit-end-of-thing pred (abs arg) 'restricted)
(treesit-beginning-of-thing pred (abs arg) 'restricted))
@@ -1824,7 +2128,7 @@ return nil without moving point."
;; the obstacle, like `forward-sexp' does. If we couldn't
;; find a parent, we simply return nil without moving point,
;; then functions like `up-list' will signal "at top level".
- (when-let* ((parent (nth 2 (treesit--things-around (point) pred)))
+ (when-let* ((parent (treesit--thing-at (point) pred t))
(boundary (if (> arg 0)
(treesit-node-child parent -1)
(treesit-node-child parent 0))))
@@ -1842,7 +2146,12 @@ its sibling node ARG nodes away.
Return a pair of positions as described by
`transpose-sexps-function' for use in `transpose-subr' and
friends."
- (let* ((parent (treesit-node-parent (treesit-node-at (point))))
+ ;; First arrive at the right level at where the node at point is
+ ;; considered a sexp. If sexp isn't defined, or we can't find any
+ ;; node that's a sexp, use the node at point.
+ (let* ((node (or (treesit-thing-at-point 'sexp 'nested)
+ (treesit-node-at (point))))
+ (parent (treesit-node-parent node))
(child (treesit-node-child parent 0 t)))
(named-let loop ((prev child)
(next (treesit-node-next-sibling child t)))
@@ -1873,7 +2182,8 @@ friends."
;; - treesit-thing/defun-at-point
;;
;; And more generic functions like:
-;; - treesit--things-around
+;; - treesit--thing-prev/next
+;; - treesit--thing-at
;; - treesit--top-level-thing
;; - treesit--navigate-thing
;;
@@ -1882,11 +2192,13 @@ friends."
;;
;; TODO: I'm not entirely sure how would this go, so I only documented
;; the "defun" functions and didn't document any "thing" functions.
-;; We should also document `treesit-block-type-regexp' and support it
-;; in major modes if we can meaningfully integrate hideshow: I tried
-;; and failed, we need SomeOne that understands hideshow to look at
-;; it. (BTW, hideshow should use its own
-;; `treesit-hideshow-block-type-regexp'.)
+;; We should also document `treesit-thing-settings'.
+
+;; TODO: Integration with thing-at-point: once our thing interface is
+;; stable.
+;;
+;; TODO: Integration with hideshow: I tried and failed, we need
+;; SomeOne that understands hideshow to look at it.
(defvar-local treesit-defun-type-regexp nil
"A regexp that matches the node type of defun nodes.
@@ -1900,9 +2212,6 @@ for invalid node.
This is used by `treesit-beginning-of-defun' and friends.")
-(defvar-local treesit-block-type-regexp nil
- "Like `treesit-defun-type-regexp', but for blocks.")
-
(defvar-local treesit-defun-tactic 'nested
"Determines how does Emacs treat nested defuns.
If the value is `top-level', Emacs only moves across top-level
@@ -1928,11 +2237,28 @@ nil.")
"The delimiter used to connect several defun names.
This is used in `treesit-add-log-current-defun'.")
-(defun treesit-beginning-of-thing (pred &optional arg tactic)
+(defun treesit-thing-definition (thing language)
+ "Return the predicate for THING if it's defined for LANGUAGE.
+A thing is considered defined if it has an entry in
+`treesit-thing-settings'.
+
+If LANGUAGE is nil, return the first definition for THING in
+`treesit-thing-settings'."
+ (if language
+ (car (alist-get thing (alist-get language
+ treesit-thing-settings)))
+ (car (alist-get thing (mapcan (lambda (entry)
+ (copy-tree (cdr entry)))
+ treesit-thing-settings)))))
+
+(defalias 'treesit-thing-defined-p #'treesit-thing-definition
+ "Return non-nil if THING is defined.")
+
+(defun treesit-beginning-of-thing (thing &optional arg tactic)
"Like `beginning-of-defun', but generalized into things.
-PRED is like `treesit-defun-type-regexp', ARG
-is the same as in `beginning-of-defun'.
+THING can be a thing defined in `treesit-thing-settings', which see,
+or a predicate. ARG is the same as in `beginning-of-defun'.
TACTIC determines how does this function move between things. It
can be `nested', `top-level', `restricted', or nil. `nested'
@@ -1947,15 +2273,15 @@ should there be one. If omitted, TACTIC is considered to be
Return non-nil if successfully moved, nil otherwise."
(pcase-let* ((arg (or arg 1))
(dest (treesit--navigate-thing
- (point) (- arg) 'beg pred tactic)))
+ (point) (- arg) 'beg thing tactic)))
(when dest
(goto-char dest))))
-(defun treesit-end-of-thing (pred &optional arg tactic)
+(defun treesit-end-of-thing (thing &optional arg tactic)
"Like `end-of-defun', but generalized into things.
-PRED is like `treesit-defun-type-regexp', ARG is the same as
-in `end-of-defun'.
+THING can be a thing defined in `treesit-thing-settings', which
+see, or a predicate. ARG is the same as in `end-of-defun'.
TACTIC determines how does this function move between things. It
can be `nested', `top-level', `restricted', or nil. `nested'
@@ -1970,7 +2296,7 @@ should there be one. If omitted, TACTIC is considered to be
Return non-nil if successfully moved, nil otherwise."
(pcase-let* ((arg (or arg 1))
(dest (treesit--navigate-thing
- (point) arg 'end pred tactic)))
+ (point) arg 'end thing tactic)))
(when dest
(goto-char dest))))
@@ -1984,19 +2310,21 @@ If search is successful, return t, otherwise return nil.
This is a tree-sitter equivalent of `beginning-of-defun'.
Behavior of this function depends on `treesit-defun-type-regexp'
-and `treesit-defun-skipper'."
+and `treesit-defun-skipper'. If `treesit-defun-type-regexp' is
+not set, Emacs also looks for definition of defun in
+`treesit-thing-settings'."
(interactive "^p")
(or (not (eq this-command 'treesit-beginning-of-defun))
(eq last-command 'treesit-beginning-of-defun)
(and transient-mark-mode mark-active)
(push-mark))
(let ((orig-point (point))
- (success nil))
+ (success nil)
+ (pred (or treesit-defun-type-regexp 'defun)))
(catch 'done
(dotimes (_ 2)
- (when (treesit-beginning-of-thing
- treesit-defun-type-regexp arg treesit-defun-tactic)
+ (when (treesit-beginning-of-thing pred arg treesit-defun-tactic)
(when treesit-defun-skipper
(funcall treesit-defun-skipper)
(setq success t)))
@@ -2017,9 +2345,12 @@ Negative argument -N means move back to Nth preceding end of defun.
This is a tree-sitter equivalent of `end-of-defun'. Behavior of
this function depends on `treesit-defun-type-regexp' and
-`treesit-defun-skipper'."
+`treesit-defun-skipper'. If `treesit-defun-type-regexp' is not
+set, Emacs also looks for definition of defun in
+`treesit-thing-settings'."
(interactive "^p\nd")
- (let ((orig-point (point)))
+ (let ((orig-point (point))
+ (pred (or treesit-defun-type-regexp 'defun)))
(if (or (null arg) (= arg 0)) (setq arg 1))
(or (not (eq this-command 'treesit-end-of-defun))
(eq last-command 'treesit-end-of-defun)
@@ -2028,8 +2359,7 @@ this function depends on `treesit-defun-type-regexp' and
(catch 'done
(dotimes (_ 2) ; Not making progress is better than infloop.
- (when (treesit-end-of-thing
- treesit-defun-type-regexp arg treesit-defun-tactic)
+ (when (treesit-end-of-thing pred arg treesit-defun-tactic)
(when treesit-defun-skipper
(funcall treesit-defun-skipper)))
@@ -2041,6 +2371,9 @@ this function depends on `treesit-defun-type-regexp' and
(throw 'done nil)
(setq arg (if (> arg 0) (1+ arg) (1- arg))))))))
+(make-obsolete 'treesit-text-type-regexp
+ "`treesit-text-type-regexp' will be removed soon, use `treesit-thing-settings' instead." "30.1")
+
(defvar-local treesit-text-type-regexp "\\`comment\\'"
"A regexp that matches the node type of textual nodes.
@@ -2050,6 +2383,9 @@ comments and multiline string literals. For example,
\"text_block\" in the case of a string. This is used by
`prog-fill-reindent-defun' and friends.")
+(make-obsolete 'treesit-sentence-type-regexp
+ "`treesit-sentence-type-regexp' will be removed soon, use `treesit-thing-settings' instead." "30.1")
+
(defvar-local treesit-sentence-type-regexp nil
"A regexp that matches the node type of sentence nodes.
@@ -2059,21 +2395,21 @@ smaller in scope than defuns. This is used by
`treesit-forward-sentence' and friends.")
(defun treesit-forward-sentence (&optional arg)
- "Tree-sitter `forward-sentence-function' function.
+ "Tree-sitter `forward-sentence-function' implementation.
ARG is the same as in `forward-sentence'.
-If inside comment or other nodes described in
-`treesit-sentence-type-regexp', use
-`forward-sentence-default-function', else move across nodes as
-described by `treesit-sentence-type-regexp'."
- (if (string-match-p
- treesit-text-type-regexp
- (treesit-node-type (treesit-node-at (point))))
+If point is inside a text environment, go forward a prose
+sentence using `forward-sentence-default-function'. If point is
+inside code, go forward a source code sentence.
+
+What constitutes as text and source code sentence is determined
+by `text' and `sentence' in `treesit-thing-settings'."
+ (if (treesit-node-match-p (treesit-node-at (point)) 'text t)
(funcall #'forward-sentence-default-function arg)
(funcall
(if (> arg 0) #'treesit-end-of-thing #'treesit-beginning-of-thing)
- treesit-sentence-type-regexp (abs arg))))
+ 'sentence (abs arg))))
(defun treesit-default-defun-skipper ()
"Skips spaces after navigating a defun.
@@ -2088,22 +2424,13 @@ the current line if the beginning of the defun is indented."
(forward-line 1))
;; Moving backward, but there are some whitespace (and only
;; whitespace) between point and BOL: go back to BOL.
- ((looking-back (rx (+ (or " " "\t")))
+ ((looking-back (rx bol (+ (or " " "\t")))
(line-beginning-position))
(beginning-of-line))))
-;; prev-sibling:
-;; 1. end-of-node before pos
-;; 2. highest such node
-;;
-;; next-sibling:
-;; 1. beg-of-node after pos
-;; 2. highest such node
-;;
-;; parent:
-;; 1. node covers pos
-;; 2. smallest such node
-(defun treesit--things-around (pos pred)
+(make-obsolete 'treesit--things-around
+ "`treesit--things-around' will be removed soon, use `treesit--thing-prev', `treesit--thing-next', `treesit--thing-at' instead." "30.1")
+(defun treesit--things-around (pos thing)
"Return the previous, next, and parent thing around POS.
Return a list of (PREV NEXT PARENT), where PREV and NEXT are
@@ -2111,8 +2438,8 @@ previous and next sibling things around POS, and PARENT is the
parent thing surrounding POS. All of three could be nil if no
sound things exists.
-PRED can be a regexp, a predicate function, and more. See
-`treesit-thing-settings' for details."
+THING should be a thing defined in `treesit-thing-settings',
+which see; it can also be a predicate."
(let* ((node (treesit-node-at pos))
(result (list nil nil nil)))
;; 1. Find previous and next sibling defuns.
@@ -2135,7 +2462,7 @@ PRED can be a regexp, a predicate function, and more. See
when node
do (let ((cursor node)
(iter-pred (lambda (node)
- (and (treesit-node-match-p node pred)
+ (and (treesit-node-match-p node thing t)
(funcall pos-pred node)))))
;; Find the node just before/after POS to start searching.
(save-excursion
@@ -2149,11 +2476,11 @@ PRED can be a regexp, a predicate function, and more. See
(setf (nth idx result)
(treesit-node-top-level cursor iter-pred t))
(setq cursor (treesit-search-forward
- cursor pred backward backward)))))
+ cursor thing backward backward)))))
;; 2. Find the parent defun.
(let ((cursor (or (nth 0 result) (nth 1 result) node))
(iter-pred (lambda (node)
- (and (treesit-node-match-p node pred)
+ (and (treesit-node-match-p node thing t)
(not (treesit-node-eq node (nth 0 result)))
(not (treesit-node-eq node (nth 1 result)))
(< (treesit-node-start node)
@@ -2163,6 +2490,77 @@ PRED can be a regexp, a predicate function, and more. See
(treesit-parent-until cursor iter-pred)))
result))
+(defun treesit--thing-sibling (pos thing prev)
+ "Return the next or previous THING at POS.
+
+If PREV is non-nil, return the previous THING. It's guaranteed
+that returned previous sibling's end <= POS, and returned next
+sibling's beginning >= POS.
+
+Return nil if no THING can be found. THING should be a thing
+defined in `treesit-thing-settings', or a predicate as described
+in `treesit-thing-settings'."
+ (let* ((cursor (treesit-node-at pos))
+ (pos-pred (if prev
+ (lambda (n) (<= (treesit-node-end n) pos))
+ (lambda (n) (>= (treesit-node-start n) pos))))
+ (iter-pred (lambda (node)
+ (and (treesit-node-match-p node thing t)
+ (funcall pos-pred node))))
+ (sibling nil))
+ (when cursor
+ ;; Find the node just before/after POS to start searching.
+ (save-excursion
+ (while (and cursor (not (funcall pos-pred cursor)))
+ (setq cursor (treesit-search-forward-goto
+ cursor "" prev prev t))))
+ ;; Keep searching until we run out of candidates or found a
+ ;; return value.
+ (while (and cursor
+ (funcall pos-pred cursor)
+ (null sibling))
+ (setq sibling (treesit-node-top-level cursor iter-pred t))
+ (setq cursor (treesit-search-forward cursor thing prev prev)))
+ sibling)))
+
+(defun treesit--thing-prev (pos thing)
+ "Return the previous THING at POS.
+
+The returned node, if non-nil, must be before POS, i.e., its end
+<= POS.
+
+THING should be a thing defined in `treesit-thing-settings', or a
+predicate as described in `treesit-thing-settings'."
+ (treesit--thing-sibling pos thing t))
+
+(defun treesit--thing-next (pos thing)
+ "Return the next THING at POS.
+
+The returned node, if non-nil, must be after POS, i.e., its
+start >= POS.
+
+THING should be a thing defined in `treesit-thing-settings', or a
+predicate as described in `treesit-thing-settings'."
+ (treesit--thing-sibling pos thing nil))
+
+(defun treesit--thing-at (pos thing &optional strict)
+ "Return the smallest THING enclosing POS.
+
+The returned node, if non-nil, must enclose POS, i.e., its start
+<= POS, its end > POS. If STRICT is non-nil, the returned node's
+start must < POS rather than <= POS.
+
+THING should be a thing defined in `treesit-thing-settings', or
+it can be a predicate described in `treesit-thing-settings'."
+ (let* ((cursor (treesit-node-at pos))
+ (iter-pred (lambda (node)
+ (and (treesit-node-match-p node thing t)
+ (if strict
+ (< (treesit-node-start node) pos)
+ (<= (treesit-node-start node) pos))
+ (< pos (treesit-node-end node))))))
+ (treesit-parent-until cursor iter-pred t)))
+
;; The basic idea for nested defun navigation is that we first try to
;; move across sibling defuns in the same level, if no more siblings
;; exist, we move to parents's beg/end, rinse and repeat. We never
@@ -2190,7 +2588,7 @@ PRED can be a regexp, a predicate function, and more. See
;; -> Obviously we don't want to go to parent's end, instead, we
;; want to go to parent's prev-sibling's end. Again, we recurse
;; in the function to do that.
-(defun treesit--navigate-thing (pos arg side pred &optional tactic recursing)
+(defun treesit--navigate-thing (pos arg side thing &optional tactic recursing)
"Navigate thing ARG steps from POS.
If ARG is positive, move forward that many steps, if negative,
@@ -2201,7 +2599,7 @@ This function doesn't actually move point, it just returns the
position it would move to. If there aren't enough things to move
across, return nil.
-PRED can be a regexp, a predicate function, and more. See
+THING can be a regexp, a predicate function, and more. See
`treesit-thing-settings' for details.
TACTIC determines how does this function move between things. It
@@ -2229,15 +2627,21 @@ function is called recursively."
dest)))))
(catch 'term
(while (> counter 0)
- (pcase-let
- ((`(,prev ,next ,parent)
- (treesit--things-around pos pred)))
+ (let ((prev (treesit--thing-prev pos thing))
+ (next (treesit--thing-next pos thing))
+ (parent (treesit--thing-at pos thing t)))
+ (when (and parent prev
+ (not (treesit-node-enclosed-p prev parent)))
+ (setq prev nil))
+ (when (and parent next
+ (not (treesit-node-enclosed-p next parent)))
+ (setq next nil))
;; When PARENT is nil, nested and top-level are the same, if
;; there is a PARENT, make PARENT to be the top-level parent
;; and pretend there is no nested PREV and NEXT.
(when (and (eq tactic 'top-level)
parent)
- (setq parent (treesit-node-top-level parent pred t)
+ (setq parent (treesit-node-top-level parent thing t)
prev nil
next nil))
;; If TACTIC is `restricted', the implementation is very simple.
@@ -2269,7 +2673,7 @@ function is called recursively."
;; the end of next before recurring.)
(setq pos (or (treesit--navigate-thing
(treesit-node-end (or next parent))
- 1 'beg pred tactic t)
+ 1 'beg thing tactic t)
(throw 'term nil)))
;; Normal case.
(setq pos (funcall advance (or next parent))))
@@ -2281,7 +2685,7 @@ function is called recursively."
;; Special case: go to prev end-of-defun.
(setq pos (or (treesit--navigate-thing
(treesit-node-start (or prev parent))
- -1 'end pred tactic t)
+ -1 'end thing tactic t)
(throw 'term nil)))
;; Normal case.
(setq pos (funcall advance (or prev parent))))))
@@ -2291,25 +2695,18 @@ function is called recursively."
(if (eq counter 0) pos nil)))
;; TODO: In corporate into thing-at-point.
-(defun treesit-thing-at-point (pred tactic)
- "Return the thing node at point or nil if none is found.
-
-\"Thing\" is defined by PRED, which can be a regexp, a
-predication function, and more, see `treesit-thing-settings'
-for details.
-
-Return the top-level defun if TACTIC is `top-level', return the
-immediate parent thing if TACTIC is `nested'."
- (pcase-let* ((`(,_ ,next ,parent)
- (treesit--things-around (point) pred))
- ;; If point is at the beginning of a thing, we
- ;; prioritize that thing over the parent in nested
- ;; mode.
- (node (or (and (eq (treesit-node-start next) (point))
- next)
- parent)))
+(defun treesit-thing-at-point (thing tactic)
+ "Return the THING at point or nil if none is found.
+
+THING can be a symbol, regexp, a predicate function, and more,
+see `treesit-thing-settings' for details.
+
+Return the top-level THING if TACTIC is `top-level', return the
+smallest enclosing THING as POS if TACTIC is `nested'."
+
+ (let ((node (treesit--thing-at (point) thing)))
(if (eq tactic 'top-level)
- (treesit-node-top-level node pred t)
+ (treesit-node-top-level node thing t)
node)))
(defun treesit-defun-at-point ()
@@ -2319,10 +2716,11 @@ Respects `treesit-defun-tactic': return the top-level defun if it
is `top-level', return the immediate parent defun if it is
`nested'.
-Return nil if `treesit-defun-type-regexp' is not set."
- (when treesit-defun-type-regexp
+Return nil if `treesit-defun-type-regexp' isn't set and `defun'
+isn't defined in `treesit-thing-settings'."
+ (when (or treesit-defun-type-regexp (treesit-thing-defined-p 'defun))
(treesit-thing-at-point
- treesit-defun-type-regexp treesit-defun-tactic)))
+ (or treesit-defun-type-regexp 'defun) treesit-defun-tactic)))
(defun treesit-defun-name (node)
"Return the defun name of NODE.
@@ -2495,14 +2893,18 @@ and enable `font-lock-mode'.
If `treesit-simple-indent-rules' is non-nil, set up indentation.
-If `treesit-defun-type-regexp' is non-nil, set up
-`beginning-of-defun-function' and `end-of-defun-function'.
+If `treesit-defun-type-regexp' is non-nil or `defun' is defined
+in `treesit-thing-settings', set up `beginning-of-defun-function'
+and `end-of-defun-function'.
If `treesit-defun-name-function' is non-nil, set up
`add-log-current-defun'.
If `treesit-simple-imenu-settings' is non-nil, set up Imenu.
+If `sexp', `sentence' are defined in `treesit-thing-settings',
+enable tree-sitter navigation commands for them.
+
Make sure necessary parsers are created for the current buffer
before calling this function."
;; Font-lock.
@@ -2513,11 +2915,17 @@ before calling this function."
'( nil nil nil nil
(font-lock-fontify-syntactically-function
. treesit-font-lock-fontify-region)))
- (font-lock-mode 1)
(treesit-font-lock-recompute-features)
(dolist (parser (treesit-parser-list))
(treesit-parser-add-notifier
- parser #'treesit--font-lock-notifier)))
+ parser #'treesit--font-lock-notifier))
+ (add-hook 'pre-redisplay-functions #'treesit--pre-redisplay 0 t))
+ ;; Syntax
+ (dolist (parser (treesit-parser-list))
+ (treesit-parser-add-notifier
+ parser #'treesit--syntax-propertize-notifier))
+ (add-hook 'syntax-propertize-extend-region-functions
+ #'treesit--pre-syntax-ppss 0 t)
;; Indent.
(when treesit-simple-indent-rules
(setq-local treesit-simple-indent-rules
@@ -2526,7 +2934,8 @@ before calling this function."
(setq-local indent-line-function #'treesit-indent)
(setq-local indent-region-function #'treesit-indent-region))
;; Navigation.
- (when treesit-defun-type-regexp
+ (when (or treesit-defun-type-regexp
+ (treesit-thing-defined-p 'defun nil))
(keymap-set (current-local-map) "<remap> <beginning-of-defun>"
#'treesit-beginning-of-defun)
(keymap-set (current-local-map) "<remap> <end-of-defun>"
@@ -2545,16 +2954,23 @@ before calling this function."
(setq-local add-log-current-defun-function
#'treesit-add-log-current-defun))
- (when treesit-sexp-type-regexp
- (setq-local forward-sexp-function #'treesit-forward-sexp))
- (setq-local transpose-sexps-function #'treesit-transpose-sexps)
- (when treesit-sentence-type-regexp
+ (when (treesit-thing-defined-p 'sexp nil)
+ (setq-local forward-sexp-function #'treesit-forward-sexp)
+ (setq-local transpose-sexps-function #'treesit-transpose-sexps))
+
+ (when (treesit-thing-defined-p 'sentence nil)
(setq-local forward-sentence-function #'treesit-forward-sentence))
;; Imenu.
(when treesit-simple-imenu-settings
(setq-local imenu-create-index-function
- #'treesit-simple-imenu)))
+ #'treesit-simple-imenu))
+
+ ;; Remove existing local parsers.
+ (dolist (ov (overlays-in (point-min) (point-max)))
+ (when-let ((parser (overlay-get ov 'treesit-parser)))
+ (treesit-parser-delete parser)
+ (delete-overlay ov))))
;;; Debugging
@@ -2605,7 +3021,8 @@ in `treesit-parser-list'."
'bold nil))
name
(if (treesit-node-check node 'named) ")" "\""))))
- (setq treesit--inspect-name name)
+ ;; Escape the percent character for mode-line. (Bug#65540)
+ (setq treesit--inspect-name (string-replace "%" "%%" name))
(force-mode-line-update)
(when arg
(if node-list
@@ -2661,7 +3078,9 @@ to the offending pattern and highlight the pattern."
(start (nth 1 data))
(inhibit-read-only t))
(erase-buffer)
- (insert (treesit-query-expand query))
+ (insert (if (stringp query)
+ query
+ (treesit-query-expand query)))
(goto-char start)
(search-forward " " nil t)
(put-text-property start (point) 'face 'error)
@@ -2947,10 +3366,12 @@ the text in the active region is highlighted in the explorer
window."
:lighter " TSexplore"
(if treesit-explore-mode
- (let ((language (intern (completing-read
- "Language: "
- (mapcar #'treesit-parser-language
- (treesit-parser-list))))))
+ (let ((language
+ (intern (completing-read
+ "Language: "
+ (cl-remove-duplicates
+ (mapcar #'treesit-parser-language
+ (treesit-parser-list nil nil t)))))))
(if (not (treesit-language-available-p language))
(user-error "Cannot find tree-sitter grammar for %s: %s"
language (cdr (treesit-language-available-p
@@ -2966,13 +3387,13 @@ window."
(treesit--explorer-tree-mode)))
(display-buffer treesit--explorer-buffer
(cons nil '((inhibit-same-window . t))))
+ (setq-local treesit--explorer-last-node nil)
(treesit--explorer-refresh)
;; Set up variables and hooks.
(add-hook 'post-command-hook
#'treesit--explorer-post-command 0 t)
(add-hook 'kill-buffer-hook
#'treesit--explorer-kill-explorer-buffer 0 t)
- (setq-local treesit--explorer-last-node nil)
;; Tell `desktop-save' to not save explorer buffers.
(when (boundp 'desktop-modes-not-to-save)
(unless (memq 'treesit--explorer-tree-mode
@@ -3110,7 +3531,7 @@ nil, the grammar is installed to the standard location, the
" ")))
;; If success, Save the recipe for the current session.
(setf (alist-get lang treesit-language-source-alist)
- recipe))))
+ (cdr recipe)))))
(error
(display-warning
'treesit
@@ -3277,7 +3698,6 @@ function signals an error."
(define-short-documentation-group treesit
-
"Parsers"
(treesit-parser-create
:no-eval (treesit-parser-create 'c)
@@ -3327,6 +3747,9 @@ function signals an error."
"Retrieving a node from another node"
+ (treesit-node-get
+ :no-eval (treesit-node-get node '((parent 1) (sibling 1) (text)))
+ :eg-result-string "#<treesit-node (declaration) in 1-11>")
(treesit-node-parent
:no-eval (treesit-node-parent node)
:eg-result-string "#<treesit-node (declaration) in 1-11>")
@@ -3420,7 +3843,9 @@ function signals an error."
(treesit-node-check
:no-eval (treesit-node-check node 'named)
:eg-result t)
-
+ (treesit-node-enclosed-p
+ :no-eval (treesit-node-enclosed-p node1 node2)
+ :no-eval (treesit-node-enclosed-p node1 '(12 . 18)))
(treesit-node-field-name-for-child
:no-eval (treesit-node-field-name-for-child node)
diff --git a/lisp/tutorial.el b/lisp/tutorial.el
index eb494be8d4d..d754db238de 100644
--- a/lisp/tutorial.el
+++ b/lisp/tutorial.el
@@ -1,6 +1,6 @@
;;; tutorial.el --- tutorial for Emacs -*- lexical-binding: t -*-
-;; Copyright (C) 2006-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2006-2024 Free Software Foundation, Inc.
;; Maintainer: emacs-devel@gnu.org
;; Keywords: help, internal
diff --git a/lisp/type-break.el b/lisp/type-break.el
index 494ed80c496..182f4656b16 100644
--- a/lisp/type-break.el
+++ b/lisp/type-break.el
@@ -1,6 +1,6 @@
;;; type-break.el --- encourage rests from typing at appropriate intervals -*- lexical-binding: t -*-
-;; Copyright (C) 1994-1995, 1997, 2000-2023 Free Software Foundation,
+;; Copyright (C) 1994-1995, 1997, 2000-2024 Free Software Foundation,
;; Inc.
;; Author: Noah Friedman <friedman@splode.com>
@@ -77,7 +77,8 @@ rest from typing, then the next typing break is simply rescheduled for later.
If a break is interrupted before this much time elapses, the user will be
asked whether or not really to interrupt the break."
:set-after '(type-break-interval)
- :type 'natnum
+ :type '(choice (const :tag "Don't check idle time" nil)
+ natnum)
:group 'type-break)
(defcustom type-break-good-break-interval nil
@@ -201,7 +202,8 @@ key is pressed."
"Name of file used to save state across sessions.
If this is nil, no data will be saved across sessions."
:version "24.4" ; added locate-user
- :type 'file)
+ :type '(choice (const :tag "Don't save data" nil)
+ file))
(defvar type-break-post-command-hook '(type-break-check)
"Hook run indirectly by `post-command-hook' for typing break functions.
diff --git a/lisp/uniquify.el b/lisp/uniquify.el
index 2ad2fb0eeac..7085089dbe3 100644
--- a/lisp/uniquify.el
+++ b/lisp/uniquify.el
@@ -1,6 +1,6 @@
;;; uniquify.el --- unique buffer names dependent on file name -*- lexical-binding: t -*-
-;; Copyright (C) 1989, 1995-1997, 2001-2023 Free Software Foundation,
+;; Copyright (C) 1989, 1995-1997, 2001-2024 Free Software Foundation,
;; Inc.
;; Author: Dick King <king@reasoning.com>
@@ -187,9 +187,9 @@ name will then be used to uniquify the buffer's name.
To include components from the `project-name' of the buffer, set
this variable to `project-uniquify-dirname-transform'."
- :type '(choice (function-item :tag "Use directory name as-is" identity)
+ :type `(choice (function-item :tag "Use directory name as-is" identity)
(function-item :tag "Include project name in directory name"
- #'project-uniquify-dirname-transform)
+ ,#'project-uniquify-dirname-transform)
function)
:version "30.1"
:group 'uniquify)
diff --git a/lisp/url/ChangeLog.1 b/lisp/url/ChangeLog.1
index 4cd0a151446..37feda0e026 100644
--- a/lisp/url/ChangeLog.1
+++ b/lisp/url/ChangeLog.1
@@ -3068,7 +3068,7 @@
;; coding: utf-8
;; End:
- Copyright (C) 1999, 2001-2002, 2004-2023 Free Software Foundation,
+ Copyright (C) 1999, 2001-2002, 2004-2024 Free Software Foundation,
Inc.
This file is part of GNU Emacs.
diff --git a/lisp/url/url-auth.el b/lisp/url/url-auth.el
index 6848c0c73a7..8f4df780a54 100644
--- a/lisp/url/url-auth.el
+++ b/lisp/url/url-auth.el
@@ -1,6 +1,6 @@
;;; url-auth.el --- Uniform Resource Locator authorization modules -*- lexical-binding: t -*-
-;; Copyright (C) 1996-1999, 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-1999, 2004-2024 Free Software Foundation, Inc.
;; Keywords: comm, data, processes, hypermedia
diff --git a/lisp/url/url-cache.el b/lisp/url/url-cache.el
index 51c52d701e9..0d27321cc47 100644
--- a/lisp/url/url-cache.el
+++ b/lisp/url/url-cache.el
@@ -1,6 +1,6 @@
;;; url-cache.el --- Uniform Resource Locator retrieval tool -*- lexical-binding: t; -*-
-;; Copyright (C) 1996-1999, 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-1999, 2004-2024 Free Software Foundation, Inc.
;; Keywords: comm, data, processes, hypermedia
diff --git a/lisp/url/url-cid.el b/lisp/url/url-cid.el
index a716b37abbe..17a0318e652 100644
--- a/lisp/url/url-cid.el
+++ b/lisp/url/url-cid.el
@@ -1,6 +1,6 @@
;;; url-cid.el --- Content-ID URL loader -*- lexical-binding: t; -*-
-;; Copyright (C) 1998-1999, 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-1999, 2004-2024 Free Software Foundation, Inc.
;; Keywords: comm, data, processes
diff --git a/lisp/url/url-cookie.el b/lisp/url/url-cookie.el
index 22b36980c9e..4c1ea2e185b 100644
--- a/lisp/url/url-cookie.el
+++ b/lisp/url/url-cookie.el
@@ -1,6 +1,6 @@
;;; url-cookie.el --- URL cookie support -*- lexical-binding:t -*-
-;; Copyright (C) 1996-1999, 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-1999, 2004-2024 Free Software Foundation, Inc.
;; Keywords: comm, data, processes, hypermedia
diff --git a/lisp/url/url-dav.el b/lisp/url/url-dav.el
index 7e7cd863f46..632b2dac9d0 100644
--- a/lisp/url/url-dav.el
+++ b/lisp/url/url-dav.el
@@ -1,6 +1,6 @@
;;; url-dav.el --- WebDAV support -*- lexical-binding: t; -*-
-;; Copyright (C) 2001, 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001, 2004-2024 Free Software Foundation, Inc.
;; Author: Bill Perry <wmperry@gnu.org>
;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/url/url-domsuf.el b/lisp/url/url-domsuf.el
index 671885e418f..b720f73efd7 100644
--- a/lisp/url/url-domsuf.el
+++ b/lisp/url/url-domsuf.el
@@ -1,6 +1,6 @@
;;; url-domsuf.el --- Say what domain names can have cookies set. -*- lexical-binding:t -*-
-;; Copyright (C) 2012-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2012-2024 Free Software Foundation, Inc.
;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
diff --git a/lisp/url/url-expand.el b/lisp/url/url-expand.el
index b3f29a7063d..39d4d722cc8 100644
--- a/lisp/url/url-expand.el
+++ b/lisp/url/url-expand.el
@@ -1,6 +1,6 @@
;;; url-expand.el --- expand-file-name for URLs -*- lexical-binding: t -*-
-;; Copyright (C) 1999, 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999, 2004-2024 Free Software Foundation, Inc.
;; Keywords: comm, data, processes
diff --git a/lisp/url/url-file.el b/lisp/url/url-file.el
index f63fce3e000..5277e99a158 100644
--- a/lisp/url/url-file.el
+++ b/lisp/url/url-file.el
@@ -1,6 +1,6 @@
;;; url-file.el --- File retrieval code -*- lexical-binding:t -*-
-;; Copyright (C) 1996-1999, 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-1999, 2004-2024 Free Software Foundation, Inc.
;; Keywords: comm, data, processes
diff --git a/lisp/url/url-ftp.el b/lisp/url/url-ftp.el
index c3ea4dce714..439de574382 100644
--- a/lisp/url/url-ftp.el
+++ b/lisp/url/url-ftp.el
@@ -1,6 +1,6 @@
;;; url-ftp.el --- FTP wrapper -*- lexical-binding: t -*-
-;; Copyright (C) 1996-1999, 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-1999, 2004-2024 Free Software Foundation, Inc.
;; Keywords: comm, data, processes
diff --git a/lisp/url/url-future.el b/lisp/url/url-future.el
index 9b528835a7b..790da8b5d6d 100644
--- a/lisp/url/url-future.el
+++ b/lisp/url/url-future.el
@@ -1,6 +1,6 @@
;;; url-future.el --- general futures facility for url.el -*- lexical-binding: t -*-
-;; Copyright (C) 2011-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2011-2024 Free Software Foundation, Inc.
;; Author: Teodor Zlatanov <tzz@lifelogs.com>
;; Keywords: data
diff --git a/lisp/url/url-gw.el b/lisp/url/url-gw.el
index 4d7297f6f2e..62be70827fa 100644
--- a/lisp/url/url-gw.el
+++ b/lisp/url/url-gw.el
@@ -1,6 +1,6 @@
;;; url-gw.el --- Gateway munging for URL loading -*- lexical-binding: t; -*-
-;; Copyright (C) 1997-1998, 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997-1998, 2004-2024 Free Software Foundation, Inc.
;; Author: Bill Perry <wmperry@gnu.org>
;; Maintainer: emacs-devel@gnu.org
@@ -97,21 +97,27 @@ This list will be executed as a command after logging in via telnet."
(defcustom url-gateway-broken-resolution nil
"Whether to use nslookup to resolve hostnames.
-This should be used when your version of Emacs cannot correctly use DNS,
-but your machine can. This usually happens if you are running a statically
-linked Emacs under SunOS 4.x."
+This should be used when your version of Emacs cannot correctly
+use DNS, but your machine can.
+
+This used to happen on SunOS 4.x and Ultrix when Emacs was linked
+statically, and also was not linked with the resolver libraries.
+Those systems are no longer supported by Emacs."
:type 'boolean
:group 'url-gateway)
+(make-obsolete-variable 'url-gateway-broken-resolution nil "30.1")
(defcustom url-gateway-nslookup-program "nslookup"
"If non-nil then a string naming nslookup program."
:type '(choice (const :tag "None" :value nil) string)
:group 'url-gateway)
+(make-obsolete-variable 'url-gateway-nslookup-program nil "30.1")
;; Stolen from ange-ftp
;;;###autoload
(defun url-gateway-nslookup-host (host)
"Attempt to resolve the given HOST using nslookup if possible."
+ (declare (obsolete nil "30.1"))
(interactive "sHost: ")
(if url-gateway-nslookup-program
(let ((proc (start-process " *nslookup*" " *nslookup*"
@@ -237,7 +243,8 @@ overriding the value of `url-gateway-method'."
;; If the user told us to do DNS for them, do it.
(if url-gateway-broken-resolution
- (setq host (url-gateway-nslookup-host host)))
+ (with-suppressed-warnings ((obsolete url-gateway-nslookup-host))
+ (setq host (url-gateway-nslookup-host host))))
;; This is a clean way to ensure the new process inherits the
;; right coding systems in both Emacs and XEmacs.
diff --git a/lisp/url/url-handlers.el b/lisp/url/url-handlers.el
index cb4c811185c..9edc7865a74 100644
--- a/lisp/url/url-handlers.el
+++ b/lisp/url/url-handlers.el
@@ -1,6 +1,6 @@
;;; url-handlers.el --- file-name-handler stuff for URL loading -*- lexical-binding:t -*-
-;; Copyright (C) 1996-1999, 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-1999, 2004-2024 Free Software Foundation, Inc.
;; Keywords: comm, data, processes, hypermedia
diff --git a/lisp/url/url-history.el b/lisp/url/url-history.el
index 0264f16366d..e4f353afd02 100644
--- a/lisp/url/url-history.el
+++ b/lisp/url/url-history.el
@@ -1,6 +1,6 @@
;;; url-history.el --- Global history tracking for URL package -*- lexical-binding:t -*-
-;; Copyright (C) 1996-1999, 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-1999, 2004-2024 Free Software Foundation, Inc.
;; Keywords: comm, data, processes, hypermedia
diff --git a/lisp/url/url-http.el b/lisp/url/url-http.el
index ada6341ee73..d6a1d0eade8 100644
--- a/lisp/url/url-http.el
+++ b/lisp/url/url-http.el
@@ -1,6 +1,6 @@
;;; url-http.el --- HTTP retrieval routines -*- lexical-binding:t -*-
-;; Copyright (C) 1999, 2001, 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999, 2001, 2004-2024 Free Software Foundation, Inc.
;; Author: Bill Perry <wmperry@gnu.org>
;; Maintainer: emacs-devel@gnu.org
@@ -358,10 +358,6 @@ Use `url-http-referer' as the Referer-header (subject to `url-privacy-level')."
(url-port url-http-target-url))
(format "Host: %s\r\n"
(url-http--encode-string (puny-encode-domain host))))
- ;; Who its from
- (if url-personal-mail-address
- (concat
- "From: " url-personal-mail-address "\r\n"))
;; Encodings we understand
(if (or url-mime-encoding-string
;; MS-Windows loads zlib dynamically, so recheck
diff --git a/lisp/url/url-imap.el b/lisp/url/url-imap.el
index 6fa34e6c791..abfd21bc375 100644
--- a/lisp/url/url-imap.el
+++ b/lisp/url/url-imap.el
@@ -1,6 +1,6 @@
;;; url-imap.el --- IMAP retrieval routines -*- lexical-binding: t; -*-
-;; Copyright (C) 1999, 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999, 2004-2024 Free Software Foundation, Inc.
;; Author: Simon Josefsson <jas@pdc.kth.se>
;; Keywords: comm, data, processes
diff --git a/lisp/url/url-irc.el b/lisp/url/url-irc.el
index 1463335d40f..e6499bce31e 100644
--- a/lisp/url/url-irc.el
+++ b/lisp/url/url-irc.el
@@ -1,6 +1,6 @@
;;; url-irc.el --- IRC URL interface -*- lexical-binding: t -*-
-;; Copyright (C) 1996-1999, 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-1999, 2004-2024 Free Software Foundation, Inc.
;; Keywords: comm, data, processes
@@ -83,18 +83,20 @@ PASSWORD - What password to use.
(pass (url-password url))
(user (url-user url))
(chan (url-filename url))
- (type (url-type url))
- (compatp (eql 5 (cdr (func-arity url-irc-function)))))
+ (type (url-type url)))
(if (url-target url)
(setq chan (concat chan "#" (url-target url))))
(if (string-match "^/" chan)
(setq chan (substring chan 1 nil)))
(if (= (length chan) 0)
(setq chan nil))
- (when compatp
- (lwarn 'url :error "Obsolete value for `url-irc-function'"))
- (apply url-irc-function
- host port chan user pass (unless compatp (list type)))
+ (condition-case nil
+ (funcall url-irc-function host port chan user pass type)
+ (wrong-number-of-arguments
+ (display-warning 'url
+ (concat "Incompatible value for `url-irc-function'."
+ " Likely not expecting a 6th (SCHEME) arg."))
+ (funcall url-irc-function host port chan user pass)))
nil))
;;;; ircs://
diff --git a/lisp/url/url-ldap.el b/lisp/url/url-ldap.el
index f06ba1cd8de..1bdd5099637 100644
--- a/lisp/url/url-ldap.el
+++ b/lisp/url/url-ldap.el
@@ -1,6 +1,6 @@
;;; url-ldap.el --- LDAP Uniform Resource Locator retrieval code -*- lexical-binding: t; -*-
-;; Copyright (C) 1998-1999, 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-1999, 2004-2024 Free Software Foundation, Inc.
;; Keywords: comm, data, processes
diff --git a/lisp/url/url-mailto.el b/lisp/url/url-mailto.el
index 04d6d9681ff..c2d347a1646 100644
--- a/lisp/url/url-mailto.el
+++ b/lisp/url/url-mailto.el
@@ -1,6 +1,6 @@
;;; url-mailto.el --- Mail Uniform Resource Locator retrieval code -*- lexical-binding: t; -*-
-;; Copyright (C) 1996-1999, 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-1999, 2004-2024 Free Software Foundation, Inc.
;; Keywords: comm, data, processes
diff --git a/lisp/url/url-methods.el b/lisp/url/url-methods.el
index 9643e992044..5681a4e3785 100644
--- a/lisp/url/url-methods.el
+++ b/lisp/url/url-methods.el
@@ -1,6 +1,6 @@
;;; url-methods.el --- Load URL schemes as needed -*- lexical-binding: t; -*-
-;; Copyright (C) 1996-1999, 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-1999, 2004-2024 Free Software Foundation, Inc.
;; Keywords: comm, data, processes, hypermedia
diff --git a/lisp/url/url-misc.el b/lisp/url/url-misc.el
index 96f5c46ea00..23dd5f2d743 100644
--- a/lisp/url/url-misc.el
+++ b/lisp/url/url-misc.el
@@ -1,6 +1,6 @@
;;; url-misc.el --- Misc Uniform Resource Locator retrieval code -*- lexical-binding: t; -*-
-;; Copyright (C) 1996-1999, 2002, 2004-2023 Free Software Foundation,
+;; Copyright (C) 1996-1999, 2002, 2004-2024 Free Software Foundation,
;; Inc.
;; Keywords: comm, data, processes
diff --git a/lisp/url/url-news.el b/lisp/url/url-news.el
index 592f34213ee..9271a2d7a63 100644
--- a/lisp/url/url-news.el
+++ b/lisp/url/url-news.el
@@ -1,6 +1,6 @@
;;; url-news.el --- News Uniform Resource Locator retrieval code -*- lexical-binding: t; -*-
-;; Copyright (C) 1996-1999, 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-1999, 2004-2024 Free Software Foundation, Inc.
;; Keywords: comm, data, processes
diff --git a/lisp/url/url-nfs.el b/lisp/url/url-nfs.el
index 76f9b04076c..d00ec6d27f4 100644
--- a/lisp/url/url-nfs.el
+++ b/lisp/url/url-nfs.el
@@ -1,6 +1,6 @@
;;; url-nfs.el --- NFS URL interface -*- lexical-binding: t; -*-
-;; Copyright (C) 1996-1999, 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-1999, 2004-2024 Free Software Foundation, Inc.
;; Keywords: comm, data, processes
diff --git a/lisp/url/url-parse.el b/lisp/url/url-parse.el
index cd0e155e954..e7b6541342a 100644
--- a/lisp/url/url-parse.el
+++ b/lisp/url/url-parse.el
@@ -1,6 +1,6 @@
;;; url-parse.el --- Uniform Resource Locator parser -*- lexical-binding: t -*-
-;; Copyright (C) 1996-1999, 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-1999, 2004-2024 Free Software Foundation, Inc.
;; Keywords: comm, data, processes
diff --git a/lisp/url/url-privacy.el b/lisp/url/url-privacy.el
index 2be77b33035..aa710588f49 100644
--- a/lisp/url/url-privacy.el
+++ b/lisp/url/url-privacy.el
@@ -1,6 +1,6 @@
;;; url-privacy.el --- Global history tracking for URL package -*- lexical-binding: t; -*-
-;; Copyright (C) 1996-1999, 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-1999, 2004-2024 Free Software Foundation, Inc.
;; Keywords: comm, data, processes, hypermedia
@@ -59,16 +59,6 @@
('tty "TTY")
(_ nil)))))
- (setq url-personal-mail-address (or url-personal-mail-address
- user-mail-address
- (format "%s@%s" (user-real-login-name)
- (system-name))))
-
- (if (or (memq url-privacy-level '(paranoid high))
- (and (listp url-privacy-level)
- (memq 'email url-privacy-level)))
- (setq url-personal-mail-address nil))
-
(setq url-os-type
(cond
((or (eq url-privacy-level 'paranoid)
diff --git a/lisp/url/url-proxy.el b/lisp/url/url-proxy.el
index 0c330069789..15f117f0a34 100644
--- a/lisp/url/url-proxy.el
+++ b/lisp/url/url-proxy.el
@@ -1,6 +1,6 @@
;;; url-proxy.el --- Proxy server support -*- lexical-binding: t; -*-
-;; Copyright (C) 1999, 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999, 2004-2024 Free Software Foundation, Inc.
;; Keywords: comm, data, processes, hypermedia
diff --git a/lisp/url/url-queue.el b/lisp/url/url-queue.el
index f89f38bf965..79340059bca 100644
--- a/lisp/url/url-queue.el
+++ b/lisp/url/url-queue.el
@@ -1,6 +1,6 @@
;;; url-queue.el --- Fetching web pages in parallel -*- lexical-binding: t -*-
-;; Copyright (C) 2011-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2011-2024 Free Software Foundation, Inc.
;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
;; Keywords: comm
diff --git a/lisp/url/url-tramp.el b/lisp/url/url-tramp.el
index 172e0de6ab0..a56e707457c 100644
--- a/lisp/url/url-tramp.el
+++ b/lisp/url/url-tramp.el
@@ -1,6 +1,6 @@
;;; url-tramp.el --- file-name-handler magic invoking Tramp for some protocols -*- lexical-binding: t; -*-
-;; Copyright (C) 2014-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2014-2024 Free Software Foundation, Inc.
;; Author: Michael Albinus <michael.albinus@gmx.de>
;; Keywords: comm, data, processes, hypermedia
diff --git a/lisp/url/url-util.el b/lisp/url/url-util.el
index a7cb8364b5f..28d1885387d 100644
--- a/lisp/url/url-util.el
+++ b/lisp/url/url-util.el
@@ -1,6 +1,6 @@
;;; url-util.el --- Miscellaneous helper routines for URL library -*- lexical-binding: t -*-
-;; Copyright (C) 1996-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-2024 Free Software Foundation, Inc.
;; Author: Bill Perry <wmperry@gnu.org>
;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/url/url-vars.el b/lisp/url/url-vars.el
index 7e2290217d0..09b3019a553 100644
--- a/lisp/url/url-vars.el
+++ b/lisp/url/url-vars.el
@@ -1,6 +1,6 @@
;;; url-vars.el --- Variables for Uniform Resource Locator tool -*- lexical-binding:t -*-
-;; Copyright (C) 1996-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-2024 Free Software Foundation, Inc.
;; Keywords: comm, data, processes, hypermedia
@@ -90,6 +90,7 @@ This is what is sent to HTTP servers as the FROM field in an HTTP
request."
:type '(choice (const :tag "Unspecified" nil) string)
:group 'url)
+(make-obsolete-variable 'url-personal-mail-address nil "30.1")
(defcustom url-directory-index-file "index.html"
"The filename to look for when indexing a directory.
@@ -113,18 +114,22 @@ paranoid -- don't send anything
If a list, this should be a list of symbols of what NOT to send.
Valid symbols are:
-email -- the email address
+email -- the email address (in Emacs 29 or older)
os -- the operating system info
emacs -- the version of Emacs
lastloc -- the last location (see also `url-lastloc-privacy-level')
agent -- do not send the User-Agent string
cookies -- never accept HTTP cookies
+Emacs 30 and newer never includes the email address in the
+User-Agent string. If you expect to use older versions of Emacs,
+it is recommended to always customize this list to include `email'.
+
Samples:
(setq url-privacy-level \\='high)
(setq url-privacy-level \\='(email lastloc)) ;; equivalent to \\='high
- (setq url-privacy-level \\='(os))
+ (setq url-privacy-level \\='(email lastloc os emacs))
::NOTE::
This variable controls several other variables and is _NOT_ automatically
@@ -146,7 +151,7 @@ variable."
(const :tag "Emacs version" :value emacs)
(const :tag "Last location" :value lastloc)
(const :tag "Browser identification" :value agent)
- (const :tag "No cookies" :value cookie)))
+ (const :tag "No cookies" :value cookies)))
:group 'url)
(defcustom url-lastloc-privacy-level 'domain-match
@@ -331,7 +336,7 @@ undefined."
(defcustom url-max-redirections 30
"The maximum number of redirection requests to honor in a HTTP connection.
A negative number means to honor an unlimited number of redirection requests."
- :type 'natnum
+ :type 'integer
:group 'url)
(defcustom url-confirmation-func 'y-or-n-p
diff --git a/lisp/url/url.el b/lisp/url/url.el
index 09e555a7b15..dea251b453b 100644
--- a/lisp/url/url.el
+++ b/lisp/url/url.el
@@ -1,6 +1,6 @@
;;; url.el --- Uniform Resource Locator retrieval tool -*- lexical-binding: t -*-
-;; Copyright (C) 1996-1999, 2001, 2004-2023 Free Software Foundation,
+;; Copyright (C) 1996-1999, 2001, 2004-2024 Free Software Foundation,
;; Inc.
;; Author: Bill Perry <wmperry@gnu.org>
diff --git a/lisp/use-package/use-package-bind-key.el b/lisp/use-package/use-package-bind-key.el
index 47eb066eba0..18c3f29cf34 100644
--- a/lisp/use-package/use-package-bind-key.el
+++ b/lisp/use-package/use-package-bind-key.el
@@ -1,6 +1,6 @@
;;; use-package-bind-key.el --- Support for the :bind/:bind-keymap keywords -*- lexical-binding: t; -*-
-;; Copyright (C) 2012-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2012-2024 Free Software Foundation, Inc.
;; Author: John Wiegley <johnw@newartisans.com>
;; Maintainer: John Wiegley <johnw@newartisans.com>
diff --git a/lisp/use-package/use-package-core.el b/lisp/use-package/use-package-core.el
index 34c45b7aec3..d9343e14839 100644
--- a/lisp/use-package/use-package-core.el
+++ b/lisp/use-package/use-package-core.el
@@ -1,6 +1,6 @@
;;; use-package-core.el --- A configuration macro for simplifying your .emacs -*- lexical-binding: t; -*-
-;; Copyright (C) 2012-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2012-2024 Free Software Foundation, Inc.
;; Author: John Wiegley <johnw@newartisans.com>
;; Maintainer: John Wiegley <johnw@newartisans.com>
@@ -1619,7 +1619,7 @@ ARG is the normalized input to the `:vc' keyword, as returned by
the `use-package-normalize/:vc' function.
REST is a plist of other (following) keywords and their
-arguments, each having already been normalised by the respective
+arguments, each having already been normalized by the respective
function.
STATE is a plist of any state that keywords processed before
@@ -1690,7 +1690,7 @@ node `(use-package) Creating an extension'."
(`(,(pred symbolp) . ,(or (pred plistp) ; plist/version string + name
(pred stringp)))
(use-package-normalize--vc-arg arg))
- (_ (use-package-error "Unrecognised argument to :vc.\
+ (_ (use-package-error "Unrecognized argument to :vc.\
The keyword wants an argument of nil, t, a name of a package,\
or a cons-cell as accepted by `package-vc-selected-packages', where \
the accepted plist is augmented by a `:rev' keyword.")))))
diff --git a/lisp/use-package/use-package-delight.el b/lisp/use-package/use-package-delight.el
index 4f571cd3990..c458d263cf0 100644
--- a/lisp/use-package/use-package-delight.el
+++ b/lisp/use-package/use-package-delight.el
@@ -1,6 +1,6 @@
;;; use-package-delight.el --- Support for the :delight keyword -*- lexical-binding: t; -*-
-;; Copyright (C) 2012-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2012-2024 Free Software Foundation, Inc.
;; Author: John Wiegley <johnw@newartisans.com>
;; Maintainer: John Wiegley <johnw@newartisans.com>
diff --git a/lisp/use-package/use-package-diminish.el b/lisp/use-package/use-package-diminish.el
index f683694dbd8..79421a0e273 100644
--- a/lisp/use-package/use-package-diminish.el
+++ b/lisp/use-package/use-package-diminish.el
@@ -1,6 +1,6 @@
;;; use-package-diminish.el --- Support for the :diminish keyword -*- lexical-binding: t; -*-
-;; Copyright (C) 2012-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2012-2024 Free Software Foundation, Inc.
;; Author: John Wiegley <johnw@newartisans.com>
;; Maintainer: John Wiegley <johnw@newartisans.com>
diff --git a/lisp/use-package/use-package-ensure-system-package.el b/lisp/use-package/use-package-ensure-system-package.el
index ef4afac1a0b..025721746cc 100644
--- a/lisp/use-package/use-package-ensure-system-package.el
+++ b/lisp/use-package/use-package-ensure-system-package.el
@@ -1,6 +1,6 @@
;;; use-package-ensure-system-package.el --- auto install system packages -*- lexical-binding: t; -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;; Author: Justin Talbott <justin@waymondo.com>
;; Keywords: convenience, tools, extensions
diff --git a/lisp/use-package/use-package-ensure.el b/lisp/use-package/use-package-ensure.el
index 395a0bbda00..5f75b6b59ea 100644
--- a/lisp/use-package/use-package-ensure.el
+++ b/lisp/use-package/use-package-ensure.el
@@ -1,6 +1,6 @@
;;; use-package-ensure.el --- Support for the :ensure and :pin keywords -*- lexical-binding: t; -*-
-;; Copyright (C) 2012-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2012-2024 Free Software Foundation, Inc.
;; Author: John Wiegley <johnw@newartisans.com>
;; Maintainer: John Wiegley <johnw@newartisans.com>
diff --git a/lisp/use-package/use-package-jump.el b/lisp/use-package/use-package-jump.el
index 4fc5c3f0a8e..604b2600b3d 100644
--- a/lisp/use-package/use-package-jump.el
+++ b/lisp/use-package/use-package-jump.el
@@ -1,6 +1,6 @@
;;; use-package-jump.el --- Attempt to jump to a use-package declaration -*- lexical-binding: t; -*-
-;; Copyright (C) 2012-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2012-2024 Free Software Foundation, Inc.
;; Author: John Wiegley <johnw@newartisans.com>
;; Maintainer: John Wiegley <johnw@newartisans.com>
diff --git a/lisp/use-package/use-package-lint.el b/lisp/use-package/use-package-lint.el
index 9239d01148a..15c58809478 100644
--- a/lisp/use-package/use-package-lint.el
+++ b/lisp/use-package/use-package-lint.el
@@ -1,6 +1,6 @@
;;; use-package-lint.el --- Attempt to find errors in use-package declarations -*- lexical-binding: t; -*-
-;; Copyright (C) 2012-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2012-2024 Free Software Foundation, Inc.
;; Author: John Wiegley <johnw@newartisans.com>
;; Maintainer: John Wiegley <johnw@newartisans.com>
diff --git a/lisp/use-package/use-package.el b/lisp/use-package/use-package.el
index 1b63a6d651a..fc5c994a5f9 100644
--- a/lisp/use-package/use-package.el
+++ b/lisp/use-package/use-package.el
@@ -1,6 +1,6 @@
;;; use-package.el --- A configuration macro for simplifying your .emacs -*- lexical-binding: t; -*-
-;; Copyright (C) 2012-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2012-2024 Free Software Foundation, Inc.
;; Author: John Wiegley <johnw@newartisans.com>
;; Maintainer: John Wiegley <johnw@newartisans.com>
@@ -10,6 +10,9 @@
;; Keywords: dotemacs startup speed config package extensions
;; URL: https://github.com/jwiegley/use-package
+;; This is a GNU ELPA :core package. Avoid functionality that is not
+;; compatible with the version of Emacs recorded above.
+
;; This file is part of GNU Emacs.
;; GNU Emacs is free software: you can redistribute it and/or modify
diff --git a/lisp/userlock.el b/lisp/userlock.el
index 4623608f1db..db94bb214e6 100644
--- a/lisp/userlock.el
+++ b/lisp/userlock.el
@@ -1,6 +1,6 @@
;;; userlock.el --- handle file access contention between multiple users -*- lexical-binding: t -*-
-;; Copyright (C) 1985-1986, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1985-1986, 2001-2024 Free Software Foundation, Inc.
;; Author: Richard King
;; (according to authors.el)
@@ -64,10 +64,11 @@ in any way you like."
(match-string 0 opponent)))
opponent))
(while (null answer)
+ (when noninteractive
+ (signal 'file-locked (list file opponent "Cannot resolve lock conflict in batch mode")))
(message (substitute-command-keys
"%s locked by %s: (\\`s', \\`q', \\`p', \\`?')? ")
short-file short-opponent)
- (if noninteractive (error "Cannot resolve lock conflict in batch mode"))
(let ((tem (let ((inhibit-quit t)
(cursor-in-echo-area t))
(prog1 (downcase (read-char))
diff --git a/lisp/vc/add-log.el b/lisp/vc/add-log.el
index 22ae6db72ab..d4751f66723 100644
--- a/lisp/vc/add-log.el
+++ b/lisp/vc/add-log.el
@@ -1,6 +1,6 @@
;;; add-log.el --- change log maintenance commands for Emacs -*- lexical-binding: t; -*-
-;; Copyright (C) 1985-1986, 1988, 1993-1994, 1997-1998, 2000-2023 Free
+;; Copyright (C) 1985-1986, 1988, 1993-1994, 1997-1998, 2000-2024 Free
;; Software Foundation, Inc.
;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/vc/compare-w.el b/lisp/vc/compare-w.el
index 728198eb361..4aca2707115 100644
--- a/lisp/vc/compare-w.el
+++ b/lisp/vc/compare-w.el
@@ -1,6 +1,6 @@
;;; compare-w.el --- compare text between windows for Emacs -*- lexical-binding: t; -*-
-;; Copyright (C) 1986-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1986-2024 Free Software Foundation, Inc.
;; Maintainer: emacs-devel@gnu.org
;; Keywords: convenience files vc
diff --git a/lisp/vc/cvs-status.el b/lisp/vc/cvs-status.el
index 7982cd89efc..c9ad1d13d24 100644
--- a/lisp/vc/cvs-status.el
+++ b/lisp/vc/cvs-status.el
@@ -1,6 +1,6 @@
;;; cvs-status.el --- major mode for browsing `cvs status' output -*- lexical-binding: t -*-
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
;; Keywords: pcl-cvs cvs status tree vc tools
@@ -352,10 +352,8 @@ the list is a three-string list TAG, KIND, REV."
(delete-region pt (point)))
tags)))
-(defvar font-lock-mode)
;; (defun cvs-refontify (beg end)
-;; (when (and font-lock-mode
-;; (fboundp 'font-lock-fontify-region))
+;; (when font-lock-mode
;; (font-lock-fontify-region (1- beg) (1+ end))))
(defun cvs-status-trees ()
diff --git a/lisp/vc/diff-mode.el b/lisp/vc/diff-mode.el
index d776375d681..03efe0fdb31 100644
--- a/lisp/vc/diff-mode.el
+++ b/lisp/vc/diff-mode.el
@@ -1,6 +1,6 @@
;;; diff-mode.el --- a mode for viewing/editing context diffs -*- lexical-binding: t -*-
-;; Copyright (C) 1998-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-2024 Free Software Foundation, Inc.
;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
;; Keywords: convenience patch diff vc
@@ -216,6 +216,7 @@ The default \"-b\" means to ignore whitespace-only changes,
"C-x 4 A" #'diff-add-change-log-entries-other-window
;; Misc operations.
"C-c C-a" #'diff-apply-hunk
+ "C-c C-m a" #'diff-apply-buffer
"C-c C-e" #'diff-ediff-patch
"C-c C-n" #'diff-restrict-view
"C-c C-s" #'diff-split-hunk
@@ -2054,6 +2055,40 @@ With a prefix argument, try to REVERSE the hunk."
(diff-hunk-kill)
(diff-hunk-next)))))
+(defun diff-apply-buffer ()
+ "Apply the diff in the entire diff buffer.
+When applying all hunks was successful, then save the changed buffers."
+ (interactive)
+ (let ((buffer-edits nil)
+ (failures 0)
+ (diff-refine nil))
+ (save-excursion
+ (goto-char (point-min))
+ (diff-beginning-of-hunk t)
+ (while (pcase-let ((`(,buf ,line-offset ,pos ,_src ,dst ,switched)
+ (diff-find-source-location nil nil)))
+ (cond ((and line-offset (not switched))
+ (push (cons pos dst)
+ (alist-get buf buffer-edits)))
+ (t (setq failures (1+ failures))))
+ (and (not (eq (prog1 (point) (ignore-errors (diff-hunk-next)))
+ (point)))
+ (looking-at-p diff-hunk-header-re)))))
+ (cond ((zerop failures)
+ (dolist (buf-edits (reverse buffer-edits))
+ (with-current-buffer (car buf-edits)
+ (dolist (edit (cdr buf-edits))
+ (let ((pos (car edit))
+ (dst (cdr edit))
+ (inhibit-read-only t))
+ (goto-char (car pos))
+ (delete-region (car pos) (cdr pos))
+ (insert (car dst))))
+ (save-buffer)))
+ (message "Saved %d buffers" (length buffer-edits)))
+ (t
+ (message "%d hunks failed; no buffers changed" failures)))))
+
(defalias 'diff-mouse-goto-source #'diff-goto-source)
(defun diff-goto-source (&optional other-file event)
diff --git a/lisp/vc/diff.el b/lisp/vc/diff.el
index 90c43d111f5..a64fbc47853 100644
--- a/lisp/vc/diff.el
+++ b/lisp/vc/diff.el
@@ -1,6 +1,6 @@
;;; diff.el --- run `diff' -*- lexical-binding: t -*-
-;; Copyright (C) 1992, 1994, 1996, 2001-2023 Free Software Foundation,
+;; Copyright (C) 1992, 1994, 1996, 2001-2024 Free Software Foundation,
;; Inc.
;; Author: Frank Bresz
@@ -165,7 +165,7 @@ returns the buffer used."
(unless (bufferp new) (setq new (expand-file-name new)))
(unless (bufferp old) (setq old (expand-file-name old)))
(or switches (setq switches diff-switches)) ; If not specified, use default.
- (unless (listp switches) (setq switches (list switches)))
+ (setq switches (ensure-list switches))
(or buf (setq buf (get-buffer-create "*Diff*")))
(diff-check-labels)
(let* ((old-alt (diff-file-local-copy old))
diff --git a/lisp/vc/ediff-diff.el b/lisp/vc/ediff-diff.el
index 42c313b3f07..83bd7cde12f 100644
--- a/lisp/vc/ediff-diff.el
+++ b/lisp/vc/ediff-diff.el
@@ -1,6 +1,6 @@
;;; ediff-diff.el --- diff-related utilities -*- lexical-binding:t -*-
-;; Copyright (C) 1994-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1994-2024 Free Software Foundation, Inc.
;; Author: Michael Kifer <kifer@cs.stonybrook.edu>
;; Package: ediff
diff --git a/lisp/vc/ediff-help.el b/lisp/vc/ediff-help.el
index e8d4b3d4f5d..56e1ec80c5c 100644
--- a/lisp/vc/ediff-help.el
+++ b/lisp/vc/ediff-help.el
@@ -1,6 +1,6 @@
;;; ediff-help.el --- Code related to the contents of Ediff help buffers -*- lexical-binding:t -*-
-;; Copyright (C) 1996-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-2024 Free Software Foundation, Inc.
;; Author: Michael Kifer <kifer@cs.stonybrook.edu>
;; Package: ediff
diff --git a/lisp/vc/ediff-hook.el b/lisp/vc/ediff-hook.el
index 2f860d2ae73..3c78990d393 100644
--- a/lisp/vc/ediff-hook.el
+++ b/lisp/vc/ediff-hook.el
@@ -1,6 +1,6 @@
;;; ediff-hook.el --- setup for Ediff's menus and autoloads -*- lexical-binding:t -*-
-;; Copyright (C) 1995-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1995-2024 Free Software Foundation, Inc.
;; Author: Michael Kifer <kifer@cs.stonybrook.edu>
;; Package: ediff
diff --git a/lisp/vc/ediff-init.el b/lisp/vc/ediff-init.el
index 28630792211..c5eda873b5e 100644
--- a/lisp/vc/ediff-init.el
+++ b/lisp/vc/ediff-init.el
@@ -1,6 +1,6 @@
;;; ediff-init.el --- Macros, variables, and defsubsts used by Ediff -*- lexical-binding:t -*-
-;; Copyright (C) 1994-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1994-2024 Free Software Foundation, Inc.
;; Author: Michael Kifer <kifer@cs.stonybrook.edu>
;; Package: ediff
diff --git a/lisp/vc/ediff-merg.el b/lisp/vc/ediff-merg.el
index b1cc9fd8c28..606c23cb8aa 100644
--- a/lisp/vc/ediff-merg.el
+++ b/lisp/vc/ediff-merg.el
@@ -1,6 +1,6 @@
;;; ediff-merg.el --- merging utilities -*- lexical-binding:t -*-
-;; Copyright (C) 1994-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1994-2024 Free Software Foundation, Inc.
;; Author: Michael Kifer <kifer@cs.stonybrook.edu>
;; Package: ediff
diff --git a/lisp/vc/ediff-mult.el b/lisp/vc/ediff-mult.el
index 3fda8c7f2f1..66d4935cd75 100644
--- a/lisp/vc/ediff-mult.el
+++ b/lisp/vc/ediff-mult.el
@@ -1,6 +1,6 @@
;;; ediff-mult.el --- support for multi-file/multi-buffer processing in Ediff -*- lexical-binding:t -*-
-;; Copyright (C) 1995-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1995-2024 Free Software Foundation, Inc.
;; Author: Michael Kifer <kifer@cs.stonybrook.edu>
;; Package: ediff
diff --git a/lisp/vc/ediff-ptch.el b/lisp/vc/ediff-ptch.el
index e62434360aa..f8d4c1c1c4b 100644
--- a/lisp/vc/ediff-ptch.el
+++ b/lisp/vc/ediff-ptch.el
@@ -1,6 +1,6 @@
;;; ediff-ptch.el --- Ediff's patch support -*- lexical-binding:t -*-
-;; Copyright (C) 1996-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-2024 Free Software Foundation, Inc.
;; Author: Michael Kifer <kifer@cs.stonybrook.edu>
;; Package: ediff
diff --git a/lisp/vc/ediff-util.el b/lisp/vc/ediff-util.el
index 8011d7ce2e0..597d8a5e643 100644
--- a/lisp/vc/ediff-util.el
+++ b/lisp/vc/ediff-util.el
@@ -1,6 +1,6 @@
;;; ediff-util.el --- the core commands and utilities of ediff -*- lexical-binding:t -*-
-;; Copyright (C) 1994-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1994-2024 Free Software Foundation, Inc.
;; Author: Michael Kifer <kifer@cs.stonybrook.edu>
;; Package: ediff
@@ -1269,36 +1269,28 @@ which see."
(or (display-graphic-p)
(user-error "Emacs is not running as a window application"))
- (cond ((eq ediff-window-setup-function #'ediff-setup-windows-multiframe)
- (setq ediff-multiframe nil)
- (setq window-setup-func #'ediff-setup-windows-plain)
- (message "ediff is now in `plain' mode"))
- ((eq ediff-window-setup-function #'ediff-setup-windows-plain)
- (if (and (ediff-buffer-live-p ediff-control-buffer)
- (window-live-p ediff-control-window))
- (set-window-dedicated-p ediff-control-window nil))
- (setq ediff-multiframe t)
- (setq window-setup-func #'ediff-setup-windows-multiframe)
- (message "ediff is now in `multiframe' mode"))
- (t
- (if (and (ediff-buffer-live-p ediff-control-buffer)
- (window-live-p ediff-control-window))
- (set-window-dedicated-p ediff-control-window nil))
- (setq ediff-multiframe t)
- (setq window-setup-func #'ediff-setup-windows-multiframe))
- (message "ediff is now in `multiframe' mode"))
-
- ;; change default
- (setq-default ediff-window-setup-function window-setup-func)
- ;; change in all active ediff sessions
- (mapc (lambda(buf) (ediff-with-current-buffer buf
- (setq ediff-window-setup-function window-setup-func
- ediff-window-B nil)))
- ediff-session-registry)
- (if (ediff-in-control-buffer-p)
- (progn
- (set-window-dedicated-p (selected-window) nil)
- (ediff-recenter 'no-rehighlight)))))
+ (cond ((eq ediff-window-setup-function #'ediff-setup-windows-multiframe)
+ (setq ediff-multiframe nil)
+ (setq window-setup-func #'ediff-setup-windows-plain)
+ (message "ediff is now in `plain' mode"))
+ (t ; (eq ediff-window-setup-function #'ediff-setup-windows-plain)
+ (if (and (ediff-buffer-live-p ediff-control-buffer)
+ (window-live-p ediff-control-window))
+ (set-window-dedicated-p ediff-control-window nil))
+ (setq ediff-multiframe t)
+ (setq window-setup-func #'ediff-setup-windows-multiframe)
+ (message "ediff is now in `multiframe' mode")))
+
+ ;; change default
+ (setq-default ediff-window-setup-function window-setup-func)
+ ;; change in all active ediff sessions
+ (mapc (lambda (buf) (ediff-with-current-buffer buf
+ (setq ediff-window-setup-function window-setup-func
+ ediff-window-B nil)))
+ ediff-session-registry)
+ (when (ediff-in-control-buffer-p)
+ (set-window-dedicated-p (selected-window) nil)
+ (ediff-recenter 'no-rehighlight))))
;;;###autoload
@@ -3138,16 +3130,15 @@ Hit \\[ediff-recenter] to reset the windows afterward."
;; e.g., if file name ends with .Z or .gz
;; This is needed so that patches produced by ediff will
;; have more meaningful names
- (ediff-make-empty-tmp-file short-f))
+ (make-temp-file short-f))
(prefix
;; Prefix is most often the same as the file name for the
- ;; variant. Here we are trying to use the original file
- ;; name but in the temp directory.
- (ediff-make-empty-tmp-file f 'keep-name))
+ ;; variant.
+ (make-temp-file f))
(t
;; If don't care about name, add some random stuff
;; to proposed file name.
- (ediff-make-empty-tmp-file short-f))))
+ (make-temp-file short-f))))
;; create the file
(ediff-with-current-buffer buff
@@ -3159,28 +3150,6 @@ Hit \\[ediff-recenter] to reset the windows afterward."
(set-file-modes f ediff-temp-file-mode)
(expand-file-name f))))
-;; Create a temporary file.
-;; The returned file name (created by appending some random characters at the
-;; end of PROPOSED-NAME is guaranteed to point to a newly created empty file.
-;; This is a replacement for make-temp-name, which eliminates a security hole.
-;; If KEEP-PROPOSED-NAME isn't nil, try to keep PROPOSED-NAME, unless such file
-;; already exists.
-;; It is a modified version of make-temp-file in emacs 20.5
-(defun ediff-make-empty-tmp-file (proposed-name &optional keep-proposed-name)
- (let ((file proposed-name))
- (while (condition-case ()
- (progn
- (if (or (file-exists-p file) (not keep-proposed-name))
- (setq file (make-temp-name proposed-name)))
- (write-region "" nil file nil 'silent nil 'excl)
- nil)
- (file-already-exists t))
- ;; the file was somehow created by someone else between
- ;; `make-temp-name' and `write-region', let's try again.
- nil)
- file))
-
-
;; Make sure the current buffer (for a file) has the same contents as the
;; file on disk, and attempt to remedy the situation if not.
;; Signal an error if we can't make them the same, or the user doesn't want
@@ -3741,7 +3710,7 @@ Ediff Control Panel to restore highlighting."
;; these buffers).
;; EXCL-BUFF-LIST is an exclusion list.
(defun ediff-other-buffer (excl-buff-lst)
- (or (listp excl-buff-lst) (setq excl-buff-lst (list excl-buff-lst)))
+ (setq excl-buff-lst (ensure-list excl-buff-lst))
(let* ((all-buffers (nconc (ediff-get-selected-buffers) (buffer-list)))
;; we compute this the second time because we need to do memq on it
;; later, and nconc above will break it. Either this or use slow
@@ -4144,6 +4113,10 @@ Mail anyway? (y or n) ")
(define-obsolete-function-alias 'ediff-intersection #'seq-intersection "28.1")
(define-obsolete-function-alias 'ediff-set-difference #'seq-difference "28.1")
+(defun ediff-make-empty-tmp-file (prefix &optional _ignored)
+ (declare (obsolete make-temp-file "30.1"))
+ (make-temp-file prefix))
+
(run-hooks 'ediff-load-hook)
;;; ediff-util.el ends here
diff --git a/lisp/vc/ediff-vers.el b/lisp/vc/ediff-vers.el
index ed85764682f..52856b06399 100644
--- a/lisp/vc/ediff-vers.el
+++ b/lisp/vc/ediff-vers.el
@@ -1,6 +1,6 @@
;;; ediff-vers.el --- version control interface to Ediff -*- lexical-binding:t -*-
-;; Copyright (C) 1995-1997, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1995-1997, 2001-2024 Free Software Foundation, Inc.
;; Author: Michael Kifer <kifer@cs.stonybrook.edu>
;; Package: ediff
diff --git a/lisp/vc/ediff-wind.el b/lisp/vc/ediff-wind.el
index 7d7f849b09c..0e172e60277 100644
--- a/lisp/vc/ediff-wind.el
+++ b/lisp/vc/ediff-wind.el
@@ -1,6 +1,6 @@
;;; ediff-wind.el --- window manipulation utilities -*- lexical-binding:t -*-
-;; Copyright (C) 1994-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1994-2024 Free Software Foundation, Inc.
;; Author: Michael Kifer <kifer@cs.stonybrook.edu>
;; Package: ediff
diff --git a/lisp/vc/ediff.el b/lisp/vc/ediff.el
index 24836e1b1c1..30cc107d60b 100644
--- a/lisp/vc/ediff.el
+++ b/lisp/vc/ediff.el
@@ -1,6 +1,6 @@
;;; ediff.el --- a comprehensive visual interface to diff & patch -*- lexical-binding:t -*-
-;; Copyright (C) 1994-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1994-2024 Free Software Foundation, Inc.
;; Author: Michael Kifer <kifer@cs.stonybrook.edu>
;; Created: February 2, 1994
@@ -909,7 +909,7 @@ MERGE-AUTOSTORE-DIR is the directory in which to store merged files."
(defun ediff-windows-wordwise (dumb-mode &optional wind-A wind-B startup-hooks)
"Compare WIND-A and WIND-B, which are selected by clicking, wordwise.
This compares the portions of text visible in each of the two windows.
-With prefix argument, DUMB-MODE, or on a non-windowing display, works as
+With prefix argument, DUMB-MODE, or on a non-graphical display, works as
follows:
If WIND-A is nil, use selected window.
If WIND-B is nil, use window next to WIND-A.
@@ -923,7 +923,7 @@ arguments after setting up the Ediff buffers."
(defun ediff-windows-linewise (dumb-mode &optional wind-A wind-B startup-hooks)
"Compare WIND-A and WIND-B, which are selected by clicking, linewise.
This compares the portions of text visible in each of the two windows.
-With prefix argument, DUMB-MODE, or on a non-windowing display, works as
+With prefix argument, DUMB-MODE, or on a non-graphical display, works as
follows:
If WIND-A is nil, use selected window.
If WIND-B is nil, use window next to WIND-A.
@@ -935,7 +935,7 @@ arguments after setting up the Ediff buffers."
;; Compare visible portions of text in WIND-A and WIND-B, which are
;; selected by clicking.
-;; With prefix argument, DUMB-MODE, or on a non-windowing display,
+;; With prefix argument, DUMB-MODE, or on a non-graphical display,
;; works as follows:
;; If WIND-A is nil, use selected window.
;; If WIND-B is nil, use window next to WIND-A.
diff --git a/lisp/vc/emerge.el b/lisp/vc/emerge.el
index e95742b304a..5328ebc73ad 100644
--- a/lisp/vc/emerge.el
+++ b/lisp/vc/emerge.el
@@ -877,8 +877,8 @@ This is *not* a user option, since Emerge uses it for its own processing.")
(defun emerge-buffers (buffer-A buffer-B &optional startup-hooks quit-hooks)
"Run Emerge on two buffers BUFFER-A and BUFFER-B."
(interactive "bBuffer A to merge: \nbBuffer B to merge: ")
- (let ((emerge-file-A (emerge-make-temp-file "A"))
- (emerge-file-B (emerge-make-temp-file "B")))
+ (let ((emerge-file-A (make-temp-file "emerge-A"))
+ (emerge-file-B (make-temp-file "emerge-B")))
(with-current-buffer
buffer-A
(write-region (point-min) (point-max) emerge-file-A nil 'no-message))
@@ -901,9 +901,9 @@ This is *not* a user option, since Emerge uses it for its own processing.")
"Run Emerge on two buffers, giving another buffer as the ancestor."
(interactive
"bBuffer A to merge: \nbBuffer B to merge: \nbAncestor buffer: ")
- (let ((emerge-file-A (emerge-make-temp-file "A"))
- (emerge-file-B (emerge-make-temp-file "B"))
- (emerge-file-ancestor (emerge-make-temp-file "anc")))
+ (let ((emerge-file-A (make-temp-file "emerge-A"))
+ (emerge-file-B (make-temp-file "emerge-B"))
+ (emerge-file-ancestor (make-temp-file "emerge-ancestor")))
(with-current-buffer
buffer-A
(write-region (point-min) (point-max) emerge-file-A nil 'no-message))
@@ -1039,8 +1039,8 @@ This is *not* a user option, since Emerge uses it for its own processing.")
startup-hooks quit-hooks _output-file)
(let ((buffer-A (get-buffer-create (format "%s,%s" file revision-A)))
(buffer-B (get-buffer-create (format "%s,%s" file revision-B)))
- (emerge-file-A (emerge-make-temp-file "A"))
- (emerge-file-B (emerge-make-temp-file "B")))
+ (emerge-file-A (make-temp-file "emerge-A"))
+ (emerge-file-B (make-temp-file "emerge-B")))
;; Get the revisions into buffers
(with-current-buffer
buffer-A
@@ -1076,9 +1076,9 @@ This is *not* a user option, since Emerge uses it for its own processing.")
(let ((buffer-A (get-buffer-create (format "%s,%s" file revision-A)))
(buffer-B (get-buffer-create (format "%s,%s" file revision-B)))
(buffer-ancestor (get-buffer-create (format "%s,%s" file ancestor)))
- (emerge-file-A (emerge-make-temp-file "A"))
- (emerge-file-B (emerge-make-temp-file "B"))
- (emerge-ancestor (emerge-make-temp-file "ancestor")))
+ (emerge-file-A (make-temp-file "emerge-A"))
+ (emerge-file-B (make-temp-file "emerge-B"))
+ (emerge-ancestor (make-temp-file "emerge-ancestor")))
;; Get the revisions into buffers
(with-current-buffer
buffer-A
@@ -2851,14 +2851,6 @@ Otherwise, signal an error."
(setq vars (cdr vars))
(setq values (cdr values))))
-;; When the pointless option emerge-temp-file-prefix goes,
-;; make this function obsolete too, and just use make-temp-file.
-(defun emerge-make-temp-file (prefix)
- "Make a private temporary file based on PREFIX.
-This is named by concatenating `emerge-temp-file-prefix' with
-PREFIX."
- (make-temp-file (concat emerge-temp-file-prefix prefix)))
-
;;; Functions that query the user before he can write out the current buffer.
(defun emerge-query-write-file ()
@@ -3062,6 +3054,8 @@ See also `auto-save-file-name-p'."
:type '(choice (const nil) regexp))
(make-obsolete-variable 'emerge-metachars nil "26.1")
+(define-obsolete-function-alias 'emerge-make-temp-file #'make-temp-file "30.1")
+
(provide 'emerge)
;;; emerge.el ends here
diff --git a/lisp/vc/log-edit.el b/lisp/vc/log-edit.el
index 1e249c637a6..72867f14d2f 100644
--- a/lisp/vc/log-edit.el
+++ b/lisp/vc/log-edit.el
@@ -1,6 +1,6 @@
;;; log-edit.el --- Major mode for editing CVS commit messages -*- lexical-binding: t -*-
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
;; Keywords: pcl-cvs cvs commit log vc
@@ -61,12 +61,12 @@
"C-c C-d" #'log-edit-show-diff
"C-c C-f" #'log-edit-show-files
"C-c C-k" #'log-edit-kill-buffer
- "C-a" #'log-edit-beginning-of-line
"M-n" #'log-edit-next-comment
"M-p" #'log-edit-previous-comment
"M-r" #'log-edit-comment-search-backward
"M-s" #'log-edit-comment-search-forward
- "C-c ?" #'log-edit-mode-help)
+ "C-c ?" #'log-edit-mode-help
+ "<remap> <move-beginning-of-line>" #'log-edit-beginning-of-line)
(easy-menu-define log-edit-menu log-edit-mode-map
"Menu used for `log-edit-mode'."
@@ -76,6 +76,8 @@
"--"
["Insert ChangeLog" log-edit-insert-changelog
:help "Insert a log message by looking at the ChangeLog"]
+ ["Generate ChangeLog" log-edit-generate-changelog-from-diff
+ :help "Generate a log message from the diff and insert it into this buffer"]
["Add to ChangeLog" log-edit-add-to-changelog
:help "Insert this log message into the appropriate ChangeLog file"]
"--"
@@ -93,6 +95,60 @@
["Search comment backward" log-edit-comment-search-backward
:help "Search backwards through comment history for substring match of str"]))
+(defvar log-edit-tool-bar-map
+ (let ((map (make-sparse-keymap)))
+ (tool-bar-local-item-from-menu 'find-file "new" map
+ nil :label "New File"
+ :vert-only t)
+ (tool-bar-local-item-from-menu 'menu-find-file-existing "open" map
+ nil :label "Open" :vert-only t)
+ (tool-bar-local-item-from-menu 'dired "diropen" map nil :vert-only t)
+ (tool-bar-local-item-from-menu 'kill-this-buffer "close" map nil
+ :vert-only t)
+ (define-key-after map [separator-1] menu-bar-separator)
+ (tool-bar-local-item-from-menu 'log-edit-done "commit"
+ map log-edit-mode-map :vert-only t
+ :help
+ "Exit log buffer and commit the changes")
+ (define-key-after map [separator-2] menu-bar-separator)
+ (tool-bar-local-item-from-menu 'log-edit-insert-changelog
+ "load-changelog"
+ map log-edit-mode-map :vert-only t
+ :help
+ "Produce log message from ChangeLog file")
+ (tool-bar-local-item-from-menu 'log-edit-generate-changelog-from-diff
+ "gen-changelog"
+ map log-edit-mode-map :vert-only t
+ :help
+ "Generate log message skeleton from diffs")
+ (tool-bar-local-item-from-menu 'log-edit-add-to-changelog
+ "ins-changelog"
+ map log-edit-mode-map :vert-only t
+ :help
+ "Insert this log message into ChangeLog file")
+ (define-key-after map [separator-3] menu-bar-separator)
+ (tool-bar-local-item-from-menu 'log-edit-show-diff
+ "view-diff"
+ map log-edit-mode-map :vert-only t
+ :help
+ "View diffs for the files to be committed")
+ (tool-bar-local-item-from-menu 'log-edit-show-files
+ "info"
+ map log-edit-mode-map :vert-only t
+ :help
+ "View list of files to be committed")
+ (define-key-after map [separator-4] menu-bar-separator)
+ (tool-bar-local-item-from-menu 'undo "undo" map nil)
+ (define-key-after map [separator-5] menu-bar-separator)
+ (tool-bar-local-item-from-menu (lookup-key menu-bar-edit-menu [cut])
+ "cut" map nil)
+ (tool-bar-local-item-from-menu (lookup-key menu-bar-edit-menu [copy])
+ "copy" map nil)
+ (tool-bar-local-item-from-menu (lookup-key menu-bar-edit-menu [paste])
+ "paste" map nil)
+ map)
+ "Like the default `tool-bar-map', but with additions for Log-Edit mode.")
+
(defcustom log-edit-confirm 'changed
"If non-nil, `log-edit-done' will request confirmation.
If `changed', only request confirmation if the list of files has
@@ -511,7 +567,9 @@ the \\[vc-prefix-map] prefix for VC commands, for example).
(setq-local fill-paragraph-function #'log-edit-fill-entry)
(make-local-variable 'log-edit-comment-ring-index)
(add-hook 'kill-buffer-hook 'log-edit-remember-comment nil t)
- (hack-dir-local-variables-non-file-buffer))
+ (hack-dir-local-variables-non-file-buffer)
+ ;; Replace the tool bar map with `log-edit-tool-bar-map'.
+ (setq-local tool-bar-map log-edit-tool-bar-map))
(defun log-edit--insert-filled-defuns (func-names)
"Insert FUNC-NAMES, following ChangeLog formatting."
@@ -1219,7 +1277,10 @@ line of MSG."
(let ((pt (point)))
(and (zerop (forward-line 1))
(looking-at "\n\\|\\'")
- (let ((summary (buffer-substring-no-properties pt (1- (point)))))
+ (let ((summary (buffer-substring-no-properties pt
+ (if (bolp)
+ (1- (point))
+ (point)))))
(skip-chars-forward " \n")
(delete-region pt (point))
(log-edit-set-header "Summary" summary)))))))
diff --git a/lisp/vc/log-view.el b/lisp/vc/log-view.el
index e6eb6a5b973..e9e6602e414 100644
--- a/lisp/vc/log-view.el
+++ b/lisp/vc/log-view.el
@@ -1,6 +1,6 @@
;;; log-view.el --- Major mode for browsing revision log histories -*- lexical-binding: t -*-
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
;; Keywords: tools, vc
@@ -163,14 +163,14 @@
:help "Go to the previous count'th log message"]
["Next File" log-view-file-next
:help "Go to the next count'th file"
- :active (derived-mode-p vc-cvs-log-view-mode
- vc-rcs-log-view-mode
- vc-sccs-log-view-mode)]
+ :active (derived-mode-p 'vc-cvs-log-view-mode
+ 'vc-rcs-log-view-mode
+ 'vc-sccs-log-view-mode)]
["Previous File" log-view-file-prev
:help "Go to the previous count'th file"
- :active (derived-mode-p vc-cvs-log-view-mode
- vc-rcs-log-view-mode
- vc-sccs-log-view-mode)]))
+ :active (derived-mode-p 'vc-cvs-log-view-mode
+ 'vc-rcs-log-view-mode
+ 'vc-sccs-log-view-mode)]))
(defvar log-view-mode-hook nil
"Hook run at the end of `log-view-mode'.")
@@ -516,7 +516,8 @@ If called interactively, visit the version at point."
(switch-to-buffer (vc-find-revision (if log-view-per-file-logs
(log-view-current-file)
(car log-view-vc-fileset))
- (log-view-current-tag)))))
+ (log-view-current-tag)
+ log-view-vc-backend))))
(defun log-view-extract-comment ()
@@ -562,7 +563,8 @@ If called interactively, annotate the version at point."
(vc-annotate (if log-view-per-file-logs
(log-view-current-file)
(car log-view-vc-fileset))
- (log-view-current-tag))))
+ (log-view-current-tag)
+ nil nil nil log-view-vc-backend)))
;;
;; diff
diff --git a/lisp/vc/pcvs-defs.el b/lisp/vc/pcvs-defs.el
index 3bbf2355b81..05f07c6e999 100644
--- a/lisp/vc/pcvs-defs.el
+++ b/lisp/vc/pcvs-defs.el
@@ -1,6 +1,6 @@
;;; pcvs-defs.el --- variable definitions for PCL-CVS -*- lexical-binding: t; -*-
-;; Copyright (C) 1991-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1991-2024 Free Software Foundation, Inc.
;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
;; Keywords: pcl-cvs
diff --git a/lisp/vc/pcvs-info.el b/lisp/vc/pcvs-info.el
index 86655ef6fde..ad3dc265874 100644
--- a/lisp/vc/pcvs-info.el
+++ b/lisp/vc/pcvs-info.el
@@ -1,6 +1,6 @@
;;; pcvs-info.el --- internal representation of a fileinfo entry -*- lexical-binding: t; -*-
-;; Copyright (C) 1991-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1991-2024 Free Software Foundation, Inc.
;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
;; Keywords: pcl-cvs
diff --git a/lisp/vc/pcvs-parse.el b/lisp/vc/pcvs-parse.el
index df10efab41e..1c46324d7ce 100644
--- a/lisp/vc/pcvs-parse.el
+++ b/lisp/vc/pcvs-parse.el
@@ -1,6 +1,6 @@
;;; pcvs-parse.el --- the CVS output parser -*- lexical-binding: t; -*-
-;; Copyright (C) 1991-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1991-2024 Free Software Foundation, Inc.
;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
;; Keywords: pcl-cvs
diff --git a/lisp/vc/pcvs-util.el b/lisp/vc/pcvs-util.el
index 5ff94405d11..10daa07d668 100644
--- a/lisp/vc/pcvs-util.el
+++ b/lisp/vc/pcvs-util.el
@@ -1,6 +1,6 @@
;;; pcvs-util.el --- utility functions for PCL-CVS -*- lexical-binding: t; -*-
-;; Copyright (C) 1991-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1991-2024 Free Software Foundation, Inc.
;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
;; Keywords: pcl-cvs
diff --git a/lisp/vc/pcvs.el b/lisp/vc/pcvs.el
index c90b9f6bdf1..cf7982f4ffa 100644
--- a/lisp/vc/pcvs.el
+++ b/lisp/vc/pcvs.el
@@ -1,6 +1,6 @@
;;; pcvs.el --- a front-end to CVS -*- lexical-binding:t -*-
-;; Copyright (C) 1991-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1991-2024 Free Software Foundation, Inc.
;; Author: The PCL-CVS Trust <pcl-cvs@cyclic.com>
;; Per Cederqvist <ceder@lysator.liu.se>
diff --git a/lisp/vc/smerge-mode.el b/lisp/vc/smerge-mode.el
index c39a9cc2f22..a16c7871ff9 100644
--- a/lisp/vc/smerge-mode.el
+++ b/lisp/vc/smerge-mode.el
@@ -1,6 +1,6 @@
;;; smerge-mode.el --- Minor mode to resolve diff3 conflicts -*- lexical-binding: t -*-
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
;; Keywords: vc, tools, revision control, merge, diff3, cvs, conflict
@@ -255,10 +255,6 @@ Can be nil if the style is undecided, or else:
- `diff3-E'
- `diff3-A'")
-;; Compiler pacifiers
-(defvar font-lock-mode)
-(defvar font-lock-keywords)
-
;;;;
;;;; Actual code
;;;;
@@ -1243,7 +1239,11 @@ spacing of the \"Lower\" chunk."
(write-region beg1 end1 file1 nil 'nomessage)
(write-region beg2 end2 file2 nil 'nomessage)
(unwind-protect
- (with-current-buffer (get-buffer-create smerge-diff-buffer-name)
+ (save-current-buffer
+ (if-let (buffer (get-buffer smerge-diff-buffer-name))
+ (set-buffer buffer)
+ (set-buffer (get-buffer-create smerge-diff-buffer-name))
+ (setq buffer-read-only t))
(setq default-directory dir)
(let ((inhibit-read-only t))
(erase-buffer)
diff --git a/lisp/vc/vc-annotate.el b/lisp/vc/vc-annotate.el
index d83660f9d79..b206abec27f 100644
--- a/lisp/vc/vc-annotate.el
+++ b/lisp/vc/vc-annotate.el
@@ -1,6 +1,6 @@
;;; vc-annotate.el --- VC Annotate Support -*- lexical-binding: t -*-
-;; Copyright (C) 1997-1998, 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997-1998, 2000-2024 Free Software Foundation, Inc.
;; Author: Martin Lorentzson <emwson@emw.ericsson.se>
;; Maintainer: emacs-devel@gnu.org
@@ -162,6 +162,11 @@ List of factors, used to expand/compress the time scale. See `vc-annotate'."
:type '(repeat number)
:group 'vc)
+(defcustom vc-annotate-use-short-revision t
+ "If non-nil, \\[vc-annotate] will use short revisions in its buffer name."
+ :type 'boolean
+ :group 'vc)
+
(defvar-keymap vc-annotate-mode-map
:doc "Local keymap used for VC-Annotate mode."
"a" #'vc-annotate-revision-previous-to-line
@@ -397,7 +402,10 @@ should be applied to the background or to the foreground."
(save-current-buffer
(vc-ensure-vc-buffer)
(list buffer-file-name
- (let ((def (vc-working-revision buffer-file-name)))
+ (let ((def (funcall (if vc-annotate-use-short-revision
+ #'vc-short-revision
+ #'vc-working-revision)
+ buffer-file-name)))
(if (null current-prefix-arg) def
(vc-read-revision
(format-prompt "Annotate from revision" def)
@@ -718,23 +726,24 @@ The annotations are relative to the current time, unless overridden by OFFSET."
(let* ((color (or (vc-annotate-compcar difference vc-annotate-color-map)
(cons nil vc-annotate-very-old-color)))
;; substring from index 1 to remove any leading `#' in the name
- (face-name (concat "vc-annotate-face-"
- (if (string-equal
- (substring (cdr color) 0 1) "#")
- (substring (cdr color) 1)
- (cdr color))))
+ (face (intern (concat "vc-annotate-face-"
+ (if (string-equal
+ (substring (cdr color) 0 1) "#")
+ (substring (cdr color) 1)
+ (cdr color)))))
;; Make the face if not done.
- (face (or (intern-soft face-name)
- (let ((tmp-face (make-face (intern face-name))))
- (set-face-extend tmp-face t)
- (cond
- (vc-annotate-background-mode
- (set-face-background tmp-face (cdr color)))
- (t
- (set-face-foreground tmp-face (cdr color))
- (when vc-annotate-background
- (set-face-background tmp-face vc-annotate-background))))
- tmp-face)))) ; Return the face
+ (face (if (facep face)
+ face
+ (make-face face)
+ (set-face-extend face t)
+ (cond
+ (vc-annotate-background-mode
+ (set-face-background face (cdr color)))
+ (t
+ (set-face-foreground face (cdr color))
+ (when vc-annotate-background
+ (set-face-background face vc-annotate-background))))
+ face)))
(put-text-property start end 'face face)))))
;; Pretend to font-lock there were no matches.
nil)
diff --git a/lisp/vc/vc-bzr.el b/lisp/vc/vc-bzr.el
index f66e37fffa4..a357dc4827f 100644
--- a/lisp/vc/vc-bzr.el
+++ b/lisp/vc/vc-bzr.el
@@ -1,6 +1,6 @@
;;; vc-bzr.el --- VC backend for the bzr revision control system -*- lexical-binding: t -*-
-;; Copyright (C) 2006-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2006-2024 Free Software Foundation, Inc.
;; Author: Dave Love <fx@gnu.org>
;; Riccardo Murri <riccardo.murri@gmail.com>
diff --git a/lisp/vc/vc-cvs.el b/lisp/vc/vc-cvs.el
index 145697d1b06..52039f8da74 100644
--- a/lisp/vc/vc-cvs.el
+++ b/lisp/vc/vc-cvs.el
@@ -1,6 +1,6 @@
;;; vc-cvs.el --- non-resident support for CVS version-control -*- lexical-binding: t -*-
-;; Copyright (C) 1995, 1998-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1995, 1998-2024 Free Software Foundation, Inc.
;; Author: FSF (see vc.el for full credits)
;; Package: vc
diff --git a/lisp/vc/vc-dav.el b/lisp/vc/vc-dav.el
index a0e3866cca2..ae2cf149771 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-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2001, 2004-2024 Free Software Foundation, Inc.
;; Author: Bill Perry <wmperry@gnu.org>
;; Keywords: url, vc
diff --git a/lisp/vc/vc-dir.el b/lisp/vc/vc-dir.el
index 53d58870b32..d733b36f8ff 100644
--- a/lisp/vc/vc-dir.el
+++ b/lisp/vc/vc-dir.el
@@ -1,6 +1,6 @@
;;; vc-dir.el --- Directory status display under VC -*- lexical-binding: t -*-
-;; Copyright (C) 2007-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2024 Free Software Foundation, Inc.
;; Author: Dan Nicolaescu <dann@ics.uci.edu>
;; Keywords: vc tools
@@ -785,8 +785,7 @@ MARK-FILES should be a list of absolute filenames."
(defun vc-dir-mark-state-files (states)
"Mark files that are in the state specified by the list in STATES."
- (unless (listp states)
- (setq states (list states)))
+ (setq states (ensure-list states))
(ewoc-map
(lambda (filearg)
(when (memq (vc-dir-fileinfo->state filearg) states)
diff --git a/lisp/vc/vc-dispatcher.el b/lisp/vc/vc-dispatcher.el
index fd5f655a0f6..998cef649ff 100644
--- a/lisp/vc/vc-dispatcher.el
+++ b/lisp/vc/vc-dispatcher.el
@@ -1,6 +1,6 @@
;;; vc-dispatcher.el --- generic command-dispatcher facility. -*- lexical-binding: t -*-
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
;; Author: FSF (see below for full credits)
;; Keywords: vc tools
diff --git a/lisp/vc/vc-filewise.el b/lisp/vc/vc-filewise.el
index 99df438e294..a87592ba0fd 100644
--- a/lisp/vc/vc-filewise.el
+++ b/lisp/vc/vc-filewise.el
@@ -1,6 +1,6 @@
;;; vc-filewise.el --- common functions for file-oriented back ends. -*- lexical-binding: t; -*-
-;; Copyright (C) 1992-1996, 1998-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1992-1996, 1998-2024 Free Software Foundation, Inc.
;; Author: FSF (see vc.el for full credits)
;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/vc/vc-git.el b/lisp/vc/vc-git.el
index a7763360795..fed15ae2033 100644
--- a/lisp/vc/vc-git.el
+++ b/lisp/vc/vc-git.el
@@ -1,6 +1,6 @@
;;; vc-git.el --- VC backend for the git version control system -*- lexical-binding: t -*-
-;; Copyright (C) 2006-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2006-2024 Free Software Foundation, Inc.
;; Author: Alexandre Julliard <julliard@winehq.org>
;; Keywords: vc tools
@@ -89,6 +89,7 @@
;; - make-version-backups-p (file) NOT NEEDED
;; - previous-revision (file rev) OK
;; - next-revision (file rev) OK
+;; - file-name-changes (rev) OK
;; - check-headers () COULD BE SUPPORTED
;; - delete-file (file) OK
;; - rename-file (old new) OK
@@ -122,7 +123,10 @@ If nil, use the value of `vc-diff-switches'. If t, use no switches."
(defcustom vc-git-annotate-switches nil
"String or list of strings specifying switches for Git blame under VC.
-If nil, use the value of `vc-annotate-switches'. If t, use no switches."
+If nil, use the value of `vc-annotate-switches'. If t, use no switches.
+
+Tip: Set this to \"-w\" to make Git blame ignore whitespace when
+comparing changes. See Man page `git-blame' for more."
:type '(choice (const :tag "Unspecified" nil)
(const :tag "None" t)
(string :tag "Argument String")
@@ -149,6 +153,18 @@ If nil, use the value of `vc-annotate-switches'. If t, use no switches."
(repeat :tag "Argument List" :value ("") string))
:version "30.1")
+(defcustom vc-git-file-name-changes-switches '("-M" "-C")
+ "String or list of string to pass to Git when finding previous names.
+
+This option should usually at least contain '-M'. You can adjust
+the flags to change the similarity thresholds (default 50%). Or
+add `--find-copies-harder' (slower in large projects, since it
+uses a full scan)."
+ :type '(choice (const :tag "None" nil)
+ (string :tag "Argument String")
+ (repeat :tag "Argument List" :value ("") string))
+ :version "30.1")
+
(defcustom vc-git-resolve-conflicts t
"When non-nil, mark conflicted file as resolved upon saving.
That is performed after all conflict markers in it have been
@@ -413,15 +429,20 @@ in the order given by `git status'."
(defun vc-git-mode-line-string (file)
"Return a string for `vc-mode-line' to put in the mode line for FILE."
- (let* ((rev (vc-working-revision file 'Git))
- (disp-rev (or (vc-git--symbolic-ref file)
- (and rev (substring rev 0 7))))
- (def-ml (vc-default-mode-line-string 'Git file))
- (help-echo (get-text-property 0 'help-echo def-ml))
- (face (get-text-property 0 'face def-ml)))
- (propertize (concat (substring def-ml 0 4) disp-rev)
- 'face face
- 'help-echo (concat help-echo "\nCurrent revision: " rev))))
+ (pcase-let* ((backend-name "Git")
+ (state (vc-state file))
+ (`(,state-echo ,face ,indicator)
+ (vc-mode-line-state state))
+ (rev (vc-working-revision file 'Git))
+ (disp-rev (or (vc-git--symbolic-ref file)
+ (and rev (substring rev 0 7))))
+ (state-string (concat (unless (eq vc-display-status 'no-backend)
+ backend-name)
+ indicator disp-rev)))
+ (propertize state-string 'face face 'help-echo
+ (concat state-echo " under the " backend-name
+ " version control system"
+ "\nCurrent revision: " rev))))
(cl-defstruct (vc-git-extra-fileinfo
(:copier nil)
@@ -1058,7 +1079,8 @@ It is based on `log-edit-mode', and has Git-specific extensions."
;; might not support the non-ASCII characters in the log
;; message. Handle also remote files.
(if (eq system-type 'windows-nt)
- (let ((default-directory (file-name-directory file1)))
+ (let ((default-directory (or (file-name-directory file1)
+ default-directory)))
(make-nearby-temp-file "git-msg"))))
to-stash)
(when vc-git-patch-string
@@ -1120,7 +1142,15 @@ It is based on `log-edit-mode', and has Git-specific extensions."
(t (push file-name to-stash)))
(setq pos (point))))))
(unless (string-empty-p vc-git-patch-string)
- (let ((patch-file (make-nearby-temp-file "git-patch")))
+ (let ((patch-file (make-nearby-temp-file "git-patch"))
+ ;; Temporarily countermand the let-binding at the
+ ;; beginning of this function.
+ (coding-system-for-write
+ (coding-system-change-eol-conversion
+ ;; On DOS/Windows, it is important for the patch file
+ ;; to have the Unix EOL format, because Git expects
+ ;; that, even on Windows.
+ (or pcsw vc-git-commits-coding-system) 'unix)))
(with-temp-file patch-file
(insert vc-git-patch-string))
(unwind-protect
@@ -1399,7 +1429,16 @@ This prompts for a branch to merge from."
;; Long explanation here:
;; https://stackoverflow.com/questions/46487476/git-log-follow-graph-skips-commits
(defcustom vc-git-print-log-follow nil
- "If true, follow renames in Git logs for a single file."
+ "If non-nil, use the flag `--follow' when producing single file logs.
+
+A non-nil value will make the printed log automatically follow
+the file renames. The downsides is that the log produced this
+way may omit certain (merge) commits, and that `log-view-diff'
+fails on commits that used the previous name, in that log buffer.
+
+When this variable is nil, and the log ends with a rename, we
+show a button below that which allows to show the log for the
+file name before the rename."
:type 'boolean
:version "26.1")
@@ -1631,7 +1670,6 @@ This requires git 1.8.4 or later, for the \"-L\" option of \"git log\"."
map))
(defvar vc-git--log-view-long-font-lock-keywords nil)
-(defvar font-lock-keywords)
(defvar vc-git-region-history-font-lock-keywords
'((vc-git-region-history-font-lock)))
@@ -1709,7 +1747,7 @@ This requires git 1.8.4 or later, for the \"-L\" option of \"git log\"."
"^refs/\\(heads\\|tags\\|remotes\\)/\\(.*\\)$")))
(while (re-search-forward regexp nil t)
(push (match-string 2) table))))
- table))
+ (nreverse table)))
(defun vc-git-revision-completion-table (files)
(letrec ((table (lazy-completion-table
@@ -1819,8 +1857,11 @@ This requires git 1.8.4 or later, for the \"-L\" option of \"git log\"."
(defun vc-git--rev-parse (rev)
(with-temp-buffer
(and
- (vc-git--out-ok "rev-parse" rev)
- (buffer-substring-no-properties (point-min) (+ (point-min) 40)))))
+ (apply #'vc-git--out-ok "rev-parse"
+ (append (when vc-use-short-revision '("--short"))
+ (list rev)))
+ (goto-char (point-min))
+ (buffer-substring-no-properties (point) (pos-eol)))))
(defun vc-git-next-revision (file rev)
"Git-specific version of `vc-next-revision'."
@@ -1850,6 +1891,31 @@ This requires git 1.8.4 or later, for the \"-L\" option of \"git log\"."
(progn (forward-line 1) (1- (point)))))))))
(or (vc-git-symbolic-commit next-rev) next-rev)))
+(defun vc-git-file-name-changes (rev)
+ (with-temp-buffer
+ (let ((root (vc-git-root default-directory)))
+ (unless vc-git-print-log-follow
+ (apply #'vc-git-command (current-buffer) t nil
+ "diff"
+ "--name-status"
+ "--diff-filter=ADCR"
+ (concat rev "^") rev
+ (vc-switches 'git 'file-name-changes)))
+ (let (res)
+ (goto-char (point-min))
+ (while (re-search-forward "^\\([ADCR]\\)[0-9]*\t\\([^\n\t]+\\)\\(?:\t\\([^\n\t]+\\)\\)?" nil t)
+ (pcase (match-string 1)
+ ("A" (push (cons nil (match-string 2)) res))
+ ("D" (push (cons (match-string 2) nil) res))
+ ((or "C" "R") (push (cons (match-string 2) (match-string 3)) res))
+ ;; ("M" (push (cons (match-string 1) (match-string 1)) res))
+ ))
+ (mapc (lambda (c)
+ (if (car c) (setcar c (expand-file-name (car c) root)))
+ (if (cdr c) (setcdr c (expand-file-name (cdr c) root))))
+ res)
+ (nreverse res)))))
+
(defun vc-git-delete-file (file)
(vc-git-command nil 0 file "rm" "-f" "--"))
diff --git a/lisp/vc/vc-hg.el b/lisp/vc/vc-hg.el
index 182d76882bb..7de41a2ae50 100644
--- a/lisp/vc/vc-hg.el
+++ b/lisp/vc/vc-hg.el
@@ -1,6 +1,6 @@
;;; vc-hg.el --- VC backend for the mercurial version control system -*- lexical-binding: t -*-
-;; Copyright (C) 2006-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2006-2024 Free Software Foundation, Inc.
;; Author: Ivan Kanis
;; Maintainer: emacs-devel@gnu.org
@@ -77,6 +77,7 @@
;; - make-version-backups-p (file) ??
;; - previous-revision (file rev) OK
;; - next-revision (file rev) OK
+;; - file-name-changes (rev) OK
;; - check-headers () ??
;; - delete-file (file) TEST IT
;; - rename-file (old new) OK
@@ -216,8 +217,9 @@ If `ask', you will be prompted for a branch type."
(defun vc-hg-state (file)
"Hg-specific version of `vc-state'."
- (let ((state (vc-hg-state-fast file)))
- (if (eq state 'unsupported) (vc-hg-state-slow file) state)))
+ (unless (file-directory-p file)
+ (let ((state (vc-hg-state-fast file)))
+ (if (eq state 'unsupported) (vc-hg-state-slow file) state))))
(defun vc-hg-state-slow (file)
"Determine status of FILE by running hg."
@@ -249,7 +251,10 @@ If `ask', you will be prompted for a branch type."
(error nil)))))))
(when (and (eq 0 status)
(> (length out) 0)
- (null (string-match ".*: No such file or directory$" out)))
+ ;; Posix
+ (null (or (string-match ".*: No such file or directory$" out)
+ ;; MS-Windows
+ (string-match ".*: The system cannot find the file specified$" out))))
(let ((state (aref out 0)))
(cond
((eq state ?=) 'up-to-date)
@@ -348,47 +353,24 @@ specific file to query."
(defun vc-hg-mode-line-string (file)
"Hg-specific version of `vc-mode-line-string'."
- (let* ((backend-name "Hg")
- (truename (file-truename file))
- (state (vc-state truename))
- (state-echo nil)
- (face nil)
- (rev (and state
- (let ((default-directory
- (expand-file-name (vc-hg-root truename))))
- (vc-hg--symbolic-revision
- "."
- (and vc-hg-use-file-version-for-mode-line-version
- truename)))))
- (rev (or rev "???")))
- (propertize
- (cond ((or (eq state 'up-to-date)
- (eq state 'needs-update))
- (setq state-echo "Up to date file")
- (setq face 'vc-up-to-date-state)
- (concat backend-name "-" rev))
- ((eq state 'added)
- (setq state-echo "Locally added file")
- (setq face 'vc-locally-added-state)
- (concat backend-name "@" rev))
- ((eq state 'conflict)
- (setq state-echo "File contains conflicts after the last merge")
- (setq face 'vc-conflict-state)
- (concat backend-name "!" rev))
- ((eq state 'removed)
- (setq state-echo "File removed from the VC system")
- (setq face 'vc-removed-state)
- (concat backend-name "!" rev))
- ((eq state 'missing)
- (setq state-echo "File tracked by the VC system, but missing from the file system")
- (setq face 'vc-missing-state)
- (concat backend-name "?" rev))
- (t
- (setq state-echo "Locally modified file")
- (setq face 'vc-edited-state)
- (concat backend-name ":" rev)))
- 'face face
- 'help-echo (concat state-echo " under the " backend-name
+ (pcase-let* ((backend-name "Hg")
+ (truename (file-truename file))
+ (state (vc-state truename))
+ (`(,state-echo ,face ,indicator)
+ (vc-mode-line-state state))
+ (rev (and state
+ (let ((default-directory
+ (expand-file-name (vc-hg-root truename))))
+ (vc-hg--symbolic-revision
+ "."
+ (and vc-hg-use-file-version-for-mode-line-version
+ truename)))))
+ (rev (or rev "???"))
+ (state-string (concat (unless (eq vc-display-status 'no-backend)
+ backend-name)
+ indicator rev)))
+ (propertize state-string 'face face 'help-echo
+ (concat state-echo " under the " backend-name
" version control system"))))
;;; History functions
@@ -497,7 +479,6 @@ This requires hg 4.4 or later, for the \"-L\" option of \"hg log\"."
map))
(defvar vc-hg--log-view-long-font-lock-keywords nil)
-(defvar font-lock-keywords)
(defvar vc-hg-region-history-font-lock-keywords
'((vc-hg-region-history-font-lock)))
@@ -603,8 +584,8 @@ Optional arg REVISION is a revision to annotate from."
(vc-annotate-convert-time
(let ((str (match-string-no-properties 2)))
(encode-time 0 0 0
- (string-to-number (substring str 6 8))
- (string-to-number (substring str 4 6))
+ (string-to-number (substring str 8 10))
+ (string-to-number (substring str 5 7))
(string-to-number (substring str 0 4)))))))
(defun vc-hg-annotate-extract-revision-at-line ()
@@ -1223,6 +1204,22 @@ REV is ignored."
(vc-hg-command buffer 0 file "cat" "-r" rev)
(vc-hg-command buffer 0 file "cat"))))
+(defun vc-hg-file-name-changes (rev)
+ (unless (member "--follow" vc-hg-log-switches)
+ (with-temp-buffer
+ (let ((root (vc-hg-root default-directory)))
+ (vc-hg-command (current-buffer) t nil
+ "log" "-g" "-p" "-r" rev)
+ (let (res)
+ (goto-char (point-min))
+ (while (re-search-forward "^diff --git a/\\([^ \n]+\\) b/\\([^ \n]+\\)" nil t)
+ (when (not (equal (match-string 1) (match-string 2)))
+ (push (cons
+ (expand-file-name (match-string 1) root)
+ (expand-file-name (match-string 2) root))
+ res)))
+ (nreverse res))))))
+
(defun vc-hg-find-ignore-file (file)
"Return the root directory of the repository of FILE."
(expand-file-name ".hgignore"
diff --git a/lisp/vc/vc-hooks.el b/lisp/vc/vc-hooks.el
index e75165ea2e9..1ef1388e21f 100644
--- a/lisp/vc/vc-hooks.el
+++ b/lisp/vc/vc-hooks.el
@@ -1,6 +1,6 @@
;;; vc-hooks.el --- resident support for version-control -*- lexical-binding:t -*-
-;; Copyright (C) 1992-1996, 1998-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1992-1996, 1998-2024 Free Software Foundation, Inc.
;; Author: FSF (see vc.el for full credits)
;; Maintainer: emacs-devel@gnu.org
@@ -87,6 +87,11 @@
"Face for VC modeline state when the file is edited."
:version "25.1")
+(defface vc-ignored-state
+ '((default :inherit vc-state-base))
+ "Face for VC modeline state when the file is registered, but ignored."
+ :version "30.1")
+
;; Customization Variables (the rest is in vc.el)
(defcustom vc-ignore-dir-regexp
@@ -147,8 +152,12 @@ visited and a warning displayed."
(defcustom vc-display-status t
"If non-nil, display revision number and lock status in mode line.
-Otherwise, not displayed."
- :type 'boolean
+If nil, only the backend name is displayed. When the value
+is `no-backend', then no backend name is displayed before the
+revision number and lock status."
+ :type '(choice (const :tag "Show only revision/status" no-backend)
+ (const :tag "Show backend and revision/status" t)
+ (const :tag "Show only backend name" nil))
:group 'vc)
@@ -497,6 +506,18 @@ If FILE is not registered, this function always returns nil."
(vc-call-backend
backend 'working-revision file))))))
+(defvar vc-use-short-revision nil
+ "If non-nil, VC backend functions should return short revisions if possible.
+This is set to t when calling `vc-short-revision', which will
+then call the \\=`working-revision' backend function.")
+
+(defun vc-short-revision (file &optional backend)
+ "Return the repository version for FILE in a shortened form.
+If FILE is not registered, this function always returns nil."
+ (let ((vc-use-short-revision t))
+ (vc-call-backend (or backend (vc-backend file))
+ 'working-revision file)))
+
(defun vc-default-registered (backend file)
"Check if FILE is registered in BACKEND using vc-BACKEND-master-templates."
(let ((sym (vc-make-backend-sym backend 'master-templates)))
@@ -700,6 +721,50 @@ If BACKEND is passed use it as the VC backend when computing the result."
(force-mode-line-update)
backend)
+(defun vc-mode-line-state (state)
+ "Return a list of data to display on the mode line.
+The argument STATE should contain the version control state returned
+from `vc-state'. The returned list includes three elements: the echo
+string, the face name, and the indicator that usually is one character."
+ (let (state-echo face indicator)
+ (cond ((or (eq state 'up-to-date)
+ (eq state 'needs-update))
+ (setq state-echo "Up to date file")
+ (setq face 'vc-up-to-date-state)
+ (setq indicator "-"))
+ ((stringp state)
+ (setq state-echo (concat "File locked by" state))
+ (setq face 'vc-locked-state)
+ (setq indicator (concat ":" state ":")))
+ ((eq state 'added)
+ (setq state-echo "Locally added file")
+ (setq face 'vc-locally-added-state)
+ (setq indicator "@"))
+ ((eq state 'conflict)
+ (setq state-echo "File contains conflicts after the last merge")
+ (setq face 'vc-conflict-state)
+ (setq indicator "!"))
+ ((eq state 'removed)
+ (setq state-echo "File removed from the VC system")
+ (setq face 'vc-removed-state)
+ (setq indicator "!"))
+ ((eq state 'missing)
+ (setq state-echo "File tracked by the VC system, but missing from the file system")
+ (setq face 'vc-missing-state)
+ (setq indicator "?"))
+ ((eq state 'ignored)
+ (setq state-echo "File tracked by the VC system, but ignored")
+ (setq face 'vc-ignored-state)
+ (setq indicator "!"))
+ (t
+ ;; Not just for the 'edited state, but also a fallback
+ ;; for all other states. Think about different symbols
+ ;; for 'needs-update and 'needs-merge.
+ (setq state-echo "Locally modified file")
+ (setq face 'vc-edited-state)
+ (setq indicator ":")))
+ (list state-echo face indicator)))
+
(defun vc-default-mode-line-string (backend file)
"Return a string for `vc-mode-line' to put in the mode line for FILE.
Format:
@@ -712,47 +777,17 @@ Format:
\"BACKEND?REV\" if the file is under VC, but is missing
This function assumes that the file is registered."
- (let* ((backend-name (symbol-name backend))
- (state (vc-state file backend))
- (state-echo nil)
- (face nil)
- (rev (vc-working-revision file backend)))
- (propertize
- (cond ((or (eq state 'up-to-date)
- (eq state 'needs-update))
- (setq state-echo "Up to date file")
- (setq face 'vc-up-to-date-state)
- (concat backend-name "-" rev))
- ((stringp state)
- (setq state-echo (concat "File locked by" state))
- (setq face 'vc-locked-state)
- (concat backend-name ":" state ":" rev))
- ((eq state 'added)
- (setq state-echo "Locally added file")
- (setq face 'vc-locally-added-state)
- (concat backend-name "@" rev))
- ((eq state 'conflict)
- (setq state-echo "File contains conflicts after the last merge")
- (setq face 'vc-conflict-state)
- (concat backend-name "!" rev))
- ((eq state 'removed)
- (setq state-echo "File removed from the VC system")
- (setq face 'vc-removed-state)
- (concat backend-name "!" rev))
- ((eq state 'missing)
- (setq state-echo "File tracked by the VC system, but missing from the file system")
- (setq face 'vc-missing-state)
- (concat backend-name "?" rev))
- (t
- ;; Not just for the 'edited state, but also a fallback
- ;; for all other states. Think about different symbols
- ;; for 'needs-update and 'needs-merge.
- (setq state-echo "Locally modified file")
- (setq face 'vc-edited-state)
- (concat backend-name ":" rev)))
- 'face face
- 'help-echo (concat state-echo " under the " backend-name
- " version control system"))))
+ (pcase-let* ((backend-name (symbol-name backend))
+ (state (vc-state file backend))
+ (rev (vc-working-revision file backend))
+ (`(,state-echo ,face ,indicator)
+ (vc-mode-line-state state))
+ (state-string (concat (unless (eq vc-display-status 'no-backend)
+ backend-name)
+ indicator rev)))
+ (propertize state-string 'face face 'help-echo
+ (concat state-echo " under the " backend-name
+ " version control system"))))
(defun vc-follow-link ()
"If current buffer visits a symbolic link, visit the real file.
diff --git a/lisp/vc/vc-rcs.el b/lisp/vc/vc-rcs.el
index c2112b76ad3..1a43b440d18 100644
--- a/lisp/vc/vc-rcs.el
+++ b/lisp/vc/vc-rcs.el
@@ -1,6 +1,6 @@
;;; vc-rcs.el --- support for RCS version-control -*- lexical-binding:t -*-
-;; Copyright (C) 1992-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1992-2024 Free Software Foundation, Inc.
;; Author: FSF (see vc.el for full credits)
;; Maintainer: emacs-devel@gnu.org
@@ -714,7 +714,7 @@ Optional arg REVISION is a revision to annotate from."
(insert insn)
(delete-char insn)))
;; Now apply the forward-chronological edits (directly from the
- ;; parse-tree) for the branch(es), if necessary. We re-use vars
+ ;; parse-tree) for the branch(es), if necessary. We reuse vars
;; `pre' and `meta' for the sake of internal func `r/d/a'.
(while nbls
(setq pre (cdr (pop nbls)))
@@ -864,14 +864,15 @@ and CVS."
(defvar vc-rcs-rcs2log-program
(let (exe)
(cond ((file-executable-p
- (setq exe (expand-file-name "rcs2log" exec-directory)))
+ (setq exe (expand-file-name rcs2log-program-name
+ exec-directory)))
exe)
;; In the unlikely event that someone is running an
;; uninstalled Emacs and wants to do something RCS-related.
((file-executable-p
(setq exe (expand-file-name "lib-src/rcs2log" source-directory)))
exe)
- (t "rcs2log")))
+ (t rcs2log-program-name)))
"Path to the `rcs2log' program (normally in `exec-directory').")
(autoload 'vc-buffer-sync "vc-dispatcher")
diff --git a/lisp/vc/vc-sccs.el b/lisp/vc/vc-sccs.el
index 03e9d12b76f..7e87849337a 100644
--- a/lisp/vc/vc-sccs.el
+++ b/lisp/vc/vc-sccs.el
@@ -1,6 +1,6 @@
;;; vc-sccs.el --- support for SCCS version-control -*- lexical-binding:t -*-
-;; Copyright (C) 1992-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1992-2024 Free Software Foundation, Inc.
;; Author: FSF (see vc.el for full credits)
;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/vc/vc-src.el b/lisp/vc/vc-src.el
index 69903e8e681..c85c90f7897 100644
--- a/lisp/vc/vc-src.el
+++ b/lisp/vc/vc-src.el
@@ -1,6 +1,6 @@
;;; vc-src.el --- support for SRC version-control -*- lexical-binding:t -*-
-;; Copyright (C) 1992-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1992-2024 Free Software Foundation, Inc.
;; Author: FSF (see vc.el for full credits)
;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/vc/vc-svn.el b/lisp/vc/vc-svn.el
index 6c93c8b3cab..96baa642b44 100644
--- a/lisp/vc/vc-svn.el
+++ b/lisp/vc/vc-svn.el
@@ -1,6 +1,6 @@
;;; vc-svn.el --- non-resident support for Subversion version-control -*- lexical-binding:t -*-
-;; Copyright (C) 2003-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003-2024 Free Software Foundation, Inc.
;; Author: FSF (see vc.el for full credits)
;; Maintainer: Stefan Monnier <monnier@gnu.org>
diff --git a/lisp/vc/vc.el b/lisp/vc/vc.el
index be7fa46c28e..b8cc44fc3dc 100644
--- a/lisp/vc/vc.el
+++ b/lisp/vc/vc.el
@@ -1,6 +1,6 @@
;;; vc.el --- drive a version-control system from within Emacs -*- lexical-binding:t -*-
-;; Copyright (C) 1992-1998, 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1992-1998, 2000-2024 Free Software Foundation, Inc.
;; Author: FSF (see below for full credits)
;; Maintainer: emacs-devel@gnu.org
@@ -517,6 +517,13 @@
;; Return the revision number that precedes REV for FILE, or nil if no such
;; revision exists.
;;
+;; - file-name-changes (rev)
+;;
+;; Return the list of pairs with changes in file names in REV. When
+;; a file was added, it should be a cons with nil car. When
+;; deleted, a cons with nil cdr. When copied or renamed, a cons
+;; with the source name as car and destination name as cdr.
+;;
;; - next-revision (file rev)
;;
;; Return the revision number that follows REV for FILE, or nil if no such
@@ -668,7 +675,7 @@
;;;; New Primitives:
;;
;; - uncommit: undo last checkin, leave changes in place in the workfile,
-;; stash the commit comment for re-use.
+;; stash the commit comment for reuse.
;;
;; - deal with push operations.
;;
@@ -1067,18 +1074,29 @@ Within directories, only files already under version control are noticed."
(defvar vc-dir-backend)
(defvar log-view-vc-backend)
+(defvar log-view-vc-fileset)
(defvar log-edit-vc-backend)
(defvar diff-vc-backend)
(defvar diff-vc-revisions)
+(defcustom vc-deduce-backend-nonvc-modes
+ ;; Maybe we could even use comint-mode rather than shell-mode?
+ '(dired-mode shell-mode eshell-mode compilation-mode)
+ "List of modes not supported by VC where backend should be deduced.
+In these modes the backend is deduced based on `default-directory'.
+If the value is t, the backend is deduced in all modes."
+ :type '(choice (const :tag "None" nil)
+ (repeat symbol)
+ (const :tag "All" t))
+ :version "30.1")
+
(defun vc-deduce-backend ()
(cond ((derived-mode-p 'vc-dir-mode) vc-dir-backend)
((derived-mode-p 'log-view-mode) log-view-vc-backend)
((derived-mode-p 'log-edit-mode) log-edit-vc-backend)
((derived-mode-p 'diff-mode) diff-vc-backend)
- ;; Maybe we could even use comint-mode rather than shell-mode?
- ((derived-mode-p
- 'dired-mode 'shell-mode 'eshell-mode 'compilation-mode)
+ ((or (eq vc-deduce-backend-nonvc-modes t)
+ (derived-mode-p vc-deduce-backend-nonvc-modes))
(ignore-errors (vc-responsible-backend default-directory)))
(vc-mode (vc-backend buffer-file-name))))
@@ -1138,6 +1156,11 @@ BEWARE: this function may change the current buffer."
(vc-state buffer-file-name)
(vc-checkout-model backend buffer-file-name))
(list backend (list buffer-file-name))))
+ ((derived-mode-p 'log-view-mode)
+ ;; 'log-view-mode' stashes the backend and the fileset in the
+ ;; two special variables, so we use them to avoid any possible
+ ;; mistakes from a decision made here ad-hoc.
+ (list log-view-vc-backend log-view-vc-fileset))
((and (buffer-live-p vc-parent-buffer)
;; FIXME: Why this test? --Stef
(or (buffer-file-name vc-parent-buffer)
@@ -1211,18 +1234,23 @@ BEWARE: this function may change the current buffer."
(defun vc-next-action (verbose)
"Do the next logical version control operation on the current fileset.
This requires that all files in the current VC fileset be in the
-same state. If not, signal an error.
-
-For merging-based version control systems:
- If every file in the VC fileset is not registered for version
- control, register the fileset (but don't commit).
- If every work file in the VC fileset is added or changed, pop
- up a *vc-log* buffer to commit the fileset.
+same state. If they are not, signal an error. Also signal an error if
+files in the fileset are missing (removed, but tracked by version control),
+or are ignored by the version control system.
+
+For modern merging-based version control systems:
+ If every file in the fileset is not registered for version
+ control, register the fileset (but don't commit). If VERBOSE is
+ non-nil (interactively, the prefix argument), ask for the VC
+ backend with which to register the fileset.
+ If every work file in the VC fileset is either added or modified,
+ pop up a *vc-log* buffer to commit the fileset changes.
For a centralized version control system, if any work file in
the VC fileset is out of date, offer to update the fileset.
For old-style locking-based version control systems, like RCS:
- If every file is not registered, register the file(s).
+ If every file is not registered, register the file(s); with a prefix
+ argument, allow to specify the VC backend for registration.
If every file is registered and unlocked, check out (lock)
the file(s) for editing.
If every file is locked by you and has changes, pop up a
@@ -1230,14 +1258,21 @@ For old-style locking-based version control systems, like RCS:
read-only copy of each changed file after checking in.
If every file is locked by you and unchanged, unlock them.
If every file is locked by someone else, offer to steal the lock.
+ If files are unlocked, but have changes, offer to either claim the
+ lock or revert to the last checked-in version.
+
+If this command is invoked from a patch buffer under `diff-mode', it
+will apply the diffs from the patch and pop up a *vc-log* buffer to
+check-in the resulting changes.
When using this command to register a new file (or files), it
will automatically deduce which VC repository to register it
with, using the most specific one.
If VERBOSE is non-nil (interactively, the prefix argument),
-you can specify a VC backend or (for centralized VCS only)
-the revision ID or branch ID."
+you can specify another VC backend for the file(s),
+or (for centralized VCS only) the revision ID or branch ID
+from which to check out the file(s)."
(interactive "P")
(let* ((vc-fileset (vc-deduce-fileset nil t 'state-model-only-files))
(backend (car vc-fileset))
@@ -1264,6 +1299,8 @@ the revision ID or branch ID."
(error "Fileset files are missing, so cannot be operated on"))
((eq state 'ignored)
(error "Fileset files are ignored by the version-control system"))
+ ;; Fileset comes from a diff-mode buffer, see
+ ;; 'diff-vc-deduce-fileset', and the buffer is the patch to apply.
((eq model 'patch)
(vc-checkin files backend nil nil nil (buffer-string)))
((or (null state) (eq state 'unregistered))
@@ -1724,7 +1761,8 @@ Runs the normal hooks `vc-before-checkin-hook' and `vc-checkin-hook'."
nil
"-p1"
"-r" null-device
- "--no-backup-if-mismatch"
+ "--posix"
+ "--remove-empty-files"
"-i" "-"))
(user-error "Patch failed: %s" (buffer-string))))
(vc-call-backend backend 'checkin files comment))
@@ -1883,7 +1921,9 @@ in the output buffer."
(vc-run-delayed (vc-diff-finish (current-buffer) nil))))
(defun vc-diff-internal (async vc-fileset rev1 rev2 &optional verbose buffer)
- "Report diffs between two revisions of a fileset.
+ "Report diffs between revisions REV1 and REV2 of a fileset in VC-FILESET.
+ASYNC non-nil means run the backend's commands asynchronously if possible.
+VC-FILESET should have the format described in `vc-deduce-fileset'.
Output goes to the buffer BUFFER, which defaults to *vc-diff*.
BUFFER, if non-nil, should be a buffer or a buffer name.
Return t if the buffer had changes, nil otherwise."
@@ -1899,15 +1939,26 @@ Return t if the buffer had changes, nil otherwise."
;; but the only way to set it for each file included would
;; be to call the back end separately for each file.
(coding-system-for-read
- (if files (vc-coding-system-for-diff (car files)) 'undecided))
+ ;; Force the EOL conversion to be -unix, in case the files
+ ;; to be compared have DOS EOLs. In that case, EOL
+ ;; conversion will produce a patch file that will either
+ ;; fail to apply, or will change the EOL format of some of
+ ;; the lines in the patched file.
+ (coding-system-change-eol-conversion
+ (if files (vc-coding-system-for-diff (car files)) 'undecided)
+ 'unix))
(orig-diff-buffer-clone
(if revert-buffer-in-progress-p
(clone-buffer
(generate-new-buffer-name " *vc-diff-clone*") nil))))
;; On MS-Windows and MS-DOS, Diff is likely to produce DOS-style
;; EOLs, which will look ugly if (car files) happens to have Unix
- ;; EOLs.
- (if (memq system-type '(windows-nt ms-dos))
+ ;; EOLs. But for Git, we must force Unix EOLs in the diffs, since
+ ;; Git always produces Unix EOLs in the parts that didn't come
+ ;; from the file, and wants to see any CR characters when applying
+ ;; patches.
+ (if (and (memq system-type '(windows-nt ms-dos))
+ (not (eq (car vc-fileset) 'Git)))
(setq coding-system-for-read
(coding-system-change-eol-conversion coding-system-for-read
'dos)))
@@ -2211,7 +2262,7 @@ saving the buffer."
(vc-maybe-buffer-sync not-urgent)
(let ((backend (vc-deduce-backend))
(default-directory default-directory)
- rootdir working-revision)
+ rootdir)
(if backend
(setq rootdir (vc-call-backend backend 'root default-directory))
(setq rootdir (read-directory-name "Directory for VC root-diff: "))
@@ -2219,14 +2270,13 @@ saving the buffer."
(if backend
(setq default-directory rootdir)
(error "Directory is not version controlled")))
- (setq working-revision (vc-working-revision rootdir))
;; VC diff for the root directory produces output that is
;; relative to it. Bind default-directory to the root directory
;; here, this way the *vc-diff* buffer is setup correctly, so
;; relative file names work.
(let ((default-directory rootdir))
(vc-diff-internal
- t (list backend (list rootdir) working-revision) nil nil
+ t (list backend (list rootdir)) nil nil
(called-interactively-p 'interactive))))))
;;;###autoload
@@ -2645,22 +2695,53 @@ Not all VC backends support short logs!")
(defvar log-view-vc-fileset)
(defvar log-view-message-re)
+;; XXX: File might have been renamed multiple times, so to support
+;; multiple jumps back, this probably should be a stack of entries.
+(defvar log-view-vc-prev-revision nil)
+(defvar log-view-vc-prev-fileset nil)
(defun vc-print-log-setup-buttons (working-revision is-start-revision limit pl-return)
"Insert at the end of the current buffer buttons to show more log entries.
In the new log, leave point at WORKING-REVISION (if non-nil).
-LIMIT is the number of entries currently shown.
-Does nothing if IS-START-REVISION is non-nil, or if LIMIT is nil,
-or if PL-RETURN is `limit-unsupported'."
+LIMIT is the current maximum number of entries shown. Does
+nothing if IS-START-REVISION is non-nil and LIMIT is 1, or if
+LIMIT is nil, or if PL-RETURN is `limit-unsupported'."
+ ;; LIMIT=1 is set by vc-annotate-show-log-revision-at-line
+ ;; or by vc-print-root-log with current-prefix-arg=1.
+ ;; In either case only one revision is wanted, no buttons.
(when (and limit (not (eq 'limit-unsupported pl-return))
- (not is-start-revision))
+ (not (and is-start-revision
+ (= limit 1))))
(let ((entries 0))
(goto-char (point-min))
(while (re-search-forward log-view-message-re nil t)
(cl-incf entries))
- ;; If we got fewer entries than we asked for, then displaying
- ;; the "more" buttons isn't useful.
- (when (>= entries limit)
+ (if (< entries limit)
+ ;; The log has been printed in full. Perhaps it started
+ ;; with a copy or rename?
+ ;; FIXME: We'd probably still want this button even when
+ ;; vc-log-show-limit is customized to 0 (should be rare).
+ (let* ((last-revision (log-view-current-tag (point-max)))
+ ;; XXX: Could skip this when vc-git-print-log-follow = t.
+ (name-changes
+ (condition-case nil
+ (vc-call-backend log-view-vc-backend
+ 'file-name-changes last-revision)
+ (vc-not-supported nil)))
+ (matching-changes
+ (cl-delete-if-not (lambda (f) (member f log-view-vc-fileset))
+ name-changes :key #'cdr))
+ (old-names (delq nil (mapcar #'car matching-changes))))
+ (when old-names
+ (goto-char (point-max))
+ (unless (looking-back "\n\n" (- (point) 2))
+ (insert "\n"))
+ (vc-print-log-renamed-add-button old-names log-view-vc-backend
+ log-view-vc-fileset
+ working-revision
+ last-revision
+ limit)))
+ ;; Perhaps there are more entries in the log.
(goto-char (point-max))
(insert "\n")
(insert-text-button
@@ -2681,6 +2762,49 @@ or if PL-RETURN is `limit-unsupported'."
'help-echo "Show the log again, including all entries")
(insert "\n")))))
+(defun vc-print-log-renamed-add-button ( renamed-files backend
+ current-fileset
+ current-revision
+ revision limit)
+ "Print the button for jump to the log for a different fileset.
+RENAMED-FILES is the fileset to use. BACKEND is the VC backend.
+REVISION is the revision from which to start the new log.
+CURRENT-FILESET, if non-nil, is the fileset to use in the \"back\"
+button for. Same for CURRENT-REVISION. LIMIT means the usual."
+ (let ((relatives (mapcar #'file-relative-name renamed-files))
+ (from-to (if current-fileset "from" "to"))
+ (before-after (if current-fileset "before" "after")))
+ (insert
+ (format
+ "Renamed %s %s"
+ from-to
+ (mapconcat (lambda (s)
+ (propertize s 'font-lock-face
+ 'log-view-file))
+ relatives
+ ", "))
+ " ")
+ (insert-text-button
+ "View log"
+ 'action (lambda (&rest _ignore)
+ ;; To set up parent buffer in the new viewer.
+ (with-current-buffer vc-parent-buffer
+ (let ((log-view-vc-prev-fileset current-fileset)
+ (log-view-vc-prev-revision current-revision))
+ (vc-print-log-internal backend renamed-files
+ revision t limit))))
+ ;; XXX: Showing the full history for OLD-NAMES (with
+ ;; IS-START-REVISION=nil) can be better sometimes
+ ;; (e.g. when some edits still occurred after a rename
+ ;; -- multiple branches scenario), but it also can hurt
+ ;; in others because of Git's automatic history
+ ;; simplification: as a result, the logs for some
+ ;; use-package's files before merge could not be found.
+ 'help-echo
+ (format
+ "Show the log for the file name(s) %s the rename"
+ before-after))))
+
(defun vc-print-log-internal (backend files working-revision
&optional is-start-revision limit type)
"For specified BACKEND and FILES, show the VC log.
@@ -2688,9 +2812,6 @@ Leave point at WORKING-REVISION, if it is non-nil.
If IS-START-REVISION is non-nil, start the log from WORKING-REVISION
\(not all backends support this); i.e., show only WORKING-REVISION and
earlier revisions. Show up to LIMIT entries (non-nil means unlimited)."
- ;; As of 2013/04 the only thing that passes IS-START-REVISION non-nil
- ;; is vc-annotate-show-log-revision-at-line, which sets LIMIT = 1.
-
;; Don't switch to the output buffer before running the command,
;; so that any buffer-local settings in the vc-controlled
;; buffer can be accessed by the command.
@@ -2702,8 +2823,22 @@ earlier revisions. Show up to LIMIT entries (non-nil means unlimited)."
(vc-log-internal-common
backend buffer-name files type
(lambda (bk buf _type-arg files-arg)
- (vc-call-backend bk 'print-log files-arg buf shortlog
- (when is-start-revision working-revision) limit))
+ (vc-call-backend bk 'print-log files-arg buf shortlog
+ (when is-start-revision working-revision) limit)
+ (when log-view-vc-prev-fileset
+ (with-current-buffer buf
+ (let ((inhibit-read-only t)
+ (pmark (process-mark (get-buffer-process buf))))
+ (goto-char (point-min))
+ (vc-print-log-renamed-add-button log-view-vc-prev-fileset
+ backend
+ nil
+ nil
+ log-view-vc-prev-revision
+ limit)
+ (insert "\n\n")
+ (when (< pmark (point))
+ (set-marker pmark (point)))))))
(lambda (_bk _files-arg ret)
(save-excursion
(vc-print-log-setup-buttons working-revision
@@ -3156,14 +3291,13 @@ its name; otherwise return nil."
(vc-resynch-buffer file t t))
;;;###autoload
-(defun vc-switch-backend (file backend)
+(defun vc-change-backend (file backend)
"Make BACKEND the current version control system for FILE.
FILE must already be registered in BACKEND. The change is not
permanent, only for the current session. This function only changes
VC's perspective on FILE, it does not register or unregister it.
By default, this command cycles through the registered backends.
To get a prompt, use a prefix argument."
- (declare (obsolete nil "28.1"))
(interactive
(list
(or buffer-file-name
@@ -3194,6 +3328,9 @@ To get a prompt, use a prefix argument."
(error "%s is not registered in %s" file backend))
(vc-mode-line file)))
+(define-obsolete-function-alias 'vc-switch-backend #'vc-change-backend
+ "30.1")
+
;;;###autoload
(defun vc-transfer-file (file new-backend)
"Transfer FILE to another version control system NEW-BACKEND.
@@ -3218,8 +3355,7 @@ backend to NEW-BACKEND, and unregister FILE from the current backend.
(if registered
(set-file-modes file (logior (file-modes file) 128))
;; `registered' might have switched under us.
- (with-suppressed-warnings ((obsolete vc-switch-backend))
- (vc-switch-backend file old-backend))
+ (vc-change-backend file old-backend)
(let* ((rev (vc-working-revision file))
(modified-file (and edited (make-temp-file file)))
(unmodified-file (and modified-file (vc-version-backup-file file))))
@@ -3238,19 +3374,16 @@ backend to NEW-BACKEND, and unregister FILE from the current backend.
(vc-revert-file file))))
(vc-call-backend new-backend 'receive-file file rev))
(when modified-file
- (with-suppressed-warnings ((obsolete vc-switch-backend))
- (vc-switch-backend file new-backend))
+ (vc-change-backend file new-backend)
(unless (eq (vc-checkout-model new-backend (list file)) 'implicit)
(vc-checkout file))
(rename-file modified-file file 'ok-if-already-exists)
(vc-file-setprop file 'vc-checkout-time nil)))))
(when move
- (with-suppressed-warnings ((obsolete vc-switch-backend))
- (vc-switch-backend file old-backend))
+ (vc-change-backend file old-backend)
(setq comment (vc-call-backend old-backend 'comment-history file))
(vc-call-backend old-backend 'unregister file))
- (with-suppressed-warnings ((obsolete vc-switch-backend))
- (vc-switch-backend file new-backend))
+ (vc-change-backend file new-backend)
(when (or move edited)
(vc-file-setprop file 'vc-state 'edited)
(vc-mode-line file new-backend)
@@ -3663,8 +3796,7 @@ If successful, returns the string with the directory of the
checkout. If BACKEND is nil, iterate through every known backend
in `vc-handled-backends' until one succeeds. If REV is non-nil,
it indicates a specific revision to check out."
- (unless directory
- (setq directory default-directory))
+ (setq directory (expand-file-name (or directory default-directory)))
(if backend
(progn
(unless (memq backend vc-handled-backends)
diff --git a/lisp/vcursor.el b/lisp/vcursor.el
index 48fa1160deb..ec5adbd832c 100644
--- a/lisp/vcursor.el
+++ b/lisp/vcursor.el
@@ -1,6 +1,6 @@
;;; vcursor.el --- manipulate an alternative ("virtual") cursor -*- lexical-binding: t; -*-
-;; Copyright (C) 1994-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1994-2024 Free Software Foundation, Inc.
;; Author: Peter Stephenson <pws@ibmth.df.unipi.it>
;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/version.el b/lisp/version.el
index 0eb4ea76f4f..a84f7f161f0 100644
--- a/lisp/version.el
+++ b/lisp/version.el
@@ -1,6 +1,6 @@
;;; version.el --- record version number of Emacs -*- lexical-binding:t -*-
-;; Copyright (C) 1985, 1992, 1994-1995, 1999-2023 Free Software
+;; Copyright (C) 1985, 1992, 1994-1995, 1999-2024 Free Software
;; Foundation, Inc.
;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/view.el b/lisp/view.el
index 8760b91d06c..2ac7479739f 100644
--- a/lisp/view.el
+++ b/lisp/view.el
@@ -1,6 +1,6 @@
;;; view.el --- peruse file or buffer without editing -*- lexical-binding: t -*-
-;; Copyright (C) 1985-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1985-2024 Free Software Foundation, Inc.
;; Author: K. Shane Hartman
;; Maintainer: emacs-devel@gnu.org
diff --git a/lisp/w32-fns.el b/lisp/w32-fns.el
index d9b91cfb6ea..a68f1ceec35 100644
--- a/lisp/w32-fns.el
+++ b/lisp/w32-fns.el
@@ -1,6 +1,6 @@
;;; w32-fns.el --- Lisp routines for 32-bit Windows -*- lexical-binding: t; -*-
-;; Copyright (C) 1994, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1994, 2001-2024 Free Software Foundation, Inc.
;; Author: Geoff Voelker <voelker@cs.washington.edu>
;; Keywords: internal
diff --git a/lisp/w32-vars.el b/lisp/w32-vars.el
index a3deab9bc3a..0c567dda918 100644
--- a/lisp/w32-vars.el
+++ b/lisp/w32-vars.el
@@ -1,6 +1,6 @@
;;; w32-vars.el --- MS-Windows specific user options -*- lexical-binding:t -*-
-;; Copyright (C) 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2024 Free Software Foundation, Inc.
;; Author: Jason Rumney <jasonr@gnu.org>
;; Keywords: internal
diff --git a/lisp/wdired.el b/lisp/wdired.el
index 7b9c75d36b1..d5d593483dc 100644
--- a/lisp/wdired.el
+++ b/lisp/wdired.el
@@ -1,6 +1,6 @@
;;; wdired.el --- Rename files editing their names in dired buffers -*- coding: utf-8; lexical-binding: t; -*-
-;; Copyright (C) 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2004-2024 Free Software Foundation, Inc.
;; Filename: wdired.el
;; Author: Juan León Lahoz García <juanleon1@gmail.com>
@@ -261,6 +261,10 @@ See `wdired-mode'."
(add-function :override (local 'revert-buffer-function) #'wdired-revert)
(set-buffer-modified-p nil)
(setq buffer-undo-list nil)
+ ;; Non-nil `dired-filename-display-length' may cause filenames to be
+ ;; hidden partly, so we remove filename invisibility spec
+ ;; temporarily to ensure filenames are visible for editing.
+ (dired-filename-update-invisibility-spec)
(run-mode-hooks 'wdired-mode-hook)
(message "%s" (substitute-command-keys
"Press \\[wdired-finish-edit] when finished \
@@ -453,9 +457,12 @@ non-nil means return old filename."
(force-mode-line-update)
(setq buffer-read-only t)
(setq major-mode 'dired-mode)
- (setq mode-name "Dired")
+ (dired-sort-set-mode-line)
(dired-advertise)
(dired-hide-details-update-invisibility-spec)
+ ;; Restore filename invisibility spec that is removed in
+ ;; `wdired-change-to-wdired-mode'.
+ (dired-filename-update-invisibility-spec)
(remove-hook 'kill-buffer-hook #'wdired-check-kill-buffer t)
(remove-hook 'before-change-functions #'wdired--before-change-fn t)
(remove-hook 'after-change-functions #'wdired--restore-properties t)
diff --git a/lisp/whitespace.el b/lisp/whitespace.el
index 86fc179396e..6f47e32beb5 100644
--- a/lisp/whitespace.el
+++ b/lisp/whitespace.el
@@ -1,9 +1,9 @@
;;; whitespace.el --- minor mode to visualize TAB, (HARD) SPACE, NEWLINE -*- lexical-binding: t -*-
-;; Copyright (C) 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2000-2024 Free Software Foundation, Inc.
;; Author: Vinicius Jose Latorre <viniciusjl.gnu@gmail.com>
-;; Keywords: data, wp
+;; Keywords: data, text
;; Version: 13.2.2
;; URL: https://www.emacswiki.org/cgi-bin/wiki/ViniciusJoseLatorre
@@ -1026,8 +1026,8 @@ See also `whitespace-newline' and `whitespace-display-mappings'."
((eq whitespace-global-modes t))
((listp whitespace-global-modes)
(if (eq (car-safe whitespace-global-modes) 'not)
- (not (apply #'derived-mode-p (cdr whitespace-global-modes)))
- (apply #'derived-mode-p whitespace-global-modes)))
+ (not (derived-mode-p (cdr whitespace-global-modes)))
+ (derived-mode-p whitespace-global-modes)))
(t nil))
;; ...we have a display (not running a batch job)
(not noninteractive)
diff --git a/lisp/wid-browse.el b/lisp/wid-browse.el
index 9578531fcc3..bb56f3f62fb 100644
--- a/lisp/wid-browse.el
+++ b/lisp/wid-browse.el
@@ -1,6 +1,6 @@
;;; wid-browse.el --- functions for browsing widgets -*- lexical-binding: t -*-
-;; Copyright (C) 1997-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997-2024 Free Software Foundation, Inc.
;; Author: Per Abrahamsen <abraham@dina.kvl.dk>
;; Keywords: extensions
diff --git a/lisp/wid-edit.el b/lisp/wid-edit.el
index a70598bb6c9..cd06acd3f99 100644
--- a/lisp/wid-edit.el
+++ b/lisp/wid-edit.el
@@ -1,6 +1,6 @@
;;; wid-edit.el --- Functions for creating and using widgets -*- lexical-binding:t -*-
;;
-;; Copyright (C) 1996-1997, 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-1997, 1999-2024 Free Software Foundation, Inc.
;;
;; Author: Per Abrahamsen <abraham@dina.kvl.dk>
;; Maintainer: emacs-devel@gnu.org
@@ -282,16 +282,20 @@ The user is asked to choose between each NAME from ITEMS.
If ITEMS has simple item definitions, then this function returns the VALUE of
the chosen element. If ITEMS is a keymap, then the return value is the symbol
in the key vector, as in the argument of `define-key'."
- ;; Apply quote substitution to customize choice menu item text,
- ;; whether it occurs in a widget buffer or in a popup menu.
+ ;; Apply substitution to choice menu title and item text, whether it
+ ;; occurs in a widget buffer or in a popup menu.
(let ((items (mapc (lambda (x)
- (when (consp x)
- (dotimes (i (1- (length x)))
- (when (stringp (nth i x))
- (setcar (nthcdr i x)
- (substitute-command-keys
- (car (nthcdr i x))))))))
- items)))
+ (if (proper-list-p x)
+ (dotimes (i (1- (length x)))
+ (when (stringp (nth i x))
+ (setcar (nthcdr i x)
+ (substitute-command-keys
+ (car (nthcdr i x))))))
+ ;; ITEMS has simple item definitions.
+ (when (and (consp x) (stringp (car x)))
+ (setcar x (substitute-command-keys (car x))))))
+ items))
+ (title (substitute-command-keys title)))
(cond ((and (< (length items) widget-menu-max-size)
event (display-popup-menus-p))
;; Mouse click.
@@ -644,8 +648,7 @@ Return a list whose car contains all members of VALS that matched WIDGET."
(defun widget-prompt-value (widget prompt &optional value unbound)
"Prompt for a value matching WIDGET, using PROMPT.
The current value is assumed to be VALUE, unless UNBOUND is non-nil."
- (unless (listp widget)
- (setq widget (list widget)))
+ (setq widget (ensure-list widget))
(setq prompt (format "[%s] %s" (widget-type widget) prompt))
(setq widget (widget-convert widget))
(let ((answer (widget-apply widget :prompt-value prompt value unbound)))
@@ -1124,7 +1127,7 @@ If nothing was called, return non-nil."
;; This a touchscreen event and must be handled
;; specially through `touch-screen-track-tap'.
(progn
- (unless (touch-screen-track-tap event)
+ (unless (touch-screen-track-tap event nil nil t)
(throw 'button-press-cancelled t)))
(unless (widget-apply button :mouse-down-action event)
(let ((track-mouse t))
@@ -3678,7 +3681,9 @@ match-alternatives: %S"
:warning)
;; Make sure we will `read' a string.
(setq value (prin1-to-string value)))
- (read value)))
+ (if (string-empty-p value)
+ value
+ (read value))))
(defun widget-restricted-sexp-match (widget value)
(let ((alternatives (widget-get widget :match-alternatives))
diff --git a/lisp/widget.el b/lisp/widget.el
index 0d4396ad1c1..11954378af1 100644
--- a/lisp/widget.el
+++ b/lisp/widget.el
@@ -1,6 +1,6 @@
;;; widget.el --- a library of user interface components -*- lexical-binding: t; -*-
;;
-;; Copyright (C) 1996-1997, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1996-1997, 2001-2024 Free Software Foundation, Inc.
;;
;; Author: Per Abrahamsen <abraham@dina.kvl.dk>
;; Keywords: help, extensions, faces, hypermedia
diff --git a/lisp/windmove.el b/lisp/windmove.el
index 746a440bacb..bc2beed5055 100644
--- a/lisp/windmove.el
+++ b/lisp/windmove.el
@@ -1,6 +1,6 @@
;;; windmove.el --- directional window-selection routines -*- lexical-binding:t -*-
-;; Copyright (C) 1998-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1998-2024 Free Software Foundation, Inc.
;; Author: Hovav Shacham <hovav@cs.stanford.edu>
;; Created: 17 October 1998
@@ -485,7 +485,7 @@ Default value of MODIFIERS is `shift'."
(interactive)
(unless modifiers (setq modifiers 'shift))
(when (eq modifiers 'none) (setq modifiers nil))
- (unless (listp modifiers) (setq modifiers (list modifiers)))
+ (setq modifiers (ensure-list modifiers))
(windmove-install-defaults nil modifiers
'((windmove-left left)
(windmove-right right)
@@ -626,7 +626,7 @@ Default value of MODIFIERS is `shift-meta'."
(interactive)
(unless modifiers (setq modifiers '(shift meta)))
(when (eq modifiers 'none) (setq modifiers nil))
- (unless (listp modifiers) (setq modifiers (list modifiers)))
+ (setq modifiers (ensure-list modifiers))
(windmove-install-defaults nil modifiers
'((windmove-display-left left)
(windmove-display-right right)
@@ -703,10 +703,10 @@ Default value of PREFIX is \\`C-x' and MODIFIERS is `shift'."
(interactive)
(unless prefix (setq prefix '(?\C-x)))
(when (eq prefix 'none) (setq prefix nil))
- (unless (listp prefix) (setq prefix (list prefix)))
+ (setq prefix (ensure-list prefix))
(unless modifiers (setq modifiers '(shift)))
(when (eq modifiers 'none) (setq modifiers nil))
- (unless (listp modifiers) (setq modifiers (list modifiers)))
+ (setq modifiers (ensure-list modifiers))
(windmove-install-defaults prefix modifiers
'((windmove-delete-left left)
(windmove-delete-right right)
@@ -766,7 +766,7 @@ Default value of MODIFIERS is `shift-super'."
(interactive)
(unless modifiers (setq modifiers '(shift super)))
(when (eq modifiers 'none) (setq modifiers nil))
- (unless (listp modifiers) (setq modifiers (list modifiers)))
+ (setq modifiers (ensure-list modifiers))
(windmove-install-defaults nil modifiers
'((windmove-swap-states-left left)
(windmove-swap-states-right right)
diff --git a/lisp/window.el b/lisp/window.el
index b0970cfb064..e100f25526b 100644
--- a/lisp/window.el
+++ b/lisp/window.el
@@ -1,6 +1,6 @@
;;; window.el --- GNU Emacs window commands aside from those written in C -*- lexical-binding:t -*-
-;; Copyright (C) 1985-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1985-2024 Free Software Foundation, Inc.
;; Maintainer: emacs-devel@gnu.org
;; Keywords: internal
@@ -4177,8 +4177,8 @@ a non-nil `no-other-window' parameter."
"How to choose a frame's selected window after window deletion.
When a frame's selected window gets deleted, Emacs has to choose
another live window on that frame to serve as its selected
-window. This option allows to control which window gets selected
-instead.
+window. This option controls the window that is selected in such
+a situation.
The possible choices are `mru' (the default) to select the most
recently used window on that frame, and `pos' to choose the
@@ -5682,7 +5682,8 @@ Return the new window.
If optional argument SIZE is omitted or nil, both windows get the
same height, or close to it. If SIZE is positive, the upper
\(selected) window gets SIZE lines. If SIZE is negative, the
-lower (new) window gets -SIZE lines.
+lower (new) window gets -SIZE lines. Interactively, SIZE is
+the prefix numeric argument.
If the variable `split-window-keep-point' is non-nil, both
windows get the same value of point as the WINDOW-TO-SPLIT.
@@ -5734,8 +5735,10 @@ amount of redisplay; this is convenient on slow terminals."
"Split root window of current frame in two.
The current window configuration is retained in the top window,
the lower window takes up the whole width of the frame. SIZE is
-handled as in `split-window-below'."
- (interactive "P")
+handled as in `split-window-below', and interactively is the
+prefix numeric argument."
+ (interactive `(,(when current-prefix-arg
+ (prefix-numeric-value current-prefix-arg))))
(split-window-below size (frame-root-window)))
(defun split-window-right (&optional size window-to-split)
@@ -5752,7 +5755,7 @@ same width, or close to it. If SIZE is positive, the left-hand
right-hand (new) window gets -SIZE columns. Here, SIZE includes
the width of the window's scroll bar; if there are no scroll
bars, it includes the width of the divider column to the window's
-right, if any."
+right, if any. Interactively, SIZE is the prefix numeric argument."
(interactive `(,(when current-prefix-arg
(prefix-numeric-value current-prefix-arg))
,(selected-window)))
@@ -5774,8 +5777,9 @@ right, if any."
The current window configuration is retained within the left
window, and a new window is created on the right, taking up the
whole height of the frame. SIZE is treated as by
-`split-window-right'."
- (interactive "P")
+`split-window-right' and interactively, is the prefix numeric argument."
+ (interactive `(,(when current-prefix-arg
+ (prefix-numeric-value current-prefix-arg))))
(split-window-right size (frame-root-window)))
;;; Balancing windows.
@@ -6860,6 +6864,7 @@ BUFFER in a window of the selected frame.
If ARGS is a list whose car is a symbol, use (car ARGS) as a
function to do the work. Pass it BUFFER as first argument, and
pass the elements of (cdr ARGS) as the remaining arguments."
+ (declare (obsolete display-buffer-pop-up-frame "30.1"))
(if (and args (symbolp (car args)))
(apply (car args) buffer (cdr args))
(let ((window (get-buffer-window buffer 0)))
@@ -6879,9 +6884,8 @@ pass the elements of (cdr ARGS) as the remaining arguments."
;; Stay on the same frame if requested.
(when (or (cdr (assq 'same-frame args)) (cdr (assq 'same-window args)))
(let* ((pop-up-windows t)
- pop-up-frames
special-display-buffer-names special-display-regexps)
- (display-buffer buffer)))
+ (display-buffer buffer '((pop-up-frames . nil)))))
;; If no window yet, make one in a new frame.
(let* ((frame
(with-current-buffer buffer
@@ -6994,6 +6998,13 @@ Emacs Lisp manual for an example."
(const :tag "Always" t))
:group 'windows)
+(defun window--pop-up-frames (alist)
+ (let* ((override (assq 'pop-up-frames alist))
+ (pop-up (if override (cdr override) pop-up-frames)))
+ (if (eq pop-up 'graphic-only)
+ (display-graphic-p)
+ pop-up)))
+
(defcustom display-buffer-reuse-frames nil
"Non-nil means `display-buffer' should reuse frames.
If the buffer in question is already displayed in a frame, raise
@@ -7468,6 +7479,64 @@ Return WINDOW if BUFFER and WINDOW are live."
The actual non-nil value of this variable will be copied to the
`window-dedicated-p' flag.")
+(defcustom toggle-window-dedicated-flag 'interactive
+ "What dedicated flag should `toggle-window-dedicated' use by default.
+
+If `toggle-window-dedicated' does not receive a flag argument,
+the value of this variable is used and passed to
+`set-window-dedicated-p'. Setting this to t will make
+`toggle-window-dedicated' use strong dedication by default. Any
+other non-nil value will result in the same kind of non-strong
+dedication."
+ :type '(choice (const :tag "Strongly dedicated" t)
+ (const :tag "Dedicated" interactive))
+ :version "30.0"
+ :group 'windows)
+
+(defun toggle-window-dedicated (&optional window flag interactive)
+ "Toggle whether WINDOW is dedicated to its current buffer.
+
+WINDOW must be a live window and defaults to the selected one.
+If FLAG is t (interactively, the prefix argument), make the window
+\"strongly\" dedicated to its buffer. FLAG defaults to a non-nil,
+non-t value, and is passed to `set-window-dedicated-p', which see.
+If INTERACTIVE is non-nil, print a message describing the dedication
+status of WINDOW, after toggling it. Interactively, this argument is
+always non-nil.
+
+When a window is dedicated to its buffer, `display-buffer' will avoid
+displaying another buffer in it, if possible. When a window is
+strongly dedicated to its buffer, changing the buffer shown in the
+window will usually signal an error.
+
+You can control the default of FLAG with
+`toggle-window-dedicated-flag'. Consequently, if you set that
+variable to t, strong dedication will be used by default and
+\\[universal-argument] will make the window weakly dedicated.
+
+See the info node `(elisp)Dedicated Windows' for more details."
+ (interactive "i\nP\np")
+ (setq window (window-normalize-window window))
+ (setq flag (cond
+ ((consp flag)
+ (if (eq toggle-window-dedicated-flag t)
+ 'interactive
+ t))
+ ((null flag) toggle-window-dedicated-flag)
+ (t flag)))
+ (if (window-dedicated-p window)
+ (set-window-dedicated-p window nil)
+ (set-window-dedicated-p window flag))
+ (when interactive
+ (message "Window is %s dedicated to buffer %s"
+ (let ((status (window-dedicated-p window)))
+ (cond
+ ((null status) "no longer")
+ ((eq status t) "now strongly")
+ (t "now")))
+ (current-buffer))
+ (force-mode-line-update)))
+
(defconst display-buffer--action-function-custom-type
'(choice :tag "Function"
(const :tag "--" ignore) ; default for insertion
@@ -7535,10 +7604,8 @@ where:
arguments: a buffer to display and an alist of the same form as
ALIST. See `display-buffer' for details.
-`display-buffer' scans this alist until it either finds a
-matching regular expression or the function specified by a
-condition returns non-nil. In any of these cases, it adds the
-associated action to the list of actions it will try."
+`display-buffer' scans this alist until the CONDITION is satisfied
+and adds the associated ACTION to the list of actions it will try."
:type `(alist :key-type
(choice :tag "Condition"
regexp
@@ -7684,6 +7751,8 @@ Action alist entries are:
Possible values are nil (the selected frame), t (any live
frame), visible (any visible frame), 0 (any visible or
iconified frame) or an existing live frame.
+ `pop-up-frames' -- Same effect as the eponymous variable.
+ Takes precedence over the variable.
`pop-up-frame-parameters' -- The value specifies an alist of
frame parameters to give a new frame, if one is created.
`window-height' -- The value specifies the desired height of the
@@ -7772,12 +7841,12 @@ specified by the ACTION argument."
user-action special-action action extra-action
display-buffer-base-action
display-buffer-fallback-action))
- (functions (apply 'append
+ (functions (apply #'append
(mapcar (lambda (x)
(setq x (car x))
(if (functionp x) (list x) x))
actions)))
- (alist (apply 'append (mapcar 'cdr actions)))
+ (alist (apply #'append (mapcar #'cdr actions)))
window)
(unless (buffer-live-p buffer)
(error "Invalid buffer"))
@@ -7920,9 +7989,7 @@ called only by `display-buffer' or a function directly or
indirectly called by the latter."
(let* ((alist-entry (assq 'reusable-frames alist))
(frames (cond (alist-entry (cdr alist-entry))
- ((if (eq pop-up-frames 'graphic-only)
- (display-graphic-p)
- pop-up-frames)
+ ((window--pop-up-frames alist)
0)
(display-buffer-reuse-frames 0)
(t (last-nonminibuffer-frame))))
@@ -7976,9 +8043,7 @@ indirectly called by the latter."
(let* ((alist-entry (assq 'reusable-frames alist))
(alist-mode-entry (assq 'mode alist))
(frames (cond (alist-entry (cdr alist-entry))
- ((if (eq pop-up-frames 'graphic-only)
- (display-graphic-p)
- pop-up-frames)
+ ((window--pop-up-frames alist)
0)
(display-buffer-reuse-frames 0)
(t (last-nonminibuffer-frame))))
@@ -7990,8 +8055,7 @@ indirectly called by the latter."
buffer-mode))
(curwin (selected-window))
(curframe (selected-frame)))
- (unless (listp allowed-modes)
- (setq allowed-modes (list allowed-modes)))
+ (setq allowed-modes (ensure-list allowed-modes))
(let (same-mode-same-frame
same-mode-other-frame
derived-mode-same-frame
@@ -7999,10 +8063,8 @@ indirectly called by the latter."
(dolist (window windows)
(let ((mode?
(with-current-buffer (window-buffer window)
- (cond ((memq major-mode allowed-modes)
- 'same)
- ((apply #'derived-mode-p allowed-modes)
- 'derived)))))
+ (cond ((memq major-mode allowed-modes) 'same)
+ ((derived-mode-p allowed-modes) 'derived)))))
(when (and mode?
(not (and inhibit-same-window-p
(eq window curwin))))
@@ -8127,9 +8189,7 @@ text-only terminal), try with `display-buffer-pop-up-frame'.
ALIST is an association list of action symbols and values. See
Info node `(elisp) Buffer Display Action Alists' for details of
such alists."
- (and (if (eq pop-up-frames 'graphic-only)
- (display-graphic-p)
- pop-up-frames)
+ (and (window--pop-up-frames alist)
(display-buffer-pop-up-frame buffer alist)))
(defun display-buffer--maybe-pop-up-window (buffer alist)
@@ -8276,8 +8336,8 @@ This function tries to reuse or split a window such that the
window produced this way is on the side of the reference window
specified by the `direction' entry.
-Four special values for `direction' entries allow to implicitly
-specify the selected frame's main window as reference window:
+Four special values for `direction' entries allow implicitly
+specifying the selected frame's main window as reference window:
`leftmost', `top', `rightmost' and `bottom'. Hence, instead of
`(direction . left) (window . main)' one can simply write
`(direction . leftmost)'.
@@ -8493,9 +8553,7 @@ indirectly called by the latter."
(cdr (assq 'inhibit-same-window alist)))
(frames (cond
(alist-entry (cdr alist-entry))
- ((if (eq pop-up-frames 'graphic-only)
- (display-graphic-p)
- pop-up-frames)
+ ((window--pop-up-frames alist)
0)
(display-buffer-reuse-frames 0)
(t (last-nonminibuffer-frame))))
@@ -10751,6 +10809,7 @@ Used in `repeat-mode'."
"2" #'split-root-window-below
"3" #'split-root-window-right
"s" #'window-toggle-side-windows
+ "d" #'toggle-window-dedicated
"^ f" #'tear-off-window
"^ t" #'tab-window-detach
"-" #'fit-window-to-buffer
diff --git a/lisp/winner.el b/lisp/winner.el
index 84a7b0ce903..2aa59a86b25 100644
--- a/lisp/winner.el
+++ b/lisp/winner.el
@@ -1,6 +1,6 @@
;;; winner.el --- Restore old window configurations -*- lexical-binding: t -*-
-;; Copyright (C) 1997-1998, 2001-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1997-1998, 2001-2024 Free Software Foundation, Inc.
;; Author: Ivar Rummelhoff <ivarru@math.uio.no>
;; Created: 27 Feb 1997
diff --git a/lisp/woman.el b/lisp/woman.el
index e4e3d176d08..a9af46fa387 100644
--- a/lisp/woman.el
+++ b/lisp/woman.el
@@ -1,6 +1,6 @@
;;; woman.el --- browse UN*X manual pages `wo (without) man' -*- lexical-binding: t; -*-
-;; Copyright (C) 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2000-2024 Free Software Foundation, Inc.
;; Author: Francis J. Wright <F.J.Wright@qmul.ac.uk>
;; Maintainer: emacs-devel@gnu.org
@@ -34,6 +34,10 @@
;; the emulation is modified to include the reformatting done by the
;; Emacs `man' command. No hyphenation is performed.
+;; Note that `M-x woman' doesn’t yet support the latest features of
+;; modern man pages, so we recommend using `M-x man' if that is
+;; available on your system.
+
;; Advantages
;; Much more direct, does not require any external programs.
@@ -1149,7 +1153,11 @@ speed. With a prefix argument, force the caches to be
updated (e.g. to re-interpret the current directory).
Used non-interactively, arguments are optional: if given then TOPIC
-should be a topic string and non-nil RE-CACHE forces re-caching."
+should be a topic string and non-nil RE-CACHE forces re-caching.
+
+Note that `M-x woman' doesn’t yet support the latest features of
+modern man pages, so we recommend using `M-x man' if that is
+available on your system."
(interactive (list nil current-prefix-arg))
;; The following test is for non-interactive calls via emacsclient, etc.
(if (or (not (stringp topic)) (string-match-p "\\S " topic))
@@ -1338,8 +1346,8 @@ PATH-DIRS should be a list of general manual directories (like
manual directory regexps (like `woman-path').
Ignore any paths that are unreadable or not directories."
;; Allow each path to be a single string or a list of strings:
- (if (not (listp path-dirs)) (setq path-dirs (list path-dirs)))
- (if (not (listp path-regexps)) (setq path-regexps (list path-regexps)))
+ (setq path-dirs (ensure-list path-dirs))
+ (setq path-regexps (ensure-list path-regexps))
(let (head dirs path)
(dolist (dir path-dirs)
(when (consp dir)
@@ -2081,8 +2089,6 @@ European characters."
;;; The main decoding driver:
-(defvar font-lock-mode) ; for the compiler
-
(defun woman-decode-buffer ()
"Decode a buffer in UN*X man-page source format.
No external programs are used."
diff --git a/lisp/x-dnd.el b/lisp/x-dnd.el
index b87fc97f8fd..063b1dd6228 100644
--- a/lisp/x-dnd.el
+++ b/lisp/x-dnd.el
@@ -1,6 +1,6 @@
;;; x-dnd.el --- drag and drop support for X -*- lexical-binding: t; -*-
-;; Copyright (C) 2004-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2004-2024 Free Software Foundation, Inc.
;; Author: Jan Djärv <jan.h.d@swipnet.se>
;; Maintainer: emacs-devel@gnu.org
@@ -369,10 +369,9 @@ WINDOW is the window where the drop happened.
STRING is the uri-list as a string. The URIs are separated by \\r\\n."
(let ((uri-list (split-string string "[\0\r\n]" t))
retval)
- (dolist (bf uri-list)
- ;; If one URL is handled, treat as if the whole drop succeeded.
- (let ((did-action (dnd-handle-one-url window action bf)))
- (when did-action (setq retval did-action))))
+ (let ((did-action (dnd-handle-multiple-urls window uri-list
+ action)))
+ (when did-action (setq retval did-action)))
retval))
(defun x-dnd-handle-file-name (window action string)
@@ -383,17 +382,23 @@ STRING is the file names as a string, separated by nulls."
(coding (or file-name-coding-system
default-file-name-coding-system))
retval)
- (dolist (bf uri-list)
- ;; If one URL is handled, treat as if the whole drop succeeded.
- (if coding (setq bf (encode-coding-string bf coding)))
- (let* ((file-uri (concat "file://"
- (mapconcat 'url-hexify-string
- (split-string bf "/") "/")))
- (did-action (dnd-handle-one-url window action file-uri)))
- (when did-action (setq retval did-action))))
+ (let ((did-action
+ (dnd-handle-multiple-urls
+ window
+ (mapcar
+ (lambda (item)
+ (when coding
+ (setq item (encode-coding-string item
+ coding)))
+ (concat "file://"
+ (mapconcat 'url-hexify-string
+ (split-string item "/")
+ "/")))
+ uri-list)
+ action)))
+ (when did-action (setq retval did-action)))
retval))
-
(defun x-dnd-choose-type (types &optional known-types)
"Choose which type we want to receive for the drop.
TYPES are the types the source of the drop offers, a vector of type names
diff --git a/lisp/xdg.el b/lisp/xdg.el
index 43b29578976..4c675489400 100644
--- a/lisp/xdg.el
+++ b/lisp/xdg.el
@@ -1,6 +1,6 @@
;;; xdg.el --- XDG specification and standard support -*- lexical-binding: t -*-
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
;; Author: Mark Oteiza <mvoteiza@udel.edu>
;; Created: 27 January 2017
diff --git a/lisp/xml.el b/lisp/xml.el
index 5a7501dcf41..849377bb758 100644
--- a/lisp/xml.el
+++ b/lisp/xml.el
@@ -1,6 +1,6 @@
;;; xml.el --- XML parser -*- lexical-binding: t -*-
-;; Copyright (C) 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2000-2024 Free Software Foundation, Inc.
;; Author: Emmanuel Briot <briot@gnat.com>
;; Maintainer: Mark A. Hershberger <mah@everybody.org>
diff --git a/lisp/xt-mouse.el b/lisp/xt-mouse.el
index 4ccd35d5277..cd00467f14f 100644
--- a/lisp/xt-mouse.el
+++ b/lisp/xt-mouse.el
@@ -1,6 +1,6 @@
;;; xt-mouse.el --- support the mouse when emacs run in an xterm -*- lexical-binding: t -*-
-;; Copyright (C) 1994, 2000-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1994, 2000-2024 Free Software Foundation, Inc.
;; Author: Per Abrahamsen <abraham@dina.kvl.dk>
;; Keywords: mouse, terminals
@@ -63,9 +63,13 @@ https://invisible-island.net/xterm/ctlseqs/ctlseqs.html)."
(is-move (eq 'mouse-movement ev-command))
(is-down (string-match "down-" (symbol-name ev-command))))
- ;; Mouse events symbols must have an 'event-kind property with
- ;; the value 'mouse-click.
- (when ev-command (put ev-command 'event-kind 'mouse-click))
+ ;; Mouse events symbols must have an 'event-kind property set.
+ ;; Most of them use the value 'mouse-click, but 'mouse-movement has
+ ;; a different value. See head_table in keyboard.c. (bug#67457)
+ (when ev-command (put ev-command 'event-kind
+ (if (eq ev-command 'mouse-movement)
+ 'mouse-movement
+ 'mouse-click)))
(cond
((null event) nil) ;Unknown/bogus byte sequence!
diff --git a/lisp/xwidget.el b/lisp/xwidget.el
index 7daca81f9f7..cca01c8cb3a 100644
--- a/lisp/xwidget.el
+++ b/lisp/xwidget.el
@@ -1,6 +1,6 @@
;;; xwidget.el --- api functions for xwidgets -*- lexical-binding: t -*-
-;; Copyright (C) 2011-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2011-2024 Free Software Foundation, Inc.
;; Author: Joakim Verona <joakim@verona.se>
diff --git a/lisp/yank-media.el b/lisp/yank-media.el
index abc137d9c38..e33c36da5b6 100644
--- a/lisp/yank-media.el
+++ b/lisp/yank-media.el
@@ -1,6 +1,6 @@
;;; yank-media.el --- Yanking images and HTML -*- lexical-binding:t -*-
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
;; Author: Lars Ingebrigtsen <larsi@gnus.org>
;; Keywords: utility
diff --git a/lwlib/ChangeLog.1 b/lwlib/ChangeLog.1
index 460e73f4dcc..a033a797387 100644
--- a/lwlib/ChangeLog.1
+++ b/lwlib/ChangeLog.1
@@ -1964,7 +1964,7 @@
;; coding: utf-8
;; End:
- Copyright (C) 1995-1999, 2001-2023 Free Software Foundation, Inc.
+ Copyright (C) 1995-1999, 2001-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/lwlib/Makefile.in b/lwlib/Makefile.in
index 70f6cd17d78..fbb60b35b24 100644
--- a/lwlib/Makefile.in
+++ b/lwlib/Makefile.in
@@ -1,7 +1,7 @@
### @configure_input@
# Copyright (C) 1992, 1993 Lucid, Inc.
-# Copyright (C) 1994, 2001-2023 Free Software Foundation, Inc.
+# Copyright (C) 1994, 2001-2024 Free Software Foundation, Inc.
#
# This file is part of the Lucid Widget Library.
#
diff --git a/lwlib/deps.mk b/lwlib/deps.mk
index d55374d3023..20671375706 100644
--- a/lwlib/deps.mk
+++ b/lwlib/deps.mk
@@ -1,7 +1,7 @@
### deps.mk --- lwlib/Makefile fragment for GNU Emacs
# Copyright (C) 1992, 1993 Lucid, Inc.
-# Copyright (C) 1994, 2001-2023 Free Software Foundation, Inc.
+# Copyright (C) 1994, 2001-2024 Free Software Foundation, Inc.
#
# This file is part of the Lucid Widget Library.
#
diff --git a/lwlib/lwlib-Xaw.c b/lwlib/lwlib-Xaw.c
index f23576162c6..a700a5b168d 100644
--- a/lwlib/lwlib-Xaw.c
+++ b/lwlib/lwlib-Xaw.c
@@ -1,7 +1,7 @@
/* The lwlib interface to Athena widgets.
Copyright (C) 1993 Chuck Thompson <cthomp@cs.uiuc.edu>
-Copyright (C) 1994, 2001-2023 Free Software Foundation, Inc.
+Copyright (C) 1994, 2001-2024 Free Software Foundation, Inc.
This file is part of the Lucid Widget Library.
diff --git a/lwlib/lwlib-Xlw.c b/lwlib/lwlib-Xlw.c
index 03f5809ca37..40e079e08c4 100644
--- a/lwlib/lwlib-Xlw.c
+++ b/lwlib/lwlib-Xlw.c
@@ -1,7 +1,7 @@
/* The lwlib interface to "xlwmenu" menus.
Copyright (C) 1992 Lucid, Inc.
-Copyright (C) 1994, 2000-2023 Free Software Foundation, Inc.
+Copyright (C) 1994, 2000-2024 Free Software Foundation, Inc.
This file is part of the Lucid Widget Library.
diff --git a/lwlib/lwlib-Xm.c b/lwlib/lwlib-Xm.c
index 451b9a38746..dd3f63605a4 100644
--- a/lwlib/lwlib-Xm.c
+++ b/lwlib/lwlib-Xm.c
@@ -1,6 +1,6 @@
/* The lwlib interface to Motif widgets.
-Copyright (C) 1994-1997, 1999-2023 Free Software Foundation, Inc.
+Copyright (C) 1994-1997, 1999-2024 Free Software Foundation, Inc.
Copyright (C) 1992 Lucid, Inc.
This file is part of the Lucid Widget Library.
diff --git a/lwlib/lwlib-int.h b/lwlib/lwlib-int.h
index 09f674f75a8..897ecc16179 100644
--- a/lwlib/lwlib-int.h
+++ b/lwlib/lwlib-int.h
@@ -1,6 +1,6 @@
/*
Copyright (C) 1992 Lucid, Inc.
-Copyright (C) 2000-2023 Free Software Foundation, Inc.
+Copyright (C) 2000-2024 Free Software Foundation, Inc.
This file is part of the Lucid Widget Library.
diff --git a/lwlib/lwlib-utils.c b/lwlib/lwlib-utils.c
index f7606fa0361..b9478a885ee 100644
--- a/lwlib/lwlib-utils.c
+++ b/lwlib/lwlib-utils.c
@@ -1,7 +1,7 @@
/* Defines some widget utility functions.
Copyright (C) 1992 Lucid, Inc.
-Copyright (C) 1994, 2001-2023 Free Software Foundation, Inc.
+Copyright (C) 1994, 2001-2024 Free Software Foundation, Inc.
This file is part of the Lucid Widget Library.
diff --git a/lwlib/lwlib-widget.h b/lwlib/lwlib-widget.h
index 7c8af4286c1..3c7da530cb0 100644
--- a/lwlib/lwlib-widget.h
+++ b/lwlib/lwlib-widget.h
@@ -1,6 +1,6 @@
/*
Copyright (C) 1992, 1993 Lucid, Inc.
-Copyright (C) 1994, 1999-2023 Free Software Foundation, Inc.
+Copyright (C) 1994, 1999-2024 Free Software Foundation, Inc.
This file is part of the Lucid Widget Library.
diff --git a/lwlib/lwlib.c b/lwlib/lwlib.c
index cf519de8968..354faeed5b2 100644
--- a/lwlib/lwlib.c
+++ b/lwlib/lwlib.c
@@ -1,7 +1,7 @@
/* A general interface to the widgets of different toolkits.
Copyright (C) 1992, 1993 Lucid, Inc.
-Copyright (C) 1994-1996, 1999-2023 Free Software Foundation, Inc.
+Copyright (C) 1994-1996, 1999-2024 Free Software Foundation, Inc.
This file is part of the Lucid Widget Library.
diff --git a/lwlib/lwlib.h b/lwlib/lwlib.h
index 341d0a75428..ec990c98241 100644
--- a/lwlib/lwlib.h
+++ b/lwlib/lwlib.h
@@ -1,6 +1,6 @@
/*
Copyright (C) 1992, 1993 Lucid, Inc.
-Copyright (C) 1994, 1999-2023 Free Software Foundation, Inc.
+Copyright (C) 1994, 1999-2024 Free Software Foundation, Inc.
This file is part of the Lucid Widget Library.
diff --git a/lwlib/xlwmenu.c b/lwlib/xlwmenu.c
index 84d41bd8e01..0f8f94b803c 100644
--- a/lwlib/xlwmenu.c
+++ b/lwlib/xlwmenu.c
@@ -1,7 +1,7 @@
/* Implements a lightweight menubar widget.
Copyright (C) 1992 Lucid, Inc.
-Copyright (C) 1994-1995, 1997, 1999-2023 Free Software Foundation, Inc.
+Copyright (C) 1994-1995, 1997, 1999-2024 Free Software Foundation, Inc.
This file is part of the Lucid Widget Library.
diff --git a/lwlib/xlwmenu.h b/lwlib/xlwmenu.h
index 6b59b945ce3..ce54ed04461 100644
--- a/lwlib/xlwmenu.h
+++ b/lwlib/xlwmenu.h
@@ -1,6 +1,6 @@
/* Interface of a lightweight menubar widget.
-Copyright (C) 2002-2023 Free Software Foundation, Inc.
+Copyright (C) 2002-2024 Free Software Foundation, Inc.
Copyright (C) 1992 Lucid, Inc.
This file is part of the Lucid Widget Library.
diff --git a/lwlib/xlwmenuP.h b/lwlib/xlwmenuP.h
index a05d202fb7f..869c3502341 100644
--- a/lwlib/xlwmenuP.h
+++ b/lwlib/xlwmenuP.h
@@ -1,6 +1,6 @@
/* Internals of a lightweight menubar widget.
-Copyright (C) 2002-2023 Free Software Foundation, Inc.
+Copyright (C) 2002-2024 Free Software Foundation, Inc.
Copyright (C) 1992 Lucid, Inc.
This file is part of the Lucid Widget Library.
diff --git a/m4/00gnulib.m4 b/m4/00gnulib.m4
index 7fe03e0b9c0..3448c40bbd6 100644
--- a/m4/00gnulib.m4
+++ b/m4/00gnulib.m4
@@ -1,5 +1,5 @@
# 00gnulib.m4 serial 8
-dnl Copyright (C) 2009-2023 Free Software Foundation, Inc.
+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,
dnl with or without modifications, as long as this notice is preserved.
diff --git a/m4/__inline.m4 b/m4/__inline.m4
index acf8668bc58..992e16f4ea7 100644
--- a/m4/__inline.m4
+++ b/m4/__inline.m4
@@ -1,5 +1,5 @@
# Test for __inline keyword
-dnl Copyright 2017-2023 Free Software Foundation, Inc.
+dnl Copyright 2017-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.
diff --git a/m4/absolute-header.m4 b/m4/absolute-header.m4
index e7947648881..aa7d0dac6da 100644
--- a/m4/absolute-header.m4
+++ b/m4/absolute-header.m4
@@ -1,5 +1,5 @@
# absolute-header.m4 serial 17
-dnl Copyright (C) 2006-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2006-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.
diff --git a/m4/acl.m4 b/m4/acl.m4
index 38b1dc66212..199bf67cbc5 100644
--- a/m4/acl.m4
+++ b/m4/acl.m4
@@ -1,7 +1,7 @@
# acl.m4 - check for access control list (ACL) primitives
# serial 29
-# Copyright (C) 2002, 2004-2023 Free Software Foundation, Inc.
+# Copyright (C) 2002, 2004-2024 Free Software Foundation, Inc.
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
diff --git a/m4/alloca.m4 b/m4/alloca.m4
index c685fac918a..911a003a04f 100644
--- a/m4/alloca.m4
+++ b/m4/alloca.m4
@@ -1,6 +1,6 @@
# alloca.m4 serial 21
-dnl Copyright (C) 2002-2004, 2006-2007, 2009-2023 Free Software Foundation,
-dnl Inc.
+dnl Copyright (C) 2002-2004, 2006-2007, 2009-2024 Free Software
+dnl 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.
diff --git a/m4/assert_h.m4 b/m4/assert_h.m4
index d255855d313..a73e45f0641 100644
--- a/m4/assert_h.m4
+++ b/m4/assert_h.m4
@@ -1,5 +1,5 @@
# assert-h.m4
-dnl Copyright (C) 2011-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2011-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.
diff --git a/m4/builtin-expect.m4 b/m4/builtin-expect.m4
index 531ed48af7f..8faffc50354 100644
--- a/m4/builtin-expect.m4
+++ b/m4/builtin-expect.m4
@@ -1,6 +1,6 @@
dnl Check for __builtin_expect.
-dnl Copyright 2016-2023 Free Software Foundation, Inc.
+dnl Copyright 2016-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.
diff --git a/m4/byteswap.m4 b/m4/byteswap.m4
index 8058d178bce..5493d901916 100644
--- a/m4/byteswap.m4
+++ b/m4/byteswap.m4
@@ -1,5 +1,5 @@
# byteswap.m4 serial 5
-dnl Copyright (C) 2005, 2007, 2009-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2005, 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,
dnl with or without modifications, as long as this notice is preserved.
diff --git a/m4/c-bool.m4 b/m4/c-bool.m4
index f614371bb28..44fba3c012f 100644
--- a/m4/c-bool.m4
+++ b/m4/c-bool.m4
@@ -1,6 +1,6 @@
# Check for bool that conforms to C2023.
-dnl Copyright 2022-2023 Free Software Foundation, Inc.
+dnl Copyright 2022-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.
diff --git a/m4/canonicalize.m4 b/m4/canonicalize.m4
index d319645fd3f..a5831bb4b62 100644
--- a/m4/canonicalize.m4
+++ b/m4/canonicalize.m4
@@ -1,6 +1,6 @@
# canonicalize.m4 serial 38
-dnl Copyright (C) 2003-2007, 2009-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 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,
diff --git a/m4/clock_time.m4 b/m4/clock_time.m4
index 28534db1c76..369e1412ec6 100644
--- a/m4/clock_time.m4
+++ b/m4/clock_time.m4
@@ -1,5 +1,5 @@
# clock_time.m4 serial 13
-dnl Copyright (C) 2002-2006, 2009-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2002-2006, 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.
diff --git a/m4/codeset.m4 b/m4/codeset.m4
index 5804f472e9a..0b01779abc9 100644
--- a/m4/codeset.m4
+++ b/m4/codeset.m4
@@ -1,6 +1,6 @@
# codeset.m4 serial 5 (gettext-0.18.2)
-dnl Copyright (C) 2000-2002, 2006, 2008-2014, 2016, 2019-2023 Free Software
-dnl Foundation, Inc.
+dnl Copyright (C) 2000-2002, 2006, 2008-2014, 2016, 2019-2024 Free
+dnl 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.
diff --git a/m4/copy-file-range.m4 b/m4/copy-file-range.m4
index fa6ab341091..e9198549510 100644
--- a/m4/copy-file-range.m4
+++ b/m4/copy-file-range.m4
@@ -1,5 +1,5 @@
# copy-file-range.m4
-dnl Copyright 2019-2023 Free Software Foundation, Inc.
+dnl Copyright 2019-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.
diff --git a/m4/d-type.m4 b/m4/d-type.m4
index 3f63bbe78ee..13bab57a3a5 100644
--- a/m4/d-type.m4
+++ b/m4/d-type.m4
@@ -5,7 +5,8 @@ dnl
dnl Check whether struct dirent has a member named d_type.
dnl
-# Copyright (C) 1997, 1999-2004, 2006, 2009-2023 Free Software Foundation, Inc.
+# Copyright (C) 1997, 1999-2004, 2006, 2009-2024 Free Software
+# Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
diff --git a/m4/dirent_h.m4 b/m4/dirent_h.m4
index b6c189c0d9f..1e55f025d28 100644
--- a/m4/dirent_h.m4
+++ b/m4/dirent_h.m4
@@ -1,5 +1,5 @@
# dirent_h.m4 serial 20
-dnl Copyright (C) 2008-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 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.
diff --git a/m4/dirfd.m4 b/m4/dirfd.m4
index 7968b1287ce..6578dc0232b 100644
--- a/m4/dirfd.m4
+++ b/m4/dirfd.m4
@@ -2,7 +2,7 @@
dnl Find out how to get the file descriptor associated with an open DIR*.
-# Copyright (C) 2001-2006, 2008-2023 Free Software Foundation, Inc.
+# Copyright (C) 2001-2006, 2008-2024 Free Software Foundation, Inc.
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
diff --git a/m4/double-slash-root.m4 b/m4/double-slash-root.m4
index 1776e5eb75d..00f23a70b0c 100644
--- a/m4/double-slash-root.m4
+++ b/m4/double-slash-root.m4
@@ -1,5 +1,5 @@
# double-slash-root.m4 serial 4 -*- Autoconf -*-
-dnl Copyright (C) 2006, 2008-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2006, 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.
diff --git a/m4/dup2.m4 b/m4/dup2.m4
index e1cc73e18db..1833ff0ec17 100644
--- a/m4/dup2.m4
+++ b/m4/dup2.m4
@@ -1,5 +1,6 @@
#serial 27
-dnl Copyright (C) 2002, 2005, 2007, 2009-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2002, 2005, 2007, 2009-2024 Free Software Foundation,
+dnl 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.
diff --git a/m4/eealloc.m4 b/m4/eealloc.m4
index cb3e08fe53a..d8862a1e0f3 100644
--- a/m4/eealloc.m4
+++ b/m4/eealloc.m4
@@ -1,5 +1,5 @@
# eealloc.m4 serial 3
-dnl Copyright (C) 2003, 2009-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2003, 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.
diff --git a/m4/environ.m4 b/m4/environ.m4
index 741dfc56a1e..5b9e06b0088 100644
--- a/m4/environ.m4
+++ b/m4/environ.m4
@@ -1,5 +1,5 @@
# environ.m4 serial 8
-dnl Copyright (C) 2001-2004, 2006-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2001-2004, 2006-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.
diff --git a/m4/errno_h.m4 b/m4/errno_h.m4
index 4c70d225289..8900d6c7257 100644
--- a/m4/errno_h.m4
+++ b/m4/errno_h.m4
@@ -1,5 +1,5 @@
# errno_h.m4 serial 14
-dnl Copyright (C) 2004, 2006, 2008-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2004, 2006, 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.
diff --git a/m4/euidaccess.m4 b/m4/euidaccess.m4
index 7429779c152..e3d828f6ca5 100644
--- a/m4/euidaccess.m4
+++ b/m4/euidaccess.m4
@@ -1,5 +1,5 @@
# euidaccess.m4 serial 17
-dnl Copyright (C) 2002-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2002-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.
diff --git a/m4/execinfo.m4 b/m4/execinfo.m4
index 269e697a45a..a76c33525e6 100644
--- a/m4/execinfo.m4
+++ b/m4/execinfo.m4
@@ -1,6 +1,6 @@
# Check for GNU-style execinfo.h.
-dnl Copyright 2012-2023 Free Software Foundation, Inc.
+dnl Copyright 2012-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.
diff --git a/m4/explicit_bzero.m4 b/m4/explicit_bzero.m4
index aa74bea3d26..59576b7e018 100644
--- a/m4/explicit_bzero.m4
+++ b/m4/explicit_bzero.m4
@@ -1,4 +1,4 @@
-dnl Copyright 2017-2023 Free Software Foundation, Inc.
+dnl Copyright 2017-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.
diff --git a/m4/extensions.m4 b/m4/extensions.m4
index 5336b8daf7e..6fc2e300e0a 100644
--- a/m4/extensions.m4
+++ b/m4/extensions.m4
@@ -1,7 +1,7 @@
# serial 23 -*- Autoconf -*-
# Enable extensions on systems that normally disable them.
-# Copyright (C) 2003, 2006-2023 Free Software Foundation, Inc.
+# Copyright (C) 2003, 2006-2024 Free Software Foundation, Inc.
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
diff --git a/m4/extern-inline.m4 b/m4/extern-inline.m4
index f9894d7fe5c..680250ec774 100644
--- a/m4/extern-inline.m4
+++ b/m4/extern-inline.m4
@@ -1,6 +1,6 @@
dnl 'extern inline' a la ISO C99.
-dnl Copyright 2012-2023 Free Software Foundation, Inc.
+dnl Copyright 2012-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.
diff --git a/m4/faccessat.m4 b/m4/faccessat.m4
index a858bfee33d..b8c058cef28 100644
--- a/m4/faccessat.m4
+++ b/m4/faccessat.m4
@@ -1,7 +1,7 @@
# serial 12
# See if we need to provide faccessat replacement.
-dnl Copyright (C) 2009-2023 Free Software Foundation, Inc.
+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,
dnl with or without modifications, as long as this notice is preserved.
diff --git a/m4/fchmodat.m4 b/m4/fchmodat.m4
index 5356da40bae..9750572a5a3 100644
--- a/m4/fchmodat.m4
+++ b/m4/fchmodat.m4
@@ -1,5 +1,5 @@
# fchmodat.m4 serial 8
-dnl Copyright (C) 2004-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2004-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.
diff --git a/m4/fcntl.m4 b/m4/fcntl.m4
index 524a99af80a..02b93f8357c 100644
--- a/m4/fcntl.m4
+++ b/m4/fcntl.m4
@@ -1,5 +1,5 @@
# fcntl.m4 serial 11
-dnl Copyright (C) 2009-2023 Free Software Foundation, Inc.
+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,
dnl with or without modifications, as long as this notice is preserved.
diff --git a/m4/fcntl_h.m4 b/m4/fcntl_h.m4
index 68f4e648021..ba4eb4494db 100644
--- a/m4/fcntl_h.m4
+++ b/m4/fcntl_h.m4
@@ -1,6 +1,6 @@
# serial 20
# Configure fcntl.h.
-dnl Copyright (C) 2006-2007, 2009-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2006-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,
dnl with or without modifications, as long as this notice is preserved.
diff --git a/m4/fdopendir.m4 b/m4/fdopendir.m4
index dfcc46c03e2..bf361ff154c 100644
--- a/m4/fdopendir.m4
+++ b/m4/fdopendir.m4
@@ -1,7 +1,7 @@
# serial 15
# See if we need to provide fdopendir.
-dnl Copyright (C) 2009-2023 Free Software Foundation, Inc.
+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,
dnl with or without modifications, as long as this notice is preserved.
diff --git a/m4/filemode.m4 b/m4/filemode.m4
index 3cafc5cd1e1..3dd40f44b8b 100644
--- a/m4/filemode.m4
+++ b/m4/filemode.m4
@@ -1,5 +1,6 @@
# filemode.m4 serial 9
-dnl Copyright (C) 2002, 2005-2006, 2009-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2002, 2005-2006, 2009-2024 Free Software Foundation,
+dnl 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.
diff --git a/m4/flexmember.m4 b/m4/flexmember.m4
index 13f7e870d31..9df6c03cd3b 100644
--- a/m4/flexmember.m4
+++ b/m4/flexmember.m4
@@ -1,7 +1,7 @@
# serial 5
# Check for flexible array member support.
-# Copyright (C) 2006, 2009-2023 Free Software Foundation, Inc.
+# Copyright (C) 2006, 2009-2024 Free Software Foundation, Inc.
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
diff --git a/m4/fpending.m4 b/m4/fpending.m4
index 6991f81066d..05064b851ec 100644
--- a/m4/fpending.m4
+++ b/m4/fpending.m4
@@ -1,6 +1,6 @@
# serial 23
-# Copyright (C) 2000-2001, 2004-2023 Free Software Foundation, Inc.
+# Copyright (C) 2000-2001, 2004-2024 Free Software Foundation, Inc.
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
diff --git a/m4/fpieee.m4 b/m4/fpieee.m4
index 706b33141d3..239cf4a7e2d 100644
--- a/m4/fpieee.m4
+++ b/m4/fpieee.m4
@@ -1,5 +1,5 @@
# fpieee.m4 serial 2 -*- coding: utf-8 -*-
-dnl Copyright (C) 2007, 2009-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 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,
dnl with or without modifications, as long as this notice is preserved.
diff --git a/m4/free.m4 b/m4/free.m4
index 0389dea3f49..4f6dc2e256d 100644
--- a/m4/free.m4
+++ b/m4/free.m4
@@ -1,5 +1,5 @@
# free.m4 serial 6
-# Copyright (C) 2003-2005, 2009-2023 Free Software Foundation, Inc.
+# Copyright (C) 2003-2005, 2009-2024 Free Software Foundation, Inc.
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
diff --git a/m4/fstatat.m4 b/m4/fstatat.m4
index 083076911ff..1b5e5f19276 100644
--- a/m4/fstatat.m4
+++ b/m4/fstatat.m4
@@ -1,5 +1,5 @@
# fstatat.m4 serial 4
-dnl Copyright (C) 2004-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2004-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.
diff --git a/m4/fsusage.m4 b/m4/fsusage.m4
index 724a863ac30..9a81dabe34c 100644
--- a/m4/fsusage.m4
+++ b/m4/fsusage.m4
@@ -1,7 +1,8 @@
# serial 35
# Obtaining file system usage information.
-# Copyright (C) 1997-1998, 2000-2001, 2003-2023 Free Software Foundation, Inc.
+# Copyright (C) 1997-1998, 2000-2001, 2003-2024 Free Software
+# Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
diff --git a/m4/fsync.m4 b/m4/fsync.m4
index 857e495506f..08e3db8931e 100644
--- a/m4/fsync.m4
+++ b/m4/fsync.m4
@@ -1,5 +1,5 @@
# fsync.m4 serial 2
-dnl Copyright (C) 2008-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 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.
diff --git a/m4/futimens.m4 b/m4/futimens.m4
index dc0b21b9d51..ac961e7bde5 100644
--- a/m4/futimens.m4
+++ b/m4/futimens.m4
@@ -1,7 +1,7 @@
# serial 11
# See if we need to provide futimens replacement.
-dnl Copyright (C) 2009-2023 Free Software Foundation, Inc.
+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,
dnl with or without modifications, as long as this notice is preserved.
diff --git a/m4/getdelim.m4 b/m4/getdelim.m4
index 60555b9718b..0dbd8bc6f8b 100644
--- a/m4/getdelim.m4
+++ b/m4/getdelim.m4
@@ -1,6 +1,6 @@
# getdelim.m4 serial 19
-dnl Copyright (C) 2005-2007, 2009-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2005-2007, 2009-2024 Free Software Foundation, Inc.
dnl
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
diff --git a/m4/getdtablesize.m4 b/m4/getdtablesize.m4
index 8bcda9053b6..3b89456baf9 100644
--- a/m4/getdtablesize.m4
+++ b/m4/getdtablesize.m4
@@ -1,5 +1,5 @@
# getdtablesize.m4 serial 8
-dnl Copyright (C) 2008-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 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.
diff --git a/m4/getgroups.m4 b/m4/getgroups.m4
index 241fec88e3c..5062278b335 100644
--- a/m4/getgroups.m4
+++ b/m4/getgroups.m4
@@ -3,7 +3,8 @@
dnl From Jim Meyering.
dnl A wrapper around AC_FUNC_GETGROUPS.
-# Copyright (C) 1996-1997, 1999-2004, 2008-2023 Free Software Foundation, Inc.
+# Copyright (C) 1996-1997, 1999-2004, 2008-2024 Free Software
+# Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
diff --git a/m4/getline.m4 b/m4/getline.m4
index 83e7e9315f6..d0e285dbc9f 100644
--- a/m4/getline.m4
+++ b/m4/getline.m4
@@ -1,7 +1,7 @@
# getline.m4 serial 33
-dnl Copyright (C) 1998-2003, 2005-2007, 2009-2023 Free Software Foundation,
-dnl Inc.
+dnl Copyright (C) 1998-2003, 2005-2007, 2009-2024 Free Software
+dnl Foundation, Inc.
dnl
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
diff --git a/m4/getloadavg.m4 b/m4/getloadavg.m4
index ee83b32f1e0..d25a594b215 100644
--- a/m4/getloadavg.m4
+++ b/m4/getloadavg.m4
@@ -1,7 +1,7 @@
# Check for getloadavg.
-# Copyright (C) 1992-1996, 1999-2000, 2002-2003, 2006, 2008-2023 Free Software
-# Foundation, Inc.
+# Copyright (C) 1992-1996, 1999-2000, 2002-2003, 2006, 2008-2024 Free
+# Software Foundation, Inc.
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
diff --git a/m4/getopt.m4 b/m4/getopt.m4
index 7981a09552b..cc0356390ba 100644
--- a/m4/getopt.m4
+++ b/m4/getopt.m4
@@ -1,5 +1,5 @@
# getopt.m4 serial 48
-dnl Copyright (C) 2002-2006, 2008-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2002-2006, 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.
diff --git a/m4/getrandom.m4 b/m4/getrandom.m4
index 7b7f9ce2ee8..6ddaed2d569 100644
--- a/m4/getrandom.m4
+++ b/m4/getrandom.m4
@@ -1,5 +1,5 @@
# getrandom.m4 serial 11
-dnl Copyright 2020-2023 Free Software Foundation, Inc.
+dnl Copyright 2020-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.
diff --git a/m4/gettime.m4 b/m4/gettime.m4
index ec1f97ee0d5..61fdbb35d46 100644
--- a/m4/gettime.m4
+++ b/m4/gettime.m4
@@ -1,5 +1,6 @@
# gettime.m4 serial 14
-dnl Copyright (C) 2002, 2004-2006, 2009-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2002, 2004-2006, 2009-2024 Free Software Foundation,
+dnl 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.
diff --git a/m4/gettimeofday.m4 b/m4/gettimeofday.m4
index 5051d61cc87..6c2f8583603 100644
--- a/m4/gettimeofday.m4
+++ b/m4/gettimeofday.m4
@@ -1,6 +1,7 @@
# serial 29
-# Copyright (C) 2001-2003, 2005, 2007, 2009-2023 Free Software Foundation, Inc.
+# Copyright (C) 2001-2003, 2005, 2007, 2009-2024 Free Software
+# Foundation, Inc.
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
diff --git a/m4/gnulib-common.m4 b/m4/gnulib-common.m4
index 2426eb63985..db0c8853d73 100644
--- a/m4/gnulib-common.m4
+++ b/m4/gnulib-common.m4
@@ -1,5 +1,5 @@
# gnulib-common.m4 serial 87
-dnl Copyright (C) 2007-2023 Free Software Foundation, Inc.
+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.
diff --git a/m4/gnulib-comp.m4 b/m4/gnulib-comp.m4
index 14ff92040a4..f3ac7cc2409 100644
--- a/m4/gnulib-comp.m4
+++ b/m4/gnulib-comp.m4
@@ -1,5 +1,5 @@
# DO NOT EDIT! GENERATED AUTOMATICALLY!
-# Copyright (C) 2002-2023 Free Software Foundation, Inc.
+# Copyright (C) 2002-2024 Free Software Foundation, Inc.
#
# This file is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
diff --git a/m4/group-member.m4 b/m4/group-member.m4
index 7c56ee3de7d..e058ace62b9 100644
--- a/m4/group-member.m4
+++ b/m4/group-member.m4
@@ -1,6 +1,7 @@
# serial 14
-# Copyright (C) 1999-2001, 2003-2007, 2009-2023 Free Software Foundation, Inc.
+# Copyright (C) 1999-2001, 2003-2007, 2009-2024 Free Software
+# Foundation, Inc.
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
diff --git a/m4/ieee754-h.m4 b/m4/ieee754-h.m4
index 73a8f8350b6..cc8ef32bd32 100644
--- a/m4/ieee754-h.m4
+++ b/m4/ieee754-h.m4
@@ -1,6 +1,6 @@
# Configure ieee754-h module
-dnl Copyright 2018-2023 Free Software Foundation, Inc.
+dnl Copyright 2018-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.
diff --git a/m4/include_next.m4 b/m4/include_next.m4
index 9f19215ef05..8a1c52c8564 100644
--- a/m4/include_next.m4
+++ b/m4/include_next.m4
@@ -1,5 +1,5 @@
# include_next.m4 serial 26
-dnl Copyright (C) 2006-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2006-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.
diff --git a/m4/inttypes.m4 b/m4/inttypes.m4
index e7efbe94167..6abf9dbe280 100644
--- a/m4/inttypes.m4
+++ b/m4/inttypes.m4
@@ -1,5 +1,5 @@
# inttypes.m4 serial 37
-dnl Copyright (C) 2006-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2006-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.
diff --git a/m4/largefile.m4 b/m4/largefile.m4
index 8b051c0042b..2ac98cc8c93 100644
--- a/m4/largefile.m4
+++ b/m4/largefile.m4
@@ -1,7 +1,7 @@
# Enable large files on systems where this is not the default.
# Enable support for files on Linux file systems with 64-bit inode numbers.
-# Copyright 1992-1996, 1998-2023 Free Software Foundation, Inc.
+# Copyright 1992-1996, 1998-2024 Free Software Foundation, Inc.
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
diff --git a/m4/lchmod.m4 b/m4/lchmod.m4
index a1370e163fb..7b263a241eb 100644
--- a/m4/lchmod.m4
+++ b/m4/lchmod.m4
@@ -1,6 +1,6 @@
#serial 10
-dnl Copyright (C) 2005-2006, 2008-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2005-2006, 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.
diff --git a/m4/libgmp.m4 b/m4/libgmp.m4
index eb20ada0fa5..782dfbae2e1 100644
--- a/m4/libgmp.m4
+++ b/m4/libgmp.m4
@@ -1,6 +1,6 @@
# libgmp.m4 serial 8
# Configure the GMP library or a replacement.
-dnl Copyright 2020-2023 Free Software Foundation, Inc.
+dnl Copyright 2020-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.
diff --git a/m4/limits-h.m4 b/m4/limits-h.m4
index 6a5983ebc25..1825328380b 100644
--- a/m4/limits-h.m4
+++ b/m4/limits-h.m4
@@ -1,6 +1,6 @@
dnl Check whether limits.h has needed features.
-dnl Copyright 2016-2023 Free Software Foundation, Inc.
+dnl Copyright 2016-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.
diff --git a/m4/lstat.m4 b/m4/lstat.m4
index 2bc46697934..d69b3b2182e 100644
--- a/m4/lstat.m4
+++ b/m4/lstat.m4
@@ -1,6 +1,6 @@
# serial 34
-# Copyright (C) 1997-2001, 2003-2023 Free Software Foundation, Inc.
+# Copyright (C) 1997-2001, 2003-2024 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
diff --git a/m4/malloc.m4 b/m4/malloc.m4
index bc580176f5f..770b1ba0ccd 100644
--- a/m4/malloc.m4
+++ b/m4/malloc.m4
@@ -1,5 +1,5 @@
# malloc.m4 serial 29
-dnl Copyright (C) 2007, 2009-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 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,
dnl with or without modifications, as long as this notice is preserved.
diff --git a/m4/manywarnings.m4 b/m4/manywarnings.m4
index a06f26f672e..4d44f3aa34d 100644
--- a/m4/manywarnings.m4
+++ b/m4/manywarnings.m4
@@ -1,5 +1,5 @@
# manywarnings.m4 serial 24
-dnl Copyright (C) 2008-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 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.
diff --git a/m4/mbstate_t.m4 b/m4/mbstate_t.m4
index dcd66b96131..b2bcba45e96 100644
--- a/m4/mbstate_t.m4
+++ b/m4/mbstate_t.m4
@@ -1,5 +1,5 @@
# mbstate_t.m4 serial 14
-dnl Copyright (C) 2000-2002, 2008-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2000-2002, 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.
diff --git a/m4/md5.m4 b/m4/md5.m4
index 678489e5c5b..7af56a8a3d1 100644
--- a/m4/md5.m4
+++ b/m4/md5.m4
@@ -1,5 +1,5 @@
# md5.m4 serial 14
-dnl Copyright (C) 2002-2006, 2008-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2002-2006, 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.
diff --git a/m4/memmem.m4 b/m4/memmem.m4
index 3cf46bc2e9c..7985266f8b7 100644
--- a/m4/memmem.m4
+++ b/m4/memmem.m4
@@ -1,5 +1,5 @@
# memmem.m4 serial 29
-dnl Copyright (C) 2002-2004, 2007-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2002-2004, 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.
diff --git a/m4/mempcpy.m4 b/m4/mempcpy.m4
index 612b77b3c11..375b3b4cda9 100644
--- a/m4/mempcpy.m4
+++ b/m4/mempcpy.m4
@@ -1,6 +1,6 @@
# mempcpy.m4 serial 14
-dnl Copyright (C) 2003-2004, 2006-2007, 2009-2023 Free Software Foundation,
-dnl Inc.
+dnl Copyright (C) 2003-2004, 2006-2007, 2009-2024 Free Software
+dnl 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.
diff --git a/m4/memrchr.m4 b/m4/memrchr.m4
index 7611ac7e3ac..21604f0ef94 100644
--- a/m4/memrchr.m4
+++ b/m4/memrchr.m4
@@ -1,6 +1,6 @@
# memrchr.m4 serial 11
-dnl Copyright (C) 2002-2003, 2005-2007, 2009-2023 Free Software Foundation,
-dnl Inc.
+dnl Copyright (C) 2002-2003, 2005-2007, 2009-2024 Free Software
+dnl 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.
diff --git a/m4/memset_explicit.m4 b/m4/memset_explicit.m4
index 9dcd89a758a..6ac798d4557 100644
--- a/m4/memset_explicit.m4
+++ b/m4/memset_explicit.m4
@@ -1,4 +1,4 @@
-dnl Copyright 2022-2023 Free Software Foundation, Inc.
+dnl Copyright 2022-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.
diff --git a/m4/minmax.m4 b/m4/minmax.m4
index fd09846ffb3..5c0a927da66 100644
--- a/m4/minmax.m4
+++ b/m4/minmax.m4
@@ -1,5 +1,5 @@
# minmax.m4 serial 4
-dnl Copyright (C) 2005, 2009-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2005, 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.
diff --git a/m4/mkostemp.m4 b/m4/mkostemp.m4
index 1b0d0d55946..1c22b8d51b4 100644
--- a/m4/mkostemp.m4
+++ b/m4/mkostemp.m4
@@ -1,5 +1,5 @@
# mkostemp.m4 serial 4
-dnl Copyright (C) 2009-2023 Free Software Foundation, Inc.
+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,
dnl with or without modifications, as long as this notice is preserved.
diff --git a/m4/mktime.m4 b/m4/mktime.m4
index 69cce86da5a..a4aeb9f76ba 100644
--- a/m4/mktime.m4
+++ b/m4/mktime.m4
@@ -1,6 +1,6 @@
# serial 38
-dnl Copyright (C) 2002-2003, 2005-2007, 2009-2023 Free Software Foundation,
-dnl Inc.
+dnl Copyright (C) 2002-2003, 2005-2007, 2009-2024 Free Software
+dnl 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.
diff --git a/m4/mode_t.m4 b/m4/mode_t.m4
index 82197c0214a..af88da51285 100644
--- a/m4/mode_t.m4
+++ b/m4/mode_t.m4
@@ -1,5 +1,5 @@
# mode_t.m4 serial 2
-dnl Copyright (C) 2009-2023 Free Software Foundation, Inc.
+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,
dnl with or without modifications, as long as this notice is preserved.
diff --git a/m4/multiarch.m4 b/m4/multiarch.m4
index 3ba5b0f76c6..5f8339f5c7d 100644
--- a/m4/multiarch.m4
+++ b/m4/multiarch.m4
@@ -1,5 +1,5 @@
# multiarch.m4 serial 9
-dnl Copyright (C) 2008-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 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.
diff --git a/m4/musl.m4 b/m4/musl.m4
index e28a3fed677..34d2c1ff22a 100644
--- a/m4/musl.m4
+++ b/m4/musl.m4
@@ -1,5 +1,5 @@
# musl.m4 serial 4
-dnl Copyright (C) 2019-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2019-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.
diff --git a/m4/nanosleep.m4 b/m4/nanosleep.m4
index b7f22d7b606..ad3f68cb75b 100644
--- a/m4/nanosleep.m4
+++ b/m4/nanosleep.m4
@@ -5,7 +5,7 @@ dnl Check for the nanosleep function.
dnl If not found, use the supplied replacement.
dnl
-# Copyright (C) 1999-2001, 2003-2023 Free Software Foundation, Inc.
+# Copyright (C) 1999-2001, 2003-2024 Free Software Foundation, Inc.
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
diff --git a/m4/ndk-build.m4 b/m4/ndk-build.m4
index ab4e88ca168..aacb2ed048b 100644
--- a/m4/ndk-build.m4
+++ b/m4/ndk-build.m4
@@ -1,4 +1,4 @@
-dnl Copyright (C) 2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2023-2024 Free Software Foundation, Inc.
dnl This file is part of GNU Emacs.
dnl GNU Emacs is free software: you can redistribute it and/or modify
diff --git a/m4/nocrash.m4 b/m4/nocrash.m4
index 6a766387618..9730fc09034 100644
--- a/m4/nocrash.m4
+++ b/m4/nocrash.m4
@@ -1,5 +1,5 @@
# nocrash.m4 serial 5
-dnl Copyright (C) 2005, 2009-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2005, 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.
diff --git a/m4/nproc.m4 b/m4/nproc.m4
index c892ad74b7d..e4065776a86 100644
--- a/m4/nproc.m4
+++ b/m4/nproc.m4
@@ -1,5 +1,5 @@
# nproc.m4 serial 6
-dnl Copyright (C) 2009-2023 Free Software Foundation, Inc.
+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,
dnl with or without modifications, as long as this notice is preserved.
diff --git a/m4/nstrftime.m4 b/m4/nstrftime.m4
index 04c0b63fbd0..01725b2a331 100644
--- a/m4/nstrftime.m4
+++ b/m4/nstrftime.m4
@@ -1,6 +1,7 @@
# serial 37
-# Copyright (C) 1996-1997, 1999-2007, 2009-2023 Free Software Foundation, Inc.
+# Copyright (C) 1996-1997, 1999-2007, 2009-2024 Free Software
+# Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
diff --git a/m4/off_t.m4 b/m4/off_t.m4
index 880f347250a..f3259f9c245 100644
--- a/m4/off_t.m4
+++ b/m4/off_t.m4
@@ -1,5 +1,5 @@
# off_t.m4 serial 1
-dnl Copyright (C) 2012-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2012-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.
diff --git a/m4/open-cloexec.m4 b/m4/open-cloexec.m4
index fd572fcd1de..a2d50329b97 100644
--- a/m4/open-cloexec.m4
+++ b/m4/open-cloexec.m4
@@ -1,6 +1,6 @@
# Test whether O_CLOEXEC is defined.
-dnl Copyright 2017-2023 Free Software Foundation, Inc.
+dnl Copyright 2017-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.
diff --git a/m4/open-slash.m4 b/m4/open-slash.m4
index 1f731f8ad80..45310c0c581 100644
--- a/m4/open-slash.m4
+++ b/m4/open-slash.m4
@@ -1,5 +1,5 @@
# open-slash.m4 serial 2
-dnl Copyright (C) 2007-2023 Free Software Foundation, Inc.
+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.
diff --git a/m4/open.m4 b/m4/open.m4
index 94fa2bb7530..edbd8b93c83 100644
--- a/m4/open.m4
+++ b/m4/open.m4
@@ -1,5 +1,5 @@
# open.m4 serial 15
-dnl Copyright (C) 2007-2023 Free Software Foundation, Inc.
+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.
diff --git a/m4/pathmax.m4 b/m4/pathmax.m4
index 6d47d2c026e..b7ce9ff1468 100644
--- a/m4/pathmax.m4
+++ b/m4/pathmax.m4
@@ -1,6 +1,6 @@
# pathmax.m4 serial 11
-dnl Copyright (C) 2002-2003, 2005-2006, 2009-2023 Free Software Foundation,
-dnl Inc.
+dnl Copyright (C) 2002-2003, 2005-2006, 2009-2024 Free Software
+dnl 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.
diff --git a/m4/pid_t.m4 b/m4/pid_t.m4
index 0fd7d0a1810..8f8d39d81db 100644
--- a/m4/pid_t.m4
+++ b/m4/pid_t.m4
@@ -1,5 +1,5 @@
# pid_t.m4 serial 4
-dnl Copyright (C) 2020-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2020-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.
diff --git a/m4/pipe2.m4 b/m4/pipe2.m4
index 79de69cd1a4..74b7b284b3e 100644
--- a/m4/pipe2.m4
+++ b/m4/pipe2.m4
@@ -1,5 +1,5 @@
# pipe2.m4 serial 4
-dnl Copyright (C) 2009-2023 Free Software Foundation, Inc.
+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,
dnl with or without modifications, as long as this notice is preserved.
diff --git a/m4/printf-posix-rpl.m4 b/m4/printf-posix-rpl.m4
index 36156d43502..0f741192499 100644
--- a/m4/printf-posix-rpl.m4
+++ b/m4/printf-posix-rpl.m4
@@ -1,5 +1,5 @@
# printf-posix-rpl.m4 serial 4
-dnl Copyright (C) 2007-2023 Free Software Foundation, Inc.
+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.
diff --git a/m4/pselect.m4 b/m4/pselect.m4
index 6c3d1b8f97f..005b722b965 100644
--- a/m4/pselect.m4
+++ b/m4/pselect.m4
@@ -1,5 +1,5 @@
# pselect.m4 serial 11
-dnl Copyright (C) 2011-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2011-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.
diff --git a/m4/pthread_sigmask.m4 b/m4/pthread_sigmask.m4
index 27795282bee..81be9611db2 100644
--- a/m4/pthread_sigmask.m4
+++ b/m4/pthread_sigmask.m4
@@ -1,5 +1,5 @@
# pthread_sigmask.m4 serial 22
-dnl Copyright (C) 2011-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2011-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.
diff --git a/m4/rawmemchr.m4 b/m4/rawmemchr.m4
index a48d829526f..57d1c2915e3 100644
--- a/m4/rawmemchr.m4
+++ b/m4/rawmemchr.m4
@@ -1,5 +1,5 @@
# rawmemchr.m4 serial 3
-dnl Copyright (C) 2003, 2007-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2003, 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.
diff --git a/m4/readlink.m4 b/m4/readlink.m4
index f1d41d2b113..6d78ec84a03 100644
--- a/m4/readlink.m4
+++ b/m4/readlink.m4
@@ -1,5 +1,5 @@
# readlink.m4 serial 17
-dnl Copyright (C) 2003, 2007, 2009-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 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,
dnl with or without modifications, as long as this notice is preserved.
diff --git a/m4/readlinkat.m4 b/m4/readlinkat.m4
index 5c513562919..99822102294 100644
--- a/m4/readlinkat.m4
+++ b/m4/readlinkat.m4
@@ -1,7 +1,7 @@
# serial 8
# See if we need to provide readlinkat replacement.
-dnl Copyright (C) 2009-2023 Free Software Foundation, Inc.
+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,
dnl with or without modifications, as long as this notice is preserved.
diff --git a/m4/readutmp.m4 b/m4/readutmp.m4
index 0a47f4bb77d..d458a8b554a 100644
--- a/m4/readutmp.m4
+++ b/m4/readutmp.m4
@@ -1,5 +1,5 @@
# readutmp.m4 serial 30
-dnl Copyright (C) 2002-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2002-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.
diff --git a/m4/realloc.m4 b/m4/realloc.m4
index 26053914cbe..7c769644a6e 100644
--- a/m4/realloc.m4
+++ b/m4/realloc.m4
@@ -1,5 +1,5 @@
# realloc.m4 serial 27
-dnl Copyright (C) 2007, 2009-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 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,
dnl with or without modifications, as long as this notice is preserved.
diff --git a/m4/regex.m4 b/m4/regex.m4
index 7acadc48343..7a43e1c9a26 100644
--- a/m4/regex.m4
+++ b/m4/regex.m4
@@ -1,6 +1,6 @@
# serial 74
-# Copyright (C) 1996-2001, 2003-2023 Free Software Foundation, Inc.
+# Copyright (C) 1996-2001, 2003-2024 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
diff --git a/m4/sha1.m4 b/m4/sha1.m4
index 16b79c0868b..c0a87536a5c 100644
--- a/m4/sha1.m4
+++ b/m4/sha1.m4
@@ -1,5 +1,5 @@
# sha1.m4 serial 12
-dnl Copyright (C) 2002-2006, 2008-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2002-2006, 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.
diff --git a/m4/sha256.m4 b/m4/sha256.m4
index 4d1d1dda158..2dd754c1778 100644
--- a/m4/sha256.m4
+++ b/m4/sha256.m4
@@ -1,5 +1,5 @@
# sha256.m4 serial 8
-dnl Copyright (C) 2005, 2008-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2005, 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.
diff --git a/m4/sha512.m4 b/m4/sha512.m4
index b66dc726d80..19d03b50271 100644
--- a/m4/sha512.m4
+++ b/m4/sha512.m4
@@ -1,5 +1,5 @@
# sha512.m4 serial 9
-dnl Copyright (C) 2005-2006, 2008-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2005-2006, 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.
diff --git a/m4/sig2str.m4 b/m4/sig2str.m4
index aee18efeefd..2cb77c58a46 100644
--- a/m4/sig2str.m4
+++ b/m4/sig2str.m4
@@ -1,5 +1,6 @@
# serial 7
-dnl Copyright (C) 2002, 2005-2006, 2009-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2002, 2005-2006, 2009-2024 Free Software Foundation,
+dnl 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.
diff --git a/m4/sigdescr_np.m4 b/m4/sigdescr_np.m4
index da44b432c00..d844e2f9db7 100644
--- a/m4/sigdescr_np.m4
+++ b/m4/sigdescr_np.m4
@@ -1,5 +1,5 @@
# sigdescr_np.m4 serial 2
-dnl Copyright (C) 2020-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2020-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.
diff --git a/m4/signal_h.m4 b/m4/signal_h.m4
index cdd6812f97c..6f7dcc733b4 100644
--- a/m4/signal_h.m4
+++ b/m4/signal_h.m4
@@ -1,5 +1,5 @@
# signal_h.m4 serial 22
-dnl Copyright (C) 2007-2023 Free Software Foundation, Inc.
+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.
diff --git a/m4/socklen.m4 b/m4/socklen.m4
index 1c63a85363e..9c46db18937 100644
--- a/m4/socklen.m4
+++ b/m4/socklen.m4
@@ -1,5 +1,5 @@
# socklen.m4 serial 11
-dnl Copyright (C) 2005-2007, 2009-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2005-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,
dnl with or without modifications, as long as this notice is preserved.
diff --git a/m4/ssize_t.m4 b/m4/ssize_t.m4
index 52bd77d2aeb..65c96fcf56b 100644
--- a/m4/ssize_t.m4
+++ b/m4/ssize_t.m4
@@ -1,5 +1,6 @@
# ssize_t.m4 serial 6
-dnl Copyright (C) 2001-2003, 2006, 2010-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2001-2003, 2006, 2010-2024 Free Software Foundation,
+dnl 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.
diff --git a/m4/st_dm_mode.m4 b/m4/st_dm_mode.m4
index 819dd5677fc..fab2499e8fb 100644
--- a/m4/st_dm_mode.m4
+++ b/m4/st_dm_mode.m4
@@ -1,6 +1,6 @@
# serial 6
-# Copyright (C) 1998-1999, 2001, 2009-2023 Free Software Foundation,
+# Copyright (C) 1998-1999, 2001, 2009-2024 Free Software Foundation,
# Inc.
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
diff --git a/m4/stat-time.m4 b/m4/stat-time.m4
index 40993d5731c..7535a4c7e5c 100644
--- a/m4/stat-time.m4
+++ b/m4/stat-time.m4
@@ -1,7 +1,7 @@
# Checks for stat-related time functions.
-# Copyright (C) 1998-1999, 2001, 2003, 2005-2007, 2009-2023 Free Software
-# Foundation, Inc.
+# Copyright (C) 1998-1999, 2001, 2003, 2005-2007, 2009-2024 Free
+# Software Foundation, Inc.
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
diff --git a/m4/std-gnu11.m4 b/m4/std-gnu11.m4
index 4179470ec94..59998c17cf7 100644
--- a/m4/std-gnu11.m4
+++ b/m4/std-gnu11.m4
@@ -9,7 +9,7 @@
m4_version_prereq([2.70], [], [
-# Copyright (C) 2001-2023 Free Software Foundation, Inc.
+# Copyright (C) 2001-2024 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
diff --git a/m4/stdalign.m4 b/m4/stdalign.m4
index 6a39ffe7565..2683fae7daf 100644
--- a/m4/stdalign.m4
+++ b/m4/stdalign.m4
@@ -1,6 +1,6 @@
# Check for alignas and alignof that conform to C23.
-dnl Copyright 2011-2023 Free Software Foundation, Inc.
+dnl Copyright 2011-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.
diff --git a/m4/stddef_h.m4 b/m4/stddef_h.m4
index aa012219fcd..1bf9eb39b66 100644
--- a/m4/stddef_h.m4
+++ b/m4/stddef_h.m4
@@ -1,5 +1,5 @@
# stddef_h.m4 serial 14
-dnl Copyright (C) 2009-2023 Free Software Foundation, Inc.
+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,
dnl with or without modifications, as long as this notice is preserved.
diff --git a/m4/stdint.m4 b/m4/stdint.m4
index b9f764d4c1c..8c0d430c042 100644
--- a/m4/stdint.m4
+++ b/m4/stdint.m4
@@ -1,5 +1,5 @@
# stdint.m4 serial 62
-dnl Copyright (C) 2001-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2001-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.
diff --git a/m4/stdio_h.m4 b/m4/stdio_h.m4
index dbfa0d5d61b..c19feefe717 100644
--- a/m4/stdio_h.m4
+++ b/m4/stdio_h.m4
@@ -1,5 +1,5 @@
# stdio_h.m4 serial 63
-dnl Copyright (C) 2007-2023 Free Software Foundation, Inc.
+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.
diff --git a/m4/stdlib_h.m4 b/m4/stdlib_h.m4
index f47c1eb37b3..bd6ef381c69 100644
--- a/m4/stdlib_h.m4
+++ b/m4/stdlib_h.m4
@@ -1,5 +1,5 @@
# stdlib_h.m4 serial 75
-dnl Copyright (C) 2007-2023 Free Software Foundation, Inc.
+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.
diff --git a/m4/stpcpy.m4 b/m4/stpcpy.m4
index f3acbee7be9..04c8bbe4c94 100644
--- a/m4/stpcpy.m4
+++ b/m4/stpcpy.m4
@@ -1,5 +1,5 @@
# stpcpy.m4 serial 11
-dnl Copyright (C) 2002, 2007, 2009-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2002, 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,
dnl with or without modifications, as long as this notice is preserved.
diff --git a/m4/string_h.m4 b/m4/string_h.m4
index 7f51391cbff..3cbcbc74873 100644
--- a/m4/string_h.m4
+++ b/m4/string_h.m4
@@ -1,6 +1,6 @@
# Configure a GNU-like replacement for <string.h>.
-# Copyright (C) 2007-2023 Free Software Foundation, Inc.
+# Copyright (C) 2007-2024 Free Software Foundation, Inc.
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
diff --git a/m4/strnlen.m4 b/m4/strnlen.m4
index d2cac59b6f2..16b351a3d41 100644
--- a/m4/strnlen.m4
+++ b/m4/strnlen.m4
@@ -1,6 +1,6 @@
# strnlen.m4 serial 14
-dnl Copyright (C) 2002-2003, 2005-2007, 2009-2023 Free Software Foundation,
-dnl Inc.
+dnl Copyright (C) 2002-2003, 2005-2007, 2009-2024 Free Software
+dnl 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.
diff --git a/m4/strtoimax.m4 b/m4/strtoimax.m4
index db5cfb7aa9d..0708d7e1ce8 100644
--- a/m4/strtoimax.m4
+++ b/m4/strtoimax.m4
@@ -1,5 +1,6 @@
# strtoimax.m4 serial 16
-dnl Copyright (C) 2002-2004, 2006, 2009-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2002-2004, 2006, 2009-2024 Free Software Foundation,
+dnl 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.
diff --git a/m4/strtoll.m4 b/m4/strtoll.m4
index a0cbc805bc9..5ba266f7687 100644
--- a/m4/strtoll.m4
+++ b/m4/strtoll.m4
@@ -1,5 +1,6 @@
# strtoll.m4 serial 11
-dnl Copyright (C) 2002, 2004, 2006, 2008-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2002, 2004, 2006, 2008-2024 Free Software Foundation,
+dnl 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.
diff --git a/m4/symlink.m4 b/m4/symlink.m4
index 52d6c115ca5..62062cf1499 100644
--- a/m4/symlink.m4
+++ b/m4/symlink.m4
@@ -1,7 +1,7 @@
# serial 10
# See if we need to provide symlink replacement.
-dnl Copyright (C) 2009-2023 Free Software Foundation, Inc.
+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,
dnl with or without modifications, as long as this notice is preserved.
diff --git a/m4/sys_random_h.m4 b/m4/sys_random_h.m4
index 01d5feebb31..b050d079b92 100644
--- a/m4/sys_random_h.m4
+++ b/m4/sys_random_h.m4
@@ -1,5 +1,5 @@
# sys_random_h.m4 serial 8
-dnl Copyright (C) 2020-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2020-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.
diff --git a/m4/sys_select_h.m4 b/m4/sys_select_h.m4
index 4ec5ed7a09f..9e279fbab8d 100644
--- a/m4/sys_select_h.m4
+++ b/m4/sys_select_h.m4
@@ -1,5 +1,5 @@
# sys_select_h.m4 serial 23
-dnl Copyright (C) 2006-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2006-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.
diff --git a/m4/sys_socket_h.m4 b/m4/sys_socket_h.m4
index 98a10416cae..af524849f03 100644
--- a/m4/sys_socket_h.m4
+++ b/m4/sys_socket_h.m4
@@ -1,5 +1,5 @@
# sys_socket_h.m4 serial 29
-dnl Copyright (C) 2005-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2005-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.
diff --git a/m4/sys_stat_h.m4 b/m4/sys_stat_h.m4
index ca57398aebd..75018537d57 100644
--- a/m4/sys_stat_h.m4
+++ b/m4/sys_stat_h.m4
@@ -1,5 +1,5 @@
# sys_stat_h.m4 serial 42 -*- Autoconf -*-
-dnl Copyright (C) 2006-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2006-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.
diff --git a/m4/sys_time_h.m4 b/m4/sys_time_h.m4
index 45a1f8b0240..dc5353f3785 100644
--- a/m4/sys_time_h.m4
+++ b/m4/sys_time_h.m4
@@ -1,7 +1,7 @@
# Configure a replacement for <sys/time.h>.
# serial 12
-# Copyright (C) 2007, 2009-2023 Free Software Foundation, Inc.
+# Copyright (C) 2007, 2009-2024 Free Software Foundation, Inc.
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
diff --git a/m4/sys_types_h.m4 b/m4/sys_types_h.m4
index 627671fbdf7..37d0ccad403 100644
--- a/m4/sys_types_h.m4
+++ b/m4/sys_types_h.m4
@@ -1,5 +1,5 @@
# sys_types_h.m4 serial 13
-dnl Copyright (C) 2011-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2011-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.
diff --git a/m4/tempname.m4 b/m4/tempname.m4
index abed7991dab..31d35c83eb5 100644
--- a/m4/tempname.m4
+++ b/m4/tempname.m4
@@ -1,6 +1,6 @@
#serial 5
-# Copyright (C) 2006-2007, 2009-2023 Free Software Foundation, Inc.
+# Copyright (C) 2006-2007, 2009-2024 Free Software Foundation, Inc.
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
diff --git a/m4/time_h.m4 b/m4/time_h.m4
index 632d18fc071..07f82cdfaeb 100644
--- a/m4/time_h.m4
+++ b/m4/time_h.m4
@@ -1,6 +1,7 @@
# Configure a more-standard replacement for <time.h>.
-# Copyright (C) 2000-2001, 2003-2007, 2009-2023 Free Software Foundation, Inc.
+# Copyright (C) 2000-2001, 2003-2007, 2009-2024 Free Software
+# Foundation, Inc.
# serial 24
diff --git a/m4/time_r.m4 b/m4/time_r.m4
index 4831eb26f90..4ee2175b690 100644
--- a/m4/time_r.m4
+++ b/m4/time_r.m4
@@ -1,6 +1,6 @@
dnl Reentrant time functions: localtime_r, gmtime_r.
-dnl Copyright (C) 2003, 2006-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2003, 2006-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.
diff --git a/m4/time_rz.m4 b/m4/time_rz.m4
index d13bc06b7a0..c3b72b7603b 100644
--- a/m4/time_rz.m4
+++ b/m4/time_rz.m4
@@ -1,6 +1,6 @@
dnl Time zone functions: tzalloc, localtime_rz, etc.
-dnl Copyright (C) 2015-2023 Free Software Foundation, Inc.
+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,
dnl with or without modifications, as long as this notice is preserved.
diff --git a/m4/timegm.m4 b/m4/timegm.m4
index 6da07807698..84336043e5d 100644
--- a/m4/timegm.m4
+++ b/m4/timegm.m4
@@ -1,5 +1,5 @@
# timegm.m4 serial 16
-dnl Copyright (C) 2003, 2007, 2009-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 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,
dnl with or without modifications, as long as this notice is preserved.
diff --git a/m4/timer_time.m4 b/m4/timer_time.m4
index 437d1dc5428..10b7654d30f 100644
--- a/m4/timer_time.m4
+++ b/m4/timer_time.m4
@@ -1,5 +1,5 @@
# timer_time.m4 serial 6
-dnl Copyright (C) 2011-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2011-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.
diff --git a/m4/timespec.m4 b/m4/timespec.m4
index 95f475f2cc5..0a1c90e550c 100644
--- a/m4/timespec.m4
+++ b/m4/timespec.m4
@@ -1,6 +1,7 @@
#serial 15
-# Copyright (C) 2000-2001, 2003-2007, 2009-2023 Free Software Foundation, Inc.
+# Copyright (C) 2000-2001, 2003-2007, 2009-2024 Free Software
+# Foundation, Inc.
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
diff --git a/m4/tm_gmtoff.m4 b/m4/tm_gmtoff.m4
index bc41de361cc..f2e51597fdf 100644
--- a/m4/tm_gmtoff.m4
+++ b/m4/tm_gmtoff.m4
@@ -1,5 +1,5 @@
# tm_gmtoff.m4 serial 3
-dnl Copyright (C) 2002, 2009-2023 Free Software Foundation, Inc.
+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.
diff --git a/m4/unistd_h.m4 b/m4/unistd_h.m4
index 1c96158155a..3a1cacaef55 100644
--- a/m4/unistd_h.m4
+++ b/m4/unistd_h.m4
@@ -1,5 +1,5 @@
# unistd_h.m4 serial 94
-dnl Copyright (C) 2006-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2006-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.
diff --git a/m4/unlocked-io.m4 b/m4/unlocked-io.m4
index 407c0bac832..558f57d809b 100644
--- a/m4/unlocked-io.m4
+++ b/m4/unlocked-io.m4
@@ -1,6 +1,6 @@
# unlocked-io.m4 serial 16
-# Copyright (C) 1998-2006, 2009-2023 Free Software Foundation, Inc.
+# Copyright (C) 1998-2006, 2009-2024 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
diff --git a/m4/utimens.m4 b/m4/utimens.m4
index 5f8606167a6..af03e6b52be 100644
--- a/m4/utimens.m4
+++ b/m4/utimens.m4
@@ -1,4 +1,4 @@
-dnl Copyright (C) 2003-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2003-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.
diff --git a/m4/utimensat.m4 b/m4/utimensat.m4
index 1a670bb7b78..e595b333d17 100644
--- a/m4/utimensat.m4
+++ b/m4/utimensat.m4
@@ -1,7 +1,7 @@
# serial 11
# See if we need to provide utimensat replacement.
-dnl Copyright (C) 2009-2023 Free Software Foundation, Inc.
+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,
dnl with or without modifications, as long as this notice is preserved.
diff --git a/m4/utimes.m4 b/m4/utimes.m4
index 73b9a2da34e..040b1af8050 100644
--- a/m4/utimes.m4
+++ b/m4/utimes.m4
@@ -1,7 +1,7 @@
# Detect some bugs in glibc's implementation of utimes.
# serial 8
-dnl Copyright (C) 2003-2005, 2009-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2003-2005, 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.
diff --git a/m4/vararrays.m4 b/m4/vararrays.m4
index fd6230c2968..164bf0c49a9 100644
--- a/m4/vararrays.m4
+++ b/m4/vararrays.m4
@@ -4,7 +4,7 @@
# From Paul Eggert
-# Copyright (C) 2001, 2009-2023 Free Software Foundation, Inc.
+# Copyright (C) 2001, 2009-2024 Free Software Foundation, Inc.
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
diff --git a/m4/warnings.m4 b/m4/warnings.m4
index 9433cb523bf..6c97ef194e4 100644
--- a/m4/warnings.m4
+++ b/m4/warnings.m4
@@ -1,5 +1,5 @@
# warnings.m4 serial 19
-dnl Copyright (C) 2008-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 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.
diff --git a/m4/wchar_t.m4 b/m4/wchar_t.m4
index 50bde08aecb..94353571b00 100644
--- a/m4/wchar_t.m4
+++ b/m4/wchar_t.m4
@@ -1,5 +1,5 @@
# wchar_t.m4 serial 4 (gettext-0.18.2)
-dnl Copyright (C) 2002-2003, 2008-2023 Free Software Foundation, Inc.
+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.
diff --git a/m4/xattr.m4 b/m4/xattr.m4
index 70bf0db4419..7f72a81eeab 100644
--- a/m4/xattr.m4
+++ b/m4/xattr.m4
@@ -1,7 +1,7 @@
# xattr.m4 - check for Extended Attributes (Linux)
# serial 7
-# Copyright (C) 2003-2023 Free Software Foundation, Inc.
+# Copyright (C) 2003-2024 Free Software Foundation, Inc.
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
diff --git a/m4/year2038.m4 b/m4/year2038.m4
index 78b267a088e..189a218bbb9 100644
--- a/m4/year2038.m4
+++ b/m4/year2038.m4
@@ -1,5 +1,5 @@
# year2038.m4 serial 8
-dnl Copyright (C) 2017-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2017-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.
diff --git a/m4/zzgnulib.m4 b/m4/zzgnulib.m4
index 362102b6069..eed5ecbfe1e 100644
--- a/m4/zzgnulib.m4
+++ b/m4/zzgnulib.m4
@@ -1,5 +1,5 @@
# zzgnulib.m4 serial 1
-dnl Copyright (C) 2020-2023 Free Software Foundation, Inc.
+dnl Copyright (C) 2020-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.
diff --git a/make-dist b/make-dist
index a3b7219af3a..91639652350 100755
--- a/make-dist
+++ b/make-dist
@@ -1,7 +1,7 @@
#!/bin/sh
### make-dist: create an Emacs distribution tar file from current srcdir
-## Copyright (C) 1995, 1997-1998, 2000-2023 Free Software Foundation,
+## Copyright (C) 1995, 1997-1998, 2000-2024 Free Software Foundation,
## Inc.
## This file is part of GNU Emacs.
@@ -356,8 +356,9 @@ possibly_non_vc_files="
$top_level_ChangeLog
MANIFEST aclocal.m4 configure
admin/charsets/jisx2131-filter
- src/config.in exec/configure
- exec/config.h.in
+ src/config.in
+ exec/configure exec/config.h.in
+ leim/small-ja-dic-option
"$(
find admin doc etc lisp \
\( -name '*.el' -o -name '*.elc' -o -name '*.map' -o -name '*.stamp' \
diff --git a/modules/modhelp.py b/modules/modhelp.py
index 3ed75dbf628..80ebc79367a 100755
--- a/modules/modhelp.py
+++ b/modules/modhelp.py
@@ -2,7 +2,7 @@
# Module helper script.
-# Copyright 2015-2023 Free Software Foundation, Inc.
+# Copyright 2015-2024 Free Software Foundation, Inc.
# This file is part of GNU Emacs.
diff --git a/msdos/ChangeLog.1 b/msdos/ChangeLog.1
index c58ff771084..8880336767c 100644
--- a/msdos/ChangeLog.1
+++ b/msdos/ChangeLog.1
@@ -1550,7 +1550,7 @@
;; coding: utf-8
;; End:
- Copyright (C) 1994-1999, 2001-2023 Free Software Foundation, Inc.
+ Copyright (C) 1994-1999, 2001-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/msdos/INSTALL b/msdos/INSTALL
index 4baf2b15ab1..9e379d7d235 100644
--- a/msdos/INSTALL
+++ b/msdos/INSTALL
@@ -1,6 +1,6 @@
GNU Emacs Installation Guide for the DJGPP (a.k.a. MS-DOS) port
-Copyright (C) 1992, 1994, 1996-1997, 2000-2023 Free Software Foundation,
+Copyright (C) 1992, 1994, 1996-1997, 2000-2024 Free Software Foundation,
Inc.
See the end of the file for license conditions.
diff --git a/msdos/README b/msdos/README
index fb321273083..e9b7b62b498 100644
--- a/msdos/README
+++ b/msdos/README
@@ -1,4 +1,4 @@
-Copyright (C) 2001-2023 Free Software Foundation, Inc.
+Copyright (C) 2001-2024 Free Software Foundation, Inc.
See the end of the file for license conditions.
@@ -10,7 +10,7 @@ The files emacs.ico and emacs.pif are for using the DJGPP version on
Windows 3.X. Since these are binary files, their copyright notice is
reproduced here:
-# Copyright (C) 1993, 2002-2022 Free Software Foundation, Inc.
+# Copyright (C) 1993, 2002-2024 Free Software Foundation, Inc.
#
# This file is part of GNU Emacs.
#
diff --git a/msdos/autogen/Makefile.in b/msdos/autogen/Makefile.in
index df9b7797989..18403250875 100644
--- a/msdos/autogen/Makefile.in
+++ b/msdos/autogen/Makefile.in
@@ -1,7 +1,7 @@
# Makefile.in generated by automake 1.11.1 from Makefile.am.
# @configure_input@
-# Copyright (C) 1994-2009, 2013-2023 Free Software Foundation, Inc.
+# Copyright (C) 1994-2009, 2013-2024 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
diff --git a/msdos/autogen/config.in b/msdos/autogen/config.in
index 88728cb309c..f6c83bdb4b8 100644
--- a/msdos/autogen/config.in
+++ b/msdos/autogen/config.in
@@ -2,7 +2,7 @@
/* GNU Emacs site configuration template file.
-Copyright (C) 1988, 1993-1994, 1999-2002, 2004-2023 Free Software
+Copyright (C) 1988, 1993-1994, 1999-2002, 2004-2024 Free Software
Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/msdos/depfiles.bat b/msdos/depfiles.bat
index 269a5d07181..17a7faee147 100644
--- a/msdos/depfiles.bat
+++ b/msdos/depfiles.bat
@@ -1,7 +1,7 @@
@echo off
rem ----------------------------------------------------------------------
rem Auxiliary script for MSDOS, run by ../config.bat
-rem Copyright (C) 2011-2023 Free Software Foundation, Inc.
+rem Copyright (C) 2011-2024 Free Software Foundation, Inc.
rem This file is part of GNU Emacs.
diff --git a/msdos/inttypes.h b/msdos/inttypes.h
index ef646eef415..e33bdbafb87 100644
--- a/msdos/inttypes.h
+++ b/msdos/inttypes.h
@@ -1,6 +1,6 @@
/* Replacement inttypes.h file for building GNU Emacs on MS-DOS with DJGPP.
-Copyright (C) 2011-2023 Free Software Foundation, Inc.
+Copyright (C) 2011-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/msdos/langinfo.h b/msdos/langinfo.h
index 018497af437..67b0976bf46 100644
--- a/msdos/langinfo.h
+++ b/msdos/langinfo.h
@@ -1,6 +1,6 @@
/* Replacement langinfo.h file for building GNU Emacs on MS-DOS with DJGPP.
-Copyright (C) 2021-2023 Free Software Foundation, Inc.
+Copyright (C) 2021-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/msdos/mainmake.v2 b/msdos/mainmake.v2
index 4a1e10b336f..b8bb7a332f0 100644
--- a/msdos/mainmake.v2
+++ b/msdos/mainmake.v2
@@ -1,6 +1,6 @@
# Top-level Makefile for Emacs under MS-DOS/DJGPP v2.0 or higher. -*-makefile-*-
-# Copyright (C) 1996-2023 Free Software Foundation, Inc.
+# Copyright (C) 1996-2024 Free Software Foundation, Inc.
# This file is part of GNU Emacs.
diff --git a/msdos/sed1v2.inp b/msdos/sed1v2.inp
index d299ec17574..632c45a16b6 100644
--- a/msdos/sed1v2.inp
+++ b/msdos/sed1v2.inp
@@ -2,7 +2,7 @@
# Configuration script for src/Makefile under DJGPP v2.x
# ----------------------------------------------------------------------
#
-# Copyright (C) 1996-1997, 1999-2023 Free Software Foundation, Inc.
+# Copyright (C) 1996-1997, 1999-2024 Free Software Foundation, Inc.
#
# This file is part of GNU Emacs.
#
diff --git a/msdos/sed1x.inp b/msdos/sed1x.inp
index 1a8e362f951..721eaa447f3 100644
--- a/msdos/sed1x.inp
+++ b/msdos/sed1x.inp
@@ -2,7 +2,7 @@
# Extra configuration script for src/makefile for DesqView/X
# ----------------------------------------------------------------------
#
-# Copyright (C) 1994-1997, 1999-2023 Free Software Foundation, Inc.
+# Copyright (C) 1994-1997, 1999-2024 Free Software Foundation, Inc.
#
# This file is part of GNU Emacs.
#
diff --git a/msdos/sed2v2.inp b/msdos/sed2v2.inp
index 58c1663dda0..9f8bca1a987 100644
--- a/msdos/sed2v2.inp
+++ b/msdos/sed2v2.inp
@@ -2,7 +2,7 @@
# Configuration script for src/config.h under DJGPP v2.x
# ----------------------------------------------------------------------
#
-# Copyright (C) 1993-1997, 1999-2000, 2002-2023 Free Software
+# Copyright (C) 1993-1997, 1999-2000, 2002-2024 Free Software
# Foundation, Inc.
#
# This file is part of GNU Emacs.
@@ -27,7 +27,7 @@
#ifndef MSDOS\
#define MSDOS\
#endif
-/^#undef COPYRIGHT *$/s/^.*$/#define COPYRIGHT "Copyright (C) 2023 Free Software Foundation, Inc."/
+/^#undef COPYRIGHT *$/s/^.*$/#define COPYRIGHT "Copyright (C) 2024 Free Software Foundation, Inc."/
/^#undef DIRECTORY_SEP *$/s!^.*$!#define DIRECTORY_SEP '/'!
/^#undef DOS_NT *$/s/^.*$/#define DOS_NT/
/^#undef FLOAT_CHECK_DOMAIN *$/s/^.*$/#define FLOAT_CHECK_DOMAIN/
diff --git a/msdos/sed2x.inp b/msdos/sed2x.inp
index 4c38952b11c..bcbed8fd0c7 100644
--- a/msdos/sed2x.inp
+++ b/msdos/sed2x.inp
@@ -2,7 +2,7 @@
# Extra configuration script for src/config.h for DesqView/X
# ----------------------------------------------------------------------
#
-# Copyright (C) 1994, 2001-2023 Free Software Foundation, Inc.
+# Copyright (C) 1994, 2001-2024 Free Software Foundation, Inc.
#
# This file is part of GNU Emacs.
#
diff --git a/msdos/sed3v2.inp b/msdos/sed3v2.inp
index 0699fb68b02..9982a5e638f 100644
--- a/msdos/sed3v2.inp
+++ b/msdos/sed3v2.inp
@@ -2,7 +2,7 @@
# Configuration script for lib-src/makefile under DJGPP v2
# ----------------------------------------------------------------------
#
-# Copyright (C) 1996, 1998, 2000-2023 Free Software Foundation, Inc.
+# Copyright (C) 1996, 1998, 2000-2024 Free Software Foundation, Inc.
#
# This file is part of GNU Emacs.
#
diff --git a/msdos/sed4.inp b/msdos/sed4.inp
index 1a579b78773..ca0d370b23a 100644
--- a/msdos/sed4.inp
+++ b/msdos/sed4.inp
@@ -2,7 +2,7 @@
# Configuration script for src/paths.h
# ----------------------------------------------------------------------
#
-# Copyright (C) 1994, 2001-2023 Free Software Foundation, Inc.
+# Copyright (C) 1994, 2001-2024 Free Software Foundation, Inc.
#
# This file is part of GNU Emacs.
#
diff --git a/msdos/sed5x.inp b/msdos/sed5x.inp
index 250ac9b4adb..db32a74c43a 100644
--- a/msdos/sed5x.inp
+++ b/msdos/sed5x.inp
@@ -2,7 +2,7 @@
# Configuration script for oldxmenu/makefile for DesqView/X
# ----------------------------------------------------------------------
#
-# Copyright (C) 1994, 2001-2023 Free Software Foundation, Inc.
+# Copyright (C) 1994, 2001-2024 Free Software Foundation, Inc.
#
# This file is part of GNU Emacs.
#
diff --git a/msdos/sed6.inp b/msdos/sed6.inp
index ec04b8f0af7..43c4ed8bf75 100644
--- a/msdos/sed6.inp
+++ b/msdos/sed6.inp
@@ -3,7 +3,7 @@
# doc/lispintro/Makefile, and doc/misc/Makefile under DJGPP v2.x
# ---------------------------------------------------------------------------
#
-# Copyright (C) 1997, 2000-2023 Free Software Foundation, Inc.
+# Copyright (C) 1997, 2000-2024 Free Software Foundation, Inc.
#
# This file is part of GNU Emacs.
#
diff --git a/msdos/sedadmin.inp b/msdos/sedadmin.inp
index a2d652ac8a3..185b34c35b3 100644
--- a/msdos/sedadmin.inp
+++ b/msdos/sedadmin.inp
@@ -2,7 +2,7 @@
# Configuration script for admin/unidata/Makefile under DJGPP v2.x
# ----------------------------------------------------------------------
#
-# Copyright (C) 2014-2023 Free Software Foundation, Inc.
+# Copyright (C) 2014-2024 Free Software Foundation, Inc.
#
# This file is part of GNU Emacs.
#
diff --git a/msdos/sedalloc.inp b/msdos/sedalloc.inp
index 716bc6c0e8e..f058f8b6e5e 100644
--- a/msdos/sedalloc.inp
+++ b/msdos/sedalloc.inp
@@ -2,7 +2,7 @@
# Configuration script for SYSTEM_MALLOC/REL_ALLOC in src/config.h
# ----------------------------------------------------------------------
#
-# Copyright (C) 2008-2023 Free Software Foundation, Inc.
+# Copyright (C) 2008-2024 Free Software Foundation, Inc.
#
# This file is part of GNU Emacs.
#
diff --git a/msdos/sedleim.inp b/msdos/sedleim.inp
index d759fc40714..f644e9ce965 100644
--- a/msdos/sedleim.inp
+++ b/msdos/sedleim.inp
@@ -2,7 +2,7 @@
# Configuration script for leim/Makefile under DJGPP v2.x
# ----------------------------------------------------------------------
#
-# Copyright (C) 1999-2023 Free Software Foundation, Inc.
+# Copyright (C) 1999-2024 Free Software Foundation, Inc.
#
# This file is part of GNU Emacs.
#
diff --git a/msdos/sedlibcf.inp b/msdos/sedlibcf.inp
index 8966e799a38..8f7aa33f823 100644
--- a/msdos/sedlibcf.inp
+++ b/msdos/sedlibcf.inp
@@ -5,7 +5,7 @@
# files whose names are invalid on DOS 8+3 filesystems.
# ----------------------------------------------------------------------
#
-# Copyright (C) 2011-2023 Free Software Foundation, Inc.
+# Copyright (C) 2011-2024 Free Software Foundation, Inc.
#
# This file is part of GNU Emacs.
#
diff --git a/msdos/sedlibmk.inp b/msdos/sedlibmk.inp
index 664bfaf693c..1d8ae778168 100644
--- a/msdos/sedlibmk.inp
+++ b/msdos/sedlibmk.inp
@@ -2,7 +2,7 @@
# Configuration script for lib/Makefile under DJGPP v2.x
# ----------------------------------------------------------------------
#
-# Copyright (C) 2011-2023 Free Software Foundation, Inc.
+# Copyright (C) 2011-2024 Free Software Foundation, Inc.
#
# This file is part of GNU Emacs.
#
diff --git a/msdos/sedlisp.inp b/msdos/sedlisp.inp
index 89d11fb44e3..e9033098ce1 100644
--- a/msdos/sedlisp.inp
+++ b/msdos/sedlisp.inp
@@ -2,7 +2,7 @@
# Configuration script for lisp/Makefile under DJGPP v2.x
# ----------------------------------------------------------------------
#
-# Copyright (C) 2000-2023 Free Software Foundation, Inc.
+# Copyright (C) 2000-2024 Free Software Foundation, Inc.
#
# This file is part of GNU Emacs.
#
diff --git a/nextstep/ChangeLog.1 b/nextstep/ChangeLog.1
index 26def2266fe..34de7b77b4c 100644
--- a/nextstep/ChangeLog.1
+++ b/nextstep/ChangeLog.1
@@ -6,7 +6,7 @@
* Makefile.in (links): New phony target to create a fake
installation pointing back to the source tree to run GUI Emacs
- in-place (http://article.gmane.org/gmane.emacs.devel:178330).
+ in-place (http://article.gmane.org/gmane.emacs.devel:178330). [dead link]
2014-11-22 Glenn Morris <rgm@gnu.org>
@@ -312,7 +312,7 @@
;; coding: utf-8
;; End:
- Copyright (C) 2008-2023 Free Software Foundation, Inc.
+ Copyright (C) 2008-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/nextstep/INSTALL b/nextstep/INSTALL
index cce19a41ed8..174c7e105e2 100644
--- a/nextstep/INSTALL
+++ b/nextstep/INSTALL
@@ -1,4 +1,4 @@
-Copyright (C) 2008-2023 Free Software Foundation, Inc.
+Copyright (C) 2008-2024 Free Software Foundation, Inc.
See the end of the file for license conditions.
diff --git a/nextstep/Makefile.in b/nextstep/Makefile.in
index 5e3465315af..5811bf87342 100644
--- a/nextstep/Makefile.in
+++ b/nextstep/Makefile.in
@@ -1,6 +1,6 @@
### @configure_input@
-## Copyright (C) 2012-2023 Free Software Foundation, Inc.
+## Copyright (C) 2012-2024 Free Software Foundation, Inc.
## This file is part of GNU Emacs.
@@ -46,11 +46,7 @@ ns_check_file = @ns_appdir@/@ns_check_file@
.PHONY: all
-ifeq ($(DUMPING),pdumper)
-ns_pdmp_target = ${ns_applibexecdir}/Emacs.pdmp
-endif
-
-all: ${ns_appdir} ${ns_appbindir}/Emacs ${ns_pdmp_target}
+all: ${ns_appdir} ${ns_appbindir}/Emacs
${ns_check_file}: ${ns_appdir}
@@ -71,12 +67,6 @@ ${ns_appbindir}/Emacs: ${ns_appdir} ${ns_check_file} ../src/emacs${EXEEXT}
${MKDIR_P} ${ns_appbindir}
cp -f ../src/emacs${EXEEXT} $@
-# FIXME: Don't install the dump file into the app bundle when
-# self-contained install is disabled.
-${ns_applibexecdir}/Emacs.pdmp: ${ns_appdir} ${ns_check_file} ../src/emacs${EXEEXT}.pdmp
- ${MKDIR_P} ${ns_applibexecdir}
- cp -f ../src/emacs${EXEEXT}.pdmp $@
-
.PHONY: FORCE
../src/emacs${EXEEXT}: FORCE
diff --git a/nextstep/README b/nextstep/README
index 3fe1b9421f7..9bf3e6ffbc0 100644
--- a/nextstep/README
+++ b/nextstep/README
@@ -105,7 +105,7 @@ future development.
----------------------------------------------------------------------
-Copyright 2008-2023 Free Software Foundation, Inc.
+Copyright 2008-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/nextstep/templates/Info.plist.in b/nextstep/templates/Info.plist.in
index 0f95bcebb24..beddbf4a893 100644
--- a/nextstep/templates/Info.plist.in
+++ b/nextstep/templates/Info.plist.in
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
-Copyright (C) 2008-2023 Free Software Foundation, Inc.
+Copyright (C) 2008-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/nt/ChangeLog.1 b/nt/ChangeLog.1
index 1e54afd7a1d..0a3f96c01eb 100644
--- a/nt/ChangeLog.1
+++ b/nt/ChangeLog.1
@@ -3548,7 +3548,7 @@
;; add-log-time-zone-rule: t
;; End:
- Copyright (C) 1995-1999, 2001-2023 Free Software Foundation, Inc.
+ Copyright (C) 1995-1999, 2001-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/nt/INSTALL b/nt/INSTALL
index 3b465ba494c..77626f8a343 100644
--- a/nt/INSTALL
+++ b/nt/INSTALL
@@ -1,7 +1,7 @@
Building and Installing Emacs on MS-Windows
using the MSYS and MinGW tools
- Copyright (C) 2013-2023 Free Software Foundation, Inc.
+ Copyright (C) 2013-2024 Free Software Foundation, Inc.
See the end of the file for license conditions.
The MSYS/MinGW build described here is supported on versions of
diff --git a/nt/INSTALL.W64 b/nt/INSTALL.W64
index fe5f74e3209..2aa05ea0062 100644
--- a/nt/INSTALL.W64
+++ b/nt/INSTALL.W64
@@ -1,7 +1,7 @@
Building and Installing Emacs on 64-bit MS-Windows
using MSYS2 and MinGW-w64
- Copyright (c) 2015-2023 Free Software Foundation, Inc.
+ Copyright (c) 2015-2024 Free Software Foundation, Inc.
See the end of the file for license conditions.
This document describes how to compile a 64-bit GNU Emacs using MSYS2
diff --git a/nt/Makefile.in b/nt/Makefile.in
index 0c3192a63e6..865e3d807e8 100644
--- a/nt/Makefile.in
+++ b/nt/Makefile.in
@@ -1,6 +1,6 @@
### @configure_input@
-# Copyright (C) 2013-2023 Free Software Foundation, Inc.
+# Copyright (C) 2013-2024 Free Software Foundation, Inc.
# This file is part of GNU Emacs.
diff --git a/nt/README b/nt/README
index 118ead25fce..694e8854446 100644
--- a/nt/README
+++ b/nt/README
@@ -1,6 +1,6 @@
Emacs for Windows NT/2000 and Windows 95/98/ME
- Copyright (C) 2001-2023 Free Software Foundation, Inc.
+ Copyright (C) 2001-2024 Free Software Foundation, Inc.
See the end of the file for license conditions.
This directory contains support for compiling and running GNU Emacs on
diff --git a/nt/README.W32 b/nt/README.W32
index da1ede1ea4d..98657246f67 100644
--- a/nt/README.W32
+++ b/nt/README.W32
@@ -1,4 +1,4 @@
-Copyright (C) 2001-2023 Free Software Foundation, Inc.
+Copyright (C) 2001-2024 Free Software Foundation, Inc.
See the end of the file for license conditions.
Emacs version 30.0.50 for MS-Windows
diff --git a/nt/addpm.c b/nt/addpm.c
index 1f137144aac..6aee45d8149 100644
--- a/nt/addpm.c
+++ b/nt/addpm.c
@@ -1,5 +1,5 @@
/* Add entries to the GNU Emacs Program Manager folder.
- Copyright (C) 1995, 2001-2023 Free Software Foundation, Inc.
+ Copyright (C) 1995, 2001-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/nt/cmdproxy.c b/nt/cmdproxy.c
index d669fa1a391..0500b653bb2 100644
--- a/nt/cmdproxy.c
+++ b/nt/cmdproxy.c
@@ -1,5 +1,5 @@
/* Proxy shell designed for use with Emacs on Windows 95 and NT.
- Copyright (C) 1997, 2001-2023 Free Software Foundation, Inc.
+ Copyright (C) 1997, 2001-2024 Free Software Foundation, Inc.
Accepts subset of Unix sh(1) command-line options, for compatibility
with elisp code written for Unix. When possible, executes external
diff --git a/nt/configure.bat b/nt/configure.bat
new file mode 100755
index 00000000000..6e2ebe5357e
--- /dev/null
+++ b/nt/configure.bat
@@ -0,0 +1,26 @@
+@echo off
+rem ----------------------------------------------------------------------
+rem This was the old configuration script for MS Windows operating systems
+rem Copyright (C) 1999-2024 Free Software Foundation, Inc.
+
+rem This file is part of GNU Emacs.
+
+rem GNU Emacs is free software: you can redistribute it and/or modify
+rem it under the terms of the GNU General Public License as published by
+rem the Free Software Foundation, either version 3 of the License, or
+rem (at your option) any later version.
+
+rem GNU Emacs is distributed in the hope that it will be useful,
+rem but WITHOUT ANY WARRANTY; without even the implied warranty of
+rem MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+rem GNU General Public License for more details.
+
+rem You should have received a copy of the GNU General Public License
+rem along with GNU Emacs. If not, see https://www.gnu.org/licenses/.
+
+rem ----------------------------------------------------------------------
+echo ****************************************************************
+echo *** THIS METHOD OF BUILDING EMACS IS NO LONGER SUPPORTED. **
+echo *** INSTEAD, FOLLOW THE INSTRUCTIONS IN THE FILE INSTALL. **
+echo *** IN THE SAME DIRECTORY AS THIS BATCH FILE. **
+echo ****************************************************************
diff --git a/nt/ddeclient.c b/nt/ddeclient.c
index 1fbd2da4c13..2862cb30d71 100644
--- a/nt/ddeclient.c
+++ b/nt/ddeclient.c
@@ -1,5 +1,5 @@
/* Simple client interface to DDE servers.
- Copyright (C) 1998, 2001-2023 Free Software Foundation, Inc.
+ Copyright (C) 1998, 2001-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/nt/epaths.nt b/nt/epaths.nt
index 6069004cd13..143b6110a1c 100644
--- a/nt/epaths.nt
+++ b/nt/epaths.nt
@@ -12,7 +12,7 @@
the host system (e.g., i686-pc-mingw32), and @SRC@ by the root of
the Emacs source tree used to build Emacs. */
/*
-Copyright (C) 1993, 1995, 1997, 1999, 2001-2023 Free Software
+Copyright (C) 1993, 1995, 1997, 1999, 2001-2024 Free Software
Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/nt/gnulib-cfg.mk b/nt/gnulib-cfg.mk
index fe29e942d80..5b1c2c88ba5 100644
--- a/nt/gnulib-cfg.mk
+++ b/nt/gnulib-cfg.mk
@@ -1,6 +1,6 @@
# Configurations for ../lib/gnulib.mk.
#
-# Copyright 2017-2023 Free Software Foundation, Inc.
+# Copyright 2017-2024 Free Software Foundation, Inc.
#
# This file is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
diff --git a/nt/icons/README b/nt/icons/README
index dbb28fcfee1..9787d8b6017 100644
--- a/nt/icons/README
+++ b/nt/icons/README
@@ -2,13 +2,13 @@ COPYRIGHT AND LICENSE INFORMATION FOR IMAGE FILES
File: emacs.ico
Author: Kentaro Ohkouchi <nanasess@fsm.ne.jp>
-Copyright (C) 2008-2023 Free Software Foundation, Inc.
+Copyright (C) 2008-2024 Free Software Foundation, Inc.
License: GNU General Public License version 3 or later
File: emacs22.ico
Author: Andrew Zhilin
-Copyright (C) 2005-2023 Free Software Foundation, Inc.
+Copyright (C) 2005-2024 Free Software Foundation, Inc.
License: GNU General Public License version 3 or later (see COPYING)
@@ -17,7 +17,7 @@ Files: gnu2a32.ico gnu2a32t.ico gnu2b48.ico gnu2b48t.ico
gnu5w32.ico gnu5w32t.ico gnu6w48.ico gnu6w48t.ico
gnu7.ico gnu8.ico gnu9.ico
Author: Rob Davenport <rgd at bigfoot.com>
-Copyright (C) 1999, 2001-2023 Free Software Foundation, Inc.
+Copyright (C) 1999, 2001-2024 Free Software Foundation, Inc.
License: GNU General Public License version 3 or later (see COPYING)
<http://users.adelphia.net/~rob.davenport/gnuicons.html>
diff --git a/nt/inc/grp.h b/nt/inc/grp.h
index 1a5f0276ca1..695d28b4292 100644
--- a/nt/inc/grp.h
+++ b/nt/inc/grp.h
@@ -1,6 +1,6 @@
/* Replacement grp.h file for building GNU Emacs on Windows.
-Copyright (C) 2003-2023 Free Software Foundation, Inc.
+Copyright (C) 2003-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/nt/inc/inttypes.h b/nt/inc/inttypes.h
index 657bd960758..a8552b99b18 100644
--- a/nt/inc/inttypes.h
+++ b/nt/inc/inttypes.h
@@ -1,6 +1,6 @@
/* Replacement inttypes.h file for building GNU Emacs on Windows with MSVC.
-Copyright (C) 2011-2023 Free Software Foundation, Inc.
+Copyright (C) 2011-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/nt/inc/langinfo.h b/nt/inc/langinfo.h
index 86d925bd13f..0315e52d576 100644
--- a/nt/inc/langinfo.h
+++ b/nt/inc/langinfo.h
@@ -1,6 +1,6 @@
/* Replacement langinfo.h file for building GNU Emacs on Windows.
-Copyright (C) 2006-2023 Free Software Foundation, Inc.
+Copyright (C) 2006-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/nt/inc/ms-w32.h b/nt/inc/ms-w32.h
index fce15fcbd8c..cea0b072723 100644
--- a/nt/inc/ms-w32.h
+++ b/nt/inc/ms-w32.h
@@ -1,6 +1,6 @@
/* System description file for Windows NT.
-Copyright (C) 1993-1995, 2001-2023 Free Software Foundation, Inc.
+Copyright (C) 1993-1995, 2001-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
@@ -208,7 +208,7 @@ extern struct tm * sys_localtime (const time_t *);
/* Unlike MS and mingw.org, MinGW64 doesn't define gai_strerror as an
inline function in a system header file, and instead seems to
- require to link against ws2_32.a. But we don't want to link with
+ require linking against ws2_32.a. But we don't want to link with
-lws2_32, as that would make Emacs dependent on the respective DLL.
So MinGW64 is amply punished here by the following: */
#undef HAVE_GAI_STRERROR
diff --git a/nt/inc/nl_types.h b/nt/inc/nl_types.h
index 17debcc5b64..541a82c5cc1 100644
--- a/nt/inc/nl_types.h
+++ b/nt/inc/nl_types.h
@@ -1,6 +1,6 @@
/* Replacement nl_types.h file for building GNU Emacs on Windows.
-Copyright (C) 2006-2023 Free Software Foundation, Inc.
+Copyright (C) 2006-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/nt/inc/stdint.h b/nt/inc/stdint.h
index c9b667f5759..194d6104fdb 100644
--- a/nt/inc/stdint.h
+++ b/nt/inc/stdint.h
@@ -1,6 +1,6 @@
/* Replacement stdint.h file for building GNU Emacs on Windows.
-Copyright (C) 2011-2023 Free Software Foundation, Inc.
+Copyright (C) 2011-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/nt/inc/sys/resource.h b/nt/inc/sys/resource.h
index 72d855e6a82..b64f95ee660 100644
--- a/nt/inc/sys/resource.h
+++ b/nt/inc/sys/resource.h
@@ -1,6 +1,6 @@
/* A limited emulation of sys/resource.h.
-Copyright (C) 2016-2023 Free Software Foundation, Inc.
+Copyright (C) 2016-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/nt/inc/sys/socket.h b/nt/inc/sys/socket.h
index 43a24797b4c..5ecec24d04b 100644
--- a/nt/inc/sys/socket.h
+++ b/nt/inc/sys/socket.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 1995, 2001-2023 Free Software Foundation, Inc.
+/* Copyright (C) 1995, 2001-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/nt/inc/sys/stat.h b/nt/inc/sys/stat.h
index 0eb178dc0c9..cdd19ceeff4 100644
--- a/nt/inc/sys/stat.h
+++ b/nt/inc/sys/stat.h
@@ -1,7 +1,7 @@
/* sys/stat.h supplied with MSVCRT uses too narrow data types for
inode and user/group id, so we replace them with our own.
-Copyright (C) 2008-2023 Free Software Foundation, Inc.
+Copyright (C) 2008-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/nt/inc/sys/wait.h b/nt/inc/sys/wait.h
index 6f49c055fb7..23d17444bbc 100644
--- a/nt/inc/sys/wait.h
+++ b/nt/inc/sys/wait.h
@@ -1,6 +1,6 @@
/* A limited emulation of sys/wait.h on Posix systems.
-Copyright (C) 2012-2023 Free Software Foundation, Inc.
+Copyright (C) 2012-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/nt/preprep.c b/nt/preprep.c
new file mode 100644
index 00000000000..d1c4f2136cc
--- /dev/null
+++ b/nt/preprep.c
@@ -0,0 +1,830 @@
+/* Pre-process emacs.exe for profiling by MSVC.
+ Copyright (C) 1999, 2001-2024 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or (at
+your option) any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+
+ Andrew Innes <andrewi@harlequin.co.uk> 16-Jan-1999
+ based on code from addsection.c
+*/
+
+#define DEFER_MS_W32_H
+#include <config.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <time.h>
+#if defined(__GNUC__) && !defined(MINGW_W64)
+#define _ANONYMOUS_UNION
+#define _ANONYMOUS_STRUCT
+#endif
+#include <windows.h>
+
+/* Include relevant definitions from IMAGEHLP.H, which can be found
+ in \\win32sdk\mstools\samples\image\include\imagehlp.h. */
+
+PIMAGE_NT_HEADERS (__stdcall * pfnCheckSumMappedFile) (LPVOID BaseAddress,
+ DWORD_PTR FileLength,
+ PDWORD_PTR HeaderSum,
+ PDWORD_PTR CheckSum);
+
+#undef min
+#undef max
+#define min(x, y) (((x) < (y)) ? (x) : (y))
+#define max(x, y) (((x) > (y)) ? (x) : (y))
+
+
+/* File handling. */
+
+typedef struct file_data {
+ const char *name;
+ unsigned long size;
+ HANDLE file;
+ HANDLE file_mapping;
+ unsigned char *file_base;
+} file_data;
+
+int
+open_input_file (file_data *p_file, const char *filename)
+{
+ HANDLE file;
+ HANDLE file_mapping;
+ void *file_base;
+ unsigned long size, upper_size;
+
+ file = CreateFile (filename, GENERIC_READ, FILE_SHARE_READ, NULL,
+ OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
+ if (file == INVALID_HANDLE_VALUE)
+ return FALSE;
+
+ size = GetFileSize (file, &upper_size);
+ file_mapping = CreateFileMapping (file, NULL, PAGE_READONLY,
+ 0, size, NULL);
+ if (!file_mapping)
+ return FALSE;
+
+ file_base = MapViewOfFile (file_mapping, FILE_MAP_READ, 0, 0, size);
+ if (file_base == 0)
+ return FALSE;
+
+ p_file->name = filename;
+ p_file->size = size;
+ p_file->file = file;
+ p_file->file_mapping = file_mapping;
+ p_file->file_base = file_base;
+
+ return TRUE;
+}
+
+int
+open_output_file (file_data *p_file, const char *filename, unsigned long size)
+{
+ HANDLE file;
+ HANDLE file_mapping;
+ void *file_base;
+
+ file = CreateFile (filename, GENERIC_READ | GENERIC_WRITE, 0, NULL,
+ CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
+ if (file == INVALID_HANDLE_VALUE)
+ return FALSE;
+
+ file_mapping = CreateFileMapping (file, NULL, PAGE_READWRITE,
+ 0, size, NULL);
+ if (!file_mapping)
+ return FALSE;
+
+ file_base = MapViewOfFile (file_mapping, FILE_MAP_WRITE, 0, 0, size);
+ if (file_base == 0)
+ return FALSE;
+
+ p_file->name = filename;
+ p_file->size = size;
+ p_file->file = file;
+ p_file->file_mapping = file_mapping;
+ p_file->file_base = file_base;
+
+ return TRUE;
+}
+
+int
+open_inout_file (file_data *p_file, const char *filename)
+{
+ HANDLE file;
+ HANDLE file_mapping;
+ void *file_base;
+ unsigned long size, upper_size;
+
+ file = CreateFile (filename, GENERIC_READ | GENERIC_WRITE, 0, NULL,
+ OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
+ if (file == INVALID_HANDLE_VALUE)
+ return FALSE;
+
+ size = GetFileSize (file, &upper_size);
+ file_mapping = CreateFileMapping (file, NULL, PAGE_READWRITE,
+ 0, size, NULL);
+ if (!file_mapping)
+ return FALSE;
+
+ file_base = MapViewOfFile (file_mapping, FILE_MAP_WRITE, 0, 0, size);
+ if (file_base == 0)
+ return FALSE;
+
+ p_file->name = filename;
+ p_file->size = size;
+ p_file->file = file;
+ p_file->file_mapping = file_mapping;
+ p_file->file_base = file_base;
+
+ return TRUE;
+}
+
+/* Close the system structures associated with the given file. */
+void
+close_file_data (file_data *p_file)
+{
+ UnmapViewOfFile (p_file->file_base);
+ CloseHandle (p_file->file_mapping);
+ /* For the case of output files, set final size. */
+ SetFilePointer (p_file->file, p_file->size, NULL, FILE_BEGIN);
+ SetEndOfFile (p_file->file);
+ CloseHandle (p_file->file);
+}
+
+
+/* Routines to manipulate NT executable file sections. */
+
+unsigned long
+get_unrounded_section_size (PIMAGE_SECTION_HEADER p_section)
+{
+ /* The true section size, before rounding, for an initialized data or
+ code section. (Supposedly some linkers swap the meaning of these
+ two values.) */
+ return min (p_section->SizeOfRawData,
+ p_section->Misc.VirtualSize);
+}
+
+/* Return pointer to section header for named section. */
+IMAGE_SECTION_HEADER *
+find_section (const char *name, IMAGE_NT_HEADERS *nt_header)
+{
+ PIMAGE_SECTION_HEADER section;
+ int i;
+
+ section = IMAGE_FIRST_SECTION (nt_header);
+
+ for (i = 0; i < nt_header->FileHeader.NumberOfSections; i++)
+ {
+ if (strcmp (section->Name, name) == 0)
+ return section;
+ section++;
+ }
+ return NULL;
+}
+
+/* Return pointer to section header for section containing the given
+ relative virtual address. */
+IMAGE_SECTION_HEADER *
+rva_to_section (DWORD_PTR rva, IMAGE_NT_HEADERS * nt_header)
+{
+ PIMAGE_SECTION_HEADER section;
+ int i;
+
+ section = IMAGE_FIRST_SECTION (nt_header);
+
+ for (i = 0; i < nt_header->FileHeader.NumberOfSections; i++)
+ {
+ /* Some linkers (eg. the NT SDK linker I believe) swapped the
+ meaning of these two values - or rather, they ignored
+ VirtualSize entirely and always set it to zero. This affects
+ some very old exes (eg. gzip dated Dec 1993). Since
+ w32_executable_type relies on this function to work reliably,
+ we need to cope with this. */
+ DWORD_PTR real_size = max (section->SizeOfRawData,
+ section->Misc.VirtualSize);
+ if (rva >= section->VirtualAddress
+ && rva < section->VirtualAddress + real_size)
+ return section;
+ section++;
+ }
+ return NULL;
+}
+
+/* Return pointer to section header for section containing the given
+ offset in its raw data area. */
+IMAGE_SECTION_HEADER *
+offset_to_section (DWORD_PTR offset, IMAGE_NT_HEADERS * nt_header)
+{
+ PIMAGE_SECTION_HEADER section;
+ int i;
+
+ section = IMAGE_FIRST_SECTION (nt_header);
+
+ for (i = 0; i < nt_header->FileHeader.NumberOfSections; i++)
+ {
+ if (offset >= section->PointerToRawData
+ && offset < section->PointerToRawData + section->SizeOfRawData)
+ return section;
+ section++;
+ }
+ return NULL;
+}
+
+/* Return offset to an object in dst, given offset in src. We assume
+ there is at least one section in both src and dst images, and that
+ the some sections may have been added to dst (after sections in src). */
+static DWORD_PTR
+relocate_offset (DWORD_PTR offset,
+ IMAGE_NT_HEADERS * src_nt_header,
+ IMAGE_NT_HEADERS * dst_nt_header)
+{
+ PIMAGE_SECTION_HEADER src_section = IMAGE_FIRST_SECTION (src_nt_header);
+ PIMAGE_SECTION_HEADER dst_section = IMAGE_FIRST_SECTION (dst_nt_header);
+ int i = 0;
+
+ while (offset >= src_section->PointerToRawData)
+ {
+ if (offset < src_section->PointerToRawData + src_section->SizeOfRawData)
+ break;
+ i++;
+ if (i == src_nt_header->FileHeader.NumberOfSections)
+ {
+ /* Handle offsets after the last section. */
+ dst_section = IMAGE_FIRST_SECTION (dst_nt_header);
+ dst_section += dst_nt_header->FileHeader.NumberOfSections - 1;
+ while (dst_section->PointerToRawData == 0)
+ dst_section--;
+ while (src_section->PointerToRawData == 0)
+ src_section--;
+ return offset
+ + (dst_section->PointerToRawData + dst_section->SizeOfRawData)
+ - (src_section->PointerToRawData + src_section->SizeOfRawData);
+ }
+ src_section++;
+ dst_section++;
+ }
+ return offset +
+ (dst_section->PointerToRawData - src_section->PointerToRawData);
+}
+
+#define OFFSET_TO_RVA(offset, section) \
+ ((section)->VirtualAddress + ((DWORD_PTR)(offset) - (section)->PointerToRawData))
+
+#define RVA_TO_OFFSET(rva, section) \
+ ((section)->PointerToRawData + ((DWORD_PTR)(rva) - (section)->VirtualAddress))
+
+#define RVA_TO_SECTION_OFFSET(rva, section) \
+ ((DWORD_PTR)(rva) - (section)->VirtualAddress)
+
+#define RVA_TO_PTR(var,section,filedata) \
+ ((void *)((unsigned char *)(RVA_TO_OFFSET(var,section) + (filedata)->file_base)))
+
+/* Convert address in executing image to RVA. */
+#define PTR_TO_RVA(ptr) ((DWORD_PTR)(ptr) - (DWORD_PTR) GetModuleHandle (NULL))
+
+#define PTR_TO_OFFSET(ptr, pfile_data) \
+ ((unsigned const char *)(ptr) - (pfile_data)->file_base)
+
+#define OFFSET_TO_PTR(offset, pfile_data) \
+ ((pfile_data)->file_base + (DWORD_PTR)(offset))
+
+#define ROUND_UP(p, align) \
+ (((DWORD_PTR)(p) + (align)-1) & ~((DWORD_PTR)(align)-1))
+#define ROUND_DOWN(p, align) ((DWORD_PTR)(p) & ~((DWORD_PTR)(align)-1))
+
+
+/* The MSVC prep program generates a ._xe file from .exe, where relevant
+ function calls etc have been patched to go through thunks (generated
+ by prep) that record timing/call information. Because the thunks
+ need to make references to functions imported from profile.dll, the
+ import table must be expanded; the end result is that all the
+ sections following .rdata are relocated to higher RVAs (add a final
+ code section is added holding all the thunks). The .reloc section is
+ also expanded, so that the thunks themselves are relocatable.
+
+ It is this relocation which kills emacs._xe, because the dumped heap
+ pointers aren't relocated, because there is no relocation data for
+ either the relevant global/static variables or the heap section
+ itself, both of which contain pointers into the heap. [Note that
+ static variables which aren't initialized during linking may become
+ initialized with heap pointers, or even pointers to other static
+ variables, because of dumping.]
+
+ We could potentially generate the relocation data ourselves by making
+ two versions of temacs, one with an extra dummy section before
+ EMHEAP to offset it, and then compare the dumped executables from
+ both. That is a lot of work though, and it doesn't solve the problem
+ of dumped pointers to static variables, which also can be relocated.
+
+ A better solution is to pre-process emacs.exe so that the .rdata and
+ .reloc sections are moved to the end of the section table, and thus
+ prep won't relocate anything else. (Of course, we leave "dead"
+ copies of these two sections in place, so that the virtual address of
+ everything else is unaffected.) Relocating the .reloc data is
+ trivial - we just update the IMAGE_BASE_RELOCATION address in the
+ header (the data itself doesn't change). Relocating the import table
+ is more complicated though, because the calls to imported functions
+ must be patched up. That requires us to selectively apply the base
+ relocations when we encounter references to imported functions (or
+ variables) in other sections, but at least the base relocations are
+ easy to parse. */
+
+static void
+copy_executable_and_move_sections (file_data *p_infile,
+ file_data *p_outfile)
+{
+ unsigned char *dst;
+ PIMAGE_DOS_HEADER dos_header;
+ PIMAGE_NT_HEADERS nt_header;
+ PIMAGE_NT_HEADERS dst_nt_header;
+ PIMAGE_SECTION_HEADER section;
+ PIMAGE_SECTION_HEADER dst_section;
+ PIMAGE_SECTION_HEADER import_section;
+ PIMAGE_SECTION_HEADER reloc_section;
+ PIMAGE_DATA_DIRECTORY import_dir;
+ PIMAGE_DATA_DIRECTORY reloc_dir;
+ DWORD_PTR import_delta_rva;
+ DWORD_PTR reloc_delta_rva;
+ DWORD_PTR offset;
+ int i;
+
+#define COPY_CHUNK(message, src, size) \
+ do { \
+ unsigned const char *s = (void *)(src); \
+ unsigned long count = (size); \
+ printf ("%s\n", (message)); \
+ printf ("\t0x%08x Offset in input file.\n", s - p_infile->file_base); \
+ printf ("\t0x%08x Offset in output file.\n", dst - p_outfile->file_base); \
+ printf ("\t0x%08x Size in bytes.\n", count); \
+ memcpy (dst, s, count); \
+ dst += count; \
+ } while (0)
+
+#define DST_TO_OFFSET() PTR_TO_OFFSET (dst, p_outfile)
+#define ROUND_UP_DST_AND_ZERO(align) \
+ do { \
+ unsigned char *newdst = p_outfile->file_base \
+ + ROUND_UP (DST_TO_OFFSET (), (align)); \
+ /* Zero the alignment slop; it may actually initialize real data. */ \
+ memset (dst, 0, newdst - dst); \
+ dst = newdst; \
+ } while (0)
+
+ /* Copy the source image sequentially, ie. section by section after
+ copying the headers and section table, to simplify the process of
+ relocating the .rdata and .reloc section table entries (which might
+ force the raw section data to be relocated).
+
+ Note that dst is updated implicitly by each COPY_CHUNK. */
+
+ dos_header = (PIMAGE_DOS_HEADER) p_infile->file_base;
+ nt_header = (PIMAGE_NT_HEADERS) (((unsigned char *) dos_header) +
+ dos_header->e_lfanew);
+ section = IMAGE_FIRST_SECTION (nt_header);
+
+ import_dir = &nt_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
+ import_section = rva_to_section (import_dir->VirtualAddress, nt_header);
+
+ reloc_dir = &nt_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC];
+ reloc_section = rva_to_section (reloc_dir->VirtualAddress, nt_header);
+ if (!reloc_section)
+ {
+ printf ("No relocation data, cannot prepare for profile prepping.\n");
+ exit (1);
+ }
+
+ dst = (unsigned char *) p_outfile->file_base;
+
+ COPY_CHUNK ("Copying DOS header...", dos_header,
+ (DWORD_PTR) nt_header - (DWORD_PTR) dos_header);
+ dst_nt_header = (PIMAGE_NT_HEADERS) dst;
+ COPY_CHUNK ("Copying NT header...", nt_header,
+ (DWORD_PTR) section - (DWORD_PTR) nt_header);
+ dst_section = (PIMAGE_SECTION_HEADER) dst;
+ COPY_CHUNK ("Copying section table...", section,
+ nt_header->FileHeader.NumberOfSections * sizeof (*section));
+
+ /* Leave room for extra section table entries; filled in below. */
+ dst += 2 * sizeof (*section);
+
+ /* Align the first section's raw data area, and set the header size
+ field accordingly. */
+ ROUND_UP_DST_AND_ZERO (dst_nt_header->OptionalHeader.FileAlignment);
+ dst_nt_header->OptionalHeader.SizeOfHeaders = DST_TO_OFFSET ();
+
+ for (i = 0; i < nt_header->FileHeader.NumberOfSections;
+ i++, section++, dst_section++)
+ {
+ char msg[100];
+ sprintf (msg, "Copying raw data for %s...", section->Name);
+
+ /* "Blank out" the two sections being relocated. */
+ if (section == import_section || section == reloc_section)
+ {
+ dst_section->Name[0] = 'X';
+ dst_section->Misc.VirtualSize =
+ ROUND_UP (dst_section->Misc.VirtualSize,
+ dst_nt_header->OptionalHeader.SectionAlignment);
+ dst_section->PointerToRawData = 0;
+ dst_section->SizeOfRawData = 0;
+ dst_section->Characteristics &= ~IMAGE_SCN_CNT_INITIALIZED_DATA;
+ dst_section->Characteristics |= IMAGE_SCN_CNT_UNINITIALIZED_DATA;
+ dst_section->Characteristics &= ~IMAGE_SCN_MEM_WRITE;
+ continue;
+ }
+
+ /* Update the file-relative offset for this section's raw data (if
+ it has any) in case things have been relocated; we will update
+ the other offsets below once we know where everything is. */
+ if (dst_section->PointerToRawData)
+ dst_section->PointerToRawData = DST_TO_OFFSET ();
+
+ /* Copy the original raw data. */
+ COPY_CHUNK
+ (msg, OFFSET_TO_PTR (section->PointerToRawData, p_infile),
+ section->SizeOfRawData);
+
+ /* Round up the raw data size to the new alignment. */
+ dst_section->SizeOfRawData =
+ ROUND_UP (dst_section->SizeOfRawData,
+ dst_nt_header->OptionalHeader.FileAlignment);
+
+ /* Align the next section's raw data area. */
+ ROUND_UP_DST_AND_ZERO (dst_nt_header->OptionalHeader.FileAlignment);
+ }
+
+ /* Add the extra section entries, copying the raw data we skipped
+ earlier. We'll patch up the data itself below. */
+ if (import_section != NULL)
+ {
+ dst_nt_header->FileHeader.NumberOfSections++;
+ dst_nt_header->OptionalHeader.SizeOfImage +=
+ ROUND_UP (import_section->Misc.VirtualSize,
+ dst_nt_header->OptionalHeader.SectionAlignment);
+ *dst_section = *import_section;
+ dst_section->VirtualAddress =
+ dst_section[-1].VirtualAddress
+ + ROUND_UP (dst_section[-1].Misc.VirtualSize,
+ dst_nt_header->OptionalHeader.SectionAlignment);
+ dst_section->PointerToRawData = DST_TO_OFFSET ();
+ /* Remember delta applied to import section. */
+ import_delta_rva = dst_section->VirtualAddress - import_section->VirtualAddress;
+ COPY_CHUNK
+ ("Relocating import directory",
+ OFFSET_TO_PTR (import_section->PointerToRawData, p_infile),
+ import_section->SizeOfRawData);
+ ROUND_UP_DST_AND_ZERO (dst_nt_header->OptionalHeader.FileAlignment);
+ dst_section++;
+ }
+ if (reloc_section != NULL)
+ {
+ dst_nt_header->FileHeader.NumberOfSections++;
+ dst_nt_header->OptionalHeader.SizeOfImage +=
+ ROUND_UP (reloc_section->Misc.VirtualSize,
+ dst_nt_header->OptionalHeader.SectionAlignment);
+ *dst_section = *reloc_section;
+ dst_section->VirtualAddress =
+ dst_section[-1].VirtualAddress
+ + ROUND_UP (dst_section[-1].Misc.VirtualSize,
+ dst_nt_header->OptionalHeader.SectionAlignment);
+ dst_section->PointerToRawData = DST_TO_OFFSET ();
+ /* Remember delta applied to reloc section. */
+ reloc_delta_rva = dst_section->VirtualAddress - reloc_section->VirtualAddress;
+ COPY_CHUNK
+ ("Relocating base relocations directory",
+ OFFSET_TO_PTR (reloc_section->PointerToRawData, p_infile),
+ reloc_section->SizeOfRawData);
+ ROUND_UP_DST_AND_ZERO (dst_nt_header->OptionalHeader.FileAlignment);
+ reloc_dir = &dst_nt_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC];
+ reloc_dir->VirtualAddress += reloc_delta_rva;
+ dst_section++;
+ }
+
+ /* Copy remainder of source image. */
+ section--;
+ offset = ROUND_UP (section->PointerToRawData + section->SizeOfRawData,
+ nt_header->OptionalHeader.FileAlignment);
+ COPY_CHUNK
+ ("Copying remainder of executable...",
+ OFFSET_TO_PTR (offset, p_infile),
+ p_infile->size - offset);
+
+ /* Final size for new image. */
+ p_outfile->size = DST_TO_OFFSET ();
+
+ /* Now patch up remaining file-relative offsets. */
+ printf ("Patching up raw data offsets...\n");
+
+ section = IMAGE_FIRST_SECTION (nt_header);
+ dst_section = IMAGE_FIRST_SECTION (dst_nt_header);
+
+#define ADJUST_OFFSET(var) \
+ do { \
+ if ((var) != 0) \
+ (var) = relocate_offset ((var), nt_header, dst_nt_header); \
+ } while (0)
+
+#define ADJUST_IMPORT_RVA(var) \
+ do { \
+ if ((var) != 0) \
+ *((DWORD_PTR *)&(var)) += import_delta_rva; \
+ } while (0)
+
+ dst_nt_header->OptionalHeader.SizeOfInitializedData = 0;
+ dst_nt_header->OptionalHeader.SizeOfUninitializedData = 0;
+ for (i = 0; i < dst_nt_header->FileHeader.NumberOfSections; i++)
+ {
+ /* Recompute data sizes for completeness. */
+ if (dst_section[i].Characteristics & IMAGE_SCN_CNT_INITIALIZED_DATA)
+ dst_nt_header->OptionalHeader.SizeOfInitializedData +=
+ ROUND_UP (dst_section[i].Misc.VirtualSize, dst_nt_header->OptionalHeader.FileAlignment);
+ else if (dst_section[i].Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA)
+ dst_nt_header->OptionalHeader.SizeOfUninitializedData +=
+ ROUND_UP (dst_section[i].Misc.VirtualSize, dst_nt_header->OptionalHeader.FileAlignment);
+
+ ADJUST_OFFSET (dst_section[i].PointerToLinenumbers);
+ }
+
+ ADJUST_OFFSET (dst_nt_header->FileHeader.PointerToSymbolTable);
+
+ /* Update offsets in debug directory entries. Note that the debug
+ directory may be in the same section as the import table, so its
+ RVA may need to be adjusted too. */
+ {
+ PIMAGE_DATA_DIRECTORY debug_dir =
+ &dst_nt_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG];
+ PIMAGE_DEBUG_DIRECTORY debug_entry;
+
+ /* Update debug_dir if part of import_section. */
+ if (rva_to_section (debug_dir->VirtualAddress, nt_header) == import_section)
+ debug_dir->VirtualAddress += import_delta_rva;
+
+ section = rva_to_section (debug_dir->VirtualAddress, dst_nt_header);
+ if (section)
+ {
+ int size;
+
+ debug_entry = RVA_TO_PTR (debug_dir->VirtualAddress, section, p_outfile);
+ size = debug_dir->Size / sizeof (IMAGE_DEBUG_DIRECTORY);
+
+ for (i = 0; i < size; i++, debug_entry++)
+ {
+ /* The debug data itself is normally not part of any
+ section, but stored after all the raw section data. So
+ let relocate_offset do the work. */
+ ADJUST_OFFSET (debug_entry->PointerToRawData);
+ ADJUST_IMPORT_RVA (debug_entry->AddressOfRawData);
+ }
+ }
+ }
+
+ /* Update RVAs in import directory entries. */
+ {
+ PIMAGE_IMPORT_DESCRIPTOR imports;
+ PIMAGE_THUNK_DATA import_thunks;
+
+ import_dir = &dst_nt_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
+ import_dir->VirtualAddress += import_delta_rva;
+
+ section = rva_to_section (import_dir->VirtualAddress, dst_nt_header);
+ imports = RVA_TO_PTR (import_dir->VirtualAddress, section, p_outfile);
+
+ for ( ; imports->Name != 0; imports++)
+ {
+ ADJUST_IMPORT_RVA (imports->OriginalFirstThunk);
+ ADJUST_IMPORT_RVA (imports->FirstThunk);
+ ADJUST_IMPORT_RVA (imports->Name);
+
+ for (import_thunks = RVA_TO_PTR (imports->OriginalFirstThunk, section, p_outfile);
+ import_thunks->u1.Function != 0;
+ import_thunks++)
+ if ((import_thunks->u1.Ordinal >> 31) == 0)
+ ADJUST_IMPORT_RVA (import_thunks->u1.Ordinal);
+
+ for (import_thunks = RVA_TO_PTR (imports->FirstThunk, section, p_outfile);
+ import_thunks->u1.Function != 0;
+ import_thunks++)
+ if ((import_thunks->u1.Ordinal >> 31) == 0)
+ ADJUST_IMPORT_RVA (import_thunks->u1.Ordinal);
+ }
+
+ import_dir = &dst_nt_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT];
+ import_dir->VirtualAddress += import_delta_rva;
+ }
+
+ /* Fix up references to the import section. */
+ printf ("Applying fixups to import references...\n");
+
+ {
+ IMAGE_BASE_RELOCATION *relocs, *block, *start_block, *end_block;
+ DWORD_PTR import_start = import_section->VirtualAddress + dst_nt_header->OptionalHeader.ImageBase;
+ DWORD_PTR import_end = import_start + import_section->Misc.VirtualSize;
+ DWORD_PTR len_import_relocs;
+ DWORD_PTR len_remaining_relocs;
+ int seen_high = 0;
+ WORD * high_word;
+ void * holder;
+
+ reloc_dir = &dst_nt_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC];
+ reloc_section = rva_to_section (reloc_dir->VirtualAddress, dst_nt_header);
+ relocs = RVA_TO_PTR (reloc_dir->VirtualAddress, reloc_section, p_outfile);
+
+ /* Move the base relocations for the import section, if there are
+ any; the profiler needs to be able to patch RVAs in the import
+ section itself. */
+ for (block = relocs, start_block = 0;
+ (DWORD_PTR) block - (DWORD_PTR) relocs < reloc_dir->Size;
+ block = (void *)((DWORD_PTR) block + block->SizeOfBlock))
+ {
+ if (block->VirtualAddress >= import_section->VirtualAddress + import_section->Misc.VirtualSize)
+ {
+ end_block = block;
+ break;
+ }
+ if (block->VirtualAddress >= import_section->VirtualAddress)
+ {
+ if (start_block == 0)
+ start_block = block;
+ block->VirtualAddress += import_delta_rva;
+ }
+ }
+ if (start_block)
+ {
+ len_import_relocs = (DWORD_PTR) end_block - (DWORD_PTR) start_block;
+ len_remaining_relocs = (DWORD_PTR) relocs + reloc_dir->Size - (DWORD_PTR) end_block;
+ holder = malloc (len_import_relocs);
+ if (holder == 0)
+ abort ();
+ memcpy (holder, start_block, len_import_relocs);
+ memcpy (start_block, end_block, len_remaining_relocs);
+ memcpy ((char *) start_block + len_remaining_relocs, holder, len_import_relocs);
+ free (holder);
+ }
+
+ /* Walk up the list of base relocations, checking for references
+ to the old import section location, and patching them to
+ reference the new location. */
+ for (block = relocs;
+ (DWORD_PTR) block - (DWORD_PTR) relocs < reloc_dir->Size;
+ block = (void *)((DWORD_PTR) block + block->SizeOfBlock))
+ {
+ DWORD_PTR page_rva = block->VirtualAddress;
+ DWORD_PTR page_offset;
+ union {
+ WORD word;
+ DWORD_PTR dword;
+ } * ploc;
+ WORD *fixup;
+
+ section = rva_to_section (page_rva, dst_nt_header);
+ /* Don't apply fixups to the blanked sections. */
+ if (section->Name[0] == 'X')
+ continue;
+
+ for (fixup = (WORD *) &block[1];
+ (DWORD_PTR) fixup - (DWORD_PTR) block < block->SizeOfBlock;
+ fixup++)
+ {
+ page_offset = (*fixup) & 0xfff;
+ ploc = RVA_TO_PTR (page_rva + page_offset, section, p_outfile);
+
+ /* Unless our assumption is wrong, all low word fixups
+ should immediately follow a high fixup. */
+ if (seen_high && ((*fixup) >> 12) != IMAGE_REL_BASED_LOW)
+ abort ();
+
+ switch ((*fixup) >> 12)
+ {
+ case IMAGE_REL_BASED_ABSOLUTE:
+ break;
+ case IMAGE_REL_BASED_HIGH:
+ /* We must assume that high and low fixups occur in
+ pairs, specifically a low fixup immediately follows a
+ high fixup (normally separated by two bytes). We
+ have to process the two fixups together, to find out
+ the full pointer value and decide whether to apply
+ the fixup. */
+ seen_high = 1;
+ high_word = &ploc->word;
+ break;
+ case IMAGE_REL_BASED_LOW:
+ offset = (*high_word << 16) + ploc->word;
+ if (offset >= import_start && offset < import_end)
+ {
+ (*high_word) += import_delta_rva >> 16;
+ ploc->dword += import_delta_rva & 0xffff;
+ }
+ seen_high = 0;
+ break;
+ case IMAGE_REL_BASED_HIGHLOW:
+ /* Docs imply two words in big-endian order, so perhaps
+ this is only used on big-endian platforms, in which
+ case the obvious code will work. */
+ if (ploc->dword >= import_start && ploc->dword < import_end)
+ ploc->dword += import_delta_rva;
+ break;
+ case IMAGE_REL_BASED_HIGHADJ:
+ /* Docs don't say, but I guess this is the equivalent
+ for little-endian platforms. */
+ if (ploc->dword >= import_start && ploc->dword < import_end)
+ ploc->dword += import_delta_rva;
+ break;
+ case IMAGE_REL_BASED_MIPS_JMPADDR:
+ /* Don't know how to handle this; MIPS support has been
+ dropped from NT4 anyway. */
+ abort ();
+ break;
+#ifdef IMAGE_REL_BASED_SECTION
+ case IMAGE_REL_BASED_SECTION:
+ case IMAGE_REL_BASED_REL32:
+ /* Docs don't say what these values mean. */
+#endif
+ default:
+ abort ();
+ }
+ }
+ }
+ }
+}
+
+
+int
+main (int argc, char **argv)
+{
+ PIMAGE_DOS_HEADER dos_header;
+ PIMAGE_NT_HEADERS nt_header;
+ file_data in_file, out_file;
+ char out_filename[MAX_PATH], in_filename[MAX_PATH];
+
+ strcpy (in_filename, argv[1]);
+ strcpy (out_filename, argv[2]);
+
+ printf ("Preparing %s for profile prepping\n", out_filename);
+
+ /* Open the original (dumped) executable file for reference. */
+ if (!open_input_file (&in_file, in_filename))
+ {
+ printf ("Failed to open %s (%d)...bailing.\n",
+ in_filename, GetLastError ());
+ exit (1);
+ }
+
+ /* Create a new image that can be prepped; we don't expect the size to
+ change because we are only adding two new section table entries,
+ which should fit in the alignment slop. */
+ if (!open_output_file (&out_file, out_filename, in_file.size))
+ {
+ printf ("Failed to open %s (%d)...bailing.\n",
+ out_filename, GetLastError ());
+ exit (1);
+ }
+
+ copy_executable_and_move_sections (&in_file, &out_file);
+
+ /* Patch up header fields; profiler is picky about this. */
+ {
+ HANDLE hImagehelp = LoadLibrary ("imagehlp.dll");
+ DWORD_PTR headersum;
+ DWORD_PTR checksum;
+
+ dos_header = (PIMAGE_DOS_HEADER) out_file.file_base;
+ nt_header = (PIMAGE_NT_HEADERS) ((char *) dos_header + dos_header->e_lfanew);
+
+ nt_header->OptionalHeader.CheckSum = 0;
+// nt_header->FileHeader.TimeDateStamp = time (NULL);
+// dos_header->e_cp = size / 512;
+// nt_header->OptionalHeader.SizeOfImage = size;
+
+ pfnCheckSumMappedFile = (void *) GetProcAddress (hImagehelp, "CheckSumMappedFile");
+ if (pfnCheckSumMappedFile)
+ {
+// nt_header->FileHeader.TimeDateStamp = time (NULL);
+ pfnCheckSumMappedFile (out_file.file_base,
+ out_file.size,
+ &headersum,
+ &checksum);
+ nt_header->OptionalHeader.CheckSum = checksum;
+ }
+ FreeLibrary (hImagehelp);
+ }
+
+ close_file_data (&out_file);
+ close_file_data (&in_file);
+
+ return 0;
+}
+
+/* eof */
diff --git a/nt/runemacs.c b/nt/runemacs.c
index 9226bb50745..4188a1fa9a4 100644
--- a/nt/runemacs.c
+++ b/nt/runemacs.c
@@ -1,6 +1,6 @@
/* runemacs --- Simple program to start Emacs with its console window hidden.
-Copyright (C) 2001-2023 Free Software Foundation, Inc.
+Copyright (C) 2001-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/oldXMenu/Activate.c b/oldXMenu/Activate.c
index 0bfa70900f0..ffc5d5ecef1 100644
--- a/oldXMenu/Activate.c
+++ b/oldXMenu/Activate.c
@@ -21,7 +21,7 @@ without express or implied warranty.
/*
-Copyright (C) 2001-2023 Free Software Foundation, Inc.
+Copyright (C) 2001-2024 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/oldXMenu/ChangeLog.1 b/oldXMenu/ChangeLog.1
index 2de6071a33c..629ac2e2b65 100644
--- a/oldXMenu/ChangeLog.1
+++ b/oldXMenu/ChangeLog.1
@@ -240,7 +240,7 @@
* Relicense all FSF files to GPLv3 or later.
-2007-06-04 Ulrich Mueller <ulm@gentoo.org> (tiny change)
+2007-06-04 Ulrich Müller <ulm@gentoo.org> (tiny change)
* ChgPane.c, ChgSel.c: Quiet --with-x-toolkit=no
compilation warnings: #include <config.h>.
@@ -249,7 +249,7 @@
* Version 22.1 released.
-2007-05-30 Ulrich Mueller <ulm@gentoo.org> (tiny change)
+2007-05-30 Ulrich Müller <ulm@gentoo.org> (tiny change)
* XMakeAssoc.c (XMakeAssoc): Use malloc rather than xmalloc.
@@ -712,7 +712,7 @@
;; coding: utf-8
;; End:
- Copyright (C) 1993-1999, 2001-2023 Free Software Foundation, Inc.
+ Copyright (C) 1993-1999, 2001-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/oldXMenu/Create.c b/oldXMenu/Create.c
index 9518b2833a2..c602d984168 100644
--- a/oldXMenu/Create.c
+++ b/oldXMenu/Create.c
@@ -21,7 +21,7 @@ without express or implied warranty.
/*
-Copyright (C) 1993-1994, 2001-2023 Free Software Foundation, Inc.
+Copyright (C) 1993-1994, 2001-2024 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/oldXMenu/FindSel.c b/oldXMenu/FindSel.c
index 0153af1b02f..4e68d167ade 100644
--- a/oldXMenu/FindSel.c
+++ b/oldXMenu/FindSel.c
@@ -21,7 +21,7 @@ without express or implied warranty.
/*
-Copyright (C) 2001-2023 Free Software Foundation, Inc.
+Copyright (C) 2001-2024 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/oldXMenu/Internal.c b/oldXMenu/Internal.c
index cf4960cd113..db13f7ac736 100644
--- a/oldXMenu/Internal.c
+++ b/oldXMenu/Internal.c
@@ -21,7 +21,7 @@ without express or implied warranty.
/*
-Copyright (C) 1993, 1996, 2001-2023 Free Software Foundation, Inc.
+Copyright (C) 1993, 1996, 2001-2024 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/oldXMenu/Makefile.in b/oldXMenu/Makefile.in
index 602d05fb621..cdafe83b7a2 100644
--- a/oldXMenu/Makefile.in
+++ b/oldXMenu/Makefile.in
@@ -15,7 +15,7 @@
## without express or implied warranty.
-## Copyright (C) 2001-2023 Free Software Foundation, Inc.
+## Copyright (C) 2001-2024 Free Software Foundation, Inc.
## This program is free software: you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
diff --git a/oldXMenu/deps.mk b/oldXMenu/deps.mk
index cf85047d971..b223fce75d4 100644
--- a/oldXMenu/deps.mk
+++ b/oldXMenu/deps.mk
@@ -15,7 +15,7 @@
## without express or implied warranty.
-## Copyright (C) 2001-2023 Free Software Foundation, Inc.
+## Copyright (C) 2001-2024 Free Software Foundation, Inc.
## This program is free software: you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
diff --git a/oldXMenu/insque.c b/oldXMenu/insque.c
index 3d7c3b3086c..78d99d2b4ea 100644
--- a/oldXMenu/insque.c
+++ b/oldXMenu/insque.c
@@ -1,5 +1,5 @@
/*
-Copyright (C) 1993-1998, 2001-2023 Free Software Foundation, Inc.
+Copyright (C) 1993-1998, 2001-2024 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/src/.gdbinit b/src/.gdbinit
index c97e78559f1..bc6cad0560e 100644
--- a/src/.gdbinit
+++ b/src/.gdbinit
@@ -1,4 +1,4 @@
-# Copyright (C) 1992-1998, 2000-2023 Free Software Foundation, Inc.
+# Copyright (C) 1992-1998, 2000-2024 Free Software Foundation, Inc.
#
# This file is part of GNU Emacs.
#
diff --git a/src/.lldbinit b/src/.lldbinit
index f5fcdd7b597..e958c1b832c 100644
--- a/src/.lldbinit
+++ b/src/.lldbinit
@@ -1,5 +1,5 @@
# -*- mode: shell-script -*-
-# Copyright (C) 2022-2023 Free Software Foundation, Inc.
+# Copyright (C) 2022-2024 Free Software Foundation, Inc.
#
# This file is part of GNU Emacs.
#
@@ -30,4 +30,7 @@ script -- sys.path.append('../etc')
# Load our Python files
command script import emacs_lldb
+# Print with children provider, depth 2.
+command alias xprint frame variable -P 2
+
# end.
diff --git a/src/ChangeLog.1 b/src/ChangeLog.1
index 37d6d6bd897..adeccfa9a6d 100644
--- a/src/ChangeLog.1
+++ b/src/ChangeLog.1
@@ -3521,7 +3521,7 @@
* minibuf.c: Don't allow entry to minibuffer
while minibuffer is selected.
- Copyright (C) 1985-1986, 2001-2023 Free Software Foundation, Inc.
+ Copyright (C) 1985-1986, 2001-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/ChangeLog.10 b/src/ChangeLog.10
index 949e4507f4c..cb6502e915c 100644
--- a/src/ChangeLog.10
+++ b/src/ChangeLog.10
@@ -27912,7 +27912,7 @@ See ChangeLog.9 for earlier changes.
;; add-log-time-zone-rule: t
;; End:
- Copyright (C) 2001-2023 Free Software Foundation, Inc.
+ Copyright (C) 2001-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/ChangeLog.11 b/src/ChangeLog.11
index b2b776d491f..abea7688c87 100644
--- a/src/ChangeLog.11
+++ b/src/ChangeLog.11
@@ -2029,7 +2029,7 @@
(update_frame_tool_bar): Calculate tool-bar style once per call.
Instead of hiding text labels, omit them. Don't use
xg_show_toolbar_item; create new GtkToolItems from scratch if
- necessary, instead of trying to re-use them. This avoids an
+ necessary, instead of trying to reuse them. This avoids an
annoying animation when changing tool-bars.
2010-12-31 Jan Djärv <jan.h.d@swipnet.se>
@@ -2048,7 +2048,7 @@
(ns_set_name): Call ns_set_name_internal.
(x_explicitly_set_name): Remove call to ns_set_name_iconic.
(x_implicitly_set_name): Ditto.
- (x_set_title): Remove commet about EXPLICIT. Call ns_set_name_internal.
+ (x_set_title): Remove comment about EXPLICIT. Call ns_set_name_internal.
(ns_set_name_as_filename): Encode name with ENCODE_UTF_8 (Bug#7517).
2010-12-29 Štěpán Němec <stepnem@gmail.com> (tiny change)
@@ -6278,7 +6278,7 @@
2010-07-09 Michael Albinus <michael.albinus@gmx.de>
* dbusbind.c (xd_initialize): Add new argument RAISE_ERROR, which
- allows to suppress errors when polling in Emacs' main loop.
+ allows suppressing errors when polling in Emacs' main loop.
(Fdbus_init_bus, Fdbus_get_unique_name, Fdbus_call_method)
(Fdbus_call_method_asynchronously, Fdbus_method_return_internal)
(Fdbus_method_error_internal, Fdbus_send_signal)
@@ -9435,7 +9435,7 @@
continuation line, and start looking for a suitable row from
there.
- * term.c (append_glyph): Reverse glyphs by pre-pending them,
+ * term.c (append_glyph): Reverse glyphs by prepending them,
rather than appending, if the glyph_row's reversed_p flag is set.
Set the resolved_level and bidi_type members of each glyph.
@@ -12876,7 +12876,7 @@
* editfns.c (Ftranspose_regions): Doc fix (Bug#3248).
-2009-05-10 Ulrich Mueller <ulm@gentoo.org>
+2009-05-10 Ulrich Müller <ulm@gentoo.org>
* s/gnu-linux.h: Make GCPROs and UNGCPRO no-ops also on SuperH.
@@ -12978,7 +12978,7 @@
* process.c (create_process): Clean up merger residues of
2008-07-17 change.
-2009-04-29 Ulrich Mueller <ulm@gentoo.org>
+2009-04-29 Ulrich Müller <ulm@gentoo.org>
* lread.c (Vread_circle): New variable.
(read1): Disable recursive read if Vread_circle is nil.
@@ -14860,7 +14860,7 @@
* process.c (Fsystem_process_attributes, syms_of_process):
Fix typo in name of Ssystem_process_attributes.
- Reported by Ulrich Mueller <ulm@kph.uni-mainz.de>.
+ Reported by Ulrich Müller <ulm@kph.uni-mainz.de>.
2008-12-11 Juanma Barranquero <lekktu@gmail.com>
@@ -15356,7 +15356,7 @@
* keyboard.c (command_loop_1): Handle NORECORD in call of
Fselect_frame (currently ifdefd).
-2008-11-02 Ulrich Mueller <ulm@kph.uni-mainz.de>
+2008-11-02 Ulrich Müller <ulm@kph.uni-mainz.de>
* emacs.c (USAGE2): Untabify.
@@ -15626,7 +15626,7 @@
(Fset_window_buffer): Respect any non-nil dedicated value for
window. Rename "buffer" argument to "buffer_or_name".
-2008-10-18 Ulrich Mueller <ulm@gentoo.org>
+2008-10-18 Ulrich Müller <ulm@gentoo.org>
* m/sh3.h: New file, machine description for SuperH.
@@ -23405,7 +23405,7 @@
* Makefile.in (lisp): Add ${lispsource}language/tai-viet.el.
(shortlisp): Add ../lisp/language/tai-viet.el.
-2008-02-01 Ulrich Mueller <ulm@gentoo.org>
+2008-02-01 Ulrich Müller <ulm@gentoo.org>
* Makefile.in (${lispsource}international/charprop.el): Depend on
temacs${EXEEXT}.
@@ -31385,7 +31385,7 @@ See ChangeLog.10 for earlier changes.
;; coding: utf-8
;; End:
- Copyright (C) 2007-2023 Free Software Foundation, Inc.
+ Copyright (C) 2007-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/ChangeLog.12 b/src/ChangeLog.12
index fdb7a2e659b..7792bd88c01 100644
--- a/src/ChangeLog.12
+++ b/src/ChangeLog.12
@@ -22936,7 +22936,7 @@ See ChangeLog.11 for earlier changes.
;; coding: utf-8
;; End:
- Copyright (C) 2011-2023 Free Software Foundation, Inc.
+ Copyright (C) 2011-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/ChangeLog.13 b/src/ChangeLog.13
index d9736479a04..312909f462f 100644
--- a/src/ChangeLog.13
+++ b/src/ChangeLog.13
@@ -5464,7 +5464,7 @@
(set_horizontal_scroll_bar): New function.
(redisplay_window): Set ignore_mouse_drag_p when tool bar has
more than one line. Handle horizontal scroll bars.
- (note_mouse_highlight): Handle horizontal scrol bars.
+ (note_mouse_highlight): Handle horizontal scroll bars.
(expose_frame): Set dimensions of XRectangle from frame's text
sizes.
(Vvoid_text_area_pointer): Update doc-string.
@@ -8437,7 +8437,7 @@
* xdisp.c (syms_of_xdisp): Doc clarification (bug#15657).
- * keyboard.c (Frecursive_edit): Say more precicely how throwing
+ * keyboard.c (Frecursive_edit): Say more precisely how throwing
`exit' works (bug#15865).
2014-02-07 Martin Rudalics <rudalics@gmx.at>
@@ -16678,7 +16678,7 @@
2013-05-27 Eli Zaretskii <eliz@gnu.org>
- * xdisp.c (pos_visible_p): When CHARPOS is displayed frrom a
+ * xdisp.c (pos_visible_p): When CHARPOS is displayed from a
display vector, and we backtrack, handle the case that the
previous character position is also displayed from a display
vector or covered by a display string or image. (Bug#14476)
@@ -17905,7 +17905,7 @@ See ChangeLog.12 for earlier changes.
;; coding: utf-8
;; End:
- Copyright (C) 2011-2023 Free Software Foundation, Inc.
+ Copyright (C) 2011-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/ChangeLog.2 b/src/ChangeLog.2
index d518c759642..6f4e79e71f5 100644
--- a/src/ChangeLog.2
+++ b/src/ChangeLog.2
@@ -4771,7 +4771,7 @@
See ChangeLog.1 for earlier changes.
- Copyright (C) 1986-1988, 2001-2023 Free Software Foundation, Inc.
+ Copyright (C) 1986-1988, 2001-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/ChangeLog.3 b/src/ChangeLog.3
index fbfb36fdb2a..e9fa000aff4 100644
--- a/src/ChangeLog.3
+++ b/src/ChangeLog.3
@@ -16503,7 +16503,7 @@ See ChangeLog.2 for earlier changes.
;; coding: utf-8
;; End:
- Copyright (C) 1993, 2001-2023 Free Software Foundation, Inc.
+ Copyright (C) 1993, 2001-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/ChangeLog.4 b/src/ChangeLog.4
index 0c47d979ecc..711e142232c 100644
--- a/src/ChangeLog.4
+++ b/src/ChangeLog.4
@@ -3490,7 +3490,7 @@
* Makefile.in.in (temacs): Delete redundant use of LDFLAGS.
-1994-01-02 Ulrich Mueller (ulm@vsnhd1.cern.ch)
+1994-01-02 Ulrich Müller (ulm@vsnhd1.cern.ch)
* sysdep.c (get_system_name): If the official name of the host is
not a fully qualified domain name, then try to find one in the
@@ -6906,7 +6906,7 @@ See ChangeLog.3 for earlier changes.
;; coding: utf-8
;; End:
- Copyright (C) 1993-1994, 2001-2023 Free Software Foundation, Inc.
+ Copyright (C) 1993-1994, 2001-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/ChangeLog.5 b/src/ChangeLog.5
index 3ea0acafff0..df1de5efe6b 100644
--- a/src/ChangeLog.5
+++ b/src/ChangeLog.5
@@ -7148,7 +7148,7 @@ See ChangeLog.4 for earlier changes.
;; coding: utf-8
;; End:
- Copyright (C) 1994-1995, 2001-2023 Free Software Foundation, Inc.
+ Copyright (C) 1994-1995, 2001-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/ChangeLog.6 b/src/ChangeLog.6
index f9ea372c55d..6838f16ad41 100644
--- a/src/ChangeLog.6
+++ b/src/ChangeLog.6
@@ -5358,7 +5358,7 @@ See ChangeLog.5 for earlier changes.
;; coding: utf-8
;; End:
- Copyright (C) 1995-1996, 2001-2023 Free Software Foundation, Inc.
+ Copyright (C) 1995-1996, 2001-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/ChangeLog.7 b/src/ChangeLog.7
index dfa41bec8f7..61892b54bf5 100644
--- a/src/ChangeLog.7
+++ b/src/ChangeLog.7
@@ -11091,7 +11091,7 @@ See ChangeLog.6 for earlier changes.
;; coding: utf-8
;; End:
- Copyright (C) 1997-1998, 2001-2023 Free Software Foundation, Inc.
+ Copyright (C) 1997-1998, 2001-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/ChangeLog.8 b/src/ChangeLog.8
index 1f479a89ed8..e91448e32e2 100644
--- a/src/ChangeLog.8
+++ b/src/ChangeLog.8
@@ -10802,7 +10802,7 @@
(display_mode_element): Ditto.
(echo_area_display): Don't display if frame has no pools yet.
(echo_area_display): Work with window matrix for mini window.
- (redisplay_window): Use window marix for mini window.
+ (redisplay_window): Use window matrix for mini window.
(display_text_line): Assume HPOS and VPOS are window relative and
use that for DISPLAY_STRING.
@@ -13979,7 +13979,7 @@
See ChangeLog.7 for earlier changes.
- Copyright (C) 1999, 2001-2023 Free Software Foundation, Inc.
+ Copyright (C) 1999, 2001-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/ChangeLog.9 b/src/ChangeLog.9
index d005b51604b..8331d09a128 100644
--- a/src/ChangeLog.9
+++ b/src/ChangeLog.9
@@ -11622,7 +11622,7 @@
(set_font_frame_param): If `font' is specified in lface, use it.
(Finternal_get_lisp_face_attribute): Handle `font' slot in lface.
(lface_same_font_attributes_p): Likewise.
- (make_realized_face): Arguent changed. Caller changed. Set
+ (make_realized_face): Argument changed. Caller changed. Set
face->ascii_face to face itself.
(free_realized_face): Free face->fontset if face is for ASCII.
(face_suitable_for_iso8859_1_p, face_suitable_for_charset_p)
@@ -13294,7 +13294,7 @@ See ChangeLog.8 for earlier changes.
;; coding: utf-8
;; End:
- Copyright (C) 2001-2023 Free Software Foundation, Inc.
+ Copyright (C) 2001-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/Makefile.in b/src/Makefile.in
index b14681f2537..de45b2290f1 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -1,6 +1,6 @@
### @configure_input@
-# Copyright (C) 1985, 1987-1988, 1993-1995, 1999-2023 Free Software
+# Copyright (C) 1985, 1987-1988, 1993-1995, 1999-2024 Free Software
# Foundation, Inc.
# This file is part of GNU Emacs.
@@ -943,6 +943,8 @@ elnlisp := \
international/charscript.eln \
emacs-lisp/comp.eln \
emacs-lisp/comp-cstr.eln \
+ emacs-lisp/comp-common.eln \
+ emacs-lisp/comp-run.eln \
international/emoji-zwj.eln
elnlisp := $(addprefix ${lispsource}/,${elnlisp}) $(lisp:.elc=.eln)
diff --git a/src/README b/src/README
index 7d4427b8610..a8ddf830b72 100644
--- a/src/README
+++ b/src/README
@@ -1,4 +1,4 @@
-Copyright (C) 2001-2023 Free Software Foundation, Inc.
+Copyright (C) 2001-2024 Free Software Foundation, Inc.
See the end of the file for license conditions.
diff --git a/src/alloc.c b/src/alloc.c
index c77bdc6372d..53ba85d88b7 100644
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -1,6 +1,6 @@
/* Storage allocation and gc for GNU Emacs Lisp interpreter.
-Copyright (C) 1985-2023 Free Software Foundation, Inc.
+Copyright (C) 1985-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
@@ -34,7 +34,6 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include "dispextern.h"
#include "intervals.h"
#include "puresize.h"
-#include "sheap.h"
#include "sysstdio.h"
#include "systime.h"
#include "character.h"
@@ -105,7 +104,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
or a new vector block is allocated (allocate_vector_from_block).
Accordingly, objects reused from the free list are unpoisoned.
- This feature can be disabled wtih the run-time flag
+ This feature can be disabled with the run-time flag
`allow_user_poisoning' set to zero. */
#if ADDRESS_SANITIZER && defined HAVE_SANITIZER_ASAN_INTERFACE_H \
&& !defined GC_ASAN_POISON_OBJECTS
@@ -413,31 +412,6 @@ static EMACS_INT gc_threshold;
const char *pending_malloc_warning;
-/* Pointer sanity only on request. FIXME: Code depending on
- SUSPICIOUS_OBJECT_CHECKING is obsolete; remove it entirely. */
-#ifdef ENABLE_CHECKING
-#define SUSPICIOUS_OBJECT_CHECKING 1
-#endif
-
-#ifdef SUSPICIOUS_OBJECT_CHECKING
-struct suspicious_free_record
-{
- void *suspicious_object;
- void *backtrace[128];
-};
-static void *suspicious_objects[32];
-static int suspicious_object_index;
-struct suspicious_free_record suspicious_free_history[64] EXTERNALLY_VISIBLE;
-static int suspicious_free_history_index;
-/* Find the first currently-monitored suspicious pointer in range
- [begin,end) or NULL if no such pointer exists. */
-static void *find_suspicious_object_in_range (void *begin, void *end);
-static void detect_suspicious_free (void *ptr);
-#else
-# define find_suspicious_object_in_range(begin, end) ((void *) NULL)
-# define detect_suspicious_free(ptr) ((void) 0)
-#endif
-
/* Maximum amount of C stack to save when a GC happens. */
#ifndef MAX_SAVE_STACK
@@ -3054,9 +3028,8 @@ enum { VECTOR_BLOCK_SIZE = 4096 };
/* Vector size requests are a multiple of this. */
enum { roundup_size = COMMON_MULTIPLE (LISP_ALIGNMENT, word_size) };
-/* Verify assumptions described above. */
+/* Verify assumption described above. */
verify (VECTOR_BLOCK_SIZE % roundup_size == 0);
-verify (VECTOR_BLOCK_SIZE <= (1 << PSEUDOVECTOR_SIZE_BITS));
/* Round up X to nearest mult-of-ROUNDUP_SIZE --- use at compile time. */
#define vroundup_ct(x) ROUNDUP (x, roundup_size)
@@ -3067,6 +3040,11 @@ verify (VECTOR_BLOCK_SIZE <= (1 << PSEUDOVECTOR_SIZE_BITS));
enum {VECTOR_BLOCK_BYTES = VECTOR_BLOCK_SIZE - vroundup_ct (sizeof (void *))};
+/* The current code expects to be able to represent an unused block by
+ a single PVEC_FREE object, whose size is limited by the header word.
+ (Of course we could use multiple such objects.) */
+verify (VECTOR_BLOCK_BYTES <= (word_size << PSEUDOVECTOR_REST_BITS));
+
/* Size of the minimal vector allocated from block. */
enum { VBLOCK_BYTES_MIN = vroundup_ct (header_size + sizeof (Lisp_Object)) };
@@ -3076,10 +3054,10 @@ enum { VBLOCK_BYTES_MIN = vroundup_ct (header_size + sizeof (Lisp_Object)) };
enum { VBLOCK_BYTES_MAX = vroundup_ct ((VECTOR_BLOCK_BYTES / 2) - word_size) };
/* We maintain one free list for each possible block-allocated
- vector size, and this is the number of free lists we have. */
-
-enum { VECTOR_MAX_FREE_LIST_INDEX =
- (VECTOR_BLOCK_BYTES - VBLOCK_BYTES_MIN) / roundup_size + 1 };
+ vector size, one for blocks one word bigger,
+ and one for all free vectors larger than that. */
+enum { VECTOR_FREE_LIST_ARRAY_SIZE =
+ (VBLOCK_BYTES_MAX - VBLOCK_BYTES_MIN) / roundup_size + 1 + 2 };
/* Common shortcut to advance vector pointer over a block data. */
@@ -3141,9 +3119,20 @@ struct vector_block
static struct vector_block *vector_blocks;
/* Vector free lists, where NTH item points to a chain of free
- vectors of the same NBYTES size, so NTH == VINDEX (NBYTES). */
+ vectors of the same NBYTES size, so NTH == VINDEX (NBYTES),
+ except for the last element which may contain larger vectors.
+
+ I.e., for each vector V in vector_free_lists[I] the following holds:
+ - V has type PVEC_FREE
+ - V's total size in bytes, BS(V) = PVSIZE(V) * word_size + header_size
+ - For I < VECTOR_FREE_LIST_ARRAY_SIZE-1, VINDEX(BS(V)) = I
+ - For I = VECTOR_FREE_LIST_ARRAY_SIZE-1, VINDEX(BS(V)) ≥ I */
+static struct Lisp_Vector *vector_free_lists[VECTOR_FREE_LIST_ARRAY_SIZE];
-static struct Lisp_Vector *vector_free_lists[VECTOR_MAX_FREE_LIST_INDEX];
+/* Index to the bucket in vector_free_lists into which we last inserted
+ or split a free vector. We use this as a heuristic telling us where
+ to start looking for free vectors when the exact-size bucket is empty. */
+static ptrdiff_t last_inserted_vector_free_idx = VECTOR_FREE_LIST_ARRAY_SIZE;
/* Singly-linked list of large vectors. */
@@ -3176,10 +3165,12 @@ setup_on_free_list (struct Lisp_Vector *v, ptrdiff_t nbytes)
XSETPVECTYPESIZE (v, PVEC_FREE, 0, nwords);
eassert (nbytes % roundup_size == 0);
ptrdiff_t vindex = VINDEX (nbytes);
- eassert (vindex < VECTOR_MAX_FREE_LIST_INDEX);
+ /* Anything too large goes into the last slot (overflow bin). */
+ vindex = min(vindex, VECTOR_FREE_LIST_ARRAY_SIZE - 1);
set_next_vector (v, vector_free_lists[vindex]);
ASAN_POISON_VECTOR_CONTENTS (v, nbytes - header_size);
vector_free_lists[vindex] = v;
+ last_inserted_vector_free_idx = vindex;
}
/* Get a new vector block. */
@@ -3208,6 +3199,17 @@ init_vectors (void)
staticpro (&zero_vector);
}
+/* Memory footprint in bytes of a pseudovector other than a bool-vector. */
+static ptrdiff_t
+pseudovector_nbytes (const union vectorlike_header *hdr)
+{
+ eassert (!PSEUDOVECTOR_TYPEP (hdr, PVEC_BOOL_VECTOR));
+ ptrdiff_t nwords = ((hdr->size & PSEUDOVECTOR_SIZE_MASK)
+ + ((hdr->size & PSEUDOVECTOR_REST_MASK)
+ >> PSEUDOVECTOR_SIZE_BITS));
+ return vroundup (header_size + word_size * nwords);
+}
+
/* Allocate vector from a vector block. */
static struct Lisp_Vector *
@@ -3234,18 +3236,21 @@ allocate_vector_from_block (ptrdiff_t nbytes)
/* Next, check free lists containing larger vectors. Since
we will split the result, we should have remaining space
large enough to use for one-slot vector at least. */
- for (index = VINDEX (nbytes + VBLOCK_BYTES_MIN);
- index < VECTOR_MAX_FREE_LIST_INDEX; index++)
+ for (index = max (VINDEX (nbytes + VBLOCK_BYTES_MIN),
+ last_inserted_vector_free_idx);
+ index < VECTOR_FREE_LIST_ARRAY_SIZE; index++)
if (vector_free_lists[index])
{
/* This vector is larger than requested. */
vector = vector_free_lists[index];
+ size_t vector_nbytes = pseudovector_nbytes (&vector->header);
+ eassert (vector_nbytes > nbytes);
ASAN_UNPOISON_VECTOR_CONTENTS (vector, nbytes - header_size);
vector_free_lists[index] = next_vector (vector);
/* Excess bytes are used for the smaller vector,
which should be set on an appropriate free list. */
- restbytes = index * roundup_size + VBLOCK_BYTES_MIN - nbytes;
+ restbytes = vector_nbytes - nbytes;
eassert (restbytes % roundup_size == 0);
#if GC_ASAN_POISON_OBJECTS
/* Ensure that accessing excess bytes does not trigger ASan. */
@@ -3299,9 +3304,7 @@ vectorlike_nbytes (const union vectorlike_header *hdr)
nwords = (boolvec_bytes - header_size + word_size - 1) / word_size;
}
else
- nwords = ((size & PSEUDOVECTOR_SIZE_MASK)
- + ((size & PSEUDOVECTOR_REST_MASK)
- >> PSEUDOVECTOR_SIZE_BITS));
+ return pseudovector_nbytes (hdr);
}
else
nwords = size;
@@ -3323,94 +3326,134 @@ vectorlike_nbytes (const union vectorlike_header *hdr)
static void
cleanup_vector (struct Lisp_Vector *vector)
{
- detect_suspicious_free (vector);
-
- if (PSEUDOVECTOR_TYPEP (&vector->header, PVEC_BIGNUM))
- mpz_clear (PSEUDOVEC_STRUCT (vector, Lisp_Bignum)->value);
- else if (PSEUDOVECTOR_TYPEP (&vector->header, PVEC_OVERLAY))
+ if ((vector->header.size & PSEUDOVECTOR_FLAG) == 0)
+ return; /* nothing more to do for plain vectors */
+ switch (PSEUDOVECTOR_TYPE (vector))
{
- struct Lisp_Overlay *ol = PSEUDOVEC_STRUCT (vector, Lisp_Overlay);
- xfree (ol->interval);
- }
- else if (PSEUDOVECTOR_TYPEP (&vector->header, PVEC_FINALIZER))
- unchain_finalizer (PSEUDOVEC_STRUCT (vector, Lisp_Finalizer));
- else if (PSEUDOVECTOR_TYPEP (&vector->header, PVEC_FONT))
- {
- if ((vector->header.size & PSEUDOVECTOR_SIZE_MASK) == FONT_OBJECT_MAX)
- {
- struct font *font = PSEUDOVEC_STRUCT (vector, font);
- struct font_driver const *drv = font->driver;
+ case PVEC_BIGNUM:
+ mpz_clear (PSEUDOVEC_STRUCT (vector, Lisp_Bignum)->value);
+ break;
+ case PVEC_OVERLAY:
+ {
+ struct Lisp_Overlay *ol = PSEUDOVEC_STRUCT (vector, Lisp_Overlay);
+ xfree (ol->interval);
+ }
+ break;
+ case PVEC_FINALIZER:
+ unchain_finalizer (PSEUDOVEC_STRUCT (vector, Lisp_Finalizer));
+ break;
+ case PVEC_FONT:
+ {
+ if ((vector->header.size & PSEUDOVECTOR_SIZE_MASK) == FONT_OBJECT_MAX)
+ {
+ struct font *font = PSEUDOVEC_STRUCT (vector, font);
+ struct font_driver const *drv = font->driver;
- /* The font driver might sometimes be NULL, e.g. if Emacs was
- interrupted before it had time to set it up. */
- if (drv)
- {
- /* Attempt to catch subtle bugs like Bug#16140. */
- eassert (valid_font_driver (drv));
- drv->close_font (font);
- }
- }
+ /* The font driver might sometimes be NULL, e.g. if Emacs was
+ interrupted before it had time to set it up. */
+ if (drv)
+ {
+ /* Attempt to catch subtle bugs like Bug#16140. */
+ eassert (valid_font_driver (drv));
+ drv->close_font (font);
+ }
+ }
#if defined HAVE_ANDROID && !defined ANDROID_STUBIFY
- /* The Android font driver needs the ability to associate extra
- information with font entities. */
- if (((vector->header.size & PSEUDOVECTOR_SIZE_MASK)
- == FONT_ENTITY_MAX)
- && PSEUDOVEC_STRUCT (vector, font_entity)->is_android)
- android_finalize_font_entity (PSEUDOVEC_STRUCT (vector, font_entity));
+ /* The Android font driver needs the ability to associate extra
+ information with font entities. */
+ if (((vector->header.size & PSEUDOVECTOR_SIZE_MASK)
+ == FONT_ENTITY_MAX)
+ && PSEUDOVEC_STRUCT (vector, font_entity)->is_android)
+ android_finalize_font_entity (PSEUDOVEC_STRUCT (vector, font_entity));
#endif
- }
- else if (PSEUDOVECTOR_TYPEP (&vector->header, PVEC_THREAD))
- finalize_one_thread (PSEUDOVEC_STRUCT (vector, thread_state));
- else if (PSEUDOVECTOR_TYPEP (&vector->header, PVEC_MUTEX))
- finalize_one_mutex (PSEUDOVEC_STRUCT (vector, Lisp_Mutex));
- else if (PSEUDOVECTOR_TYPEP (&vector->header, PVEC_CONDVAR))
- finalize_one_condvar (PSEUDOVEC_STRUCT (vector, Lisp_CondVar));
- else if (PSEUDOVECTOR_TYPEP (&vector->header, PVEC_MARKER))
- {
+ }
+ break;
+ case PVEC_THREAD:
+ finalize_one_thread (PSEUDOVEC_STRUCT (vector, thread_state));
+ break;
+ case PVEC_MUTEX:
+ finalize_one_mutex (PSEUDOVEC_STRUCT (vector, Lisp_Mutex));
+ break;
+ case PVEC_CONDVAR:
+ finalize_one_condvar (PSEUDOVEC_STRUCT (vector, Lisp_CondVar));
+ break;
+ case PVEC_MARKER:
/* sweep_buffer should already have unchained this from its buffer. */
eassert (! PSEUDOVEC_STRUCT (vector, Lisp_Marker)->buffer);
- }
- else if (PSEUDOVECTOR_TYPEP (&vector->header, PVEC_USER_PTR))
- {
- struct Lisp_User_Ptr *uptr = PSEUDOVEC_STRUCT (vector, Lisp_User_Ptr);
- if (uptr->finalizer)
- uptr->finalizer (uptr->p);
- }
+ break;
+ case PVEC_USER_PTR:
+ {
+ struct Lisp_User_Ptr *uptr = PSEUDOVEC_STRUCT (vector, Lisp_User_Ptr);
+ if (uptr->finalizer)
+ uptr->finalizer (uptr->p);
+ }
+ break;
+ case PVEC_TS_PARSER:
#ifdef HAVE_TREE_SITTER
- else if (PSEUDOVECTOR_TYPEP (&vector->header, PVEC_TS_PARSER))
- treesit_delete_parser (PSEUDOVEC_STRUCT (vector, Lisp_TS_Parser));
- else if (PSEUDOVECTOR_TYPEP (&vector->header, PVEC_TS_COMPILED_QUERY))
- treesit_delete_query (PSEUDOVEC_STRUCT (vector, Lisp_TS_Query));
+ treesit_delete_parser (PSEUDOVEC_STRUCT (vector, Lisp_TS_Parser));
#endif
+ break;
+ case PVEC_TS_COMPILED_QUERY:
+#ifdef HAVE_TREE_SITTER
+ treesit_delete_query (PSEUDOVEC_STRUCT (vector, Lisp_TS_Query));
+#endif
+ break;
+ case PVEC_MODULE_FUNCTION:
#ifdef HAVE_MODULES
- else if (PSEUDOVECTOR_TYPEP (&vector->header, PVEC_MODULE_FUNCTION))
- {
- ATTRIBUTE_MAY_ALIAS struct Lisp_Module_Function *function
- = (struct Lisp_Module_Function *) vector;
- module_finalize_function (function);
- }
+ {
+ ATTRIBUTE_MAY_ALIAS struct Lisp_Module_Function *function
+ = (struct Lisp_Module_Function *) vector;
+ module_finalize_function (function);
+ }
#endif
+ break;
+ case PVEC_NATIVE_COMP_UNIT:
#ifdef HAVE_NATIVE_COMP
- else if (PSEUDOVECTOR_TYPEP (&vector->header, PVEC_NATIVE_COMP_UNIT))
- {
- struct Lisp_Native_Comp_Unit *cu =
- PSEUDOVEC_STRUCT (vector, Lisp_Native_Comp_Unit);
- unload_comp_unit (cu);
- }
- else if (PSEUDOVECTOR_TYPEP (&vector->header, PVEC_SUBR))
- {
- struct Lisp_Subr *subr =
- PSEUDOVEC_STRUCT (vector, Lisp_Subr);
- if (!NILP (subr->native_comp_u))
- {
- /* FIXME Alternative and non invasive solution to this
- cast? */
- xfree ((char *)subr->symbol_name);
- xfree (subr->native_c_name);
- }
- }
+ {
+ struct Lisp_Native_Comp_Unit *cu =
+ PSEUDOVEC_STRUCT (vector, Lisp_Native_Comp_Unit);
+ unload_comp_unit (cu);
+ }
#endif
+ break;
+ case PVEC_SUBR:
+#ifdef HAVE_NATIVE_COMP
+ {
+ struct Lisp_Subr *subr = PSEUDOVEC_STRUCT (vector, Lisp_Subr);
+ if (!NILP (subr->native_comp_u))
+ {
+ /* FIXME Alternative and non invasive solution to this cast? */
+ xfree ((char *)subr->symbol_name);
+ xfree (subr->native_c_name);
+ }
+ }
+#endif
+ break;
+ /* Keep the switch exhaustive. */
+ case PVEC_NORMAL_VECTOR:
+ case PVEC_FREE:
+ case PVEC_SYMBOL_WITH_POS:
+ case PVEC_MISC_PTR:
+ case PVEC_PROCESS:
+ case PVEC_FRAME:
+ case PVEC_WINDOW:
+ case PVEC_BOOL_VECTOR:
+ case PVEC_BUFFER:
+ case PVEC_HASH_TABLE:
+ case PVEC_TERMINAL:
+ case PVEC_WINDOW_CONFIGURATION:
+ case PVEC_OTHER:
+ case PVEC_XWIDGET:
+ case PVEC_XWIDGET_VIEW:
+ case PVEC_TS_NODE:
+ case PVEC_SQLITE:
+ case PVEC_COMPILED:
+ case PVEC_CHAR_TABLE:
+ case PVEC_SUB_CHAR_TABLE:
+ case PVEC_RECORD:
+ break;
+ }
}
/* Reclaim space used by unmarked vectors. */
@@ -3426,6 +3469,7 @@ sweep_vectors (void)
gcstat.total_vectors = 0;
gcstat.total_vector_slots = gcstat.total_free_vector_slots = 0;
memset (vector_free_lists, 0, sizeof (vector_free_lists));
+ last_inserted_vector_free_idx = VECTOR_FREE_LIST_ARRAY_SIZE;
/* Looking through vector blocks. */
@@ -3559,9 +3603,6 @@ allocate_vectorlike (ptrdiff_t len, bool clearit)
mallopt (M_MMAP_MAX, MMAP_MAX_AREAS);
#endif
- if (find_suspicious_object_in_range (p, (char *) p + nbytes))
- emacs_abort ();
-
tally_consing (nbytes);
vector_cells_consed += len;
@@ -3613,7 +3654,7 @@ allocate_pseudovector (int memlen, int lisplen,
enum { size_max = (1 << PSEUDOVECTOR_SIZE_BITS) - 1 };
enum { rest_max = (1 << PSEUDOVECTOR_REST_BITS) - 1 };
verify (size_max + rest_max <= VECTOR_ELTS_MAX);
- eassert (0 <= tag && tag <= PVEC_FONT);
+ eassert (0 <= tag && tag <= PVEC_TAG_MAX);
eassert (0 <= lisplen && lisplen <= zerolen && zerolen <= memlen);
eassert (lisplen <= size_max);
eassert (memlen <= size_max + rest_max);
@@ -6534,7 +6575,7 @@ garbage_collect (void)
/* Everything is now marked, except for the data in font caches,
undo lists, and finalizers. The first two are compacted by
- removing an items which aren't reachable otherwise. */
+ removing any items which aren't reachable otherwise. */
compact_font_caches ();
@@ -6595,13 +6636,6 @@ garbage_collect (void)
image_prune_animation_caches (false);
#endif
- if (!NILP (Vpost_gc_hook))
- {
- specpdl_ref gc_count = inhibit_garbage_collection ();
- safe_run_hooks (Qpost_gc_hook);
- unbind_to (gc_count, Qnil);
- }
-
/* Accumulate statistics. */
if (FLOATP (Vgc_elapsed))
{
@@ -6620,6 +6654,13 @@ garbage_collect (void)
if (tot_after < tot_before)
malloc_probe (min (tot_before - tot_after, SIZE_MAX));
}
+
+ if (!NILP (Vpost_gc_hook))
+ {
+ specpdl_ref gc_count = inhibit_garbage_collection ();
+ safe_run_hooks (Qpost_gc_hook);
+ unbind_to (gc_count, Qnil);
+ }
}
DEFUN ("garbage-collect", Fgarbage_collect, Sgarbage_collect, 0, 0, "",
@@ -6891,20 +6932,6 @@ mark_face_cache (struct face_cache *c)
}
}
-NO_INLINE /* To reduce stack depth in mark_object. */
-static void
-mark_localized_symbol (struct Lisp_Symbol *ptr)
-{
- struct Lisp_Buffer_Local_Value *blv = SYMBOL_BLV (ptr);
- Lisp_Object where = blv->where;
- /* If the value is set up for a killed buffer restore its global binding. */
- if ((BUFFERP (where) && !BUFFER_LIVE_P (XBUFFER (where))))
- swap_in_global_binding (ptr);
- mark_object (blv->where);
- mark_object (blv->valcell);
- mark_object (blv->defcell);
-}
-
/* Remove killed buffers or items whose car is a killed buffer from
LIST, and mark other items. Return changed LIST, which is marked. */
@@ -7306,7 +7333,17 @@ process_mark_stack (ptrdiff_t base_sp)
break;
}
case SYMBOL_LOCALIZED:
- mark_localized_symbol (ptr);
+ {
+ struct Lisp_Buffer_Local_Value *blv = SYMBOL_BLV (ptr);
+ Lisp_Object where = blv->where;
+ /* If the value is set up for a killed buffer,
+ restore its global binding. */
+ if (BUFFERP (where) && !BUFFER_LIVE_P (XBUFFER (where)))
+ swap_in_global_binding (ptr);
+ mark_stack_push_value (blv->where);
+ mark_stack_push_value (blv->valcell);
+ mark_stack_push_value (blv->defcell);
+ }
break;
case SYMBOL_FORWARDED:
/* If the value is forwarded to a buffer or keyboard field,
@@ -7953,78 +7990,6 @@ which_symbols (Lisp_Object obj, EMACS_INT find_max)
return unbind_to (gc_count, found);
}
-#ifdef SUSPICIOUS_OBJECT_CHECKING
-
-static void *
-find_suspicious_object_in_range (void *begin, void *end)
-{
- char *begin_a = begin;
- char *end_a = end;
- int i;
-
- for (i = 0; i < ARRAYELTS (suspicious_objects); ++i)
- {
- char *suspicious_object = suspicious_objects[i];
- if (begin_a <= suspicious_object && suspicious_object < end_a)
- return suspicious_object;
- }
-
- return NULL;
-}
-
-static void
-note_suspicious_free (void *ptr)
-{
- struct suspicious_free_record *rec;
-
- rec = &suspicious_free_history[suspicious_free_history_index++];
- if (suspicious_free_history_index ==
- ARRAYELTS (suspicious_free_history))
- {
- suspicious_free_history_index = 0;
- }
-
- memset (rec, 0, sizeof (*rec));
- rec->suspicious_object = ptr;
- backtrace (&rec->backtrace[0], ARRAYELTS (rec->backtrace));
-}
-
-static void
-detect_suspicious_free (void *ptr)
-{
- int i;
-
- eassert (ptr != NULL);
-
- for (i = 0; i < ARRAYELTS (suspicious_objects); ++i)
- if (suspicious_objects[i] == ptr)
- {
- note_suspicious_free (ptr);
- suspicious_objects[i] = NULL;
- }
-}
-
-#endif /* SUSPICIOUS_OBJECT_CHECKING */
-
-DEFUN ("suspicious-object", Fsuspicious_object, Ssuspicious_object, 1, 1, 0,
- doc: /* Return OBJ, maybe marking it for extra scrutiny.
-If Emacs is compiled with suspicious object checking, capture
-a stack trace when OBJ is freed in order to help track down
-garbage collection bugs. Otherwise, do nothing and return OBJ. */)
- (Lisp_Object obj)
-{
-#ifdef SUSPICIOUS_OBJECT_CHECKING
- /* Right now, we care only about vectors. */
- if (VECTORLIKEP (obj))
- {
- suspicious_objects[suspicious_object_index++] = XVECTOR (obj);
- if (suspicious_object_index == ARRAYELTS (suspicious_objects))
- suspicious_object_index = 0;
- }
-#endif
- return obj;
-}
-
#ifdef ENABLE_CHECKING
bool suppress_checking;
@@ -8256,7 +8221,6 @@ N should be nonnegative. */);
#ifdef HAVE_MALLOC_TRIM
defsubr (&Smalloc_trim);
#endif
- defsubr (&Ssuspicious_object);
Lisp_Object watcher;
diff --git a/src/android-asset.h b/src/android-asset.h
index 4fb309f1645..a6b5aa3366c 100644
--- a/src/android-asset.h
+++ b/src/android-asset.h
@@ -1,6 +1,6 @@
/* Android initialization for GNU Emacs.
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
@@ -340,7 +340,7 @@ android_asset_read_internal (AAsset *asset, int nbytes, char *buffer)
/* Detect error conditions. */
if ((*env)->ExceptionCheck (env))
- goto out;
+ goto out_errno;
/* Detect EOF. */
@@ -363,6 +363,14 @@ android_asset_read_internal (AAsset *asset, int nbytes, char *buffer)
(*env)->ExceptionClear (env);
(*env)->DeleteLocalRef (env, stash);
return total;
+
+ out_errno:
+ /* Return an error indication if an exception arises while the file
+ is being read. */
+ (*env)->ExceptionClear (env);
+ (*env)->DeleteLocalRef (env, stash);
+ errno = EIO;
+ return -1;
}
static long
@@ -399,7 +407,7 @@ AAsset_getBuffer (AAsset *asset)
if (android_asset_read_internal (asset, length, buffer)
!= length)
{
- xfree (buffer);
+ free (buffer);
return NULL;
}
diff --git a/src/android-emacs.c b/src/android-emacs.c
index 2c405795860..5a43445612a 100644
--- a/src/android-emacs.c
+++ b/src/android-emacs.c
@@ -1,6 +1,6 @@
/* Android initialization for GNU Emacs.
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/android.c b/src/android.c
index ed304baf0e6..757f256c188 100644
--- a/src/android.c
+++ b/src/android.c
@@ -1,6 +1,6 @@
/* Android initialization for GNU Emacs.
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
@@ -18,6 +18,7 @@ You should have received a copy of the GNU General Public License
along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include <config.h>
+
#include <allocator.h>
#include <assert.h>
#include <careadlinkat.h>
@@ -31,12 +32,15 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include <pthread.h>
#include <semaphore.h>
#include <signal.h>
+#include <stat-time.h>
#include <stdckdint.h>
#include <string.h>
-#include <sys/param.h>
#include <timespec.h>
#include <unistd.h>
+#include <sys/param.h>
+#include <sys/stat.h>
+
/* Old NDK versions lack MIN and MAX. */
#include <minmax.h>
@@ -47,6 +51,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include "blockinput.h"
#include "coding.h"
#include "epaths.h"
+#include "systime.h"
/* Whether or not Emacs is running inside the application process and
Android windowing should be enabled. */
@@ -68,7 +73,6 @@ bool android_init_gui;
struct android_emacs_pixmap
{
jclass class;
- jmethodID constructor;
jmethodID constructor_mutable;
};
@@ -82,7 +86,6 @@ struct android_emacs_drawable
{
jclass class;
jmethodID get_bitmap;
- jmethodID damage_rect;
};
struct android_emacs_window
@@ -101,11 +104,13 @@ struct android_emacs_window
jmethodID make_input_focus;
jmethodID raise;
jmethodID lower;
+ jmethodID reconfigure;
jmethodID get_window_geometry;
jmethodID translate_coordinates;
jmethodID set_dont_accept_focus;
jmethodID set_dont_focus_on_map;
jmethodID define_cursor;
+ jmethodID damage_rect;
};
struct android_emacs_cursor
@@ -187,6 +192,10 @@ static struct android_emacs_window window_class;
/* Various methods associated with the EmacsCursor class. */
static struct android_emacs_cursor cursor_class;
+/* The time at which Emacs was installed, which also supplies the
+ mtime of asset files. */
+struct timespec emacs_installation_time;
+
/* The last event serial used. This is a 32 bit value, but it is
stored in unsigned long to be consistent with X. */
unsigned int event_serial;
@@ -273,6 +282,46 @@ static volatile sig_atomic_t android_pselect_interrupted;
#endif
+/* Set the task name of the current task to NAME, a string at most 16
+ characters in length.
+
+ This name is displayed as that of the task (LWP)'s pthread in
+ GDB. */
+
+static void
+android_set_task_name (const char *name)
+{
+ char proc_name[INT_STRLEN_BOUND (long)
+ + sizeof "/proc/self/task//comm"];
+ int fd;
+ pid_t lwp;
+ size_t length;
+
+ lwp = gettid ();
+ sprintf (proc_name, "/proc/self/task/%ld/comm", (long) lwp);
+ fd = open (proc_name, O_WRONLY | O_TRUNC);
+
+ if (fd < 0)
+ goto failure;
+
+ length = strlen (name);
+
+ if (write (fd, name, MIN (16, length)) < 0)
+ goto failure;
+
+ close (fd);
+ return;
+
+ failure:
+ __android_log_print (ANDROID_LOG_WARN, __func__,
+ "Failed to set task name for LWP %ld: %s",
+ (long) lwp, strerror (errno));
+
+ /* Close the file descriptor if it is already set. */
+ if (fd >= 0)
+ close (fd);
+}
+
static void *
android_run_select_thread (void *data)
{
@@ -289,6 +338,9 @@ android_run_select_thread (void *data)
int sig;
#endif
+ /* Set the name of this thread's LWP for debugging purposes. */
+ android_set_task_name ("`android_select'");
+
#if __ANDROID_API__ < 16
/* A completely different implementation is used when building for
Android versions earlier than 16, because pselect with a signal
@@ -788,6 +840,9 @@ android_run_debug_thread (void *data)
char *line;
size_t n;
+ /* Set the name of this thread's LWP for debugging purposes. */
+ android_set_task_name ("`android_debug'");
+
fd = (int) (intptr_t) data;
file = fdopen (fd, "r");
@@ -824,22 +879,18 @@ android_user_full_name (struct passwd *pw)
return (char *) "Android user";
return pw->pw_gecos;
-#else
+#else /* !HAVE_STRUCT_PASSWD_PW_GECOS */
return "Android user";
-#endif
+#endif /* HAVE_STRUCT_PASSWD_PW_GECOS */
}
-/* Determine whether or not the specified file NAME describes a file
- in the directory DIR, which should be an absolute file name. NAME
- must be in canonical form.
+/* Return whether or not the specified file NAME designates a file in
+ the directory DIR, which should be an absolute file name. NAME
+ must be in canonical form. */
- Value is NULL if not. Otherwise, it is a pointer to the first
- character in NAME after the part containing DIR and its trailing
- directory separator. */
-
-const char *
+bool
android_is_special_directory (const char *name, const char *dir)
{
size_t len;
@@ -848,7 +899,7 @@ android_is_special_directory (const char *name, const char *dir)
len = strlen (dir);
if (strncmp (name, dir, len))
- return NULL;
+ return false;
/* Now see if the character of NAME after len is either a directory
separator or a terminating NULL. */
@@ -856,20 +907,13 @@ android_is_special_directory (const char *name, const char *dir)
name += len;
switch (*name)
{
- case '\0':
- /* Return the empty string if this is the end of the file
- name. */
- return name;
-
- case '/':
- /* Return NAME (with the separator removed) if it describes a
- file. */
- return name + 1;
-
- default:
- /* The file name doesn't match. */
- return NULL;
+ case '\0': /* NAME is an exact match for DIR. */
+ case '/': /* NAME is a constituent of DIR. */
+ return true;
}
+
+ /* The file name doesn't match. */
+ return false;
}
#if 0
@@ -1216,6 +1260,14 @@ NATIVE_NAME (dup) (JNIEnv *env, jobject object, jint fd)
return dup (fd);
}
+JNIEXPORT jint JNICALL
+NATIVE_NAME (close) (JNIEnv *env, jobject object, jint fd)
+{
+ JNI_STACK_ALIGNMENT_PROLOGUE;
+
+ return close (fd);
+}
+
JNIEXPORT jstring JNICALL
NATIVE_NAME (getFingerprint) (JNIEnv *env, jobject object)
{
@@ -1247,6 +1299,7 @@ NATIVE_NAME (setEmacsParams) (JNIEnv *env, jobject object,
int pipefd[2];
pthread_t thread;
const char *java_string;
+ struct stat statb;
/* Set the Android API level early, as it is used by
`android_vfs_init'. */
@@ -1341,13 +1394,24 @@ NATIVE_NAME (setEmacsParams) (JNIEnv *env, jobject object,
android_class_path = strdup ((const char *) java_string);
- if (!android_files_dir)
+ if (!android_class_path)
emacs_abort ();
(*env)->ReleaseStringUTFChars (env, (jstring) class_path,
java_string);
}
+ /* Derive the installation date from the modification time of the
+ file constitituing the class path. */
+
+ emacs_installation_time = invalid_timespec ();
+
+ if (class_path)
+ {
+ if (!stat (android_class_path, &statb))
+ emacs_installation_time = get_stat_mtime (&statb);
+ }
+
/* Calculate the site-lisp path. */
android_site_load_path = malloc (PATH_MAX + 1);
@@ -1391,6 +1455,18 @@ NATIVE_NAME (setEmacsParams) (JNIEnv *env, jobject object,
the possibility of Java locating libemacs later. */
setenv ("EMACS_LD_LIBRARY_PATH", android_lib_dir, 1);
+ /* If the system is Android 5.0 or later, set LANG to en_US.utf8,
+ which is understood by the C library. In other instances set it
+ to C, a meaningless value, for good measure. */
+
+ if (emacs_service_object)
+ {
+ if (api_level >= 21)
+ setenv ("LANG", "en_US.utf8", 1);
+ else
+ setenv ("LANG", "C", 1);
+ }
+
/* Make a reference to the Emacs service. */
if (emacs_service_object)
@@ -1475,7 +1551,7 @@ android_init_emacs_service (void)
= (*android_java_env)->GetMethodID (android_java_env, \
service_class.class, \
name, signature); \
- assert (service_class.c_name);
+ eassert (service_class.c_name);
FIND_METHOD (fill_rectangle, "fillRectangle",
"(Lorg/gnu/emacs/EmacsDrawable;"
@@ -1497,7 +1573,7 @@ android_init_emacs_service (void)
"(Lorg/gnu/emacs/EmacsWindow;)V");
FIND_METHOD (clear_area, "clearArea",
"(Lorg/gnu/emacs/EmacsWindow;IIII)V");
- FIND_METHOD (ring_bell, "ringBell", "()V");
+ FIND_METHOD (ring_bell, "ringBell", "(I)V");
FIND_METHOD (query_tree, "queryTree",
"(Lorg/gnu/emacs/EmacsWindow;)[S");
FIND_METHOD (get_screen_width, "getScreenWidth", "(Z)I");
@@ -1564,6 +1640,10 @@ android_init_emacs_service (void)
"Ljava/lang/String;)Ljava/lang/String;");
FIND_METHOD (valid_authority, "validAuthority",
"(Ljava/lang/String;)Z");
+ FIND_METHOD (external_storage_available,
+ "externalStorageAvailable", "()Z");
+ FIND_METHOD (request_storage_access,
+ "requestStorageAccess", "()V");
#undef FIND_METHOD
}
@@ -1591,9 +1671,8 @@ android_init_emacs_pixmap (void)
= (*android_java_env)->GetMethodID (android_java_env, \
pixmap_class.class, \
name, signature); \
- assert (pixmap_class.c_name);
+ eassert (pixmap_class.c_name);
- FIND_METHOD (constructor, "<init>", "(S[IIII)V");
FIND_METHOD (constructor_mutable, "<init>", "(SIII)V");
#undef FIND_METHOD
@@ -1623,7 +1702,7 @@ android_init_graphics_point (void)
= (*android_java_env)->GetMethodID (android_java_env, \
point_class.class, \
name, signature); \
- assert (point_class.c_name);
+ eassert (point_class.c_name);
FIND_METHOD (constructor, "<init>", "(II)V");
#undef FIND_METHOD
@@ -1653,10 +1732,9 @@ android_init_emacs_drawable (void)
= (*android_java_env)->GetMethodID (android_java_env, \
drawable_class.class, \
name, signature); \
- assert (drawable_class.c_name);
+ eassert (drawable_class.c_name);
FIND_METHOD (get_bitmap, "getBitmap", "()Landroid/graphics/Bitmap;");
- FIND_METHOD (damage_rect, "damageRect", "(Landroid/graphics/Rect;)V");
#undef FIND_METHOD
}
@@ -1684,7 +1762,7 @@ android_init_emacs_window (void)
= (*android_java_env)->GetMethodID (android_java_env, \
window_class.class, \
name, signature); \
- assert (window_class.c_name);
+ eassert (window_class.c_name);
FIND_METHOD (swap_buffers, "swapBuffers", "()V");
FIND_METHOD (toggle_on_screen_keyboard,
@@ -1702,6 +1780,7 @@ android_init_emacs_window (void)
FIND_METHOD (make_input_focus, "makeInputFocus", "(J)V");
FIND_METHOD (raise, "raise", "()V");
FIND_METHOD (lower, "lower", "()V");
+ FIND_METHOD (reconfigure, "reconfigure", "(Lorg/gnu/emacs/EmacsWindow;I)V");
FIND_METHOD (get_window_geometry, "getWindowGeometry",
"()[I");
FIND_METHOD (translate_coordinates, "translateCoordinates",
@@ -1710,6 +1789,12 @@ android_init_emacs_window (void)
FIND_METHOD (set_dont_accept_focus, "setDontAcceptFocus", "(Z)V");
FIND_METHOD (define_cursor, "defineCursor",
"(Lorg/gnu/emacs/EmacsCursor;)V");
+
+ /* In spite of the declaration of this function being located within
+ EmacsDrawable, the ID of the `damage_rect' method is retrieved
+ from EmacsWindow, which avoids virtual function dispatch within
+ android_damage_window. */
+ FIND_METHOD (damage_rect, "damageRect", "(IIII)V");
#undef FIND_METHOD
}
@@ -1737,7 +1822,7 @@ android_init_emacs_cursor (void)
= (*android_java_env)->GetMethodID (android_java_env, \
cursor_class.class, \
name, signature); \
- assert (cursor_class.c_name);
+ eassert (cursor_class.c_name);
FIND_METHOD (constructor, "<init>", "(SI)V");
#undef FIND_METHOD
@@ -1765,7 +1850,7 @@ NATIVE_NAME (initEmacs) (JNIEnv *env, jobject object, jarray argv,
android_java_env = env;
nelements = (*env)->GetArrayLength (env, argv);
- c_argv = alloca (sizeof *c_argv * nelements);
+ c_argv = alloca (sizeof *c_argv * (nelements + 1));
for (i = 0; i < nelements; ++i)
{
@@ -1783,6 +1868,8 @@ NATIVE_NAME (initEmacs) (JNIEnv *env, jobject object, jarray argv,
(*env)->ReleaseStringUTFChars (env, (jstring) argument, c_argument);
}
+ c_argv[nelements] = NULL;
+
android_init_emacs_service ();
android_init_emacs_pixmap ();
android_init_graphics_point ();
@@ -1867,6 +1954,45 @@ NATIVE_NAME (quit) (JNIEnv *env, jobject object)
kill (getpid (), SIGIO);
}
+/* Call shut_down_emacs subsequent to a call to the service's
+ onDestroy callback. CLOSURE is ignored. */
+
+static void
+android_shut_down_emacs (void *closure)
+{
+ __android_log_print (ANDROID_LOG_INFO, __func__,
+ "The Emacs service is being shut down");
+ shut_down_emacs (0, Qnil);
+}
+
+JNIEXPORT void JNICALL
+NATIVE_NAME (shutDownEmacs) (JNIEnv *env, jobject object)
+{
+ JNI_STACK_ALIGNMENT_PROLOGUE;
+
+ android_run_in_emacs_thread (android_shut_down_emacs, NULL);
+}
+
+/* Carry out garbage collection and clear all image caches on the
+ Android terminal. Called when the system has depleted most of its
+ memory and desires that background processes release unused
+ core. */
+
+static void
+android_on_low_memory (void *closure)
+{
+ Fclear_image_cache (Qt, Qnil);
+ garbage_collect ();
+}
+
+JNIEXPORT void JNICALL
+NATIVE_NAME (onLowMemory) (JNIEnv *env, jobject object)
+{
+ JNI_STACK_ALIGNMENT_PROLOGUE;
+
+ android_run_in_emacs_thread (android_on_low_memory, NULL);
+}
+
JNIEXPORT jlong JNICALL
NATIVE_NAME (sendConfigureNotify) (JNIEnv *env, jobject object,
jshort window, jlong time,
@@ -2259,6 +2385,100 @@ NATIVE_NAME (sendExpose) (JNIEnv *env, jobject object,
}
JNIEXPORT jboolean JNICALL
+NATIVE_NAME (sendDndDrag) (JNIEnv *env, jobject object,
+ jshort window, jint x, jint y)
+{
+ JNI_STACK_ALIGNMENT_PROLOGUE;
+
+ union android_event event;
+
+ event.dnd.type = ANDROID_DND_DRAG_EVENT;
+ event.dnd.serial = ++event_serial;
+ event.dnd.window = window;
+ event.dnd.x = x;
+ event.dnd.y = y;
+ event.dnd.uri_or_string = NULL;
+ event.dnd.length = 0;
+
+ android_write_event (&event);
+ return event_serial;
+}
+
+JNIEXPORT jboolean JNICALL
+NATIVE_NAME (sendDndUri) (JNIEnv *env, jobject object,
+ jshort window, jint x, jint y,
+ jstring string)
+{
+ JNI_STACK_ALIGNMENT_PROLOGUE;
+
+ union android_event event;
+ const jchar *characters;
+ jsize length;
+ uint16_t *buffer;
+
+ event.dnd.type = ANDROID_DND_URI_EVENT;
+ event.dnd.serial = ++event_serial;
+ event.dnd.window = window;
+ event.dnd.x = x;
+ event.dnd.y = y;
+
+ length = (*env)->GetStringLength (env, string);
+ buffer = malloc (length * sizeof *buffer);
+ characters = (*env)->GetStringChars (env, string, NULL);
+
+ if (!characters)
+ /* The JVM has run out of memory; return and let the out of memory
+ error take its course. */
+ return 0;
+
+ memcpy (buffer, characters, length * sizeof *buffer);
+ (*env)->ReleaseStringChars (env, string, characters);
+
+ event.dnd.uri_or_string = buffer;
+ event.dnd.length = length;
+
+ android_write_event (&event);
+ return event_serial;
+}
+
+JNIEXPORT jboolean JNICALL
+NATIVE_NAME (sendDndText) (JNIEnv *env, jobject object,
+ jshort window, jint x, jint y,
+ jstring string)
+{
+ JNI_STACK_ALIGNMENT_PROLOGUE;
+
+ union android_event event;
+ const jchar *characters;
+ jsize length;
+ uint16_t *buffer;
+
+ event.dnd.type = ANDROID_DND_TEXT_EVENT;
+ event.dnd.serial = ++event_serial;
+ event.dnd.window = window;
+ event.dnd.x = x;
+ event.dnd.y = y;
+
+ length = (*env)->GetStringLength (env, string);
+ buffer = malloc (length * sizeof *buffer);
+ characters = (*env)->GetStringChars (env, string, NULL);
+
+ if (!characters)
+ /* The JVM has run out of memory; return and let the out of memory
+ error take its course. */
+ return 0;
+
+ memcpy (buffer, characters, length * sizeof *buffer);
+ (*env)->ReleaseStringChars (env, string, characters);
+
+ event.dnd.uri_or_string = buffer;
+ event.dnd.length = length;
+
+ android_write_event (&event);
+ return event_serial;
+}
+
+JNIEXPORT jboolean JNICALL
NATIVE_NAME (shouldForwardMultimediaButtons) (JNIEnv *env,
jobject object)
{
@@ -2267,6 +2487,12 @@ NATIVE_NAME (shouldForwardMultimediaButtons) (JNIEnv *env,
return !android_pass_multimedia_buttons_to_system;
}
+JNIEXPORT jboolean JNICALL
+NATIVE_NAME (shouldForwardCtrlSpace) (JNIEnv *env, jobject object)
+{
+ return !android_intercept_control_space;
+}
+
JNIEXPORT void JNICALL
NATIVE_NAME (blitRect) (JNIEnv *env, jobject object,
jobject src, jobject dest,
@@ -2532,12 +2758,12 @@ android_destroy_handle (android_handle handle)
class
= (*android_java_env)->FindClass (android_java_env,
"org/gnu/emacs/EmacsHandleObject");
- assert (class != NULL);
+ eassert (class != NULL);
method
= (*android_java_env)->GetMethodID (android_java_env, class,
"destroyHandle", "()V");
- assert (method != NULL);
+ eassert (method != NULL);
old = class;
class
@@ -2553,7 +2779,7 @@ android_destroy_handle (android_handle handle)
/* Just clear any exception thrown. If destroying the handle
fails from an out-of-memory error, then Emacs loses some
- resources, but that is not as big deal as signalling. */
+ resources, but that is not as big deal as signaling. */
(*android_java_env)->ExceptionClear (android_java_env);
/* Delete the global reference regardless of any error. */
@@ -2680,13 +2906,13 @@ android_create_window (android_window parent, int x, int y,
{
class = (*android_java_env)->FindClass (android_java_env,
"org/gnu/emacs/EmacsWindow");
- assert (class != NULL);
+ eassert (class != NULL);
constructor
= (*android_java_env)->GetMethodID (android_java_env, class, "<init>",
"(SLorg/gnu/emacs/EmacsWindow;"
"IIIIZ)V");
- assert (constructor != NULL);
+ eassert (constructor != NULL);
old = class;
class = (*android_java_env)->NewGlobalRef (android_java_env, class);
@@ -2762,12 +2988,12 @@ android_init_android_rect_class (void)
android_rect_class
= (*android_java_env)->FindClass (android_java_env,
"android/graphics/Rect");
- assert (android_rect_class);
+ eassert (android_rect_class);
android_rect_constructor
= (*android_java_env)->GetMethodID (android_java_env, android_rect_class,
"<init>", "(IIII)V");
- assert (emacs_gc_constructor);
+ eassert (emacs_gc_constructor);
old = android_rect_class;
android_rect_class
@@ -2789,19 +3015,19 @@ android_init_emacs_gc_class (void)
emacs_gc_class
= (*android_java_env)->FindClass (android_java_env,
"org/gnu/emacs/EmacsGC");
- assert (emacs_gc_class);
+ eassert (emacs_gc_class);
emacs_gc_constructor
= (*android_java_env)->GetMethodID (android_java_env,
emacs_gc_class,
"<init>", "(S)V");
- assert (emacs_gc_constructor);
+ eassert (emacs_gc_constructor);
emacs_gc_mark_dirty
= (*android_java_env)->GetMethodID (android_java_env,
emacs_gc_class,
"markDirty", "(Z)V");
- assert (emacs_gc_mark_dirty);
+ eassert (emacs_gc_mark_dirty);
old = emacs_gc_class;
emacs_gc_class
@@ -3337,86 +3563,91 @@ android_create_pixmap_from_bitmap_data (char *data, unsigned int width,
unsigned long background,
unsigned int depth)
{
- android_handle prev_max_handle;
- jobject object;
- jintArray colors;
android_pixmap pixmap;
+ jobject object;
+ AndroidBitmapInfo info;
+ unsigned int *depth_24;
+ unsigned char *depth_8;
+ void *bitmap_data;
unsigned int x, y;
- jint *region;
+ unsigned int r, g, b;
- USE_SAFE_ALLOCA;
+ /* Create a pixmap with the right dimensions and depth. */
+ pixmap = android_create_pixmap (width, height, depth);
- /* Create the color array holding the data. */
- colors = (*android_java_env)->NewIntArray (android_java_env,
- width * height);
- android_exception_check ();
+ /* Lock the bitmap data. */
+ bitmap_data = android_lock_bitmap (pixmap, &info, &object);
+
+ /* Merely return if locking the bitmap fails. */
+ if (!bitmap_data)
+ return pixmap;
- SAFE_NALLOCA (region, sizeof *region, width);
+ eassert (info.format == ANDROID_BITMAP_FORMAT_RGBA_8888
+ || info.format == ANDROID_BITMAP_FORMAT_A_8);
- for (y = 0; y < height; ++y)
+ /* Begin copying each line. */
+
+ switch (info.format)
{
- for (x = 0; x < width; ++x)
+ case ANDROID_BITMAP_FORMAT_RGBA_8888:
+
+ /* Swizzle the pixels into ABGR format. Android uses Skia's
+ ``native color type'', which is ABGR. This is despite the
+ format being named ``ARGB'', and more confusingly
+ `ANDROID_BITMAP_FORMAT_RGBA_8888' in bitmap.h. */
+
+ r = background & 0x00ff0000;
+ g = background & 0x0000ff00;
+ b = background & 0x000000ff;
+ background = (r >> 16) | g | (b << 16) | 0xff000000;
+ r = foreground & 0x00ff0000;
+ g = foreground & 0x0000ff00;
+ b = foreground & 0x000000ff;
+ foreground = (r >> 16) | g | (b << 16) | 0xff000000;
+
+ for (y = 0; y < height; ++y)
{
- if (depth == 24)
- {
- /* The alpha channels must be set, or otherwise, the
- pixmap will be created entirely transparent. */
+ depth_24 = (void *) ((char *) bitmap_data + y * info.stride);
- if (data[x / 8] & (1 << (x % 8)))
- region[x] = foreground | 0xff000000;
- else
- region[x] = background | 0xff000000;
- }
- else
- {
- if (data[x / 8] & (1 << (x % 8)))
- region[x] = foreground;
- else
- region[x] = background;
- }
+ for (x = 0; x < width; ++x)
+ depth_24[x] = ((data[x / 8] & (1 << (x % 8)))
+ ? foreground : background);
+
+ data += (width + 7) / 8;
}
- (*android_java_env)->SetIntArrayRegion (android_java_env,
- colors,
- width * y, width,
- region);
- data += width / 8;
- }
+ break;
- /* First, allocate the pixmap handle. */
- prev_max_handle = max_handle;
- pixmap = android_alloc_id ();
+ case ANDROID_BITMAP_FORMAT_A_8:
- if (!pixmap)
- {
- ANDROID_DELETE_LOCAL_REF ((jobject) colors);
- error ("Out of pixmap handles!");
- }
+ /* 8-bit pixmaps are created, but in spite of that they are
+ employed only to represent bitmaps. */
- object = (*android_java_env)->NewObject (android_java_env,
- pixmap_class.class,
- pixmap_class.constructor,
- (jshort) pixmap, colors,
- (jint) width, (jint) height,
- (jint) depth);
- (*android_java_env)->ExceptionClear (android_java_env);
- ANDROID_DELETE_LOCAL_REF ((jobject) colors);
+ foreground = (foreground ? 255 : 0);
+ background = (background ? 255 : 0);
- if (!object)
- {
- max_handle = prev_max_handle;
- memory_full (0);
+ for (y = 0; y < height; ++y)
+ {
+ depth_8 = (void *) ((char *) bitmap_data + y * info.stride);
+
+ for (x = 0; x < width; ++x)
+ depth_8[x] = ((data[x / 8] & (1 << (x % 8)))
+ ? foreground : background);
+
+ data += (width + 7) / 8;
+ }
+
+ break;
+
+ default:
+ emacs_abort ();
}
- android_handles[pixmap].type = ANDROID_HANDLE_PIXMAP;
- android_handles[pixmap].handle
- = (*android_java_env)->NewGlobalRef (android_java_env, object);
+ /* Unlock the bitmap itself. */
+ AndroidBitmap_unlockPixels (android_java_env, object);
ANDROID_DELETE_LOCAL_REF (object);
- if (!android_handles[pixmap].handle)
- memory_full (0);
-
- SAFE_FREE ();
+ /* Return the pixmap. */
return pixmap;
}
@@ -4337,6 +4568,7 @@ android_fill_polygon (android_drawable drawable, struct android_gc *gc,
service_class.fill_polygon,
drawable_object,
gcontext, array);
+ android_exception_check_1 (array);
ANDROID_DELETE_LOCAL_REF (array);
}
@@ -4359,6 +4591,10 @@ android_draw_rectangle (android_drawable handle, struct android_gc *gc,
drawable, gcontext,
(jint) x, (jint) y,
(jint) width, (jint) height);
+
+ /* In lieu of android_exception_check, clear all exceptions after
+ calling this frequently called graphics operation. */
+ (*android_java_env)->ExceptionClear (android_java_env);
}
void
@@ -4379,6 +4615,10 @@ android_draw_point (android_drawable handle, struct android_gc *gc,
service_class.draw_point,
drawable, gcontext,
(jint) x, (jint) y);
+
+ /* In lieu of android_exception_check, clear all exceptions after
+ calling this frequently called graphics operation. */
+ (*android_java_env)->ExceptionClear (android_java_env);
}
void
@@ -4400,6 +4640,10 @@ android_draw_line (android_drawable handle, struct android_gc *gc,
drawable, gcontext,
(jint) x, (jint) y,
(jint) x2, (jint) y2);
+
+ /* In lieu of android_exception_check, clear all exceptions after
+ calling this frequently called graphics operation. */
+ (*android_java_env)->ExceptionClear (android_java_env);
}
android_pixmap
@@ -4830,10 +5074,17 @@ android_put_image (android_pixmap handle, struct android_image *image)
void
android_bell (void)
{
+ jint duration;
+
+ /* Restrict android_keyboard_bell_duration to values between 10 and
+ 1000. */
+ duration = MIN (1000, MAX (0, android_keyboard_bell_duration));
+
(*android_java_env)->CallNonvirtualVoidMethod (android_java_env,
emacs_service,
service_class.class,
- service_class.ring_bell);
+ service_class.ring_bell,
+ duration);
android_exception_check ();
}
@@ -4886,6 +5137,37 @@ android_lower_window (android_window handle)
android_exception_check ();
}
+void
+android_reconfigure_wm_window (android_window handle,
+ enum android_wc_value_mask value_mask,
+ struct android_window_changes *values)
+{
+ jobject sibling, window;
+
+ window = android_resolve_handle (handle, ANDROID_HANDLE_WINDOW);
+
+ if (!(value_mask & ANDROID_CW_STACK_MODE))
+ return;
+
+ /* If value_mask & ANDROID_CW_SIBLING, place HANDLE above or below
+ values->sibling pursuant to values->stack_mode; else, reposition
+ it at the top or the bottom of its parent. */
+
+ sibling = NULL;
+
+ if (value_mask & ANDROID_CW_SIBLING)
+ sibling = android_resolve_handle (values->sibling,
+ ANDROID_HANDLE_WINDOW);
+
+ (*android_java_env)->CallNonvirtualVoidMethod (android_java_env,
+ window,
+ window_class.class,
+ window_class.reconfigure,
+ sibling,
+ (jint) values->stack_mode);
+ android_exception_check ();
+}
+
int
android_query_tree (android_window handle, android_window *root_return,
android_window *parent_return,
@@ -4896,15 +5178,17 @@ android_query_tree (android_window handle, android_window *root_return,
jsize nelements, i;
android_window *children;
jshort *shorts;
+ jmethodID method;
window = android_resolve_handle (handle, ANDROID_HANDLE_WINDOW);
/* window can be NULL, so this is a service method. */
+ method = service_class.query_tree;
array
- = (*android_java_env)->CallObjectMethod (android_java_env,
- emacs_service,
- service_class.query_tree,
- window);
+ = (*android_java_env)->CallNonvirtualObjectMethod (android_java_env,
+ emacs_service,
+ service_class.class,
+ method, window);
android_exception_check ();
/* The first element of the array is the parent window. The rest
@@ -4957,9 +5241,10 @@ android_get_geometry (android_window handle,
get_geometry = window_class.get_window_geometry;
window_geometry
- = (*android_java_env)->CallObjectMethod (android_java_env,
- window,
- get_geometry);
+ = (*android_java_env)->CallNonvirtualObjectMethod (android_java_env,
+ window,
+ window_class.class,
+ get_geometry);
android_exception_check ();
/* window_geometry is an array containing x, y, width and
@@ -5017,9 +5302,11 @@ android_translate_coordinates (android_window src, int x,
window = android_resolve_handle (src, ANDROID_HANDLE_WINDOW);
method = window_class.translate_coordinates;
coordinates
- = (*android_java_env)->CallObjectMethod (android_java_env,
- window, method,
- (jint) x, (jint) y);
+ = (*android_java_env)->CallNonvirtualObjectMethod (android_java_env,
+ window,
+ window_class.class,
+ method, (jint) x,
+ (jint) y);
android_exception_check ();
/* The array must contain two elements: X, Y translated to the root
@@ -5057,7 +5344,9 @@ android_wc_lookup_string (android_key_pressed_event *event,
const jchar *characters;
jsize size;
size_t i;
+ JNIEnv *env;
+ env = android_java_env;
status = ANDROID_LOOKUP_NONE;
rc = 0;
@@ -5108,9 +5397,10 @@ android_wc_lookup_string (android_key_pressed_event *event,
{
window = android_handles[event->window].handle;
string
- = (*android_java_env)->CallObjectMethod (android_java_env, window,
- window_class.lookup_string,
- (jint) event->serial);
+ = (*env)->CallNonvirtualObjectMethod (env, window,
+ window_class.class,
+ window_class.lookup_string,
+ (jint) event->serial);
android_exception_check ();
if (!string)
@@ -5118,13 +5408,11 @@ android_wc_lookup_string (android_key_pressed_event *event,
else
{
/* Now return this input method string. */
- characters = (*android_java_env)->GetStringChars (android_java_env,
- string, NULL);
+ characters = (*env)->GetStringChars (env, string, NULL);
android_exception_check_nonnull ((void *) characters, string);
- /* Figure out how big the string is. */
- size = (*android_java_env)->GetStringLength (android_java_env,
- string);
+ /* Establish the size of the the string. */
+ size = (*env)->GetStringLength (env, string);
/* Copy over the string data. */
for (i = 0; i < MIN ((unsigned int) wchars_buffer, size); ++i)
@@ -5143,8 +5431,7 @@ android_wc_lookup_string (android_key_pressed_event *event,
else
rc = size;
- (*android_java_env)->ReleaseStringChars (android_java_env, string,
- characters);
+ (*env)->ReleaseStringChars (env, string, characters);
ANDROID_DELETE_LOCAL_REF (string);
}
}
@@ -5164,7 +5451,7 @@ android_wc_lookup_string (android_key_pressed_event *event,
The caller must take care to unlock the bitmap data afterwards. */
unsigned char *
-android_lock_bitmap (android_window drawable,
+android_lock_bitmap (android_drawable drawable,
AndroidBitmapInfo *bitmap_info,
jobject *bitmap_return)
{
@@ -5180,9 +5467,15 @@ android_lock_bitmap (android_window drawable,
object,
drawable_class.get_bitmap);
if (!bitmap)
- /* NULL is returned when the bitmap does not currently exist due
- to ongoing reconfiguration on the main thread. */
- return NULL;
+ {
+ /* Report any exception signaled. */
+ android_exception_check ();
+
+ /* If no exception was signaled, then NULL was returned as the
+ bitmap does not presently exist due to window reconfiguration
+ on the main thread. */
+ return NULL;
+ }
memset (bitmap_info, 0, sizeof *bitmap_info);
@@ -5218,29 +5511,22 @@ void
android_damage_window (android_drawable handle,
struct android_rectangle *damage)
{
- jobject drawable, rect;
+ jobject drawable;
drawable = android_resolve_handle (handle, ANDROID_HANDLE_WINDOW);
- /* Now turn DAMAGE into a Java rectangle. */
- rect = (*android_java_env)->NewObject (android_java_env,
- android_rect_class,
- android_rect_constructor,
- (jint) damage->x,
- (jint) damage->y,
- (jint) (damage->x
- + damage->width),
- (jint) (damage->y
- + damage->height));
- android_exception_check ();
-
/* Post the damage to the drawable. */
- (*android_java_env)->CallVoidMethod (android_java_env,
- drawable,
- drawable_class.damage_rect,
- rect);
- android_exception_check_1 (rect);
- ANDROID_DELETE_LOCAL_REF (rect);
+ (*android_java_env)->CallNonvirtualVoidMethod (android_java_env,
+ drawable,
+ window_class.class,
+ window_class.damage_rect,
+ (jint) damage->x,
+ (jint) damage->y,
+ (jint) (damage->x
+ + damage->width),
+ (jint) (damage->y
+ + damage->height));
+ android_exception_check ();
}
@@ -5365,13 +5651,45 @@ android_get_keysym_name (int keysym, char *name_return, size_t size)
{
jobject string;
const char *buffer;
+ jmethodID method;
+
+ /* These keysyms are special editor actions sent by the input
+ method. */
+
+ switch (keysym)
+ {
+ case 65536 + 1:
+ strncpy (name_return, "select-all", size - 1);
+ name_return[size] = '\0';
+ return;
+
+ case 65536 + 2:
+ strncpy (name_return, "start-selecting-text", size - 1);
+ name_return[size] = '\0';
+ return;
+
+ case 65536 + 3:
+ strncpy (name_return, "stop-selecting-text", size - 1);
+ name_return[size] = '\0';
+ return;
+ }
- string = (*android_java_env)->CallObjectMethod (android_java_env,
- emacs_service,
- service_class.name_keysym,
- (jint) keysym);
+ method = service_class.name_keysym;
+ string
+ = (*android_java_env)->CallNonvirtualObjectMethod (android_java_env,
+ emacs_service,
+ service_class.class,
+ method,
+ (jint) keysym);
android_exception_check ();
+ if (!string)
+ {
+ strncpy (name_return, "stop-selecting-text", size - 1);
+ name_return[size] = '\0';
+ return;
+ }
+
buffer = (*android_java_env)->GetStringUTFChars (android_java_env,
(jstring) string,
NULL);
@@ -5411,22 +5729,40 @@ android_toggle_on_screen_keyboard (android_window window, bool show)
+#if defined __clang_major__ && __clang_major__ < 5
+# define HAS_BUILTIN_TRAP 0
+#elif 3 < __GNUC__ + (3 < __GNUC_MINOR__ + (4 <= __GNUC_PATCHLEVEL__))
+# define HAS_BUILTIN_TRAP 1
+#elif defined __has_builtin
+# define HAS_BUILTIN_TRAP __has_builtin (__builtin_trap)
+#else /* !__has_builtin */
+# define HAS_BUILTIN_TRAP 0
+#endif /* defined __clang_major__ && __clang_major__ < 5 */
+
/* emacs_abort implementation for Android. This logs a stack
trace. */
void
emacs_abort (void)
{
+#ifndef HAS_BUILTIN_TRAP
volatile char *foo;
+#endif /* !HAS_BUILTIN_TRAP */
__android_log_print (ANDROID_LOG_FATAL, __func__,
- "emacs_abort called, please review the ensuing"
+ "emacs_abort called, please review the following"
" stack trace");
- /* Cause a NULL pointer dereference to make debuggerd generate a
+#ifndef HAS_BUILTIN_TRAP
+ /* Induce a NULL pointer dereference to make debuggerd generate a
tombstone. */
foo = NULL;
*foo = '\0';
+#else /* HAS_BUILTIN_TRAP */
+ /* Crash through __builtin_trap instead. This appears to more
+ uniformly elicit crash reports from debuggerd. */
+ __builtin_trap ();
+#endif /* !HAS_BUILTIN_TRAP */
abort ();
}
@@ -5461,7 +5797,7 @@ android_check_string (Lisp_Object text)
better represent the UCS-16 based Java String format, and to let
strings contain NULL characters while remaining valid C strings:
NULL bytes are encoded as two-byte sequences, and Unicode surrogate
- pairs encoded as two-byte sequences are prefered to four-byte
+ pairs encoded as two-byte sequences are preferred to four-byte
sequences when encoding characters above the BMP. */
int
@@ -5514,15 +5850,20 @@ android_verify_jni_string (const char *name)
}
/* Given a Lisp string TEXT, return a local reference to an equivalent
- Java string. */
+ Java string. Each argument following TEXT should be NULL or a
+ local reference that will be freed if creating the string fails,
+ whereupon memory_full will also be signaled. */
jstring
-android_build_string (Lisp_Object text)
+android_build_string (Lisp_Object text, ...)
{
Lisp_Object encoded;
jstring string;
size_t nchars;
jchar *characters;
+ va_list ap;
+ jobject object;
+
USE_SAFE_ALLOCA;
/* Directly encode TEXT if it contains no non-ASCII characters, or
@@ -5540,9 +5881,11 @@ android_build_string (Lisp_Object text)
{
string = (*android_java_env)->NewStringUTF (android_java_env,
SSDATA (text));
- android_exception_check ();
- SAFE_FREE ();
+ if ((*android_java_env)->ExceptionCheck (android_java_env))
+ goto error;
+
+ SAFE_FREE ();
return string;
}
@@ -5561,10 +5904,36 @@ android_build_string (Lisp_Object text)
string
= (*android_java_env)->NewString (android_java_env,
characters, nchars);
- android_exception_check ();
+
+ if ((*android_java_env)->ExceptionCheck (android_java_env))
+ goto error;
SAFE_FREE ();
return string;
+
+ error:
+ /* An exception arose while creating the string. When this
+ transpires, an assumption is made that the error was induced by
+ running out of memory. Delete each of the local references
+ within AP. */
+
+ va_start (ap, text);
+
+ __android_log_print (ANDROID_LOG_WARN, __func__,
+ "Possible out of memory error. "
+ " The Java exception follows: ");
+ /* Describe exactly what went wrong. */
+ (*android_java_env)->ExceptionDescribe (android_java_env);
+ (*android_java_env)->ExceptionClear (android_java_env);
+
+ /* Now remove each and every local reference provided after
+ OBJECT. */
+
+ while ((object = va_arg (ap, jobject)))
+ ANDROID_DELETE_LOCAL_REF (object);
+
+ va_end (ap);
+ memory_full (0);
}
/* Do the same, except TEXT is constant string data in ASCII or
@@ -5650,8 +6019,9 @@ android_exception_check (void)
}
/* Check for JNI exceptions. If there is one such exception, clear
- it, then delete the local reference to OBJECT and call
- memory_full. */
+ it, then delete the local reference to OBJECT and call memory_full.
+ OBJECT can be NULL, which is a valid local reference to the Java
+ null object. */
void
android_exception_check_1 (jobject object)
@@ -5665,7 +6035,10 @@ android_exception_check_1 (jobject object)
/* Describe exactly what went wrong. */
(*android_java_env)->ExceptionDescribe (android_java_env);
(*android_java_env)->ExceptionClear (android_java_env);
- ANDROID_DELETE_LOCAL_REF (object);
+
+ if (object)
+ ANDROID_DELETE_LOCAL_REF (object);
+
memory_full (0);
}
@@ -5684,8 +6057,13 @@ android_exception_check_2 (jobject object, jobject object1)
/* Describe exactly what went wrong. */
(*android_java_env)->ExceptionDescribe (android_java_env);
(*android_java_env)->ExceptionClear (android_java_env);
- ANDROID_DELETE_LOCAL_REF (object);
- ANDROID_DELETE_LOCAL_REF (object1);
+
+ if (object)
+ ANDROID_DELETE_LOCAL_REF (object);
+
+ if (object1)
+ ANDROID_DELETE_LOCAL_REF (object1);
+
memory_full (0);
}
@@ -5705,9 +6083,16 @@ android_exception_check_3 (jobject object, jobject object1,
/* Describe exactly what went wrong. */
(*android_java_env)->ExceptionDescribe (android_java_env);
(*android_java_env)->ExceptionClear (android_java_env);
- ANDROID_DELETE_LOCAL_REF (object);
- ANDROID_DELETE_LOCAL_REF (object1);
- ANDROID_DELETE_LOCAL_REF (object2);
+
+ if (object)
+ ANDROID_DELETE_LOCAL_REF (object);
+
+ if (object1)
+ ANDROID_DELETE_LOCAL_REF (object1);
+
+ if (object2)
+ ANDROID_DELETE_LOCAL_REF (object2);
+
memory_full (0);
}
@@ -5727,10 +6112,19 @@ android_exception_check_4 (jobject object, jobject object1,
/* Describe exactly what went wrong. */
(*android_java_env)->ExceptionDescribe (android_java_env);
(*android_java_env)->ExceptionClear (android_java_env);
- ANDROID_DELETE_LOCAL_REF (object);
- ANDROID_DELETE_LOCAL_REF (object1);
- ANDROID_DELETE_LOCAL_REF (object2);
- ANDROID_DELETE_LOCAL_REF (object3);
+
+ if (object)
+ ANDROID_DELETE_LOCAL_REF (object);
+
+ if (object1)
+ ANDROID_DELETE_LOCAL_REF (object1);
+
+ if (object2)
+ ANDROID_DELETE_LOCAL_REF (object2);
+
+ if (object3)
+ ANDROID_DELETE_LOCAL_REF (object3);
+
memory_full (0);
}
@@ -6050,12 +6444,14 @@ android_browse_url (Lisp_Object url, Lisp_Object send)
Lisp_Object tem;
const char *buffer;
- string = android_build_string (url);
- value = (*android_java_env)->CallObjectMethod (android_java_env,
- emacs_service,
- service_class.browse_url,
- string,
- (jboolean) !NILP (send));
+ string = android_build_string (url, NULL);
+ value
+ = (*android_java_env)->CallNonvirtualObjectMethod (android_java_env,
+ emacs_service,
+ service_class.class,
+ service_class.browse_url,
+ string,
+ (jboolean) !NILP (send));
android_exception_check ();
ANDROID_DELETE_LOCAL_REF (string);
@@ -6067,7 +6463,7 @@ android_browse_url (Lisp_Object url, Lisp_Object send)
buffer = (*android_java_env)->GetStringUTFChars (android_java_env,
(jstring) value,
NULL);
- android_exception_check_1 (string);
+ android_exception_check_1 (value);
/* Otherwise, build the string describing the error. */
tem = build_string_from_utf8 (buffer);
@@ -6099,7 +6495,7 @@ android_restart_emacs (void)
exit (0);
}
-/* Return a number from 1 to 33 describing the version of Android
+/* Return a number from 1 to 34 describing the version of Android
Emacs is running on.
This is different from __ANDROID_API__, as that describes the
@@ -6120,10 +6516,14 @@ android_query_battery (struct android_battery_state *status)
{
jlongArray array;
jlong *longs;
+ jmethodID method;
- array = (*android_java_env)->CallObjectMethod (android_java_env,
- emacs_service,
- service_class.query_battery);
+ method = service_class.query_battery;
+ array
+ = (*android_java_env)->CallNonvirtualObjectMethod (android_java_env,
+ emacs_service,
+ service_class.class,
+ method);
android_exception_check ();
/* A NULL return with no exception means that battery information
@@ -6174,6 +6574,57 @@ android_request_directory_access (void)
return rc;
}
+/* Return whether Emacs is entitled to access external storage.
+
+ On Android 5.1 and earlier, such permissions as are declared within
+ an application's manifest are granted during installation and are
+ irrevocable.
+
+ On Android 6.0 through Android 10.0, the right to read external
+ storage is a regular permission granted from the Permissions
+ panel.
+
+ On Android 11.0 and later, that right must be granted through an
+ independent ``Special App Access'' settings panel. */
+
+bool
+android_external_storage_available_p (void)
+{
+ jboolean rc;
+ jmethodID method;
+
+ if (android_api_level <= 22) /* LOLLIPOP_MR1 */
+ return true;
+
+ method = service_class.external_storage_available;
+ rc = (*android_java_env)->CallNonvirtualBooleanMethod (android_java_env,
+ emacs_service,
+ service_class.class,
+ method);
+ android_exception_check ();
+
+ return rc;
+}
+
+/* Display a dialog from which the aforementioned rights can be
+ granted. */
+
+void
+android_request_storage_access (void)
+{
+ jmethodID method;
+
+ if (android_api_level <= 22) /* LOLLIPOP_MR1 */
+ return;
+
+ method = service_class.request_storage_access;
+ (*android_java_env)->CallNonvirtualVoidMethod (android_java_env,
+ emacs_service,
+ service_class.class,
+ method);
+ android_exception_check ();
+}
+
/* The thread from which a query against a thread is currently being
@@ -6358,7 +6809,7 @@ android_begin_query (void)
if (old == 1)
{
/* Answer the query that is currently being made. */
- assert (android_query_function != NULL);
+ eassert (android_query_function != NULL);
android_answer_query ();
}
diff --git a/src/android.h b/src/android.h
index e865d7da665..1059933d339 100644
--- a/src/android.h
+++ b/src/android.h
@@ -1,6 +1,6 @@
/* Android initialization for GNU Emacs.
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
@@ -54,7 +54,7 @@ extern char *android_user_full_name (struct passwd *);
/* File I/O operations. Many of these are defined in
androidvfs.c. */
-extern const char *android_is_special_directory (const char *, const char *);
+extern bool android_is_special_directory (const char *, const char *);
extern const char *android_get_home_directory (void);
extern void android_vfs_init (JNIEnv *, jobject);
@@ -108,7 +108,7 @@ extern void android_set_dont_focus_on_map (android_window, bool);
extern void android_set_dont_accept_focus (android_window, bool);
extern int android_verify_jni_string (const char *);
-extern jstring android_build_string (Lisp_Object);
+extern jstring android_build_string (Lisp_Object, ...);
extern jstring android_build_jstring (const char *);
extern void android_exception_check (void);
extern void android_exception_check_1 (jobject);
@@ -123,6 +123,8 @@ extern void android_wait_event (void);
extern void android_toggle_on_screen_keyboard (android_window, bool);
extern _Noreturn void android_restart_emacs (void);
extern int android_request_directory_access (void);
+extern bool android_external_storage_available_p (void);
+extern void android_request_storage_access (void);
extern int android_get_current_api_level (void)
__attribute__ ((pure));
@@ -238,7 +240,7 @@ extern int android_rewrite_spawn_argv (const char ***);
/* Define a substitute for use during Emacs compilation. */
-#define android_is_special_directory(name, dir) ((const char *) NULL)
+#define android_is_special_directory(name, dir) (false)
#endif /* !ANDROID_STUBIFY */
@@ -289,6 +291,8 @@ struct android_emacs_service
jmethodID rename_document;
jmethodID move_document;
jmethodID valid_authority;
+ jmethodID external_storage_available;
+ jmethodID request_storage_access;
};
extern JNIEnv *android_java_env;
@@ -299,6 +303,10 @@ extern jobject emacs_service;
/* Various methods associated with the EmacsService. */
extern struct android_emacs_service service_class;
+/* The time at which Emacs was installed, which also supplies the
+ mtime of asset files. */
+extern struct timespec emacs_installation_time;
+
#define ANDROID_DELETE_LOCAL_REF(ref) \
((*android_java_env)->DeleteLocalRef (android_java_env, \
(ref)))
diff --git a/src/androidfns.c b/src/androidfns.c
index 9e8372f524b..bf8ab5b45cc 100644
--- a/src/androidfns.c
+++ b/src/androidfns.c
@@ -1,6 +1,6 @@
/* Communication module for Android terminals.
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
@@ -27,6 +27,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include "keyboard.h"
#include "buffer.h"
#include "androidgui.h"
+#include "pdumper.h"
#ifndef ANDROID_STUBIFY
@@ -367,8 +368,16 @@ android_change_tab_bar_height (struct frame *f, int height)
the tab bar by even 1 pixel, FRAME_TAB_BAR_LINES will be changed,
leading to the tab bar height being incorrectly set upon the next
call to android_set_font. (bug#59285) */
+
lines = height / unit;
+ /* Even so, HEIGHT might be less than unit if the tab bar face is
+ not so tall as the frame's font height; which if true lines will
+ be set to 0 and the tab bar will thus vanish. */
+
+ if (lines == 0 && height != 0)
+ lines = 1;
+
/* Make sure we redisplay all windows in this frame. */
fset_redisplay (f);
@@ -1326,9 +1335,9 @@ DEFUN ("x-display-backing-store", Fx_display_backing_store,
{
check_android_display_info (terminal);
- /* The Java part is implemented in a way that it always does the
- equivalent of backing store. */
- return Qalways;
+ /* Window contents are preserved insofar as they remain mapped, in a
+ fashion tantamount to WhenMapped. */
+ return Qwhen_mapped;
}
DEFUN ("x-display-visual-class", Fx_display_visual_class,
@@ -1591,7 +1600,8 @@ and width values are in pixels.
#endif
}
-DEFUN ("android-frame-edges", Fandroid_frame_edges, Sandroid_frame_edges, 0, 2, 0,
+DEFUN ("android-frame-edges", Fandroid_frame_edges,
+ Sandroid_frame_edges, 0, 2, 0,
doc: /* Return edge coordinates of FRAME.
FRAME must be a live frame and defaults to the selected one. The return
value is a list of the form (LEFT, TOP, RIGHT, BOTTOM). All values are
@@ -1693,6 +1703,28 @@ TERMINAL is a frame. */)
#endif
}
+#ifndef ANDROID_STUBIFY
+
+static void
+android_frame_restack (struct frame *f1, struct frame *f2,
+ bool above_flag)
+{
+ android_window window1;
+ struct android_window_changes wc;
+ unsigned long mask;
+
+ window1 = FRAME_ANDROID_WINDOW (f1);
+ wc.sibling = FRAME_ANDROID_WINDOW (f2);
+ wc.stack_mode = above_flag ? ANDROID_ABOVE : ANDROID_BELOW;
+ mask = ANDROID_CW_SIBLING | ANDROID_CW_STACK_MODE;
+
+ block_input ();
+ android_reconfigure_wm_window (window1, mask, &wc);
+ unblock_input ();
+}
+
+#endif /* !ANDROID_STUBIFY */
+
DEFUN ("android-frame-restack", Fandroid_frame_restack,
Sandroid_frame_restack, 2, 3, 0,
doc: /* Restack FRAME1 below FRAME2.
@@ -1709,19 +1741,25 @@ that of FRAME2. Hence the position of FRAME2 in its display's Z
\(stacking) order relative to all other frames excluding FRAME1 remains
unaltered.
-The Android system refuses to restack windows, so this does not
-work. */)
- (Lisp_Object frame1, Lisp_Object frame2, Lisp_Object frame3)
+Android does not facilitate restacking top-level windows managed by
+its own window manager; nor is it possible to restack frames that are
+children of different parents. Consequently, this function only
+functions when FRAME1 and FRAME2 are both child frames subordinate to
+the same parent frame. */)
+ (Lisp_Object frame1, Lisp_Object frame2, Lisp_Object above)
{
#ifdef ANDROID_STUBIFY
error ("Android cross-compilation stub called!");
return Qnil;
-#else
- /* This is not supported on Android because of limitations in the
- platform that prevent ViewGroups from restacking
- SurfaceViews. */
- return Qnil;
-#endif
+#else /* !ANDROID_STUBIFY */
+ struct frame *f1 = decode_live_frame (frame1);
+ struct frame *f2 = decode_live_frame (frame2);
+
+ if (!(FRAME_ANDROID_WINDOW (f1) && FRAME_ANDROID_WINDOW (f2)))
+ error ("Cannot restack frames");
+ android_frame_restack (f1, f2, !NILP (above));
+ return Qt;
+#endif /* ANDROID_STUBIFY */
}
DEFUN ("android-mouse-absolute-pixel-position",
@@ -3067,6 +3105,42 @@ within the directory `/content/storage'. */)
+/* Functions concerning storage permissions. */
+
+DEFUN ("android-external-storage-available-p",
+ Fandroid_external_storage_available_p,
+ Sandroid_external_storage_available_p, 0, 0, 0,
+ doc: /* Return non-nil if Emacs is entitled to access external storage.
+Return nil if the requisite permissions for external storage access
+have not been granted to Emacs, t otherwise. Such permissions can be
+requested by means of the `android-request-storage-access'
+command.
+
+External storage on Android encompasses the `/sdcard' and
+`/storage/emulated' directories, access to which is denied to programs
+absent these permissions. */)
+ (void)
+{
+ return android_external_storage_available_p () ? Qt : Qnil;
+}
+
+DEFUN ("android-request-storage-access", Fandroid_request_storage_access,
+ Sandroid_request_storage_access, 0, 0, "",
+ doc: /* Request permissions to access external storage.
+
+Return nil regardless of whether access permissions are granted or not,
+immediately after displaying the permissions request dialog.
+
+Use `android-external-storage-available-p' (which see) to verify
+whether Emacs has actually received such access permissions. */)
+ (void)
+{
+ android_request_storage_access ();
+ return Qnil;
+}
+
+
+
/* Miscellaneous input method related stuff. */
/* Report X, Y, by the phys cursor width and height as the cursor
@@ -3097,12 +3171,197 @@ android_set_preeditarea (struct window *w, int x, int y)
+#ifndef ANDROID_STUBIFY
+
+static void
+syms_of_androidfns_for_pdumper (void)
+{
+ jclass locale;
+ jmethodID method;
+ jobject object;
+ jstring string;
+ Lisp_Object language, country, script, variant;
+ const char *data;
+
+ /* Find the Locale class. */
+
+ locale = (*android_java_env)->FindClass (android_java_env,
+ "java/util/Locale");
+ if (!locale)
+ emacs_abort ();
+
+ /* And the method from which the default locale can be
+ extracted. */
+
+ method = (*android_java_env)->GetStaticMethodID (android_java_env,
+ locale,
+ "getDefault",
+ "()Ljava/util/Locale;");
+ if (!method)
+ emacs_abort ();
+
+ /* Retrieve the default locale. */
+
+ object = (*android_java_env)->CallStaticObjectMethod (android_java_env,
+ locale, method);
+ android_exception_check_1 (locale);
+
+ if (!object)
+ emacs_abort ();
+
+ /* Retrieve its language field. Each of these methods is liable to
+ return the empty string, though if language is empty, the locale
+ is malformed. */
+
+ method = (*android_java_env)->GetMethodID (android_java_env, locale,
+ "getLanguage",
+ "()Ljava/lang/String;");
+ if (!method)
+ emacs_abort ();
+
+ string = (*android_java_env)->CallObjectMethod (android_java_env, object,
+ method);
+ android_exception_check_2 (object, locale);
+
+ if (!string)
+ language = empty_unibyte_string;
+ else
+ {
+ data = (*android_java_env)->GetStringUTFChars (android_java_env,
+ string, NULL);
+ android_exception_check_3 (object, locale, string);
+
+ if (!data)
+ language = empty_unibyte_string;
+ else
+ {
+ language = build_unibyte_string (data);
+ (*android_java_env)->ReleaseStringUTFChars (android_java_env,
+ string, data);
+ }
+ }
+
+ /* Delete the reference to this string. */
+ ANDROID_DELETE_LOCAL_REF (string);
+
+ /* Proceed to retrieve the country code. */
+
+ method = (*android_java_env)->GetMethodID (android_java_env, locale,
+ "getCountry",
+ "()Ljava/lang/String;");
+ if (!method)
+ emacs_abort ();
+
+ string = (*android_java_env)->CallObjectMethod (android_java_env, object,
+ method);
+ android_exception_check_2 (object, locale);
+
+ if (!string)
+ country = empty_unibyte_string;
+ else
+ {
+ data = (*android_java_env)->GetStringUTFChars (android_java_env,
+ string, NULL);
+ android_exception_check_3 (object, locale, string);
+
+ if (!data)
+ country = empty_unibyte_string;
+ else
+ {
+ country = build_unibyte_string (data);
+ (*android_java_env)->ReleaseStringUTFChars (android_java_env,
+ string, data);
+ }
+ }
+
+ ANDROID_DELETE_LOCAL_REF (string);
+
+ /* Proceed to retrieve the script. */
+
+ if (android_get_current_api_level () < 21)
+ script = empty_unibyte_string;
+ else
+ {
+ method = (*android_java_env)->GetMethodID (android_java_env, locale,
+ "getScript",
+ "()Ljava/lang/String;");
+ if (!method)
+ emacs_abort ();
+
+ string = (*android_java_env)->CallObjectMethod (android_java_env,
+ object, method);
+ android_exception_check_2 (object, locale);
+
+ if (!string)
+ script = empty_unibyte_string;
+ else
+ {
+ data = (*android_java_env)->GetStringUTFChars (android_java_env,
+ string, NULL);
+ android_exception_check_3 (object, locale, string);
+
+ if (!data)
+ script = empty_unibyte_string;
+ else
+ {
+ script = build_unibyte_string (data);
+ (*android_java_env)->ReleaseStringUTFChars (android_java_env,
+ string, data);
+ }
+ }
+ }
+
+ ANDROID_DELETE_LOCAL_REF (string);
+
+ /* And variant. */
+
+ method = (*android_java_env)->GetMethodID (android_java_env, locale,
+ "getVariant",
+ "()Ljava/lang/String;");
+ if (!method)
+ emacs_abort ();
+
+ string = (*android_java_env)->CallObjectMethod (android_java_env, object,
+ method);
+ android_exception_check_2 (object, locale);
+
+ if (!string)
+ variant = empty_unibyte_string;
+ else
+ {
+ data = (*android_java_env)->GetStringUTFChars (android_java_env,
+ string, NULL);
+ android_exception_check_3 (object, locale, string);
+
+ if (!data)
+ variant = empty_unibyte_string;
+ else
+ {
+ variant = build_unibyte_string (data);
+ (*android_java_env)->ReleaseStringUTFChars (android_java_env,
+ string, data);
+ }
+ }
+
+ /* Delete the reference to this string. */
+ ANDROID_DELETE_LOCAL_REF (string);
+
+ /* And other remaining local references. */
+ ANDROID_DELETE_LOCAL_REF (object);
+ ANDROID_DELETE_LOCAL_REF (locale);
+
+ /* Set Vandroid_os_language. */
+ Vandroid_os_language = list4 (language, country, script, variant);
+}
+
+#endif /* ANDROID_STUBIFY */
+
void
syms_of_androidfns (void)
{
/* Miscellaneous symbols used by some functions here. */
DEFSYM (Qtrue_color, "true-color");
- DEFSYM (Qalways, "always");
+ DEFSYM (Qwhen_mapped, "when-mapped");
DEFVAR_LISP ("x-pointer-shape", Vx_pointer_shape,
doc: /* SKIP: real text in xfns.c. */);
@@ -3205,6 +3464,19 @@ Note that if you set this, you will no longer be able to quit Emacs
using the volume down button. */);
android_pass_multimedia_buttons_to_system = false;
+ DEFVAR_BOOL ("android-intercept-control-space",
+ android_intercept_control_space,
+ doc: /* Whether Emacs should intercept C-SPC.
+When this variable is set, Emacs intercepts C-SPC events as they are
+delivered to a frame before they are registered and filtered by the
+input method.
+
+For no apparent purpose, Android input methods customarily discard SPC
+events with the Ctrl modifier set without delivering them to Emacs
+afterwards, which is an impediment to typing key sequences
+incorporating such keys. */);
+ android_intercept_control_space = true;
+
DEFVAR_BOOL ("android-use-exec-loader", android_use_exec_loader,
doc: /* Whether or not to bypass system restrictions on program execution.
@@ -3219,6 +3491,33 @@ restrictions.
This option has no effect on Android 9 and earlier. */);
android_use_exec_loader = true;
+ DEFVAR_INT ("android-keyboard-bell-duration",
+ android_keyboard_bell_duration,
+ doc: /* Number of milliseconds to vibrate after ringing the keyboard bell.
+The keyboard bell under Android systems takes the form of a vibrating
+element that is activated for a given number of milliseconds upon the
+bell being rung. */);
+ android_keyboard_bell_duration = 50;
+
+ DEFVAR_LISP ("android-os-language", Vandroid_os_language,
+ doc: /* A list representing the configured system language on Android.
+This list has four elements: LANGUAGE, COUNTRY, SCRIPT and VARIANT, where:
+
+LANGUAGE and COUNTRY are ISO language and country codes identical to
+those found in POSIX locale specifications.
+
+SCRIPT is an ISO 15924 script tag, representing the script used
+if available, or if required to disambiguate between distinct
+writing systems for the same combination of language and country.
+
+VARIANT is an arbitrary string representing the variant of the
+LANGUAGE or SCRIPT.
+
+Each of these fields might be empty or nil, but the locale is invalid
+if LANGUAGE is empty. Users of this variable should consider the
+language to be US English if LANGUAGE is empty. */);
+ Vandroid_os_language = Qnil;
+
/* Functions defined. */
defsubr (&Sx_create_frame);
defsubr (&Sxw_color_defined_p);
@@ -3252,6 +3551,8 @@ This option has no effect on Android 9 and earlier. */);
#ifndef ANDROID_STUBIFY
defsubr (&Sandroid_query_battery);
defsubr (&Sandroid_request_directory_access);
+ defsubr (&Sandroid_external_storage_available_p);
+ defsubr (&Sandroid_request_storage_access);
tip_timer = Qnil;
staticpro (&tip_timer);
@@ -3267,5 +3568,7 @@ This option has no effect on Android 9 and earlier. */);
staticpro (&tip_dx);
tip_dy = Qnil;
staticpro (&tip_dy);
+
+ pdumper_do_now_and_after_load (syms_of_androidfns_for_pdumper);
#endif /* !ANDROID_STUBIFY */
}
diff --git a/src/androidfont.c b/src/androidfont.c
index db2f94008f2..5fd3018b6d4 100644
--- a/src/androidfont.c
+++ b/src/androidfont.c
@@ -1,6 +1,6 @@
/* Android fallback font driver.
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
@@ -204,11 +204,11 @@ android_init_font_driver (void)
FIND_METHOD (open_font, "openFont", "(Lorg/gnu/emacs/EmacsFontDriver$Font"
"Entity;I)Lorg/gnu/emacs/EmacsFontDriver$FontObject;");
FIND_METHOD (has_char, "hasChar", "(Lorg/gnu/emacs/EmacsFontDriver$Font"
- "Spec;C)I");
+ "Spec;I)I");
FIND_METHOD (text_extents, "textExtents", "(Lorg/gnu/emacs/EmacsFontDriver"
"$FontObject;[ILorg/gnu/emacs/EmacsFontDriver$FontMetrics;)V");
FIND_METHOD (encode_char, "encodeChar", "(Lorg/gnu/emacs/EmacsFontDriver"
- "$FontObject;C)I");
+ "$FontObject;I)I");
FIND_METHOD (draw, "draw", "(Lorg/gnu/emacs/EmacsFontDriver$FontObject;"
"Lorg/gnu/emacs/EmacsGC;Lorg/gnu/emacs/EmacsDrawable;[IIIIZ)I");
@@ -776,7 +776,7 @@ androidfont_open_font (struct frame *f, Lisp_Object font_entity,
#undef DO_CARDINAL_FIELD
/* This should eventually become unnecessary. */
- font->props[FONT_NAME_INDEX] = Ffont_xlfd_name (font_object, Qnil);
+ font->props[FONT_NAME_INDEX] = Ffont_xlfd_name (font_object, Qnil, Qt);
return font_object;
}
diff --git a/src/androidgui.h b/src/androidgui.h
index 14225f7bf80..69efd393d55 100644
--- a/src/androidgui.h
+++ b/src/androidgui.h
@@ -1,5 +1,5 @@
/* Android window system support.
- Copyright (C) 2023 Free Software Foundation, Inc.
+ Copyright (C) 2023-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
@@ -248,6 +248,9 @@ enum android_event_type
ANDROID_CONTEXT_MENU,
ANDROID_EXPOSE,
ANDROID_INPUT_METHOD,
+ ANDROID_DND_DRAG_EVENT,
+ ANDROID_DND_URI_EVENT,
+ ANDROID_DND_TEXT_EVENT,
};
struct android_any_event
@@ -463,6 +466,7 @@ enum android_ime_operation
ANDROID_IME_END_BATCH_EDIT,
ANDROID_IME_REQUEST_SELECTION_UPDATE,
ANDROID_IME_REQUEST_CURSOR_UPDATES,
+ ANDROID_IME_REPLACE_TEXT,
};
enum
@@ -509,6 +513,28 @@ struct android_ime_event
unsigned long counter;
};
+struct android_dnd_event
+{
+ /* Type of the event. */
+ enum android_event_type type;
+
+ /* The event serial. */
+ unsigned long serial;
+
+ /* The window that gave rise to the event. */
+ android_window window;
+
+ /* X and Y coordinates of the event. */
+ int x, y;
+
+ /* Data tied to this event, such as a URI or clipboard string.
+ Must be deallocated with `free'. */
+ unsigned short *uri_or_string;
+
+ /* Length of that data. */
+ size_t length;
+};
+
union android_event
{
enum android_event_type type;
@@ -540,6 +566,11 @@ union android_event
/* This is used to dispatch input method editing requests. */
struct android_ime_event ime;
+
+ /* There is no analog under X because Android defines a strict DND
+ protocol, whereas there exist several competing X protocols
+ implemented in terms of X client messages. */
+ struct android_dnd_event dnd;
};
enum
@@ -563,6 +594,24 @@ enum android_ic_mode
ANDROID_IC_MODE_TEXT = 2,
};
+enum android_stack_mode
+ {
+ ANDROID_ABOVE = 0,
+ ANDROID_BELOW = 1,
+ };
+
+enum android_wc_value_mask
+ {
+ ANDROID_CW_SIBLING = 0,
+ ANDROID_CW_STACK_MODE = 1,
+ };
+
+struct android_window_changes
+{
+ android_window sibling;
+ enum android_stack_mode stack_mode;
+};
+
extern int android_pending (void);
extern void android_next_event (union android_event *);
extern bool android_check_if_event (union android_event *,
@@ -642,6 +691,9 @@ extern void android_bell (void);
extern void android_set_input_focus (android_window, unsigned long);
extern void android_raise_window (android_window);
extern void android_lower_window (android_window);
+extern void android_reconfigure_wm_window (android_window,
+ enum android_wc_value_mask,
+ struct android_window_changes *);
extern int android_query_tree (android_window, android_window *,
android_window *, android_window **,
unsigned int *);
diff --git a/src/androidmenu.c b/src/androidmenu.c
index 94e3f646b44..1728ae81e42 100644
--- a/src/androidmenu.c
+++ b/src/androidmenu.c
@@ -1,6 +1,6 @@
/* Communication module for Android terminals.
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
@@ -162,10 +162,11 @@ android_dismiss_menu (void *pointer)
struct android_dismiss_menu_data *data;
data = pointer;
- (*android_java_env)->CallVoidMethod (android_java_env,
- data->menu,
- menu_class.dismiss,
- data->window);
+ (*android_java_env)->CallNonvirtualVoidMethod (android_java_env,
+ data->menu,
+ menu_class.class,
+ menu_class.dismiss,
+ data->window);
popup_activated_flag = 0;
}
@@ -247,7 +248,6 @@ android_menu_show (struct frame *f, int x, int y, int menuflags,
jobject title_string, help_string, temp;
size_t i;
Lisp_Object pane_name, prefix;
- const char *pane_string;
specpdl_ref count, count1;
Lisp_Object item_name, enable, def, tem, entry, type, selected;
Lisp_Object help;
@@ -261,9 +261,11 @@ android_menu_show (struct frame *f, int x, int y, int menuflags,
struct android_menu_subprefix *subprefix_1;
bool checkmark;
unsigned int serial;
+ JNIEnv *env;
count = SPECPDL_INDEX ();
serial = ++current_menu_serial;
+ env = android_java_env;
block_input ();
@@ -276,7 +278,7 @@ android_menu_show (struct frame *f, int x, int y, int menuflags,
title_string = NULL;
if (STRINGP (title) && menu_items_n_panes < 2)
- title_string = android_build_string (title);
+ title_string = android_build_string (title, NULL);
/* Push the first local frame for the context menu. */
method = menu_class.create_context_menu;
@@ -313,9 +315,10 @@ android_menu_show (struct frame *f, int x, int y, int menuflags,
context menu. */
store = current_context_menu;
current_context_menu
- = (*android_java_env)->CallObjectMethod (android_java_env,
- current_context_menu,
- menu_class.parent);
+ = (*env)->CallNonvirtualObjectMethod (env,
+ current_context_menu,
+ menu_class.class,
+ menu_class.parent);
android_exception_check ();
if (store != context_menu)
@@ -353,20 +356,26 @@ android_menu_show (struct frame *f, int x, int y, int menuflags,
/* Now figure out the title of this pane. */
pane_name = AREF (menu_items, i + MENU_ITEMS_PANE_NAME);
prefix = AREF (menu_items, i + MENU_ITEMS_PANE_PREFIX);
- pane_string = (NILP (pane_name)
- ? "" : SSDATA (pane_name));
- if ((menuflags & MENU_KEYMAPS) && !NILP (prefix))
- pane_string++;
+
+ /* PANE_NAME may be nil, in which case it must be set to an
+ empty string. */
+
+ if (NILP (pane_name))
+ pane_name = empty_unibyte_string;
+
+ /* Remove the leading prefix character if need be. */
+
+ if ((menuflags & MENU_KEYMAPS) && !NILP (prefix)
+ && SCHARS (prefix))
+ pane_name = Fsubstring (pane_name, make_fixnum (1), Qnil);
/* Add the pane. */
- temp = (*android_java_env)->NewStringUTF (android_java_env,
- pane_string);
+ temp = android_build_string (pane_name, NULL);
android_exception_check ();
- (*android_java_env)->CallVoidMethod (android_java_env,
- current_context_menu,
- menu_class.add_pane,
- temp);
+ (*env)->CallNonvirtualVoidMethod (env, current_context_menu,
+ menu_class.class,
+ menu_class.add_pane, temp);
android_exception_check ();
ANDROID_DELETE_LOCAL_REF (temp);
@@ -390,7 +399,7 @@ android_menu_show (struct frame *f, int x, int y, int menuflags,
{
/* This is a submenu. Add it. */
title_string = (!NILP (item_name)
- ? android_build_string (item_name)
+ ? android_build_string (item_name, NULL)
: NULL);
help_string = NULL;
@@ -399,15 +408,16 @@ android_menu_show (struct frame *f, int x, int y, int menuflags,
if (android_get_current_api_level () >= 26
&& STRINGP (help))
- help_string = android_build_string (help);
+ help_string = android_build_string (help, NULL);
store = current_context_menu;
current_context_menu
- = (*android_java_env)->CallObjectMethod (android_java_env,
- current_context_menu,
- menu_class.add_submenu,
- title_string,
- help_string);
+ = (*env)->CallNonvirtualObjectMethod (env,
+ current_context_menu,
+ menu_class.class,
+ menu_class.add_submenu,
+ title_string,
+ help_string);
android_exception_check ();
if (store != context_menu)
@@ -433,7 +443,7 @@ android_menu_show (struct frame *f, int x, int y, int menuflags,
/* Add this menu item with the appropriate state. */
title_string = (!NILP (item_name)
- ? android_build_string (item_name)
+ ? android_build_string (item_name, NULL)
: NULL);
help_string = NULL;
@@ -442,24 +452,25 @@ android_menu_show (struct frame *f, int x, int y, int menuflags,
if (android_get_current_api_level () >= 26
&& STRINGP (help))
- help_string = android_build_string (help);
+ help_string = android_build_string (help, NULL);
/* Determine whether or not to display a check box. */
checkmark = (EQ (type, QCtoggle)
|| EQ (type, QCradio));
- (*android_java_env)->CallVoidMethod (android_java_env,
- current_context_menu,
- menu_class.add_item,
- (jint) item_id,
- title_string,
- (jboolean) !NILP (enable),
- (jboolean) checkmark,
- (jboolean) !NILP (selected),
- help_string,
- (jboolean) (EQ (type,
- QCradio)));
+ (*env)->CallNonvirtualVoidMethod (env,
+ current_context_menu,
+ menu_class.class,
+ menu_class.add_item,
+ (jint) item_id,
+ title_string,
+ (jboolean) !NILP (enable),
+ (jboolean) checkmark,
+ (jboolean) !NILP (selected),
+ help_string,
+ (jboolean) (EQ (type,
+ QCradio)));
android_exception_check ();
if (title_string)
@@ -479,12 +490,12 @@ android_menu_show (struct frame *f, int x, int y, int menuflags,
/* Now, display the context menu. */
window = android_resolve_handle (FRAME_ANDROID_WINDOW (f),
ANDROID_HANDLE_WINDOW);
- rc = (*android_java_env)->CallBooleanMethod (android_java_env,
- context_menu,
- menu_class.display,
- window, (jint) x,
- (jint) y,
- (jint) serial);
+ rc = (*env)->CallNonvirtualBooleanMethod (env, context_menu,
+ menu_class.class,
+ menu_class.display,
+ window, (jint) x,
+ (jint) y,
+ (jint) serial);
android_exception_check ();
if (!rc)
@@ -652,6 +663,7 @@ android_dialog_show (struct frame *f, Lisp_Object title,
int id;
jmethodID method;
unsigned int serial;
+ JNIEnv *env;
/* Generate a unique ID for events from this dialog box. */
serial = ++current_menu_serial;
@@ -674,7 +686,7 @@ android_dialog_show (struct frame *f, Lisp_Object title,
: android_build_jstring ("Question"));
/* And the title. */
- java_title = android_build_string (title);
+ java_title = android_build_string (title, NULL);
/* Now create the dialog. */
method = dialog_class.create_dialog;
@@ -690,6 +702,11 @@ android_dialog_show (struct frame *f, Lisp_Object title,
ANDROID_DELETE_LOCAL_REF (java_header);
ANDROID_DELETE_LOCAL_REF (java_title);
+ /* Save the JNI environment pointer prior to constructing the
+ dialog, as typing (*android_java_env)->... gives rise to very
+ long lines. */
+ env = android_java_env;
+
/* Create the buttons. */
i = MENU_ITEMS_PANE_LENGTH;
while (i < menu_items_used)
@@ -721,12 +738,12 @@ android_dialog_show (struct frame *f, Lisp_Object title,
}
/* Add the button. */
- temp = android_build_string (item_name);
- (*android_java_env)->CallVoidMethod (android_java_env,
- dialog,
- dialog_class.add_button,
- temp, (jint) i,
- (jboolean) NILP (enable));
+ temp = android_build_string (item_name, NULL);
+ (*env)->CallNonvirtualVoidMethod (env, dialog,
+ dialog_class.class,
+ dialog_class.add_button,
+ temp, (jint) i,
+ (jboolean) NILP (enable));
android_exception_check ();
ANDROID_DELETE_LOCAL_REF (temp);
i += MENU_ITEMS_ITEM_LENGTH;
@@ -734,9 +751,9 @@ android_dialog_show (struct frame *f, Lisp_Object title,
}
/* The dialog is now built. Run it. */
- rc = (*android_java_env)->CallBooleanMethod (android_java_env,
- dialog,
- dialog_class.display);
+ rc = (*env)->CallNonvirtualBooleanMethod (env, dialog,
+ dialog_class.class,
+ dialog_class.display);
android_exception_check ();
if (!rc)
diff --git a/src/androidselect.c b/src/androidselect.c
index 5735eda2dd5..3ba3058aeb9 100644
--- a/src/androidselect.c
+++ b/src/androidselect.c
@@ -1,6 +1,6 @@
/* Communication module for Android terminals.
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
@@ -90,7 +90,7 @@ android_init_emacs_clipboard (void)
= (*android_java_env)->GetMethodID (android_java_env, \
clipboard_class.class, \
name, signature); \
- assert (clipboard_class.c_name);
+ eassert (clipboard_class.c_name);
FIND_METHOD (set_clipboard, "setClipboard", "([B)V");
FIND_METHOD (owns_clipboard, "ownsClipboard", "()I");
@@ -107,7 +107,7 @@ android_init_emacs_clipboard (void)
"makeClipboard",
"()Lorg/gnu/emacs/"
"EmacsClipboard;");
- assert (clipboard_class.make_clipboard);
+ eassert (clipboard_class.make_clipboard);
#undef FIND_METHOD
}
@@ -299,7 +299,7 @@ data type available from the clipboard. */)
bytes_array);
for (i = 0; i < length; ++i)
{
- /* Retireve the MIME type. */
+ /* Retrieve the MIME type. */
bytes
= (*android_java_env)->GetObjectArrayElement (android_java_env,
bytes_array, i);
@@ -511,7 +511,7 @@ android_init_emacs_desktop_notification (void)
= (*android_java_env)->GetMethodID (android_java_env, \
notification_class.class, \
name, signature); \
- assert (notification_class.c_name);
+ eassert (notification_class.c_name);
FIND_METHOD (init, "<init>", "(Ljava/lang/String;"
"Ljava/lang/String;Ljava/lang/String;"
@@ -613,10 +613,12 @@ android_notifications_notify_1 (Lisp_Object title, Lisp_Object body,
(long int) (boot_time.tv_sec / 2), id);
/* Encode all strings into their Java counterparts. */
- title1 = android_build_string (title);
- body1 = android_build_string (body);
- group1 = android_build_string (group);
- identifier1 = android_build_jstring (identifier);
+ title1 = android_build_string (title, NULL);
+ body1 = android_build_string (body, title1, NULL);
+ group1 = android_build_string (group, body1, title1, NULL);
+ identifier1
+ = (*android_java_env)->NewStringUTF (android_java_env, identifier);
+ android_exception_check_3 (title1, body1, group1);
/* Create the notification. */
notification
@@ -660,12 +662,18 @@ keywords is understood:
:icon The name of a drawable resource to display as the
notification's icon.
-The notification group and urgency are ignored on Android 7.1 and
-earlier versions of Android. Outside such older systems, it
-identifies a category that will be displayed in the system Settings
-menu. The urgency provided always extends to affect all notifications
-displayed within that category. If the group is not provided, it
-defaults to the string "Desktop Notifications".
+The notification group is ignored on Android 7.1 and earlier versions
+of Android. Outside such older systems, it identifies a category that
+will be displayed in the system Settings menu, and the urgency
+provided always extends to affect all notifications displayed within
+that category. If the group is not provided, it defaults to the
+string "Desktop Notifications".
+
+Each caller should strive to provide one unchanging combination of
+notification group and urgency for each kind of notification it sends,
+inasmuch as the system may, subject to user configuration, disregard
+the urgency specified within a notification, should it not be the
+first notification sent to its notification group.
The provided icon should be the name of a "drawable resource" present
within the "android.R.drawable" class designating an icon with a
diff --git a/src/androidterm.c b/src/androidterm.c
index a60dd50e5db..2e4ee64f390 100644
--- a/src/androidterm.c
+++ b/src/androidterm.c
@@ -1,6 +1,6 @@
/* Communication module for Android terminals.
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
@@ -21,7 +21,6 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
-#include <assert.h>
#include <semaphore.h>
#include "lisp.h"
@@ -687,9 +686,17 @@ android_handle_ime_event (union android_event *event, struct frame *f)
{
case ANDROID_IME_COMMIT_TEXT:
case ANDROID_IME_SET_COMPOSING_TEXT:
+ case ANDROID_IME_REPLACE_TEXT:
text = android_decode_utf16 (event->ime.text,
event->ime.length);
xfree (event->ime.text);
+
+ /* Return should text be long enough that it overflows ptrdiff_t.
+ Such circumstances are detected within android_decode_utf16. */
+
+ if (NILP (text))
+ return;
+
break;
default:
@@ -773,6 +780,12 @@ android_handle_ime_event (union android_event *event, struct frame *f)
case ANDROID_IME_REQUEST_CURSOR_UPDATES:
android_request_cursor_updates (f, event->ime.length);
break;
+
+ case ANDROID_IME_REPLACE_TEXT:
+ replace_text (f, event->ime.start, event->ime.end,
+ text, event->ime.position,
+ event->ime.counter);
+ break;
}
}
@@ -1128,7 +1141,7 @@ handle_one_android_event (struct android_display_info *dpyinfo,
Lisp_Object window
= window_from_coordinates (f, event->xmotion.x,
event->xmotion.y, 0,
- false, false);
+ false, false, false);
/* A window will be autoselected only when it is not
selected now and the last mouse movement event was
@@ -1277,7 +1290,7 @@ handle_one_android_event (struct android_display_info *dpyinfo,
int x = event->xbutton.x;
int y = event->xbutton.y;
- window = window_from_coordinates (f, x, y, 0, true, true);
+ window = window_from_coordinates (f, x, y, 0, true, true, true);
tab_bar_p = EQ (window, f->tab_bar_window);
if (tab_bar_p)
@@ -1299,7 +1312,7 @@ handle_one_android_event (struct android_display_info *dpyinfo,
int x = event->xbutton.x;
int y = event->xbutton.y;
- window = window_from_coordinates (f, x, y, 0, true, true);
+ window = window_from_coordinates (f, x, y, 0, true, true, true);
tool_bar_p = (EQ (window, f->tool_bar_window)
&& ((event->xbutton.type
!= ANDROID_BUTTON_RELEASE)
@@ -1364,7 +1377,7 @@ handle_one_android_event (struct android_display_info *dpyinfo,
{
/* Simply update the tool position and send an update. */
touchpoint->x = event->touch.x;
- touchpoint->y = event->touch.x;
+ touchpoint->y = event->touch.y;
android_update_tools (any, &inev.ie);
inev.ie.timestamp = event->touch.time;
@@ -1377,7 +1390,7 @@ handle_one_android_event (struct android_display_info *dpyinfo,
touchpoint = xmalloc (sizeof *touchpoint);
touchpoint->tool_id = event->touch.pointer_id;
touchpoint->x = event->touch.x;
- touchpoint->y = event->touch.x;
+ touchpoint->y = event->touch.y;
touchpoint->next = FRAME_OUTPUT_DATA (any)->touch_points;
touchpoint->tool_bar_p = false;
FRAME_OUTPUT_DATA (any)->touch_points = touchpoint;
@@ -1395,7 +1408,7 @@ handle_one_android_event (struct android_display_info *dpyinfo,
int y = event->touch.y;
window = window_from_coordinates (any, x, y, 0, true,
- true);
+ true, true);
/* If this touch has started in the tool bar, do not
send it to Lisp. Instead, simulate a tool bar
@@ -1592,7 +1605,7 @@ handle_one_android_event (struct android_display_info *dpyinfo,
/* Figure out how much to scale the deltas by. */
window = window_from_coordinates (any, event->wheel.x,
event->wheel.y, NULL,
- false, false);
+ false, false, false);
if (WINDOWP (window))
scroll_height = XWINDOW (window)->pixel_height;
@@ -1692,6 +1705,45 @@ handle_one_android_event (struct android_display_info *dpyinfo,
goto OTHER;
+ case ANDROID_DND_DRAG_EVENT:
+
+ if (!any)
+ goto OTHER;
+
+ /* Generate a drag and drop event to convey its position. */
+ inev.ie.kind = DRAG_N_DROP_EVENT;
+ XSETFRAME (inev.ie.frame_or_window, any);
+ inev.ie.timestamp = ANDROID_CURRENT_TIME;
+ XSETINT (inev.ie.x, event->dnd.x);
+ XSETINT (inev.ie.y, event->dnd.y);
+ inev.ie.arg = Fcons (inev.ie.x, inev.ie.y);
+ goto OTHER;
+
+ case ANDROID_DND_URI_EVENT:
+ case ANDROID_DND_TEXT_EVENT:
+
+ if (!any)
+ {
+ free (event->dnd.uri_or_string);
+ goto OTHER;
+ }
+
+ /* An item was dropped over ANY, and is a file in the form of a
+ content or file URI or a string to be inserted. Generate an
+ event with this information. */
+
+ inev.ie.kind = DRAG_N_DROP_EVENT;
+ XSETFRAME (inev.ie.frame_or_window, any);
+ inev.ie.timestamp = ANDROID_CURRENT_TIME;
+ XSETINT (inev.ie.x, event->dnd.x);
+ XSETINT (inev.ie.y, event->dnd.y);
+ inev.ie.arg = Fcons ((event->type == ANDROID_DND_TEXT_EVENT
+ ? Qtext : Quri),
+ android_decode_utf16 (event->dnd.uri_or_string,
+ event->dnd.length));
+ free (event->dnd.uri_or_string);
+ goto OTHER;
+
default:
goto OTHER;
}
@@ -2440,7 +2492,8 @@ android_reset_clip_rectangles (struct frame *f, struct android_gc *gc)
static void
android_clip_to_row (struct window *w, struct glyph_row *row,
- enum glyph_row_area area, struct android_gc *gc)
+ enum glyph_row_area area, struct android_gc *gc,
+ struct android_rectangle *rect_return)
{
struct android_rectangle clip_rect;
int window_x, window_y, window_width;
@@ -2454,6 +2507,9 @@ android_clip_to_row (struct window *w, struct glyph_row *row,
clip_rect.height = row->visible_height;
android_set_clip_rectangles (gc, 0, 0, &clip_rect, 1);
+
+ if (rect_return)
+ *rect_return = clip_rect;
}
static void
@@ -2463,9 +2519,10 @@ android_draw_fringe_bitmap (struct window *w, struct glyph_row *row,
struct frame *f = XFRAME (WINDOW_FRAME (w));
struct android_gc *gc = f->output_data.android->normal_gc;
struct face *face = p->face;
+ struct android_rectangle clip_rect;
/* Must clip because of partially visible lines. */
- android_clip_to_row (w, row, ANY_AREA, gc);
+ android_clip_to_row (w, row, ANY_AREA, gc, &clip_rect);
if (p->bx >= 0 && !p->overlay_p)
{
@@ -2499,6 +2556,8 @@ android_draw_fringe_bitmap (struct window *w, struct glyph_row *row,
struct android_gc_values gcv;
unsigned long background, cursor_pixel;
int depth;
+ struct android_rectangle image_rect, dest;
+ int px, py, pwidth, pheight;
drawable = FRAME_ANDROID_DRAWABLE (f);
clipmask = ANDROID_NONE;
@@ -2506,6 +2565,28 @@ android_draw_fringe_bitmap (struct window *w, struct glyph_row *row,
cursor_pixel = f->output_data.android->cursor_pixel;
depth = FRAME_DISPLAY_INFO (f)->n_planes;
+ /* Intersect the destination rectangle with that of the row.
+ Setting a clip mask overrides the clip rectangles provided by
+ android_clip_to_row, so clipping must be performed by
+ hand. */
+
+ image_rect.x = p->x;
+ image_rect.y = p->y;
+ image_rect.width = p->wd;
+ image_rect.height = p->h;
+
+ if (!gui_intersect_rectangles (&clip_rect, &image_rect, &dest))
+ /* The entire destination rectangle falls outside the row. */
+ goto undo_clip;
+
+ /* Extrapolate the source rectangle from the difference between
+ the destination and image rectangles. */
+
+ px = dest.x - image_rect.x;
+ py = dest.y - image_rect.y;
+ pwidth = dest.width;
+ pheight = dest.height;
+
if (p->wd > 8)
bits = (char *) (p->bits + p->dh);
else
@@ -2533,8 +2614,8 @@ android_draw_fringe_bitmap (struct window *w, struct glyph_row *row,
&gcv);
}
- android_copy_area (pixmap, drawable, gc, 0, 0, p->wd, p->h,
- p->x, p->y);
+ android_copy_area (pixmap, drawable, gc, px, py,
+ pwidth, pheight, dest.x, dest.y);
android_free_pixmap (pixmap);
if (p->overlay_p)
@@ -2545,6 +2626,7 @@ android_draw_fringe_bitmap (struct window *w, struct glyph_row *row,
}
}
+ undo_clip:
android_reset_clip_rectangles (f, gc);
}
@@ -4327,7 +4409,7 @@ android_draw_hollow_cursor (struct window *w, struct glyph_row *row)
wd -= 1;
}
/* Set clipping, draw the rectangle, and reset clipping again. */
- android_clip_to_row (w, row, TEXT_AREA, gc);
+ android_clip_to_row (w, row, TEXT_AREA, gc, NULL);
android_draw_rectangle (FRAME_ANDROID_DRAWABLE (f), gc, x, y, wd, h - 1);
android_reset_clip_rectangles (f, gc);
}
@@ -4385,7 +4467,7 @@ android_draw_bar_cursor (struct window *w, struct glyph_row *row, int width,
FRAME_DISPLAY_INFO (f)->scratch_cursor_gc = gc;
}
- android_clip_to_row (w, row, TEXT_AREA, gc);
+ android_clip_to_row (w, row, TEXT_AREA, gc, NULL);
if (kind == BAR_CURSOR)
{
@@ -4827,6 +4909,39 @@ NATIVE_NAME (finishComposingText) (JNIEnv *env, jobject object,
android_write_event (&event);
}
+JNIEXPORT void JNICALL
+NATIVE_NAME (replaceText) (JNIEnv *env, jobject object, jshort window,
+ jint start, jint end, jobject text,
+ int new_cursor_position, jobject attribute)
+{
+ JNI_STACK_ALIGNMENT_PROLOGUE;
+
+ union android_event event;
+ size_t length;
+
+ /* First, obtain a copy of the Java string. */
+ text = android_copy_java_string (env, text, &length);
+
+ if (!text)
+ return;
+
+ /* Next, populate the event with the information in this function's
+ arguments. */
+
+ event.ime.type = ANDROID_INPUT_METHOD;
+ event.ime.serial = ++event_serial;
+ event.ime.window = window;
+ event.ime.operation = ANDROID_IME_REPLACE_TEXT;
+ event.ime.start = start + 1;
+ event.ime.end = end + 1;
+ event.ime.length = length;
+ event.ime.position = new_cursor_position;
+ event.ime.text = text;
+ event.ime.counter = ++edit_counter;
+
+ android_write_event (&event);
+}
+
/* Structure describing the context used for a text query. */
struct android_conversion_query_context
@@ -5287,11 +5402,22 @@ NATIVE_NAME (performContextMenuAction) (JNIEnv *env, jobject object,
switch (action)
{
+ /* The subsequent three keycodes are addressed by
+ android_get_keysym_name rather than in keyboard.c. */
+
case 0: /* android.R.id.selectAll */
+ key = 65536 + 1;
+ break;
+
case 1: /* android.R.id.startSelectingText */
+ key = 65536 + 2;
+ break;
+
case 2: /* android.R.id.stopSelectingText */
+ key = 65536 + 3;
+ break;
+
default:
- /* These actions are not implemented. */
return;
case 3: /* android.R.id.cut */
@@ -5486,15 +5612,15 @@ NATIVE_NAME (getExtractedText) (JNIEnv *env, jobject ignored_object,
class
= (*env)->FindClass (env, ("android/view/inputmethod"
"/ExtractedTextRequest"));
- assert (class);
+ eassert (class);
request_class.hint_max_chars
= (*env)->GetFieldID (env, class, "hintMaxChars", "I");
- assert (request_class.hint_max_chars);
+ eassert (request_class.hint_max_chars);
request_class.token
= (*env)->GetFieldID (env, class, "token", "I");
- assert (request_class.token);
+ eassert (request_class.token);
request_class.initialized = true;
}
@@ -5504,12 +5630,12 @@ NATIVE_NAME (getExtractedText) (JNIEnv *env, jobject ignored_object,
text_class.class
= (*env)->FindClass (env, ("android/view/inputmethod"
"/ExtractedText"));
- assert (text_class.class);
+ eassert (text_class.class);
class
= text_class.class
= (*env)->NewGlobalRef (env, text_class.class);
- assert (text_class.class);
+ eassert (text_class.class);
text_class.flags
= (*env)->GetFieldID (env, class, "flags", "I");
@@ -5808,7 +5934,7 @@ android_get_surrounding_text_internal (JNIEnv *env, jshort window,
return NULL;
}
#else /* __ANDROID_API__ >= 31 */
- assert (class);
+ eassert (class);
#endif /* __ANDROID_API__ < 31 */
class = (*env)->NewGlobalRef (env, class);
@@ -5820,7 +5946,7 @@ android_get_surrounding_text_internal (JNIEnv *env, jshort window,
/* Now look for its constructor. */
constructor = (*env)->GetMethodID (env, class, "<init>",
"(Ljava/lang/CharSequence;III)V");
- assert (constructor);
+ eassert (constructor);
}
context.before_length = before_length;
@@ -5916,7 +6042,7 @@ NATIVE_NAME (takeSnapshot) (JNIEnv *env, jobject object, jshort window)
return NULL;
}
#else /* __ANDROID_API__ >= 33 */
- assert (class);
+ eassert (class);
#endif /* __ANDROID_API__ < 33 */
class = (*env)->NewGlobalRef (env, class);
@@ -5928,7 +6054,7 @@ NATIVE_NAME (takeSnapshot) (JNIEnv *env, jobject object, jshort window)
constructor = (*env)->GetMethodID (env, class, "<init>",
"(Landroid/view/inputmethod"
"/SurroundingText;III)V");
- assert (constructor);
+ eassert (constructor);
}
/* Try to create a TextSnapshot object. */
@@ -5975,7 +6101,7 @@ android_update_selection (struct frame *f, struct window *w)
else
start = -1, end = -1;
- /* Now constrain START and END to the maximium size of a Java
+ /* Now constrain START and END to the maximum size of a Java
integer. */
start = min (start, TYPE_MAXIMUM (jint));
end = min (end, TYPE_MAXIMUM (jint));
@@ -6112,7 +6238,7 @@ android_reset_conversion (struct frame *f)
android_reset_ic (FRAME_ANDROID_WINDOW (f), mode);
- /* Clear extracted text flags. Since the IM has been reinitialised,
+ /* Clear extracted text flags. Since the IM has been reinitialized,
it should no longer be displaying extracted text. */
FRAME_ANDROID_OUTPUT (f)->extracted_text_flags = 0;
@@ -6516,6 +6642,10 @@ Emacs is running on. */);
pdumper_do_now_and_after_load (android_set_build_fingerprint);
DEFSYM (Qx_underline_at_descent_line, "x-underline-at-descent-line");
+
+ /* Symbols defined for DND events. */
+ DEFSYM (Quri, "uri");
+ DEFSYM (Qtext, "text");
}
void
diff --git a/src/androidterm.h b/src/androidterm.h
index e75d46b1dfb..7568055a20b 100644
--- a/src/androidterm.h
+++ b/src/androidterm.h
@@ -1,6 +1,6 @@
/* Communication module for Android terminals.
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
@@ -262,7 +262,7 @@ struct android_output
text''. */
int extracted_text_flags;
- /* Token asssociated with that request. */
+ /* Token associated with that request. */
int extracted_text_token;
/* The number of characters of extracted text wanted by the IM. */
diff --git a/src/androidvfs.c b/src/androidvfs.c
index d6b832d6caf..3377683c84f 100644
--- a/src/androidvfs.c
+++ b/src/androidvfs.c
@@ -1,6 +1,6 @@
/* Android virtual file-system support for GNU Emacs.
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
@@ -26,6 +26,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include <errno.h>
#include <minmax.h>
#include <string.h>
+#include <systime.h>
#include <semaphore.h>
#include <sys/stat.h>
@@ -402,6 +403,16 @@ android_init_fd_class (JNIEnv *env)
+/* Account for SAF file names two times as large as PATH_MAX; larger
+ values are prohibitively slow, but smaller values can't face up to
+ some long file names within several nested layers of directories.
+
+ Buffers holding components or other similar file name constituents
+ which don't represent SAF files must continue to use PATH_MAX, for
+ that is the restriction imposed by the Unix file system. */
+
+#define EMACS_PATH_MAX (PATH_MAX * 2)
+
/* Delete redundant instances of `.' and `..' from NAME in-place.
NAME must be *LENGTH long, excluding a mandatory trailing NULL
byte.
@@ -1920,6 +1931,21 @@ android_afs_open (struct android_vnode *vnode, int flags,
/* Size of the file. */
info->statb.st_size = AAsset_getLength (asset);
+ /* If the installation date can be ascertained, return that as
+ the file's modification time. */
+
+ if (timespec_valid_p (emacs_installation_time))
+ {
+#ifdef STAT_TIMESPEC
+ STAT_TIMESPEC (&info->statb, st_mtim) = emacs_installation_time;
+#else /* !STAT_TIMESPEC */
+ /* Headers supplied by the NDK r10b contain a `struct stat'
+ without POSIX fields for nano-second timestamps. */
+ info->statb.st_mtime = emacs_installation_time.tv_sec;
+ info->statb.st_mtime_nsec = emacs_installation_time.tv_nsec;
+#endif /* STAT_TIMESPEC */
+ }
+
/* Chain info onto afs_file_descriptors. */
afs_file_descriptors = info;
@@ -2058,7 +2084,7 @@ android_afs_stat (struct android_vnode *vnode, struct stat *statb)
/* Concoct a nonexistent device and an inode number. */
statb->st_dev = -1;
statb->st_ino = 0;
- return 0;
+ goto set_file_times;
}
/* AASSET_MODE_STREAMING is fastest here. */
@@ -2083,6 +2109,24 @@ android_afs_stat (struct android_vnode *vnode, struct stat *statb)
/* Close the asset. */
AAsset_close (asset_desc);
+
+ set_file_times:
+
+ /* If the installation date can be ascertained, return that as the
+ file's modification time. */
+
+ if (timespec_valid_p (emacs_installation_time))
+ {
+#ifdef STAT_TIMESPEC
+ STAT_TIMESPEC (statb, st_mtim) = emacs_installation_time;
+#else /* !STAT_TIMESPEC */
+ /* Headers supplied by the NDK r10b contain a `struct stat'
+ without POSIX fields for nano-second timestamps. */
+ statb->st_mtime = emacs_installation_time.tv_sec;
+ statb->st_mtime_nsec = emacs_installation_time.tv_nsec;
+#endif /* STAT_TIMESPEC */
+ }
+
return 0;
}
@@ -2864,6 +2908,7 @@ android_check_content_access (const char *uri, int mode)
{
jobject string;
jboolean rc, read, write;
+ jmethodID method;
string = (*android_java_env)->NewStringUTF (android_java_env, uri);
android_exception_check ();
@@ -2873,11 +2918,13 @@ android_check_content_access (const char *uri, int mode)
read = (bool) (mode & R_OK || (mode == F_OK));
write = (bool) (mode & W_OK);
+ method = service_class.check_content_uri;
- rc = (*android_java_env)->CallBooleanMethod (android_java_env,
- emacs_service,
- service_class.check_content_uri,
- string, read, write);
+ rc = (*android_java_env)->CallNonvirtualBooleanMethod (android_java_env,
+ emacs_service,
+ service_class.class,
+ method, string, read,
+ write);
android_exception_check_1 (string);
ANDROID_DELETE_LOCAL_REF (string);
return rc;
@@ -2979,6 +3026,15 @@ android_authority_name (struct android_vnode *vnode, char *name,
if (*name == '/')
name++, length -= 1;
+ /* If the provided URI is a directory, return NULL and set errno
+ to ENOTDIR. Content files are never directories. */
+
+ if (name[length - 1] == '/')
+ {
+ errno = ENOTDIR;
+ return NULL;
+ }
+
/* NAME must be a valid JNI string, so that it can be encoded
properly. */
@@ -3014,6 +3070,7 @@ android_authority_open (struct android_vnode *vnode, int flags,
size_t length;
jobject string;
int fd;
+ JNIEnv *env;
vp = (struct android_authority_vnode *) vnode;
@@ -3025,39 +3082,40 @@ android_authority_open (struct android_vnode *vnode, int flags,
return -1;
}
+ /* Save the JNI environment within `env', to make wrapping
+ subsequent lines referencing CallNonvirtualIntMethod
+ feasible. */
+ env = android_java_env;
+
/* Allocate a buffer to hold the file name. */
length = strlen (vp->uri);
- string = (*android_java_env)->NewByteArray (android_java_env,
- length);
+ string = (*env)->NewByteArray (env, length);
if (!string)
{
- (*android_java_env)->ExceptionClear (android_java_env);
+ (*env)->ExceptionClear (env);
errno = ENOMEM;
return -1;
}
/* Copy the URI into this byte array. */
- (*android_java_env)->SetByteArrayRegion (android_java_env,
- string, 0, length,
- (jbyte *) vp->uri);
+ (*env)->SetByteArrayRegion (env, string, 0, length,
+ (jbyte *) vp->uri);
/* Try to open the file descriptor. */
- fd
- = (*android_java_env)->CallIntMethod (android_java_env,
- emacs_service,
- service_class.open_content_uri,
- string,
- (jboolean) ((mode & O_WRONLY
- || mode & O_RDWR)
- != 0),
- (jboolean) !(mode & O_WRONLY),
- (jboolean) ((mode & O_TRUNC)
- != 0));
-
- if ((*android_java_env)->ExceptionCheck (android_java_env))
+ fd = (*env)->CallNonvirtualIntMethod (env, emacs_service,
+ service_class.class,
+ service_class.open_content_uri,
+ string,
+ (jboolean) ((mode & O_WRONLY
+ || mode & O_RDWR)
+ != 0),
+ (jboolean) !(mode & O_WRONLY),
+ (jboolean) ((mode & O_TRUNC)
+ != 0));
+ if ((*env)->ExceptionCheck (env))
{
- (*android_java_env)->ExceptionClear (android_java_env);
+ (*env)->ExceptionClear (env);
errno = ENOMEM;
ANDROID_DELETE_LOCAL_REF (string);
return -1;
@@ -3959,8 +4017,11 @@ android_saf_exception_check (int n, ...)
/* First, check for an exception. */
if (!(*env)->ExceptionCheck (env))
- /* No exception has taken place. Return 0. */
- return 0;
+ {
+ /* No exception has taken place. Return 0. */
+ va_end (ap);
+ return 0;
+ }
/* Print the exception. */
(*env)->ExceptionDescribe (env);
@@ -4009,6 +4070,7 @@ android_saf_exception_check (int n, ...)
/* expression is still a local reference! */
ANDROID_DELETE_LOCAL_REF ((jobject) exception);
errno = new_errno;
+ va_end (ap);
return 1;
}
@@ -4117,7 +4179,7 @@ android_saf_stat (const char *uri_name, const char *id_name,
}
/* Detect if Emacs has access to the document designated by the the
- documen ID ID_NAME within the tree URI_NAME. If ID_NAME is NULL,
+ document ID ID_NAME within the tree URI_NAME. If ID_NAME is NULL,
use the document ID in URI_NAME itself.
If WRITABLE, also check that the file is writable, which is true
@@ -4233,10 +4295,11 @@ android_saf_delete_document (const char *tree, const char *doc_id,
/* Now, try to delete the document. */
method = service_class.delete_document;
- rc = (*android_java_env)->CallIntMethod (android_java_env,
- emacs_service,
- method, uri, id,
- name);
+ rc = (*android_java_env)->CallNonvirtualIntMethod (android_java_env,
+ emacs_service,
+ service_class.class,
+ method, uri, id,
+ name);
if (android_saf_exception_check (3, id, uri, name))
return -1;
@@ -4391,11 +4454,13 @@ android_saf_move_document (const char *uri, char **doc_id,
/* Do the rename. */
method = service_class.move_document;
- result = (*android_java_env)->CallObjectMethod (android_java_env,
- emacs_service,
- method, uri1,
- doc_id1, dir_name1,
- dst_id1, src_id1);
+ result
+ = (*android_java_env)->CallNonvirtualObjectMethod (android_java_env,
+ emacs_service,
+ service_class.class,
+ method, uri1,
+ doc_id1, dir_name1,
+ dst_id1, src_id1);
if (android_saf_exception_check (5, src_id1, dst_id1, dir_name1,
doc_id1, uri1))
{
@@ -4935,7 +5000,7 @@ android_saf_tree_rename (struct android_vnode *src,
{
char *last, *dst_last;
struct android_saf_tree_vnode *vp, *vdst;
- char path[PATH_MAX], path1[PATH_MAX];
+ char path[EMACS_PATH_MAX], path1[EMACS_PATH_MAX];
char *fill, *dst_id;
int rc;
@@ -5021,8 +5086,8 @@ android_saf_tree_rename (struct android_vnode *src,
/* The names of the source and destination directories will have
to be copied to path. */
- if (last - vp->name >= PATH_MAX
- || dst_last - vdst->name >= PATH_MAX)
+ if (last - vp->name >= EMACS_PATH_MAX
+ || dst_last - vdst->name >= EMACS_PATH_MAX)
{
errno = ENAMETOOLONG;
return -1;
@@ -5136,7 +5201,7 @@ android_saf_tree_rename (struct android_vnode *src,
directory is required, as it provides the directory whose entries
will be modified. */
- if (last - vp->name >= PATH_MAX)
+ if (last - vp->name >= EMACS_PATH_MAX)
{
errno = ENAMETOOLONG;
return -1;
@@ -5425,7 +5490,7 @@ android_saf_tree_opendir (struct android_vnode *vnode)
struct android_saf_tree_vdir *dir;
char *fill, *end;
jobject cursor;
- char component[PATH_MAX];
+ char component[EMACS_PATH_MAX];
vp = (struct android_saf_tree_vnode *) vnode;
@@ -5455,7 +5520,7 @@ android_saf_tree_opendir (struct android_vnode *vnode)
if (!end)
emacs_abort ();
- if (end - fill >= PATH_MAX)
+ if (end - fill >= EMACS_PATH_MAX)
{
errno = ENAMETOOLONG;
xfree (dir);
@@ -6362,7 +6427,7 @@ android_root_name (struct android_vnode *vnode, char *name,
if (!component_end)
component_end = name + length;
else
- /* Move past the spearator character. */
+ /* Move past the separator character. */
component_end++;
/* Now, find out if the first component is a special vnode; if so,
@@ -6400,7 +6465,7 @@ android_root_name (struct android_vnode *vnode, char *name,
least N bytes.
NAME may be either an absolute file name or a name relative to the
- current working directory. It must not be longer than PATH_MAX
+ current working directory. It must not be longer than EMACS_PATH_MAX
bytes.
Value is NULL upon failure with errno set accordingly, or the
@@ -6409,14 +6474,14 @@ android_root_name (struct android_vnode *vnode, char *name,
static struct android_vnode *
android_name_file (const char *name)
{
- char buffer[PATH_MAX + 1], *head;
+ char buffer[EMACS_PATH_MAX + 1], *head;
const char *end;
size_t len;
int nslash, c;
struct android_vnode *vp;
len = strlen (name);
- if (len > PATH_MAX)
+ if (len > EMACS_PATH_MAX)
{
errno = ENAMETOOLONG;
return NULL;
@@ -6502,12 +6567,12 @@ android_vfs_init (JNIEnv *env, jobject manager)
/* Initialize some required classes. */
java_string_class = (*env)->FindClass (env, "java/lang/String");
- assert (java_string_class);
+ eassert (java_string_class);
old = java_string_class;
java_string_class = (jclass) (*env)->NewGlobalRef (env,
java_string_class);
- assert (java_string_class);
+ eassert (java_string_class);
(*env)->DeleteLocalRef (env, old);
/* And initialize those used on Android 5.0 and later. */
@@ -6954,7 +7019,7 @@ int
android_fstatat (int dirfd, const char *restrict pathname,
struct stat *restrict statbuf, int flags)
{
- char buffer[PATH_MAX + 1];
+ char buffer[EMACS_PATH_MAX + 1];
struct android_vnode *vp;
int rc;
@@ -6968,7 +7033,7 @@ android_fstatat (int dirfd, const char *restrict pathname,
/* Now establish whether DIRFD is a file descriptor corresponding to
an open VFS directory stream. */
- if (!android_fstatat_1 (dirfd, pathname, buffer, PATH_MAX + 1))
+ if (!android_fstatat_1 (dirfd, pathname, buffer, EMACS_PATH_MAX + 1))
{
pathname = buffer;
goto vfs;
@@ -6994,7 +7059,7 @@ int
android_faccessat (int dirfd, const char *restrict pathname,
int mode, int flags)
{
- char buffer[PATH_MAX + 1];
+ char buffer[EMACS_PATH_MAX + 1];
struct android_vnode *vp;
int rc;
@@ -7008,7 +7073,7 @@ android_faccessat (int dirfd, const char *restrict pathname,
/* Now establish whether DIRFD is a file descriptor corresponding to
an open VFS directory stream. */
- if (!android_fstatat_1 (dirfd, pathname, buffer, PATH_MAX + 1))
+ if (!android_fstatat_1 (dirfd, pathname, buffer, EMACS_PATH_MAX + 1))
{
pathname = buffer;
goto vfs;
@@ -7034,7 +7099,7 @@ int
android_fchmodat (int dirfd, const char *pathname, mode_t mode,
int flags)
{
- char buffer[PATH_MAX + 1];
+ char buffer[EMACS_PATH_MAX + 1];
struct android_vnode *vp;
int rc;
@@ -7044,7 +7109,7 @@ android_fchmodat (int dirfd, const char *pathname, mode_t mode,
/* Now establish whether DIRFD is a file descriptor corresponding to
an open VFS directory stream. */
- if (!android_fstatat_1 (dirfd, pathname, buffer, PATH_MAX + 1))
+ if (!android_fstatat_1 (dirfd, pathname, buffer, EMACS_PATH_MAX + 1))
{
pathname = buffer;
goto vfs;
@@ -7070,7 +7135,7 @@ ssize_t
android_readlinkat (int dirfd, const char *restrict pathname,
char *restrict buf, size_t bufsiz)
{
- char buffer[PATH_MAX + 1];
+ char buffer[EMACS_PATH_MAX + 1];
struct android_vnode *vp;
ssize_t rc;
@@ -7080,7 +7145,7 @@ android_readlinkat (int dirfd, const char *restrict pathname,
/* Now establish whether DIRFD is a file descriptor corresponding to
an open VFS directory stream. */
- if (!android_fstatat_1 (dirfd, pathname, buffer, PATH_MAX + 1))
+ if (!android_fstatat_1 (dirfd, pathname, buffer, EMACS_PATH_MAX + 1))
{
pathname = buffer;
goto vfs;
@@ -7107,7 +7172,7 @@ android_readlinkat (int dirfd, const char *restrict pathname,
while file streams also require ownership over file descriptors
they are created on behalf of.
- Detaching the parcel file descriptor linked to FD consequentially
+ Detaching the parcel file descriptor linked to FD consequently
prevents the owner from being notified when it is eventually
closed, but for now that hasn't been demonstrated to be problematic
yet, as Emacs doesn't write to file streams. */
@@ -7341,6 +7406,21 @@ android_asset_fstat (struct android_fd_or_asset asset,
statb->st_uid = 0;
statb->st_gid = 0;
+ /* If the installation date can be ascertained, return that as the
+ file's modification time. */
+
+ if (timespec_valid_p (emacs_installation_time))
+ {
+#ifdef STAT_TIMESPEC
+ STAT_TIMESPEC (statb, st_mtim) = emacs_installation_time;
+#else /* !STAT_TIMESPEC */
+ /* Headers supplied by the NDK r10b contain a `struct stat'
+ without POSIX fields for nano-second timestamps. */
+ statb->st_mtime = emacs_installation_time.tv_sec;
+ statb->st_mtime_nsec = emacs_installation_time.tv_nsec;
+#endif /* STAT_TIMESPEC */
+ }
+
/* Size of the file. */
statb->st_size = AAsset_getLength (asset.asset);
return 0;
diff --git a/src/atimer.c b/src/atimer.c
index d07cdb82b7a..8253ae3a166 100644
--- a/src/atimer.c
+++ b/src/atimer.c
@@ -1,5 +1,5 @@
/* Asynchronous timers.
- Copyright (C) 2000-2023 Free Software Foundation, Inc.
+ Copyright (C) 2000-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/atimer.h b/src/atimer.h
index 551c186d24e..51de226b82e 100644
--- a/src/atimer.h
+++ b/src/atimer.h
@@ -1,5 +1,5 @@
/* Asynchronous timers.
- Copyright (C) 2000-2023 Free Software Foundation, Inc.
+ Copyright (C) 2000-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/bidi.c b/src/bidi.c
index 3c26ae19322..93bb061ac32 100644
--- a/src/bidi.c
+++ b/src/bidi.c
@@ -1,6 +1,6 @@
/* Low-level bidirectional buffer/string-scanning functions for GNU Emacs.
-Copyright (C) 2000-2001, 2004-2005, 2009-2023 Free Software Foundation,
+Copyright (C) 2000-2001, 2004-2005, 2009-2024 Free Software Foundation,
Inc.
Author: Eli Zaretskii <eliz@gnu.org>
diff --git a/src/bignum.c b/src/bignum.c
index 22ed171533f..1fe195d78ea 100644
--- a/src/bignum.c
+++ b/src/bignum.c
@@ -1,6 +1,6 @@
/* Big numbers for Emacs.
-Copyright 2018-2023 Free Software Foundation, Inc.
+Copyright 2018-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/bignum.h b/src/bignum.h
index b9957a642d1..2749f8370d0 100644
--- a/src/bignum.h
+++ b/src/bignum.h
@@ -1,6 +1,6 @@
/* Big numbers for Emacs.
-Copyright 2018-2023 Free Software Foundation, Inc.
+Copyright 2018-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/blockinput.h b/src/blockinput.h
index 5fd63c2575c..88a1f68849e 100644
--- a/src/blockinput.h
+++ b/src/blockinput.h
@@ -1,5 +1,5 @@
/* blockinput.h - interface to blocking complicated interrupt-driven input.
- Copyright (C) 1989, 1993, 2001-2023 Free Software Foundation, Inc.
+ Copyright (C) 1989, 1993, 2001-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/buffer.c b/src/buffer.c
index 9facc4b7ab8..352aca8ddfd 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -1,6 +1,6 @@
/* Buffer manipulation primitives for GNU Emacs.
-Copyright (C) 1985-2023 Free Software Foundation, Inc.
+Copyright (C) 1985-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
@@ -210,11 +210,6 @@ bset_buffer_file_coding_system (struct buffer *b, Lisp_Object val)
b->buffer_file_coding_system_ = val;
}
static void
-bset_case_fold_search (struct buffer *b, Lisp_Object val)
-{
- b->case_fold_search_ = val;
-}
-static void
bset_ctl_arrow (struct buffer *b, Lisp_Object val)
{
b->ctl_arrow_ = val;
@@ -519,8 +514,11 @@ See also `find-buffer-visiting'. */)
return Qnil;
}
-Lisp_Object
-get_truename_buffer (register Lisp_Object filename)
+DEFUN ("get-truename-buffer", Fget_truename_buffer, Sget_truename_buffer, 1, 1, 0,
+ doc: /* Return the buffer with `file-truename' equal to FILENAME (a string).
+If there is no such live buffer, return nil.
+See also `find-buffer-visiting'. */)
+ (register Lisp_Object filename)
{
register Lisp_Object tail, buf;
@@ -533,6 +531,22 @@ get_truename_buffer (register Lisp_Object filename)
return Qnil;
}
+DEFUN ("find-buffer", Ffind_buffer, Sfind_buffer, 2, 2, 0,
+ doc: /* Return the buffer with buffer-local VARIABLE `equal' to VALUE.
+If there is no such live buffer, return nil.
+See also `find-buffer-visiting'. */)
+ (Lisp_Object variable, Lisp_Object value)
+{
+ register Lisp_Object tail, buf;
+
+ FOR_EACH_LIVE_BUFFER (tail, buf)
+ {
+ if (!NILP (Fequal (value, Fbuffer_local_value (variable, buf))))
+ return buf;
+ }
+ return Qnil;
+}
+
/* Run buffer-list-update-hook if Vrun_hooks is non-nil and BUF does
not have buffer hooks inhibited. */
@@ -1739,7 +1753,7 @@ exists, return the buffer `*scratch*' (creating it if necessary). */)
if (!NILP (notsogood))
return notsogood;
else
- return safe_call (1, Qget_scratch_buffer_create);
+ return safe_calln (Qget_scratch_buffer_create);
}
/* The following function is a safe variant of Fother_buffer: It doesn't
@@ -1760,7 +1774,7 @@ other_buffer_safely (Lisp_Object buffer)
becoming dead under our feet. safe_call below could return nil
if recreating *scratch* in Lisp, which does some fancy stuff,
signals an error in some weird use case. */
- buf = safe_call (1, Qget_scratch_buffer_create);
+ buf = safe_calln (Qget_scratch_buffer_create);
if (NILP (buf))
{
AUTO_STRING (scratch, "*scratch*");
@@ -4099,7 +4113,7 @@ report_overlay_modification (Lisp_Object start, Lisp_Object end, bool after,
}
/* Test for intersecting intervals. This does the right thing
for both insertion and deletion. */
- if (! insertion || (end_arg > obegin && begin_arg < oend))
+ if (end_arg > obegin && begin_arg < oend)
{
Lisp_Object prop = Foverlay_get (overlay, Qmodification_hooks);
if (!NILP (prop))
@@ -4673,7 +4687,6 @@ init_buffer_once (void)
XSETFASTINT (BVAR (&buffer_local_flags, mode_line_format), idx); ++idx;
XSETFASTINT (BVAR (&buffer_local_flags, abbrev_mode), idx); ++idx;
XSETFASTINT (BVAR (&buffer_local_flags, overwrite_mode), idx); ++idx;
- XSETFASTINT (BVAR (&buffer_local_flags, case_fold_search), idx); ++idx;
XSETFASTINT (BVAR (&buffer_local_flags, auto_fill_function), idx); ++idx;
XSETFASTINT (BVAR (&buffer_local_flags, selective_display), idx); ++idx;
XSETFASTINT (BVAR (&buffer_local_flags, selective_display_ellipses), idx); ++idx;
@@ -4766,7 +4779,6 @@ init_buffer_once (void)
bset_tab_line_format (&buffer_defaults, Qnil);
bset_abbrev_mode (&buffer_defaults, Qnil);
bset_overwrite_mode (&buffer_defaults, Qnil);
- bset_case_fold_search (&buffer_defaults, Qt);
bset_auto_fill_function (&buffer_defaults, Qnil);
bset_selective_display (&buffer_defaults, Qnil);
bset_selective_display_ellipses (&buffer_defaults, Qt);
@@ -5196,10 +5208,6 @@ Format with `format-mode-line' to produce a string value. */);
doc: /* Non-nil if Abbrev mode is enabled.
Use the command `abbrev-mode' to change this variable. */);
- DEFVAR_PER_BUFFER ("case-fold-search", &BVAR (current_buffer, case_fold_search),
- Qnil,
- doc: /* Non-nil if searches and matches should ignore case. */);
-
DEFVAR_PER_BUFFER ("fill-column", &BVAR (current_buffer, fill_column),
Qintegerp,
doc: /* Column beyond which automatic line-wrapping should happen.
@@ -5359,8 +5367,8 @@ visual lines rather than logical lines. See the documentation of
Qstringp,
doc: /* Name of default directory of current buffer.
It should be an absolute directory name; on GNU and Unix systems,
-these names start with `/' or `~' and end with `/'.
-To interactively change the default directory, use command `cd'. */);
+these names start with "/" or "~" and end with "/".
+To interactively change the default directory, use the command `cd'. */);
DEFVAR_PER_BUFFER ("auto-fill-function", &BVAR (current_buffer, auto_fill_function),
Qnil,
@@ -5932,6 +5940,12 @@ If `delete-auto-save-files' is nil, any autosave deletion is inhibited. */);
This is the default. If nil, auto-save file deletion is inhibited. */);
delete_auto_save_files = 1;
+ DEFVAR_LISP ("case-fold-search", Vcase_fold_search,
+ doc: /* Non-nil if searches and matches should ignore case. */);
+ Vcase_fold_search = Qt;
+ DEFSYM (Qcase_fold_search, "case-fold-search");
+ Fmake_variable_buffer_local (Qcase_fold_search);
+
DEFVAR_LISP ("clone-indirect-buffer-hook", Vclone_indirect_buffer_hook,
doc: /* Normal hook to run in the new buffer at the end of `make-indirect-buffer'.
@@ -6010,6 +6024,8 @@ There is no reason to change that value except for debugging purposes. */);
defsubr (&Sbuffer_list);
defsubr (&Sget_buffer);
defsubr (&Sget_file_buffer);
+ defsubr (&Sget_truename_buffer);
+ defsubr (&Sfind_buffer);
defsubr (&Sget_buffer_create);
defsubr (&Smake_indirect_buffer);
defsubr (&Sgenerate_new_buffer_name);
diff --git a/src/buffer.h b/src/buffer.h
index e71ffe28045..80edfdcbc22 100644
--- a/src/buffer.h
+++ b/src/buffer.h
@@ -1,6 +1,6 @@
/* Header file for the buffer manipulation primitives.
-Copyright (C) 1985-2023 Free Software Foundation, Inc.
+Copyright (C) 1985-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
@@ -379,7 +379,6 @@ struct buffer
/* Values of several buffer-local variables. */
/* tab-width is buffer-local so that redisplay can find it
in buffers that are not current. */
- Lisp_Object case_fold_search_;
Lisp_Object tab_width_;
Lisp_Object fill_column_;
Lisp_Object left_margin_;
@@ -656,9 +655,9 @@ struct buffer
ptrdiff_t last_window_start;
/* If the long line scan cache is enabled (i.e. the buffer-local
- variable cache-long-line-scans is non-nil), newline_cache
- points to the newline cache, and width_run_cache points to the
- width run cache.
+ variable cache-long-scans is non-nil), newline_cache points to
+ the newline cache, and width_run_cache points to the width run
+ cache.
The newline cache records which stretches of the buffer are
known *not* to contain newlines, so that they can be skipped
diff --git a/src/bytecode.c b/src/bytecode.c
index c53ef678edd..e989e5fadf0 100644
--- a/src/bytecode.c
+++ b/src/bytecode.c
@@ -1,5 +1,5 @@
/* Execution of byte code produced by bytecomp.el.
- Copyright (C) 1985-1988, 1993, 2000-2023 Free Software Foundation,
+ Copyright (C) 1985-1988, 1993, 2000-2024 Free Software Foundation,
Inc.
This file is part of GNU Emacs.
diff --git a/src/callint.c b/src/callint.c
index 00e9a080654..b31faba8704 100644
--- a/src/callint.c
+++ b/src/callint.c
@@ -1,5 +1,5 @@
/* Call a Lisp function interactively.
- Copyright (C) 1985-1986, 1993-1995, 1997, 2000-2023 Free Software
+ Copyright (C) 1985-1986, 1993-1995, 1997, 2000-2024 Free Software
Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/callproc.c b/src/callproc.c
index dc37dfdc01f..db36ef569e6 100644
--- a/src/callproc.c
+++ b/src/callproc.c
@@ -1,6 +1,6 @@
/* Synchronous subprocess invocation for GNU Emacs.
-Copyright (C) 1985-1988, 1993-1995, 1999-2023 Free Software Foundation,
+Copyright (C) 1985-1988, 1993-1995, 1999-2024 Free Software Foundation,
Inc.
This file is part of GNU Emacs.
@@ -1735,6 +1735,10 @@ getenv_internal (const char *var, ptrdiff_t varlen, char **value,
}
#endif
+ /* Setting DISPLAY under Android hinders attempts to display other
+ programs within X servers that are available for Android. */
+
+#ifndef HAVE_ANDROID
/* For DISPLAY try to get the values from the frame or the initial env. */
if (strcmp (var, "DISPLAY") == 0)
{
@@ -1747,12 +1751,13 @@ getenv_internal (const char *var, ptrdiff_t varlen, char **value,
*valuelen = SBYTES (display);
return 1;
}
-#endif
+#endif /* !HAVE_PGTK */
/* If still not found, Look for DISPLAY in Vinitial_environment. */
if (getenv_internal_1 (var, varlen, value, valuelen,
Vinitial_environment))
return *value ? 1 : 0;
}
+#endif /* !HAVE_ANDROID */
return 0;
}
@@ -1845,7 +1850,9 @@ make_environment_block (Lisp_Object current_dir)
register char **new_env;
char **p, **q;
register int new_length;
+#ifndef HAVE_ANDROID
Lisp_Object display = Qnil;
+#endif /* !HAVE_ANDROID */
new_length = 0;
@@ -1853,14 +1860,20 @@ make_environment_block (Lisp_Object current_dir)
CONSP (tem) && STRINGP (XCAR (tem));
tem = XCDR (tem))
{
+#ifndef HAVE_ANDROID
if (strncmp (SSDATA (XCAR (tem)), "DISPLAY", 7) == 0
&& (SDATA (XCAR (tem)) [7] == '\0'
|| SDATA (XCAR (tem)) [7] == '='))
/* DISPLAY is specified in process-environment. */
display = Qt;
+#endif /* !HAVE_ANDROID */
new_length++;
}
+ /* Setting DISPLAY under Android hinders attempts to display other
+ programs within X servers that are available for Android. */
+
+#ifndef HAVE_ANDROID
/* If not provided yet, use the frame's DISPLAY. */
if (NILP (display))
{
@@ -1875,7 +1888,7 @@ make_environment_block (Lisp_Object current_dir)
&& strcmp (G_OBJECT_TYPE_NAME (FRAME_X_DISPLAY (SELECTED_FRAME ())),
"GdkX11Display"))
tmp = Qnil;
-#endif
+#endif /* HAVE_PGTK */
if (!STRINGP (tmp) && CONSP (Vinitial_environment))
/* If still not found, Look for DISPLAY in Vinitial_environment. */
@@ -1887,6 +1900,7 @@ make_environment_block (Lisp_Object current_dir)
new_length++;
}
}
+#endif /* !HAVE_ANDROID */
/* new_length + 2 to include PWD and terminating 0. */
env = new_env = xnmalloc (new_length + 2, sizeof *env);
@@ -1896,6 +1910,7 @@ make_environment_block (Lisp_Object current_dir)
if (egetenv ("PWD"))
*new_env++ = pwd_var;
+#ifndef HAVE_ANDROID
if (STRINGP (display))
{
char *vdata = xmalloc (sizeof "DISPLAY=" + SBYTES (display));
@@ -1903,6 +1918,7 @@ make_environment_block (Lisp_Object current_dir)
lispstpcpy (stpcpy (vdata, "DISPLAY="), display);
new_env = add_env (env, new_env, vdata);
}
+#endif /* !HAVE_ANDROID */
/* Overrides. */
for (tem = Vprocess_environment;
@@ -2216,6 +2232,17 @@ the system. */);
Vebrowse_program_name = build_pure_c_string ("libebrowse.so");
#endif
+ DEFVAR_LISP ("rcs2log-program-name", Vrcs2log_program_name,
+ doc: /* Name of the `rcs2log' program distributed with Emacs.
+Use this instead of calling `rcs2log' directly, as `rcs2log'
+may have been renamed to comply with executable naming restrictions on
+the system. */);
+#if !defined HAVE_ANDROID || defined ANDROID_STUBIFY
+ Vrcs2log_program_name = build_pure_c_string ("rcs2log");
+#else /* HAVE_ANDROID && !ANDROID_STUBIFY */
+ Vrcs2log_program_name = build_pure_c_string ("librcs2log.so");
+#endif /* !HAVE_ANDROID || ANDROID_STUBIFY */
+
defsubr (&Scall_process);
defsubr (&Sgetenv_internal);
defsubr (&Scall_process_region);
diff --git a/src/casefiddle.c b/src/casefiddle.c
index d567a5e353a..b252f07ae13 100644
--- a/src/casefiddle.c
+++ b/src/casefiddle.c
@@ -1,7 +1,7 @@
/* -*- coding: utf-8 -*- */
/* GNU Emacs case conversion functions.
-Copyright (C) 1985, 1994, 1997-1999, 2001-2023 Free Software Foundation,
+Copyright (C) 1985, 1994, 1997-1999, 2001-2024 Free Software Foundation,
Inc.
This file is part of GNU Emacs.
@@ -92,6 +92,12 @@ prepare_casing_context (struct casing_context *ctx,
SETUP_BUFFER_SYNTAX_TABLE (); /* For syntax_prefix_flag_p. */
}
+static bool
+case_ch_is_word (enum syntaxcode syntax)
+{
+ return syntax == Sword || (case_symbols_as_words && syntax == Ssymbol);
+}
+
struct casing_str_buf
{
unsigned char data[max (6, MAX_MULTIBYTE_LENGTH)];
@@ -115,7 +121,7 @@ case_character_impl (struct casing_str_buf *buf,
/* Update inword state */
bool was_inword = ctx->inword;
- ctx->inword = SYNTAX (ch) == Sword &&
+ ctx->inword = case_ch_is_word (SYNTAX (ch)) &&
(!ctx->inbuffer || was_inword || !syntax_prefix_flag_p (ch));
/* Normalize flag so its one of CASE_UP, CASE_DOWN or CASE_CAPITALIZE. */
@@ -222,7 +228,7 @@ case_character (struct casing_str_buf *buf, struct casing_context *ctx,
has a word syntax (i.e. current character is end of word), use final
sigma. */
if (was_inword && ch == GREEK_CAPITAL_LETTER_SIGMA && changed
- && (!next || SYNTAX (STRING_CHAR (next)) != Sword))
+ && (!next || !case_ch_is_word (SYNTAX (STRING_CHAR (next)))))
{
buf->len_bytes = CHAR_STRING (GREEK_SMALL_LETTER_FINAL_SIGMA, buf->data);
buf->len_chars = 1;
@@ -720,6 +726,21 @@ Called with one argument METHOD which can be:
3rd argument. */);
Vregion_extract_function = Qnil; /* simple.el sets this. */
+ DEFVAR_BOOL ("case-symbols-as-words", case_symbols_as_words,
+ doc: /* If non-nil, case functions treat symbol syntax as part of words.
+
+Functions such as `upcase-initials' and `replace-match' check or modify
+the case pattern of sequences of characters. Normally, these operate on
+sequences of characters whose syntax is word constituent. If this
+variable is non-nil, then they operate on sequences of characters whose
+syntax is either word constituent or symbol constituent.
+
+This is useful for programming languages and styles where only the first
+letter of a symbol's name is ever capitalized.*/);
+ case_symbols_as_words = 0;
+ DEFSYM (Qcase_symbols_as_words, "case-symbols-as-words");
+ Fmake_variable_buffer_local (Qcase_symbols_as_words);
+
defsubr (&Supcase);
defsubr (&Sdowncase);
defsubr (&Scapitalize);
diff --git a/src/casetab.c b/src/casetab.c
index f844022395a..41e9004e10f 100644
--- a/src/casetab.c
+++ b/src/casetab.c
@@ -1,5 +1,5 @@
/* GNU Emacs routines to deal with case tables.
- Copyright (C) 1993-1994, 2001-2023 Free Software Foundation, Inc.
+ Copyright (C) 1993-1994, 2001-2024 Free Software Foundation, Inc.
Author: Howard Gayle
diff --git a/src/category.c b/src/category.c
index dac5c78b5af..b539bad31eb 100644
--- a/src/category.c
+++ b/src/category.c
@@ -1,6 +1,6 @@
/* GNU Emacs routines to deal with category tables.
-Copyright (C) 1998, 2001-2023 Free Software Foundation, Inc.
+Copyright (C) 1998, 2001-2024 Free Software Foundation, Inc.
Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
2005, 2006, 2007, 2008, 2009, 2010, 2011
National Institute of Advanced Industrial Science and Technology (AIST)
diff --git a/src/ccl.c b/src/ccl.c
index 67f2a275841..1d3ad010382 100644
--- a/src/ccl.c
+++ b/src/ccl.c
@@ -1,5 +1,5 @@
/* CCL (Code Conversion Language) interpreter.
- Copyright (C) 2001-2023 Free Software Foundation, Inc.
+ Copyright (C) 2001-2024 Free Software Foundation, Inc.
Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
2005, 2006, 2007, 2008, 2009, 2010, 2011
National Institute of Advanced Industrial Science and Technology (AIST)
diff --git a/src/character.c b/src/character.c
index 2118b20a7c7..dcad8f83793 100644
--- a/src/character.c
+++ b/src/character.c
@@ -1,6 +1,6 @@
/* Basic character support.
-Copyright (C) 2001-2023 Free Software Foundation, Inc.
+Copyright (C) 2001-2024 Free Software Foundation, Inc.
Copyright (C) 1995, 1997, 1998, 2001 Electrotechnical Laboratory, JAPAN.
Licensed to the Free Software Foundation.
Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
diff --git a/src/charset.c b/src/charset.c
index d5e42d038df..3aa105e57bd 100644
--- a/src/charset.c
+++ b/src/charset.c
@@ -1,6 +1,6 @@
/* Basic character set support.
-Copyright (C) 2001-2023 Free Software Foundation, Inc.
+Copyright (C) 2001-2024 Free Software Foundation, Inc.
Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
2005, 2006, 2007, 2008, 2009, 2010, 2011
diff --git a/src/charset.h b/src/charset.h
index 6d115fa3596..1743eb4c909 100644
--- a/src/charset.h
+++ b/src/charset.h
@@ -1,5 +1,5 @@
/* Header for charset handler.
- Copyright (C) 2001-2023 Free Software Foundation, Inc.
+ Copyright (C) 2001-2024 Free Software Foundation, Inc.
Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
2005, 2006, 2007, 2008, 2009, 2010, 2011
National Institute of Advanced Industrial Science and Technology (AIST)
diff --git a/src/chartab.c b/src/chartab.c
index 6f0bc28f31b..58bb1658504 100644
--- a/src/chartab.c
+++ b/src/chartab.c
@@ -580,7 +580,8 @@ DEFUN ("char-table-range", Fchar_table_range, Schar_table_range,
2, 2, 0,
doc: /* Return the value in CHAR-TABLE for a range of characters RANGE.
RANGE should be nil (for the default value),
-a cons of character codes (for characters in the range), or a character code. */)
+a cons of character codes (for characters in the range), or a character code.
+If RANGE is a cons (FROM . TO), the function returns the value for FROM. */)
(Lisp_Object char_table, Lisp_Object range)
{
Lisp_Object val;
diff --git a/src/cm.c b/src/cm.c
index 4711085d796..d6b54d507c7 100644
--- a/src/cm.c
+++ b/src/cm.c
@@ -1,5 +1,5 @@
/* Cursor motion subroutines for GNU Emacs.
- Copyright (C) 1985, 1995, 2001-2023 Free Software Foundation, Inc.
+ Copyright (C) 1985, 1995, 2001-2024 Free Software Foundation, Inc.
based primarily on public domain code written by Chris Torek
This file is part of GNU Emacs.
diff --git a/src/cm.h b/src/cm.h
index 70d2c7078fc..871980551d9 100644
--- a/src/cm.h
+++ b/src/cm.h
@@ -1,5 +1,5 @@
/* Cursor motion calculation definitions for GNU Emacs
- Copyright (C) 1985, 1989, 2001-2023 Free Software Foundation, Inc.
+ Copyright (C) 1985, 1989, 2001-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/cmds.c b/src/cmds.c
index a9b4bd9c321..81788b07242 100644
--- a/src/cmds.c
+++ b/src/cmds.c
@@ -1,6 +1,6 @@
/* Simple built-in editing commands.
-Copyright (C) 1985, 1993-1998, 2001-2023 Free Software Foundation, Inc.
+Copyright (C) 1985, 1993-1998, 2001-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/coding.c b/src/coding.c
index b7f4120dc8d..219e3554c18 100644
--- a/src/coding.c
+++ b/src/coding.c
@@ -1,5 +1,5 @@
/* Coding system handler (conversion, detection, etc).
- Copyright (C) 2001-2023 Free Software Foundation, Inc.
+ Copyright (C) 2001-2024 Free Software Foundation, Inc.
Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
2005, 2006, 2007, 2008, 2009, 2010, 2011
National Institute of Advanced Industrial Science and Technology (AIST)
@@ -8170,7 +8170,7 @@ decode_coding_object (struct coding_system *coding,
Fcons (undo_list, Fcurrent_buffer ()));
bset_undo_list (current_buffer, Qt);
TEMP_SET_PT_BOTH (coding->dst_pos, coding->dst_pos_byte);
- val = safe_call1 (CODING_ATTR_POST_READ (attrs),
+ val = safe_calln (CODING_ATTR_POST_READ (attrs),
make_fixnum (coding->produced_char));
CHECK_FIXNAT (val);
coding->produced_char += Z - prev_Z;
@@ -8336,7 +8336,7 @@ encode_coding_object (struct coding_system *coding,
set_buffer_internal (XBUFFER (coding->src_object));
}
- safe_call2 (CODING_ATTR_PRE_WRITE (attrs),
+ safe_calln (CODING_ATTR_PRE_WRITE (attrs),
make_fixnum (BEG), make_fixnum (Z));
if (XBUFFER (coding->src_object) != current_buffer)
kill_src_buffer = 1;
diff --git a/src/coding.h b/src/coding.h
index 08c29c884a5..e9b72403c6b 100644
--- a/src/coding.h
+++ b/src/coding.h
@@ -1,5 +1,5 @@
/* Header for coding system handler.
- Copyright (C) 2001-2023 Free Software Foundation, Inc.
+ Copyright (C) 2001-2024 Free Software Foundation, Inc.
Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
2005, 2006, 2007, 2008, 2009, 2010, 2011
National Institute of Advanced Industrial Science and Technology (AIST)
diff --git a/src/commands.h b/src/commands.h
index ac7cdb60db3..6ba81241f99 100644
--- a/src/commands.h
+++ b/src/commands.h
@@ -1,5 +1,5 @@
/* Definitions needed by most editing commands.
- Copyright (C) 1985, 1994, 2001-2023 Free Software Foundation, Inc.
+ Copyright (C) 1985, 1994, 2001-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/comp.c b/src/comp.c
index b81a80b00f8..6cb35a8619a 100644
--- a/src/comp.c
+++ b/src/comp.c
@@ -1,5 +1,5 @@
/* Compile Emacs Lisp into native code.
- Copyright (C) 2019-2023 Free Software Foundation, Inc.
+ Copyright (C) 2019-2024 Free Software Foundation, Inc.
Author: Andrea Corallo <acorallo@gnu.org>
diff --git a/src/comp.h b/src/comp.h
index f86f3c5ed85..158ed0b46df 100644
--- a/src/comp.h
+++ b/src/comp.h
@@ -1,6 +1,6 @@
/* Elisp native compiler definitions
-Copyright (C) 2019-2023 Free Software Foundation, Inc.
+Copyright (C) 2019-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/composite.c b/src/composite.c
index 9332c1cb9a3..91836fa2a8f 100644
--- a/src/composite.c
+++ b/src/composite.c
@@ -1,5 +1,5 @@
/* Composite sequence support.
- Copyright (C) 2001-2023 Free Software Foundation, Inc.
+ Copyright (C) 2001-2024 Free Software Foundation, Inc.
Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
National Institute of Advanced Industrial Science and Technology (AIST)
Registration Number H14PRO021
@@ -987,7 +987,7 @@ autocmp_chars (Lisp_Object rule, ptrdiff_t charpos, ptrdiff_t bytepos,
if (NILP (string))
record_unwind_protect (restore_point_unwind,
build_marker (current_buffer, pt, pt_byte));
- lgstring = safe_call (7, Vauto_composition_function, AREF (rule, 2),
+ lgstring = safe_calln (Vauto_composition_function, AREF (rule, 2),
pos, make_fixnum (to), font_object, string,
direction);
}
diff --git a/src/composite.h b/src/composite.h
index 0f791c1ea62..c99888ccec2 100644
--- a/src/composite.h
+++ b/src/composite.h
@@ -1,5 +1,5 @@
/* Header for composite sequence handler.
- Copyright (C) 2001-2023 Free Software Foundation, Inc.
+ Copyright (C) 2001-2024 Free Software Foundation, Inc.
Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
National Institute of Advanced Industrial Science and Technology (AIST)
Registration Number H14PRO021
diff --git a/src/conf_post.h b/src/conf_post.h
index f31e012dc6e..7701bcf40b2 100644
--- a/src/conf_post.h
+++ b/src/conf_post.h
@@ -1,6 +1,6 @@
/* conf_post.h --- configure.ac includes this via AH_BOTTOM
-Copyright (C) 1988, 1993-1994, 1999-2002, 2004-2023 Free Software
+Copyright (C) 1988, 1993-1994, 1999-2002, 2004-2024 Free Software
Foundation, Inc.
This file is part of GNU Emacs.
@@ -96,7 +96,7 @@ typedef bool bool_bf;
#ifdef emacs
/* We include stdlib.h here, because Gnulib's stdlib.h might redirect
'free' to its replacement, and we want to avoid that in unexec
- builds. Inclduing it here will render its inclusion after config.h
+ builds. Including it here will render its inclusion after config.h
a no-op. */
# if (defined DARWIN_OS && defined HAVE_UNEXEC) || defined HYBRID_MALLOC
# include <stdlib.h>
diff --git a/src/cygw32.c b/src/cygw32.c
index 35cac23504e..7658e9a24a0 100644
--- a/src/cygw32.c
+++ b/src/cygw32.c
@@ -1,5 +1,5 @@
/* Cygwin support routines.
- Copyright (C) 2011-2023 Free Software Foundation, Inc.
+ Copyright (C) 2011-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/cygw32.h b/src/cygw32.h
index 6f8706e3436..cc3414a39d9 100644
--- a/src/cygw32.h
+++ b/src/cygw32.h
@@ -1,5 +1,5 @@
/* Header for Cygwin support routines.
- Copyright (C) 2011-2023 Free Software Foundation, Inc.
+ Copyright (C) 2011-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/data.c b/src/data.c
index 377bcfce35d..0c47750cb75 100644
--- a/src/data.c
+++ b/src/data.c
@@ -1,5 +1,5 @@
/* Primitive operations on Lisp data types for GNU Emacs Lisp interpreter.
- Copyright (C) 1985-1986, 1988, 1993-1995, 1997-2023 Free Software
+ Copyright (C) 1985-1986, 1988, 1993-1995, 1997-2024 Free Software
Foundation, Inc.
This file is part of GNU Emacs.
@@ -886,7 +886,7 @@ add_to_function_history (Lisp_Object symbol, Lisp_Object olddef)
Lisp_Object past = Fget (symbol, Qfunction_history);
Lisp_Object file = Qnil;
/* FIXME: Sadly, `Vload_file_name` gives less precise information
- (it's sometimes non-nil when it shoujld be nil). */
+ (it's sometimes non-nil when it should be nil). */
Lisp_Object tail = Vcurrent_load_list;
FOR_EACH_TAIL_SAFE (tail)
if (NILP (XCDR (tail)) && STRINGP (XCAR (tail)))
@@ -1607,8 +1607,6 @@ set_internal (Lisp_Object symbol, Lisp_Object newval, Lisp_Object where,
bool voide = BASE_EQ (newval, Qunbound);
/* If restoring in a dead buffer, do nothing. */
- /* if (BUFFERP (where) && NILP (XBUFFER (where)->name))
- return; */
CHECK_SYMBOL (symbol);
struct Lisp_Symbol *sym = XSYMBOL (symbol);
@@ -4369,8 +4367,6 @@ syms_of_data (void)
defsubr (&Sbool_vector_count_consecutive);
defsubr (&Sbool_vector_count_population);
- set_symbol_function (Qwholenump, XSYMBOL (Qnatnump)->u.s.function);
-
DEFVAR_LISP ("most-positive-fixnum", Vmost_positive_fixnum,
doc: /* The greatest integer that is represented efficiently.
This variable cannot be set; trying to do so will signal an error. */);
diff --git a/src/dbusbind.c b/src/dbusbind.c
index 97094e407d7..7069e27e3eb 100644
--- a/src/dbusbind.c
+++ b/src/dbusbind.c
@@ -1,5 +1,5 @@
/* Elisp bindings for D-Bus.
- Copyright (C) 2007-2023 Free Software Foundation, Inc.
+ Copyright (C) 2007-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/decompress.c b/src/decompress.c
index 162f6167b73..fcdbb40fc90 100644
--- a/src/decompress.c
+++ b/src/decompress.c
@@ -1,5 +1,5 @@
/* Interface to zlib.
- Copyright (C) 2013-2023 Free Software Foundation, Inc.
+ Copyright (C) 2013-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/deps.mk b/src/deps.mk
index a7c8ae11f72..65536729014 100644
--- a/src/deps.mk
+++ b/src/deps.mk
@@ -1,6 +1,6 @@
### deps.mk --- src/Makefile fragment for GNU Emacs
-## Copyright (C) 1985, 1987-1988, 1993-1995, 1999-2023 Free Software
+## Copyright (C) 1985, 1987-1988, 1993-1995, 1999-2024 Free Software
## Foundation, Inc.
## This file is part of GNU Emacs.
diff --git a/src/dired.c b/src/dired.c
index c10531cdb16..9a372201ae0 100644
--- a/src/dired.c
+++ b/src/dired.c
@@ -1,5 +1,5 @@
/* Lisp functions for making directory listings.
- Copyright (C) 1985-1986, 1993-1994, 1999-2023 Free Software
+ Copyright (C) 1985-1986, 1993-1994, 1999-2024 Free Software
Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/dispextern.h b/src/dispextern.h
index 3a4d6095f73..6cab3ff243e 100644
--- a/src/dispextern.h
+++ b/src/dispextern.h
@@ -1,6 +1,6 @@
/* Interface definitions for display code.
-Copyright (C) 1985, 1993-1994, 1997-2023 Free Software Foundation, Inc.
+Copyright (C) 1985, 1993-1994, 1997-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
@@ -3618,6 +3618,7 @@ void image_prune_animation_caches (bool);
bool valid_image_p (Lisp_Object);
void prepare_image_for_display (struct frame *, struct image *);
ptrdiff_t lookup_image (struct frame *, Lisp_Object, int);
+Lisp_Object image_spec_value (Lisp_Object, Lisp_Object, bool *);
#if defined HAVE_X_WINDOWS || defined USE_CAIRO || defined HAVE_NS \
|| defined HAVE_HAIKU || defined HAVE_ANDROID
diff --git a/src/dispnew.c b/src/dispnew.c
index d6a27ac29ec..d0f259eef6c 100644
--- a/src/dispnew.c
+++ b/src/dispnew.c
@@ -1,6 +1,6 @@
/* Updating of data structures for redisplay.
-Copyright (C) 1985-1988, 1993-1995, 1997-2023 Free Software Foundation,
+Copyright (C) 1985-1988, 1993-1995, 1997-2024 Free Software Foundation,
Inc.
This file is part of GNU Emacs.
@@ -6206,9 +6206,9 @@ bitch_at_user (void)
DEFUN ("sleep-for", Fsleep_for, Ssleep_for, 1, 2, 0,
doc: /* Pause, without updating display, for SECONDS seconds.
SECONDS may be a floating-point value, meaning that you can wait for a
-fraction of a second. Optional second arg MILLISECONDS specifies an
-additional wait period, in milliseconds; this is for backwards compatibility.
-\(Not all operating systems support waiting for a fraction of a second.) */)
+fraction of a second.
+An optional second arg MILLISECONDS can be provided but is deprecated:
+it specifies an additional wait period, in milliseconds. */)
(Lisp_Object seconds, Lisp_Object milliseconds)
{
double duration = extract_float (seconds);
diff --git a/src/disptab.h b/src/disptab.h
index 0069176fd24..d63d19ae754 100644
--- a/src/disptab.h
+++ b/src/disptab.h
@@ -1,5 +1,5 @@
/* Things for GLYPHS and glyph tables.
- Copyright (C) 1993, 2001-2023 Free Software Foundation, Inc.
+ Copyright (C) 1993, 2001-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/dmpstruct.awk b/src/dmpstruct.awk
index 344a22f977a..706e137a5b0 100644
--- a/src/dmpstruct.awk
+++ b/src/dmpstruct.awk
@@ -1,4 +1,4 @@
-# Copyright (C) 2018-2023 Free Software Foundation, Inc.
+# Copyright (C) 2018-2024 Free Software Foundation, Inc.
#
# This file is part of GNU Emacs.
#
diff --git a/src/doc.c b/src/doc.c
index 37e04262681..a451b468ef2 100644
--- a/src/doc.c
+++ b/src/doc.c
@@ -1,6 +1,6 @@
/* Record indices of function doc strings stored in a file. -*- coding: utf-8 -*-
-Copyright (C) 1985-1986, 1993-1995, 1997-2023 Free Software Foundation,
+Copyright (C) 1985-1986, 1993-1995, 1997-2024 Free Software Foundation,
Inc.
This file is part of GNU Emacs.
diff --git a/src/doprnt.c b/src/doprnt.c
index e8911fad252..d764f25c6f7 100644
--- a/src/doprnt.c
+++ b/src/doprnt.c
@@ -1,7 +1,7 @@
/* Output like sprintf to a buffer of specified size. -*- coding: utf-8 -*-
Also takes args differently: pass one pointer to the end
of the format string in addition to the format string itself.
- Copyright (C) 1985, 2001-2023 Free Software Foundation, Inc.
+ Copyright (C) 1985, 2001-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/dosfns.c b/src/dosfns.c
index ad885311c80..3eb3b34145e 100644
--- a/src/dosfns.c
+++ b/src/dosfns.c
@@ -1,6 +1,6 @@
/* MS-DOS specific Lisp utilities. Coded by Manabu Higashida, 1991.
Major changes May-July 1993 Morten Welinder (only 10% original code left)
- Copyright (C) 1991, 1993, 1996-1998, 2001-2023 Free Software
+ Copyright (C) 1991, 1993, 1996-1998, 2001-2024 Free Software
Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/dosfns.h b/src/dosfns.h
index fbfd734023a..47254d4670b 100644
--- a/src/dosfns.h
+++ b/src/dosfns.h
@@ -2,7 +2,7 @@
Coded by Manabu Higashida, 1991.
Modified by Morten Welinder, 1993-1994.
-Copyright (C) 1991, 1994-1995, 1997, 1999, 2001-2023 Free Software
+Copyright (C) 1991, 1994-1995, 1997, 1999, 2001-2024 Free Software
Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/dynlib.c b/src/dynlib.c
index abbb0c45917..62e6e176c14 100644
--- a/src/dynlib.c
+++ b/src/dynlib.c
@@ -1,6 +1,6 @@
/* Portable API for dynamic loading.
-Copyright 2015-2023 Free Software Foundation, Inc.
+Copyright 2015-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/dynlib.h b/src/dynlib.h
index 9527b758af9..e12958c73cc 100644
--- a/src/dynlib.h
+++ b/src/dynlib.h
@@ -1,6 +1,6 @@
/* Portable API for dynamic loading.
-Copyright 2015-2023 Free Software Foundation, Inc.
+Copyright 2015-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/editfns.c b/src/editfns.c
index 02fca3f5714..f3b3cfb7243 100644
--- a/src/editfns.c
+++ b/src/editfns.c
@@ -1,6 +1,6 @@
/* Lisp functions pertaining to editing. -*- coding: utf-8 -*-
-Copyright (C) 1985-2023 Free Software Foundation, Inc.
+Copyright (C) 1985-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
@@ -727,6 +727,7 @@ This function does not move point. Also see `line-beginning-position'. */)
DEFUN ("line-beginning-position",
Fline_beginning_position, Sline_beginning_position, 0, 1, 0,
doc: /* Return the position of the first character in the current line/field.
+With optional argument N non-nil, move forward N - 1 lines first.
This function is like `pos-bol' (which see), but respects fields.
This function constrains the returned position to the current field
@@ -1784,7 +1785,7 @@ determines whether case is significant or ignored. */)
register EMACS_INT begp1, endp1, begp2, endp2, temp;
register struct buffer *bp1, *bp2;
register Lisp_Object trt
- = (!NILP (BVAR (current_buffer, case_fold_search))
+ = (!NILP (Vcase_fold_search)
? BVAR (current_buffer, case_canon_table) : Qnil);
ptrdiff_t chars = 0;
ptrdiff_t i1, i2, i1_byte, i2_byte;
@@ -2780,7 +2781,7 @@ labeled_restrictions_pop (Lisp_Object buf)
Lisp_Object restrictions = assq_no_quit (buf, labeled_restrictions);
if (NILP (restrictions))
return;
- if (EQ (labeled_restrictions_peek_label (buf), Qoutermost_restriction))
+ if (BASE_EQ (labeled_restrictions_peek_label (buf), Qoutermost_restriction))
labeled_restrictions_remove (buf);
else
XSETCDR (restrictions, list1 (XCDR (XCAR (XCDR (restrictions)))));
@@ -2920,7 +2921,7 @@ To gain access to other portions of the buffer, use
current_buffer are the bounds that were set by the user, no
labeled restriction is in effect in current_buffer anymore:
remove it from the labeled_restrictions alist. */
- if (EQ (label, Qoutermost_restriction))
+ if (BASE_EQ (label, Qoutermost_restriction))
labeled_restrictions_pop (buf);
}
/* Changing the buffer bounds invalidates any recorded current column. */
@@ -4366,7 +4367,7 @@ Case is ignored if `case-fold-search' is non-nil in the current buffer. */)
if (XFIXNUM (c1) == XFIXNUM (c2))
return Qt;
- if (NILP (BVAR (current_buffer, case_fold_search)))
+ if (NILP (Vcase_fold_search))
return Qnil;
i1 = XFIXNAT (c1);
diff --git a/src/emacs-icon.h b/src/emacs-icon.h
index 84ae557be2b..22915b14f33 100644
--- a/src/emacs-icon.h
+++ b/src/emacs-icon.h
@@ -1,7 +1,7 @@
/* XPM */
/* Emacs icon
-Copyright (C) 2008-2023 Free Software Foundation, Inc.
+Copyright (C) 2008-2024 Free Software Foundation, Inc.
Author: Kentaro Ohkouchi <nanasess@fsm.ne.jp>
Nicolas Petton <nicolas@petton.fr>
diff --git a/src/emacs-module.c b/src/emacs-module.c
index 86360a0f225..46bd732e8eb 100644
--- a/src/emacs-module.c
+++ b/src/emacs-module.c
@@ -1,6 +1,6 @@
/* emacs-module.c - Module loading and runtime implementation
-Copyright (C) 2015-2023 Free Software Foundation, Inc.
+Copyright (C) 2015-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/emacs-module.h.in b/src/emacs-module.h.in
index a455c41a5f1..690254bd28c 100644
--- a/src/emacs-module.h.in
+++ b/src/emacs-module.h.in
@@ -1,6 +1,6 @@
/* emacs-module.h - GNU Emacs module API.
-Copyright (C) 2015-2023 Free Software Foundation, Inc.
+Copyright (C) 2015-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/emacs.c b/src/emacs.c
index 687b8c7f81f..eb1871841ec 100644
--- a/src/emacs.c
+++ b/src/emacs.c
@@ -1,6 +1,6 @@
/* Fully extensible Emacs, running on Unix, intended for GNU.
-Copyright (C) 1985-1987, 1993-1995, 1997-1999, 2001-2023 Free Software
+Copyright (C) 1985-1987, 1993-1995, 1997-1999, 2001-2024 Free Software
Foundation, Inc.
This file is part of GNU Emacs.
@@ -401,11 +401,6 @@ section of the Emacs manual or the file BUGS.\n"
/* True if handling a fatal error already. */
bool fatal_error_in_progress;
-#ifdef HAVE_NS
-/* NS autorelease pool, for memory management. */
-static void *ns_pool;
-#endif
-
#if !HAVE_SETLOCALE
static char *
setlocale (int cat, char const *locale)
@@ -1291,7 +1286,7 @@ main (int argc, char **argv)
for pointers. */
void *stack_bottom_variable;
int old_argc;
-#if !(defined HAVE_ANDROID && !defined ANDROID_STUBIFY)
+#if defined HAVE_PDUMPER && !(defined HAVE_ANDROID && !defined ANDROID_STUBIFY)
char *dump_file;
/* This is just a dummy argument used to avoid extra defines. */
@@ -1424,6 +1419,11 @@ main (int argc, char **argv)
w32_init_main_thread ();
#endif
+#ifdef HAVE_NS
+ /* Initialize the Obj C autorelease pool. */
+ ns_init_pool ();
+#endif
+
#ifdef HAVE_PDUMPER
if (attempt_load_pdump)
initial_emacs_executable = load_pdump (argc, argv, dump_file);
@@ -1643,7 +1643,6 @@ main (int argc, char **argv)
if (! (lc_all && strcmp (lc_all, "C") == 0))
{
#ifdef HAVE_NS
- ns_pool = ns_alloc_autorelease_pool ();
ns_init_locale ();
#endif
setlocale (LC_ALL, "");
@@ -2993,10 +2992,6 @@ killed. */
shut_down_emacs (0, (STRINGP (arg) && !feof (stdin)) ? arg : Qnil);
-#ifdef HAVE_NS
- ns_release_autorelease_pool (ns_pool);
-#endif
-
/* If we have an auto-save list file,
kill it because we are exiting Emacs deliberately (not crashing).
Do it after shut_down_emacs, which does an auto-save. */
@@ -3331,9 +3326,6 @@ decode_env_path (const char *evarname, const char *defalt, bool empty)
{
const char *path, *p;
Lisp_Object lpath, element, tem;
-#ifdef NS_SELF_CONTAINED
- void *autorelease = NULL;
-#endif
/* Default is to use "." for empty path elements.
But if argument EMPTY is true, use nil instead. */
Lisp_Object empty_element = empty ? Qnil : build_string (".");
@@ -3361,8 +3353,6 @@ decode_env_path (const char *evarname, const char *defalt, bool empty)
if (!path)
{
#ifdef NS_SELF_CONTAINED
- /* ns_relocate needs a valid autorelease pool around it. */
- autorelease = ns_alloc_autorelease_pool ();
path = ns_relocate (defalt);
#else
path = defalt;
@@ -3466,10 +3456,6 @@ decode_env_path (const char *evarname, const char *defalt, bool empty)
break;
}
-#ifdef NS_SELF_CONTAINED
- if (autorelease)
- ns_release_autorelease_pool (autorelease);
-#endif
return Fnreverse (lpath);
}
diff --git a/src/emacsgtkfixed.c b/src/emacsgtkfixed.c
index 2b6ebee65fd..3941960b3ba 100644
--- a/src/emacsgtkfixed.c
+++ b/src/emacsgtkfixed.c
@@ -1,7 +1,7 @@
/* A Gtk Widget that inherits GtkFixed, but can be shrunk.
This file is only use when compiling with Gtk+ 3.
-Copyright (C) 2011-2023 Free Software Foundation, Inc.
+Copyright (C) 2011-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/emacsgtkfixed.h b/src/emacsgtkfixed.h
index 952dfed5e1e..9fa9ef79278 100644
--- a/src/emacsgtkfixed.h
+++ b/src/emacsgtkfixed.h
@@ -1,7 +1,7 @@
/* A Gtk Widget that inherits GtkFixed, but can be shrunk.
This file is only use when compiling with Gtk+ 3.
-Copyright (C) 2011-2023 Free Software Foundation, Inc.
+Copyright (C) 2011-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/epaths.in b/src/epaths.in
index afddd57763a..275d13985aa 100644
--- a/src/epaths.in
+++ b/src/epaths.in
@@ -1,6 +1,6 @@
/* Hey Emacs, this is -*- C -*- code! */
/*
-Copyright (C) 1993, 1995, 1997, 1999, 2001-2023 Free Software
+Copyright (C) 1993, 1995, 1997, 1999, 2001-2024 Free Software
Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/eval.c b/src/eval.c
index 9268b65aa85..7f67b5a9db8 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -1,6 +1,6 @@
/* Evaluator for GNU Emacs Lisp interpreter.
-Copyright (C) 1985-1987, 1993-1995, 1999-2023 Free Software Foundation,
+Copyright (C) 1985-1987, 1993-1995, 1999-2024 Free Software Foundation,
Inc.
This file is part of GNU Emacs.
@@ -689,7 +689,7 @@ lexbound_p (Lisp_Object symbol)
{
case SPECPDL_LET_DEFAULT:
case SPECPDL_LET:
- if (EQ (specpdl_symbol (pdl), Qinternal_interpreter_environment))
+ if (BASE_EQ (specpdl_symbol (pdl), Qinternal_interpreter_environment))
{
Lisp_Object env = specpdl_old_value (pdl);
if (CONSP (env) && !NILP (Fassq (symbol, env)))
@@ -792,8 +792,7 @@ DEFUN ("defvar", Fdefvar, Sdefvar, 1, UNEVALLED, 0,
You are not required to define a variable in order to use it, but
defining it lets you supply an initial value and documentation, which
can be referred to by the Emacs help facilities and other programming
-tools. The `defvar' form also declares the variable as \"special\",
-so that it is always dynamically bound even if `lexical-binding' is t.
+tools.
If SYMBOL's value is void and the optional argument INITVALUE is
provided, INITVALUE is evaluated and the result used to set SYMBOL's
@@ -801,6 +800,13 @@ value. If SYMBOL is buffer-local, its default value is what is set;
buffer-local values are not affected. If INITVALUE is missing,
SYMBOL's value is not set.
+If INITVALUE is provided, the `defvar' form also declares the variable
+as \"special\", so that it is always dynamically bound even if
+`lexical-binding' is t. If INITVALUE is missing, the form marks the
+variable \"special\" locally (i.e., within the current
+lexical scope, or the current file, if the form is at top-level),
+and does nothing if `lexical-binding' is nil.
+
If SYMBOL is let-bound, then this form does not affect the local let
binding but the toplevel default binding instead, like
`set-toplevel-default-binding`.
@@ -1678,6 +1684,10 @@ DEFUN ("signal", Fsignal, Ssignal, 2, 2, 0,
doc: /* Signal an error. Args are ERROR-SYMBOL and associated DATA.
This function does not return.
+When `noninteractive' is non-nil (in particular, in batch mode), an
+unhandled error calls `kill-emacs', which terminates the Emacs
+session with a non-zero exit code.
+
An error symbol is a symbol with an `error-conditions' property
that is a list of condition names. The symbol should be non-nil.
A handler for any of those names will get to handle this signal.
@@ -1831,7 +1841,7 @@ signal_or_quit (Lisp_Object error_symbol, Lisp_Object data, bool keyboard_quit)
{
max_ensure_room (&max_lisp_eval_depth, lisp_eval_depth, 100);
specpdl_ref count = SPECPDL_INDEX ();
- AUTO_STRING (redisplay_trace, "*Redisplay_trace*");
+ AUTO_STRING (redisplay_trace, "*Redisplay-trace*");
Lisp_Object redisplay_trace_buffer;
AUTO_STRING (gap, "\n\n\n\n"); /* Separates things in *Redisplay-trace* */
Lisp_Object delayed_warning;
@@ -1847,7 +1857,7 @@ signal_or_quit (Lisp_Object error_symbol, Lisp_Object data, bool keyboard_quit)
call_debugger (list2 (Qerror, Fcons (error_symbol, data)));
unbind_to (count, Qnil);
delayed_warning = make_string
- ("Error in a redisplay Lisp hook. See buffer *Redisplay_trace*", 61);
+ ("Error in a redisplay Lisp hook. See buffer *Redisplay-trace*", 61);
Vdelayed_warnings_list = Fcons (list2 (Qerror, delayed_warning),
Vdelayed_warnings_list);
@@ -2364,9 +2374,13 @@ static Lisp_Object list_of_t; /* Never-modified constant containing (t). */
DEFUN ("eval", Feval, Seval, 1, 2, 0,
doc: /* Evaluate FORM and return its value.
-If LEXICAL is t, evaluate using lexical scoping.
-LEXICAL can also be an actual lexical environment, in the form of an
-alist mapping symbols to their value. */)
+If LEXICAL is `t', evaluate using lexical binding by default.
+This is the recommended value.
+
+If absent or `nil', use dynamic scoping only.
+
+LEXICAL can also represent an actual lexical environment; see the Info
+node `(elisp)Eval' for details. */)
(Lisp_Object form, Lisp_Object lexical)
{
specpdl_ref count = SPECPDL_INDEX ();
@@ -3015,6 +3029,35 @@ usage: (funcall FUNCTION &rest ARGUMENTS) */)
}
+static Lisp_Object
+safe_eval_handler (Lisp_Object arg, ptrdiff_t nargs, Lisp_Object *args)
+{
+ add_to_log ("Error muted by safe_call: %S signaled %S",
+ Flist (nargs, args), arg);
+ return Qnil;
+}
+
+Lisp_Object
+safe_funcall (ptrdiff_t nargs, Lisp_Object *args)
+{
+ specpdl_ref count = SPECPDL_INDEX ();
+ /* FIXME: This function started its life in 'xdisp.c' for use internally
+ by the redisplay. So it was important to inhibit redisplay.
+ Not clear if we still need this 'specbind' now that 'xdisp.c' has its
+ own version of this code. */
+ specbind (Qinhibit_redisplay, Qt);
+ /* Use Qt to ensure debugger does not run. */
+ Lisp_Object val = internal_condition_case_n (Ffuncall, nargs, args, Qt,
+ safe_eval_handler);
+ return unbind_to (count, val);
+}
+
+Lisp_Object
+safe_eval (Lisp_Object sexp)
+{
+ return safe_calln (Qeval, sexp, Qt);
+}
+
/* Apply a C subroutine SUBR to the NUMARGS evaluated arguments in ARG_VECTOR
and return the result of evaluation. */
@@ -3025,21 +3068,21 @@ funcall_subr (struct Lisp_Subr *subr, ptrdiff_t numargs, Lisp_Object *args)
if (numargs >= subr->min_args)
{
/* Conforming call to finite-arity subr. */
- if (numargs <= subr->max_args
- && subr->max_args <= 8)
+ ptrdiff_t maxargs = subr->max_args;
+ if (numargs <= maxargs && maxargs <= 8)
{
Lisp_Object argbuf[8];
Lisp_Object *a;
- if (numargs < subr->max_args)
+ if (numargs < maxargs)
{
- eassume (subr->max_args <= ARRAYELTS (argbuf));
+ eassume (maxargs <= ARRAYELTS (argbuf));
a = argbuf;
memcpy (a, args, numargs * word_size);
- memclear (a + numargs, (subr->max_args - numargs) * word_size);
+ memclear (a + numargs, (maxargs - numargs) * word_size);
}
else
a = args;
- switch (subr->max_args)
+ switch (maxargs)
{
case 0:
return subr->function.a0 ();
@@ -3061,14 +3104,12 @@ funcall_subr (struct Lisp_Subr *subr, ptrdiff_t numargs, Lisp_Object *args)
case 8:
return subr->function.a8 (a[0], a[1], a[2], a[3], a[4], a[5],
a[6], a[7]);
- default:
- emacs_abort (); /* Can't happen. */
}
+ eassume (false); /* In case the compiler is too stupid. */
}
/* Call to n-adic subr. */
- if (subr->max_args == MANY
- || subr->max_args > 8)
+ if (maxargs == MANY || maxargs > 8)
return subr->function.aMANY (numargs, args);
}
@@ -3798,10 +3839,18 @@ get_backtrace_starting_at (Lisp_Object base)
if (!NILP (base))
{ /* Skip up to `base'. */
+ int offset = 0;
+ if (CONSP (base) && FIXNUMP (XCAR (base)))
+ {
+ offset = XFIXNUM (XCAR (base));
+ base = XCDR (base);
+ }
base = Findirect_function (base, Qt);
while (backtrace_p (pdl)
&& !EQ (base, Findirect_function (backtrace_function (pdl), Qt)))
pdl = backtrace_next (pdl);
+ while (backtrace_p (pdl) && offset-- > 0)
+ pdl = backtrace_next (pdl);
}
return pdl;
@@ -3841,13 +3890,14 @@ backtrace_frame_apply (Lisp_Object function, union specbinding *pdl)
}
}
-DEFUN ("backtrace-debug", Fbacktrace_debug, Sbacktrace_debug, 2, 2, 0,
+DEFUN ("backtrace-debug", Fbacktrace_debug, Sbacktrace_debug, 2, 3, 0,
doc: /* Set the debug-on-exit flag of eval frame LEVEL levels down to FLAG.
+LEVEL and BASE specify the activation frame to use, as in `backtrace-frame'.
The debugger is entered when that frame exits, if the flag is non-nil. */)
- (Lisp_Object level, Lisp_Object flag)
+ (Lisp_Object level, Lisp_Object flag, Lisp_Object base)
{
CHECK_FIXNUM (level);
- union specbinding *pdl = get_backtrace_frame(level, Qnil);
+ union specbinding *pdl = get_backtrace_frame (level, base);
if (backtrace_p (pdl))
set_backtrace_debug_on_exit (pdl, !NILP (flag));
@@ -4103,7 +4153,7 @@ NFRAMES and BASE specify the activation frame to use, as in `backtrace-frame'.
{
Lisp_Object sym = specpdl_symbol (tmp);
Lisp_Object val = specpdl_old_value (tmp);
- if (EQ (sym, Qinternal_interpreter_environment))
+ if (BASE_EQ (sym, Qinternal_interpreter_environment))
{
Lisp_Object env = val;
for (; CONSP (env); env = XCDR (env))
@@ -4330,11 +4380,14 @@ might not be safe to continue. */);
DEFSYM (Qdebugger, "debugger");
DEFVAR_LISP ("debugger", Vdebugger,
doc: /* Function to call to invoke debugger.
-If due to frame exit, args are `exit' and the value being returned;
+If due to frame exit, arguments are `exit' and the value being returned;
this function's value will be returned instead of that.
-If due to error, args are `error' and a list of the args to `signal'.
-If due to `apply' or `funcall' entry, one arg, `lambda'.
-If due to `eval' entry, one arg, t. */);
+If due to error, arguments are `error' and a list of arguments to `signal'.
+If due to `apply' or `funcall' entry, one argument, `lambda'.
+If due to `eval' entry, one argument, t.
+IF the desired entry point of the debugger is higher in the call stack,
+it can be specified with the keyword argument `:backtrace-base', whose
+format should be the same as the BASE argument of `backtrace-frame'. */);
Vdebugger = Qdebug_early;
DEFVAR_LISP ("signal-hook-function", Vsignal_hook_function,
diff --git a/src/fileio.c b/src/fileio.c
index 51e3e8849d1..a92da93ae48 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -1,6 +1,6 @@
/* File IO for GNU Emacs.
-Copyright (C) 1985-1988, 1993-2023 Free Software Foundation, Inc.
+Copyright (C) 1985-1988, 1993-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
@@ -203,7 +203,7 @@ check_vfs_filename (Lisp_Object encoded, const char *reason)
#ifdef HAVE_LIBSELINUX
/* Return whether SELinux is enabled and pertinent to FILE. Provide
- for cases where FILE is or is a constitutent of a special
+ for cases where FILE is or is a constituent of a special
directory, such as /assets or /content on Android. */
static bool
@@ -2518,8 +2518,8 @@ permissions. */)
ts[1] = get_stat_mtime (&st);
if (futimens (ofd, ts) != 0
/* Various versions of the Android C library are missing
- futimens, which leads a gnulib fallback to be installed
- that uses fdutimens instead. However, fdutimens is not
+ futimens, prompting Gnulib to install a fallback that
+ uses fdutimens instead. However, fdutimens is not
supported on many Android kernels, so just silently fail
if errno is ENOTSUP or ENOSYS. */
#if defined HAVE_ANDROID && !defined ANDROID_STUBIFY
@@ -4778,7 +4778,7 @@ by calling `format-decode', which see. */)
make_gap (total - GAP_SIZE + 1);
if (beg_offset != 0 || (!NILP (replace)
- && !EQ (replace, Qunbound)))
+ && !BASE_EQ (replace, Qunbound)))
{
if (emacs_fd_lseek (fd, beg_offset, SEEK_SET) < 0)
report_file_error ("Setting file position", orig_filename);
@@ -4805,7 +4805,7 @@ by calling `format-decode', which see. */)
/* 'try' is reserved in some compilers (Microsoft C). */
ptrdiff_t trytry = min (gap_size, READ_BUF_SIZE);
- if (!NILP (end))
+ if (seekable || !NILP (end))
trytry = min (trytry, total - inserted);
if (!seekable && NILP (end))
diff --git a/src/filelock.c b/src/filelock.c
index c2b306ab47d..8c27b226900 100644
--- a/src/filelock.c
+++ b/src/filelock.c
@@ -1,6 +1,6 @@
/* Lock files for editing.
-Copyright (C) 1985-1987, 1993-1994, 1996, 1998-2023 Free Software
+Copyright (C) 1985-1987, 1993-1994, 1996, 1998-2024 Free Software
Foundation, Inc.
Author: Richard King
@@ -563,7 +563,7 @@ lock_file (Lisp_Object fn)
/* See if this file is visited and has changed on disk since it was
visited. */
- Lisp_Object subject_buf = get_truename_buffer (fn);
+ Lisp_Object subject_buf = Fget_truename_buffer (fn);
if (!NILP (subject_buf)
&& NILP (Fverify_visited_file_modtime (subject_buf))
&& !NILP (Ffile_exists_p (fn))
diff --git a/src/firstfile.c b/src/firstfile.c
index 0b4881dbbe3..737757a2779 100644
--- a/src/firstfile.c
+++ b/src/firstfile.c
@@ -1,5 +1,5 @@
/* Mark beginning of data space to dump as pure, for GNU Emacs.
- Copyright (C) 1997, 2001-2023 Free Software Foundation, Inc.
+ Copyright (C) 1997, 2001-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/floatfns.c b/src/floatfns.c
index e40364f8188..4492815c765 100644
--- a/src/floatfns.c
+++ b/src/floatfns.c
@@ -1,6 +1,6 @@
/* Primitive operations on floating point for GNU Emacs Lisp interpreter.
-Copyright (C) 1988, 1993-1994, 1999, 2001-2023 Free Software Foundation,
+Copyright (C) 1988, 1993-1994, 1999, 2001-2024 Free Software Foundation,
Inc.
Author: Wolfgang Rupprecht (according to ack.texi)
diff --git a/src/fns.c b/src/fns.c
index ae9969a5432..05b7fe85601 100644
--- a/src/fns.c
+++ b/src/fns.c
@@ -1,6 +1,6 @@
/* Random utility Lisp functions.
-Copyright (C) 1985-2023 Free Software Foundation, Inc.
+Copyright (C) 1985-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
@@ -141,6 +141,10 @@ efficient. */)
if (STRINGP (sequence))
val = SCHARS (sequence);
+ else if (CONSP (sequence))
+ val = list_length (sequence);
+ else if (NILP (sequence))
+ val = 0;
else if (VECTORP (sequence))
val = ASIZE (sequence);
else if (CHAR_TABLE_P (sequence))
@@ -149,10 +153,6 @@ efficient. */)
val = bool_vector_size (sequence);
else if (COMPILEDP (sequence) || RECORDP (sequence))
val = PVSIZE (sequence);
- else if (CONSP (sequence))
- val = list_length (sequence);
- else if (NILP (sequence))
- val = 0;
else
wrong_type_argument (Qsequencep, sequence);
@@ -2104,7 +2104,27 @@ changing the value of a sequence `foo'. See also `remove', which
does not modify the argument. */)
(Lisp_Object elt, Lisp_Object seq)
{
- if (VECTORP (seq))
+ if (NILP (seq))
+ ;
+ else if (CONSP (seq))
+ {
+ Lisp_Object prev = Qnil, tail = seq;
+
+ FOR_EACH_TAIL (tail)
+ {
+ if (!NILP (Fequal (elt, XCAR (tail))))
+ {
+ if (NILP (prev))
+ seq = XCDR (tail);
+ else
+ Fsetcdr (prev, XCDR (tail));
+ }
+ else
+ prev = tail;
+ }
+ CHECK_LIST_END (tail, seq);
+ }
+ else if (VECTORP (seq))
{
ptrdiff_t n = 0;
ptrdiff_t size = ASIZE (seq);
@@ -2193,23 +2213,7 @@ does not modify the argument. */)
}
}
else
- {
- Lisp_Object prev = Qnil, tail = seq;
-
- FOR_EACH_TAIL (tail)
- {
- if (!NILP (Fequal (elt, XCAR (tail))))
- {
- if (NILP (prev))
- seq = XCDR (tail);
- else
- Fsetcdr (prev, XCDR (tail));
- }
- else
- prev = tail;
- }
- CHECK_LIST_END (tail, seq);
- }
+ wrong_type_argument (Qsequencep, seq);
return seq;
}
@@ -2222,8 +2226,6 @@ This function may destructively modify SEQ to produce the value. */)
{
if (NILP (seq))
return seq;
- else if (STRINGP (seq))
- return Freverse (seq);
else if (CONSP (seq))
{
Lisp_Object prev, tail, next;
@@ -2263,6 +2265,8 @@ This function may destructively modify SEQ to produce the value. */)
bool_vector_set (seq, size - i - 1, tem);
}
}
+ else if (STRINGP (seq))
+ return Freverse (seq);
else
wrong_type_argument (Qarrayp, seq);
return seq;
@@ -2334,9 +2338,9 @@ See also the function `nreverse', which is used more often. */)
/* Stably sort LIST ordered by PREDICATE using the TIMSORT
- algorithm. This converts the list to a vector, sorts the vector,
- and returns the result converted back to a list. The input list is
- destructively reused to hold the sorted result. */
+ algorithm. This converts the list to a vector, sorts the vector,
+ and returns the result converted back to a list. The input list
+ is destructively reused to hold the sorted result. */
static Lisp_Object
sort_list (Lisp_Object list, Lisp_Object predicate)
@@ -2774,10 +2778,13 @@ internal_equal (Lisp_Object o1, Lisp_Object o2, enum equal_kind equal_kind,
/* A symbol with position compares the contained symbol, and is
`equal' to the corresponding ordinary symbol. */
- if (SYMBOL_WITH_POS_P (o1))
- o1 = SYMBOL_WITH_POS_SYM (o1);
- if (SYMBOL_WITH_POS_P (o2))
- o2 = SYMBOL_WITH_POS_SYM (o2);
+ if (symbols_with_pos_enabled)
+ {
+ if (SYMBOL_WITH_POS_P (o1))
+ o1 = SYMBOL_WITH_POS_SYM (o1);
+ if (SYMBOL_WITH_POS_P (o2))
+ o2 = SYMBOL_WITH_POS_SYM (o2);
+ }
if (BASE_EQ (o1, o2))
return true;
@@ -2825,8 +2832,8 @@ internal_equal (Lisp_Object o1, Lisp_Object o2, enum equal_kind equal_kind,
if (ASIZE (o2) != size)
return false;
- /* Compare bignums, overlays, markers, and boolvectors
- specially, by comparing their values. */
+ /* Compare bignums, overlays, markers, boolvectors, and
+ symbols with position specially, by comparing their values. */
if (BIGNUMP (o1))
return mpz_cmp (*xbignum_val (o1), *xbignum_val (o2)) == 0;
if (OVERLAYP (o1))
@@ -2858,6 +2865,11 @@ internal_equal (Lisp_Object o1, Lisp_Object o2, enum equal_kind equal_kind,
if (TS_NODEP (o1))
return treesit_node_eq (o1, o2);
#endif
+ if (SYMBOL_WITH_POS_P(o1)) /* symbols_with_pos_enabled is false. */
+ return (BASE_EQ (XSYMBOL_WITH_POS (o1)->sym,
+ XSYMBOL_WITH_POS (o2)->sym)
+ && BASE_EQ (XSYMBOL_WITH_POS (o1)->pos,
+ XSYMBOL_WITH_POS (o2)->pos));
/* Aside from them, only true vectors, char-tables, compiled
functions, and fonts (font-spec, font-entity, font-object)
@@ -3227,7 +3239,7 @@ by a mouse, or by some window-system gesture, or via a menu. */)
&& (CONSP (last_nonmenu_event)
|| (NILP (last_nonmenu_event) && CONSP (last_input_event))
|| (val = find_symbol_value (Qfrom__tty_menu_p),
- (!NILP (val) && !EQ (val, Qunbound))))
+ (!NILP (val) && !BASE_EQ (val, Qunbound))))
&& use_dialog_box)
{
Lisp_Object pane, menu, obj;
diff --git a/src/font.c b/src/font.c
index ff81fefcad0..0a0ac5f8030 100644
--- a/src/font.c
+++ b/src/font.c
@@ -1,6 +1,6 @@
/* font.c -- "Font" primitives.
-Copyright (C) 2006-2023 Free Software Foundation, Inc.
+Copyright (C) 2006-2024 Free Software Foundation, Inc.
Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011
National Institute of Advanced Industrial Science and Technology (AIST)
Registration Number H13PRO009
@@ -252,12 +252,20 @@ font_build_object (int vectorsize, Lisp_Object type,
{
int len;
char name[256];
- Lisp_Object font_object = font_make_object (vectorsize, entity, pixelsize);
+ char *xlfd_name;
+ Lisp_Object font_object;
+
+ font_object = font_make_object (vectorsize, entity, pixelsize);
ASET (font_object, FONT_TYPE_INDEX, type);
- len = font_unparse_xlfd (entity, pixelsize, name, sizeof name);
- if (len > 0)
- ASET (font_object, FONT_NAME_INDEX, make_string (name, len));
+ xlfd_name = font_dynamic_unparse_xlfd (entity, pixelsize);
+
+ if (xlfd_name)
+ {
+ ASET (font_object, FONT_NAME_INDEX, build_string (xlfd_name));
+ xfree (xlfd_name);
+ }
+
len = font_unparse_fcname (entity, pixelsize, name, sizeof name);
if (len > 0)
ASET (font_object, FONT_FULLNAME_INDEX, make_string (name, len));
@@ -1067,8 +1075,8 @@ font_parse_xlfd_1 (char *name, ptrdiff_t len, Lisp_Object font, int segments)
Lisp_Object val;
char *p;
- if (len > 255 || !len)
- /* Maximum XLFD name length is 255. */
+ /* Reject empty XLFDs. */
+ if (!len)
return -1;
/* Accept "*-.." as a fully specified XLFD. */
@@ -1276,6 +1284,167 @@ font_parse_xlfd (char *name, ptrdiff_t len, Lisp_Object font)
return -1;
}
+/* Return the XLFD name of FONT as a NULL terminated string, or NULL
+ if the font is invalid. If FONT is a scalable font, return
+ PIXEL_SIZE as the XLFD's pixel size in lieu of its
+ FONT_SIZE_INDEX. */
+
+char *
+font_dynamic_unparse_xlfd (Lisp_Object font, int pixel_size)
+{
+ char *p;
+ const char *f[XLFD_REGISTRY_INDEX + 1];
+ Lisp_Object val;
+ int i, j;
+ char *name;
+ USE_SAFE_ALLOCA;
+
+ eassert (FONTP (font));
+
+ for (i = FONT_FOUNDRY_INDEX, j = XLFD_FOUNDRY_INDEX; i <= FONT_REGISTRY_INDEX;
+ i++, j++)
+ {
+ if (i == FONT_ADSTYLE_INDEX)
+ j = XLFD_ADSTYLE_INDEX;
+ else if (i == FONT_REGISTRY_INDEX)
+ j = XLFD_REGISTRY_INDEX;
+ val = AREF (font, i);
+ if (NILP (val))
+ {
+ if (j == XLFD_REGISTRY_INDEX)
+ f[j] = "*-*";
+ else
+ f[j] = "*";
+ }
+ else
+ {
+ if (SYMBOLP (val))
+ val = SYMBOL_NAME (val);
+ if (j == XLFD_REGISTRY_INDEX
+ && ! strchr (SSDATA (val), '-'))
+ {
+ ptrdiff_t alloc = SBYTES (val) + 4;
+
+ /* Change "jisx0208*" and "jisx0208" to "jisx0208*-*". */
+ f[j] = p = SAFE_ALLOCA (alloc);
+ sprintf (p, "%s%s-*", SDATA (val),
+ &"*"[SDATA (val)[SBYTES (val) - 1] == '*']);
+ }
+ else
+ f[j] = SSDATA (val);
+ }
+ }
+
+ for (i = FONT_WEIGHT_INDEX, j = XLFD_WEIGHT_INDEX; i <= FONT_WIDTH_INDEX;
+ i++, j++)
+ {
+ val = font_style_symbolic (font, i, 0);
+ if (NILP (val))
+ f[j] = "*";
+ else
+ {
+ int c, k, l;
+ ptrdiff_t alloc;
+
+ val = SYMBOL_NAME (val);
+ alloc = SBYTES (val) + 1;
+ f[j] = p = SAFE_ALLOCA (alloc);
+ /* Copy the name while excluding '-', '?', ',', and '"'. */
+ for (k = l = 0; k < alloc; k++)
+ {
+ c = SREF (val, k);
+ if (c != '-' && c != '?' && c != ',' && c != '"')
+ p[l++] = c;
+ }
+ }
+ }
+
+ val = AREF (font, FONT_SIZE_INDEX);
+ eassert (NUMBERP (val) || NILP (val));
+ char font_size_index_buf[sizeof "-*"
+ + max (INT_STRLEN_BOUND (EMACS_INT),
+ 1 + DBL_MAX_10_EXP + 1)];
+ if (INTEGERP (val))
+ {
+ intmax_t v;
+ if (! (integer_to_intmax (val, &v) && 0 < v))
+ v = pixel_size;
+ if (v > 0)
+ {
+ f[XLFD_PIXEL_INDEX] = p = font_size_index_buf;
+ sprintf (p, "%"PRIdMAX"-*", v);
+ }
+ else
+ f[XLFD_PIXEL_INDEX] = "*-*";
+ }
+ else if (FLOATP (val))
+ {
+ double v = XFLOAT_DATA (val) * 10;
+ f[XLFD_PIXEL_INDEX] = p = font_size_index_buf;
+ sprintf (p, "*-%.0f", v);
+ }
+ else
+ f[XLFD_PIXEL_INDEX] = "*-*";
+
+ char dpi_index_buf[sizeof "-" + 2 * INT_STRLEN_BOUND (EMACS_INT)];
+ if (FIXNUMP (AREF (font, FONT_DPI_INDEX)))
+ {
+ EMACS_INT v = XFIXNUM (AREF (font, FONT_DPI_INDEX));
+ f[XLFD_RESX_INDEX] = p = dpi_index_buf;
+ sprintf (p, "%"pI"d-%"pI"d", v, v);
+ }
+ else
+ f[XLFD_RESX_INDEX] = "*-*";
+
+ if (FIXNUMP (AREF (font, FONT_SPACING_INDEX)))
+ {
+ EMACS_INT spacing = XFIXNUM (AREF (font, FONT_SPACING_INDEX));
+
+ f[XLFD_SPACING_INDEX] = (spacing <= FONT_SPACING_PROPORTIONAL ? "p"
+ : spacing <= FONT_SPACING_DUAL ? "d"
+ : spacing <= FONT_SPACING_MONO ? "m"
+ : "c");
+ }
+ else
+ f[XLFD_SPACING_INDEX] = "*";
+
+ char avgwidth_index_buf[INT_BUFSIZE_BOUND (EMACS_INT)];
+ if (FIXNUMP (AREF (font, FONT_AVGWIDTH_INDEX)))
+ {
+ f[XLFD_AVGWIDTH_INDEX] = p = avgwidth_index_buf;
+ sprintf (p, "%"pI"d", XFIXNUM (AREF (font, FONT_AVGWIDTH_INDEX)));
+ }
+ else
+ f[XLFD_AVGWIDTH_INDEX] = "*";
+
+ /* Allocate a buffer large enough to accommodate the entire
+ XLFD. */
+
+ name = xmalloc (strlen (f[XLFD_FOUNDRY_INDEX])
+ + strlen (f[XLFD_FAMILY_INDEX])
+ + strlen (f[XLFD_WEIGHT_INDEX])
+ + strlen (f[XLFD_SLANT_INDEX])
+ + strlen (f[XLFD_SWIDTH_INDEX])
+ + strlen (f[XLFD_ADSTYLE_INDEX])
+ + strlen (f[XLFD_PIXEL_INDEX])
+ + strlen (f[XLFD_RESX_INDEX])
+ + strlen (f[XLFD_SPACING_INDEX])
+ + strlen (f[XLFD_AVGWIDTH_INDEX])
+ + strlen (f[XLFD_REGISTRY_INDEX])
+ + sizeof "-----------");
+
+ /* Return the XLFD. */
+
+ sprintf (name, "-%s-%s-%s-%s-%s-%s-%s-%s-%s-%s-%s",
+ f[XLFD_FOUNDRY_INDEX], f[XLFD_FAMILY_INDEX],
+ f[XLFD_WEIGHT_INDEX], f[XLFD_SLANT_INDEX],
+ f[XLFD_SWIDTH_INDEX], f[XLFD_ADSTYLE_INDEX],
+ f[XLFD_PIXEL_INDEX], f[XLFD_RESX_INDEX],
+ f[XLFD_SPACING_INDEX], f[XLFD_AVGWIDTH_INDEX],
+ f[XLFD_REGISTRY_INDEX]);
+ SAFE_FREE ();
+ return name;
+}
/* Store XLFD name of FONT (font-spec or font-entity) in NAME (NBYTES
length), and return the name length. If FONT_SIZE_INDEX of FONT is
@@ -1878,7 +2047,7 @@ font_rescale_ratio (Lisp_Object font_entity)
if (STRINGP (XCAR (elt)))
{
if (NILP (name))
- name = Ffont_xlfd_name (font_entity, Qnil);
+ name = Ffont_xlfd_name (font_entity, Qnil, Qt);
/* N.B. that `name' is set to nil if the resulting XLFD
is too long. */
@@ -2490,12 +2659,30 @@ font_delete_unmatched (Lisp_Object vec, Lisp_Object spec, int size)
entity = AREF (vec, i);
if (! NILP (Vface_ignored_fonts))
{
- char name[256];
+ char name[256], *xlfd;
ptrdiff_t namelen;
namelen = font_unparse_xlfd (entity, 0, name, 256);
+
if (namelen >= 0)
- if (font_is_ignored (name, namelen))
+ {
+ if (font_is_ignored (name, namelen))
continue;
+ }
+ else
+ {
+ /* The font family or foundry is too long for a 256
+ character xlfd to accommodate. */
+
+ xlfd = font_dynamic_unparse_xlfd (entity, 0);
+
+ if (xlfd && font_is_ignored (xlfd, sizeof (xlfd)))
+ {
+ xfree (xlfd);
+ continue;
+ }
+
+ xfree (xlfd);
+ }
}
if (NILP (spec))
{
@@ -4239,16 +4426,20 @@ Optional 2nd argument FRAME, if non-nil, specifies the target frame. */)
return val;
}
-DEFUN ("font-xlfd-name", Ffont_xlfd_name, Sfont_xlfd_name, 1, 2, 0,
+DEFUN ("font-xlfd-name", Ffont_xlfd_name, Sfont_xlfd_name, 1, 3, 0,
doc: /* Return XLFD name of FONT.
FONT is a font-spec, font-entity, or font-object.
-If the name is too long for XLFD (maximum 255 chars), return nil.
+
+If the name is too long to be represented as an XLFD (maximum 255
+chars) and LONG_XLFDS is nil, return nil.
+
If the 2nd optional arg FOLD-WILDCARDS is non-nil,
the consecutive wildcards are folded into one. */)
- (Lisp_Object font, Lisp_Object fold_wildcards)
+ (Lisp_Object font, Lisp_Object fold_wildcards, Lisp_Object long_xlfds)
{
- char name[256];
+ char name_buffer[256], *name;
int namelen, pixel_size = 0;
+ Lisp_Object string;
CHECK_FONT (font);
@@ -4261,15 +4452,32 @@ the consecutive wildcards are folded into one. */)
{
if (NILP (fold_wildcards))
return font_name;
+ name = name_buffer;
lispstpcpy (name, font_name);
namelen = SBYTES (font_name);
goto done;
}
pixel_size = XFONT_OBJECT (font)->pixel_size;
}
- namelen = font_unparse_xlfd (font, pixel_size, name, 256);
- if (namelen < 0)
- return Qnil;
+
+ if (NILP (long_xlfds))
+ {
+ name = name_buffer;
+ namelen = font_unparse_xlfd (font, pixel_size, name, 256);
+ if (namelen < 0)
+ return Qnil;
+ }
+ else
+ {
+ /* Dynamically allocate the XLFD. */
+ name = font_dynamic_unparse_xlfd (font, pixel_size);
+
+ if (!name)
+ return Qnil;
+
+ namelen = strlen (name);
+ }
+
done:
if (! NILP (fold_wildcards))
{
@@ -4283,7 +4491,14 @@ the consecutive wildcards are folded into one. */)
}
}
- return make_string (name, namelen);
+ /* If NAME is dynamically allocated, free it. */
+
+ string = make_string (name, namelen);
+
+ if (name != name_buffer)
+ xfree (name);
+
+ return string;
}
void
@@ -5487,7 +5702,7 @@ font_add_log (const char *action, Lisp_Object arg, Lisp_Object result)
Lisp_Object tail, elt;
AUTO_STRING (equal, "=");
- val = Ffont_xlfd_name (arg, Qt);
+ val = Ffont_xlfd_name (arg, Qt, Qt);
for (tail = AREF (arg, FONT_EXTRA_INDEX); CONSP (tail);
tail = XCDR (tail))
{
@@ -5515,7 +5730,7 @@ font_add_log (const char *action, Lisp_Object arg, Lisp_Object result)
result = font_vconcat_entity_vectors (result);
if (FONTP (result))
{
- val = Ffont_xlfd_name (result, Qt);
+ val = Ffont_xlfd_name (result, Qt, Qt);
if (! FONT_SPEC_P (result))
{
AUTO_STRING (colon, ":");
@@ -5532,7 +5747,7 @@ font_add_log (const char *action, Lisp_Object arg, Lisp_Object result)
{
val = XCAR (tail);
if (FONTP (val))
- val = Ffont_xlfd_name (val, Qt);
+ val = Ffont_xlfd_name (val, Qt, Qt);
XSETCAR (tail, val);
}
}
@@ -5543,7 +5758,7 @@ font_add_log (const char *action, Lisp_Object arg, Lisp_Object result)
{
val = AREF (result, i);
if (FONTP (val))
- val = Ffont_xlfd_name (val, Qt);
+ val = Ffont_xlfd_name (val, Qt, Qt);
ASET (result, i, val);
}
}
diff --git a/src/font.h b/src/font.h
index ed3b17db994..ad92f9f4739 100644
--- a/src/font.h
+++ b/src/font.h
@@ -1,5 +1,5 @@
/* font.h -- Interface definition for font handling.
- Copyright (C) 2006-2023 Free Software Foundation, Inc.
+ Copyright (C) 2006-2024 Free Software Foundation, Inc.
Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011
National Institute of Advanced Industrial Science and Technology (AIST)
Registration Number H13PRO009
@@ -303,10 +303,16 @@ struct font
SPACE glyph, the value is 0. */
int space_width;
- /* Average width of glyphs in the font. If the font itself doesn't
- have that information, but has glyphs of ASCII characters, the
- value is the average width of those glyphs. Otherwise, the value
- is 0. */
+ /* Average width of glyphs in the font. Should be the average width
+ of the glyphs of ASCII characters. The value for the default
+ face's font is used to determine the canonical character width of
+ the frame (see FRAME_COLUMN_WIDTH). For fonts that are not
+ fixed-pitch, the font backend should actually calculate the value
+ from the glyphs of ASCII characters in the range 32..126
+ inclusively; relying on the average-width attribute recorded in
+ the font is unreliable in this case, especially in fonts that
+ support CJK scripts, where many characters are wide. Value can
+ be zero if the font doesn't have glyphs for ASCII characters. */
int average_width;
/* Ascent and descent of the font (in pixels). */
@@ -885,8 +891,8 @@ extern void font_parse_family_registry (Lisp_Object family,
Lisp_Object spec);
extern int font_parse_xlfd (char *name, ptrdiff_t len, Lisp_Object font);
-extern ptrdiff_t font_unparse_xlfd (Lisp_Object font, int pixel_size,
- char *name, int bytes);
+extern char *font_dynamic_unparse_xlfd (Lisp_Object, int);
+extern ptrdiff_t font_unparse_xlfd (Lisp_Object, int, char *, int);
extern void register_font_driver (struct font_driver const *, struct frame *);
extern void free_font_driver_list (struct frame *f);
#ifdef ENABLE_CHECKING
diff --git a/src/fontset.c b/src/fontset.c
index 139dcb6eb89..005d0a98d2a 100644
--- a/src/fontset.c
+++ b/src/fontset.c
@@ -1,6 +1,6 @@
/* Fontset handler.
-Copyright (C) 2001-2023 Free Software Foundation, Inc.
+Copyright (C) 2001-2024 Free Software Foundation, Inc.
Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
2005, 2006, 2007, 2008, 2009, 2010, 2011
National Institute of Advanced Industrial Science and Technology (AIST)
@@ -1546,7 +1546,7 @@ overwrites the previous settings. */)
font_parse_family_registry (XCAR (font_spec), XCDR (font_spec), spec);
font_spec = spec;
- fontname = Ffont_xlfd_name (font_spec, Qnil);
+ fontname = Ffont_xlfd_name (font_spec, Qnil, Qt);
}
else if (STRINGP (font_spec))
{
@@ -1554,7 +1554,7 @@ overwrites the previous settings. */)
font_spec = CALLN (Ffont_spec, QCname, fontname);
}
else if (FONT_SPEC_P (font_spec))
- fontname = Ffont_xlfd_name (font_spec, Qnil);
+ fontname = Ffont_xlfd_name (font_spec, Qnil, Qt);
else if (! NILP (font_spec))
Fsignal (Qfont, list2 (build_string ("Invalid font-spec"), font_spec));
@@ -1740,6 +1740,7 @@ FONT-SPEC is a vector, a cons, or a string. See the documentation of
{
Lisp_Object fontset, tail;
int id;
+ char *string;
CHECK_STRING (name);
@@ -1749,8 +1750,6 @@ FONT-SPEC is a vector, a cons, or a string. See the documentation of
{
Lisp_Object font_spec = Ffont_spec (0, NULL);
Lisp_Object short_name;
- char xlfd[256];
- int len;
if (font_parse_xlfd (SSDATA (name), SBYTES (name), font_spec) < 0)
error ("Fontset name must be in XLFD format");
@@ -1762,10 +1761,11 @@ FONT-SPEC is a vector, a cons, or a string. See the documentation of
Vfontset_alias_alist);
ASET (font_spec, FONT_REGISTRY_INDEX, Qiso8859_1);
fontset = make_fontset (Qnil, name, Qnil);
- len = font_unparse_xlfd (font_spec, 0, xlfd, 256);
- if (len < 0)
+ string = font_dynamic_unparse_xlfd (font_spec, 0);
+ if (!string)
error ("Invalid fontset name (perhaps too long): %s", SDATA (name));
- set_fontset_ascii (fontset, make_unibyte_string (xlfd, len));
+ set_fontset_ascii (fontset, build_unibyte_string (string));
+ xfree (string);
}
else
{
@@ -1816,7 +1816,7 @@ fontset_from_font (Lisp_Object font_object)
Lisp_Object font_spec = copy_font_spec (font_object);
Lisp_Object registry = AREF (font_spec, FONT_REGISTRY_INDEX);
Lisp_Object fontset_spec, alias, name, fontset;
- Lisp_Object val;
+ Lisp_Object val, xlfd;
val = assoc_no_quit (font_spec, auto_fontset_alist);
if (CONSP (val))
@@ -1832,14 +1832,19 @@ fontset_from_font (Lisp_Object font_object)
}
fontset_spec = copy_font_spec (font_spec);
ASET (fontset_spec, FONT_REGISTRY_INDEX, alias);
- name = Ffont_xlfd_name (fontset_spec, Qnil);
+ name = Ffont_xlfd_name (fontset_spec, Qnil, Qt);
eassert (!NILP (name));
fontset = make_fontset (Qnil, name, Qnil);
Vfontset_alias_alist = Fcons (Fcons (name, SYMBOL_NAME (alias)),
Vfontset_alias_alist);
- alias = Fdowncase (AREF (font_object, FONT_NAME_INDEX));
- Vfontset_alias_alist = Fcons (Fcons (name, alias), Vfontset_alias_alist);
- auto_fontset_alist = Fcons (Fcons (font_spec, fontset), auto_fontset_alist);
+
+ xlfd = AREF (font_object, FONT_NAME_INDEX);
+ alias = Fdowncase (xlfd);
+ Vfontset_alias_alist
+ = Fcons (Fcons (name, alias), Vfontset_alias_alist);
+ auto_fontset_alist
+ = Fcons (Fcons (font_spec, fontset), auto_fontset_alist);
+
font_spec = Ffont_spec (0, NULL);
ASET (font_spec, FONT_REGISTRY_INDEX, registry);
{
@@ -2006,7 +2011,7 @@ format is the same as above. */)
for (; CONSP (alist); alist = XCDR (alist))
{
elt = XCAR (alist);
- XSETCAR (elt, Ffont_xlfd_name (XCAR (elt), Qnil));
+ XSETCAR (elt, Ffont_xlfd_name (XCAR (elt), Qnil, Qt));
}
}
c = to + 1;
diff --git a/src/fontset.h b/src/fontset.h
index de19138947d..62e5655ab1a 100644
--- a/src/fontset.h
+++ b/src/fontset.h
@@ -1,5 +1,5 @@
/* Header for fontset handler.
- Copyright (C) 1998, 2001-2023 Free Software Foundation, Inc.
+ Copyright (C) 1998, 2001-2024 Free Software Foundation, Inc.
Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
2005, 2006, 2007, 2008, 2009, 2010, 2011
National Institute of Advanced Industrial Science and Technology (AIST)
diff --git a/src/frame.c b/src/frame.c
index 4be9f06bd3c..f5b07e212f2 100644
--- a/src/frame.c
+++ b/src/frame.c
@@ -1,6 +1,6 @@
/* Generic frame functions.
-Copyright (C) 1993-1995, 1997, 1999-2023 Free Software Foundation, Inc.
+Copyright (C) 1993-1995, 1997, 1999-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
@@ -2149,7 +2149,7 @@ delete_frame (Lisp_Object frame, Lisp_Object force)
x_clipboard_manager_save_frame (frame);
#endif
- safe_call2 (Qrun_hook_with_args, Qdelete_frame_functions, frame);
+ safe_calln (Qrun_hook_with_args, Qdelete_frame_functions, frame);
}
/* delete_frame_functions may have deleted any frame, including this
@@ -2212,12 +2212,15 @@ delete_frame (Lisp_Object frame, Lisp_Object force)
}
#ifdef NS_IMPL_COCOA
else
- /* Under NS, there is no system mechanism for choosing a new
- window to get focus -- it is left to application code.
- So the portion of THIS application interfacing with NS
- needs to know about it. We call Fraise_frame, but the
- purpose is really to transfer focus. */
- Fraise_frame (frame1);
+ {
+ /* Under NS, there is no system mechanism for choosing a new
+ window to get focus -- it is left to application code.
+ So the portion of THIS application interfacing with NS
+ needs to make the frame we switch to the key window. */
+ struct frame *f1 = XFRAME (frame1);
+ if (FRAME_NS_P (f1))
+ ns_make_frame_key_window (f1);
+ }
#endif
do_switch_frame (frame1, 0, 1, Qnil);
@@ -2458,7 +2461,7 @@ delete_frame (Lisp_Object frame, Lisp_Object force)
= Fcons (list3 (Qrun_hook_with_args, Qafter_delete_frame_functions, frame),
pending_funcalls);
else
- safe_call2 (Qrun_hook_with_args, Qafter_delete_frame_functions, frame);
+ safe_calln (Qrun_hook_with_args, Qafter_delete_frame_functions, frame);
if (!NILP (minibuffer_child_frame))
/* If minibuffer_child_frame is non-nil, it was FRAME's minibuffer
diff --git a/src/frame.h b/src/frame.h
index c85df378da6..d574fe93a57 100644
--- a/src/frame.h
+++ b/src/frame.h
@@ -1,5 +1,5 @@
/* Define frame-object for GNU Emacs.
- Copyright (C) 1993-1994, 1999-2023 Free Software Foundation, Inc.
+ Copyright (C) 1993-1994, 1999-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
@@ -90,6 +90,7 @@ enum text_conversion_operation
TEXTCONV_DELETE_SURROUNDING_TEXT,
TEXTCONV_REQUEST_POINT_UPDATE,
TEXTCONV_BARRIER,
+ TEXTCONV_REPLACE_TEXT,
};
/* Structure describing a single edit being performed by the input
@@ -1521,6 +1522,10 @@ extern Lisp_Object mouse_position (bool);
extern void frame_size_history_plain (struct frame *, Lisp_Object);
extern void frame_size_history_extra (struct frame *, Lisp_Object,
int, int, int, int, int, int);
+#ifdef NS_IMPL_COCOA
+/* Implemented in nsfns.m. */
+extern void ns_make_frame_key_window (struct frame *);
+#endif
extern Lisp_Object Vframe_list;
/* Value is a pointer to the selected frame. If the selected frame
diff --git a/src/fringe.c b/src/fringe.c
index 3452c8503f0..0642de5f772 100644
--- a/src/fringe.c
+++ b/src/fringe.c
@@ -1,5 +1,5 @@
/* Fringe handling (split from xdisp.c).
- Copyright (C) 1985-1988, 1993-1995, 1997-2023 Free Software
+ Copyright (C) 1985-1988, 1993-1995, 1997-2024 Free Software
Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/ftcrfont.c b/src/ftcrfont.c
index 49564692b75..5ee375c782b 100644
--- a/src/ftcrfont.c
+++ b/src/ftcrfont.c
@@ -1,5 +1,5 @@
/* ftcrfont.c -- FreeType font driver on cairo.
- Copyright (C) 2015-2023 Free Software Foundation, Inc.
+ Copyright (C) 2015-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/ftfont.c b/src/ftfont.c
index d3c836c0f2d..0d10de5408f 100644
--- a/src/ftfont.c
+++ b/src/ftfont.c
@@ -1,5 +1,5 @@
/* ftfont.c -- FreeType font driver.
- Copyright (C) 2006-2023 Free Software Foundation, Inc.
+ Copyright (C) 2006-2024 Free Software Foundation, Inc.
Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011
National Institute of Advanced Industrial Science and Technology (AIST)
Registration Number H13PRO009
@@ -1572,6 +1572,12 @@ ftfont_glyph_metrics (FT_Face ft_face, int c, int *advance, int *lbearing,
if (FT_Load_Glyph (ft_face, c, FT_LOAD_DEFAULT) == 0)
{
FT_Glyph_Metrics *m = &ft_face->glyph->metrics;
+
+ /* At first glance this might appear to truncate the glyph's
+ horizontal advance, but FreeType internally rounds the
+ advance width to a pixel boundary prior to returning these
+ metrics. */
+
*advance = m->horiAdvance >> 6;
*lbearing = m->horiBearingX >> 6;
*rbearing = (m->horiBearingX + m->width) >> 6;
diff --git a/src/getpagesize.h b/src/getpagesize.h
index 692c9066fb1..d1fb9315f3a 100644
--- a/src/getpagesize.h
+++ b/src/getpagesize.h
@@ -1,5 +1,5 @@
/* Emulate getpagesize on systems that lack it.
- Copyright (C) 1986, 1992, 1995, 2001-2023 Free Software Foundation,
+ Copyright (C) 1986, 1992, 1995, 2001-2024 Free Software Foundation,
Inc.
This file is part of GNU Emacs.
diff --git a/src/gfilenotify.c b/src/gfilenotify.c
index de09ffe5fd3..8733db11997 100644
--- a/src/gfilenotify.c
+++ b/src/gfilenotify.c
@@ -1,5 +1,5 @@
/* Filesystem notifications support with glib API.
- Copyright (C) 2013-2023 Free Software Foundation, Inc.
+ Copyright (C) 2013-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
@@ -88,7 +88,9 @@ dir_monitor_callback (GFileMonitor *monitor,
&& !NILP (Fmember (symbol, list5 (Qchanged, Qchanges_done_hint,
Qdeleted, Qcreated, Qmoved))))
|| (!NILP (Fmember (Qattribute_change, flags))
- && EQ (symbol, Qattribute_changed)))
+ && EQ (symbol, Qattribute_changed))
+ || (!NILP (Fmember (Qwatch_mounts, flags))
+ && EQ (symbol, Qunmounted)))
{
/* Construct an event. */
EVENT_INIT (event);
@@ -105,8 +107,8 @@ dir_monitor_callback (GFileMonitor *monitor,
/* XD_DEBUG_MESSAGE ("%s", XD_OBJECT_TO_STRING (event.arg)); */
}
- /* Cancel monitor if file or directory is deleted. */
- if (!NILP (Fmember (symbol, list2 (Qdeleted, Qmoved)))
+ /* Cancel monitor if file or directory is deleted or unmounted. */
+ if (!NILP (Fmember (symbol, list3 (Qdeleted, Qmoved, Qunmounted)))
&& strcmp (name, SSDATA (XCAR (XCDR (watch_object)))) == 0
&& !g_file_monitor_is_cancelled (monitor))
g_file_monitor_cancel (monitor);
diff --git a/src/gmalloc.c b/src/gmalloc.c
index e655d69f660..2b29f5c6c81 100644
--- a/src/gmalloc.c
+++ b/src/gmalloc.c
@@ -1,5 +1,5 @@
/* Declarations for `malloc' and friends.
- Copyright (C) 1990-1993, 1995-1996, 1999, 2002-2007, 2013-2023 Free
+ Copyright (C) 1990-1993, 1995-1996, 1999, 2002-2007, 2013-2024 Free
Software Foundation, Inc.
Written May 1989 by Mike Haertel.
diff --git a/src/gnutls.c b/src/gnutls.c
index e3f1093d977..54b7eb4c90e 100644
--- a/src/gnutls.c
+++ b/src/gnutls.c
@@ -1,5 +1,5 @@
/* GnuTLS glue for GNU Emacs.
- Copyright (C) 2010-2023 Free Software Foundation, Inc.
+ Copyright (C) 2010-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/gnutls.h b/src/gnutls.h
index 16bfebadee5..18e06027c37 100644
--- a/src/gnutls.h
+++ b/src/gnutls.h
@@ -1,5 +1,5 @@
/* GnuTLS glue for GNU Emacs.
- Copyright (C) 2010-2023 Free Software Foundation, Inc.
+ Copyright (C) 2010-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/gtkutil.c b/src/gtkutil.c
index 22b2a70f279..6cfb4034ed9 100644
--- a/src/gtkutil.c
+++ b/src/gtkutil.c
@@ -1,6 +1,6 @@
/* Functions for creating and updating GTK widgets.
-Copyright (C) 2003-2023 Free Software Foundation, Inc.
+Copyright (C) 2003-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
@@ -4141,7 +4141,7 @@ xg_update_frame_menubar (struct frame *f)
g_signal_connect (x->menubar_widget, "map", G_CALLBACK (menubar_map_cb), f);
gtk_widget_show_all (x->menubar_widget);
gtk_widget_get_preferred_size (x->menubar_widget, NULL, &req);
- req.height *= xg_get_scale (f);
+ req.height *= scale;
#if !defined HAVE_PGTK && defined HAVE_GTK3
if (FRAME_DISPLAY_INFO (f)->n_planes == 32)
@@ -4154,9 +4154,9 @@ xg_update_frame_menubar (struct frame *f)
}
#endif
- if (FRAME_MENUBAR_HEIGHT (f) != (req.height * scale))
+ if (FRAME_MENUBAR_HEIGHT (f) != req.height)
{
- FRAME_MENUBAR_HEIGHT (f) = req.height * scale;
+ FRAME_MENUBAR_HEIGHT (f) = req.height;
adjust_frame_size (f, -1, -1, 2, 0, Qmenu_bar_lines);
}
unblock_input ();
diff --git a/src/gtkutil.h b/src/gtkutil.h
index acd6a3bfc8e..b689053b4b8 100644
--- a/src/gtkutil.h
+++ b/src/gtkutil.h
@@ -1,6 +1,6 @@
/* Definitions and headers for GTK widgets.
-Copyright (C) 2003-2023 Free Software Foundation, Inc.
+Copyright (C) 2003-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/haiku.c b/src/haiku.c
index 55c2cf04729..002dfe0c4f5 100644
--- a/src/haiku.c
+++ b/src/haiku.c
@@ -1,5 +1,5 @@
/* Haiku subroutines that are general to the Haiku operating system.
- Copyright (C) 2021-2023 Free Software Foundation, Inc.
+ Copyright (C) 2021-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/haiku_draw_support.cc b/src/haiku_draw_support.cc
index b779b773dd5..1671eba96d0 100644
--- a/src/haiku_draw_support.cc
+++ b/src/haiku_draw_support.cc
@@ -1,5 +1,5 @@
/* Haiku window system support. Hey, Emacs, this is -*- C++ -*-
- Copyright (C) 2021-2023 Free Software Foundation, Inc.
+ Copyright (C) 2021-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/haiku_font_support.cc b/src/haiku_font_support.cc
index 1403c06a614..416a7d90c29 100644
--- a/src/haiku_font_support.cc
+++ b/src/haiku_font_support.cc
@@ -1,5 +1,5 @@
/* Haiku window system support. Hey, Emacs, this is -*- C++ -*-
- Copyright (C) 2021-2023 Free Software Foundation, Inc.
+ Copyright (C) 2021-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/haiku_io.c b/src/haiku_io.c
index c6d7108bf49..f0862965bd8 100644
--- a/src/haiku_io.c
+++ b/src/haiku_io.c
@@ -1,5 +1,5 @@
/* Haiku window system support.
- Copyright (C) 2021-2023 Free Software Foundation, Inc.
+ Copyright (C) 2021-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/haiku_select.cc b/src/haiku_select.cc
index 76e2d829204..02f3272514f 100644
--- a/src/haiku_select.cc
+++ b/src/haiku_select.cc
@@ -1,5 +1,5 @@
/* Haiku window system selection support. Hey Emacs, this is -*- C++ -*-
- Copyright (C) 2021-2023 Free Software Foundation, Inc.
+ Copyright (C) 2021-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/haiku_support.cc b/src/haiku_support.cc
index d5649e4d2ce..1b9c5acdf14 100644
--- a/src/haiku_support.cc
+++ b/src/haiku_support.cc
@@ -1,5 +1,5 @@
/* Haiku window system support. Hey, Emacs, this is -*- C++ -*-
- Copyright (C) 2021-2023 Free Software Foundation, Inc.
+ Copyright (C) 2021-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
@@ -741,8 +741,6 @@ public:
EmacsWindow *parent;
BRect pre_fullscreen_rect;
BRect pre_zoom_rect;
- int x_before_zoom;
- int y_before_zoom;
bool shown_flag;
volatile bool was_shown_p;
bool menu_bar_active_p;
@@ -760,8 +758,6 @@ public:
B_NORMAL_WINDOW_FEEL, B_NO_SERVER_SIDE_WINDOW_MODIFIERS),
subset_windows (NULL),
parent (NULL),
- x_before_zoom (INT_MIN),
- y_before_zoom (INT_MIN),
shown_flag (false),
was_shown_p (false),
menu_bar_active_p (false),
@@ -1063,6 +1059,8 @@ public:
msg->FindInt64 ("when", &rq.time);
rq.modifiers = 0;
+ rq.keysym = 0;
+
uint32_t mods = modifiers ();
if (mods & B_SHIFT_KEY)
@@ -1077,10 +1075,39 @@ public:
if (mods & B_OPTION_KEY)
rq.modifiers |= HAIKU_MODIFIER_SUPER;
- ret = keysym_from_raw_char (raw, key, &rq.keysym);
+ /* mods & B_SHIFT_KEY should be inverted if keycode is
+ situated in the numeric keypad and Num Lock is set, for
+ this transformation is not effected on key events
+ themselves. */
+
+ if (mods & B_NUM_LOCK)
+ {
+ switch (key)
+ {
+ case 0x37:
+ case 0x38:
+ case 0x39:
+ case 0x48:
+ case 0x49:
+ case 0x4a:
+ case 0x58:
+ case 0x59:
+ case 0x5a:
+ case 0x64:
+ case 0x65:
+ mods ^= B_SHIFT_KEY;
+
+ /* If shift is set at this juncture, map these keys to
+ the digits they represent. Because raw is not
+ affected by Num Lock, keysym_from_raw_char will map
+ this to the keysym yielded by this key in the
+ absence of any modifiers. */
+ if (mods & B_SHIFT_KEY)
+ goto map_keysym;
+ }
+ }
- if (!ret)
- rq.keysym = 0;
+ ret = keysym_from_raw_char (raw, key, &rq.keysym);
if (ret < 0)
return;
@@ -1091,6 +1118,7 @@ public:
{
if (mods & B_SHIFT_KEY)
{
+ map_keysym:
if (mods & B_CAPS_LOCK)
map_caps_shift (key, &rq.multibyte_char);
else
@@ -3315,9 +3343,7 @@ class EmacsFilePanelCallbackLooper : public BLooper
{
str_buf = (char *) alloca (std::strlen (str_path)
+ std::strlen (name) + 2);
- snprintf (str_buf, std::strlen (str_path)
- + std::strlen (name) + 2, "%s/%s",
- str_path, name);
+ sprintf (str_buf, "%s/%s", str_path, name);
file_name = strdup (str_buf);
}
}
diff --git a/src/haiku_support.h b/src/haiku_support.h
index 5c22eb3b0db..e9ac7005d75 100644
--- a/src/haiku_support.h
+++ b/src/haiku_support.h
@@ -1,5 +1,5 @@
/* Haiku window system support. Hey Emacs, this is -*- C++ -*-
- Copyright (C) 2021-2023 Free Software Foundation, Inc.
+ Copyright (C) 2021-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/haikufns.c b/src/haikufns.c
index 8028a73abd1..173c1e369df 100644
--- a/src/haikufns.c
+++ b/src/haikufns.c
@@ -1,5 +1,5 @@
/* Haiku window system support
- Copyright (C) 2021-2023 Free Software Foundation, Inc.
+ Copyright (C) 2021-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
@@ -184,6 +184,11 @@ haiku_change_tab_bar_height (struct frame *f, int height)
leading to the tab bar height being incorrectly set upon the next
call to x_set_font. (bug#59285) */
int lines = height / unit;
+
+ /* Even so, HEIGHT might be less than unit if the tab bar face is
+ not so tall as the frame's font height; which if true lines will
+ be set to 0 and the tab bar will thus vanish. */
+
if (lines == 0 && height != 0)
lines = 1;
diff --git a/src/haikufont.c b/src/haikufont.c
index b6a9cb34c4d..5d14dab3d4b 100644
--- a/src/haikufont.c
+++ b/src/haikufont.c
@@ -1,6 +1,6 @@
/* Font support for Haiku windowing
-Copyright (C) 2021-2023 Free Software Foundation, Inc.
+Copyright (C) 2021-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
@@ -873,7 +873,8 @@ haikufont_open (struct frame *f, Lisp_Object font_entity, int pixel_size)
font->baseline_offset = 0;
font->relative_compose = 0;
- font->props[FONT_NAME_INDEX] = Ffont_xlfd_name (font_object, Qnil);
+ font->props[FONT_NAME_INDEX]
+ = Ffont_xlfd_name (font_object, Qnil, Qt);
unblock_input ();
return font_object;
diff --git a/src/haikugui.h b/src/haikugui.h
index 8b144cc5e1d..7b90435f664 100644
--- a/src/haikugui.h
+++ b/src/haikugui.h
@@ -1,5 +1,5 @@
/* Haiku window system support
- Copyright (C) 2021-2023 Free Software Foundation, Inc.
+ Copyright (C) 2021-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/haikuimage.c b/src/haikuimage.c
index 78c6732d94f..b54337703d0 100644
--- a/src/haikuimage.c
+++ b/src/haikuimage.c
@@ -1,5 +1,5 @@
/* Haiku window system support.
- Copyright (C) 2021-2023 Free Software Foundation, Inc.
+ Copyright (C) 2021-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/haikumenu.c b/src/haikumenu.c
index fab58946568..2e00b1803ae 100644
--- a/src/haikumenu.c
+++ b/src/haikumenu.c
@@ -1,5 +1,5 @@
/* Haiku window system support
- Copyright (C) 2021-2023 Free Software Foundation, Inc.
+ Copyright (C) 2021-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/haikuselect.c b/src/haikuselect.c
index 608b8e8fe30..9a178acf618 100644
--- a/src/haikuselect.c
+++ b/src/haikuselect.c
@@ -1,5 +1,5 @@
/* Haiku window system selection support.
- Copyright (C) 2021-2023 Free Software Foundation, Inc.
+ Copyright (C) 2021-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
@@ -1189,7 +1189,7 @@ haiku_note_drag_wheel (struct input_event *ie)
if (!NILP (Vhaiku_drag_wheel_function)
&& (haiku_dnd_allow_same_frame
|| XFRAME (ie->frame_or_window) != haiku_dnd_frame))
- safe_call (7, Vhaiku_drag_wheel_function, ie->frame_or_window,
+ safe_calln (Vhaiku_drag_wheel_function, ie->frame_or_window,
ie->x, ie->y, horizontal ? Qt : Qnil, up ? Qt : Qnil,
make_int (ie->modifiers));
diff --git a/src/haikuselect.h b/src/haikuselect.h
index c117a2ab4f9..76c637b569a 100644
--- a/src/haikuselect.h
+++ b/src/haikuselect.h
@@ -1,5 +1,5 @@
/* Haiku window system selection support. Hey Emacs, this is -*- C++ -*-
- Copyright (C) 2021-2023 Free Software Foundation, Inc.
+ Copyright (C) 2021-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/haikuterm.c b/src/haikuterm.c
index 70984936bf9..135f99dbdcb 100644
--- a/src/haikuterm.c
+++ b/src/haikuterm.c
@@ -1,5 +1,5 @@
/* Haiku window system support
- Copyright (C) 2021-2023 Free Software Foundation, Inc.
+ Copyright (C) 2021-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
@@ -1219,7 +1219,7 @@ static void
haiku_draw_glyphless_glyph_string_foreground (struct glyph_string *s)
{
struct glyph *glyph = s->first_glyph;
- unsigned char2b[8];
+ static unsigned char2b[8];
int x, i, j;
struct face *face = s->face;
unsigned long color;
@@ -1399,7 +1399,7 @@ haiku_draw_stretch_glyph_string (struct glyph_string *s)
}
if (background_width > 0)
- haiku_draw_background_rect (s, s->face, s->x, s->y,
+ haiku_draw_background_rect (s, s->face, x, s->y,
background_width, s->height);
}
s->background_filled_p = 1;
@@ -3472,7 +3472,7 @@ haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit)
if (!NILP (Vmouse_autoselect_window))
{
static Lisp_Object last_mouse_window;
- Lisp_Object window = window_from_coordinates (f, b->x, b->y, 0, 0, 0);
+ Lisp_Object window = window_from_coordinates (f, b->x, b->y, 0, 0, 0, 0);
if (WINDOWP (window)
&& !EQ (window, last_mouse_window)
@@ -3555,7 +3555,7 @@ haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit)
int x = b->x;
int y = b->y;
- window = window_from_coordinates (f, x, y, 0, true, true);
+ window = window_from_coordinates (f, x, y, 0, true, true, true);
tab_bar_p = EQ (window, f->tab_bar_window);
if (tab_bar_p)
@@ -3573,7 +3573,7 @@ haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit)
int x = b->x;
int y = b->y;
- window = window_from_coordinates (f, x, y, 0, true, true);
+ window = window_from_coordinates (f, x, y, 0, true, true, true);
tool_bar_p = (EQ (window, f->tool_bar_window)
&& (type != BUTTON_UP
|| f->last_tool_bar_item != -1));
@@ -3834,7 +3834,7 @@ haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit)
BView_get_mouse (FRAME_HAIKU_VIEW (f), &x, &y);
- wheel_window = window_from_coordinates (f, x, y, 0, false, false);
+ wheel_window = window_from_coordinates (f, x, y, 0, false, false, false);
if (NILP (wheel_window))
{
diff --git a/src/haikuterm.h b/src/haikuterm.h
index 4d8d2678e82..75c4bf0d6ef 100644
--- a/src/haikuterm.h
+++ b/src/haikuterm.h
@@ -1,5 +1,5 @@
/* Haiku window system support
- Copyright (C) 2021-2023 Free Software Foundation, Inc.
+ Copyright (C) 2021-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/hbfont.c b/src/hbfont.c
index 86ba9eea1ac..40bb44c7d04 100644
--- a/src/hbfont.c
+++ b/src/hbfont.c
@@ -1,5 +1,5 @@
/* hbfont.c -- Platform-independent support for HarfBuzz font driver.
- Copyright (C) 2019-2023 Free Software Foundation, Inc.
+ Copyright (C) 2019-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/image.c b/src/image.c
index 7019bbf31be..f09552c4017 100644
--- a/src/image.c
+++ b/src/image.c
@@ -1,6 +1,6 @@
/* Functions for image support on window system.
-Copyright (C) 1989-2023 Free Software Foundation, Inc.
+Copyright (C) 1989-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
@@ -1337,6 +1337,18 @@ image_error (const char *format, ...)
}
static void
+image_invalid_data_error (Lisp_Object data)
+{
+ image_error ("Invalid image data `%s'", data);
+}
+
+static void
+image_not_found_error (Lisp_Object filename)
+{
+ image_error ("Cannot find image file `%s'", filename);
+}
+
+static void
image_size_error (void)
{
image_error ("Invalid image size (see `max-image-size')");
@@ -1531,7 +1543,7 @@ parse_image_spec (Lisp_Object spec, struct image_keyword *keywords,
if KEY is not present in SPEC. Set *FOUND depending on whether KEY
was found in SPEC. */
-static Lisp_Object
+Lisp_Object
image_spec_value (Lisp_Object spec, Lisp_Object key, bool *found)
{
Lisp_Object tail;
@@ -2330,6 +2342,7 @@ evicted. */)
{
if (!NILP (animation_cache))
{
+ CHECK_CONS (animation_cache);
#if defined (HAVE_WEBP) || defined (HAVE_GIF)
anim_prune_animation_cache (XCDR (animation_cache));
#endif
@@ -3838,8 +3851,8 @@ image_create_x_image_and_pixmap_1 (struct frame *f, int width, int height, int d
if (*pixmap == NO_PIXMAP)
{
*pimg = NULL;
- image_error ("Unable to create X pixmap", Qnil, Qnil);
- return 0;
+ image_error ("Unable to create X pixmap");
+ return false;
}
*pimg = *pixmap;
@@ -3871,8 +3884,8 @@ image_create_x_image_and_pixmap_1 (struct frame *f, int width, int height, int d
if (*pixmap == NO_PIXMAP)
{
*pimg = NULL;
- image_error ("Unable to create pixmap", Qnil, Qnil);
- return 0;
+ image_error ("Unable to create pixmap");
+ return false;
}
*pimg = *pixmap;
@@ -4343,6 +4356,27 @@ slurp_file (image_fd fd, ptrdiff_t *size)
return buf;
}
+/* Like slurp_file above, but with added error handling. Value is
+ null if an error occurred. Set SIZE to the size of the file.
+ IMAGE_TYPE describes the image type (e.g. "PNG"). */
+
+static char *
+slurp_image (Lisp_Object filename, ptrdiff_t *size, const char *image_type)
+{
+ image_fd fd;
+ Lisp_Object file = image_find_image_fd (filename, &fd);
+ if (!STRINGP (file))
+ {
+ image_not_found_error (filename);
+ return NULL;
+ }
+ char *result = slurp_file (fd, size);
+ if (result == NULL)
+ image_error ("Error loading %s image `%s'",
+ make_unibyte_string (image_type, strlen (image_type)),
+ file);
+ return result;
+}
/***********************************************************************
@@ -5061,22 +5095,10 @@ xbm_load (struct frame *f, struct image *img)
file_name = image_spec_value (img->spec, QCfile, NULL);
if (STRINGP (file_name))
{
- image_fd fd;
- Lisp_Object file = image_find_image_fd (file_name, &fd);
- if (!STRINGP (file))
- {
- image_error ("Cannot find image file `%s'", file_name);
- return 0;
- }
-
ptrdiff_t size;
- char *contents = slurp_file (fd, &size);
+ char *contents = slurp_image (file_name, &size, "XBM");
if (contents == NULL)
- {
- image_error ("Error loading XBM image `%s'", file);
- return 0;
- }
-
+ return false;
success_p = xbm_load_image (f, img, contents, contents + size);
xfree (contents);
}
@@ -5717,12 +5739,12 @@ xpm_load (struct frame *f, struct image *img)
Lisp_Object file = image_find_image_file (specified_file);
if (!STRINGP (file))
{
- image_error ("Cannot find image file `%s'", specified_file);
+ image_not_found_error (specified_file);
#ifdef ALLOC_XPM_COLORS
xpm_free_color_cache ();
#endif
SAFE_FREE ();
- return 0;
+ return false;
}
file = ENCODE_FILE (file);
@@ -5749,7 +5771,7 @@ xpm_load (struct frame *f, struct image *img)
Lisp_Object buffer = image_spec_value (img->spec, QCdata, NULL);
if (!STRINGP (buffer))
{
- image_error ("Invalid image data `%s'", buffer);
+ image_invalid_data_error (buffer);
#ifdef ALLOC_XPM_COLORS
xpm_free_color_cache ();
#endif
@@ -6357,21 +6379,10 @@ xpm_load (struct frame *f,
file_name = image_spec_value (img->spec, QCfile, NULL);
if (STRINGP (file_name))
{
- image_fd fd;
- Lisp_Object file = image_find_image_fd (file_name, &fd);
- if (!STRINGP (file))
- {
- image_error ("Cannot find image file `%s'", file_name);
- return 0;
- }
-
ptrdiff_t size;
- char *contents = slurp_file (fd, &size);
+ char *contents = slurp_image (file_name, &size, "XPM");
if (contents == NULL)
- {
- image_error ("Error loading XPM image `%s'", file);
- return 0;
- }
+ return false;
success_p = xpm_load_image (f, img, contents, contents + size);
xfree (contents);
@@ -6383,8 +6394,8 @@ xpm_load (struct frame *f,
data = image_spec_value (img->spec, QCdata, NULL);
if (!STRINGP (data))
{
- image_error ("Invalid image data `%s'", data);
- return 0;
+ image_invalid_data_error (data);
+ return false;
}
success_p = xpm_load_image (f, img, SSDATA (data),
SSDATA (data) + SBYTES (data));
@@ -7386,21 +7397,10 @@ pbm_load (struct frame *f, struct image *img)
if (STRINGP (specified_file))
{
- image_fd fd;
- Lisp_Object file = image_find_image_fd (specified_file, &fd);
- if (!STRINGP (file))
- {
- image_error ("Cannot find image file `%s'", specified_file);
- return 0;
- }
-
ptrdiff_t size;
- contents = slurp_file (fd, &size);
+ contents = slurp_image (specified_file, &size, "PBM");
if (contents == NULL)
- {
- image_error ("Error reading `%s'", file);
- return 0;
- }
+ return false;
p = contents;
end = contents + size;
@@ -7411,8 +7411,8 @@ pbm_load (struct frame *f, struct image *img)
data = image_spec_value (img->spec, QCdata, NULL);
if (!STRINGP (data))
{
- image_error ("Invalid image data `%s'", data);
- return 0;
+ image_invalid_data_error (data);
+ return false;
}
p = SSDATA (data);
end = p + SBYTES (data);
@@ -8060,8 +8060,8 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c)
|| (fd = emacs_open (SSDATA (ENCODE_FILE (file)),
O_RDONLY, 0)) < 0)
{
- image_error ("Cannot find image file `%s'", specified_file);
- return 0;
+ image_not_found_error (specified_file);
+ return false;
}
/* Open the image file. */
@@ -8085,8 +8085,8 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c)
{
if (!STRINGP (specified_data))
{
- image_error ("Invalid image data `%s'", specified_data);
- return 0;
+ image_invalid_data_error (specified_data);
+ return false;
}
/* Read from memory. */
@@ -8789,8 +8789,8 @@ jpeg_load_body (struct frame *f, struct image *img,
|| (fd = emacs_open (SSDATA (ENCODE_FILE (file)),
O_RDONLY, 0)) < 0)
{
- image_error ("Cannot find image file `%s'", specified_file);
- return 0;
+ image_not_found_error (specified_file);
+ return false;
}
fp = emacs_fdopen (fd, "rb");
@@ -8802,8 +8802,8 @@ jpeg_load_body (struct frame *f, struct image *img,
}
else if (!STRINGP (specified_data))
{
- image_error ("Invalid image data `%s'", specified_data);
- return 0;
+ image_invalid_data_error (specified_data);
+ return false;
}
/* Customize libjpeg's error handling to call my_error_exit when an
@@ -9244,8 +9244,8 @@ tiff_load (struct frame *f, struct image *img)
Lisp_Object file = image_find_image_file (specified_file);
if (!STRINGP (file))
{
- image_error ("Cannot find image file `%s'", specified_file);
- return 0;
+ image_not_found_error (specified_file);
+ return false;
}
Lisp_Object encoded_file = ENCODE_FILE (file);
@@ -9265,8 +9265,8 @@ tiff_load (struct frame *f, struct image *img)
{
if (!STRINGP (specified_data))
{
- image_error ("Invalid image data `%s'", specified_data);
- return 0;
+ image_invalid_data_error (specified_data);
+ return false;
}
/* Memory source! */
@@ -9673,7 +9673,7 @@ gif_load (struct frame *f, struct image *img)
Lisp_Object file = image_find_image_file (specified_file);
if (!STRINGP (file))
{
- image_error ("Cannot find image file `%s'", specified_file);
+ image_not_found_error (specified_file);
return false;
}
@@ -9718,7 +9718,7 @@ gif_load (struct frame *f, struct image *img)
{
if (!STRINGP (specified_data))
{
- image_error ("Invalid image data `%s'", specified_data);
+ image_invalid_data_error (specified_data);
return false;
}
@@ -10290,26 +10290,15 @@ webp_load (struct frame *f, struct image *img)
if (NILP (specified_data))
{
- image_fd fd;
- file = image_find_image_fd (specified_file, &fd);
- if (!STRINGP (file))
- {
- image_error ("Cannot find image file `%s'", specified_file);
- return false;
- }
-
- contents = (uint8_t *) slurp_file (fd, &size);
+ contents = (uint8_t *) slurp_image (specified_file, &size, "WebP");
if (contents == NULL)
- {
- image_error ("Error loading WebP image `%s'", file);
- return false;
- }
+ return false;
}
else
{
if (!STRINGP (specified_data))
{
- image_error ("Invalid image data `%s'", specified_data);
+ image_invalid_data_error (specified_data);
return false;
}
contents = SDATA (specified_data);
@@ -10450,22 +10439,36 @@ webp_load (struct frame *f, struct image *img)
}
/* Create the x image and pixmap. */
- Emacs_Pix_Container ximg, mask_img = NULL;
+ Emacs_Pix_Container ximg;
if (!image_create_x_image_and_pixmap (f, img, width, height, 0, &ximg, false))
goto webp_error2;
- /* Create an image and pixmap serving as mask if the WebP image
- contains an alpha channel. */
- if (features.has_alpha
- && !image_create_x_image_and_pixmap (f, img, width, height, 1,
- &mask_img, true))
+ /* Find the background to use if the WebP image contains an alpha
+ channel. */
+ Emacs_Color bg_color;
+ if (features.has_alpha)
{
- image_destroy_x_image (ximg);
- image_clear_image_1 (f, img, CLEAR_IMAGE_PIXMAP);
- goto webp_error2;
+ Lisp_Object specified_bg
+ = image_spec_value (img->spec, QCbackground, NULL);
+
+ /* If the user specified a color, try to use it; if not, use the
+ current frame background, ignoring any default background
+ color set by the image. */
+ if (STRINGP (specified_bg))
+ FRAME_TERMINAL (f)->defined_color_hook (f,
+ SSDATA (specified_bg),
+ &bg_color,
+ false,
+ false);
+ else
+ FRAME_TERMINAL (f)->query_frame_background_color (f, &bg_color);
+ bg_color.red >>= 8;
+ bg_color.green >>= 8;
+ bg_color.blue >>= 8;
}
- /* Fill the X image and mask from WebP data. */
+ /* Fill the X image from WebP data. */
+
init_color_table ();
img->corners[TOP_CORNER] = 0;
@@ -10480,21 +10483,24 @@ webp_load (struct frame *f, struct image *img)
{
for (int x = 0; x < width; ++x)
{
- int r = *p++ << 8;
- int g = *p++ << 8;
- int b = *p++ << 8;
- PUT_PIXEL (ximg, x, y, lookup_rgb_color (f, r, g, b));
-
- /* An alpha channel associates variable transparency with an
- image. WebP allows up to 256 levels of partial transparency.
- We handle this like with PNG (which see), using the frame's
- background color to combine the image with. */
+ int r, g, b;
+ /* The WebP alpha channel allows 256 levels of partial
+ transparency. Blend it with the background manually. */
if (features.has_alpha || anim)
{
- if (mask_img)
- PUT_PIXEL (mask_img, x, y, *p > 0 ? PIX_MASK_DRAW : PIX_MASK_RETAIN);
- ++p;
+ float a = (float) p[3] / UINT8_MAX;
+ r = (int)(a * p[0] + (1 - a) * bg_color.red) << 8;
+ g = (int)(a * p[1] + (1 - a) * bg_color.green) << 8;
+ b = (int)(a * p[2] + (1 - a) * bg_color.blue) << 8;
+ p += 4;
}
+ else
+ {
+ r = *p++ << 8;
+ g = *p++ << 8;
+ b = *p++ << 8;
+ }
+ PUT_PIXEL (ximg, x, y, lookup_rgb_color (f, r, g, b));
}
}
@@ -10507,16 +10513,6 @@ webp_load (struct frame *f, struct image *img)
/* Put ximg into the image. */
image_put_x_image (f, img, ximg, 0);
- /* Same for the mask. */
- if (mask_img)
- {
- /* Fill in the background_transparent field while we have the
- mask handy. Casting avoids a GCC warning. */
- image_background_transparent (img, f, (Emacs_Pix_Context)mask_img);
-
- image_put_x_image (f, img, mask_img, 1);
- }
-
img->width = width;
img->height = height;
@@ -11311,8 +11307,8 @@ imagemagick_load (struct frame *f, struct image *img)
Lisp_Object file = image_find_image_file (file_name);
if (!STRINGP (file))
{
- image_error ("Cannot find image file `%s'", file_name);
- return 0;
+ image_not_found_error (file_name);
+ return false;
}
file = ENCODE_FILE (file);
#ifdef WINDOWSNT
@@ -11329,8 +11325,8 @@ imagemagick_load (struct frame *f, struct image *img)
data = image_spec_value (img->spec, QCdata, NULL);
if (!STRINGP (data))
{
- image_error ("Invalid image data `%s'", data);
- return 0;
+ image_invalid_data_error (data);
+ return false;
}
success_p = imagemagick_load_image (f, img, SDATA (data),
SBYTES (data), NULL);
@@ -11693,8 +11689,8 @@ svg_load (struct frame *f, struct image *img)
Lisp_Object file = image_find_image_fd (file_name, &fd);
if (!STRINGP (file))
{
- image_error ("Cannot find image file `%s'", file_name);
- return 0;
+ image_not_found_error (file_name);
+ return false;
}
/* Read the entire file into memory. */
@@ -11703,7 +11699,7 @@ svg_load (struct frame *f, struct image *img)
if (contents == NULL)
{
image_error ("Error loading SVG image `%s'", file);
- return 0;
+ return false;
}
/* If the file was slurped into memory properly, parse it. */
if (!STRINGP (base_uri))
@@ -11721,8 +11717,8 @@ svg_load (struct frame *f, struct image *img)
data = image_spec_value (img->spec, QCdata, NULL);
if (!STRINGP (data))
{
- image_error ("Invalid image data `%s'", data);
- return 0;
+ image_invalid_data_error (data);
+ return false;
}
if (!STRINGP (base_uri))
base_uri = BVAR (current_buffer, filename);
@@ -11789,7 +11785,7 @@ svg_css_length_to_pixels (RsvgLength length, double dpi, int font_size)
If we do set explicit width and height values in the image
spec, this will work out correctly as librsvg will still
- honour the percentage sizes in its final rendering no matter
+ honor the percentage sizes in its final rendering no matter
what size we make the image. */
value = 0;
break;
@@ -11808,7 +11804,17 @@ svg_css_length_to_pixels (RsvgLength length, double dpi, int font_size)
Use librsvg to do most of the image processing.
- Return true when successful. */
+ Return true when successful.
+
+ The basic process, which is used for all versions of librsvg, is to
+ load the SVG and parse it, then extract the image dimensions. We
+ then use those image dimensions to calculate the final size and
+ wrap the SVG data inside another SVG we build on the fly. This
+ wrapper does the necessary resizing and setting of foreground and
+ background colors and is then parsed and rasterized.
+
+ It should also be noted that setting up the SVG prior to 2.32 was
+ done differently, but the overall process is the same. */
static bool
svg_load_image (struct frame *f, struct image *img, char *contents,
ptrdiff_t size, char *filename)
@@ -11862,7 +11868,13 @@ svg_load_image (struct frame *f, struct image *img, char *contents,
Lisp_Object lcss = image_spec_value (img->spec, QCcss, NULL);
if (!STRINGP (lcss))
{
- /* Generate the CSS for the SVG image. */
+ /* Generate the CSS for the SVG image.
+
+ We use this to set the font (font-family in CSS lingo) and
+ the font size. We can extend this to handle any CSS values
+ SVG supports, however it's only available in librsvg 2.48 and
+ above so some things we could set here are handled in the
+ wrapper below. */
/* FIXME: The below calculations leave enough space for a font
size up to 9999, if it overflows we just throw an error but
should probably increase the buffer size. */
@@ -11908,7 +11920,23 @@ svg_load_image (struct frame *f, struct image *img, char *contents,
if (err) goto rsvg_error;
#endif
- /* Get the image dimensions. */
+ /* Get the image dimensions.
+
+ There are a couple of approaches used here, depending on the
+ contents of the SVG, and which version of librsvg we're using.
+ With librsvg versions prior to 2.46 we ask librsvg for the size
+ of the image, however this may include pats of the image that are
+ outside of the viewbox.
+
+ librsvg 2.46 allows us to request the image's "intrinsic
+ dimensions", which are the sizes given in the SVG in CSS units.
+ So, for example, if the image defines it's width as "10mm", we
+ are given a struct that we need to translate into pixel values
+ ourself (see svg_css_length_to_pixels).
+
+ 2.52 introduces a function that will give us the pixel sizes
+ directly, assuming we provide the correct screen DPI values.
+ */
#if LIBRSVG_CHECK_VERSION (2, 46, 0)
gdouble gviewbox_width = 0, gviewbox_height = 0;
gboolean has_viewbox = FALSE;
@@ -12056,6 +12084,18 @@ svg_load_image (struct frame *f, struct image *img, char *contents,
img->background_valid = 1;
}
+#if HAVE_NTGUI
+ /* Windows stores the image colors in BGR format, and SVG expects
+ them in RGB. */
+ foreground = (foreground & 0x0000FF) << 16
+ | (foreground & 0xFF0000) >> 16
+ | (foreground & 0x00FF00);
+
+ background = (background & 0x0000FF) << 16
+ | (background & 0xFF0000) >> 16
+ | (background & 0x00FF00);
+#endif
+
wrapped_contents = xmalloc (buffer_size);
if (buffer_size <= snprintf (wrapped_contents, buffer_size, wrapper,
@@ -12088,6 +12128,8 @@ svg_load_image (struct frame *f, struct image *img, char *contents,
FRAME_DISPLAY_INFO (f)->resy);
#if LIBRSVG_CHECK_VERSION (2, 48, 0)
+ /* Set the CSS for the wrapped SVG. See the comment above the
+ previous use of 'css'. */
rsvg_handle_set_stylesheet (rsvg_handle, (guint8 *)css, strlen (css), NULL);
#endif
#else
diff --git a/src/indent.c b/src/indent.c
index eda85f2e94d..3094a9d3089 100644
--- a/src/indent.c
+++ b/src/indent.c
@@ -1,5 +1,5 @@
/* Indentation functions.
- Copyright (C) 1985-1988, 1993-1995, 1998, 2000-2023 Free Software
+ Copyright (C) 1985-1988, 1993-1995, 1998, 2000-2024 Free Software
Foundation, Inc.
This file is part of GNU Emacs.
@@ -2031,7 +2031,7 @@ vmotion (ptrdiff_t from, ptrdiff_t from_byte,
}
/* Return the width taken by line-number display in window W. */
-static void
+void
line_number_display_width (struct window *w, int *width, int *pixel_width)
{
if (NILP (Vdisplay_line_numbers))
@@ -2101,7 +2101,7 @@ numbers on display. */)
{
int width, pixel_width;
struct window *w = XWINDOW (selected_window);
- line_number_display_width (XWINDOW (selected_window), &width, &pixel_width);
+ line_number_display_width (w, &width, &pixel_width);
if (EQ (pixelwise, Qcolumns))
{
struct frame *f = XFRAME (w->frame);
diff --git a/src/indent.h b/src/indent.h
index 7bcecb3fdd5..5f8e7ecfd2c 100644
--- a/src/indent.h
+++ b/src/indent.h
@@ -1,5 +1,5 @@
/* Definitions for interface to indent.c
- Copyright (C) 1985-1986, 2001-2023 Free Software Foundation, Inc.
+ Copyright (C) 1985-1986, 2001-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/inotify.c b/src/inotify.c
index 105ff5a9d8a..2ee874530cc 100644
--- a/src/inotify.c
+++ b/src/inotify.c
@@ -1,6 +1,6 @@
/* Inotify support for Emacs
-Copyright (C) 2012-2023 Free Software Foundation, Inc.
+Copyright (C) 2012-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
@@ -148,6 +148,11 @@ symbol_to_inotifymask (Lisp_Object symb)
else if (EQ (symb, Qonlydir))
return IN_ONLYDIR;
+ else if (EQ (symb, Qignored))
+ return IN_IGNORED;
+ else if (EQ (symb, Qunmount))
+ return IN_UNMOUNT;
+
else if (EQ (symb, Qt) || EQ (symb, Qall_events))
return IN_ALL_EVENTS;
else
@@ -512,12 +517,14 @@ it invalid. */)
#ifdef INOTIFY_DEBUG
DEFUN ("inotify-watch-list", Finotify_watch_list, Sinotify_watch_list, 0, 0, 0,
doc: /* Return a copy of the internal watch_list. */)
+ (void)
{
return Fcopy_sequence (watch_list);
}
DEFUN ("inotify-allocated-p", Finotify_allocated_p, Sinotify_allocated_p, 0, 0, 0,
doc: /* Return non-nil, if an inotify instance is allocated. */)
+ (void)
{
return inotifyfd < 0 ? Qnil : Qt;
}
diff --git a/src/insdel.c b/src/insdel.c
index b65a3fbd805..e41d9945551 100644
--- a/src/insdel.c
+++ b/src/insdel.c
@@ -1,5 +1,5 @@
/* Buffer insertion/deletion and gap motion for GNU Emacs. -*- coding: utf-8 -*-
- Copyright (C) 1985-1986, 1993-1995, 1997-2023 Free Software
+ Copyright (C) 1985-1986, 1993-1995, 1997-2024 Free Software
Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/intervals.c b/src/intervals.c
index ee976fb1035..1b1fb3b8181 100644
--- a/src/intervals.c
+++ b/src/intervals.c
@@ -1,5 +1,5 @@
/* Code for doing intervals.
- Copyright (C) 1993-1995, 1997-1998, 2001-2023 Free Software
+ Copyright (C) 1993-1995, 1997-1998, 2001-2024 Free Software
Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/intervals.h b/src/intervals.h
index 8af92223773..aa7502b4f68 100644
--- a/src/intervals.h
+++ b/src/intervals.h
@@ -1,5 +1,5 @@
/* Definitions and global variables for intervals.
- Copyright (C) 1993-1994, 2000-2023 Free Software Foundation, Inc.
+ Copyright (C) 1993-1994, 2000-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/itree.c b/src/itree.c
index ecf7d67422a..da51b3c61fd 100644
--- a/src/itree.c
+++ b/src/itree.c
@@ -1,6 +1,6 @@
/* This file implements an efficient interval data-structure.
-Copyright (C) 2017-2023 Free Software Foundation, Inc.
+Copyright (C) 2017-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
@@ -74,7 +74,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
Consider the case where next-overlay-change is called at POS, all
interval BEG positions are less than pos POS and all interval END
- posistions are after. These END positions have no order, and so
+ positions are after. These END positions have no order, and so
*every* interval must be examined. This is at least O(N). The
previous-overlay-change case is similar. The root issue is that
the iterative "narrowing" approach is not guaranteed to reduce the
@@ -278,7 +278,7 @@ check_subtree (struct itree_node *node,
This runs in constant time when ENABLE_OVERLAY_CHECKING is 0
(i.e. Emacs is not configured with
- "--enable_checking=yes,overlays"). In this mode it can't check all
+ "--enable-checking=yes,overlays"). In this mode it can't check all
the invariants. When ENABLE_OVERLAY_CHECKING is 1 it checks the
entire tree and validates all invariants.
*/
diff --git a/src/itree.h b/src/itree.h
index 79d03d31ce2..f54dbd7f07e 100644
--- a/src/itree.h
+++ b/src/itree.h
@@ -1,6 +1,6 @@
/* This file implements an efficient interval data-structure.
-Copyright (C) 2017-2023 Free Software Foundation, Inc.
+Copyright (C) 2017-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/json.c b/src/json.c
index f7979fb446e..af5f30c7275 100644
--- a/src/json.c
+++ b/src/json.c
@@ -1,6 +1,6 @@
/* JSON parsing and serialization.
-Copyright (C) 2017-2023 Free Software Foundation, Inc.
+Copyright (C) 2017-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/keyboard.c b/src/keyboard.c
index 78c88a2859b..4555b71abe7 100644
--- a/src/keyboard.c
+++ b/src/keyboard.c
@@ -1,6 +1,6 @@
/* Keyboard and mouse input; editor command loop.
-Copyright (C) 1985-1989, 1993-1997, 1999-2023 Free Software Foundation,
+Copyright (C) 1985-1989, 1993-1997, 1999-2024 Free Software Foundation,
Inc.
This file is part of GNU Emacs.
@@ -1601,7 +1601,7 @@ command_loop_1 (void)
if ((!NILP (Fwindow_system (Qnil))
|| ((symval =
find_symbol_value (Qtty_select_active_regions),
- (!EQ (symval, Qunbound) && !NILP (symval)))
+ (!BASE_EQ (symval, Qunbound) && !NILP (symval)))
&& !NILP (Fterminal_parameter (Qnil,
Qxterm__set_selection))))
/* Even if mark_active is non-nil, the actual buffer
@@ -2226,7 +2226,7 @@ show_help_echo (Lisp_Object help, Lisp_Object window, Lisp_Object object,
if (!NILP (help) && !STRINGP (help))
{
if (FUNCTIONP (help))
- help = safe_call (4, help, window, object, pos);
+ help = safe_calln (help, window, object, pos);
else
help = safe_eval (help);
@@ -3993,6 +3993,19 @@ kbd_buffer_get_event (KBOARD **kbp,
if (CONSP (Vunread_command_events))
break;
+#ifdef HAVE_TEXT_CONVERSION
+ /* That text conversion events take priority over keyboard
+ events, since input methods frequently send them immediately
+ after edits, with the assumption that this order of events
+ will be observed. */
+
+ if (detect_conversion_events ())
+ {
+ had_pending_conversion_events = true;
+ break;
+ }
+#endif /* HAVE_TEXT_CONVERSION */
+
if (kbd_fetch_ptr != kbd_store_ptr)
break;
if (some_mouse_moved ())
@@ -4021,13 +4034,6 @@ kbd_buffer_get_event (KBOARD **kbp,
break;
}
#endif
-#ifdef HAVE_TEXT_CONVERSION
- if (detect_conversion_events ())
- {
- had_pending_conversion_events = true;
- break;
- }
-#endif
if (end_time)
{
struct timespec now = current_timespec ();
@@ -4648,7 +4654,7 @@ timer_check_2 (Lisp_Object timers, Lisp_Object idle_timers)
{
Lisp_Object funcall = XCAR (pending_funcalls);
pending_funcalls = XCDR (pending_funcalls);
- safe_call2 (Qapply, XCAR (funcall), XCDR (funcall));
+ safe_calln (Qapply, XCAR (funcall), XCDR (funcall));
}
if (CONSP (timers) || CONSP (idle_timers))
@@ -4833,7 +4839,8 @@ The value when Emacs is idle is a Lisp timestamp in the style of
The value when Emacs is not idle is nil.
-PSEC is a multiple of the system clock resolution. */)
+If the value is a list of four integers (HIGH LOW USEC PSEC), then PSEC
+is a multiple of the system clock resolution. */)
(void)
{
if (timespec_valid_p (timer_idleness_start_time))
@@ -4988,12 +4995,17 @@ static const char *const lispy_accent_keys[] =
#ifdef HAVE_ANDROID
#define FUNCTION_KEY_OFFSET 0
+/* Mind that Android designates 23 KEYCODE_DPAD_CENTER, but it is
+ merely abstruse terminology for the ``select'' key frequently
+ located in certain physical keyboards. */
+
const char *const lispy_function_keys[] =
{
/* All elements in this array default to 0, except for the few
function keys that Emacs recognizes. */
[111] = "escape",
[112] = "delete",
+ [116] = "scroll",
[120] = "sysrq",
[121] = "break",
[122] = "home",
@@ -5014,21 +5026,27 @@ const char *const lispy_function_keys[] =
[140] = "f10",
[141] = "f11",
[142] = "f12",
+ [143] = "kp-numlock",
[160] = "kp-ret",
[164] = "volume-mute",
+ [165] = "info",
[19] = "up",
[20] = "down",
+ [211] = "zenkaku-hankaku",
[213] = "muhenkan",
[214] = "henkan",
[215] = "hiragana-katakana",
[218] = "kana",
[21] = "left",
+ [223] = "sleep",
[22] = "right",
+ [23] = "select",
[24] = "volume-up",
[259] = "help",
[25] = "volume-down",
[268] = "kp-up-left",
[269] = "kp-down-left",
+ [26] = "power",
[270] = "kp-up-right",
[271] = "kp-down-right",
[272] = "media-skip-forward",
@@ -5036,7 +5054,9 @@ const char *const lispy_function_keys[] =
[277] = "cut",
[278] = "copy",
[279] = "paste",
+ [285] = "browser-refresh",
[28] = "clear",
+ [300] = "XF86Forward",
[4] = "XF86Back",
[61] = "tab",
[66] = "return",
@@ -5050,6 +5070,7 @@ const char *const lispy_function_keys[] =
[89] = "media-rewind",
[92] = "prior",
[93] = "next",
+ [95] = "mode-change",
};
#elif defined HAVE_NTGUI
@@ -5516,6 +5537,10 @@ static Lisp_Object button_down_location;
the down mouse event. */
static Lisp_Object frame_relative_event_pos;
+/* The line-number display width, in columns, at the time of most
+ recent down mouse event. */
+static int down_mouse_line_number_width;
+
/* Information about the most recent up-going button event: Which
button, what location, and what time. */
@@ -5542,9 +5567,10 @@ make_lispy_position (struct frame *f, Lisp_Object x, Lisp_Object y,
/* Coordinate pixel positions to return. */
int xret = 0, yret = 0;
/* The window or frame under frame pixel coordinates (x,y) */
- Lisp_Object window_or_frame = f
- ? window_from_coordinates (f, mx, my, &part, true, true)
- : Qnil;
+ Lisp_Object window_or_frame = (f != NULL
+ ? window_from_coordinates (f, mx, my, &part,
+ false, true, true)
+ : Qnil);
#ifdef HAVE_WINDOW_SYSTEM
bool tool_bar_p = false;
bool menu_bar_p = false;
@@ -5912,6 +5938,57 @@ coords_in_tab_bar_window (struct frame *f, int x, int y)
#endif /* HAVE_WINDOW_SYSTEM */
+static void
+save_line_number_display_width (struct input_event *event)
+{
+ struct window *w;
+ int pixel_width;
+
+ if (WINDOWP (event->frame_or_window))
+ w = XWINDOW (event->frame_or_window);
+ else if (FRAMEP (event->frame_or_window))
+ w = XWINDOW (XFRAME (event->frame_or_window)->selected_window);
+ else
+ w = XWINDOW (selected_window);
+ line_number_display_width (w, &down_mouse_line_number_width, &pixel_width);
+}
+
+/* Return non-zero if the change of position from START_POS to END_POS
+ is likely to be the effect of horizontal scrolling due to a change
+ in line-number width produced by redisplay between two mouse
+ events, like mouse-down followed by mouse-up, at those positions.
+ This is used to decide whether to converts mouse-down followed by
+ mouse-up event into a mouse-drag event. */
+static bool
+line_number_mode_hscroll (Lisp_Object start_pos, Lisp_Object end_pos)
+{
+ if (!EQ (Fcar (start_pos), Fcar (end_pos)) /* different window */
+ || list_length (start_pos) < 7 /* no COL/ROW info */
+ || list_length (end_pos) < 7)
+ return false;
+
+ Lisp_Object start_col_row = Fnth (make_fixnum (6), start_pos);
+ Lisp_Object end_col_row = Fnth (make_fixnum (6), end_pos);
+ Lisp_Object window = Fcar (end_pos);
+ int col_width, pixel_width;
+ Lisp_Object start_col, end_col;
+ struct window *w;
+ if (!WINDOW_VALID_P (window))
+ {
+ if (WINDOW_LIVE_P (window))
+ window = XFRAME (window)->selected_window;
+ else
+ window = selected_window;
+ }
+ w = XWINDOW (window);
+ line_number_display_width (w, &col_width, &pixel_width);
+ start_col = Fcar (start_col_row);
+ end_col = Fcar (end_col_row);
+ return EQ (start_col, end_col)
+ && down_mouse_line_number_width >= 0
+ && col_width != down_mouse_line_number_width;
+}
+
/* Given a struct input_event, build the lisp event which represents
it. If EVENT is 0, build a mouse movement event from the mouse
movement buffer, which should have a movement event in it.
@@ -6314,6 +6391,8 @@ make_lispy_event (struct input_event *event)
*start_pos_ptr = Fcopy_alist (position);
frame_relative_event_pos = Fcons (event->x, event->y);
ignore_mouse_drag_p = false;
+ /* Squirrel away the line-number width, if any. */
+ save_line_number_display_width (event);
}
/* Now we're releasing a button - check the coordinates to
@@ -6359,12 +6438,18 @@ make_lispy_event (struct input_event *event)
it's probably OK to ignore it as well. */
&& (EQ (Fcar (Fcdr (start_pos)),
Fcar (Fcdr (position))) /* Same buffer pos */
+ /* Redisplay hscrolled text between down- and
+ up-events due to display-line-numbers-mode. */
+ || line_number_mode_hscroll (start_pos, position)
|| !EQ (Fcar (start_pos),
Fcar (position))))) /* Different window */
+
{
/* Mouse has moved enough. */
button_down_time = 0;
click_or_drag_modifier = drag_modifier;
+ /* Reset the value for future clicks. */
+ down_mouse_line_number_width = -1;
}
else if (((!EQ (Fcar (start_pos), Fcar (position)))
|| (!EQ (Fcar (Fcdr (start_pos)),
diff --git a/src/keyboard.h b/src/keyboard.h
index 9f6e65f9a09..05245f366f5 100644
--- a/src/keyboard.h
+++ b/src/keyboard.h
@@ -1,5 +1,5 @@
/* Declarations useful when processing input.
- Copyright (C) 1985-1987, 1993, 2001-2023 Free Software Foundation,
+ Copyright (C) 1985-1987, 1993, 2001-2024 Free Software Foundation,
Inc.
This file is part of GNU Emacs.
diff --git a/src/keymap.c b/src/keymap.c
index 1f863885003..10378767c65 100644
--- a/src/keymap.c
+++ b/src/keymap.c
@@ -1,5 +1,5 @@
/* Manipulation of keymaps
- Copyright (C) 1985-1988, 1993-1995, 1998-2023 Free Software
+ Copyright (C) 1985-1988, 1993-1995, 1998-2024 Free Software
Foundation, Inc.
This file is part of GNU Emacs.
@@ -610,7 +610,7 @@ map_keymap_canonical (Lisp_Object map, map_keymap_function_t fun, Lisp_Object ar
{
/* map_keymap_canonical may be used from redisplay (e.g. when building menus)
so be careful to ignore errors and to inhibit redisplay. */
- map = safe_call1 (Qkeymap_canonicalize, map);
+ map = safe_calln (Qkeymap_canonicalize, map);
/* No need to use `map_keymap' here because canonical map has no parent. */
map_keymap_internal (map, fun, args, data);
}
@@ -2885,7 +2885,7 @@ You type Translation\n\
{
Lisp_Object msg = build_unibyte_string ("Key translations");
CALLN (Ffuncall,
- Qdescribe_map_tree,
+ Qhelp__describe_map_tree,
Vkey_translation_map, Qnil, Qnil, prefix,
msg, nomenu, Qt, Qnil, Qnil, buffer);
}
@@ -2899,7 +2899,7 @@ You type Translation\n\
{
Lisp_Object msg = build_unibyte_string ("\f\nOverriding Bindings");
CALLN (Ffuncall,
- Qdescribe_map_tree,
+ Qhelp__describe_map_tree,
start1, Qt, shadow, prefix,
msg, nomenu, Qnil, Qnil, Qnil, buffer);
shadow = Fcons (start1, shadow);
@@ -2912,7 +2912,7 @@ You type Translation\n\
{
Lisp_Object msg = build_unibyte_string ("\f\nOverriding Bindings");
CALLN (Ffuncall,
- Qdescribe_map_tree,
+ Qhelp__describe_map_tree,
start1, Qt, shadow, prefix,
msg, nomenu, Qnil, Qnil, Qnil, buffer);
shadow = Fcons (start1, shadow);
@@ -2935,7 +2935,7 @@ You type Translation\n\
{
Lisp_Object msg = build_unibyte_string ("\f\n`keymap' Property Bindings");
CALLN (Ffuncall,
- Qdescribe_map_tree,
+ Qhelp__describe_map_tree,
start1, Qt, shadow, prefix,
msg, nomenu, Qnil, Qnil, Qnil, buffer);
shadow = Fcons (start1, shadow);
@@ -2946,7 +2946,7 @@ You type Translation\n\
{
/* The title for a minor mode keymap
is constructed at run time.
- We let describe-map-tree do the actual insertion
+ We let `help--describe-map-tree' do the actual insertion
because it takes care of other features when doing so. */
char *title, *p;
@@ -2968,7 +2968,7 @@ You type Translation\n\
Lisp_Object msg = build_unibyte_string (title);
CALLN (Ffuncall,
- Qdescribe_map_tree,
+ Qhelp__describe_map_tree,
maps[i], Qt, shadow, prefix,
msg, nomenu, Qnil, Qnil, Qnil, buffer);
shadow = Fcons (maps[i], shadow);
@@ -2986,7 +2986,7 @@ You type Translation\n\
build_unibyte_string ("\f\n`%s' Major Mode Bindings"),
XBUFFER (buffer)->major_mode_);
CALLN (Ffuncall,
- Qdescribe_map_tree,
+ Qhelp__describe_map_tree,
start1, Qt, shadow, prefix,
msg, nomenu, Qnil, Qnil, Qnil, buffer);
}
@@ -2994,7 +2994,7 @@ You type Translation\n\
{
Lisp_Object msg = build_unibyte_string ("\f\n`local-map' Property Bindings");
CALLN (Ffuncall,
- Qdescribe_map_tree,
+ Qhelp__describe_map_tree,
start1, Qt, shadow, prefix,
msg, nomenu, Qnil, Qnil, Qnil, buffer);
}
@@ -3005,7 +3005,7 @@ You type Translation\n\
Lisp_Object msg = build_unibyte_string ("\f\nGlobal Bindings");
CALLN (Ffuncall,
- Qdescribe_map_tree,
+ Qhelp__describe_map_tree,
current_global_map, Qt, shadow, prefix,
msg, nomenu, Qnil, Qt, Qnil, buffer);
@@ -3014,7 +3014,7 @@ You type Translation\n\
{
Lisp_Object msg = build_unibyte_string ("\f\nFunction key map translations");
CALLN (Ffuncall,
- Qdescribe_map_tree,
+ Qhelp__describe_map_tree,
KVAR (current_kboard, Vlocal_function_key_map), Qnil, Qnil, prefix,
msg, nomenu, Qt, Qnil, Qnil, buffer);
}
@@ -3024,7 +3024,7 @@ You type Translation\n\
{
Lisp_Object msg = build_unibyte_string ("\f\nInput decoding map translations");
CALLN (Ffuncall,
- Qdescribe_map_tree,
+ Qhelp__describe_map_tree,
KVAR (current_kboard, Vinput_decode_map), Qnil, Qnil, prefix,
msg, nomenu, Qt, Qnil, Qnil, buffer);
}
@@ -3341,7 +3341,7 @@ void
syms_of_keymap (void)
{
DEFSYM (Qkeymap, "keymap");
- DEFSYM (Qdescribe_map_tree, "describe-map-tree");
+ DEFSYM (Qhelp__describe_map_tree, "help--describe-map-tree");
DEFSYM (Qkeymap_canonicalize, "keymap-canonicalize");
diff --git a/src/keymap.h b/src/keymap.h
index 65be3addbdb..e79e0af9d36 100644
--- a/src/keymap.h
+++ b/src/keymap.h
@@ -1,5 +1,5 @@
/* Functions to manipulate keymaps.
- Copyright (C) 2001-2023 Free Software Foundation, Inc.
+ Copyright (C) 2001-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/kqueue.c b/src/kqueue.c
index 22c279b7ce3..4693e130208 100644
--- a/src/kqueue.c
+++ b/src/kqueue.c
@@ -1,6 +1,6 @@
/* Filesystem notifications support with kqueue API.
-Copyright (C) 2015-2023 Free Software Foundation, Inc.
+Copyright (C) 2015-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
@@ -320,13 +320,16 @@ kqueue_callback (int fd, void *data)
directory is monitored. */
if (kev.fflags & NOTE_RENAME)
actions = Fcons (Qrename, actions);
+ if (kev.fflags & NOTE_REVOKE)
+ actions = Fcons (Qrevoke, actions);
/* Create the event. */
if (! NILP (actions))
kqueue_generate_event (watch_object, actions, file, Qnil);
- /* Cancel monitor if file or directory is deleted or renamed. */
- if (kev.fflags & (NOTE_DELETE | NOTE_RENAME))
+ /* Cancel monitor if file or directory is deleted or renamed or
+ the file system is unmounted. */
+ if (kev.fflags & (NOTE_DELETE | NOTE_RENAME | NOTE_REVOKE))
Fkqueue_rm_watch (descriptor);
}
return;
@@ -351,6 +354,7 @@ following symbols:
`attrib' -- a FILE attribute was changed
`link' -- a FILE's link count was changed
`rename' -- FILE was moved to FILE1
+ `revoke' -- FILE was unmounted
When any event happens, Emacs will call the CALLBACK function passing
it a single argument EVENT, which is of the form
@@ -437,6 +441,7 @@ only when the upper directory of the renamed file is watched. */)
if (! NILP (Fmember (Qattrib, flags))) fflags |= NOTE_ATTRIB;
if (! NILP (Fmember (Qlink, flags))) fflags |= NOTE_LINK;
if (! NILP (Fmember (Qrename, flags))) fflags |= NOTE_RENAME;
+ if (! NILP (Fmember (Qrevoke, flags))) fflags |= NOTE_REVOKE;
/* Register event. */
EV_SET (&kev, fd, EVFILT_VNODE, EV_ADD | EV_ENABLE | EV_CLEAR,
@@ -526,6 +531,7 @@ syms_of_kqueue (void)
DEFSYM (Qattrib, "attrib"); /* NOTE_ATTRIB */
DEFSYM (Qlink, "link"); /* NOTE_LINK */
DEFSYM (Qrename, "rename"); /* NOTE_RENAME */
+ DEFSYM (Qrevoke, "revoke"); /* NOTE_REVOKE */
staticpro (&watch_list);
diff --git a/src/lastfile.c b/src/lastfile.c
index b80cdbc8fa6..48d3ac78634 100644
--- a/src/lastfile.c
+++ b/src/lastfile.c
@@ -1,5 +1,5 @@
/* Mark end of data space to dump as pure, for GNU Emacs.
- Copyright (C) 1985, 2001-2023 Free Software Foundation, Inc.
+ Copyright (C) 1985, 2001-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/lcms.c b/src/lcms.c
index e603573043e..52dff9afc97 100644
--- a/src/lcms.c
+++ b/src/lcms.c
@@ -1,5 +1,5 @@
/* Interface to Little CMS
- Copyright (C) 2017-2023 Free Software Foundation, Inc.
+ Copyright (C) 2017-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/lisp.h b/src/lisp.h
index 2f26e5eddce..10018e4dde7 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -1,6 +1,6 @@
/* Fundamental definitions for GNU Emacs Lisp interpreter. -*- coding: utf-8 -*-
-Copyright (C) 1985-2023 Free Software Foundation, Inc.
+Copyright (C) 1985-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
@@ -808,10 +808,11 @@ INLINE void
}
/* Extract A's pointer value, assuming A's Lisp type is TYPE and the
- extracted pointer's type is CTYPE *. */
-
-#define XUNTAG(a, type, ctype) ((ctype *) \
- ((char *) XLP (a) - LISP_WORD_TAG (type)))
+ extracted pointer's type is CTYPE *. When !USE_LSB_TAG this simply
+ extracts A's low-order bits, as (uintptr_t) LISP_WORD_TAG (type) is
+ always zero then. */
+#define XUNTAG(a, type, ctype) \
+ ((ctype *) ((uintptr_t) XLP (a) - (uintptr_t) LISP_WORD_TAG (type)))
/* A forwarding pointer to a value. It uses a generic pointer to
avoid alignment bugs that could occur if it used a pointer to a
@@ -918,20 +919,11 @@ verify (GCALIGNED (struct Lisp_Symbol));
#define DEFUN_ARGS_8 (Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, \
Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object)
-/* untagged_ptr represents a pointer before tagging, and Lisp_Word_tag
- contains a possibly-shifted tag to be added to an untagged_ptr to
- convert it to a Lisp_Word. */
+/* Lisp_Word_tag is big enough for a possibly-shifted tag, to be
+ added to a pointer value for conversion to a Lisp_Word. */
#if LISP_WORDS_ARE_POINTERS
-/* untagged_ptr is a pointer so that the compiler knows that TAG_PTR
- yields a pointer. It is char * so that adding a tag uses simple
- machine addition. */
-typedef char *untagged_ptr;
typedef uintptr_t Lisp_Word_tag;
#else
-/* untagged_ptr is an unsigned integer instead of a pointer, so that
- it can be added to the possibly-wider Lisp_Word_tag type without
- losing information. */
-typedef uintptr_t untagged_ptr;
typedef EMACS_UINT Lisp_Word_tag;
#endif
@@ -941,7 +933,7 @@ typedef EMACS_UINT Lisp_Word_tag;
/* An initializer for a Lisp_Object that contains TAG along with PTR. */
#define TAG_PTR(tag, ptr) \
- LISP_INITIALLY ((Lisp_Word) ((untagged_ptr) (ptr) + LISP_WORD_TAG (tag)))
+ LISP_INITIALLY ((Lisp_Word) ((uintptr_t) (ptr) + LISP_WORD_TAG (tag)))
/* LISPSYM_INITIALLY (Qfoo) is equivalent to Qfoo except it is
designed for use as an initializer, even for a constant initializer. */
@@ -994,25 +986,35 @@ typedef EMACS_UINT Lisp_Word_tag;
number of members has been reduced to one. */
union vectorlike_header
{
- /* The main member contains various pieces of information:
- - The MSB (ARRAY_MARK_FLAG) holds the gcmarkbit.
- - The next bit (PSEUDOVECTOR_FLAG) indicates whether this is a plain
- vector (0) or a pseudovector (1).
- - If PSEUDOVECTOR_FLAG is 0, the rest holds the size (number
- of slots) of the vector.
- - If PSEUDOVECTOR_FLAG is 1, the rest is subdivided into three fields:
- - a) pseudovector subtype held in PVEC_TYPE_MASK field;
- - b) number of Lisp_Objects slots at the beginning of the object
- held in PSEUDOVECTOR_SIZE_MASK field. These objects are always
- traced by the GC;
- - c) size of the rest fields held in PSEUDOVECTOR_REST_MASK and
- measured in word_size units. Rest fields may also include
- Lisp_Objects, but these objects usually needs some special treatment
- during GC.
- There are some exceptions. For PVEC_FREE, b) is always zero. For
- PVEC_BOOL_VECTOR and PVEC_SUBR, both b) and c) are always zero.
- Current layout limits the pseudovectors to 63 PVEC_xxx subtypes,
- 4095 Lisp_Objects in GC-ed area and 4095 word-sized other slots. */
+ /* The `size' header word, W bits wide, has one of two forms
+ discriminated by the second-highest bit (PSEUDOVECTOR_FLAG):
+
+ 1 1 W-2
+ +---+---+-------------------------------------+
+ | M | 0 | SIZE | vector
+ +---+---+-------------------------------------+
+
+ 1 1 W-32 6 12 12
+ +---+---+--------+------+----------+----------+
+ | M | 1 | unused | TYPE | RESTSIZE | LISPSIZE | pseudovector
+ +---+---+--------+------+----------+----------+
+
+ M (ARRAY_MARK_FLAG) holds the GC mark bit.
+
+ SIZE is the length (number of slots) of a regular Lisp vector,
+ and the object layout is struct Lisp_Vector.
+
+ TYPE is the pseudovector subtype (enum pvec_type).
+
+ LISPSIZE is the number of Lisp_Object fields at the beginning of the
+ object (after the header). These are always traced by the GC.
+
+ RESTSIZE is the number of fields (in word_size units) following.
+ These are not automatically traced by the GC.
+ For PVEC_BOOL and statically allocated PVEC_SUBR, RESTSIZE is 0.
+ (The block size for PVEC_BOOL is computed from its own size
+ field, to avoid being restricted by the 12-bit RESTSIZE field.)
+ */
ptrdiff_t size;
};
@@ -1076,7 +1078,8 @@ enum pvec_type
PVEC_CHAR_TABLE,
PVEC_SUB_CHAR_TABLE,
PVEC_RECORD,
- PVEC_FONT /* Should be last because it's used for range checking. */
+ PVEC_FONT,
+ PVEC_TAG_MAX = PVEC_FONT /* Keep this equal to the highest member. */
};
enum More_Lisp_Bits
@@ -3230,77 +3233,25 @@ enum maxargs
empty initializers), and is overkill for simple usages like
'Finsert (1, &text);'. */
#define CALLN(f, ...) CALLMANY (f, ((Lisp_Object []) {__VA_ARGS__}))
-
-/* Call function fn on no arguments. */
+#define calln(...) CALLN (Ffuncall, __VA_ARGS__)
+/* Compatibility aliases. */
+#define call1 calln
+#define call2 calln
+#define call3 calln
+#define call4 calln
+#define call5 calln
+#define call6 calln
+#define call7 calln
+#define call8 calln
+
+/* Define 'call0' as a function rather than a CPP macro because we
+ sometimes want to pass it as a first class function. */
INLINE Lisp_Object
call0 (Lisp_Object fn)
{
return Ffuncall (1, &fn);
}
-/* Call function fn with 1 argument arg1. */
-INLINE Lisp_Object
-call1 (Lisp_Object fn, Lisp_Object arg1)
-{
- return CALLN (Ffuncall, fn, arg1);
-}
-
-/* Call function fn with 2 arguments arg1, arg2. */
-INLINE Lisp_Object
-call2 (Lisp_Object fn, Lisp_Object arg1, Lisp_Object arg2)
-{
- return CALLN (Ffuncall, fn, arg1, arg2);
-}
-
-/* Call function fn with 3 arguments arg1, arg2, arg3. */
-INLINE Lisp_Object
-call3 (Lisp_Object fn, Lisp_Object arg1, Lisp_Object arg2, Lisp_Object arg3)
-{
- return CALLN (Ffuncall, fn, arg1, arg2, arg3);
-}
-
-/* Call function fn with 4 arguments arg1, arg2, arg3, arg4. */
-INLINE Lisp_Object
-call4 (Lisp_Object fn, Lisp_Object arg1, Lisp_Object arg2, Lisp_Object arg3,
- Lisp_Object arg4)
-{
- return CALLN (Ffuncall, fn, arg1, arg2, arg3, arg4);
-}
-
-/* Call function fn with 5 arguments arg1, arg2, arg3, arg4, arg5. */
-INLINE Lisp_Object
-call5 (Lisp_Object fn, Lisp_Object arg1, Lisp_Object arg2, Lisp_Object arg3,
- Lisp_Object arg4, Lisp_Object arg5)
-{
- return CALLN (Ffuncall, fn, arg1, arg2, arg3, arg4, arg5);
-}
-
-/* Call function fn with 6 arguments arg1, arg2, arg3, arg4, arg5, arg6. */
-INLINE Lisp_Object
-call6 (Lisp_Object fn, Lisp_Object arg1, Lisp_Object arg2, Lisp_Object arg3,
- Lisp_Object arg4, Lisp_Object arg5, Lisp_Object arg6)
-{
- return CALLN (Ffuncall, fn, arg1, arg2, arg3, arg4, arg5, arg6);
-}
-
-/* Call function fn with 7 arguments arg1, arg2, arg3, arg4, arg5, arg6, arg7. */
-INLINE Lisp_Object
-call7 (Lisp_Object fn, Lisp_Object arg1, Lisp_Object arg2, Lisp_Object arg3,
- Lisp_Object arg4, Lisp_Object arg5, Lisp_Object arg6, Lisp_Object arg7)
-{
- return CALLN (Ffuncall, fn, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
-}
-
-/* Call function fn with 8 arguments arg1, arg2, arg3, arg4, arg5,
- arg6, arg7, arg8. */
-INLINE Lisp_Object
-call8 (Lisp_Object fn, Lisp_Object arg1, Lisp_Object arg2, Lisp_Object arg3,
- Lisp_Object arg4, Lisp_Object arg5, Lisp_Object arg6, Lisp_Object arg7,
- Lisp_Object arg8)
-{
- return CALLN (Ffuncall, fn, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
-}
-
extern void defvar_lisp (struct Lisp_Objfwd const *, char const *);
extern void defvar_lisp_nopro (struct Lisp_Objfwd const *, char const *);
extern void defvar_bool (struct Lisp_Boolfwd const *, char const *);
@@ -4615,9 +4566,10 @@ extern Lisp_Object load_with_autoload_queue
Lisp_Object nosuffix, Lisp_Object must_suffix);
extern Lisp_Object call_debugger (Lisp_Object arg);
extern void init_eval_once (void);
-extern Lisp_Object safe_call (ptrdiff_t, Lisp_Object, ...);
-extern Lisp_Object safe_call1 (Lisp_Object, Lisp_Object);
-extern Lisp_Object safe_call2 (Lisp_Object, Lisp_Object, Lisp_Object);
+extern Lisp_Object safe_funcall (ptrdiff_t, Lisp_Object*);
+#define safe_calln(...) \
+ CALLMANY (safe_funcall, ((Lisp_Object []) {__VA_ARGS__}))
+
extern void init_eval (void);
extern void syms_of_eval (void);
extern void prog_ignore (Lisp_Object);
@@ -4712,7 +4664,6 @@ extern void report_overlay_modification (Lisp_Object, Lisp_Object, bool,
Lisp_Object, Lisp_Object, Lisp_Object);
extern bool overlay_touches_p (ptrdiff_t);
extern Lisp_Object other_buffer_safely (Lisp_Object);
-extern Lisp_Object get_truename_buffer (Lisp_Object);
extern void init_buffer_once (void);
extern void init_buffer (void);
extern void syms_of_buffer (void);
@@ -4880,6 +4831,7 @@ extern void keys_of_keyboard (void);
/* Defined in indent.c. */
extern ptrdiff_t current_column (void);
+extern void line_number_display_width (struct window *, int *, int *);
extern void invalidate_current_column (void);
extern bool indented_beyond_p (ptrdiff_t, ptrdiff_t, EMACS_INT);
extern void syms_of_indent (void);
diff --git a/src/lread.c b/src/lread.c
index 255b6e914d9..e95dafcf222 100644
--- a/src/lread.c
+++ b/src/lread.c
@@ -1,6 +1,6 @@
/* Lisp parsing and input streams.
-Copyright (C) 1985-1989, 1993-1995, 1997-2023 Free Software Foundation,
+Copyright (C) 1985-1989, 1993-1995, 1997-2024 Free Software Foundation,
Inc.
This file is part of GNU Emacs.
diff --git a/src/macfont.h b/src/macfont.h
index 8afba70e711..77426f6f198 100644
--- a/src/macfont.h
+++ b/src/macfont.h
@@ -1,5 +1,5 @@
/* Interface definition for macOS Core text font backend.
- Copyright (C) 2009-2023 Free Software Foundation, Inc.
+ Copyright (C) 2009-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/macfont.m b/src/macfont.m
index 9f9f6f4efaf..8aba440d196 100644
--- a/src/macfont.m
+++ b/src/macfont.m
@@ -1,5 +1,5 @@
/* Font driver on macOS Core text.
- Copyright (C) 2009-2023 Free Software Foundation, Inc.
+ Copyright (C) 2009-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/macros.c b/src/macros.c
index d1541d2817f..5f71bcbd361 100644
--- a/src/macros.c
+++ b/src/macros.c
@@ -1,6 +1,6 @@
/* Keyboard macros.
-Copyright (C) 1985-1986, 1993, 2000-2023 Free Software Foundation, Inc.
+Copyright (C) 1985-1986, 1993, 2000-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/macros.h b/src/macros.h
index a7c42f753b4..51599a29bcd 100644
--- a/src/macros.h
+++ b/src/macros.h
@@ -1,5 +1,5 @@
/* Definitions for keyboard macro interpretation in GNU Emacs.
- Copyright (C) 1985, 2001-2023 Free Software Foundation, Inc.
+ Copyright (C) 1985, 2001-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/marker.c b/src/marker.c
index 7b15cd62f1e..377f6fbe8db 100644
--- a/src/marker.c
+++ b/src/marker.c
@@ -1,5 +1,5 @@
/* Markers: examining, setting and deleting.
- Copyright (C) 1985, 1997-1998, 2001-2023 Free Software Foundation,
+ Copyright (C) 1985, 1997-1998, 2001-2024 Free Software Foundation,
Inc.
This file is part of GNU Emacs.
diff --git a/src/menu.c b/src/menu.c
index 6ab34a16996..de4d0964e9c 100644
--- a/src/menu.c
+++ b/src/menu.c
@@ -1,6 +1,6 @@
/* Platform-independent code for terminal communications.
-Copyright (C) 1986, 1988, 1993-1994, 1996, 1999-2023 Free Software
+Copyright (C) 1986, 1988, 1993-1994, 1996, 1999-2024 Free Software
Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/menu.h b/src/menu.h
index ff27509da44..8b4065dad53 100644
--- a/src/menu.h
+++ b/src/menu.h
@@ -1,5 +1,5 @@
/* Functions to manipulate menus.
- Copyright (C) 2008-2023 Free Software Foundation, Inc.
+ Copyright (C) 2008-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/minibuf.c b/src/minibuf.c
index 58adde1bf66..f4f9da9c3f9 100644
--- a/src/minibuf.c
+++ b/src/minibuf.c
@@ -1,6 +1,6 @@
/* Minibuffer input and completion.
-Copyright (C) 1985-1986, 1993-2023 Free Software Foundation, Inc.
+Copyright (C) 1985-1986, 1993-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
@@ -2320,7 +2320,6 @@ syms_of_minibuf (void)
DEFSYM (Qcurrent_input_method, "current-input-method");
DEFSYM (Qactivate_input_method, "activate-input-method");
- DEFSYM (Qcase_fold_search, "case-fold-search");
DEFSYM (Qmetadata, "metadata");
DEFSYM (Qcycle_sort_function, "cycle-sort-function");
diff --git a/src/module-env-30.h b/src/module-env-30.h
index 6ca03773181..e75210c7f8e 100644
--- a/src/module-env-30.h
+++ b/src/module-env-30.h
@@ -1,3 +1,3 @@
- /* Add module environment functions newly added in Emacs 29 here.
- Before Emacs 29 is released, remove this comment and start
- module-env-30.h on the master branch. */
+ /* Add module environment functions newly added in Emacs 30 here.
+ Before Emacs 30 is released, remove this comment and start
+ module-env-31.h on the master branch. */
diff --git a/src/msdos.c b/src/msdos.c
index 1b7f2d4ae21..bdacda50975 100644
--- a/src/msdos.c
+++ b/src/msdos.c
@@ -1,6 +1,6 @@
/* MS-DOS specific C utilities. -*- coding: cp850 -*-
-Copyright (C) 1993-1997, 1999-2023 Free Software Foundation, Inc.
+Copyright (C) 1993-1997, 1999-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
@@ -2662,7 +2662,7 @@ dos_rawgetc (void)
static Lisp_Object last_mouse_window;
mouse_window = window_from_coordinates
- (SELECTED_FRAME (), mouse_last_x, mouse_last_y, 0, 0, 0);
+ (SELECTED_FRAME (), mouse_last_x, mouse_last_y, 0, 0, 0, 0);
/* A window will be selected only when it is not
selected now, and the last mouse movement event was
not in it. A minibuffer window will be selected iff
diff --git a/src/msdos.h b/src/msdos.h
index 94878d25b35..b245d9ea761 100644
--- a/src/msdos.h
+++ b/src/msdos.h
@@ -1,5 +1,5 @@
/* MS-DOS specific C utilities, interface.
- Copyright (C) 1993, 2001-2023 Free Software Foundation, Inc.
+ Copyright (C) 1993, 2001-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/nsfns.m b/src/nsfns.m
index b846b490ff7..c521140bd68 100644
--- a/src/nsfns.m
+++ b/src/nsfns.m
@@ -1,6 +1,6 @@
/* Functions for the NeXT/Open/GNUstep and macOS window system.
-Copyright (C) 1989, 1992-1994, 2005-2006, 2008-2023 Free Software
+Copyright (C) 1989, 1992-1994, 2005-2006, 2008-2024 Free Software
Foundation, Inc.
This file is part of GNU Emacs.
@@ -641,6 +641,11 @@ ns_change_tab_bar_height (struct frame *f, int height)
leading to the tab bar height being incorrectly set upon the next
call to x_set_font. (bug#59285) */
int lines = height / unit;
+
+ /* Even so, HEIGHT might be less than unit if the tab bar face is
+ not so tall as the frame's font height; which if true lines will
+ be set to 0 and the tab bar will thus vanish. */
+
if (lines == 0 && height != 0)
lines = 1;
@@ -685,6 +690,12 @@ ns_change_tab_bar_height (struct frame *f, int height)
SET_FRAME_GARBAGED (f);
}
+void
+ns_make_frame_key_window (struct frame *f)
+{
+ [[FRAME_NS_VIEW (f) window] makeKeyWindow];
+}
+
/* tabbar support */
static void
ns_set_tab_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
@@ -794,6 +805,26 @@ ns_set_child_frame_border_width (struct frame *f, Lisp_Object arg,
}
static void
+ns_set_inhibit_double_buffering (struct frame *f,
+ Lisp_Object new_value,
+ Lisp_Object old_value)
+{
+#if defined (NS_IMPL_COCOA) && MAC_OS_X_VERSION_MIN_REQUIRED >= 101400
+ if (!EQ (new_value, old_value))
+ {
+ FRAME_DOUBLE_BUFFERED (f) = NILP (new_value);
+
+ /* If the view or layer haven't been created yet this will be a
+ noop. */
+ [(EmacsLayer *)[FRAME_NS_VIEW (f) layer]
+ setDoubleBuffered:FRAME_DOUBLE_BUFFERED (f)];
+
+ SET_FRAME_GARBAGED (f);
+ }
+#endif
+}
+
+static void
ns_set_internal_border_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
{
int old_width = FRAME_INTERNAL_BORDER_WIDTH (f);
@@ -1067,7 +1098,7 @@ frame_parm_handler ns_frame_parm_handlers[] =
gui_set_alpha,
0, /* x_set_sticky */
ns_set_tool_bar_position,
- 0, /* x_set_inhibit_double_buffering */
+ ns_set_inhibit_double_buffering,
ns_set_undecorated,
ns_set_parent_frame,
0, /* x_set_skip_taskbar */
@@ -1455,6 +1486,14 @@ DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
gui_default_parameter (f, parms, Qtitle, Qnil, "title", "Title",
RES_TYPE_STRING);
+#if defined (NS_IMPL_COCOA) && MAC_OS_X_VERSION_MIN_REQUIRED >= 101400
+ tem = gui_display_get_arg (dpyinfo, parms, Qinhibit_double_buffering, NULL, NULL,
+ RES_TYPE_BOOLEAN);
+ FRAME_DOUBLE_BUFFERED (f) = NILP (tem) || EQ (tem, Qunbound);
+ store_frame_param (f, Qinhibit_double_buffering,
+ FRAME_DOUBLE_BUFFERED (f) ? Qnil : Qt);
+#endif
+
parms = get_geometry_from_preferences (dpyinfo, parms);
window_prompting = gui_figure_window_size (f, parms, false, true);
@@ -3953,7 +3992,12 @@ be used as the image of the icon representing the frame. */);
DEFVAR_BOOL ("ns-use-proxy-icon", ns_use_proxy_icon,
doc: /* When non-nil display a proxy icon in the titlebar.
-Default is t. */);
+The proxy icon can be used to drag the file associated with the
+current buffer to other applications, a printer, the desktop, etc., in
+the same way you can from Finder. Note that you might have to disable
+`tool-bar-mode' to see the proxy icon.
+
+The default value is t. */);
ns_use_proxy_icon = true;
DEFVAR_LISP ("x-max-tooltip-size", Vx_max_tooltip_size,
diff --git a/src/nsfont.m b/src/nsfont.m
index eaa5c771457..1205fbe5263 100644
--- a/src/nsfont.m
+++ b/src/nsfont.m
@@ -1,6 +1,6 @@
/* Font back-end driver for the GNUstep window system.
See font.h
- Copyright (C) 2006-2023 Free Software Foundation, Inc.
+ Copyright (C) 2006-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/nsgui.h b/src/nsgui.h
index 469aef13070..de679075d2b 100644
--- a/src/nsgui.h
+++ b/src/nsgui.h
@@ -1,5 +1,5 @@
/* Definitions and headers for communication on the NeXT/Open/GNUstep API.
- Copyright (C) 1995, 2005, 2008-2023 Free Software Foundation, Inc.
+ Copyright (C) 1995, 2005, 2008-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/nsimage.m b/src/nsimage.m
index b33124900bb..ee72d6e0ea1 100644
--- a/src/nsimage.m
+++ b/src/nsimage.m
@@ -1,5 +1,5 @@
/* Image support for the NeXT/Open/GNUstep and macOS window system.
- Copyright (C) 1989, 1992-1994, 2005-2006, 2008-2023 Free Software
+ Copyright (C) 1989, 1992-1994, 2005-2006, 2008-2024 Free Software
Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/nsmenu.m b/src/nsmenu.m
index 2c1f575bdf2..0d21f7d03d3 100644
--- a/src/nsmenu.m
+++ b/src/nsmenu.m
@@ -1,5 +1,5 @@
/* NeXT/Open/GNUstep and macOS Cocoa menu and toolbar module.
- Copyright (C) 2007-2023 Free Software Foundation, Inc.
+ Copyright (C) 2007-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
@@ -477,6 +477,14 @@ set_frame_menubar (struct frame *f, bool deep_p)
call to ns_update_menubar. */
- (void)menuNeedsUpdate: (NSMenu *)menu
{
+
+ /* The context menu is built and then displayed, as opposed to the
+ top-menu, which is partially built and then updated and filled in
+ when it's time to display it. Therefore, we don't call
+ ns_update_menubar if a context menu is active. */
+ if (context_menu_value != 0)
+ return;
+
#ifdef NS_IMPL_GNUSTEP
static int inside = 0;
#endif
@@ -760,6 +768,10 @@ prettify_key (const char *key)
pressure: 0];
context_menu_value = -1;
+#ifdef NS_IMPL_COCOA
+ /* Don't let the system add a Services menu here. */
+ self.allowsContextMenuPlugIns = NO;
+#endif
[NSMenu popUpContextMenu: self withEvent: event forView: view];
retVal = context_menu_value;
context_menu_value = 0;
diff --git a/src/nsselect.m b/src/nsselect.m
index 120bce75bce..bb6679cd2ab 100644
--- a/src/nsselect.m
+++ b/src/nsselect.m
@@ -1,5 +1,5 @@
/* NeXT/Open/GNUstep / macOS Cocoa selection processing for emacs.
- Copyright (C) 1993-1994, 2005-2006, 2008-2023 Free Software
+ Copyright (C) 1993-1994, 2005-2006, 2008-2024 Free Software
Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/nsterm.h b/src/nsterm.h
index b6e5a813a6d..faa839dc1af 100644
--- a/src/nsterm.h
+++ b/src/nsterm.h
@@ -1,6 +1,6 @@
/* -*- objc -*- */
/* Definitions and headers for communication with NeXT/Open/GNUstep API.
- Copyright (C) 1989, 1993, 2005, 2008-2023 Free Software Foundation,
+ Copyright (C) 1989, 1993, 2005, 2008-2024 Free Software Foundation,
Inc.
This file is part of GNU Emacs.
@@ -746,9 +746,11 @@ enum ns_return_frame_mode
CGColorSpaceRef colorSpace;
IOSurfaceRef currentSurface;
CGContextRef context;
+ bool doubleBuffered;
}
-- (id) initWithColorSpace: (CGColorSpaceRef)cs;
+- (id) initWithDoubleBuffered: (bool)db;
- (void) setColorSpace: (CGColorSpaceRef)cs;
+- (void) setDoubleBuffered: (bool)db;
- (CGContextRef) getContext;
@end
#endif
@@ -996,6 +998,11 @@ struct ns_output
/* Non-zero if we are doing an animation, e.g. toggling the tool bar. */
int in_animation;
+#if defined (NS_IMPL_COCOA) && MAC_OS_X_VERSION_MIN_REQUIRED >= 101400
+ /* Is the frame double buffered? */
+ bool double_buffered;
+#endif
+
#ifdef NS_IMPL_GNUSTEP
/* Zero if this is the first time a toolbar has been updated on this
frame. */
@@ -1030,6 +1037,10 @@ struct x_output
#define FRAME_FONT(f) ((f)->output_data.ns->font)
+#if defined (NS_IMPL_COCOA) && MAC_OS_X_VERSION_MIN_REQUIRED >= 101400
+#define FRAME_DOUBLE_BUFFERED(f) ((f)->output_data.ns->double_buffered)
+#endif
+
#ifdef __OBJC__
#define XNS_SCROLL_BAR(vec) ((id) xmint_pointer (vec))
#else
@@ -1169,6 +1180,7 @@ extern void ns_retain_object (void *obj);
extern void *ns_alloc_autorelease_pool (void);
extern void ns_release_autorelease_pool (void *);
extern const char *ns_get_defaults_value (const char *key);
+extern void ns_init_pool (void);
extern void ns_init_locale (void);
/* in nsmenu */
diff --git a/src/nsterm.m b/src/nsterm.m
index 78089906752..f094b145fe3 100644
--- a/src/nsterm.m
+++ b/src/nsterm.m
@@ -1,6 +1,6 @@
/* NeXT/Open/GNUstep / macOS communication module. -*- coding: utf-8 -*-
-Copyright (C) 1989, 1993-1994, 2005-2006, 2008-2023 Free Software
+Copyright (C) 1989, 1993-1994, 2005-2006, 2008-2024 Free Software
Foundation, Inc.
This file is part of GNU Emacs.
@@ -550,33 +550,45 @@ ns_relocate (const char *epath)
void
+ns_init_pool (void)
+/* Initialize the 'outerpool' autorelease pool. This should be called
+ from main before any Objective C code is run. */
+{
+ outerpool = [[NSAutoreleasePool alloc] init];
+}
+
+
+void
ns_init_locale (void)
/* macOS doesn't set any environment variables for the locale when run
from the GUI. Get the locale from the OS and set LANG. */
{
- NSLocale *locale = [NSLocale currentLocale];
-
NSTRACE ("ns_init_locale");
- /* If we were run from a terminal then assume an unset LANG variable
- is intentional and don't try to "fix" it. */
- if (!isatty (STDIN_FILENO))
+ /* Either use LANG, if set, or try to construct LANG from
+ NSLocale. */
+ const char *lang = getenv ("LANG");
+ if (lang == NULL || *lang == 0)
{
- char *oldLocale = setlocale (LC_ALL, NULL);
- /* It seems macOS should probably use UTF-8 everywhere.
- 'localeIdentifier' does not specify the encoding, and I can't
- find any way to get the OS to tell us which encoding to use,
- so hard-code '.UTF-8'. */
- NSString *localeID = [NSString stringWithFormat:@"%@.UTF-8",
- [locale localeIdentifier]];
-
- /* Check the locale ID is valid and if so set LANG, but not if
- it is already set. */
- if (setlocale (LC_ALL, [localeID UTF8String]))
- setenv("LANG", [localeID UTF8String], 0);
+ const NSLocale *locale = [NSLocale currentLocale];
+ const NSString *localeID = [NSString stringWithFormat:@"%@.UTF-8",
+ [locale localeIdentifier]];
+ lang = [localeID UTF8String];
+ }
- setlocale (LC_ALL, oldLocale);
+ /* Check if LANG can be used for initializing the locale. If not,
+ use a default setting. Note that Emacs' main will undo the
+ setlocale below, initializing the locale from the
+ environment. */
+ if (setlocale (LC_ALL, lang) == NULL)
+ {
+ const char *const default_lang = "en_US.UTF-8";
+ fprintf (stderr, "LANG=%s cannot be used, using %s instead.\n",
+ lang, default_lang);
+ lang = default_lang;
}
+
+ setenv ("LANG", lang, 1);
}
@@ -2704,12 +2716,11 @@ ns_scroll_run (struct window *w, struct run *run)
{
NSRect srcRect = NSMakeRect (x, from_y, width, height);
NSPoint dest = NSMakePoint (x, to_y);
- NSRect destRect = NSMakeRect (x, from_y, width, height);
EmacsView *view = FRAME_NS_VIEW (f);
[view copyRect:srcRect to:dest];
-#ifdef NS_IMPL_COCOA
- [view setNeedsDisplayInRect:destRect];
+#if defined (NS_IMPL_COCOA) && MAC_OS_X_VERSION_MAX_ALLOWED < 101400
+ [view setNeedsDisplayInRect:srcRect];
#endif
}
@@ -4561,21 +4572,6 @@ ns_send_appdefined (int value)
/* Only post this event if we haven't already posted one. This will end
the [NXApp run] main loop after having processed all events queued at
this moment. */
-
-#ifdef NS_IMPL_COCOA
- if (! send_appdefined)
- {
- /* OS X 10.10.1 swallows the AppDefined event we are sending ourselves
- in certain situations (rapid incoming events).
- So check if we have one, if not add one. */
- NSEvent *appev = [NSApp nextEventMatchingMask:NSEventMaskApplicationDefined
- untilDate:[NSDate distantPast]
- inMode:NSDefaultRunLoopMode
- dequeue:NO];
- if (! appev) send_appdefined = YES;
- }
-#endif
-
if (send_appdefined)
{
NSEvent *nxev;
@@ -6126,6 +6122,11 @@ ns_term_shutdown (int sig)
*/
+- (BOOL) applicationSupportsSecureRestorableState: (NSApplication *)app
+{
+ return YES;
+}
+
- (void) terminate: (id)sender
{
struct input_event ie;
@@ -7066,13 +7067,9 @@ ns_create_font_panel_buttons (id target, SEL select, SEL cancel_action)
static Lisp_Object
ns_in_echo_area_1 (void *ptr)
{
- Lisp_Object in_echo_area;
- specpdl_ref count;
-
- count = SPECPDL_INDEX ();
+ const specpdl_ref count = SPECPDL_INDEX ();
specbind (Qinhibit_quit, Qt);
- in_echo_area = safe_call (1, Qns_in_echo_area);
-
+ const Lisp_Object in_echo_area = safe_calln (Qns_in_echo_area);
return unbind_to (count, in_echo_area);
}
@@ -7420,7 +7417,7 @@ ns_in_echo_area (void)
int x = lrint (p.x);
int y = lrint (p.y);
- window = window_from_coordinates (emacsframe, x, y, 0, true, true);
+ window = window_from_coordinates (emacsframe, x, y, 0, true, true, true);
tab_bar_p = EQ (window, emacsframe->tab_bar_window);
if (tab_bar_p)
@@ -7526,7 +7523,7 @@ ns_in_echo_area (void)
NSTRACE_MSG ("mouse_autoselect_window");
static Lisp_Object last_mouse_window;
Lisp_Object window
- = window_from_coordinates (emacsframe, pt.x, pt.y, 0, 0, 0);
+ = window_from_coordinates (emacsframe, pt.x, pt.y, 0, 0, 0, 0);
if (WINDOWP (window)
&& !EQ (window, last_mouse_window)
@@ -7922,8 +7919,6 @@ ns_in_echo_area (void)
maximizing_resize = NO;
#endif
- [[EmacsWindow alloc] initWithEmacsFrame:f];
-
#if defined (NS_IMPL_COCOA) && MAC_OS_X_VERSION_MIN_REQUIRED >= 101400
/* These settings mean AppKit will retain the contents of the frame
on resize. Unfortunately it also means the frame will not be
@@ -7934,9 +7929,16 @@ ns_in_echo_area (void)
NSViewLayerContentsRedrawOnSetNeedsDisplay];
[self setLayerContentsPlacement:NSViewLayerContentsPlacementTopLeft];
- /* initWithEmacsFrame can't create the toolbar before the layer is
- set, so have another go at creating the toolbar here. */
- [(EmacsWindow*)[self window] createToolbar:f];
+ [[EmacsWindow alloc] initWithEmacsFrame:f];
+
+ /* Now the NSWindow has been created, we can finish up configuring
+ the layer. */
+ [(EmacsLayer *)[self layer] setColorSpace:
+ [[[self window] colorSpace] CGColorSpace]];
+ [(EmacsLayer *)[self layer] setContentsScale:
+ [[self window] backingScaleFactor]];
+#else
+ [[EmacsWindow alloc] initWithEmacsFrame:f];
#endif
if (ns_drag_types)
@@ -8607,9 +8609,9 @@ ns_in_echo_area (void)
- (CALayer *)makeBackingLayer
{
EmacsLayer *l = [[EmacsLayer alloc]
- initWithColorSpace:[[[self window] colorSpace] CGColorSpace]];
+ initWithDoubleBuffered:FRAME_DOUBLE_BUFFERED (emacsframe)];
+
[l setDelegate:(id)self];
- [l setContentsScale:[[self window] backingScaleFactor]];
return l;
}
@@ -8664,8 +8666,10 @@ ns_in_echo_area (void)
NSHeight (srcRect));
#if defined (NS_IMPL_COCOA) && MAC_OS_X_VERSION_MIN_REQUIRED >= 101400
- double scale = [[self window] backingScaleFactor];
CGContextRef context = [(EmacsLayer *)[self layer] getContext];
+ CGContextFlush (context);
+
+ double scale = [[self window] backingScaleFactor];
int bpp = CGBitmapContextGetBitsPerPixel (context) / 8;
void *pixels = CGBitmapContextGetData (context);
int rowSize = CGBitmapContextGetBytesPerRow (context);
@@ -8830,8 +8834,8 @@ ns_in_echo_area (void)
so call this function instead. */
XSETFRAME (frame, emacsframe);
- safe_call (4, Vns_drag_motion_function, frame,
- make_fixnum (x), make_fixnum (y));
+ safe_calln (Vns_drag_motion_function, frame,
+ make_fixnum (x), make_fixnum (y));
redisplay ();
#endif
@@ -10435,22 +10439,19 @@ nswindow_orderedIndex_sort (id w1, id w2, void *c)
cache. If no free surfaces are found in the cache then a new one
is created. */
-#define CACHE_MAX_SIZE 2
-
-- (id) initWithColorSpace: (CGColorSpaceRef)cs
+- (id) initWithDoubleBuffered: (bool)db
{
- NSTRACE ("[EmacsLayer initWithColorSpace:]");
+ NSTRACE ("[EmacsLayer initWithDoubleBuffered:]");
self = [super init];
if (self)
{
- cache = [[NSMutableArray arrayWithCapacity:CACHE_MAX_SIZE] retain];
- [self setColorSpace:cs];
+ [self setColorSpace:nil];
+ [self setDoubleBuffered:db];
+ cache = [[NSMutableArray arrayWithCapacity:(doubleBuffered ? 2 : 1)] retain];
}
else
- {
- return nil;
- }
+ return nil;
return self;
}
@@ -10467,6 +10468,15 @@ nswindow_orderedIndex_sort (id w1, id w2, void *c)
}
+- (void) setDoubleBuffered: (bool)db
+{
+ if (doubleBuffered != db)
+ [self releaseSurfaces];
+
+ doubleBuffered = db;
+}
+
+
- (void) dealloc
{
[self releaseSurfaces];
@@ -10538,7 +10548,7 @@ nswindow_orderedIndex_sort (id w1, id w2, void *c)
}
}
- if (!surface && [cache count] >= CACHE_MAX_SIZE)
+ if (!surface && [cache count] >= (doubleBuffered ? 2 : 1))
{
/* Just grab the first one off the cache. This may result
in tearing effects. The alternative is to wait for one
@@ -10591,7 +10601,7 @@ nswindow_orderedIndex_sort (id w1, id w2, void *c)
return nil;
}
- CGContextTranslateCTM(context, 0, IOSurfaceGetHeight (currentSurface));
+ CGContextTranslateCTM(context, 0, IOSurfaceGetHeight (surface));
CGContextScaleCTM(context, scale, -scale);
}
@@ -10608,6 +10618,7 @@ nswindow_orderedIndex_sort (id w1, id w2, void *c)
if (!context)
return;
+ CGContextFlush (context);
CGContextRelease (context);
context = NULL;
@@ -10621,26 +10632,18 @@ nswindow_orderedIndex_sort (id w1, id w2, void *c)
{
NSTRACE_WHEN (NSTRACE_GROUP_FOCUS, "[EmacsLayer display]");
- if (context)
+ if (context && context != [[NSGraphicsContext currentContext] CGContext])
{
[self releaseContext];
-#if CACHE_MAX_SIZE == 1
- /* This forces the layer to see the surface as updated. */
+ /* This forces the layer to see the surface as updated even if
+ we replace it with itself. */
[self setContents:nil];
-#endif
-
[self setContents:(id)currentSurface];
/* Put currentSurface back on the end of the cache. */
[cache addObject:(id)currentSurface];
currentSurface = NULL;
-
- /* Schedule a run of getContext so that if Emacs is idle it will
- perform the buffer copy, etc. */
- [self performSelectorOnMainThread:@selector (getContext)
- withObject:nil
- waitUntilDone:NO];
}
}
diff --git a/src/nsxwidget.h b/src/nsxwidget.h
index 2b5596f905e..e26564b3a96 100644
--- a/src/nsxwidget.h
+++ b/src/nsxwidget.h
@@ -1,6 +1,6 @@
/* Header for NS Cocoa part of xwidget and webkit widget.
-Copyright (C) 2019-2023 Free Software Foundation, Inc.
+Copyright (C) 2019-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/nsxwidget.m b/src/nsxwidget.m
index 0e00589bb7f..2d83e8815a2 100644
--- a/src/nsxwidget.m
+++ b/src/nsxwidget.m
@@ -1,6 +1,6 @@
/* NS Cocoa part implementation of xwidget and webkit widget.
-Copyright (C) 2019-2023 Free Software Foundation, Inc.
+Copyright (C) 2019-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/pdumper.c b/src/pdumper.c
index 85adf4147f9..ba318605773 100644
--- a/src/pdumper.c
+++ b/src/pdumper.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2018-2023 Free Software Foundation, Inc.
+/* Copyright (C) 2018-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
@@ -2555,7 +2555,7 @@ static dump_off
dump_vectorlike_generic (struct dump_context *ctx,
const union vectorlike_header *header)
{
-#if CHECK_STRUCTS && !defined (HASH_vectorlike_header_00A5A4BFB2)
+#if CHECK_STRUCTS && !defined (HASH_vectorlike_header_785E52047B)
# error "vectorlike_header changed. See CHECK_STRUCTS comment in config.h."
#endif
const struct Lisp_Vector *v = (const struct Lisp_Vector *) header;
@@ -2747,7 +2747,7 @@ dump_hash_table (struct dump_context *ctx,
static dump_off
dump_buffer (struct dump_context *ctx, const struct buffer *in_buffer)
{
-#if CHECK_STRUCTS && !defined HASH_buffer_6C25F9C3BC
+#if CHECK_STRUCTS && !defined HASH_buffer_EB0A5191C5
# error "buffer changed. See CHECK_STRUCTS comment in config.h."
#endif
struct buffer munged_buffer = *in_buffer;
@@ -2862,8 +2862,10 @@ dump_buffer (struct dump_context *ctx, const struct buffer *in_buffer)
DUMP_FIELD_COPY (out, buffer, long_line_optimizations_p);
if (!itree_empty_p (buffer->overlays))
- /* We haven't implemented the code to dump overlays. */
- emacs_abort ();
+ {
+ /* We haven't implemented the code to dump overlays. */
+ error ("dumping overlays is not yet implemented");
+ }
else
out->overlays = NULL;
@@ -2956,7 +2958,7 @@ dump_native_comp_unit (struct dump_context *ctx,
struct Lisp_Native_Comp_Unit *comp_u)
{
if (!CONSP (comp_u->file))
- error ("Trying to dump non fixed-up eln file");
+ error ("trying to dump non fixed-up eln file");
/* Have function documentation always lazy loaded to optimize load-time. */
comp_u->data_fdoc_v = Qnil;
@@ -2998,11 +3000,12 @@ dump_vectorlike (struct dump_context *ctx,
Lisp_Object lv,
dump_off offset)
{
-#if CHECK_STRUCTS && !defined HASH_pvec_type_5F2059C47E
+#if CHECK_STRUCTS && !defined HASH_pvec_type_D8A254BC70
# error "pvec_type changed. See CHECK_STRUCTS comment in config.h."
#endif
const struct Lisp_Vector *v = XVECTOR (lv);
- switch (PSEUDOVECTOR_TYPE (v))
+ enum pvec_type ptype = PSEUDOVECTOR_TYPE (v);
+ switch (ptype)
{
case PVEC_FONT:
/* There are three kinds of font objects that all use PVEC_FONT,
@@ -3019,76 +3022,60 @@ dump_vectorlike (struct dump_context *ctx,
case PVEC_CHAR_TABLE:
case PVEC_SUB_CHAR_TABLE:
case PVEC_RECORD:
- offset = dump_vectorlike_generic (ctx, &v->header);
- break;
+ return dump_vectorlike_generic (ctx, &v->header);
case PVEC_BOOL_VECTOR:
- offset = dump_bool_vector(ctx, v);
- break;
+ return dump_bool_vector(ctx, v);
case PVEC_HASH_TABLE:
- offset = dump_hash_table (ctx, lv, offset);
- break;
+ return dump_hash_table (ctx, lv, offset);
case PVEC_BUFFER:
- offset = dump_buffer (ctx, XBUFFER (lv));
- break;
+ return dump_buffer (ctx, XBUFFER (lv));
case PVEC_SUBR:
- offset = dump_subr (ctx, XSUBR (lv));
- break;
+ return dump_subr (ctx, XSUBR (lv));
case PVEC_FRAME:
case PVEC_WINDOW:
case PVEC_PROCESS:
case PVEC_TERMINAL:
- offset = dump_nilled_pseudovec (ctx, &v->header);
- break;
+ return dump_nilled_pseudovec (ctx, &v->header);
case PVEC_MARKER:
- offset = dump_marker (ctx, XMARKER (lv));
- break;
+ return dump_marker (ctx, XMARKER (lv));
case PVEC_OVERLAY:
- offset = dump_overlay (ctx, XOVERLAY (lv));
- break;
+ return dump_overlay (ctx, XOVERLAY (lv));
case PVEC_FINALIZER:
- offset = dump_finalizer (ctx, XFINALIZER (lv));
- break;
+ return dump_finalizer (ctx, XFINALIZER (lv));
case PVEC_BIGNUM:
- offset = dump_bignum (ctx, lv);
- break;
-#ifdef HAVE_NATIVE_COMP
+ return dump_bignum (ctx, lv);
case PVEC_NATIVE_COMP_UNIT:
- offset = dump_native_comp_unit (ctx, XNATIVE_COMP_UNIT (lv));
- break;
+#ifdef HAVE_NATIVE_COMP
+ return dump_native_comp_unit (ctx, XNATIVE_COMP_UNIT (lv));
#endif
- case PVEC_WINDOW_CONFIGURATION:
- error_unsupported_dump_object (ctx, lv, "window configuration");
- case PVEC_OTHER:
- error_unsupported_dump_object (ctx, lv, "other?!");
- case PVEC_XWIDGET:
- error_unsupported_dump_object (ctx, lv, "xwidget");
- case PVEC_XWIDGET_VIEW:
- error_unsupported_dump_object (ctx, lv, "xwidget view");
- case PVEC_MISC_PTR:
- case PVEC_USER_PTR:
- error_unsupported_dump_object (ctx, lv, "smuggled pointers");
+ break;
case PVEC_THREAD:
if (main_thread_p (v))
{
eassert (dump_object_emacs_ptr (lv));
return DUMP_OBJECT_IS_RUNTIME_MAGIC;
}
- error_unsupported_dump_object (ctx, lv, "thread");
+ break;
+ case PVEC_WINDOW_CONFIGURATION:
+ case PVEC_OTHER:
+ case PVEC_XWIDGET:
+ case PVEC_XWIDGET_VIEW:
+ case PVEC_MISC_PTR:
+ case PVEC_USER_PTR:
case PVEC_MUTEX:
- error_unsupported_dump_object (ctx, lv, "mutex");
case PVEC_CONDVAR:
- error_unsupported_dump_object (ctx, lv, "condvar");
case PVEC_SQLITE:
- error_unsupported_dump_object (ctx, lv, "sqlite");
case PVEC_MODULE_FUNCTION:
- error_unsupported_dump_object (ctx, lv, "module function");
case PVEC_SYMBOL_WITH_POS:
- error_unsupported_dump_object (ctx, lv, "symbol with pos");
- default:
- error_unsupported_dump_object(ctx, lv, "weird pseudovector");
+ case PVEC_FREE:
+ case PVEC_TS_PARSER:
+ case PVEC_TS_NODE:
+ case PVEC_TS_COMPILED_QUERY:
+ break;
}
-
- return offset;
+ char msg[60];
+ snprintf (msg, sizeof msg, "pseudovector type %d", (int) ptype);
+ error_unsupported_dump_object (ctx, lv, msg);
}
/* Add an object to the dump.
@@ -4090,6 +4077,10 @@ types. */)
if (!NILP (XCDR (Fall_threads ())))
error ("No other Lisp threads can be running when this function is called");
+#ifdef HAVE_NATIVE_COMP
+ CALLN (Ffuncall, intern_c_string ("load--fixup-all-elns"));
+#endif
+
check_pure_size ();
/* Clear out any detritus in memory. */
@@ -5350,11 +5341,11 @@ dump_do_dump_relocation (const uintptr_t dump_base,
dump_ptr (dump_base, reloc_offset);
comp_u->lambda_gc_guard_h = CALLN (Fmake_hash_table, QCtest, Qeq);
if (STRINGP (comp_u->file))
- error ("Trying to load incoherent dumped eln file %s",
+ error ("trying to load incoherent dumped eln file %s",
SSDATA (comp_u->file));
if (!CONSP (comp_u->file))
- error ("Incoherent compilation unit for dump was dumped");
+ error ("incoherent compilation unit for dump was dumped");
/* emacs_execdir is always unibyte, but the file names in
comp_u->file could be multibyte, so we need to encode
diff --git a/src/pdumper.h b/src/pdumper.h
index 44985e26b3e..726805efdac 100644
--- a/src/pdumper.h
+++ b/src/pdumper.h
@@ -1,6 +1,6 @@
/* Header file for the portable dumper.
-Copyright (C) 2016, 2018-2023 Free Software Foundation, Inc.
+Copyright (C) 2016, 2018-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/pgtkfns.c b/src/pgtkfns.c
index c154d37f47f..f43eed6ad23 100644
--- a/src/pgtkfns.c
+++ b/src/pgtkfns.c
@@ -1,6 +1,6 @@
/* Functions for the pure Gtk+-3.
-Copyright (C) 1989, 1992-1994, 2005-2006, 2008-2020, 2022-2023 Free
+Copyright (C) 1989, 1992-1994, 2005-2006, 2008-2020, 2022-2024 Free
Software Foundation, Inc.
This file is part of GNU Emacs.
@@ -475,6 +475,11 @@ pgtk_change_tab_bar_height (struct frame *f, int height)
leading to the tab bar height being incorrectly set upon the next
call to x_set_font. (bug#59285) */
int lines = height / unit;
+
+ /* Even so, HEIGHT might be less than unit if the tab bar face is
+ not so tall as the frame's font height; which if true lines will
+ be set to 0 and the tab bar will thus vanish. */
+
if (lines == 0 && height != 0)
lines = 1;
diff --git a/src/pgtkgui.h b/src/pgtkgui.h
index 4d38e0abc63..c44bd6ceb97 100644
--- a/src/pgtkgui.h
+++ b/src/pgtkgui.h
@@ -1,5 +1,5 @@
/* Definitions and headers for communication on the pure Gtk+3.
- Copyright (C) 1995, 2005, 2008-2023 Free Software Foundation, Inc.
+ Copyright (C) 1995, 2005, 2008-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/pgtkim.c b/src/pgtkim.c
index 9123186cf57..f7a79caa5b3 100644
--- a/src/pgtkim.c
+++ b/src/pgtkim.c
@@ -1,6 +1,6 @@
/* Pure Gtk+-3 communication module.
-Copyright (C) 1989, 1993-1994, 2005-2006, 2008-2023 Free Software
+Copyright (C) 1989, 1993-1994, 2005-2006, 2008-2024 Free Software
Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/pgtkmenu.c b/src/pgtkmenu.c
index 31572f738c4..7666d04b098 100644
--- a/src/pgtkmenu.c
+++ b/src/pgtkmenu.c
@@ -1,5 +1,5 @@
/* Pure GTK3 menu and toolbar module.
- Copyright (C) 2019-2023 Free Software Foundation, Inc.
+ Copyright (C) 2019-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/pgtkselect.c b/src/pgtkselect.c
index 58d5035abed..b0ab15c6069 100644
--- a/src/pgtkselect.c
+++ b/src/pgtkselect.c
@@ -1,5 +1,5 @@
/* Gtk selection processing for emacs.
- Copyright (C) 1993-1994, 2005-2006, 2008-2023 Free Software
+ Copyright (C) 1993-1994, 2005-2006, 2008-2024 Free Software
Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/pgtkterm.c b/src/pgtkterm.c
index a7c687d811d..d938427c75a 100644
--- a/src/pgtkterm.c
+++ b/src/pgtkterm.c
@@ -1,6 +1,6 @@
/* Communication module for window systems using GTK.
-Copyright (C) 1989, 1993-1994, 2005-2006, 2008-2023 Free Software
+Copyright (C) 1989, 1993-1994, 2005-2006, 2008-2024 Free Software
Foundation, Inc.
This file is part of GNU Emacs.
@@ -5894,7 +5894,7 @@ motion_notify_event (GtkWidget *widget, GdkEvent *event,
{
static Lisp_Object last_mouse_window;
Lisp_Object window = window_from_coordinates
- (f, event->motion.x, event->motion.y, 0, false, false);
+ (f, event->motion.x, event->motion.y, 0, false, false, false);
/* A window will be autoselected only when it is not
selected now and the last mouse movement event was
@@ -6047,7 +6047,7 @@ button_event (GtkWidget *widget, GdkEvent *event,
int x = event->button.x;
int y = event->button.y;
- window = window_from_coordinates (f, x, y, 0, true, true);
+ window = window_from_coordinates (f, x, y, 0, true, true, true);
tab_bar_p = EQ (window, f->tab_bar_window);
if (tab_bar_p)
@@ -6259,7 +6259,7 @@ symbol_to_drag_action (Lisp_Object act)
if (NILP (act))
return GDK_ACTION_DEFAULT;
- signal_error ("Invalid drag acction", act);
+ signal_error ("Invalid drag action", act);
}
static Lisp_Object
diff --git a/src/pgtkterm.h b/src/pgtkterm.h
index 069e425fd9c..e8c54dff4d9 100644
--- a/src/pgtkterm.h
+++ b/src/pgtkterm.h
@@ -1,5 +1,5 @@
/* Definitions and headers for communication with pure Gtk+3.
- Copyright (C) 1989, 1993, 2005, 2008-2023 Free Software Foundation,
+ Copyright (C) 1989, 1993, 2005, 2008-2024 Free Software Foundation,
Inc.
This file is part of GNU Emacs.
diff --git a/src/print.c b/src/print.c
index eb20cfb1c47..26ed52b4653 100644
--- a/src/print.c
+++ b/src/print.c
@@ -1,6 +1,6 @@
/* Lisp object printing and output streams.
-Copyright (C) 1985-2023 Free Software Foundation, Inc.
+Copyright (C) 1985-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
@@ -1094,7 +1094,7 @@ print_error_message (Lisp_Object data, Lisp_Object stream, const char *context,
/* `substitute-command-keys' may bug out, which would lead
to infinite recursion when we're called from
skip_debugger, so ignore errors. */
- Lisp_Object subs = safe_call1 (Qsubstitute_command_keys, errmsg);
+ Lisp_Object subs = safe_calln (Qsubstitute_command_keys, errmsg);
if (!NILP (subs))
errmsg = subs;
}
@@ -1599,76 +1599,69 @@ print_pointer (Lisp_Object printcharfun, char *buf, const char *prefix,
}
#endif
-static bool
-print_vectorlike (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag,
- char *buf)
+static void
+print_bignum (Lisp_Object obj, Lisp_Object printcharfun)
{
- /* First do all the vectorlike types that have a readable syntax. */
- switch (PSEUDOVECTOR_TYPE (XVECTOR (obj)))
- {
- case PVEC_BIGNUM:
- {
- ptrdiff_t size = bignum_bufsize (obj, 10);
- USE_SAFE_ALLOCA;
- char *str = SAFE_ALLOCA (size);
- ptrdiff_t len = bignum_to_c_string (str, size, obj, 10);
- strout (str, len, len, printcharfun);
- SAFE_FREE ();
- }
- return true;
-
- case PVEC_BOOL_VECTOR:
- {
- EMACS_INT size = bool_vector_size (obj);
- ptrdiff_t size_in_bytes = bool_vector_bytes (size);
- ptrdiff_t real_size_in_bytes = size_in_bytes;
- unsigned char *data = bool_vector_uchar_data (obj);
-
- int len = sprintf (buf, "#&%"pI"d\"", size);
- strout (buf, len, len, printcharfun);
+ ptrdiff_t size = bignum_bufsize (obj, 10);
+ USE_SAFE_ALLOCA;
+ char *str = SAFE_ALLOCA (size);
+ ptrdiff_t len = bignum_to_c_string (str, size, obj, 10);
+ strout (str, len, len, printcharfun);
+ SAFE_FREE ();
+}
- /* Don't print more bytes than the specified maximum.
- Negative values of print-length are invalid. Treat them
- like a print-length of nil. */
- if (FIXNATP (Vprint_length)
- && XFIXNAT (Vprint_length) < size_in_bytes)
- size_in_bytes = XFIXNAT (Vprint_length);
+static void
+print_bool_vector (Lisp_Object obj, Lisp_Object printcharfun)
+{
+ EMACS_INT size = bool_vector_size (obj);
+ ptrdiff_t size_in_bytes = bool_vector_bytes (size);
+ ptrdiff_t real_size_in_bytes = size_in_bytes;
+ unsigned char *data = bool_vector_uchar_data (obj);
- for (ptrdiff_t i = 0; i < size_in_bytes; i++)
- {
- maybe_quit ();
- unsigned char c = data[i];
- if (c == '\n' && print_escape_newlines)
- print_c_string ("\\n", printcharfun);
- else if (c == '\f' && print_escape_newlines)
- print_c_string ("\\f", printcharfun);
- else if (c > '\177'
- || (print_escape_control_characters && c_iscntrl (c)))
- {
- /* Use octal escapes to avoid encoding issues. */
- octalout (c, data, i + 1, size_in_bytes, printcharfun);
- }
- else
- {
- if (c == '\"' || c == '\\')
- printchar ('\\', printcharfun);
- printchar (c, printcharfun);
- }
- }
+ char buf[sizeof "#&\"" + INT_STRLEN_BOUND (ptrdiff_t)];
+ int len = sprintf (buf, "#&%"pI"d\"", size);
+ strout (buf, len, len, printcharfun);
- if (size_in_bytes < real_size_in_bytes)
- print_c_string (" ...", printcharfun);
- printchar ('\"', printcharfun);
- }
- return true;
+ /* Don't print more bytes than the specified maximum.
+ Negative values of print-length are invalid. Treat them
+ like a print-length of nil. */
+ if (FIXNATP (Vprint_length)
+ && XFIXNAT (Vprint_length) < size_in_bytes)
+ size_in_bytes = XFIXNAT (Vprint_length);
- default:
- break;
+ for (ptrdiff_t i = 0; i < size_in_bytes; i++)
+ {
+ maybe_quit ();
+ unsigned char c = data[i];
+ if (c == '\n' && print_escape_newlines)
+ print_c_string ("\\n", printcharfun);
+ else if (c == '\f' && print_escape_newlines)
+ print_c_string ("\\f", printcharfun);
+ else if (c > '\177'
+ || (print_escape_control_characters && c_iscntrl (c)))
+ {
+ /* Use octal escapes to avoid encoding issues. */
+ octalout (c, data, i + 1, size_in_bytes, printcharfun);
+ }
+ else
+ {
+ if (c == '\"' || c == '\\')
+ printchar ('\\', printcharfun);
+ printchar (c, printcharfun);
+ }
}
- /* Then do all the pseudovector types that don't have a readable
- syntax. First check whether this is handled by
- `print-unreadable-function'. */
+ if (size_in_bytes < real_size_in_bytes)
+ print_c_string (" ...", printcharfun);
+ printchar ('\"', printcharfun);
+}
+
+/* Print a pseudovector that has no readable syntax. */
+static void
+print_vectorlike_unreadable (Lisp_Object obj, Lisp_Object printcharfun,
+ bool escapeflag, char *buf)
+{
+ /* First check whether this is handled by `print-unreadable-function'. */
if (!NILP (Vprint_unreadable_function)
&& FUNCTIONP (Vprint_unreadable_function))
{
@@ -1697,7 +1690,7 @@ print_vectorlike (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag,
if (STRINGP (result))
print_string (result, printcharfun);
/* It's handled, so stop processing here. */
- return true;
+ return;
}
}
@@ -1718,7 +1711,7 @@ print_vectorlike (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag,
print_string (BVAR (XMARKER (obj)->buffer, name), printcharfun);
}
printchar ('>', printcharfun);
- break;
+ return;
case PVEC_SYMBOL_WITH_POS:
{
@@ -1742,7 +1735,7 @@ print_vectorlike (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag,
printchar ('>', printcharfun);
}
}
- break;
+ return;
case PVEC_OVERLAY:
print_c_string ("#<overlay ", printcharfun);
@@ -1758,7 +1751,7 @@ print_vectorlike (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag,
printcharfun);
}
printchar ('>', printcharfun);
- break;
+ return;
case PVEC_USER_PTR:
{
@@ -1769,14 +1762,14 @@ print_vectorlike (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag,
strout (buf, i, i, printcharfun);
printchar ('>', printcharfun);
}
- break;
+ return;
case PVEC_FINALIZER:
print_c_string ("#<finalizer", printcharfun);
if (NILP (XFINALIZER (obj)->function))
print_c_string (" used", printcharfun);
printchar ('>', printcharfun);
- break;
+ return;
case PVEC_MISC_PTR:
{
@@ -1785,7 +1778,7 @@ print_vectorlike (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag,
int i = sprintf (buf, "#<ptr %p>", xmint_pointer (obj));
strout (buf, i, i, printcharfun);
}
- break;
+ return;
case PVEC_PROCESS:
if (escapeflag)
@@ -1796,13 +1789,13 @@ print_vectorlike (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag,
}
else
print_string (XPROCESS (obj)->name, printcharfun);
- break;
+ return;
case PVEC_SUBR:
print_c_string ("#<subr ", printcharfun);
print_c_string (XSUBR (obj)->symbol_name, printcharfun);
printchar ('>', printcharfun);
- break;
+ return;
case PVEC_XWIDGET:
#ifdef HAVE_XWIDGETS
@@ -1822,15 +1815,15 @@ print_vectorlike (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag,
#endif
strout (buf, len, len, printcharfun);
}
- break;
+ return;
}
-#else
- emacs_abort ();
#endif
+ break;
+
case PVEC_XWIDGET_VIEW:
print_c_string ("#<xwidget view", printcharfun);
printchar ('>', printcharfun);
- break;
+ return;
case PVEC_WINDOW:
{
@@ -1845,7 +1838,7 @@ print_vectorlike (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag,
}
printchar ('>', printcharfun);
}
- break;
+ return;
case PVEC_TERMINAL:
{
@@ -1859,7 +1852,7 @@ print_vectorlike (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag,
}
printchar ('>', printcharfun);
}
- break;
+ return;
case PVEC_BUFFER:
if (!BUFFER_LIVE_P (XBUFFER (obj)))
@@ -1872,11 +1865,11 @@ print_vectorlike (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag,
}
else
print_string (BVAR (XBUFFER (obj), name), printcharfun);
- break;
+ return;
case PVEC_WINDOW_CONFIGURATION:
print_c_string ("#<window-configuration>", printcharfun);
- break;
+ return;
case PVEC_FRAME:
{
@@ -1900,7 +1893,7 @@ print_vectorlike (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag,
int len = sprintf (buf, " %p>", ptr);
strout (buf, len, len, printcharfun);
}
- break;
+ return;
case PVEC_FONT:
{
@@ -1933,7 +1926,7 @@ print_vectorlike (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag,
}
printchar ('>', printcharfun);
}
- break;
+ return;
case PVEC_THREAD:
print_c_string ("#<thread ", printcharfun);
@@ -1946,7 +1939,7 @@ print_vectorlike (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag,
strout (buf, len, len, printcharfun);
}
printchar ('>', printcharfun);
- break;
+ return;
case PVEC_MUTEX:
print_c_string ("#<mutex ", printcharfun);
@@ -1959,7 +1952,7 @@ print_vectorlike (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag,
strout (buf, len, len, printcharfun);
}
printchar ('>', printcharfun);
- break;
+ return;
case PVEC_CONDVAR:
print_c_string ("#<condvar ", printcharfun);
@@ -1972,10 +1965,10 @@ print_vectorlike (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag,
strout (buf, len, len, printcharfun);
}
printchar ('>', printcharfun);
- break;
+ return;
-#ifdef HAVE_MODULES
case PVEC_MODULE_FUNCTION:
+#ifdef HAVE_MODULES
{
print_c_string ("#<module function ", printcharfun);
const struct Lisp_Module_Function *function = XMODULE_FUNCTION (obj);
@@ -2000,39 +1993,46 @@ print_vectorlike (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag,
}
printchar ('>', printcharfun);
+ return;
}
- break;
#endif
-#ifdef HAVE_NATIVE_COMP
+ break;
+
case PVEC_NATIVE_COMP_UNIT:
+#ifdef HAVE_NATIVE_COMP
{
struct Lisp_Native_Comp_Unit *cu = XNATIVE_COMP_UNIT (obj);
print_c_string ("#<native compilation unit: ", printcharfun);
- print_string (cu->file, printcharfun);
+ print_object (cu->file, printcharfun, escapeflag);
printchar (' ', printcharfun);
print_object (cu->optimize_qualities, printcharfun, escapeflag);
printchar ('>', printcharfun);
+ return;
}
- break;
#endif
+ break;
-#ifdef HAVE_TREE_SITTER
case PVEC_TS_PARSER:
+#ifdef HAVE_TREE_SITTER
print_c_string ("#<treesit-parser for ", printcharfun);
Lisp_Object language = XTS_PARSER (obj)->language_symbol;
/* No need to print the buffer because it's not that useful: we
usually know which buffer a parser belongs to. */
print_string (Fsymbol_name (language), printcharfun);
printchar ('>', printcharfun);
+ return;
+#endif
break;
+
case PVEC_TS_NODE:
+#ifdef HAVE_TREE_SITTER
/* Prints #<treesit-node (identifier) in 12-15> or
#<treesit-node "keyword" in 28-31>. */
print_c_string ("#<treesit-node", printcharfun);
if (!treesit_node_uptodate_p (obj))
{
print_c_string ("-outdated>", printcharfun);
- break;
+ return;
}
printchar (' ', printcharfun);
/* Now the node must be up-to-date, and calling functions like
@@ -2053,11 +2053,16 @@ print_vectorlike (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag,
printchar ('-', printcharfun);
print_object (Ftreesit_node_end (obj), printcharfun, escapeflag);
printchar ('>', printcharfun);
+ return;
+#endif
break;
+
case PVEC_TS_COMPILED_QUERY:
+#ifdef HAVE_TREE_SITTER
print_c_string ("#<treesit-compiled-query>", printcharfun);
- break;
+ return;
#endif
+ break;
case PVEC_SQLITE:
{
@@ -2073,13 +2078,23 @@ print_vectorlike (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag,
print_c_string (XSQLITE (obj)->name, printcharfun);
printchar ('>', printcharfun);
}
- break;
+ return;
- default:
- emacs_abort ();
+ /* Types handled earlier. */
+ case PVEC_NORMAL_VECTOR:
+ case PVEC_RECORD:
+ case PVEC_COMPILED:
+ case PVEC_CHAR_TABLE:
+ case PVEC_SUB_CHAR_TABLE:
+ case PVEC_HASH_TABLE:
+ case PVEC_BIGNUM:
+ case PVEC_BOOL_VECTOR:
+ /* Impossible cases. */
+ case PVEC_FREE:
+ case PVEC_OTHER:
+ break;
}
-
- return true;
+ emacs_abort ();
}
static char
@@ -2523,29 +2538,21 @@ print_object (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag)
switch (PSEUDOVECTOR_TYPE (XVECTOR (obj)))
{
case PVEC_NORMAL_VECTOR:
- {
- print_stack_push_vector ("[", "]", obj, 0, ASIZE (obj),
- printcharfun);
- goto next_obj;
- }
+ print_stack_push_vector ("[", "]", obj, 0, ASIZE (obj),
+ printcharfun);
+ goto next_obj;
case PVEC_RECORD:
- {
- print_stack_push_vector ("#s(", ")", obj, 0, PVSIZE (obj),
- printcharfun);
- goto next_obj;
- }
+ print_stack_push_vector ("#s(", ")", obj, 0, PVSIZE (obj),
+ printcharfun);
+ goto next_obj;
case PVEC_COMPILED:
- {
- print_stack_push_vector ("#[", "]", obj, 0, PVSIZE (obj),
- printcharfun);
- goto next_obj;
- }
+ print_stack_push_vector ("#[", "]", obj, 0, PVSIZE (obj),
+ printcharfun);
+ goto next_obj;
case PVEC_CHAR_TABLE:
- {
- print_stack_push_vector ("#^[", "]", obj, 0, PVSIZE (obj),
- printcharfun);
- goto next_obj;
- }
+ print_stack_push_vector ("#^[", "]", obj, 0, PVSIZE (obj),
+ printcharfun);
+ goto next_obj;
case PVEC_SUB_CHAR_TABLE:
{
/* Make each lowest sub_char_table start a new line.
@@ -2614,30 +2621,22 @@ print_object (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag)
goto next_obj;
}
+ case PVEC_BIGNUM:
+ print_bignum (obj, printcharfun);
+ break;
+
+ case PVEC_BOOL_VECTOR:
+ print_bool_vector (obj, printcharfun);
+ break;
+
default:
+ print_vectorlike_unreadable (obj, printcharfun, escapeflag, buf);
break;
}
-
- if (print_vectorlike (obj, printcharfun, escapeflag, buf))
break;
- FALLTHROUGH;
default:
- {
- int len;
- /* We're in trouble if this happens!
- Probably should just emacs_abort (). */
- print_c_string ("#<EMACS BUG: INVALID DATATYPE ", printcharfun);
- if (VECTORLIKEP (obj))
- len = sprintf (buf, "(PVEC 0x%08zx)", (size_t) ASIZE (obj));
- else
- len = sprintf (buf, "(0x%02x)", (unsigned) XTYPE (obj));
- strout (buf, len, len, printcharfun);
- print_c_string ((" Save your buffers immediately"
- " and please report this bug>"),
- printcharfun);
- break;
- }
+ emacs_abort ();
}
print_depth--;
diff --git a/src/process.c b/src/process.c
index 08cb810ec13..ddab9ed6c01 100644
--- a/src/process.c
+++ b/src/process.c
@@ -1,6 +1,6 @@
/* Asynchronous subprocess control for GNU Emacs.
-Copyright (C) 1985-1988, 1993-1996, 1998-1999, 2001-2023 Free Software
+Copyright (C) 1985-1988, 1993-1996, 1998-1999, 2001-2024 Free Software
Foundation, Inc.
This file is part of GNU Emacs.
@@ -1279,7 +1279,8 @@ static void
update_process_mark (struct Lisp_Process *p)
{
Lisp_Object buffer = p->buffer;
- if (BUFFERP (buffer))
+ if (BUFFERP (buffer)
+ && XMARKER (p->mark)->buffer != XBUFFER (buffer))
set_marker_both (p->mark, buffer,
BUF_ZV (XBUFFER (buffer)),
BUF_ZV_BYTE (XBUFFER (buffer)));
@@ -2206,8 +2207,14 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
inchannel = p->open_fd[READ_FROM_SUBPROCESS];
forkout = p->open_fd[SUBPROCESS_STDOUT];
-#if defined(GNU_LINUX) && defined(F_SETPIPE_SZ)
- fcntl (inchannel, F_SETPIPE_SZ, read_process_output_max);
+#if defined(F_SETPIPE_SZ) && defined(F_GETPIPE_SZ)
+ /* If they requested larger reads than the default system pipe
+ capacity, try enlarging the capacity to match the request. */
+ if (read_process_output_max > fcntl (inchannel, F_GETPIPE_SZ))
+ {
+ int readmax = clip_to_bounds (1, read_process_output_max, INT_MAX);
+ fcntl (inchannel, F_SETPIPE_SZ, readmax);
+ }
#endif
}
@@ -7205,6 +7212,8 @@ If PROCESS is a process object which contains the property
`remote-pid', or PROCESS is a number and REMOTE is a remote file name,
PROCESS is interpreted as process on the respective remote host, which
will be the process to signal.
+If PROCESS is a string, it is interpreted as process object with the
+respective process name, or as a number.
SIGCODE may be an integer, or a symbol whose name is a signal name. */)
(Lisp_Object process, Lisp_Object sigcode, Lisp_Object remote)
{
@@ -7414,8 +7423,31 @@ child_signal_notify (void)
int fd = child_signal_write_fd;
eassert (0 <= fd);
char dummy = 0;
- if (emacs_write (fd, &dummy, 1) != 1)
- emacs_perror ("writing to child signal FD");
+ /* We used to error out here, like this:
+
+ if (emacs_write (fd, &dummy, 1) != 1)
+ emacs_perror ("writing to child signal FD");
+
+ But this calls `emacs_perror', which in turn invokes a localized
+ version of strerror, which is not reentrant and must not be
+ called within a signal handler:
+
+ __lll_lock_wait_private () at /lib64/libc.so.6
+ malloc () at /lib64/libc.so.6
+ _nl_make_l10nflist.localalias () at /lib64/libc.so.6
+ _nl_find_domain () at /lib64/libc.so.6
+ __dcigettext () at /lib64/libc.so.6
+ strerror_l () at /lib64/libc.so.6
+ emacs_perror (message=message@entry=0x6babc2)
+ child_signal_notify () at process.c:7419
+ handle_child_signal (sig=17) at process.c:7533
+ deliver_process_signal (sig=17, handler=0x6186b0>)
+ <signal handler called> () at /lib64/libc.so.6
+ _int_malloc () at /lib64/libc.so.6
+ in malloc () at /lib64/libc.so.6.
+
+ So we no longer check errors of emacs_write here. */
+ emacs_write (fd, &dummy, 1);
#endif
}
@@ -7488,7 +7520,7 @@ handle_child_signal (int sig)
emacs_unlink is not async signal safe because
deleting files from content providers must proceed
- through Java code. Consequentially, if XCDR (head)
+ through Java code. Consequently, if XCDR (head)
lies on a content provider it will not be removed,
which is a bug. */
unlink (SSDATA (XCDR (head)));
diff --git a/src/process.h b/src/process.h
index bbe4528dc31..3f56b087084 100644
--- a/src/process.h
+++ b/src/process.h
@@ -1,5 +1,5 @@
/* Definitions for asynchronous process control in GNU Emacs.
- Copyright (C) 1985, 1994, 2001-2023 Free Software Foundation, Inc.
+ Copyright (C) 1985, 1994, 2001-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/profiler.c b/src/profiler.c
index 6217071ef9c..243a34872c2 100644
--- a/src/profiler.c
+++ b/src/profiler.c
@@ -1,6 +1,6 @@
/* Profiler implementation.
-Copyright (C) 2012-2023 Free Software Foundation, Inc.
+Copyright (C) 2012-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
@@ -55,6 +55,8 @@ struct profiler_log {
EMACS_INT discarded; /* Samples evicted during table overflow. */
};
+static Lisp_Object export_log (struct profiler_log *);
+
static struct profiler_log
make_log (void)
{
@@ -213,6 +215,23 @@ record_backtrace (struct profiler_log *plog, EMACS_INT count)
/* Sampling profiler. */
+/* Signal handler for sampling profiler. */
+
+static void
+add_sample (struct profiler_log *plog, EMACS_INT count)
+{
+ if (EQ (backtrace_top_function (), QAutomatic_GC)) /* bug#60237 */
+ /* Special case the time-count inside GC because the hash-table
+ code is not prepared to be used while the GC is running.
+ More specifically it uses ASIZE at many places where it does
+ not expect the ARRAY_MARK_FLAG to be set. We could try and
+ harden the hash-table code, but it doesn't seem worth the
+ effort. */
+ plog->gc_count = saturated_add (plog->gc_count, count);
+ else
+ record_backtrace (plog, count);
+}
+
#ifdef PROFILER_CPU_SUPPORT
/* The profiler timer and whether it was properly initialized, if
@@ -235,30 +254,9 @@ static enum profiler_cpu_running
/* Hash-table log of CPU profiler. */
static struct profiler_log cpu;
-/* Hash-table log of Memory profiler. */
-static struct profiler_log memory;
-
/* The current sampling interval in nanoseconds. */
static EMACS_INT current_sampling_interval;
-/* Signal handler for sampling profiler. */
-
-static void
-add_sample (struct profiler_log *plog, EMACS_INT count)
-{
- if (EQ (backtrace_top_function (), QAutomatic_GC)) /* bug#60237 */
- /* Special case the time-count inside GC because the hash-table
- code is not prepared to be used while the GC is running.
- More specifically it uses ASIZE at many places where it does
- not expect the ARRAY_MARK_FLAG to be set. We could try and
- harden the hash-table code, but it doesn't seem worth the
- effort. */
- plog->gc_count = saturated_add (plog->gc_count, count);
- else
- record_backtrace (plog, count);
-}
-
-
static void
handle_profiler_signal (int signal)
{
@@ -421,6 +419,19 @@ DEFUN ("profiler-cpu-running-p",
return profiler_cpu_running ? Qt : Qnil;
}
+DEFUN ("profiler-cpu-log", Fprofiler_cpu_log, Sprofiler_cpu_log,
+ 0, 0, 0,
+ doc: /* Return the current cpu profiler log.
+The log is a hash-table mapping backtraces to counters which represent
+the amount of time spent at those points. Every backtrace is a vector
+of functions, where the last few elements may be nil.
+Before returning, a new log is allocated for future samples. */)
+ (void)
+{
+ return (export_log (&cpu));
+}
+#endif /* PROFILER_CPU_SUPPORT */
+
static Lisp_Object
export_log (struct profiler_log *log)
{
@@ -433,29 +444,21 @@ export_log (struct profiler_log *log)
Fputhash (CALLN (Fvector, QDiscarded_Samples, Qnil),
make_fixnum (log->discarded),
result);
+#ifdef PROFILER_CPU_SUPPORT
/* Here we're making the log visible to Elisp, so it's not safe any
more for our use afterwards since we can't rely on its special
pre-allocated keys anymore. So we have to allocate a new one. */
if (profiler_cpu_running)
*log = make_log ();
+#endif /* PROFILER_CPU_SUPPORT */
return result;
}
-
-DEFUN ("profiler-cpu-log", Fprofiler_cpu_log, Sprofiler_cpu_log,
- 0, 0, 0,
- doc: /* Return the current cpu profiler log.
-The log is a hash-table mapping backtraces to counters which represent
-the amount of time spent at those points. Every backtrace is a vector
-of functions, where the last few elements may be nil.
-Before returning, a new log is allocated for future samples. */)
- (void)
-{
- return (export_log (&cpu));
-}
-#endif /* PROFILER_CPU_SUPPORT */
/* Memory profiler. */
+/* Hash-table log of Memory profiler. */
+static struct profiler_log memory;
+
/* True if memory profiler is running. */
bool profiler_memory_running;
diff --git a/src/puresize.h b/src/puresize.h
index d5463c81a09..ac5d2da30dc 100644
--- a/src/puresize.h
+++ b/src/puresize.h
@@ -1,5 +1,5 @@
/* How much read-only Lisp storage a dumped Emacs needs.
- Copyright (C) 1993, 2001-2023 Free Software Foundation, Inc.
+ Copyright (C) 1993, 2001-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/ralloc.c b/src/ralloc.c
index 1b8d26d1244..5724ae65d33 100644
--- a/src/ralloc.c
+++ b/src/ralloc.c
@@ -1,5 +1,5 @@
/* Block-relocating memory allocator.
- Copyright (C) 1993, 1995, 2000-2023 Free Software Foundation, Inc.
+ Copyright (C) 1993, 1995, 2000-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/regex-emacs.c b/src/regex-emacs.c
index 7e75f0ac597..6aa6f4f9b34 100644
--- a/src/regex-emacs.c
+++ b/src/regex-emacs.c
@@ -1,6 +1,6 @@
/* Emacs regular expression matching and search
- Copyright (C) 1993-2023 Free Software Foundation, Inc.
+ Copyright (C) 1993-2024 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -268,7 +268,9 @@ typedef enum
on_failure_jump,
/* Like on_failure_jump, but pushes a placeholder instead of the
- current string position when executed. */
+ current string position when executed. Upon failure,
+ the current string position is thus not restored.
+ Used only for single-char loops that don't require backtracking. */
on_failure_keep_string_jump,
/* Just like 'on_failure_jump', except that it checks that we
@@ -338,11 +340,12 @@ typedef enum
/* Store NUMBER in two contiguous bytes starting at DESTINATION. */
-#define STORE_NUMBER(destination, number) \
- do { \
- (destination)[0] = (number) & 0377; \
- (destination)[1] = (number) >> 8; \
- } while (false)
+static void
+STORE_NUMBER (unsigned char *destination, int16_t number)
+{
+ (destination)[0] = (number) & 0377;
+ (destination)[1] = (number) >> 8;
+}
/* Same as STORE_NUMBER, except increment DESTINATION to
the byte after where the number is stored. Therefore, DESTINATION
@@ -367,6 +370,12 @@ extract_number (re_char *source)
return leading_byte * 256 + source[0];
}
+static re_char *
+extract_address (re_char *source)
+{
+ return source + 2 + extract_number (source);
+}
+
/* Same as EXTRACT_NUMBER, except increment SOURCE to after the number.
SOURCE must be an lvalue. */
@@ -434,38 +443,27 @@ extract_number_and_incr (re_char **source)
/* If REGEX_EMACS_DEBUG is defined, print many voluminous messages
(if the variable regex_emacs_debug is positive). */
-#ifdef REGEX_EMACS_DEBUG
+#if defined REGEX_EMACS_DEBUG || ENABLE_CHECKING
/* Use standard I/O for debugging. */
# include "sysstdio.h"
-static int regex_emacs_debug = -100000;
-
-# define DEBUG_STATEMENT(e) e
-# define DEBUG_PRINT(...) \
- if (regex_emacs_debug > 0) fprintf (stderr, __VA_ARGS__)
-# define DEBUG_COMPILES_ARGUMENTS
-# define DEBUG_PRINT_COMPILED_PATTERN(p, s, e) \
- if (regex_emacs_debug > 0) print_partial_compiled_pattern (s, e)
-# define DEBUG_PRINT_DOUBLE_STRING(w, s1, sz1, s2, sz2) \
- if (regex_emacs_debug > 0) print_double_string (w, s1, sz1, s2, sz2)
-
static void
-debug_putchar (int c)
+debug_putchar (FILE *dest, int c)
{
if (c >= 32 && c <= 126)
- putc (c, stderr);
+ putc (c, dest);
else
{
unsigned int uc = c;
- fprintf (stderr, "{%02x}", uc);
+ fprintf (dest, "{%02x}", uc);
}
}
/* Print the fastmap in human-readable form. */
static void
-print_fastmap (char *fastmap)
+print_fastmap (FILE *dest, char *fastmap)
{
bool was_a_range = false;
int i = 0;
@@ -475,7 +473,7 @@ print_fastmap (char *fastmap)
if (fastmap[i++])
{
was_a_range = false;
- debug_putchar (i - 1);
+ debug_putchar (dest, i - 1);
while (i < (1 << BYTEWIDTH) && fastmap[i])
{
was_a_range = true;
@@ -483,12 +481,12 @@ print_fastmap (char *fastmap)
}
if (was_a_range)
{
- debug_putchar ('-');
- debug_putchar (i - 1);
+ debug_putchar (dest, '-');
+ debug_putchar (dest, i - 1);
}
}
}
- putc ('\n', stderr);
+ putc ('\n', dest);
}
@@ -496,7 +494,7 @@ print_fastmap (char *fastmap)
the START pointer into it and ending just before the pointer END. */
static void
-print_partial_compiled_pattern (re_char *start, re_char *end)
+print_partial_compiled_pattern (FILE *dest, re_char *start, re_char *end)
{
int mcnt, mcnt2;
re_char *p = start;
@@ -504,50 +502,50 @@ print_partial_compiled_pattern (re_char *start, re_char *end)
if (start == NULL)
{
- fputs ("(null)\n", stderr);
+ fputs ("(null)\n", dest);
return;
}
/* Loop over pattern commands. */
while (p < pend)
{
- fprintf (stderr, "%td:\t", p - start);
+ fprintf (dest, "%td:\t", p - start);
switch ((re_opcode_t) *p++)
{
case no_op:
- fputs ("/no_op", stderr);
+ fputs ("/no_op", dest);
break;
case succeed:
- fputs ("/succeed", stderr);
+ fputs ("/succeed", dest);
break;
case exactn:
mcnt = *p++;
- fprintf (stderr, "/exactn/%d", mcnt);
+ fprintf (dest, "/exactn/%d", mcnt);
do
{
- debug_putchar ('/');
- debug_putchar (*p++);
+ debug_putchar (dest, '/');
+ debug_putchar (dest, *p++);
}
while (--mcnt);
break;
case start_memory:
- fprintf (stderr, "/start_memory/%d", *p++);
+ fprintf (dest, "/start_memory/%d", *p++);
break;
case stop_memory:
- fprintf (stderr, "/stop_memory/%d", *p++);
+ fprintf (dest, "/stop_memory/%d", *p++);
break;
case duplicate:
- fprintf (stderr, "/duplicate/%d", *p++);
+ fprintf (dest, "/duplicate/%d", *p++);
break;
case anychar:
- fputs ("/anychar", stderr);
+ fputs ("/anychar", dest);
break;
case charset:
@@ -558,11 +556,11 @@ print_partial_compiled_pattern (re_char *start, re_char *end)
int length = CHARSET_BITMAP_SIZE (p - 1);
bool has_range_table = CHARSET_RANGE_TABLE_EXISTS_P (p - 1);
- fprintf (stderr, "/charset [%s",
+ fprintf (dest, "/charset [%s",
(re_opcode_t) *(p - 1) == charset_not ? "^" : "");
if (p + (*p & 0x7f) >= pend)
- fputs (" !extends past end of pattern! ", stderr);
+ fputs (" !extends past end of pattern! ", dest);
for (c = 0; c < 256; c++)
if (c / 8 < length
@@ -571,33 +569,33 @@ print_partial_compiled_pattern (re_char *start, re_char *end)
/* Are we starting a range? */
if (last + 1 == c && ! in_range)
{
- debug_putchar ('-');
+ debug_putchar (dest, '-');
in_range = true;
}
/* Have we broken a range? */
else if (last + 1 != c && in_range)
{
- debug_putchar (last);
+ debug_putchar (dest, last);
in_range = false;
}
if (! in_range)
- debug_putchar (c);
+ debug_putchar (dest, c);
last = c;
}
if (in_range)
- debug_putchar (last);
+ debug_putchar (dest, last);
- debug_putchar (']');
+ debug_putchar (dest, ']');
p += 1 + length;
if (has_range_table)
{
int count;
- fputs ("has-range-table", stderr);
+ fputs ("has-range-table", dest);
/* ??? Should print the range table; for now, just skip it. */
p += 2; /* skip range table bits */
@@ -608,160 +606,175 @@ print_partial_compiled_pattern (re_char *start, re_char *end)
break;
case begline:
- fputs ("/begline", stderr);
+ fputs ("/begline", dest);
break;
case endline:
- fputs ("/endline", stderr);
+ fputs ("/endline", dest);
break;
case on_failure_jump:
EXTRACT_NUMBER_AND_INCR (mcnt, p);
- fprintf (stderr, "/on_failure_jump to %td", p + mcnt - start);
+ fprintf (dest, "/on_failure_jump to %td", p + mcnt - start);
break;
case on_failure_keep_string_jump:
EXTRACT_NUMBER_AND_INCR (mcnt, p);
- fprintf (stderr, "/on_failure_keep_string_jump to %td",
+ fprintf (dest, "/on_failure_keep_string_jump to %td",
p + mcnt - start);
break;
case on_failure_jump_nastyloop:
EXTRACT_NUMBER_AND_INCR (mcnt, p);
- fprintf (stderr, "/on_failure_jump_nastyloop to %td",
+ fprintf (dest, "/on_failure_jump_nastyloop to %td",
p + mcnt - start);
break;
case on_failure_jump_loop:
EXTRACT_NUMBER_AND_INCR (mcnt, p);
- fprintf (stderr, "/on_failure_jump_loop to %td",
+ fprintf (dest, "/on_failure_jump_loop to %td",
p + mcnt - start);
break;
case on_failure_jump_smart:
EXTRACT_NUMBER_AND_INCR (mcnt, p);
- fprintf (stderr, "/on_failure_jump_smart to %td",
+ fprintf (dest, "/on_failure_jump_smart to %td",
p + mcnt - start);
break;
case jump:
EXTRACT_NUMBER_AND_INCR (mcnt, p);
- fprintf (stderr, "/jump to %td", p + mcnt - start);
+ fprintf (dest, "/jump to %td", p + mcnt - start);
break;
case succeed_n:
EXTRACT_NUMBER_AND_INCR (mcnt, p);
EXTRACT_NUMBER_AND_INCR (mcnt2, p);
- fprintf (stderr, "/succeed_n to %td, %d times",
+ fprintf (dest, "/succeed_n to %td, %d times",
p - 2 + mcnt - start, mcnt2);
break;
case jump_n:
EXTRACT_NUMBER_AND_INCR (mcnt, p);
EXTRACT_NUMBER_AND_INCR (mcnt2, p);
- fprintf (stderr, "/jump_n to %td, %d times",
+ fprintf (dest, "/jump_n to %td, %d times",
p - 2 + mcnt - start, mcnt2);
break;
case set_number_at:
EXTRACT_NUMBER_AND_INCR (mcnt, p);
EXTRACT_NUMBER_AND_INCR (mcnt2, p);
- fprintf (stderr, "/set_number_at location %td to %d",
+ fprintf (dest, "/set_number_at location %td to %d",
p - 2 + mcnt - start, mcnt2);
break;
case wordbound:
- fputs ("/wordbound", stderr);
+ fputs ("/wordbound", dest);
break;
case notwordbound:
- fputs ("/notwordbound", stderr);
+ fputs ("/notwordbound", dest);
break;
case wordbeg:
- fputs ("/wordbeg", stderr);
+ fputs ("/wordbeg", dest);
break;
case wordend:
- fputs ("/wordend", stderr);
+ fputs ("/wordend", dest);
break;
case symbeg:
- fputs ("/symbeg", stderr);
+ fputs ("/symbeg", dest);
break;
case symend:
- fputs ("/symend", stderr);
+ fputs ("/symend", dest);
break;
case syntaxspec:
- fputs ("/syntaxspec", stderr);
+ fputs ("/syntaxspec", dest);
mcnt = *p++;
- fprintf (stderr, "/%d", mcnt);
+ fprintf (dest, "/%d", mcnt);
break;
case notsyntaxspec:
- fputs ("/notsyntaxspec", stderr);
+ fputs ("/notsyntaxspec", dest);
mcnt = *p++;
- fprintf (stderr, "/%d", mcnt);
+ fprintf (dest, "/%d", mcnt);
break;
case at_dot:
- fputs ("/at_dot", stderr);
+ fputs ("/at_dot", dest);
break;
case categoryspec:
- fputs ("/categoryspec", stderr);
+ fputs ("/categoryspec", dest);
mcnt = *p++;
- fprintf (stderr, "/%d", mcnt);
+ fprintf (dest, "/%d", mcnt);
break;
case notcategoryspec:
- fputs ("/notcategoryspec", stderr);
+ fputs ("/notcategoryspec", dest);
mcnt = *p++;
- fprintf (stderr, "/%d", mcnt);
+ fprintf (dest, "/%d", mcnt);
break;
case begbuf:
- fputs ("/begbuf", stderr);
+ fputs ("/begbuf", dest);
break;
case endbuf:
- fputs ("/endbuf", stderr);
+ fputs ("/endbuf", dest);
break;
default:
- fprintf (stderr, "?%d", *(p-1));
+ fprintf (dest, "?%d", *(p-1));
}
- putc ('\n', stderr);
+ putc ('\n', dest);
}
- fprintf (stderr, "%td:\tend of pattern.\n", p - start);
+ fprintf (dest, "%td:\tend of pattern.\n", p - start);
}
-
-static void
-print_compiled_pattern (struct re_pattern_buffer *bufp)
+void
+print_compiled_pattern (FILE *dest, struct re_pattern_buffer *bufp)
{
+ if (!dest)
+ dest = stderr;
re_char *buffer = bufp->buffer;
- print_partial_compiled_pattern (buffer, buffer + bufp->used);
- fprintf (stderr, "%td bytes used/%td bytes allocated.\n",
+ print_partial_compiled_pattern (dest, buffer, buffer + bufp->used);
+ fprintf (dest, "%td bytes used/%td bytes allocated.\n",
bufp->used, bufp->allocated);
if (bufp->fastmap_accurate && bufp->fastmap)
{
- fputs ("fastmap: ", stderr);
- print_fastmap (bufp->fastmap);
+ fputs ("fastmap: ", dest);
+ print_fastmap (dest, bufp->fastmap);
}
- fprintf (stderr, "re_nsub: %td\t", bufp->re_nsub);
- fprintf (stderr, "regs_alloc: %d\t", bufp->regs_allocated);
- fprintf (stderr, "can_be_null: %d\n", bufp->can_be_null);
+ fprintf (dest, "re_nsub: %td\t", bufp->re_nsub);
+ fprintf (dest, "regs_alloc: %d\t", bufp->regs_allocated);
+ fprintf (dest, "can_be_null: %d\n", bufp->can_be_null);
/* Perhaps we should print the translate table? */
}
+#endif
+
+#ifdef REGEX_EMACS_DEBUG
+
+static int regex_emacs_debug = -100000;
+
+# define DEBUG_STATEMENT(e) e
+# define DEBUG_PRINT(...) \
+ if (regex_emacs_debug > 0) fprintf (stderr, __VA_ARGS__)
+# define DEBUG_COMPILES_ARGUMENTS
+# define DEBUG_PRINT_COMPILED_PATTERN(p, s, e) \
+ if (regex_emacs_debug > 0) print_partial_compiled_pattern (stderr, s, e)
+# define DEBUG_PRINT_DOUBLE_STRING(w, s1, sz1, s2, sz2) \
+ if (regex_emacs_debug > 0) print_double_string (w, s1, sz1, s2, sz2)
static void
print_double_string (re_char *where, re_char *string1, ptrdiff_t size1,
@@ -775,12 +788,12 @@ print_double_string (re_char *where, re_char *string1, ptrdiff_t size1,
if (FIRST_STRING_P (where))
{
for (i = 0; i < string1 + size1 - where; i++)
- debug_putchar (where[i]);
+ debug_putchar (stderr, where[i]);
where = string2;
}
for (i = 0; i < string2 + size2 - where; i++)
- debug_putchar (where[i]);
+ debug_putchar (stderr, where[i]);
}
}
@@ -1166,8 +1179,8 @@ static void insert_op2 (re_opcode_t op, unsigned char *loc,
static bool at_begline_loc_p (re_char *pattern, re_char *p);
static bool at_endline_loc_p (re_char *p, re_char *pend);
static re_char *skip_one_char (re_char *p);
-static int analyze_first (re_char *p, re_char *pend,
- char *fastmap, bool multibyte);
+static bool analyze_first (struct re_pattern_buffer *bufp,
+ re_char *p, re_char *pend, char *fastmap);
/* Fetch the next character in the uncompiled pattern, with no
translation. */
@@ -1760,7 +1773,7 @@ regex_compile (re_char *pattern, ptrdiff_t size,
if (regex_emacs_debug > 0)
{
for (ptrdiff_t debug_count = 0; debug_count < size; debug_count++)
- debug_putchar (pattern[debug_count]);
+ debug_putchar (stderr, pattern[debug_count]);
putc ('\n', stderr);
}
#endif
@@ -1917,18 +1930,28 @@ regex_compile (re_char *pattern, ptrdiff_t size,
ptrdiff_t startoffset = 0;
re_opcode_t ofj =
/* Check if the loop can match the empty string. */
- (simple || !analyze_first (laststart, b, NULL, false))
+ (simple || !analyze_first (bufp, laststart, b, NULL))
? on_failure_jump : on_failure_jump_loop;
eassert (skip_one_char (laststart) <= b);
if (!zero_times_ok && simple)
{ /* Since simple * loops can be made faster by using
- on_failure_keep_string_jump, we turn simple P+
- into PP* if P is simple. */
+ on_failure_keep_string_jump, we turn P+ into PP*
+ if P is simple.
+ We can't use `top: <BODY>; OFJS exit; J top; exit:`
+ because the OFJS needs to be at the beginning
+ so we can replace
+ top: OFJS exit; <BODY>; J top; exit
+ with
+ OFKSJ exit; loop: <BODY>; J loop; exit
+ i.e. a single OFJ at the beginning of the loop
+ rather than once per iteration. */
unsigned char *p1, *p2;
startoffset = b - laststart;
GET_BUFFER_SPACE (startoffset);
p1 = b; p2 = laststart;
+ /* We presume that the code skipped
+ by `skip_one_char` is position-independent. */
while (p2 < p1)
*b++ = *p2++;
zero_times_ok = 1;
@@ -1964,7 +1987,7 @@ regex_compile (re_char *pattern, ptrdiff_t size,
GET_BUFFER_SPACE (7); /* We might use less. */
if (many_times_ok)
{
- bool emptyp = !!analyze_first (laststart, b, NULL, false);
+ bool emptyp = analyze_first (bufp, laststart, b, NULL);
/* The non-greedy multiple match looks like
a repeat..until: we only need a conditional jump
@@ -2670,7 +2693,7 @@ regex_compile (re_char *pattern, ptrdiff_t size,
{
re_compile_fastmap (bufp);
DEBUG_PRINT ("\nCompiled pattern:\n");
- print_compiled_pattern (bufp);
+ print_compiled_pattern (stderr, bufp);
}
regex_emacs_debug--;
#endif
@@ -2799,309 +2822,476 @@ group_in_compile_stack (compile_stack_type compile_stack, regnum_t regnum)
return false;
}
-/* analyze_first.
- If fastmap is non-NULL, go through the pattern and fill fastmap
- with all the possible leading chars. If fastmap is NULL, don't
- bother filling it up (obviously) and only return whether the
- pattern could potentially match the empty string.
-
- Return 1 if p..pend might match the empty string.
- Return 0 if p..pend matches at least one char.
- Return -1 if fastmap was not updated accurately. */
-
-static int
-analyze_first (re_char *p, re_char *pend, char *fastmap, bool multibyte)
+/* Iterate through all the char-matching operations directly reachable from P.
+ This is the inner loop of `forall_firstchar`, which see.
+ LOOP_BEG..LOOP_END delimit the currently "block" of code (we assume
+ the code is made of syntactically nested loops).
+ LOOP_END is blindly assumed to be "safe".
+ To guarantee termination, at each iteration, either LOOP_BEG should
+ get bigger, or it should stay the same and P should get bigger. */
+static bool
+forall_firstchar_1 (re_char *p, re_char *pend,
+ re_char *loop_beg, re_char *loop_end,
+ bool f (const re_char *p, void *arg), void *arg)
{
- int j, k;
- int nbits;
- bool not;
+ eassert (p >= loop_beg);
+ eassert (p <= loop_end);
- /* If all elements for base leading-codes in fastmap is set, this
- flag is set true. */
- bool match_any_multibyte_characters = false;
-
- eassert (p);
-
- /* The loop below works as follows:
- - It has a working-list kept in the PATTERN_STACK and which basically
- starts by only containing a pointer to the first operation.
- - If the opcode we're looking at is a match against some set of
- chars, then we add those chars to the fastmap and go on to the
- next work element from the worklist (done via 'break').
- - If the opcode is a control operator on the other hand, we either
- ignore it (if it's meaningless at this point, such as 'start_memory')
- or execute it (if it's a jump). If the jump has several destinations
- (i.e. 'on_failure_jump'), then we push the other destination onto the
- worklist.
- We guarantee termination by ignoring backward jumps (more or less),
- so that P is monotonically increasing. More to the point, we
- never set P (or push) anything '<= p1'. */
-
- while (p < pend)
+ while (true)
{
- /* P1 is used as a marker of how far back a 'on_failure_jump'
- can go without being ignored. It is normally equal to P
- (which prevents any backward 'on_failure_jump') except right
- after a plain 'jump', to allow patterns such as:
- 0: jump 10
- 3..9: <body>
- 10: on_failure_jump 3
- as used for the *? operator. */
- re_char *p1 = p;
+ re_char *newp1, *newp2, *tmp;
+ re_char *p_orig = p;
+ int offset;
- switch (*p++)
- {
- case succeed:
- return 1;
+ if (p == pend)
+ return false;
+ else if (p == loop_end)
+ return true;
+ else if (p > loop_end)
+ {
+#if ENABLE_CHECKING
+ fprintf (stderr, "FORALL_FIRSTCHAR: Broken assumption1!!\n");
+#endif
+ return false; /* FIXME: Broken assumption about the code shape. */
+ }
+ else
+ switch (*p)
+ {
+ case no_op:
+ p++; continue;
+
+ /* Cases which stop the iteration. */
+ case succeed:
+ case exactn:
+ case charset:
+ case charset_not:
+ case anychar:
+ case syntaxspec:
+ case notsyntaxspec:
+ case categoryspec:
+ case notcategoryspec:
+ return f (p, arg);
+
+ /* Cases which may match the empty string. */
+ case at_dot:
+ case begbuf:
+ case wordbound:
+ case notwordbound:
+ case begline:
+ case endline:
+ case endbuf:
+ case wordbeg:
+ case wordend:
+ case symbeg:
+ case symend:
+ if (f (p, arg))
+ return true;
+ p++;
+ continue;
+
+ case jump:
+ case jump_n:
+ newp1 = extract_address (p + 1);
+ if (newp1 > p)
+ { /* Forward jump, boring. */
+ p = newp1;
+ continue;
+ }
+ switch (*newp1)
+ {
+ case on_failure_jump:
+ case on_failure_keep_string_jump:
+ case on_failure_jump_nastyloop:
+ case on_failure_jump_loop:
+ case on_failure_jump_smart:
+ case succeed_n:
+ newp2 = extract_address (newp1 + 1);
+ goto do_twoway_jump;
+ default:
+ newp2 = loop_end; /* "Safe" choice. */
+ goto do_jump;
+ }
- case duplicate:
- /* If the first character has to match a backreference, that means
- that the group was empty (since it already matched). Since this
- is the only case that interests us here, we can assume that the
- backreference must match the empty string. */
- p++;
- continue;
+ case on_failure_jump:
+ case on_failure_keep_string_jump:
+ case on_failure_jump_nastyloop:
+ case on_failure_jump_loop:
+ case on_failure_jump_smart:
+ newp1 = extract_address (p + 1);
+ newp2 = p + 3;
+ /* For `+` loops, we often have an `on_failure_jump` that skips
+ forward over a subsequent `jump`. Recognize this pattern
+ since that subsequent `jump` is the one that jumps to the
+ loop-entry. */
+ newp2 = ((re_opcode_t) *newp2 == jump)
+ ? extract_address (newp2 + 1) : newp2;
+
+ do_twoway_jump:
+ /* We have to check that both destinations are safe.
+ Arrange for `newp1` to be the smaller of the two. */
+ if (newp1 > newp2)
+ (tmp = newp1, newp1 = newp2, newp2 = tmp);
+
+ if (newp2 <= p_orig) /* Both destinations go backward! */
+ {
+#if ENABLE_CHECKING
+ fprintf (stderr, "FORALL_FIRSTCHAR: Broken assumption2!!\n");
+#endif
+ return false;
+ }
+ if (!forall_firstchar_1 (newp2, pend, loop_beg, loop_end, f, arg))
+ return false;
- /* Following are the cases which match a character. These end
- with 'break'. */
+ do_jump:
+ eassert (newp2 <= loop_end);
+ if (newp1 <= p_orig)
+ {
+ if (newp1 < loop_beg)
+ {
+#if ENABLE_CHECKING
+ fprintf (stderr, "FORALL_FIRSTCHAR: Broken assumption3!!\n");
+#endif
+ return false;
+ }
+ else if (newp1 == loop_beg)
+ /* If we jump backward to the entry point of the current loop
+ it means it's a zero-length cycle through that loop;
+ this cycle itself does not break safety. */
+ return true;
+ else
+ /* We jump backward to a new loop, nested within the current
+ one. `newp1` is the entry point and `newp2` the exit of
+ that inner loop. */
+ /* `p` gets smaller, but termination is still ensured because
+ `loop_beg` gets bigger. */
+ (loop_beg = newp1, loop_end = newp2);
+ }
+ p = newp1;
+ continue;
+
+ case succeed_n:
+ newp1 = extract_address (p + 1);
+ newp2 = p + 5; /* Skip the two bytes containing the count. */
+ goto do_twoway_jump;
+
+ case set_number_at:
+ offset = extract_number (p + 1);
+ DEBUG_STATEMENT (eassert (extract_number (p + 3)));
+ /* If we're setting the counter of an immediately following
+ `succeed_n`, then this next execution of `succeed_n` will do
+ nothing but decrement its counter and "fall through".
+ So we do the fall through here to avoid considering the
+ "on failure" part of the `succeed_n` which should only be
+ considered when coming from the `jump(_n)` at the end of
+ the loop. */
+ p += (offset == 5 && p[5] == succeed_n) ? 10 : 5;
+ continue;
+
+ case start_memory:
+ case stop_memory:
+ p += 2;
+ continue;
+
+ /* This could match the empty string, so we may need to continue,
+ but in most cases, this can match "anything", so we should
+ return `false` unless told otherwise. */
+ case duplicate:
+ if (!f (p, arg))
+ return false;
+ p += 2;
+ continue;
+
+ default:
+ abort (); /* We have listed all the cases. */
+ }
+ }
+}
- case exactn:
- if (fastmap)
- {
- /* If multibyte is nonzero, the first byte of each
- character is an ASCII or a leading code. Otherwise,
- each byte is a character. Thus, this works in both
- cases. */
- fastmap[p[1]] = 1;
- if (multibyte)
- {
- /* Cover the case of matching a raw char in a
- multibyte regexp against unibyte. */
- if (CHAR_BYTE8_HEAD_P (p[1]))
- fastmap[CHAR_TO_BYTE8 (STRING_CHAR (p + 1))] = 1;
- }
- else
- {
- /* For the case of matching this unibyte regex
- against multibyte, we must set a leading code of
- the corresponding multibyte character. */
- int c = RE_CHAR_TO_MULTIBYTE (p[1]);
+/* Iterate through all the char-matching operations directly reachable from P.
+ Return true if P is "safe", meaning that PEND cannot be reached directly
+ from P and all calls to F returned true.
+ Return false if PEND *may* be directly reachable from P or if one of
+ the calls to F returned false.
+ PEND can be NULL (and hence never reachable).
+
+ Call `F (POS, ARG)` for every POS directly reachable from P,
+ before reaching PEND, where POS is the position of a char-matching
+ operation (`exactn`, `charset`, ...).
+
+ For operations that match the empty string (`wordbeg`, ...), if F
+ returns true we stop going down that path immediately but if it returns
+ false we don't consider it as a failure and we simply look for the
+ next char-matching operations on that path.
+ For `duplicate`, it is the reverse: a false is an immediate failure
+ whereas a true just lets the analysis continue with the rest of the path.
+
+ This function can be used while building the bytecode (in which case
+ you should pass NULL for bufp), but if so, P and PEND need to delimit
+ a valid block such that there is not jump to a location outside
+ of [P...PEND]. */
+static bool
+forall_firstchar (struct re_pattern_buffer *bufp, re_char *p, re_char *pend,
+ bool f (re_char *p, void *arg), void *arg)
+{
+ eassert (!bufp || bufp->used);
+ eassert (pend || bufp->used);
+ return forall_firstchar_1 (p, pend,
+ bufp ? bufp->buffer - 1 : p,
+ bufp ? bufp->buffer + bufp->used + 1 : pend,
+ f, arg);
+}
- fastmap[CHAR_LEADING_CODE (c)] = 1;
- }
- }
- break;
+struct anafirst_data {
+ bool multibyte;
+ char *fastmap;
+ bool match_any_multibyte_characters;
+};
+static bool
+analyze_first_fastmap (const re_char *p, void *arg)
+{
+ struct anafirst_data *data = arg;
- case anychar:
- /* We could put all the chars except for \n (and maybe \0)
- but we don't bother since it is generally not worth it. */
- if (!fastmap) break;
- return -1;
+ int j, k;
+ int nbits;
+ bool not;
+ switch (*p)
+ {
+ case succeed:
+ return false;
- case charset_not:
- if (!fastmap) break;
- {
- /* Chars beyond end of bitmap are possible matches. */
- for (j = CHARSET_BITMAP_SIZE (&p[-1]) * BYTEWIDTH;
- j < (1 << BYTEWIDTH); j++)
- fastmap[j] = 1;
- }
- FALLTHROUGH;
- case charset:
- if (!fastmap) break;
- not = (re_opcode_t) *(p - 1) == charset_not;
- nbits = CHARSET_BITMAP_SIZE (&p[-1]) * BYTEWIDTH;
- p++;
- for (j = 0; j < nbits; j++)
- if (!!(p[j / BYTEWIDTH] & (1 << (j % BYTEWIDTH))) ^ not)
- fastmap[j] = 1;
-
- /* To match raw bytes (in the 80..ff range) against multibyte
- strings, add their leading bytes to the fastmap. */
- for (j = 0x80; j < nbits; j++)
- if (!!(p[j / BYTEWIDTH] & (1 << (j % BYTEWIDTH))) ^ not)
- fastmap[CHAR_LEADING_CODE (BYTE8_TO_CHAR (j))] = 1;
-
- if (/* Any leading code can possibly start a character
- which doesn't match the specified set of characters. */
- not
- ||
- /* If we can match a character class, we can match any
- multibyte characters. */
- (CHARSET_RANGE_TABLE_EXISTS_P (&p[-2])
- && CHARSET_RANGE_TABLE_BITS (&p[-2]) != 0))
+ case duplicate:
+ /* If the first character has to match a backreference, that means
+ that the group was empty (since it already matched). Since this
+ is the only case that interests us here, we can assume that the
+ backreference must match the empty string and we need to
+ build the fastmap from the rest of the path. */
+ return true;
- {
- if (match_any_multibyte_characters == false)
- {
- for (j = MIN_MULTIBYTE_LEADING_CODE;
- j <= MAX_MULTIBYTE_LEADING_CODE; j++)
- fastmap[j] = 1;
- match_any_multibyte_characters = true;
- }
- }
+ /* Following are the cases which match a character. These end
+ with 'break'. */
- else if (!not && CHARSET_RANGE_TABLE_EXISTS_P (&p[-2])
- && match_any_multibyte_characters == false)
- {
- /* Set fastmap[I] to 1 where I is a leading code of each
- multibyte character in the range table. */
- int c, count;
- unsigned char lc1, lc2;
-
- /* Make P points the range table. '+ 2' is to skip flag
- bits for a character class. */
- p += CHARSET_BITMAP_SIZE (&p[-2]) + 2;
-
- /* Extract the number of ranges in range table into COUNT. */
- EXTRACT_NUMBER_AND_INCR (count, p);
- for (; count > 0; count--, p += 3)
- {
- /* Extract the start and end of each range. */
- EXTRACT_CHARACTER (c, p);
- lc1 = CHAR_LEADING_CODE (c);
- p += 3;
- EXTRACT_CHARACTER (c, p);
- lc2 = CHAR_LEADING_CODE (c);
- for (j = lc1; j <= lc2; j++)
- fastmap[j] = 1;
- }
- }
- break;
+ case exactn:
+ p++;
+ /* If multibyte is nonzero, the first byte of each
+ character is an ASCII or a leading code. Otherwise,
+ each byte is a character. Thus, this works in both
+ cases. */
+ data->fastmap[p[1]] = 1;
+ if (data->multibyte)
+ {
+ /* Cover the case of matching a raw char in a
+ multibyte regexp against unibyte. */
+ if (CHAR_BYTE8_HEAD_P (p[1]))
+ data->fastmap[CHAR_TO_BYTE8 (STRING_CHAR (p + 1))] = 1;
+ }
+ else
+ {
+ /* For the case of matching this unibyte regex
+ against multibyte, we must set a leading code of
+ the corresponding multibyte character. */
+ int c = RE_CHAR_TO_MULTIBYTE (p[1]);
- case syntaxspec:
- case notsyntaxspec:
- if (!fastmap) break;
- /* This match depends on text properties. These end with
- aborting optimizations. */
- return -1;
+ data->fastmap[CHAR_LEADING_CODE (c)] = 1;
+ }
+ return true;
- case categoryspec:
- case notcategoryspec:
- if (!fastmap) break;
- not = (re_opcode_t)p[-1] == notcategoryspec;
- k = *p++;
- for (j = (1 << BYTEWIDTH); j >= 0; j--)
- if ((CHAR_HAS_CATEGORY (j, k)) ^ not)
- fastmap[j] = 1;
-
- /* Any leading code can possibly start a character which
- has or doesn't has the specified category. */
- if (match_any_multibyte_characters == false)
+ case anychar:
+ /* We could put all the chars except for \n (and maybe \0)
+ but we don't bother since it is generally not worth it. */
+ return false;
+
+ case charset_not:
+ {
+ /* Chars beyond end of bitmap are possible matches. */
+ for (j = CHARSET_BITMAP_SIZE (p) * BYTEWIDTH;
+ j < (1 << BYTEWIDTH); j++)
+ data->fastmap[j] = 1;
+ }
+ FALLTHROUGH;
+ case charset:
+ not = (re_opcode_t) *(p) == charset_not;
+ nbits = CHARSET_BITMAP_SIZE (p) * BYTEWIDTH;
+ p += 2;
+ for (j = 0; j < nbits; j++)
+ if (!!(p[j / BYTEWIDTH] & (1 << (j % BYTEWIDTH))) ^ not)
+ data->fastmap[j] = 1;
+
+ /* To match raw bytes (in the 80..ff range) against multibyte
+ strings, add their leading bytes to the fastmap. */
+ for (j = 0x80; j < nbits; j++)
+ if (!!(p[j / BYTEWIDTH] & (1 << (j % BYTEWIDTH))) ^ not)
+ data->fastmap[CHAR_LEADING_CODE (BYTE8_TO_CHAR (j))] = 1;
+
+ if (/* Any leading code can possibly start a character
+ which doesn't match the specified set of characters. */
+ not
+ ||
+ /* If we can match a character class, we can match any
+ multibyte characters. */
+ (CHARSET_RANGE_TABLE_EXISTS_P (&p[-2])
+ && CHARSET_RANGE_TABLE_BITS (&p[-2]) != 0))
+
+ {
+ if (!data->match_any_multibyte_characters)
{
for (j = MIN_MULTIBYTE_LEADING_CODE;
- j <= MAX_MULTIBYTE_LEADING_CODE; j++)
- fastmap[j] = 1;
- match_any_multibyte_characters = true;
+ j <= MAX_MULTIBYTE_LEADING_CODE; j++)
+ data->fastmap[j] = 1;
+ data->match_any_multibyte_characters = true;
}
- break;
-
- /* All cases after this match the empty string. These end with
- 'continue'. */
-
- case at_dot:
- case no_op:
- case begline:
- case endline:
- case begbuf:
- case endbuf:
- case wordbound:
- case notwordbound:
- case wordbeg:
- case wordend:
- case symbeg:
- case symend:
- continue;
-
+ }
- case jump:
- EXTRACT_NUMBER_AND_INCR (j, p);
- if (j < 0)
- /* Backward jumps can only go back to code that we've already
- visited. 're_compile' should make sure this is true. */
- break;
- p += j;
- switch (*p)
+ else if (!not && CHARSET_RANGE_TABLE_EXISTS_P (&p[-2])
+ && data->match_any_multibyte_characters == false)
+ {
+ /* Set fastmap[I] to 1 where I is a leading code of each
+ multibyte character in the range table. */
+ int c, count;
+ unsigned char lc1, lc2;
+
+ /* Make P points the range table. '+ 2' is to skip flag
+ bits for a character class. */
+ p += CHARSET_BITMAP_SIZE (&p[-2]) + 2;
+
+ /* Extract the number of ranges in range table into COUNT. */
+ EXTRACT_NUMBER_AND_INCR (count, p);
+ for (; count > 0; count--, p += 3)
{
- case on_failure_jump:
- case on_failure_keep_string_jump:
- case on_failure_jump_loop:
- case on_failure_jump_nastyloop:
- case on_failure_jump_smart:
- p++;
- break;
- default:
- continue;
- };
- /* Keep P1 to allow the 'on_failure_jump' we are jumping to
- to jump back to "just after here". */
- FALLTHROUGH;
- case on_failure_jump:
- case on_failure_keep_string_jump:
- case on_failure_jump_nastyloop:
- case on_failure_jump_loop:
- case on_failure_jump_smart:
- EXTRACT_NUMBER_AND_INCR (j, p);
- if (p + j <= p1)
- ; /* Backward jump to be ignored. */
- else
- { /* We have to look down both arms.
- We first go down the "straight" path so as to minimize
- stack usage when going through alternatives. */
- int r = analyze_first (p, pend, fastmap, multibyte);
- if (r) return r;
- p += j;
+ /* Extract the start and end of each range. */
+ EXTRACT_CHARACTER (c, p);
+ lc1 = CHAR_LEADING_CODE (c);
+ p += 3;
+ EXTRACT_CHARACTER (c, p);
+ lc2 = CHAR_LEADING_CODE (c);
+ for (j = lc1; j <= lc2; j++)
+ data->fastmap[j] = 1;
}
- continue;
+ }
+ return true;
+ case syntaxspec:
+ case notsyntaxspec:
+ /* This match depends on text properties. These end with
+ aborting optimizations. */
+ return false;
- case jump_n:
- /* This code simply does not properly handle forward jump_n. */
- DEBUG_STATEMENT (EXTRACT_NUMBER (j, p); eassert (j < 0));
- p += 4;
- /* jump_n can either jump or fall through. The (backward) jump
- case has already been handled, so we only need to look at the
- fallthrough case. */
- continue;
+ case categoryspec:
+ case notcategoryspec:
+ not = (re_opcode_t)p[0] == notcategoryspec;
+ p++;
+ k = *p++;
+ for (j = (1 << BYTEWIDTH); j >= 0; j--)
+ if ((CHAR_HAS_CATEGORY (j, k)) ^ not)
+ data->fastmap[j] = 1;
+
+ /* Any leading code can possibly start a character which
+ has or doesn't has the_malloc_fn specified category. */
+ if (!data->match_any_multibyte_characters)
+ {
+ for (j = MIN_MULTIBYTE_LEADING_CODE;
+ j <= MAX_MULTIBYTE_LEADING_CODE; j++)
+ data->fastmap[j] = 1;
+ data->match_any_multibyte_characters = true;
+ }
+ return true;
- case succeed_n:
- /* If N == 0, it should be an on_failure_jump_loop instead. */
- DEBUG_STATEMENT (EXTRACT_NUMBER (j, p + 2); eassert (j > 0));
- p += 4;
- /* We only care about one iteration of the loop, so we don't
- need to consider the case where this behaves like an
- on_failure_jump. */
- continue;
+ case at_dot:
+ case begbuf:
+ case wordbound:
+ case notwordbound:
+ case begline:
+ case endline:
+ case endbuf:
+ case wordbeg:
+ case wordend:
+ case symbeg:
+ case symend:
+ /* This false doesn't mean failure but rather "not succeeded yet". */
+ return false;
+ default:
+#if ENABLE_CHECKING
+ abort (); /* We have listed all the cases. */
+#endif
+ return false;
+ }
+}
- case set_number_at:
- p += 4;
- continue;
+static bool
+analyze_first_null (const re_char *p, void *arg)
+{
+ switch (*p)
+ {
+ case succeed:
+ /* This is safe: we can't reach `pend` at all from here. */
+ return true;
+ case duplicate:
+ /* Either `duplicate` ends up matching a non-empty string, in which
+ case we're good, or it matches the empty string, in which case we
+ need to continue checking the rest of this path, which is exactly
+ what returning `true` does, here. */
+ return true;
- case start_memory:
- case stop_memory:
- p += 1;
- continue;
+ case exactn:
+ case anychar:
+ case charset_not:
+ case charset:
+ case syntaxspec:
+ case notsyntaxspec:
+ case categoryspec:
+ case notcategoryspec:
+ return true;
+ case at_dot:
+ case begbuf:
+ case wordbound:
+ case notwordbound:
+ case begline:
+ case endline:
+ case endbuf:
+ case wordbeg:
+ case wordend:
+ case symbeg:
+ case symend:
+ /* This false doesn't mean failure but rather "not succeeded yet". */
+ return false;
- default:
- abort (); /* We have listed all the cases. */
- } /* switch *p++ */
+ default:
+#if ENABLE_CHECKING
+ abort (); /* We have listed all the cases. */
+#endif
+ return false;
+ }
+}
- /* Getting here means we have found the possible starting
- characters for one path of the pattern -- and that the empty
- string does not match. We need not follow this path further. */
- return 0;
- } /* while p */
+/* analyze_first.
+ If fastmap is non-NULL, go through the pattern and fill fastmap
+ with all the possible leading chars. If fastmap is NULL, don't
+ bother filling it up (obviously) and only return whether the
+ pattern could potentially match the empty string.
- /* We reached the end without matching anything. */
- return 1;
+ Return false if p matches at least one char before reaching pend.
+ Return true if p..pend might match the empty string
+ or if fastmap was not updated accurately. */
+
+static bool
+analyze_first (struct re_pattern_buffer *bufp,
+ re_char *p, re_char *pend, char *fastmap)
+{
+ eassert (pend);
+ struct anafirst_data data = { bufp ? bufp->multibyte : false,
+ fastmap, false };
+ bool safe = forall_firstchar (bufp->used ? bufp : NULL, p, pend,
+ fastmap ? analyze_first_fastmap
+ : analyze_first_null,
+ &data);
+ return !safe;
+}
-} /* analyze_first */
/* Compute a fastmap for the compiled pattern in BUFP.
A fastmap records which of the (1 << BYTEWIDTH) possible
@@ -3122,7 +3312,6 @@ static void
re_compile_fastmap (struct re_pattern_buffer *bufp)
{
char *fastmap = bufp->fastmap;
- int analysis;
eassert (fastmap && bufp->buffer);
@@ -3131,9 +3320,8 @@ re_compile_fastmap (struct re_pattern_buffer *bufp)
/* FIXME: Is the following assignment correct even when ANALYSIS < 0? */
bufp->fastmap_accurate = 1; /* It will be when we're done. */
- analysis = analyze_first (bufp->buffer, bufp->buffer + bufp->used,
- fastmap, RE_MULTIBYTE_P (bufp));
- bufp->can_be_null = (analysis != 0);
+ bufp->can_be_null = analyze_first (bufp, bufp->buffer,
+ bufp->buffer + bufp->used, fastmap);
} /* re_compile_fastmap */
/* Set REGS to hold NUM_REGS registers, storing them in STARTS and
@@ -3171,7 +3359,7 @@ re_set_registers (struct re_pattern_buffer *bufp, struct re_registers *regs,
/* Searching routines. */
/* Like re_search_2, below, but only one string is specified, and
- doesn't let you say where to stop matching. */
+ doesn't let you say where to stop matching. */
ptrdiff_t
re_search (struct re_pattern_buffer *bufp, const char *string, ptrdiff_t size,
@@ -3548,33 +3736,6 @@ skip_one_char (re_char *p)
}
-/* Jump over non-matching operations. */
-static re_char *
-skip_noops (re_char *p, re_char *pend)
-{
- int mcnt;
- while (p < pend)
- {
- switch (*p)
- {
- case start_memory:
- case stop_memory:
- p += 2; break;
- case no_op:
- p += 1; break;
- case jump:
- p += 1;
- EXTRACT_NUMBER_AND_INCR (mcnt, p);
- p += mcnt;
- break;
- default:
- return p;
- }
- }
- eassert (p == pend);
- return p;
-}
-
/* Test if C matches charset op. *PP points to the charset or charset_not
opcode. When the function finishes, *PP will be advanced past that opcode.
C is character to test (possibly after translations) and CORIG is original
@@ -3643,92 +3804,55 @@ execute_charset (re_char **pp, int c, int corig, bool unibyte,
return not;
}
-/* True if "p1 matches something" implies "p2 fails". */
+/* Case where `p2` points to an `exactn` or `endline`. */
static bool
-mutually_exclusive_p (struct re_pattern_buffer *bufp, re_char *p1,
- re_char *p2)
+mutually_exclusive_exactn (struct re_pattern_buffer *bufp, re_char *p1,
+ re_char *p2)
{
- re_opcode_t op2;
bool multibyte = RE_MULTIBYTE_P (bufp);
- unsigned char *pend = bufp->buffer + bufp->used;
- re_char *p2_orig = p2;
-
- eassert (p1 >= bufp->buffer && p1 < pend
- && p2 >= bufp->buffer && p2 <= pend);
-
- /* Skip over open/close-group commands.
- If what follows this loop is a ...+ construct,
- look at what begins its body, since we will have to
- match at least one of that. */
- p2 = skip_noops (p2, pend);
- /* The same skip can be done for p1, except that this function
- is only used in the case where p1 is a simple match operator. */
- /* p1 = skip_noops (p1, pend); */
+ int c
+ = (re_opcode_t) *p2 == endline ? '\n'
+ : RE_STRING_CHAR (p2 + 2, multibyte);
- eassert (p1 >= bufp->buffer && p1 < pend
- && p2 >= bufp->buffer && p2 <= pend);
-
- op2 = p2 == pend ? succeed : *p2;
-
- switch (op2)
+ if ((re_opcode_t) *p1 == exactn)
{
- case succeed:
- case endbuf:
- /* If we're at the end of the pattern, we can change. */
- if (skip_one_char (p1))
+ if (c != RE_STRING_CHAR (p1 + 2, multibyte))
{
- DEBUG_PRINT (" End of pattern: fast loop.\n");
+ DEBUG_PRINT (" '%c' != '%c' => fast loop.\n", c, p1[2]);
return true;
}
- break;
-
- case endline:
- case exactn:
- {
- int c
- = (re_opcode_t) *p2 == endline ? '\n'
- : RE_STRING_CHAR (p2 + 2, multibyte);
-
- if ((re_opcode_t) *p1 == exactn)
- {
- if (c != RE_STRING_CHAR (p1 + 2, multibyte))
- {
- DEBUG_PRINT (" '%c' != '%c' => fast loop.\n", c, p1[2]);
- return true;
- }
- }
-
- else if ((re_opcode_t) *p1 == charset
- || (re_opcode_t) *p1 == charset_not)
- {
- if (!execute_charset (&p1, c, c, !multibyte || ASCII_CHAR_P (c),
- Qnil))
- {
- DEBUG_PRINT (" No match => fast loop.\n");
- return true;
- }
- }
- else if ((re_opcode_t) *p1 == anychar
- && c == '\n')
- {
- DEBUG_PRINT (" . != \\n => fast loop.\n");
- return true;
- }
- }
- break;
+ }
- case charset:
- {
- if ((re_opcode_t) *p1 == exactn)
- /* Reuse the code above. */
- return mutually_exclusive_p (bufp, p2, p1);
-
- /* It is hard to list up all the character in charset
- P2 if it includes multibyte character. Give up in
- such case. */
- else if (!multibyte || !CHARSET_RANGE_TABLE_EXISTS_P (p2))
+ else if ((re_opcode_t) *p1 == charset
+ || (re_opcode_t) *p1 == charset_not)
+ {
+ if (!execute_charset (&p1, c, c, !multibyte || ASCII_CHAR_P (c),
+ Qnil))
{
- /* Now, we are sure that P2 has no range table.
+ DEBUG_PRINT (" No match => fast loop.\n");
+ return true;
+ }
+ }
+ else if ((re_opcode_t) *p1 == anychar
+ && c == '\n')
+ {
+ DEBUG_PRINT (" . != \\n => fast loop.\n");
+ return true;
+ }
+ return false;
+}
+
+/* Case where `p2` points to an `charset`. */
+static bool
+mutually_exclusive_charset (struct re_pattern_buffer *bufp, re_char *p1,
+ re_char *p2)
+{
+ /* It is hard to list up all the character in charset
+ P2 if it includes multibyte character. Give up in
+ such case. */
+ if (!RE_MULTIBYTE_P (bufp) || !CHARSET_RANGE_TABLE_EXISTS_P (p2))
+ {
+ /* Now, we are sure that P2 has no range table.
So, for the size of bitmap in P2, 'p2[1]' is
enough. But P1 may have range table, so the
size of bitmap table of P1 is extracted by
@@ -3739,113 +3863,161 @@ mutually_exclusive_p (struct re_pattern_buffer *bufp, re_char *p1,
bitmap table. So, in both cases, it is enough to test
only the bitmap table of P1. */
- if ((re_opcode_t) *p1 == charset)
- {
- int idx;
- /* We win if the charset inside the loop
+ if ((re_opcode_t) *p1 == charset)
+ {
+ int idx;
+ /* We win if the charset inside the loop
has no overlap with the one after the loop. */
- for (idx = 0;
- (idx < (int) p2[1]
- && idx < CHARSET_BITMAP_SIZE (p1));
- idx++)
- if ((p2[2 + idx] & p1[2 + idx]) != 0)
- break;
+ for (idx = 0;
+ (idx < (int) p2[1]
+ && idx < CHARSET_BITMAP_SIZE (p1));
+ idx++)
+ if ((p2[2 + idx] & p1[2 + idx]) != 0)
+ break;
- if (idx == p2[1]
- || idx == CHARSET_BITMAP_SIZE (p1))
- {
- DEBUG_PRINT (" No match => fast loop.\n");
- return true;
- }
- }
- else if ((re_opcode_t) *p1 == charset_not)
+ if (idx == p2[1]
+ || idx == CHARSET_BITMAP_SIZE (p1))
{
- int idx;
- /* We win if the charset_not inside the loop lists
+ DEBUG_PRINT (" No match => fast loop.\n");
+ return true;
+ }
+ }
+ else if ((re_opcode_t) *p1 == charset_not)
+ {
+ int idx;
+ /* We win if the charset_not inside the loop lists
every character listed in the charset after. */
- for (idx = 0; idx < (int) p2[1]; idx++)
- if (! (p2[2 + idx] == 0
- || (idx < CHARSET_BITMAP_SIZE (p1)
- && ((p2[2 + idx] & ~ p1[2 + idx]) == 0))))
- break;
+ for (idx = 0; idx < (int) p2[1]; idx++)
+ if (! (p2[2 + idx] == 0
+ || (idx < CHARSET_BITMAP_SIZE (p1)
+ && ((p2[2 + idx] & ~ p1[2 + idx]) == 0))))
+ break;
- if (idx == p2[1])
- {
- DEBUG_PRINT (" No match => fast loop.\n");
- return true;
- }
- }
- }
+ if (idx == p2[1])
+ {
+ DEBUG_PRINT (" No match => fast loop.\n");
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+struct mutexcl_data {
+ struct re_pattern_buffer *bufp;
+ re_char *p1;
+ bool unconstrained;
+};
+
+static bool
+mutually_exclusive_one (re_char *p2, void *arg)
+{
+ struct mutexcl_data *data = arg;
+ switch (*p2)
+ {
+ case succeed:
+ /* If `p1` matches, `succeed` can still match, so we should return
+ `false`. *BUT* when N iterations of `p1` and N+1 iterations of `p1`
+ match, the `succeed` that comes after N+1 always takes precedence
+ over the one after N because we always prefer a longer match, so
+ the succeed after N can actually be replaced by a "fail" without
+ changing the end result.
+ In this sense, "if `p1` matches, `succeed` can't match".
+ So we can return `true`.
+ *BUT* this only holds if we're sure that the N+1 will indeed succeed,
+ so we need to make sure there is no other matching operator between
+ the exit of the iteration and the `succeed`. */
+ return data->unconstrained;
+
+/* Remember that there may be an empty matching operator on the way.
+ If we return true, this is the "end" of this control flow path,
+ so it can't get in the way of a subsequent `succeed. */
+#define RETURN_CONSTRAIN(v) \
+ { bool tmp = (v); \
+ if (!tmp) \
+ data->unconstrained = false; \
+ return tmp; \
+ }
+
+ case endline:
+ RETURN_CONSTRAIN (mutually_exclusive_exactn (data->bufp, data->p1, p2));
+ case exactn:
+ return mutually_exclusive_exactn (data->bufp, data->p1, p2);
+ case charset:
+ {
+ if (*data->p1 == exactn)
+ return mutually_exclusive_exactn (data->bufp, p2, data->p1);
+ else
+ return mutually_exclusive_charset (data->bufp, data->p1, p2);
}
- break;
case charset_not:
- switch (*p1)
+ switch (*data->p1)
{
case exactn:
+ return mutually_exclusive_exactn (data->bufp, p2, data->p1);
case charset:
- /* Reuse the code above. */
- return mutually_exclusive_p (bufp, p2, p1);
+ return mutually_exclusive_charset (data->bufp, p2, data->p1);
case charset_not:
/* When we have two charset_not, it's very unlikely that
they don't overlap. The union of the two sets of excluded
chars should cover all possible chars, which, as a matter of
fact, is virtually impossible in multibyte buffers. */
- break;
+ return false;
}
- break;
-
- case wordend:
- return ((re_opcode_t) *p1 == syntaxspec && p1[1] == Sword);
- case symend:
- return ((re_opcode_t) *p1 == syntaxspec
- && (p1[1] == Ssymbol || p1[1] == Sword));
+ return false;
+ case anychar:
+ return false; /* FIXME: exactn \n ? */
+ case syntaxspec:
+ return (*data->p1 == notsyntaxspec && data->p1[1] == p2[1]);
case notsyntaxspec:
- return ((re_opcode_t) *p1 == syntaxspec && p1[1] == p2[1]);
+ return (*data->p1 == syntaxspec && data->p1[1] == p2[1]);
+ case categoryspec:
+ return (*data->p1 == notcategoryspec && data->p1[1] == p2[1]);
+ case notcategoryspec:
+ return (*data->p1 == categoryspec && data->p1[1] == p2[1]);
+ case endbuf:
+ return true;
case wordbeg:
- return ((re_opcode_t) *p1 == notsyntaxspec && p1[1] == Sword);
+ RETURN_CONSTRAIN (*data->p1 == notsyntaxspec && data->p1[1] == Sword);
+ case wordend:
+ RETURN_CONSTRAIN (*data->p1 == syntaxspec && data->p1[1] == Sword);
case symbeg:
- return ((re_opcode_t) *p1 == notsyntaxspec
- && (p1[1] == Ssymbol || p1[1] == Sword));
- case syntaxspec:
- return ((re_opcode_t) *p1 == notsyntaxspec && p1[1] == p2[1]);
+ RETURN_CONSTRAIN (*data->p1 == notsyntaxspec
+ && (data->p1[1] == Ssymbol || data->p1[1] == Sword));
+ case symend:
+ RETURN_CONSTRAIN (*data->p1 == syntaxspec
+ && (data->p1[1] == Ssymbol || data->p1[1] == Sword));
+ case at_dot:
+ case begbuf:
case wordbound:
- return (((re_opcode_t) *p1 == notsyntaxspec
- || (re_opcode_t) *p1 == syntaxspec)
- && p1[1] == Sword);
-
- case categoryspec:
- return ((re_opcode_t) *p1 == notcategoryspec && p1[1] == p2[1]);
- case notcategoryspec:
- return ((re_opcode_t) *p1 == categoryspec && p1[1] == p2[1]);
+ case notwordbound:
+ case begline:
+ RETURN_CONSTRAIN (false);
- case on_failure_jump_nastyloop:
- case on_failure_jump_smart:
- case on_failure_jump_loop:
- case on_failure_keep_string_jump:
- case on_failure_jump:
- {
- int mcnt;
- p2++;
- EXTRACT_NUMBER_AND_INCR (mcnt, p2);
- /* Don't just test `mcnt > 0` because non-greedy loops have
- their test at the end with an unconditional jump at the start. */
- if (p2 + mcnt > p2_orig) /* Ensure forward progress. */
- return (mutually_exclusive_p (bufp, p1, p2)
- && mutually_exclusive_p (bufp, p1, p2 + mcnt));
- break;
- }
+ case duplicate:
+ /* At this point, we know nothing about what this can match, sadly. */
+ return false;
default:
- ;
+#if ENABLE_CHECKING
+ abort (); /* We have listed all the cases. */
+#endif
+ return false;
}
-
- /* Safe default. */
- return false;
}
+/* True if "p1 matches something" implies "p2 fails". */
+
+static bool
+mutually_exclusive_p (struct re_pattern_buffer *bufp, re_char *p1,
+ re_char *p2)
+{
+ struct mutexcl_data data = { bufp, p1, true };
+ return forall_firstchar (bufp, p2, NULL, mutually_exclusive_one, &data);
+}
/* Matching routines. */
@@ -3974,6 +4146,9 @@ re_match_2_internal (struct re_pattern_buffer *bufp,
/* This keeps track of how many buffer/string positions we examined. */
ptrdiff_t nchars = 0;
+ /* Final return value of the function. */
+ ptrdiff_t retval = -1; /* Presumes failure to match for now. */
+
#ifdef DEBUG_COMPILES_ARGUMENTS
/* Counts the total number of registers pushed. */
ptrdiff_t num_regs_pushed = 0;
@@ -4228,15 +4403,8 @@ re_match_2_internal (struct re_pattern_buffer *bufp,
DEBUG_PRINT ("Returning %td from re_match_2.\n", dcnt);
- unbind_to (count, Qnil);
- SAFE_FREE ();
- /* The factor of 50 below is a heuristic that needs to be tuned. It
- means we consider 50 buffer positions examined by this function
- roughly equivalent to the display engine iterating over a single
- buffer position. */
- if (max_redisplay_ticks > 0 && nchars > 0)
- update_redisplay_ticks (nchars / 50 + 1, NULL);
- return dcnt;
+ retval = dcnt;
+ goto endof_re_match;
}
/* Otherwise match next pattern command. */
@@ -4729,7 +4897,7 @@ re_match_2_internal (struct re_pattern_buffer *bufp,
/* Have to succeed matching what follows at least n times.
- After that, handle like 'on_failure_jump'. */
+ After that, handle like 'on_failure_jump_loop'. */
case succeed_n:
/* Signedness doesn't matter since we only compare MCNT to 0. */
EXTRACT_NUMBER (mcnt, p + 2);
@@ -5077,8 +5245,7 @@ re_match_2_internal (struct re_pattern_buffer *bufp,
case succeed_n:
d = str;
continue_failure_jump:
- EXTRACT_NUMBER_AND_INCR (mcnt, pat);
- p = pat + mcnt;
+ p = extract_address (pat);
break;
case no_op:
@@ -5101,13 +5268,18 @@ re_match_2_internal (struct re_pattern_buffer *bufp,
if (best_regs_set)
goto restore_best_regs;
+endof_re_match:
unbind_to (count, Qnil);
SAFE_FREE ();
+ /* The factor of 50 below is a heuristic that needs to be tuned.
+ It means we consider 50 buffer positions examined by this function
+ roughly equivalent to the display engine iterating over a single
+ buffer position. */
if (max_redisplay_ticks > 0 && nchars > 0)
update_redisplay_ticks (nchars / 50 + 1, NULL);
- return -1; /* Failure to match. */
+ return retval;
}
/* Subroutine definitions for re_match_2. */
diff --git a/src/regex-emacs.h b/src/regex-emacs.h
index bc357633135..2402e539e64 100644
--- a/src/regex-emacs.h
+++ b/src/regex-emacs.h
@@ -1,6 +1,6 @@
/* Emacs regular expression API
- Copyright (C) 1985, 1989-1993, 1995, 2000-2023 Free Software
+ Copyright (C) 1985, 1989-1993, 1995, 2000-2024 Free Software
Foundation, Inc.
This program is free software; you can redistribute it and/or modify
@@ -195,4 +195,8 @@ extern bool re_iswctype (int ch, re_wctype_t cc);
extern re_wctype_t re_wctype_parse (const unsigned char **strp,
ptrdiff_t limit);
+#if ENABLE_CHECKING
+extern void print_compiled_pattern (FILE *dest, struct re_pattern_buffer *bufp);
+#endif
+
#endif /* EMACS_REGEX_H */
diff --git a/src/region-cache.c b/src/region-cache.c
index cbf6b7b1cee..089cb280a24 100644
--- a/src/region-cache.c
+++ b/src/region-cache.c
@@ -1,6 +1,6 @@
/* Caching facts about regions of the buffer, for optimization.
-Copyright (C) 1985-1989, 1993, 1995, 2001-2023 Free Software Foundation,
+Copyright (C) 1985-1989, 1993, 1995, 2001-2024 Free Software Foundation,
Inc.
This file is part of GNU Emacs.
diff --git a/src/region-cache.h b/src/region-cache.h
index bdf132dc2d8..686f865a05b 100644
--- a/src/region-cache.h
+++ b/src/region-cache.h
@@ -1,6 +1,6 @@
/* Header file: Caching facts about regions of the buffer, for optimization.
-Copyright (C) 1985-1986, 1993, 1995, 2001-2023 Free Software Foundation,
+Copyright (C) 1985-1986, 1993, 1995, 2001-2024 Free Software Foundation,
Inc.
This file is part of GNU Emacs.
diff --git a/src/scroll.c b/src/scroll.c
index 1f530dc5c95..fd2a9e71207 100644
--- a/src/scroll.c
+++ b/src/scroll.c
@@ -1,6 +1,6 @@
/* Calculate what line insertion or deletion to do, and do it
-Copyright (C) 1985-1986, 1990, 1993-1994, 2001-2023 Free Software
+Copyright (C) 1985-1986, 1990, 1993-1994, 2001-2024 Free Software
Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/search.c b/src/search.c
index 742a78cb0cd..f2d1f1f5449 100644
--- a/src/search.c
+++ b/src/search.c
@@ -1,6 +1,6 @@
/* String search routines for GNU Emacs.
-Copyright (C) 1985-1987, 1993-1994, 1997-1999, 2001-2023 Free Software
+Copyright (C) 1985-1987, 1993-1994, 1997-1999, 2001-2024 Free Software
Foundation, Inc.
This file is part of GNU Emacs.
@@ -281,7 +281,7 @@ looking_at_1 (Lisp_Object string, bool posix, bool modify_data)
struct regexp_cache *cache_entry = compile_pattern (
string,
modify_match_data ? &search_regs : NULL,
- (!NILP (BVAR (current_buffer, case_fold_search))
+ (!NILP (Vcase_fold_search)
? BVAR (current_buffer, case_canon_table) : Qnil),
posix,
!NILP (BVAR (current_buffer, enable_multibyte_characters)));
@@ -402,7 +402,7 @@ string_match_1 (Lisp_Object regexp, Lisp_Object string, Lisp_Object start,
struct regexp_cache *cache_entry
= compile_pattern (regexp,
modify_match_data ? &search_regs : NULL,
- (!NILP (BVAR (current_buffer, case_fold_search))
+ (!NILP (Vcase_fold_search)
? BVAR (current_buffer, case_canon_table)
: Qnil),
posix,
@@ -1068,10 +1068,10 @@ search_command (Lisp_Object string, Lisp_Object bound, Lisp_Object noerror,
BVAR (current_buffer, case_eqv_table));
np = search_buffer (string, PT, PT_BYTE, lim, lim_byte, n, RE,
- (!NILP (BVAR (current_buffer, case_fold_search))
+ (!NILP (Vcase_fold_search)
? BVAR (current_buffer, case_canon_table)
: Qnil),
- (!NILP (BVAR (current_buffer, case_fold_search))
+ (!NILP (Vcase_fold_search)
? BVAR (current_buffer, case_eqv_table)
: Qnil),
posix);
@@ -2365,7 +2365,7 @@ text has only capital letters and has at least one multiletter word,
convert NEWTEXT to all caps. Otherwise if all words are capitalized
in the replaced text, capitalize each word in NEWTEXT. Note that
what exactly is a word is determined by the syntax tables in effect
-in the current buffer.
+in the current buffer, and the variable `case-symbols-as-words'.
If optional third arg LITERAL is non-nil, insert NEWTEXT literally.
Otherwise treat `\\' as special:
@@ -2479,7 +2479,8 @@ since only regular expressions have distinguished subexpressions. */)
/* Cannot be all caps if any original char is lower case */
some_lowercase = 1;
- if (SYNTAX (prevc) != Sword)
+ if (SYNTAX (prevc) != Sword
+ && !(case_symbols_as_words && SYNTAX (prevc) == Ssymbol))
some_nonuppercase_initial = 1;
else
some_multiletter_word = 1;
@@ -2487,7 +2488,8 @@ since only regular expressions have distinguished subexpressions. */)
else if (uppercasep (c))
{
some_uppercase = 1;
- if (SYNTAX (prevc) != Sword)
+ if (SYNTAX (prevc) != Sword
+ && !(case_symbols_as_words && SYNTAX (prevc) == Ssymbol))
;
else
some_multiletter_word = 1;
@@ -2496,7 +2498,8 @@ since only regular expressions have distinguished subexpressions. */)
{
/* If the initial is a caseless word constituent,
treat that like a lowercase initial. */
- if (SYNTAX (prevc) != Sword)
+ if (SYNTAX (prevc) != Sword
+ && !(case_symbols_as_words && SYNTAX (prevc) == Ssymbol))
some_nonuppercase_initial = 1;
}
@@ -3137,11 +3140,25 @@ update_search_regs (ptrdiff_t oldstart, ptrdiff_t oldend, ptrdiff_t newend)
ptrdiff_t change = newend - oldend;
ptrdiff_t i;
+ /* When replacing subgroup 3 in a match for regexp '\(\)\(\(\)\)\(\)'
+ start[i] should ideally stay unchanged for all but i=4 and end[i]
+ should move for all but i=1.
+ We don't have enough info here to distinguish those different subgroups
+ (except for subgroup 0), so instead we lean towards leaving the start[i]s
+ unchanged and towards moving the end[i]s. */
+
for (i = 0; i < search_regs.num_regs; i++)
{
- if (search_regs.start[i] >= oldend)
+ if (search_regs.start[i] <= oldstart)
+ /* If the subgroup that 'replace-match' is modifying encloses the
+ subgroup 'i', then its 'start' position should stay unchanged.
+ That's always true for subgroup 0.
+ For other subgroups it depends on details we don't have, so
+ we optimistically assume that it also holds for them. */
+ ;
+ else if (search_regs.start[i] >= oldend)
search_regs.start[i] += change;
- else if (search_regs.start[i] > oldstart)
+ else
search_regs.start[i] = oldstart;
if (search_regs.end[i] >= oldend)
search_regs.end[i] += change;
@@ -3376,6 +3393,46 @@ the buffer. If the buffer doesn't have a cache, the value is nil. */)
set_buffer_internal_1 (old);
return val;
}
+
+DEFUN ("re--describe-compiled", Fre__describe_compiled, Sre__describe_compiled,
+ 1, 2, 0,
+ doc: /* Return a string describing the compiled form of REGEXP.
+If RAW is non-nil, just return the actual bytecode. */)
+ (Lisp_Object regexp, Lisp_Object raw)
+{
+ struct regexp_cache *cache_entry
+ = compile_pattern (regexp, NULL,
+ (!NILP (Vcase_fold_search)
+ ? BVAR (current_buffer, case_canon_table) : Qnil),
+ false,
+ !NILP (BVAR (current_buffer,
+ enable_multibyte_characters)));
+ if (!NILP (raw))
+ return make_unibyte_string ((char *) cache_entry->buf.buffer,
+ cache_entry->buf.used);
+ else
+ { /* FIXME: Why ENABLE_CHECKING? */
+#if !defined ENABLE_CHECKING
+ error ("Not available: rebuild with --enable-checking");
+#elif HAVE_OPEN_MEMSTREAM
+ char *buffer = NULL;
+ size_t size = 0;
+ FILE* f = open_memstream (&buffer, &size);
+ if (!f)
+ report_file_error ("open_memstream failed", regexp);
+ print_compiled_pattern (f, &cache_entry->buf);
+ fclose (f);
+ if (!buffer)
+ return Qnil;
+ Lisp_Object description = make_unibyte_string (buffer, size);
+ free (buffer);
+ return description;
+#else /* ENABLE_CHECKING && !HAVE_OPEN_MEMSTREAM */
+ print_compiled_pattern (stderr, &cache_entry->buf);
+ return build_string ("Description was sent to standard error");
+#endif /* !ENABLE_CHECKING */
+ }
+}
static void syms_of_search_for_pdumper (void);
@@ -3455,6 +3512,7 @@ is to bind it with `let' around a small expression. */);
defsubr (&Smatch_data__translate);
defsubr (&Sregexp_quote);
defsubr (&Snewline_cache_check);
+ defsubr (&Sre__describe_compiled);
pdumper_do_now_and_after_load (syms_of_search_for_pdumper);
}
diff --git a/src/sfnt.c b/src/sfnt.c
index e71ff9ae101..aa8b49a9ecd 100644
--- a/src/sfnt.c
+++ b/src/sfnt.c
@@ -1,6 +1,6 @@
/* TrueType format font support for GNU Emacs.
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
@@ -34,6 +34,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include <unistd.h>
#include <setjmp.h>
#include <errno.h>
+#include <alloca.h>
#ifdef HAVE_MMAP
#include <sys/mman.h>
@@ -66,6 +67,19 @@ xmalloc (size_t size)
return ptr;
}
+MAYBE_UNUSED static void *
+xzalloc (size_t size)
+{
+ void *ptr;
+
+ ptr = calloc (1, size);
+
+ if (!ptr)
+ abort ();
+
+ return ptr;
+}
+
static void *
xrealloc (void *ptr, size_t size)
{
@@ -82,7 +96,7 @@ xrealloc (void *ptr, size_t size)
static void
xfree (void *ptr)
{
- return free (ptr);
+ free (ptr);
}
/* Use this for functions that are static while building in test mode,
@@ -92,6 +106,9 @@ xfree (void *ptr)
/* Needed for tests. */
#define ARRAYELTS(arr) (sizeof (arr) / sizeof (arr)[0])
+/* Also necessary. */
+#define AVOID _Noreturn ATTRIBUTE_COLD void
+
#else
#define TEST_STATIC
#include "lisp.h"
@@ -153,6 +170,8 @@ static uint32_t sfnt_table_names[] =
[SFNT_TABLE_GVAR] = 0x67766172,
[SFNT_TABLE_CVAR] = 0x63766172,
[SFNT_TABLE_AVAR] = 0x61766172,
+ [SFNT_TABLE_OS_2] = 0x4f532f32,
+ [SFNT_TABLE_POST] = 0x706f7374,
};
/* Swap values from TrueType to system byte order. */
@@ -197,9 +216,9 @@ sfnt_read_table_directory (int fd)
range_shift, uint16_t);
rc = read (fd, subtable, offset);
- if (rc < offset)
+ if (rc == -1 || rc < offset)
{
- if (rc >= sizeof (uint32_t))
+ if (rc != -1 && rc >= sizeof (uint32_t))
{
/* Detect a TTC file. In that case, the first long will be
``ttcf''. */
@@ -242,7 +261,7 @@ sfnt_read_table_directory (int fd)
rc = read (fd, subtable->subtables, subtable_size);
- if (rc < offset)
+ if (rc == -1 || rc < offset)
{
xfree (subtable);
return NULL;
@@ -306,7 +325,7 @@ sfnt_read_cmap_format_0 (int fd,
language));
rc = read (fd, &format0->language, wanted_size);
- if (rc < wanted_size)
+ if (rc == -1 || rc < wanted_size)
{
xfree (format0);
return (struct sfnt_cmap_format_0 *) -1;
@@ -344,7 +363,7 @@ sfnt_read_cmap_format_2 (int fd,
/* Read the part before the variable length data. */
min_bytes -= offsetof (struct sfnt_cmap_format_2, language);
rc = read (fd, &format2->language, min_bytes);
- if (rc < min_bytes)
+ if (rc == -1 || rc < min_bytes)
{
xfree (format2);
return (struct sfnt_cmap_format_2 *) -1;
@@ -378,7 +397,7 @@ sfnt_read_cmap_format_2 (int fd,
- SFNT_ENDOF (struct sfnt_cmap_format_2,
sub_header_keys, uint16_t[256]));
rc = read (fd, format2 + 1, min_bytes);
- if (rc < min_bytes)
+ if (rc == -1 || rc < min_bytes)
{
xfree (format2);
return (struct sfnt_cmap_format_2 *) -1;
@@ -432,7 +451,7 @@ sfnt_read_cmap_format_4 (int fd,
int seg_count, i;
min_bytes = SFNT_ENDOF (struct sfnt_cmap_format_4,
- entry_selector, uint16_t);
+ range_shift, uint16_t);
/* Check that the length is at least min_bytes. */
if (header->length < min_bytes)
@@ -449,7 +468,7 @@ sfnt_read_cmap_format_4 (int fd,
/* Read the initial data. */
min_bytes -= offsetof (struct sfnt_cmap_format_4, language);
rc = read (fd, &format4->language, min_bytes);
- if (rc < min_bytes)
+ if (rc == -1 || rc < min_bytes)
{
xfree (format4);
return (struct sfnt_cmap_format_4 *) -1;
@@ -460,6 +479,7 @@ sfnt_read_cmap_format_4 (int fd,
sfnt_swap16 (&format4->seg_count_x2);
sfnt_swap16 (&format4->search_range);
sfnt_swap16 (&format4->entry_selector);
+ sfnt_swap16 (&format4->range_shift);
/* Get the number of segments to read. */
seg_count = format4->seg_count_x2 / 2;
@@ -467,7 +487,7 @@ sfnt_read_cmap_format_4 (int fd,
/* Now calculate whether or not the size is sufficiently large. */
bytes_minus_format4
= format4->length - SFNT_ENDOF (struct sfnt_cmap_format_4,
- entry_selector, uint16_t);
+ range_shift, uint16_t);
variable_size = (seg_count * sizeof *format4->end_code
+ sizeof *format4->reserved_pad
+ seg_count * sizeof *format4->start_code
@@ -484,7 +504,7 @@ sfnt_read_cmap_format_4 (int fd,
/* Read the rest of the bytes to the end of format4. */
rc = read (fd, format4 + 1, bytes_minus_format4);
- if (rc < bytes_minus_format4)
+ if (rc == -1 || rc < bytes_minus_format4)
{
xfree (format4);
return (struct sfnt_cmap_format_4 *) -1;
@@ -553,7 +573,7 @@ sfnt_read_cmap_format_6 (int fd,
/* Read the fixed size data. */
min_size -= offsetof (struct sfnt_cmap_format_6, language);
rc = read (fd, &format6->language, min_size);
- if (rc < min_size)
+ if (rc == -1 || rc < min_size)
{
xfree (format6);
return (struct sfnt_cmap_format_6 *) -1;
@@ -577,7 +597,8 @@ sfnt_read_cmap_format_6 (int fd,
rc = read (fd, format6 + 1,
(format6->entry_count
* sizeof *format6->glyph_index_array));
- if (rc < format6->entry_count * sizeof *format6->glyph_index_array)
+ if (rc == -1 || (rc < (format6->entry_count
+ * sizeof *format6->glyph_index_array)))
{
xfree (format6);
return (struct sfnt_cmap_format_6 *) -1;
@@ -605,7 +626,7 @@ sfnt_read_cmap_format_8 (int fd,
uint32_t length, i;
/* Read the 32-bit length field. */
- if (read (fd, &length, sizeof (length)) < sizeof (length))
+ if (read (fd, &length, sizeof length) < (int) sizeof length)
return (struct sfnt_cmap_format_8 *) -1;
/* Swap the 32-bit length field. */
@@ -627,7 +648,7 @@ sfnt_read_cmap_format_8 (int fd,
/* Read the fixed length data. */
min_size -= offsetof (struct sfnt_cmap_format_8, language);
rc = read (fd, &format8->language, min_size);
- if (rc < min_size)
+ if (rc == -1 || rc < min_size)
{
xfree (format8);
return (struct sfnt_cmap_format_8 *) -1;
@@ -663,7 +684,7 @@ sfnt_read_cmap_format_8 (int fd,
/* Now read the variable length data. */
rc = read (fd, format8 + 1, temp);
- if (rc < temp)
+ if (rc == -1 || rc < temp)
{
xfree (format8);
return (struct sfnt_cmap_format_8 *) -1;
@@ -697,7 +718,7 @@ sfnt_read_cmap_format_12 (int fd,
uint32_t length, i;
/* Read the 32-bit length field. */
- if (read (fd, &length, sizeof (length)) < sizeof (length))
+ if (read (fd, &length, sizeof length) < (int) sizeof length)
return (struct sfnt_cmap_format_12 *) -1;
/* Swap the 32-bit length field. */
@@ -719,7 +740,7 @@ sfnt_read_cmap_format_12 (int fd,
/* Read the fixed length data. */
min_size -= offsetof (struct sfnt_cmap_format_12, language);
rc = read (fd, &format12->language, min_size);
- if (rc < min_size)
+ if (rc == -1 || rc < min_size)
{
xfree (format12);
return (struct sfnt_cmap_format_12 *) -1;
@@ -755,7 +776,7 @@ sfnt_read_cmap_format_12 (int fd,
/* Now read the variable length data. */
rc = read (fd, format12 + 1, temp);
- if (rc < temp)
+ if (rc == -1 || rc < temp)
{
xfree (format12);
return (struct sfnt_cmap_format_12 *) -1;
@@ -802,12 +823,12 @@ sfnt_read_cmap_format_14 (int fd,
uint32_t buffer1[2];
size_t size, temp;
char buffer[3 + 4 + 4];
- int i;
+ uint32_t i;
/* Read the length field and number of variation selector
records. */
- if (read (fd, buffer1, sizeof buffer1) < sizeof buffer1)
+ if (read (fd, buffer1, sizeof buffer1) < (int) sizeof buffer1)
return NULL;
length = buffer1[0];
@@ -841,7 +862,7 @@ sfnt_read_cmap_format_14 (int fd,
for (i = 0; i < num_records; ++i)
{
- if (read (fd, buffer, sizeof buffer) < sizeof buffer)
+ if (read (fd, buffer, sizeof buffer) < (int) sizeof buffer)
{
xfree (format14);
return NULL;
@@ -887,7 +908,7 @@ sfnt_read_cmap_table_1 (int fd, uint32_t directory_offset,
return (struct sfnt_cmap_encoding_subtable_data *) -1;
if (read (fd, &header.format, sizeof header.format)
- < sizeof header.format)
+ < (int) sizeof header.format)
return (struct sfnt_cmap_encoding_subtable_data *) -1;
sfnt_swap16 (&header.format);
@@ -899,7 +920,7 @@ sfnt_read_cmap_table_1 (int fd, uint32_t directory_offset,
if (header.format != 14)
{
if (read (fd, &header.length, sizeof header.length)
- < sizeof header.length)
+ < (int) sizeof header.length)
return (struct sfnt_cmap_encoding_subtable_data *) -1;
sfnt_swap16 (&header.length);
@@ -978,7 +999,7 @@ sfnt_read_cmap_table (int fd, struct sfnt_offset_subtable *subtable,
cmap = xmalloc (sizeof *cmap);
rc = read (fd, cmap, sizeof *cmap);
- if (rc < sizeof *cmap)
+ if (rc < (int) sizeof *cmap)
{
xfree (cmap);
return NULL;
@@ -1005,7 +1026,7 @@ sfnt_read_cmap_table (int fd, struct sfnt_offset_subtable *subtable,
/* Read the common part of the new subtable. */
rc = read (fd, &(*subtables)[i], sizeof (*subtables)[i]);
- if (rc < sizeof (*subtables)[i])
+ if (rc < (int) sizeof (*subtables)[i])
{
xfree (cmap);
xfree (*subtables);
@@ -1115,8 +1136,8 @@ sfnt_lookup_glyph_2 (sfnt_char character,
: 0);
}
-/* Like `bsearch'. However, return the highest element above KEY if
- it could not be found. */
+/* Like `bsearch', but return the element ordered exactly above KEY if
+ one exists and KEY itself cannot be located. */
static void *
sfnt_bsearch_above (const void *key, const void *base,
@@ -1139,12 +1160,18 @@ sfnt_bsearch_above (const void *key, const void *base,
mid = low + (high - low) / 2;
sample = bytes + mid * size;
- if (compar (key, sample) > 0)
+ if ((*compar) (key, sample) > 0)
low = mid + 1;
else
high = mid;
}
+ sample = bytes + low * size;
+
+ if (low == nmemb - 1
+ && (*compar) (key, sample) > 0)
+ return NULL;
+
return (unsigned char *) bytes + low * size;
}
@@ -1222,27 +1249,6 @@ sfnt_lookup_glyph_4 (sfnt_char character,
if (glyph)
return glyph;
- /* Droid Sans Mono has overlapping segments in its format 4 cmap
- subtable where the first segment's end code is 32, while the
- second segment's start code is also 32. The TrueType Reference
- Manual says that mapping should begin by searching for the first
- segment whose end code is greater than or equal to the character
- being indexed, but that results in the first subtable being
- found, which doesn't work, while the second table does. Try to
- detect this situation and use the second table if possible. */
-
- if (!glyph
- /* The character being looked up is the current segment's end
- code. */
- && code == format4->end_code[segment]
- /* There is an additional segment. */
- && segment + 1 < format4->seg_count_x2 / 2
- /* That segment's start code is the same as this segment's end
- code. */
- && format4->start_code[segment + 1] == format4->end_code[segment])
- /* Try the second segment. */
- return sfnt_lookup_glyph_4_1 (character, segment + 1, format4);
-
/* Fail. */
return 0;
}
@@ -1262,6 +1268,19 @@ sfnt_lookup_glyph_6 (sfnt_char character,
return format6->glyph_index_array[character - format6->first_code];
}
+/* Compare the sfnt_char A with B's end code. Employed to bisect
+ through a format 8 or 12 table. */
+
+static int
+sfnt_compare_char (const void *a, const void *b)
+{
+ struct sfnt_cmap_format_8_or_12_group *group;
+
+ group = (struct sfnt_cmap_format_8_or_12_group *) b;
+
+ return ((int) *((sfnt_char *) a)) - group->end_char_code;
+}
+
/* Look up the glyph corresponding to CHARACTER in the format 8 cmap
FORMAT8. Return 0 if no glyph was found. */
@@ -1270,10 +1289,35 @@ sfnt_lookup_glyph_8 (sfnt_char character,
struct sfnt_cmap_format_8 *format8)
{
uint32_t i;
+ struct sfnt_cmap_format_8_or_12_group *group;
if (character > 0xffffffff)
return 0;
+ if (format8->num_groups > 64)
+ {
+ /* This table is large, likely supplied by a CJK or similar
+ font. Perform a binary search. */
+
+ /* Find the group whose END_CHAR_CODE is greater than or equal
+ to CHARACTER. */
+
+ group = sfnt_bsearch_above (&character, format8->groups,
+ format8->num_groups,
+ sizeof format8->groups[0],
+ sfnt_compare_char);
+
+ if (!group || group->start_char_code > character)
+ /* No glyph matches this group. */
+ return 0;
+
+ /* Otherwise, use this group to map the character to a
+ glyph. */
+ return (group->start_glyph_code
+ + character
+ - group->start_char_code);
+ }
+
for (i = 0; i < format8->num_groups; ++i)
{
if (format8->groups[i].start_char_code <= character
@@ -1286,19 +1330,6 @@ sfnt_lookup_glyph_8 (sfnt_char character,
return 0;
}
-/* Compare the sfnt_char A with B's end code. Employed to bisect
- through a format 12 table. */
-
-static int
-sfnt_compare_char (const void *a, const void *b)
-{
- struct sfnt_cmap_format_8_or_12_group *group;
-
- group = (struct sfnt_cmap_format_8_or_12_group *) b;
-
- return ((int) *((sfnt_char *) a)) - group->end_char_code;
-}
-
/* Look up the glyph corresponding to CHARACTER in the format 12 cmap
FORMAT12. Return 0 if no glyph was found. */
@@ -1325,7 +1356,7 @@ sfnt_lookup_glyph_12 (sfnt_char character,
sizeof format12->groups[0],
sfnt_compare_char);
- if (group->start_char_code > character)
+ if (!group || group->start_char_code > character)
/* No glyph matches this group. */
return 0;
@@ -1420,7 +1451,7 @@ sfnt_read_head_table (int fd, struct sfnt_offset_subtable *subtable)
head = xmalloc (sizeof *head);
rc = read (fd, head, sizeof *head);
- if (rc < sizeof *head)
+ if (rc < (int) sizeof *head)
{
xfree (head);
return NULL;
@@ -1496,7 +1527,7 @@ sfnt_read_hhea_table (int fd, struct sfnt_offset_subtable *subtable)
hhea = xmalloc (sizeof *hhea);
rc = read (fd, hhea, sizeof *hhea);
- if (rc < sizeof *hhea)
+ if (rc < (int) sizeof *hhea)
{
xfree (hhea);
return NULL;
@@ -1659,7 +1690,7 @@ sfnt_read_maxp_table (int fd, struct sfnt_offset_subtable *subtable)
size = MIN (directory->length, sizeof *maxp);
rc = read (fd, maxp, size);
- if (rc < size)
+ if (rc == -1 || rc < size)
{
xfree (maxp);
return NULL;
@@ -1739,7 +1770,7 @@ sfnt_read_glyf_table (int fd, struct sfnt_offset_subtable *subtable)
/* Read the glyph data. */
rc = read (fd, glyf->glyphs, glyf->size);
- if (rc < glyf->size)
+ if (rc == -1 || rc < glyf->size)
{
xfree (glyf);
return NULL;
@@ -2009,7 +2040,7 @@ sfnt_read_simple_glyph (struct sfnt_glyph *glyph,
/* The next byte is a delta to apply to the previous
value. Make sure it is in bounds. */
- if (vec_start + 1 >= glyf->glyphs + glyf->size)
+ if (vec_start + 1 > glyf->glyphs + glyf->size)
{
glyph->simple = NULL;
xfree (simple);
@@ -2026,7 +2057,7 @@ sfnt_read_simple_glyph (struct sfnt_glyph *glyph,
/* The next word is a delta to apply to the previous value.
Make sure it is in bounds. */
- if (vec_start + 2 >= glyf->glyphs + glyf->size)
+ if (vec_start + 2 > glyf->glyphs + glyf->size)
{
glyph->simple = NULL;
xfree (simple);
@@ -2061,7 +2092,7 @@ sfnt_read_simple_glyph (struct sfnt_glyph *glyph,
/* The next byte is a delta to apply to the previous
value. Make sure it is in bounds. */
- if (vec_start + 1 >= glyf->glyphs + glyf->size)
+ if (vec_start + 1 > glyf->glyphs + glyf->size)
{
glyph->simple = NULL;
xfree (simple);
@@ -2078,7 +2109,7 @@ sfnt_read_simple_glyph (struct sfnt_glyph *glyph,
/* The next word is a delta to apply to the previous value.
Make sure it is in bounds. */
- if (vec_start + 2 >= glyf->glyphs + glyf->size)
+ if (vec_start + 2 > glyf->glyphs + glyf->size)
{
glyph->simple = NULL;
xfree (simple);
@@ -2390,6 +2421,8 @@ sfnt_read_glyph (sfnt_glyph glyph_code,
glyph.ymin = 0;
glyph.xmax = 0;
glyph.ymax = 0;
+ glyph.advance_distortion = 0;
+ glyph.origin_distortion = 0;
glyph.simple = xmalloc (sizeof *glyph.simple);
glyph.compound = NULL;
memset (glyph.simple, 0, sizeof *glyph.simple);
@@ -2567,6 +2600,16 @@ struct sfnt_compound_glyph_context
/* Number of elements in and the size of that array. */
size_t num_end_points, end_points_size;
+
+ /* The X positions of two phantom points marking this glyph's origin
+ and advance position, only used while interpreting the glyph. */
+ sfnt_f26dot6 phantom_point_1_x, phantom_point_2_x;
+
+ /* Y positions. */
+ sfnt_f26dot6 phantom_point_1_y, phantom_point_2_y;
+
+ /* Unrounded X positions. */
+ sfnt_f26dot6 phantom_point_1_s, phantom_point_2_s;
};
/* Extend the arrays inside the compound glyph decomposition context
@@ -2671,11 +2714,17 @@ sfnt_round_fixed (int32_t number)
GET_METRICS, along with DCONTEXT, mean the same as in
sfnt_decompose_glyph.
+ If it has been arranged that a component's metrics (or those of an
+ innermore component also with the flag set) replace the metrics of
+ GLYPH, set *METRICS_RETURN to those metrics. Mind that such
+ metrics are not scaled in any manner.
+
Value is 1 upon failure, else 0. */
static int
sfnt_decompose_compound_glyph (struct sfnt_glyph *glyph,
struct sfnt_compound_glyph_context *context,
+ struct sfnt_glyph_metrics *metrics_return,
sfnt_get_glyph_proc get_glyph,
sfnt_free_glyph_proc free_glyph,
sfnt_get_metrics_proc get_metrics,
@@ -2765,7 +2814,7 @@ sfnt_decompose_compound_glyph (struct sfnt_glyph *glyph,
else
{
/* The offset is determined by matching a point location in
- a preceeding component with a point location in the
+ a preceding component with a point location in the
current component. The index of the point in the
previous component can be determined by adding
component->argument1.a or component->argument1.c to
@@ -2911,16 +2960,61 @@ sfnt_decompose_compound_glyph (struct sfnt_glyph *glyph,
/* Copy over the contours. */
for (i = 0; i < number_of_contours; ++i)
- contour_base[i] = (contour_start
- + subglyph->simple->end_pts_of_contours[i]);
+ contour_base[i]
+ = (contour_start
+ + subglyph->simple->end_pts_of_contours[i]);
+
+ /* If USE_MY_METRICS is present within this component,
+ save its metrics within *METRICS_RETURN. */
+
+ if (component->flags & 01000 /* USE_MY_METRICS */)
+ {
+ if ((*get_metrics) (component->glyph_index,
+ metrics_return, dcontext))
+ {
+ if (need_free)
+ free_glyph (subglyph, dcontext);
+
+ return 1;
+ }
+
+ /* Refer to the comment above sfnt_decompose_glyph
+ for reasons and manner in which these offsets are
+ applied. */
+ metrics_return->lbearing -= subglyph->origin_distortion;
+ metrics_return->advance += subglyph->advance_distortion;
+ }
}
}
else
{
+ /* If USE_MY_METRICS, save this subglyph's metrics within
+ sub_metrics; they might be overwritten by metrics for
+ subglyphs of this compound subglyph in turn. */
+
+ if (component->flags & 01000 /* USE_MY_METRICS */)
+ {
+ if ((*get_metrics) (component->glyph_index,
+ &sub_metrics, dcontext))
+ {
+ if (need_free)
+ free_glyph (subglyph, dcontext);
+
+ return 1;
+ }
+
+ /* Refer to the comment above sfnt_decompose_glyph for
+ reasons and manner in which these offsets are
+ applied. */
+ sub_metrics.lbearing -= subglyph->origin_distortion;
+ sub_metrics.advance += subglyph->advance_distortion;
+ }
+
/* Compound subglyph. Decompose the glyph recursively, and
then apply the transform. */
rc = sfnt_decompose_compound_glyph (subglyph,
context,
+ &sub_metrics,
get_glyph,
free_glyph,
get_metrics,
@@ -2935,19 +3029,19 @@ sfnt_decompose_compound_glyph (struct sfnt_glyph *glyph,
return 1;
}
+ if (component->flags & 01000 /* USE_MY_METRICS */)
+ /* Save sub_metrics inside *metrics_return as stated
+ above. */
+ *metrics_return = sub_metrics;
+
/* When an anchor point is being used to translate the
glyph, and the subglyph in question is actually a
compound glyph, it is impossible to know which offset to
- use until the compound subglyph has actually been
- loaded.
+ use until the compound subglyph has actually been loaded.
- As a result, the offset is calculated here, using the
- points in the loaded child compound glyph. But first, X
- and Y must be reset to 0, as otherwise the translation
- might be applied twice if defer_offsets is not set. */
-
- x = 0;
- y = 0;
+ defer_offsets is set to true if these conditions apply,
+ whereupon the offset is calculated here, using the points
+ in the loaded child compound glyph. */
if (defer_offsets)
{
@@ -3062,7 +3156,8 @@ sfnt_decompose_glyph_1 (size_t here, size_t last,
/* The contour is empty. */
if (here == last)
- return 1;
+ /* An empty contour, if redundant, is not necessarily invalid. */
+ return 0;
/* Move the pen to the start of the contour. Apparently some fonts
have off the curve points as the start of a contour, so when that
@@ -3201,7 +3296,8 @@ sfnt_decompose_glyph_2 (size_t here, size_t last,
/* The contour is empty. */
if (here == last)
- return 1;
+ /* An empty contour, if redundant, is not necessarily invalid. */
+ return 0;
/* Move the pen to the start of the contour. Apparently some fonts
have off the curve points as the start of a contour, so when that
@@ -3326,6 +3422,19 @@ sfnt_decompose_glyph_2 (size_t here, size_t last,
GET_METRICS to obtain glyph metrics prerequisite for establishing
their coordinates.
+ When glyphs originate from a GX font with an active set of
+ transforms, the correct manner of applying such transforms is to
+ apply them within GET_GLYPH, while returning unaltered metrics from
+ GET_METRICS.
+
+ If there is a component glyph within GLYPH whose metrics have been
+ indicated as replacing those of its parent glyph, the variable
+ *METRICS_RETURN will be set to its metrics with GX-induced offsets
+ applied.
+
+ *METRICS_RETURN must initially hold metrics with GX offsets
+ applied, if any.
+
All functions will be called with DCONTEXT as an argument.
The winding rule used to fill the resulting lines is described in
@@ -3337,6 +3446,7 @@ sfnt_decompose_glyph_2 (size_t here, size_t last,
static int
sfnt_decompose_glyph (struct sfnt_glyph *glyph,
+ struct sfnt_glyph_metrics *metrics_return,
sfnt_move_to_proc move_to,
sfnt_line_to_proc line_to,
sfnt_curve_to_proc curve_to,
@@ -3347,6 +3457,7 @@ sfnt_decompose_glyph (struct sfnt_glyph *glyph,
{
size_t here, last, n;
struct sfnt_compound_glyph_context context;
+ struct sfnt_glyph_metrics compound_metrics;
if (glyph->simple)
{
@@ -3388,7 +3499,15 @@ sfnt_decompose_glyph (struct sfnt_glyph *glyph,
/* Decompose the specified compound glyph. */
memset (&context, 0, sizeof context);
+ /* Rather than handing METRICS_RETURN over to
+ sfnt_decompose_compound_glyph, save metrics within a temporary
+ variable and postpone returning them until it is certain the
+ decomposition has succeeded. */
+
+ compound_metrics = *metrics_return;
+
if (sfnt_decompose_compound_glyph (glyph, &context,
+ &compound_metrics,
get_glyph, free_glyph,
get_metrics, 0,
dcontext))
@@ -3401,6 +3520,8 @@ sfnt_decompose_glyph (struct sfnt_glyph *glyph,
return 1;
}
+ *metrics_return = compound_metrics;
+
/* Now, generate the outlines. */
if (!context.num_end_points)
@@ -3474,12 +3595,18 @@ sfnt_build_append (int flags, sfnt_fixed x, sfnt_fixed y)
{
struct sfnt_glyph_outline *outline;
+ outline = build_outline_context.outline;
+
if (x == build_outline_context.x
- && y == build_outline_context.y)
+ && y == build_outline_context.y
+ /* If the outline is presently empty, the first move_to must be
+ recorded even if its X and Y are set to origin. Without this
+ initial vertex, edges will be generated from the next vertex
+ onward, and thus be misaligned. */
+ && outline->outline_used)
/* Ignore redundant motion. */
return build_outline_context.outline;
- outline = build_outline_context.outline;
outline->outline_used++;
/* See if the outline has to be extended. Checking for overflow
@@ -3873,11 +4000,11 @@ sfnt_curve_is_flat (struct sfnt_point control0,
h.x = endpoint.x - control0.x;
h.y = endpoint.y - control0.y;
- /* 2.0 is a constant describing the area covered at which point the
- curve is considered "flat". */
+ /* 1.0 is a constant representing the area covered at which point
+ the curve is considered "flat". */
return (abs (sfnt_mul_fixed (g.x, h.y)
- sfnt_mul_fixed (g.y, h.x))
- <= 0400000);
+ <= 0200000);
}
/* Recursively split the splines in the bezier curve formed from
@@ -3952,7 +4079,14 @@ sfnt_curve_to_and_build (struct sfnt_point control,
space.
Use the unscaled glyph METRICS to determine the origin point of the
- outline.
+ outline, or those of compound glyph components within *GLYPH
+ configured to replace their parents', which if existent are
+ returned in *METRICS. METRICS should not be altered by GX-derived
+ offsets, as they will be applied to *METRICS if present, following
+ this formula:
+
+ LBEARING = LBEARING - GLYPH->origin_distortion
+ ADVANCE = ADVANCE + GLYPH->advance_distortion
Call GET_GLYPH and FREE_GLYPH with the specified DCONTEXT to obtain
glyphs for compound glyph subcomponents, and GET_METRICS with the
@@ -3995,8 +4129,15 @@ sfnt_build_glyph_outline (struct sfnt_glyph *glyph,
/* Set the scale factor. */
build_outline_context.factor = scale;
+ /* Apply the glyph's advance and origin distortion to METRICS in
+ advance of constructing the glyph outline, which might replace
+ METRICS with the metrics of a compound subglyph. */
+ metrics->lbearing -= glyph->origin_distortion;
+ metrics->advance += glyph->advance_distortion;
+
/* Decompose the outline. */
- rc = sfnt_decompose_glyph (glyph, sfnt_move_to_and_build,
+ rc = sfnt_decompose_glyph (glyph, metrics,
+ sfnt_move_to_and_build,
sfnt_line_to_and_build,
sfnt_curve_to_and_build,
get_glyph, free_glyph, get_metrics,
@@ -4016,7 +4157,7 @@ sfnt_build_glyph_outline (struct sfnt_glyph *glyph,
is first used to calculate the origin point, and the origin
distortion is applied to it to get the distorted origin. */
- origin = glyph->xmin - metrics->lbearing + glyph->origin_distortion;
+ origin = glyph->xmin - metrics->lbearing;
outline->origin = sfnt_mul_fixed (origin, scale);
return outline;
@@ -4192,7 +4333,6 @@ sfnt_build_outline_edges (struct sfnt_glyph_outline *outline,
/* Compute the step X. This is how much X changes for each
increase in Y. */
-
step_x = sfnt_div_fixed (dx, dy);
edges[edge].next = NULL;
@@ -4282,7 +4422,6 @@ sfnt_poly_edges (struct sfnt_edge *edges, size_t size,
/* Step down line by line. Find active edges. */
y = edges[0].bottom;
- active = 0;
active = NULL;
e = 0;
@@ -4580,6 +4719,908 @@ sfnt_raster_glyph_outline (struct sfnt_glyph_outline *outline)
+#define sfnt_add(a, b) \
+ ((int) ((unsigned int) (a) + (unsigned int) (b)))
+
+#define sfnt_sub(a, b) \
+ ((int) ((unsigned int) (a) - (unsigned int) (b)))
+
+#define sfnt_mul(a, b) \
+ ((int) ((unsigned int) (a) * (unsigned int) (b)))
+
+
+
+/* Exact coverage scaler.
+
+ The foregoing routines calculate partial coverage for each pixel by
+ increasing each span in increments finer than a single pixel, then
+ merging active spans into the raster.
+
+ Experience has proven this yields imperfect display results,
+ particularly when combined with glyph instruction code which aligns
+ points in a certain and as yet undetermined manner.
+
+ The scaler implemented in this page attains greater precision,
+ generating at length an array of scanlines, in which each is
+ represented by a list of steps. Each step holds an X coordinate
+ and a coverage value, which contributes to the coverage of each
+ pixel within the scanline rightwards or equal to the pixel with its
+ X coordinate.
+
+ Such a coverage value can be positive or negative; when the winding
+ direction of the span it derives from is positive, so is the
+ coverage value, that the pixels to its right (thus further into the
+ polygon it demarcates) might be painted in. In the other case, the
+ value is negative, thus negating the effect of preceding steps and
+ marking the outer boundary of the section of the polygon's
+ intersection with the scanline.
+
+ The procedure for producing this array of scanlines is largely an
+ adaptation of that which sfnt_poly_edges implements; in particular
+ the process of sorting and filtering edges remains untouched.
+
+ Rather than advancing through the edges SFNT_POLY_STEP at a time,
+ the edges are iterated over scanline-by-scanline. Every edge
+ overlapping with a particular scanline is considered piecemeal to
+ generate its array of steps.
+
+ An edge might overlap pixels within the scanline in one of four
+ fashions; each is illustrated with a graphic below:
+
+ +--------ee-----+------------------------------------------------+ (I)
+ | ee.......|................................................|
+ | ee.........|................................................|
+ | ee...........|................................................|
+ |ee.............|................................................|
+ ee---------------+------------------------------------------------+
+
+ In this instance, the edge partially overlaps its first pixel, but
+ the remainder all receive complete coverage.
+
+ +---------------+---------eeeeee+--------------------------------+ (II)
+ | | eeeeee......|................................|
+ | eeeee............|................................|
+ | eeeeee.|...............|................................|
+ | eeeeee.......|...............|................................|
+ eee-------------+---------------+--------------------------------+
+
+ In this instance, the edge partially overlaps two or more pixels on
+ this scanline. These pixels are referred to as a run.
+
+ +---------------+---------------+----------------+---------------+ (III)
+ | eeeeeee.|...............|................|...............|
+ | eeeeeeee..|...............|................|...............|
+ | eeeeeeee....|...............|................|...............|
+ | eeeeeee......|...............|................|...............|
+ +---------------+---------------+----------------+---------------+
+
+ This instance is much like the first instance, save that the
+ covered vertical area does not span the entire scanline.
+
+ +---------------+---------------+----------------+---------------+ (IV)
+ | | | | eeeeeeeeeee...|
+ | | eeeeeeeeeeeeeeeeeeeeeeeeeeeeeee...|
+ | eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee|...............|
+ |eeeeeeeeeeeeeeeeeeeeeee........|................|...............|
+ +---------------+---------------+----------------+---------------+
+
+ And this the second, again with the same distinction therefrom.
+
+ In each of these instances, a trapezoid is formed within every
+ pixel of the scanline, between:
+
+ - The point of the span's entry into the first pixel, either that
+ point itself or, for subsequent pixels, its projection onto
+ those pixels.
+
+ - The point of the span's exit or its termination.
+
+ - Both those points projected into the outer boundary of the
+ pertinent pixel.
+
+ The proportion formed by the area of this trapezoid and that of the
+ pixel then constitutes the coverage value to be recorded. */
+
+/* Structure representing a step, as above. */
+
+struct sfnt_step
+{
+ /* The next step in this list. */
+ struct sfnt_step *next;
+
+ /* X coordinate of the step. This value affects all pixels at and
+ beyond this X coordinate. */
+ int x;
+
+ /* Coverage value between -1 and 1. */
+ float coverage;
+};
+
+/* Structure representing an array of steps, one for each
+ scanline. */
+
+struct sfnt_step_raster
+{
+ /* Number of scanlines within this raster. */
+ size_t scanlines;
+
+ /* Array of steps with one element for each scanline. */
+ struct sfnt_step **steps;
+
+ /* Linked list of chunks of steps allocated for this raster. */
+ struct sfnt_step_chunk *chunks;
+};
+
+enum
+ {
+ SFNT_BLOCK_STEPS = 128,
+ };
+
+/* Structure representing a block of steps, which are allocated
+ SFNT_BLOCK_STEPS at a time. */
+
+struct sfnt_step_chunk
+{
+ /* The next chunk in this list, or NULL. */
+ struct sfnt_step_chunk *next;
+
+ /* Number of steps used within this chunk thus far. */
+ size_t nused;
+
+ /* The steps themselves. */
+ struct sfnt_step steps[SFNT_BLOCK_STEPS];
+};
+
+/* Structure representing an edge as consumed by the exact coverage
+ scaler. This structure is much like struct sfnt_edge, albeit with
+ all fractionals replaced by floating point numbers and an extra
+ field holding a Y delta. */
+
+struct sfnt_fedge
+{
+ /* Next edge in this chain. */
+ struct sfnt_fedge *next;
+
+ /* Winding direction. 1 if clockwise, -1 if counterclockwise. */
+ int winding;
+
+ /* X position, top and bottom of edges. */
+ float x, top, bottom;
+
+ /* Amount to move X by upon each change of Y, and vice versa. */
+ float step_x, step_y;
+};
+
+typedef void (*sfnt_fedge_proc) (struct sfnt_fedge *, size_t,
+ void *);
+
+/* Build a list of edges for each contour in OUTLINE, displacing each
+ edge by xmin and ymin. Call EDGE_PROC with DCONTEXT and the edges
+ produced as arguments. */
+
+static void
+sfnt_build_outline_fedges (struct sfnt_glyph_outline *outline,
+ sfnt_fedge_proc edge_proc, void *dcontext)
+{
+ struct sfnt_fedge *edges;
+ size_t i, edge, next_vertex;
+ sfnt_fixed dx, dy, step_x, step_y, ymin, xmin;
+ size_t top, bottom;
+
+ edges = alloca (outline->outline_used * sizeof *edges);
+ edge = 0;
+
+ /* ymin and xmin must be the same as the offset used to set offy and
+ offx in rasters. */
+ ymin = sfnt_floor_fixed (outline->ymin);
+ xmin = sfnt_floor_fixed (outline->xmin);
+
+ for (i = 0; i < outline->outline_used; ++i)
+ {
+ /* Set NEXT_VERTEX to the next point (vertex) in this contour.
+
+ If i is past the end of the contour, then don't build edges
+ for this point. */
+ next_vertex = i + 1;
+
+ if (next_vertex == outline->outline_used
+ || !(outline->outline[next_vertex].flags
+ & SFNT_GLYPH_OUTLINE_LINETO))
+ continue;
+
+ /* Skip past horizontal vertices. */
+ if (outline->outline[next_vertex].y == outline->outline[i].y)
+ continue;
+
+ /* Figure out the winding direction. */
+ if (outline->outline[next_vertex].y < outline->outline[i].y)
+ /* Vector will cross imaginary ray from its bottom from the
+ left of the ray. Winding is thus 1. */
+ edges[edge].winding = 1;
+ else
+ /* Moving clockwise. Winding is thus -1. */
+ edges[edge].winding = -1;
+
+ /* Figure out the top and bottom values of this edge. If the
+ next edge is below, top is here and bot is the edge below.
+ If the next edge is above, then top is there and this is the
+ bottom. */
+
+ if (outline->outline[next_vertex].y < outline->outline[i].y)
+ {
+ /* End of edge is below this one (keep in mind this is a
+ cartesian coordinate system, so smaller values are below
+ larger ones.) */
+ top = i;
+ bottom = next_vertex;
+ }
+ else
+ {
+ /* End of edge is above this one. */
+ bottom = i;
+ top = next_vertex;
+ }
+
+ /* Record the edge. Rasterization happens from bottom to
+ up, so record the X at the bottom. */
+ dx = (outline->outline[top].x - outline->outline[bottom].x);
+ dy = abs (outline->outline[top].y
+ - outline->outline[bottom].y);
+
+ /* Compute the step X. This is how much X changes for each
+ increase in Y. */
+ step_x = sfnt_div_fixed (dx, dy);
+
+ /* And the step Y, which is the amount of movement to Y an
+ increase in X will incur. */
+ step_y = dx ? sfnt_div_fixed (dy, dx) : 0;
+
+ /* Save information computed above into the edge. */
+ edges[edge].top
+ = sfnt_fixed_float (outline->outline[top].y - ymin);
+ edges[edge].bottom
+ = sfnt_fixed_float (outline->outline[bottom].y - ymin);
+ edges[edge].x
+ = sfnt_fixed_float (outline->outline[bottom].x - xmin);
+ edges[edge].step_x = sfnt_fixed_float (step_x);
+ edges[edge].step_y = sfnt_fixed_float (step_y);
+ edges[edge].next = NULL;
+
+ /* Increment the edge index. */
+ edge++;
+ }
+
+ if (edge)
+ edge_proc (edges, edge, dcontext);
+}
+
+typedef void (*sfnt_step_raster_proc) (struct sfnt_step_raster *, void *);
+
+/* Append a step with the supplied COVERAGE at X to the sorted list of
+ scanline steps within the container RASTER. Y is the scanline to
+ append to. */
+
+static void
+sfnt_insert_raster_step (struct sfnt_step_raster *raster,
+ int x, float coverage, size_t scanline)
+{
+ struct sfnt_step_chunk *chunk;
+ struct sfnt_step *step, **p_next;
+
+ if (scanline >= raster->scanlines)
+ return;
+
+ if (x < 0)
+ x = 0;
+
+ /* Search within RASTER->steps[scanline] for a step at X. */
+
+ p_next = &raster->steps[scanline];
+
+ while ((step = *p_next))
+ {
+ if (step->x > x)
+ break;
+
+ if (step->x == x)
+ goto found;
+
+ p_next = &step->next;
+ }
+
+ if (!raster->chunks
+ || raster->chunks->nused == SFNT_BLOCK_STEPS)
+ {
+ /* All chunks have been consumed, and consequently a new chunk
+ must be allocated. */
+ chunk = xmalloc (sizeof *chunk);
+ chunk->next = raster->chunks;
+ chunk->nused = 0;
+ raster->chunks = chunk;
+ }
+ else
+ chunk = raster->chunks;
+
+ step = &chunk->steps[chunk->nused++];
+ step->next = *p_next;
+ *p_next = step;
+ step->x = x;
+ step->coverage = 0;
+
+ found:
+ step->coverage += coverage;
+}
+
+/* Draw EDGES, an unsorted array of polygon edges of size NEDGES.
+
+ Transform EDGES into an array of steps representing a raster with
+ HEIGHT scanlines, then call POLY_FUNC with DCONTEXT and the
+ resulting struct sfnt_step_raster to transfer it onto an actual
+ raster.
+
+ WIDTH must be the width of the raster. Although there is no
+ guarantee that no steps generated extend past WIDTH, steps starting
+ after width might be omitted, and as such it must be accurate. */
+
+static void
+sfnt_poly_edges_exact (struct sfnt_fedge *edges, size_t nedges,
+ size_t height, size_t width,
+ sfnt_step_raster_proc proc, void *dcontext)
+{
+ int y;
+ size_t size, e, edges_processed;
+ struct sfnt_fedge *active, **prev, *a, sentinel;
+ struct sfnt_step_raster raster;
+ struct sfnt_step_chunk *next, *last;
+
+ if (!height)
+ return;
+
+ /* Step down line by line. Find active edges. */
+
+ y = sfnt_floor_fixed (MAX (0, edges[0].bottom));
+ e = edges_processed = 0;
+ active = &sentinel;
+
+ /* Allocate the array of edges. */
+
+ raster.scanlines = height;
+ raster.chunks = NULL;
+
+ if (!INT_MULTIPLY_OK (height, sizeof *raster.steps, &size))
+ abort ();
+
+ raster.steps = xzalloc (size);
+
+ for (; y != height; y += 1)
+ {
+ /* Run over the whole array on each iteration of this loop;
+ experiments demonstrate this is faster for the majority of
+ glyphs. */
+ for (e = 0; e < nedges; ++e)
+ {
+ /* Although edges is unsorted, edges which have already been
+ processed will see their next fields set, and can thus be
+ disregarded. */
+ if (!edges[e].next
+ && (edges[e].bottom < y + 1)
+ && (edges[e].top > y))
+ {
+ /* As steps generated from each edge are sorted at the
+ time of their insertion, sorting the list of active
+ edges itself is redundant. */
+ edges[e].next = active;
+ active = &edges[e];
+
+ /* Increment the counter recording the number of edges
+ processed, which is used to terminate this loop early
+ once all have been processed. */
+ edges_processed++;
+ }
+ }
+
+ /* Iterate through each active edge, appending steps for it, and
+ removing it if it does not overlap with the next
+ scanline. */
+
+ for (prev = &active; (a = *prev) != &sentinel;)
+ {
+ float x_top, x_bot, x_min, x_max;
+ float y_top, y_bot;
+ int x_pixel_min, x_pixel_max;
+
+#define APPEND_STEP(x, coverage) \
+ sfnt_insert_raster_step (&raster, x, coverage, y);
+
+ /* Calculate several values to establish which overlap
+ category this edge falls into. */
+
+ y_top = y + 1; /* Topmost coordinate covered by this
+ edge in this scanline. */
+ y_bot = y; /* Bottom-most coordinate covered by this
+ edge in this scanline. */
+
+ /* III or IV? If the edge terminates before the next
+ scanline, make its terminus y_top. */
+
+ if (y_top > a->top)
+ y_top = a->top;
+
+ /* Same goes for y_bottom. */
+
+ if (a->bottom > y_bot)
+ y_bot = a->bottom;
+
+ /* y_top should never equal y_bottom, but check to be on the
+ safe side. */
+ if (y_top == y_bot)
+ goto next;
+
+ /* x_top and x_bot are the X positions where the edge enters
+ and exits this scanline. */
+
+ /*
+ (x_top)
+ +--------ee-----+------------------------------------------------+ (y_top)
+ | ee.......|................................................|
+ | ee.........|................................................|
+ | ee...........|................................................|
+ |ee.............|................................................|
+ ee---------------+------------------------------------------------+ (y_bot)
+(x_bot)
+ (y_bot might be further below.)
+ */
+
+ x_top = (y_top - a->bottom) * a->step_x + a->x;
+ x_bot = (y_bot - a->bottom) * a->step_x + a->x;
+
+ x_min = MIN (x_top, x_bot);
+ x_max = MAX (x_top, x_bot);
+
+ /* Pixels containing x_bot and x_top respectively. */
+ x_pixel_min = (int) (x_min);
+ x_pixel_max = (int) (x_max);
+
+#define TRAPEZOID_AREA(height, top_start, top_end, bot_start, bot_end) \
+ ((((float) (top_end) - (top_start)) \
+ + ((float) (bot_end) - (bot_start))) \
+ / 2.0f * (float) (height))
+
+ /* I, III? These two instances' criteria are that the edge
+ enters and exits within one pixel. */
+
+ if (x_pixel_min == x_pixel_max)
+ {
+ float xmin, xmax, ytop, ybot, height;
+ float coverage, delta;
+
+ /* Partial coverage for the first pixel. */
+
+ xmin = (x_min);
+ xmax = (x_max);
+ ytop = (y_top);
+ ybot = (y_bot);
+ height = ytop - ybot;
+
+ /* The trapezoid here is one of the following two:
+
+ ytop+------xmax--+-----------+---------------------------------------------+
+ | /................................................................|
+ | /.......|...........|.............................................|
+ | /........|...........|.............................................|
+ | /.........|...........|.............................................|
+ | / ...................................................................|
+ xmin+------------+-----------+---------------------------------------------+
+ ybot
+ ytop+------------+-----------+---------------------------------------------+
+ |\ xmin................................................................|
+ | \..........|...........|.............................................|
+ | \.........|...........|.............................................|
+ | \........|...........|.............................................|
+ | \.......|...........|.............................................|
+ | \................................................................|
+ +------xmax--+-----------+---------------------------------------------+
+
+ In either situation, the first pixel's coverage is
+ the space occupied by a trapezoid whose corners are
+ xmin and x_pixel_min + 1 and xmax and x_pixel_min +
+ 1, and whose height is ytop - ybot. The coverage for
+ the remainder is the height alone. */
+
+ coverage = (TRAPEZOID_AREA (height,
+ xmin, (int) xmin + 1,
+ xmax, (int) xmax + 1)
+ * a->winding);
+ APPEND_STEP (x_pixel_min, coverage);
+
+ /* Then if the next pixel isn't beyond the raster,
+ append complete coverage for it. */
+
+ if (x_pixel_min + 1 < width)
+ {
+ delta = (y_top - y_bot) * a->winding;
+ APPEND_STEP (x_pixel_max + 1, delta - coverage);
+ }
+ }
+ else
+ {
+ float dy, y_crossing, coverage;
+ float ytop, ybot, xtop, xbot, increment;
+ float x, last, here;
+
+ ytop = (y_top);
+ ybot = (y_bot);
+ xtop = (x_top);
+ xbot = (x_bot);
+
+#define TRIANGLE_AREA(width, height) \
+ ((width) * (height) / 2.0f)
+
+ /* II, IV. Coverage must be computed for each pixel
+ from x_pixel_min to x_pixel_max, with the latter
+ treated much as in I or III. */
+
+ if (x_bot < x_top)
+ {
+ /*
+
+
+ y_top x_top
+ +-----------+-----------+-----------+------------+-------/------+-------------------------------+
+ | | | | | /--.......|...............................|
+ |x_pixel_min| | | | /--..........|...............................|
+ | | | | /+-y_crossing...|...............................|
+ | | | | /--.|..............|...............................|
+ | | | | /-....|..............|...............................|
+ | | | | /--......|..x_pixel_max.|...............................|
+ | | | |/--.........|..............|...............................|
+ | | | /-+............|..............|...............................|
+ | | | /--..|............|..............|...............................|
+ | | | /--.....|............|..............|...............................|
+ | | |/--........|............|..............|...............................|
+ | | /-+...........|............|..............|...............................|
+ | | /--..|...........|............|..............|...............................|
+ | | /--.....|...........|............|..............|...............................|
+ | | /-........|...........|............|..............|...............................|
+ | /+-y_crossing|...........|............|..............|...............................|
+ | /--.|...........|...........|............|..............|...............................|
+ | /--....|...........|...........|............|..............|...............................|
+ | /--.......|...........|...........|............|..............|...............................|
+ +-----------+-----------+-----------+------------+--------------+-------------------------------+
+ y_bot x_bot
+
+
+The purpose of this code is to calculate the area occupied by dots of
+each pixel in between x_pixel_min and x_pixel_max + 1.
+
+The area occupied in the first pixel is a triangle comprising [x_bot,
+y_bot], [x_bot + 1, y_bot], and [x_bot + 1, y_crossing].
+
+The area occupied in the second pixel through x_pixel_max - 1 is that
+of a rectangle comprising [y_bot, pixel], [the previous rectangle's
+y_crossing, pixel], [the previous rectangle's y_crossing, pixel + 1],
+and [pixel + 1, y_bot] summed with the area the remaining triangle.
+
+The area occupied in the last pixel is a trapezoid proper.
+
+Thus the procedure is roughly as follows: dy is computed, which is the
+increase to the Y of the edge for each increase in scanline X. */
+
+ dy = a->step_y;
+
+ /* As is y_crossing for the first pixel. */
+ y_crossing = ybot + dy * ((int) xbot + 1 - xbot);
+
+ /* And the area of the first triangle.
+
+ The width is (int) xbot + 1 - xbot, and the
+ height is y_crossing - ybot. */
+ last = ((TRIANGLE_AREA (y_crossing - ybot,
+ (int) xbot + 1 - xbot))
+ * a->winding);
+ APPEND_STEP (x_pixel_min, last);
+
+ /* Coverage value for subsequent rectangles. The
+ value set here is for the next pixel, which is
+ filled from ybot to y_crossing. */
+
+ coverage = (y_crossing - ybot) * a->winding;
+ increment = dy * a->winding;
+
+ for (x = x_pixel_min + 1; x < x_pixel_max; x++)
+ {
+ here = coverage + increment / 2;
+ APPEND_STEP (x, here - last);
+ last = here;
+ coverage += increment;
+ }
+
+ /* The y_crossing for the last pixel. */
+ y_crossing = ybot + dy * ((int) xtop - xbot);
+
+ /* And calculate the area of the trapezoid in the
+ last pixel. */
+
+ coverage += a->winding * TRAPEZOID_AREA (ytop - y_crossing,
+ xtop,
+ (int) xtop + 1,
+ (int) xtop,
+ (int) xtop + 1);
+ here = coverage;
+ APPEND_STEP (x_pixel_max, here - last);
+ last = here;
+
+ /* Fill the remainder of the scanline with
+ height-derived coverage. */
+
+ if (x_pixel_max + 1 < width)
+ APPEND_STEP (x_pixel_max + 1, ((y_top - y_bot)
+ * a->winding - last));
+ }
+ else /* if (x_bot > x_top) */
+ {
+ /*
+
+ y_top x_top
+ +----------------+----------------+-----------------+-----------------+-----------------------------+
+ | \--........|................|.................|.................|.............................|
+ | \--.....|................|.................|.................|.............................|
+ | \--..|................|.................|.................|.............................|
+ | \-+.y_crossing.....|.................|.................|.............................|
+ | |\--.............|.................|.................|.............................|
+ | | \--..........|.................|.................|.............................|
+ | x_pixel_min | \---......|.................|.................|.............................|
+ | | \--...|.................|.................|.............................|
+ | | \--|y_crossing.......|.................|.............................|
+ | | \--...............|.................|.............................|
+ | | | \--............|.................|.............................|
+ | | | \--.........|.................|.............................|
+ | | | \--......|.................|.............................|
+ +----------------+----------------+-----------\-----+-----------------+-----------------------------+
+ y_bot x_bot
+
+Whereas in this situation the trapezoid is inverted, and the code must
+be as well. */
+
+ /* The edge's Y decreases as the edge's X increases,
+ yielding a negative a->step_x. */
+ dy = a->step_y;
+
+ /* Calculate y_crossing for the first pixel. */
+ y_crossing = ytop + dy * ((int) xtop + 1 - xtop);
+
+ /* And the area of the first triangle. */
+ last = ((TRIANGLE_AREA ((int) xtop + 1 - xtop,
+ ytop - y_crossing))
+ * a->winding);
+ APPEND_STEP (x_pixel_min, last);
+
+ /* Coverage value for subsequent rectangles. The
+ value set here is for the next pixel, which is
+ filled from ytop to y_crossing. */
+ coverage = (ytop - y_crossing) * a->winding;
+ increment = -dy * a->winding;
+
+ for (x = x_pixel_min + 1; x < x_pixel_max; x ++)
+ {
+ here = coverage + increment / 2;
+ APPEND_STEP (x, here - last);
+ last = here;
+ coverage += increment;
+ }
+
+ /* The y_crossing for the last pixel. */
+ y_crossing = ytop + dy * ((int) xbot - xtop);
+
+ /* And calculate the area of the trapezoid in the
+ last pixel. */
+
+ coverage += a->winding * TRAPEZOID_AREA (y_crossing - ybot,
+ (int) xbot,
+ (int) xbot + 1,
+ xbot,
+ (int) xbot + 1);
+ here = coverage;
+ APPEND_STEP (x_pixel_max, here - last);
+ last = here;
+
+ /* Fill the remainder of the scanline with
+ height-derived coverage. */
+
+ if (x_pixel_max + 1 < width)
+ APPEND_STEP (x_pixel_max + 1, ((y_top - y_bot)
+ * a->winding - last));
+ }
+
+#undef TRIANGLE_AREA
+ }
+
+#undef APPEND_STEP
+#undef TRAPEZOID_AREA
+
+ /* When an edge is created, its a->bottom (and by extension
+ a->y) is not aligned to a->x. Since this iteration can
+ only affect the scan line Y, align a to the next
+ scanline, that the next iteration of this loop to
+ consider it might consider its entire intersection. */
+ a->x += a->step_x * (y + 1 - a->bottom);
+ a->bottom = y + 1;
+ next:
+
+ if (a->top < y + 1)
+ *prev = a->next;
+ else
+ /* This edge doesn't intersect with the next scanline;
+ remove it from the list. After the edge at hand is so
+ deleted from the list, its next field remains set,
+ excluding it from future consideration. */
+ prev = &a->next;
+ }
+
+ /* Break if all is done. */
+ if (active == &sentinel && edges_processed == nedges)
+ break;
+ }
+
+ (*proc) (&raster, dcontext);
+ xfree (raster.steps);
+
+ /* Free each block of steps allocated. */
+ next = raster.chunks;
+ while (next)
+ {
+ last = next;
+ next = next->next;
+ xfree (last);
+ }
+
+#undef ONE_PIXEL
+}
+
+/* Apply winding rule to the coverage value VALUE. Convert VALUE to a
+ number between 0 and 255. If VALUE is negative, invert it. If it
+ exceeds 255 afterwards, truncate it to 255. */
+
+static int
+sfnt_compute_fill (float value)
+{
+ if (value < 0)
+ value = -value;
+
+ return MIN (value * 255, 255);
+}
+
+/* Set N pixels at DATA to the value VALUE. If N is large, call
+ memset; otherwise set this by hand. */
+
+static void
+sfnt_poly_set_steps (unsigned char *data, int value, int n)
+{
+ unsigned char *p;
+
+ p = data;
+ switch (n)
+ {
+ case 7:
+ *p++ = value;
+ FALLTHROUGH;
+ case 6:
+ *p++ = value;
+ FALLTHROUGH;
+ case 5:
+ *p++ = value;
+ FALLTHROUGH;
+ case 4:
+ *p++ = value;
+ FALLTHROUGH;
+ case 3:
+ *p++ = value;
+ FALLTHROUGH;
+ case 2:
+ *p++ = value;
+ FALLTHROUGH;
+ case 1:
+ *p++ = value;
+ FALLTHROUGH;
+ case 0:
+ break;
+ default:
+ memset (data, value, n);
+ }
+}
+
+/* Transfer steps generated by sfnt_poly_edges_exact from STEPS to the
+ provided raster RASTER. */
+
+static void
+sfnt_poly_steps (struct sfnt_step_raster *steps,
+ struct sfnt_raster *raster)
+{
+ int y;
+ unsigned char *data;
+ int x, xend, fill;
+ float total;
+ struct sfnt_step *step;
+
+ y = 0; /* This y is an X-style coordinate in RASTER's space.
+
+ Its counterpart array of steps is STEPS->steps[
+ raster->height - y - 1]. */
+ data = raster->cells;
+
+ for (y = 0; y < raster->height; ++y, data += raster->stride)
+ {
+ fill = total = x = 0;
+
+ for (step = steps->steps[raster->height - y - 1];
+ step && x < raster->width; step = step->next)
+ {
+ xend = MIN (step->x, raster->width);
+
+ if (fill)
+ sfnt_poly_set_steps (data + x, fill, xend - x);
+
+ total += step->coverage;
+ fill = sfnt_compute_fill (total);
+ x = xend;
+ }
+
+ if (x < raster->width)
+ sfnt_poly_set_steps (data + x, fill, raster->width - x);
+ }
+}
+
+/* Poly each edge in EDGES onto the raster supplied in DCONTEXT. */
+
+static void
+sfnt_raster_steps (struct sfnt_step_raster *steps, void *dcontext)
+{
+ sfnt_poly_steps (steps, dcontext);
+}
+
+/* Call sfnt_poly_edges_exact with suitable arguments for polying
+ EDGES onto DCONTEXT, a raster structure. */
+
+static void
+sfnt_raster_edges_exact (struct sfnt_fedge *edges, size_t size,
+ void *dcontext)
+{
+ struct sfnt_raster *raster;
+
+ raster = dcontext;
+ sfnt_poly_edges_exact (edges, size, raster->height,
+ raster->width, sfnt_raster_steps,
+ dcontext);
+}
+
+/* Generate an alpha mask for the glyph outline OUTLINE by means of
+ the exact coverage scaler. Value is the alpha mask upon success,
+ NULL upon failure. */
+
+TEST_STATIC struct sfnt_raster *
+sfnt_raster_glyph_outline_exact (struct sfnt_glyph_outline *outline)
+{
+ struct sfnt_raster raster, *data;
+
+ /* Get the raster parameters. */
+ sfnt_prepare_raster (&raster, outline);
+
+ /* Allocate the raster data. */
+ data = xmalloc (sizeof *data + raster.stride * raster.height);
+ *data = raster;
+ data->cells = (unsigned char *) (data + 1);
+ memset (data->cells, 0, raster.stride * raster.height);
+
+ /* Generate edges for the outline, polying each array of edges to
+ the raster. */
+ sfnt_build_outline_fedges (outline, sfnt_raster_edges_exact, data);
+
+ /* All done. */
+ return data;
+}
+
+
+
/* Glyph metrics computation. */
/* Read an hmtx table from the font FD, using the table directory
@@ -4632,7 +5673,7 @@ sfnt_read_hmtx_table (int fd, struct sfnt_offset_subtable *subtable,
/* Read into hmtx + 1. */
rc = read (fd, hmtx + 1, size);
- if (rc < size)
+ if (rc == -1 || rc < size)
{
xfree (hmtx);
return NULL;
@@ -4659,27 +5700,22 @@ sfnt_read_hmtx_table (int fd, struct sfnt_offset_subtable *subtable,
return hmtx;
}
-/* Obtain glyph metrics for the glyph indiced by GLYPH at the
- specified PIXEL_SIZE. Return 0 and the metrics in *METRICS if
- metrics could be found, else 1.
-
- If PIXEL_SIZE is -1, do not perform any scaling on the glyph
- metrics; HEAD need not be specified in that case.
+/* Obtain unscaled glyph metrics for the glyph indexed by GLYPH.
+ Return 0 and the metrics in *METRICS if metrics could be found,
+ else 1.
- HMTX, HHEA, HEAD and MAXP should be the hmtx, hhea, head, and maxp
- tables of the font respectively. */
+ HMTX, HHEA and MAXP should be the hmtx, hhea, head, and maxp tables
+ of the font respectively. */
TEST_STATIC int
-sfnt_lookup_glyph_metrics (sfnt_glyph glyph, int pixel_size,
+sfnt_lookup_glyph_metrics (sfnt_glyph glyph,
struct sfnt_glyph_metrics *metrics,
struct sfnt_hmtx_table *hmtx,
struct sfnt_hhea_table *hhea,
- struct sfnt_head_table *head,
struct sfnt_maxp_table *maxp)
{
short lbearing;
unsigned short advance;
- sfnt_fixed factor;
if (glyph < hhea->num_of_long_hor_metrics)
{
@@ -4701,37 +5737,27 @@ sfnt_lookup_glyph_metrics (sfnt_glyph glyph, int pixel_size,
/* No entry corresponds to the glyph. */
return 1;
- if (pixel_size == -1)
- {
- /* Return unscaled metrics in this case. */
- metrics->lbearing = lbearing;
- metrics->advance = advance;
- return 0;
- }
-
- /* Now scale lbearing and advance up to the pixel size. */
- factor = sfnt_div_fixed (pixel_size, head->units_per_em);
-
- /* Save them. */
- metrics->lbearing = sfnt_mul_fixed (lbearing * 65536, factor);
- metrics->advance = sfnt_mul_fixed (advance * 65536, factor);
-
- /* All done. */
+ /* Return unscaled metrics. */
+ metrics->lbearing = lbearing;
+ metrics->advance = advance;
return 0;
}
-/* Scale the specified glyph metrics by FACTOR.
- Set METRICS->lbearing and METRICS->advance to their current
- values times factor. */
+/* Scale the specified glyph metrics by FACTOR. Set METRICS->lbearing
+ and METRICS->advance to their current values times factor; take the
+ floor of the left bearing and round the advance width. */
MAYBE_UNUSED TEST_STATIC void
sfnt_scale_metrics (struct sfnt_glyph_metrics *metrics,
sfnt_fixed factor)
{
- metrics->lbearing
- = sfnt_mul_fixed (metrics->lbearing * 65536, factor);
- metrics->advance
- = sfnt_mul_fixed (metrics->advance * 65536, factor);
+ sfnt_fixed lbearing, advance;
+
+ lbearing = sfnt_mul_fixed (metrics->lbearing * 65536, factor);
+ advance = sfnt_mul_fixed (metrics->advance * 65536, factor);
+
+ metrics->lbearing = sfnt_floor_fixed (lbearing);
+ metrics->advance = sfnt_round_fixed (advance);
}
/* Calculate the factor used to convert em space to device space for a
@@ -4743,7 +5769,7 @@ sfnt_get_scale (struct sfnt_head_table *head, int ppem)
/* Figure out how to convert from font unit-space to pixel space.
To turn one unit to its corresponding pixel size given a ppem of
1, the unit must be divided by head->units_per_em. Then, it must
- be multipled by the ppem. So,
+ be multiplied by the ppem. So,
PIXEL = UNIT / UPEM * PPEM
@@ -4796,7 +5822,7 @@ sfnt_read_name_table (int fd, struct sfnt_offset_subtable *subtable)
/* Read the fixed length data. */
rc = read (fd, name, required);
- if (rc < required)
+ if (rc == -1 || rc < required)
{
xfree (name);
return NULL;
@@ -4830,8 +5856,8 @@ sfnt_read_name_table (int fd, struct sfnt_offset_subtable *subtable)
rc = read (fd, name->name_records,
(name->count
* sizeof *name->name_records));
- if (rc < (name->count
- * sizeof *name->name_records))
+ if (rc == -1 || (rc < (name->count
+ * sizeof *name->name_records)))
{
xfree (name);
return NULL;
@@ -4883,11 +5909,11 @@ sfnt_read_name_table (int fd, struct sfnt_offset_subtable *subtable)
return NULL;
}
- /* Read REQURIED bytes into the string data. */
+ /* Read REQUIRED bytes into the string data. */
name->data = (unsigned char *) (name->name_records
+ name->count);
rc = read (fd, name->data, required);
- if (rc < required)
+ if (rc == -1 || rc < required)
{
xfree (name);
return NULL;
@@ -4969,7 +5995,7 @@ sfnt_read_meta_table (int fd, struct sfnt_offset_subtable *subtable)
/* Read the header. */
rc = read (fd, meta, required);
- if (rc < required)
+ if (rc == -1 || rc < required)
{
xfree (meta);
return NULL;
@@ -5115,7 +6141,7 @@ sfnt_read_ttc_header (int fd)
size = SFNT_ENDOF (struct sfnt_ttc_header, num_fonts,
uint32_t);
rc = read (fd, ttc, size);
- if (rc < size)
+ if (rc == -1 || rc < size)
{
xfree (ttc);
return NULL;
@@ -5147,7 +6173,7 @@ sfnt_read_ttc_header (int fd)
ttc = xrealloc (ttc, sizeof *ttc + size);
ttc->offset_table = (uint32_t *) (ttc + 1);
rc = read (fd, ttc->offset_table, size);
- if (rc < size)
+ if (rc == -1 || rc < size)
{
xfree (ttc);
return NULL;
@@ -5170,7 +6196,7 @@ sfnt_read_ttc_header (int fd)
uint32_t)
- offsetof (struct sfnt_ttc_header, ul_dsig_tag));
rc = read (fd, &ttc->ul_dsig_offset, size);
- if (rc < size)
+ if (rc == -1 || rc < size)
{
xfree (ttc);
return NULL;
@@ -5502,7 +6528,8 @@ sfnt_mul_f26dot6_fixed (sfnt_f26dot6 x, sfnt_fixed y)
product = (uint64_t) y * (uint64_t) x;
/* This can be done quickly with int64_t. */
- return ((int64_t) (product + 32676) / (int64_t) 65536) * sign;
+ return ((int64_t) (product + 32768)
+ / (int64_t) 65536) * sign;
#else
struct sfnt_large_integer temp;
int sign;
@@ -5681,7 +6708,7 @@ sfnt_make_interpreter (struct sfnt_maxp_table *maxp,
interpreter->run_hook = NULL;
interpreter->push_hook = NULL;
interpreter->pop_hook = NULL;
-#endif
+#endif /* TEST */
/* Fill in pointers and default values. */
interpreter->max_stack_elements = maxp->max_stack_elements;
@@ -5731,7 +6758,7 @@ sfnt_make_interpreter (struct sfnt_maxp_table *maxp,
/* Now compute the scale. Then, scale up the control value table
values. */
interpreter->scale
- = sfnt_div_fixed (pixel_size, head->units_per_em);
+ = sfnt_div_fixed (pixel_size * 64, head->units_per_em);
/* Set the PPEM. */
interpreter->ppem = pixel_size;
@@ -5747,7 +6774,7 @@ sfnt_make_interpreter (struct sfnt_maxp_table *maxp,
/* Load the control value table. */
for (i = 0; i < interpreter->cvt_size; ++i)
interpreter->cvt[i]
- = sfnt_mul_f26dot6_fixed (cvt->values[i] * 64,
+ = sfnt_mul_f26dot6_fixed (cvt->values[i],
interpreter->scale);
/* Fill in the default values for phase, period and threshold. */
@@ -5799,7 +6826,7 @@ enum sfnt_interpreter_run_context
After this is called, it is probably okay to reuse INTERPRETER.
However, instructions must always be reloaded. */
-_Noreturn static void
+static AVOID
sfnt_interpret_trap (struct sfnt_interpreter *interpreter,
const char *reason)
{
@@ -5841,15 +6868,6 @@ sfnt_interpret_trap (struct sfnt_interpreter *interpreter,
TRAP ("instruction executed not valid" \
" outside control value program") \
-#define sfnt_add(a, b) \
- ((int) ((unsigned int) (a) + (unsigned int) (b)))
-
-#define sfnt_sub(a, b) \
- ((int) ((unsigned int) (a) - (unsigned int) (b)))
-
-#define sfnt_mul(a, b) \
- ((int) ((unsigned int) (a) * (unsigned int) (b)))
-
/* Register, alu and logic instructions. */
@@ -5884,7 +6902,7 @@ sfnt_interpret_trap (struct sfnt_interpreter *interpreter,
? (TRAP ("stack underflow"), 0) \
: *(interpreter->SP - 1))
-#if !defined TEST || !0
+#if !defined TEST
#define PUSH(value) \
{ \
@@ -5902,7 +6920,7 @@ sfnt_interpret_trap (struct sfnt_interpreter *interpreter,
interpreter->SP++; \
}
-#else /* TEST && 0 */
+#else /* TEST */
#define PUSH(value) \
{ \
@@ -6071,8 +7089,8 @@ sfnt_interpret_trap (struct sfnt_interpreter *interpreter,
single_width = POP (); \
\
interpreter->state.single_width_value \
- = (interpreter->scale * single_width \
- / 1024); \
+ = sfnt_mul_fixed (single_width, \
+ interpreter->scale); \
}
#define DUP() \
@@ -6600,8 +7618,8 @@ sfnt_interpret_trap (struct sfnt_interpreter *interpreter,
TRAP ("WCVTF out of bounds"); \
\
interpreter->cvt[location] \
- = (interpreter->scale * value \
- / 1024); \
+ = sfnt_mul_fixed (value, \
+ interpreter->scale); \
}
#define JROT() \
@@ -6657,9 +7675,12 @@ sfnt_interpret_trap (struct sfnt_interpreter *interpreter,
interpreter->state.scan_control = value; \
}
-/* Selector bit 8 is undocumented, but present in the Macintosh
+/* Selector bit 3 is undocumented, but present in the Macintosh
rasterizer. 02000 is returned if there is a variation axis in
- use. */
+ use.
+
+ Selector bit 5 is undocumented, but relied on by several fonts.
+ 010000 is returned if a grayscale rasterizer is in use. */
#define GETINFO() \
{ \
@@ -6676,6 +7697,9 @@ sfnt_interpret_trap (struct sfnt_interpreter *interpreter,
&& interpreter->norm_coords) \
k |= 02000; \
\
+ if (selector & 32) \
+ k |= 010000; \
+ \
PUSH_UNCHECKED (k); \
}
@@ -7135,8 +8159,8 @@ sfnt_interpret_trap (struct sfnt_interpreter *interpreter,
vector \
= interpreter->state.projection_vector; \
\
- PUSH ((uint16_t) vector.x); \
- PUSH ((uint16_t) vector.y); \
+ PUSH ((int32_t) vector.x); \
+ PUSH ((int32_t) vector.y); \
}
#define GFV() \
@@ -7146,8 +8170,8 @@ sfnt_interpret_trap (struct sfnt_interpreter *interpreter,
vector \
= interpreter->state.freedom_vector; \
\
- PUSH ((uint16_t) vector.x); \
- PUSH ((uint16_t) vector.y); \
+ PUSH ((int32_t) vector.x); \
+ PUSH ((int32_t) vector.y); \
}
#define SFVTPV() \
@@ -7431,6 +8455,8 @@ static void
sfnt_interpret_utp (struct sfnt_interpreter *interpreter,
uint32_t p)
{
+ unsigned char mask;
+
if (!interpreter->state.zp0)
{
if (p >= interpreter->twilight_zone_size)
@@ -7444,7 +8470,31 @@ sfnt_interpret_utp (struct sfnt_interpreter *interpreter,
|| p >= interpreter->glyph_zone->num_points)
TRAP ("UTP[] p lies outside glyph zone");
- interpreter->glyph_zone->flags[p] &= ~SFNT_POINT_TOUCHED_X;
+ /* The flags unset by UTP are subject to which axes in the freedom
+ vector are significant, as stated in the TrueType reference
+ manual by this needless mouthful:
+
+ A point may be touched in the x-direction, the y-direction, or
+ in both the x and y-directions. The position of the freedom
+ vector determines whether the point is untouched in the
+ x-direction, the y-direction, or both. If the vector is set to
+ the x-axis, the point will be untouched in the x-direction. If
+ the vector is set to the y-axis, the point will be untouched in
+ the y-direction. Otherwise the point will be untouched in both
+ directions.
+
+ A points that is marked as untouched will be moved by an IUP[]
+ instruction even if the point was previously touched. */
+
+ mask = 0xff;
+
+ if (interpreter->state.freedom_vector.x)
+ mask &= ~SFNT_POINT_TOUCHED_X;
+
+ if (interpreter->state.freedom_vector.y)
+ mask &= ~SFNT_POINT_TOUCHED_Y;
+
+ interpreter->glyph_zone->flags[p] &= mask;
}
/* Save the specified unit VECTOR into INTERPRETER's graphics state as
@@ -8785,7 +9835,7 @@ sfnt_deltac (int number, struct sfnt_interpreter *interpreter,
Touch the point P (within the zone specified in zp0) in the
directions specified in the freedom vector. Then, if OPCODE is
- 0x7f, round the point and move it the rounded distance along the
+ 0x2f, round the point and move it the rounded distance along the
freedom vector.
Finally, set the RP0 and RP1 registers to P. */
@@ -8801,7 +9851,7 @@ sfnt_interpret_mdap (struct sfnt_interpreter *interpreter,
/* Measure the current distance. */
here = sfnt_project_vector (interpreter, px, py);
- if (opcode == 0x7f)
+ if (opcode == 0x2f)
{
/* Measure distance, round, then move to the distance. */
distance = sfnt_project_vector (interpreter, px, py);
@@ -8828,12 +9878,10 @@ sfnt_interpret_mdap (struct sfnt_interpreter *interpreter,
static void
sfnt_deltap (int number, struct sfnt_interpreter *interpreter,
- unsigned char operand, unsigned int index)
+ unsigned char operand, unsigned int p)
{
int ppem, delta;
- return;
-
/* Extract the ppem from OPERAND. The format is the same as in
sfnt_deltac. */
@@ -8937,8 +9985,8 @@ sfnt_deltap (int number, struct sfnt_interpreter *interpreter,
delta *= 1l << (6 - interpreter->state.delta_shift);
/* Move the point. */
- sfnt_check_zp0 (interpreter, index);
- sfnt_move_zp0 (interpreter, index, 1, delta);
+ sfnt_check_zp0 (interpreter, p);
+ sfnt_move_zp0 (interpreter, p, 1, delta);
}
/* Needed by sfnt_interpret_call. */
@@ -9530,7 +10578,7 @@ sfnt_dot_fix_14 (int32_t ax, int32_t ay, int bx, int by)
yy = xx >> 63;
xx += 0x2000 + yy;
- return (int32_t) (xx / (2 << 14));
+ return (int32_t) (xx / (1 << 14));
#endif
}
@@ -9655,7 +10703,7 @@ sfnt_move (sfnt_f26dot6 *restrict x, sfnt_f26dot6 *restrict y,
if (versor)
{
- /* Move along X axis, converting the distance to the freedom
+ /* Move along Y axis, converting the distance to the freedom
vector. */
num = n;
k = sfnt_multiply_divide_signed (distance,
@@ -9673,6 +10721,15 @@ sfnt_move (sfnt_f26dot6 *restrict x, sfnt_f26dot6 *restrict y,
}
}
+/* Compute the dot product of the two versors A and B with
+ rounding. */
+
+static sfnt_f2dot14
+sfnt_short_frac_dot (sfnt_f2dot14 a, sfnt_f2dot14 b)
+{
+ return (sfnt_f2dot14) ((((long) a * b) + 8192) / 16384);
+}
+
/* Validate the graphics state GS.
Establish function pointers for rounding and projection.
Establish dot product used to convert vector distances between
@@ -9749,11 +10806,18 @@ sfnt_validate_gs (struct sfnt_graphics_state *gs)
gs->vector_dot_product = gs->projection_vector.y;
else
/* Actually calculate the dot product. */
- gs->vector_dot_product = ((((long) gs->projection_vector.x
- * gs->freedom_vector.x)
- + ((long) gs->projection_vector.y
- * gs->freedom_vector.y))
- / 16384);
+ gs->vector_dot_product = (sfnt_short_frac_dot (gs->projection_vector.x,
+ gs->freedom_vector.x)
+ + sfnt_short_frac_dot (gs->projection_vector.y,
+ gs->freedom_vector.y));
+
+ /* If the product is less than 1/16th of a vector, prevent overflow
+ by resetting it to 1. */
+
+ if (gs->vector_dot_product > -0x400
+ && gs->vector_dot_product < 0x400)
+ gs->vector_dot_product = (gs->vector_dot_product < 0
+ ? -0x4000 : 0x4000);
/* Now figure out which function to use to move distances. Handle
the common case where both the freedom and projection vectors are
@@ -10362,8 +11426,8 @@ sfnt_interpret_mdrp (struct sfnt_interpreter *interpreter,
uint32_t opcode)
{
uint32_t p;
- sfnt_f26dot6 distance, delta;
- sfnt_f26dot6 current_projection, original_projection;
+ sfnt_f26dot6 distance, applied;
+ sfnt_f26dot6 current_projection;
sfnt_f26dot6 x, y, org_x, org_y;
sfnt_f26dot6 rx, ry, org_rx, org_ry;
@@ -10375,20 +11439,21 @@ sfnt_interpret_mdrp (struct sfnt_interpreter *interpreter,
sfnt_address_zp0 (interpreter, interpreter->state.rp0,
&rx, &ry, &org_rx, &org_ry);
+ /* Calculate the distance between P and rp0 prior to hinting. */
distance = DUAL_PROJECT (org_x - org_rx,
org_y - org_ry);
- original_projection = distance;
+
+ /* Calculate the distance between P and rp0 as of now in the hinting
+ process. */
current_projection = PROJECT (x - rx, y - ry);
/* Test against the single width value. */
- delta = sfnt_sub (distance,
- interpreter->state.single_width_value);
-
- if (delta < 0)
- delta = -delta;
-
- if (delta < interpreter->state.sw_cut_in)
+ if (interpreter->state.sw_cut_in > 0
+ && distance < (interpreter->state.single_width_value
+ + interpreter->state.sw_cut_in)
+ && distance > (interpreter->state.single_width_value
+ - interpreter->state.sw_cut_in))
{
/* Use the single width instead, as the CVT entry is too
small. */
@@ -10399,38 +11464,34 @@ sfnt_interpret_mdrp (struct sfnt_interpreter *interpreter,
distance = -interpreter->state.single_width_value;
}
- /* Flag B means look at the cvt cut in and round the
- distance. */
+ /* Flag B implies that the distance should be rounded. The CVT cut
+ in is not taken into account by MDRP, contrary to earlier
+ presumptions. */
if (opcode & 4)
- {
- delta = sfnt_sub (distance, original_projection);
-
- if (delta < 0)
- delta = -delta;
-
- if (delta > interpreter->state.cvt_cut_in)
- distance = original_projection;
-
- /* Now, round the distance. */
- distance = sfnt_round_symmetric (interpreter, distance);
- }
+ applied = sfnt_round_symmetric (interpreter, distance);
+ else
+ applied = distance;
/* Flag C means look at the minimum distance. */
if (opcode & 8)
{
- if (original_projection >= 0
- && distance < interpreter->state.minimum_distance)
- distance = interpreter->state.minimum_distance;
- else if (original_projection < 0
- && distance > -interpreter->state.minimum_distance)
- distance = -interpreter->state.minimum_distance;
+ /* Test the sign of the initial distance, but compare the
+ distance that will be applied in reality against the minimum
+ distance. */
+
+ if (distance >= 0
+ && applied < interpreter->state.minimum_distance)
+ applied = interpreter->state.minimum_distance;
+ else if (distance < 0
+ && applied > -interpreter->state.minimum_distance)
+ applied = -interpreter->state.minimum_distance;
}
/* Finally, move the point. */
sfnt_move_zp1 (interpreter, p, 1,
- sfnt_sub (distance, current_projection));
+ sfnt_sub (applied, current_projection));
/* Set RP1 to RP0 and RP2 to the point. If flag 3 is set, also make
it RP0. */
@@ -11103,6 +12164,38 @@ sfnt_interpret_control_value_program (struct sfnt_interpreter *interpreter,
if (interpreter->state.instruct_control & 4)
sfnt_init_graphics_state (&interpreter->state);
+ else
+ {
+ /* And even if not, reset the following graphics state
+ variables, to which both the Apple and MS scalers don't
+ permit modifications from the preprogram.
+
+ Not only is such reversion undocumented, it is also
+ inefficient, for modern fonts at large only move points on
+ the Y axis. As such, these fonts must issue a redundant
+ SVTCA[Y] instruction within each glyph program, in place of
+ initializing the projection and freedom vectors once and for
+ all in prep. Unfortunately many fonts which do instruct on
+ the X axis now rely on this ill-conceived behavior, so Emacs
+ must, reluctantly, follow suit. */
+
+ interpreter->state.dual_projection_vector.x = 040000; /* 1.0 */
+ interpreter->state.dual_projection_vector.y = 0;
+ interpreter->state.freedom_vector.x = 040000; /* 1.0 */
+ interpreter->state.freedom_vector.y = 0;
+ interpreter->state.projection_vector.x = 040000; /* 1.0 */
+ interpreter->state.projection_vector.y = 0;
+ interpreter->state.rp0 = 0;
+ interpreter->state.rp1 = 0;
+ interpreter->state.rp2 = 0;
+ interpreter->state.zp0 = 1;
+ interpreter->state.zp1 = 1;
+ interpreter->state.zp2 = 1;
+ interpreter->state.loop = 1;
+
+ /* Validate the graphics state. */
+ sfnt_validate_gs (&interpreter->state);
+ }
/* Save the graphics state upon success. */
memcpy (state, &interpreter->state, sizeof *state);
@@ -11195,15 +12288,18 @@ sfnt_decompose_instructed_outline (struct sfnt_instructed_outline *outline,
/* Decompose and build an outline for the specified instructed outline
INSTRUCTED. Return the outline data with a refcount of 0 upon
- success, or NULL upon failure.
+ success, and the advance width of the instructed glyph in
+ *ADVANCE_WIDTH, or NULL upon failure.
This function is not reentrant. */
TEST_STATIC struct sfnt_glyph_outline *
-sfnt_build_instructed_outline (struct sfnt_instructed_outline *instructed)
+sfnt_build_instructed_outline (struct sfnt_instructed_outline *instructed,
+ sfnt_fixed *advance_width)
{
struct sfnt_glyph_outline *outline;
int rc;
+ sfnt_f26dot6 x1, x2;
memset (&build_outline_context, 0, sizeof build_outline_context);
@@ -11240,10 +12336,23 @@ sfnt_build_instructed_outline (struct sfnt_instructed_outline *instructed)
instructed. */
if (instructed->num_points > 1)
- outline->origin
- = instructed->x_points[instructed->num_points - 2];
+ {
+ x1 = instructed->x_points[instructed->num_points - 2];
+ x2 = instructed->x_points[instructed->num_points - 1];
+
+ /* Convert the origin point to a 16.16 fixed point number. */
+ outline->origin = x1 * 1024;
+
+ /* Do the same for the advance width. */
+ *advance_width = (x2 - x1) * 1024;
+ }
else
- outline->origin = 0;
+ {
+ /* Phantom points are absent from this outline, which is
+ impossible. */
+ *advance_width = 0;
+ outline->origin = 0;
+ }
if (rc)
{
@@ -11261,14 +12370,18 @@ sfnt_build_instructed_outline (struct sfnt_instructed_outline *instructed)
scale SCALE.
Place the X and Y coordinates of the first phantom point in *X1 and
- *Y1, and those of the second phantom point in *X2 and *Y2. */
+ *Y1, and those of the second phantom point in *X2 and *Y2.
+
+ Place the unrounded X coordinates of both phantom points in *S1 and
+ *S2 respectively. */
static void
sfnt_compute_phantom_points (struct sfnt_glyph *glyph,
struct sfnt_glyph_metrics *metrics,
sfnt_fixed scale,
sfnt_f26dot6 *x1, sfnt_f26dot6 *y1,
- sfnt_f26dot6 *x2, sfnt_f26dot6 *y2)
+ sfnt_f26dot6 *x2, sfnt_f26dot6 *y2,
+ sfnt_f26dot6 *s1, sfnt_f26dot6 *s2)
{
sfnt_fword f1, f2;
@@ -11288,8 +12401,14 @@ sfnt_compute_phantom_points (struct sfnt_glyph *glyph,
f2 += glyph->advance_distortion;
/* Next, scale both up. */
- *x1 = sfnt_mul_f26dot6_fixed (f1 * 64, scale);
- *x2 = sfnt_mul_f26dot6_fixed (f2 * 64, scale);
+ *s1 = sfnt_mul_f26dot6_fixed (f1, scale);
+ *s2 = sfnt_mul_f26dot6_fixed (f2, scale);
+
+ /* While not expressly provided in the manual, the phantom points
+ (at times termed the advance and origin points) represent pixel
+ coordinates within the raster, and are therefore rounded. */
+ *x1 = sfnt_round_f26dot6 (*s1);
+ *x2 = sfnt_round_f26dot6 (*s2);
/* Clear y1 and y2. */
*y1 = 0;
@@ -11312,9 +12431,7 @@ sfnt_interpret_simple_glyph (struct sfnt_glyph *glyph,
size_t zone_size, temp, outline_size, i;
struct sfnt_interpreter_zone *zone;
struct sfnt_interpreter_zone *volatile preserved_zone;
- sfnt_f26dot6 phantom_point_1_x;
sfnt_f26dot6 phantom_point_1_y;
- sfnt_f26dot6 phantom_point_2_x;
sfnt_f26dot6 phantom_point_2_y;
sfnt_f26dot6 tem;
volatile bool zone_was_allocated;
@@ -11369,23 +12486,25 @@ sfnt_interpret_simple_glyph (struct sfnt_glyph *glyph,
tem = glyph->simple->x_coordinates[i];
/* Scale that fword. */
- tem = sfnt_mul_f26dot6_fixed (tem * 64, interpreter->scale);
+ tem = sfnt_mul_f26dot6_fixed (tem, interpreter->scale);
/* Set x_points and x_current. */
zone->x_points[i] = tem;
zone->x_current[i] = tem;
}
- /* Compute phantom points. */
+ /* Compute and load phantom points. */
sfnt_compute_phantom_points (glyph, metrics, interpreter->scale,
- &phantom_point_1_x, &phantom_point_1_y,
- &phantom_point_2_x, &phantom_point_2_y);
-
- /* Load phantom points. */
- zone->x_points[i] = phantom_point_1_x;
- zone->x_points[i + 1] = phantom_point_2_x;
- zone->x_current[i] = phantom_point_1_x;
- zone->x_current[i + 1] = phantom_point_2_x;
+ &zone->x_current[i], &phantom_point_1_y,
+ &zone->x_current[i + 1], &phantom_point_2_y,
+ /* Phantom points are rounded to the
+ pixel grid once they are inserted
+ into the glyph zone, but the
+ original coordinates must remain
+ untouched, as fonts rely on this to
+ interpolate points by this
+ scale. */
+ &zone->x_points[i], &zone->x_points[i + 1]);
/* Load y_points and y_current, along with flags. */
for (i = 0; i < glyph->simple->number_of_points; ++i)
@@ -11395,7 +12514,7 @@ sfnt_interpret_simple_glyph (struct sfnt_glyph *glyph,
/* Scale that fword. Make sure not to round Y, as this could
lead to Y spilling over to the next line. */
- tem = sfnt_mul_fixed (tem * 64, interpreter->scale);
+ tem = sfnt_mul_f26dot6_fixed (tem, interpreter->scale);
/* Set y_points and y_current. */
zone->y_points[i] = tem;
@@ -11412,8 +12531,8 @@ sfnt_interpret_simple_glyph (struct sfnt_glyph *glyph,
/* Load phantom points. */
zone->y_points[i] = phantom_point_1_y;
zone->y_points[i + 1] = phantom_point_2_y;
- zone->y_current[i] = phantom_point_1_x;
- zone->y_current[i + 1] = phantom_point_2_x;
+ zone->y_current[i] = phantom_point_1_y;
+ zone->y_current[i + 1] = phantom_point_2_y;
/* Load phantom point flags. */
zone->flags[i] = SFNT_POINT_PHANTOM;
@@ -11570,7 +12689,8 @@ sfnt_transform_f26dot6 (struct sfnt_compound_glyph_component *component,
/* Internal helper for sfnt_interpret_compound_glyph_3.
Instruct the compound glyph GLYPH using INTERPRETER after all of
- its components have been instructed.
+ its components have been instructed. Save the resulting points
+ within CONTEXT, and set its phantom point fields to match as well.
Use the unscaled METRICS to compute the phantom points of this
glyph.
@@ -11580,6 +12700,11 @@ sfnt_transform_f26dot6 (struct sfnt_compound_glyph_component *component,
In addition, CONTEXT also contains two additional ``phantom
points'' supplying the left and right side bearings of GLYPH.
+ S1 and S2 are the unrounded values of the last two phantom points,
+ which supply the original values saved into the glyph zone. In
+ practical terms, they are set as the last two values of the glyph
+ zone's original position array.
+
Value is NULL upon success, or a description of the error upon
failure. */
@@ -11588,22 +12713,22 @@ sfnt_interpret_compound_glyph_2 (struct sfnt_glyph *glyph,
struct sfnt_interpreter *interpreter,
struct sfnt_compound_glyph_context *context,
size_t base_index, size_t base_contour,
- struct sfnt_glyph_metrics *metrics)
+ struct sfnt_glyph_metrics *metrics,
+ sfnt_f26dot6 s1, sfnt_f26dot6 s2)
{
size_t num_points, num_contours, i;
size_t zone_size, temp;
struct sfnt_interpreter_zone *zone;
struct sfnt_interpreter_zone *volatile preserved_zone;
volatile bool zone_was_allocated;
- int rc;
sfnt_f26dot6 *x_base, *y_base;
- size_t *contour_base;
- unsigned char *flags_base;
- /* Figure out how many points and contours there are to
- instruct. */
+ /* Figure out how many points and contours there are to instruct. A
+ minimum of two points must be present, namely: the origin and
+ advance phantom points. */
num_points = context->num_points - base_index;
num_contours = context->num_end_points - base_contour;
+ assert (num_points >= 2);
/* Nothing to instruct! */
if (!num_points && !num_contours)
@@ -11678,6 +12803,11 @@ sfnt_interpret_compound_glyph_2 (struct sfnt_glyph *glyph,
& ~SFNT_POINT_TOUCHED_BOTH);
}
+ /* Copy S1 and S2 into the glyph zone. */
+ assert (num_points >= 2);
+ zone->x_points[num_points - 1] = s2;
+ zone->x_points[num_points - 2] = s1;
+
/* Load the compound glyph program. */
interpreter->IP = 0;
interpreter->SP = interpreter->stack;
@@ -11712,27 +12842,20 @@ sfnt_interpret_compound_glyph_2 (struct sfnt_glyph *glyph,
context->y_coordinates[base_index + i] = zone->y_current[i];
}
- /* Grow various arrays to fit the phantom points. */
- rc = sfnt_expand_compound_glyph_context (context, 0, 2,
- &x_base, &y_base,
- &flags_base,
- &contour_base);
-
- if (rc)
- {
- if (zone_was_allocated)
- xfree (zone);
-
- return "Failed to expand arrays for phantom points";
- }
-
- /* Copy over the phantom points. */
+ /* Return the phantom points after instructing completes to the
+ context's coordinate arrays. */
+ x_base = &context->x_coordinates[i - 2];
+ y_base = &context->y_coordinates[i - 2];
x_base[0] = zone->x_current[num_points - 2];
x_base[1] = zone->x_current[num_points - 1];
y_base[0] = zone->y_current[num_points - 2];
y_base[1] = zone->y_current[num_points - 1];
- flags_base[0] = zone->flags[num_points - 2];
- flags_base[1] = zone->flags[num_points - 1];
+ context->phantom_point_1_x = x_base[0];
+ context->phantom_point_1_y = y_base[0];
+ context->phantom_point_1_s = x_base[0];
+ context->phantom_point_2_x = x_base[1];
+ context->phantom_point_2_y = y_base[1];
+ context->phantom_point_2_s = x_base[1];
/* Free the zone if needed. */
if (zone_was_allocated)
@@ -11779,10 +12902,8 @@ sfnt_interpret_compound_glyph_1 (struct sfnt_glyph *glyph,
bool defer_offsets;
struct sfnt_instructed_outline *value;
struct sfnt_glyph_metrics sub_metrics;
- sfnt_f26dot6 phantom_point_1_x;
- sfnt_f26dot6 phantom_point_1_y;
- sfnt_f26dot6 phantom_point_2_x;
- sfnt_f26dot6 phantom_point_2_y;
+ sfnt_f26dot6 pp1x, pp1y, pp1s;
+ sfnt_f26dot6 pp2x, pp2y, pp2s;
error = NULL;
@@ -11805,6 +12926,17 @@ sfnt_interpret_compound_glyph_1 (struct sfnt_glyph *glyph,
/* Pacify -Wmaybe-uninitialized. */
point = point2 = 0;
+ /* Compute phantom points for this glyph here. They will be
+ subsequently overridden if a component glyph's metrics must be
+ used instead. */
+ sfnt_compute_phantom_points (glyph, metrics, interpreter->scale,
+ &context->phantom_point_1_x,
+ &context->phantom_point_1_y,
+ &context->phantom_point_2_x,
+ &context->phantom_point_2_y,
+ &context->phantom_point_1_s,
+ &context->phantom_point_2_s);
+
for (j = 0; j < glyph->compound->num_components; ++j)
{
/* Look up the associated subglyph. */
@@ -11835,14 +12967,14 @@ sfnt_interpret_compound_glyph_1 (struct sfnt_glyph *glyph,
if (!(component->flags & 01)) /* ARG_1_AND_2_ARE_WORDS */
{
/* X and Y are signed bytes. */
- x = component->argument1.b * 64;
- y = component->argument2.b * 64;
+ x = component->argument1.b;
+ y = component->argument2.b;
}
else
{
/* X and Y are signed words. */
- x = component->argument1.d * 64;
- y = component->argument2.d * 64;
+ x = component->argument1.d;
+ y = component->argument2.d;
}
/* Now convert X and Y into device coordinates. */
@@ -11864,9 +12996,9 @@ sfnt_interpret_compound_glyph_1 (struct sfnt_glyph *glyph,
else
{
/* The offset is determined by matching a point location in
- a preceeding component with a point location in the
+ a preceding component with a point location in the
current component. The index of the point in the
- previous component can be determined by adding
+ previous component is established by adding
component->argument1.a or component->argument1.c to
point. argument2 contains the index of the point in the
current component. */
@@ -11895,38 +13027,37 @@ sfnt_interpret_compound_glyph_1 (struct sfnt_glyph *glyph,
if (!subglyph->compound)
{
+ /* Detect invalid child anchor points within simple
+ glyphs in advance. */
+
if (point2 >= subglyph->simple->number_of_points + 2)
{
- /* If POINT2 is placed within a phantom point, use
- that. */
-
if (need_free)
free_glyph (subglyph, dcontext);
return "Invalid component anchor point";
}
+ }
- /* First, set offsets to 0, because it is not yet
- possible to ascertain the position of the anchor
- point in the child. That position cannot be
- established prior to the completion of
- grid-fitting. */
- x = 0;
- y = 0;
+ /* First, set offsets to 0, because it is not yet possible
+ to ascertain the position of the anchor point in the
+ child. That position cannot be established prior to the
+ completion of grid-fitting. */
+ x = 0;
+ y = 0;
- /* Set a flag which indicates that offsets must be
- resolved from the child glyph after it is loaded, but
- before it is incorporated into the parent glyph. */
- defer_offsets = true;
- }
+ /* Set a flag which indicates that offsets must be resolved
+ from the child glyph after it is loaded, but before it is
+ incorporated into the parent glyph. */
+ defer_offsets = true;
}
/* Obtain the glyph metrics. If doing so fails, then cancel
decomposition. */
if (sfnt_lookup_glyph_metrics (component->glyph_index,
- -1, &sub_metrics,
- hmtx, hhea, NULL, maxp))
+ &sub_metrics, hmtx, hhea,
+ maxp))
{
if (need_free)
free_glyph (subglyph, dcontext);
@@ -12030,6 +13161,27 @@ sfnt_interpret_compound_glyph_1 (struct sfnt_glyph *glyph,
y = (ytemp - value->y_points[point2]);
}
+ /* If USE_MY_METRICS is present in this component, save
+ the instructed phantom points inside CONTEXT.
+
+ N.B. such points replace even the unrounded points
+ within the context, as this distinction is lost in
+ phantom points sourced from instructed glyphs. */
+
+ if (component->flags & 01000) /* USE_MY_METRICS */
+ {
+ context->phantom_point_1_x
+ = context->phantom_point_1_s
+ = value->x_points[last_point];
+ context->phantom_point_1_y
+ = value->y_points[last_point];
+ context->phantom_point_2_x
+ = context->phantom_point_2_s
+ = value->x_points[last_point + 1];
+ context->phantom_point_2_y
+ = value->y_points[last_point + 1];
+ }
+
xfree (value);
/* Apply the transform to the points, excluding phantom
@@ -12041,7 +13193,17 @@ sfnt_interpret_compound_glyph_1 (struct sfnt_glyph *glyph,
else
{
/* Compound subglyph. Decompose and instruct the glyph
- recursively, and then apply the transform. */
+ recursively, and then apply the transform.
+
+ If USE_MY_METRICS is not set, save the phantom points
+ presently in CONTEXT, then restore them afterwards. */
+
+ pp1x = context->phantom_point_1_x;
+ pp1y = context->phantom_point_1_y;
+ pp1s = context->phantom_point_1_s;
+ pp2x = context->phantom_point_2_x;
+ pp2y = context->phantom_point_2_y;
+ pp2s = context->phantom_point_2_s;
error = sfnt_interpret_compound_glyph_1 (subglyph, interpreter,
state,
@@ -12059,6 +13221,16 @@ sfnt_interpret_compound_glyph_1 (struct sfnt_glyph *glyph,
return error;
}
+ if (!(component->flags & 01000)) /* USE_MY_METRICS */
+ {
+ context->phantom_point_1_x = pp1x;
+ context->phantom_point_1_y = pp1y;
+ context->phantom_point_1_s = pp1s;
+ context->phantom_point_2_x = pp2x;
+ context->phantom_point_2_y = pp2y;
+ context->phantom_point_2_s = pp2s;
+ }
+
/* Anchor points for glyphs with instructions must be
computed after grid fitting completes.
@@ -12118,13 +13290,8 @@ sfnt_interpret_compound_glyph_1 (struct sfnt_glyph *glyph,
}
/* Run the program for the entire compound glyph, if any. CONTEXT
- should not contain phantom points by this point, so append its
- own. */
-
- /* Compute phantom points. */
- sfnt_compute_phantom_points (glyph, metrics, interpreter->scale,
- &phantom_point_1_x, &phantom_point_1_y,
- &phantom_point_2_x, &phantom_point_2_y);
+ should not contain phantom points by this point, so append the
+ points for this glyph as a whole. */
/* Grow various arrays to include those points. */
rc = sfnt_expand_compound_glyph_context (context,
@@ -12138,10 +13305,10 @@ sfnt_interpret_compound_glyph_1 (struct sfnt_glyph *glyph,
&flags_base, &contour_base);
/* Store the phantom points within the compound glyph. */
- x_base[0] = phantom_point_1_x;
- x_base[1] = phantom_point_2_x;
- y_base[0] = phantom_point_1_y;
- y_base[1] = phantom_point_2_y;
+ x_base[0] = context->phantom_point_1_x;
+ x_base[1] = context->phantom_point_2_x;
+ y_base[0] = context->phantom_point_1_y;
+ y_base[1] = context->phantom_point_2_y;
flags_base[0] = SFNT_POINT_PHANTOM;
flags_base[1] = SFNT_POINT_PHANTOM;
@@ -12151,7 +13318,9 @@ sfnt_interpret_compound_glyph_1 (struct sfnt_glyph *glyph,
error = sfnt_interpret_compound_glyph_2 (glyph, interpreter,
context, base_index,
base_contour,
- metrics);
+ metrics,
+ context->phantom_point_1_s,
+ context->phantom_point_2_s);
}
return error;
@@ -12286,18 +13455,47 @@ sfnt_interpret_compound_glyph (struct sfnt_glyph *glyph,
/* Unicode Variation Sequence (UVS) support.
- Unicode defines a mechanism by which a two-codepoint sequence
- consisting of a ``base character'' and ``variation selector'' is
- able to produce a glyph that is a variant of the glyph that would
- conventionally have been mapped to the ``base character''.
-
- TrueType describes variation selector sequences through a type of
- character mapping table that is given the format 14. The character
- mapping table consists of an array of variation selectors, each of
- which have a corresponding ``default UVS table'', which describes
- ranges of ``base characters'' having no special variant glyphs, and
- a ``non-default UVS table'', which is a map of ``base characters''
- to their corresponding variant glyphs. */
+ Unicode defines a mechanism by which two-codepoint sequences
+ comprising a ``base character'' and ``variation selector'' combine
+ to produce a glyph besides that which is mapped to the ``base
+ character'' itself.
+
+ TrueType stores variation selector sequences inside a special type
+ of character mapping table that is given the format 14. The
+ character mapping table consists of an array of variation
+ selectors, each of which is assigned a ``default UVS table''
+ recording ranges of ``base characters'' absent special variant
+ glyphs, and a ``non-default UVS table'', linking ``base
+ characters'' to their respective variant glyphs.
+
+ Unicode variation selectors occupy the range formed between 0xfe00
+ and 0xfe0f, along with that from 0xe0100 to 0xe01ef, within the
+ Unicode codespace. When a variation selector is encountered as
+ text is being examined for display with a particular font, that
+ font's character mapping table is indexed by it, yielding a default
+ and non-default UVS table. If the base character (which is
+ directly behind the variation selector) is subsequently located
+ within the default UVS table, then the glyph represented by this
+ union of base character and variation selector is that designated
+ by the base character within any UCS-4 or BMP character mapping
+ table in the font. Since this glyph is at variance with that
+ derived from the base character only when the character set of the
+ character mapping table otherwise consulted is not UCS-4 or BMP,
+ the distinction between those two glyphs is largely notional.
+ Should the nondefault UVS table hold the base character, then the
+ glyph is conversely that enumerated in said table, whose indexing
+ is facilitated by sfnt_variation_glyph_for_char. And if the base
+ character isn't present within either table or the tables for the
+ variation selector are absent in the first place, then the two
+ codepoints constituting the sequence are immiscible and therefore
+ the sequence cannot apply to the font.
+
+ The approach taken by Emacs character composition routines is
+ diametric to the approach illustrated above: in place of searching
+ for variation glyphs each time a variation selector character is
+ encountered, these routines ascertain which glyphs are linked to
+ each base character that they have adjudged subject to variation in
+ advance. See sfntfont_get_variation_glyphs. */
/* Read a default UVS table from the font file FD, at the specified
OFFSET. Value is the default UVS table upon success, else
@@ -12308,7 +13506,7 @@ sfnt_read_default_uvs_table (int fd, off_t offset)
{
struct sfnt_default_uvs_table *uvs;
uint32_t num_ranges, i, j;
- size_t size, temp;
+ ssize_t size, temp;
char data[512];
/* First, seek to the given offset. */
@@ -12318,7 +13516,8 @@ sfnt_read_default_uvs_table (int fd, off_t offset)
/* Next, read the number of ranges present. */
- if (read (fd, &num_ranges, sizeof num_ranges) != sizeof num_ranges)
+ if (read (fd, &num_ranges, sizeof num_ranges)
+ != (int) sizeof num_ranges)
return NULL;
/* Swap the number of ranges present. */
@@ -12378,7 +13577,7 @@ sfnt_read_nondefault_uvs_table (int fd, off_t offset)
{
struct sfnt_nondefault_uvs_table *uvs;
uint32_t num_mappings, i, j;
- size_t size, temp;
+ ssize_t size, temp;
char data[500];
/* First, seek to the given offset. */
@@ -12676,6 +13875,26 @@ sfnt_compare_uvs_mapping (const void *k, const void *v)
return 1;
}
+/* Compare *(sfnt_char *) K to the Unicode value range V. */
+
+static int
+sfnt_compare_unicode_value_range (const void *k, const void *v)
+{
+ const sfnt_char *key;
+ const struct sfnt_unicode_value_range *value;
+
+ key = k;
+ value = v;
+
+ if (*key < value->start_unicode_value)
+ return -1;
+ else if ((*key - value->start_unicode_value
+ <= value->additional_count))
+ return 0;
+
+ return 1;
+}
+
/* Return the ID of a variation glyph for the character C in the
nondefault UVS mapping table UVS.
@@ -12695,6 +13914,21 @@ sfnt_variation_glyph_for_char (struct sfnt_nondefault_uvs_table *uvs,
return mapping ? mapping->base_character_value : 0;
}
+/* Return whether the character C is present in the default UVS
+ mapping table UVS. */
+
+TEST_STATIC bool
+sfnt_is_character_default (struct sfnt_default_uvs_table *uvs,
+ sfnt_char c)
+{
+ /* UVS->ranges comprises ranges of characters sorted in increasing
+ order; these ranges cannot overlap. */
+
+ return (bsearch (&c, uvs->ranges, uvs->num_unicode_value_ranges,
+ sizeof *uvs->ranges,
+ sfnt_compare_unicode_value_range) != NULL);
+}
+
#if defined HAVE_MMAP && !defined TEST
@@ -12831,9 +14065,13 @@ sfnt_read_table (int fd, struct sfnt_offset_subtable *subtable,
/* Glyph variations. Instead of defining separate fonts for each
combination of weight, width and slant (bold, condensed, italic,
- etc), some fonts specify a list of ``variation axes'', each of
- which determines one delta to apply to each point in every
- glyph.
+ etc), some fonts specify a list of ``variation axes'', which are
+ options that accept values consisting of numbers on scales
+ governing deltas applied to select points in their glyphs.
+
+ Particular styles within the font are then supplied as sets of
+ values on these scales to which their respective axes are set,
+ termed ``instances''.
This optional information is specified in the `fvar' (font
variation), `gvar' (glyph variation) and `cvar' (CVT variation)
@@ -12880,7 +14118,7 @@ sfnt_read_fvar_table (int fd, struct sfnt_offset_subtable *subtable)
/* Read the fvar table header. */
buffer = NULL;
rc = read (fd, fvar, min_bytes);
- if (rc != min_bytes)
+ if (rc == -1 || rc != min_bytes)
goto bail;
/* Swap what was read. */
@@ -12990,7 +14228,7 @@ sfnt_read_fvar_table (int fd, struct sfnt_offset_subtable *subtable)
goto bail;
rc = read (fd, fvar->axis, sizeof *fvar->axis * fvar->axis_count);
- if (rc != sizeof *fvar->axis * fvar->axis_count)
+ if (rc == -1 || rc != sizeof *fvar->axis * fvar->axis_count)
goto bail;
/* Swap each axis. */
@@ -13109,7 +14347,7 @@ sfnt_read_gvar_table (int fd, struct sfnt_offset_subtable *subtable)
/* Read the gvar table header. */
rc = read (fd, gvar, min_bytes);
- if (rc != min_bytes)
+ if (rc == -1 || rc != min_bytes)
goto bail;
/* Swap what was read. */
@@ -13175,7 +14413,7 @@ sfnt_read_gvar_table (int fd, struct sfnt_offset_subtable *subtable)
{
gvar->u.offset_long = (uint32_t *) (gvar + 1);
rc = read (fd, gvar->u.offset_long, off_size);
- if (rc != off_size)
+ if (rc == -1 || rc != off_size)
goto bail;
for (i = 0; i <= gvar->glyph_count; ++i)
@@ -13184,7 +14422,8 @@ sfnt_read_gvar_table (int fd, struct sfnt_offset_subtable *subtable)
/* Start reading shared coordinates. */
- gvar->global_coords = ((sfnt_f2dot14 *) ((char *) gvar + off_size));
+ gvar->global_coords = ((sfnt_f2dot14 *) ((char *) (gvar + 1)
+ + off_size));
if (gvar->shared_coord_count)
{
@@ -13195,11 +14434,12 @@ sfnt_read_gvar_table (int fd, struct sfnt_offset_subtable *subtable)
if (lseek (fd, offset, SEEK_SET) != offset)
goto bail;
- if (read (fd, gvar->global_coords, coordinate_size)
- != coordinate_size)
+ rc = read (fd, gvar->global_coords, coordinate_size);
+
+ if (rc == -1 || rc != coordinate_size)
goto bail;
- for (i = 0; i <= coordinate_size / sizeof *gvar->global_coords; ++i)
+ for (i = 0; i < coordinate_size / sizeof *gvar->global_coords; ++i)
sfnt_swap16 (&gvar->global_coords[i]);
}
@@ -13219,8 +14459,9 @@ sfnt_read_gvar_table (int fd, struct sfnt_offset_subtable *subtable)
if (lseek (fd, offset, SEEK_SET) != offset)
goto bail;
- if (read (fd, gvar->glyph_variation_data,
- gvar->data_size) != gvar->data_size)
+ rc = read (fd, gvar->glyph_variation_data, gvar->data_size);
+
+ if (rc == -1 || rc != gvar->data_size)
goto bail;
}
@@ -13271,7 +14512,7 @@ sfnt_read_avar_table (int fd, struct sfnt_offset_subtable *subtable)
/* Read the avar table header. */
rc = read (fd, avar, min_size);
- if (rc != min_size)
+ if (rc == -1 || rc != min_size)
goto bail;
/* Swap what was read. */
@@ -13288,7 +14529,7 @@ sfnt_read_avar_table (int fd, struct sfnt_offset_subtable *subtable)
size = directory->length - min_size;
buffer = xmalloc (size);
rc = read (fd, buffer, size);
- if (rc != size)
+ if (rc == -1 || rc != size)
goto bail1;
/* Swap each word. */
@@ -13589,7 +14830,7 @@ sfnt_read_cvar_table (int fd, struct sfnt_offset_subtable *subtable,
size = directory->length - min_size;
buffer = xmalloc (size);
rc = read (fd, buffer, size);
- if (rc != size)
+ if (rc == -1 || rc != size)
goto bail;
/* Now figure out how large cvar must be by reading the tuples. */
@@ -14033,7 +15274,7 @@ sfnt_compute_tuple_scale (struct sfnt_blend *blend, bool intermediate_p,
if (intermediate_p)
{
start = intermediate_start[i] * 4;
- end = intermediate_start[i] * 4;
+ end = intermediate_end[i] * 4;
}
/* Ignore tuples that can be skipped. */
@@ -14089,322 +15330,235 @@ sfnt_compute_tuple_scale (struct sfnt_blend *blend, bool intermediate_p,
return scale;
}
-/* Infer point positions for points that have been partially moved
- within the contour in GLYPH denoted by START and END. */
+/* Move each point in the simple glyph GLYPH between PAIR_START and
+ PAIR_END to agree with the positions of those two anchor points as
+ compared with their initial positions recorded within the arrays X
+ and Y.
+
+ The range formed between PAIR_START and PAIR_END may encompass the
+ upper extreme of the contour between START and END. */
static void
-sfnt_infer_deltas_1 (struct sfnt_glyph *glyph, size_t start,
- size_t end, bool *touched, sfnt_fword *x,
- sfnt_fword *y)
+sfnt_infer_deltas_2 (struct sfnt_glyph *glyph, size_t pair_start,
+ size_t pair_end, size_t start, size_t end,
+ sfnt_fword *x, sfnt_fword *y)
{
- size_t i, pair_start, pair_end, pair_first, j;
- sfnt_fword min_pos, max_pos, position;
+ size_t j;
+ sfnt_fword min_pos, max_pos, position, d1, d2;
sfnt_fixed ratio, delta;
- pair_start = pair_first = -1;
-
- /* Look for pairs of touched points. */
+ j = pair_start + 1;
- for (i = start; i <= end; ++i)
+ while (j != pair_end)
{
- if (!touched[i])
- continue;
+ /* Reset j to the contour's start position if it is about to
+ overrun this contour. */
- if (pair_start == -1)
+ if (j > end)
{
- pair_first = i;
- goto next;
+ /* The start of the contour might also be the end of this
+ reference point. */
+ if (start == pair_end)
+ return;
+
+ j = start;
}
- pair_end = i;
+ /* Consider the X axis. Set min_pos and max_pos to the
+ smallest and greatest values along that axis. */
+ min_pos = MIN (x[pair_start], x[pair_end]);
+ max_pos = MAX (x[pair_start], x[pair_end]);
- /* pair_start to pair_end are now a pair of points, where points
- in between should be interpolated. */
+ /* Now see if the current point lies between min and
+ max...
- for (j = pair_start + 1; j < pair_end; ++j)
+ GX interpolation differs from IUP in one important detail:
+ points are shifted to follow the movement of their reference
+ points if their positions are identical to those of any of
+ their reference points, whereas IUP considers such points to
+ fall within their reference points. */
+ if (x[j] > min_pos && x[j] < max_pos)
{
- /* Consider the X axis. Set min_pos and max_pos to the
- smallest and greatest values along that axis. */
- min_pos = MIN (x[pair_start], x[pair_end]);
- max_pos = MAX (x[pair_start], x[pair_end]);
-
- /* Now see if the current point lies between min and
- max... */
- if (x[j] >= min_pos && x[j] <= max_pos)
+ /* Interpolate between min_pos and max_pos. */
+ ratio = sfnt_div_fixed ((sfnt_sub (x[j], min_pos)
+ * 65536),
+ (sfnt_sub (max_pos, min_pos)
+ * 65536));
+
+ /* Load the current positions of pair_start and pair_end
+ along this axis. */
+ min_pos = MIN (glyph->simple->x_coordinates[pair_start],
+ glyph->simple->x_coordinates[pair_end]);
+ max_pos = MAX (glyph->simple->x_coordinates[pair_start],
+ glyph->simple->x_coordinates[pair_end]);
+
+ /* Lerp in between. */
+ delta = sfnt_sub (max_pos, min_pos);
+ delta = sfnt_mul_fixed (ratio, delta);
+ glyph->simple->x_coordinates[j] = min_pos + delta;
+ }
+ else
+ {
+ /* ... otherwise, move point j by the delta of the
+ nearest touched point. */
+
+ /* If min_pos and max_pos are the same, apply
+ pair_start's delta if it is identical to that of
+ pair_end, or apply nothing at all otherwise. */
+
+ if (min_pos == max_pos)
{
- /* If min_pos and max_pos are the same, apply
- pair_start's delta if it is identical to that of
- pair_end, or apply nothing at all otherwise. */
+ d1 = (glyph->simple->x_coordinates[pair_start]
+ - x[pair_start]);
+ d2 = (glyph->simple->x_coordinates[pair_end]
+ - x[pair_end]);
- if (min_pos == max_pos)
- {
- if ((glyph->simple->x_coordinates[pair_start]
- - x[pair_start])
- == (glyph->simple->x_coordinates[pair_end]
- - x[pair_end]))
- glyph->simple->x_coordinates[j]
- += (glyph->simple->x_coordinates[pair_start]
- - x[pair_start]);
+ if (d1 == d2)
+ glyph->simple->x_coordinates[j] += d1;
- continue;
- }
+ goto consider_y;
+ }
- /* Interpolate between min_pos and max_pos. */
- ratio = sfnt_div_fixed ((sfnt_sub (x[j], min_pos)
- * 65536),
- (sfnt_sub (max_pos, min_pos)
- * 65536));
-
- /* Load the current positions of pair_start and pair_end
- along this axis. */
- min_pos = MIN (glyph->simple->x_coordinates[pair_start],
- glyph->simple->x_coordinates[pair_end]);
- max_pos = MAX (glyph->simple->x_coordinates[pair_start],
- glyph->simple->x_coordinates[pair_end]);
-
- /* Lerp in between. */
- delta = sfnt_sub (max_pos, min_pos);
- delta = sfnt_mul_fixed (ratio, delta);
- glyph->simple->x_coordinates[j] = min_pos + delta;
+ if (x[j] >= max_pos)
+ {
+ position = MAX (glyph->simple->x_coordinates[pair_start],
+ glyph->simple->x_coordinates[pair_end]);
+ delta = position - max_pos;
}
else
{
- /* ... otheriwse, move point j by the delta of the
- nearest touched point. */
+ position = MIN (glyph->simple->x_coordinates[pair_start],
+ glyph->simple->x_coordinates[pair_end]);
+ delta = position - min_pos;
+ }
- if (x[j] >= max_pos)
- {
- position = MAX (glyph->simple->x_coordinates[pair_start],
- glyph->simple->x_coordinates[pair_end]);
- delta = position - max_pos;
- }
- else
- {
- position = MIN (glyph->simple->x_coordinates[pair_start],
- glyph->simple->x_coordinates[pair_end]);
- delta = position - min_pos;
- }
+ glyph->simple->x_coordinates[j] = x[j] + delta;
+ }
- glyph->simple->x_coordinates[j] = x[j] + delta;
- }
+ consider_y:
- /* Now, consider the Y axis. */
- min_pos = MIN (y[pair_start], y[pair_end]);
- max_pos = MAX (y[pair_start], y[pair_end]);
+ /* Now, consider the Y axis. */
+ min_pos = MIN (y[pair_start], y[pair_end]);
+ max_pos = MAX (y[pair_start], y[pair_end]);
- /* Now see if the current point lies between min and
- max... */
- if (y[j] >= min_pos && y[j] <= max_pos)
+ /* Now see if the current point lies between min and
+ max...
+
+ GX interpolation differs from IUP in one important detail:
+ points are shifted to follow the movement of their reference
+ points if their positions are identical to those of any of
+ their reference points, whereas IUP considers such points to
+ fall within their reference points. */
+ if (y[j] > min_pos && y[j] < max_pos)
+ {
+ /* Interpolate between min_pos and max_pos. */
+ ratio = sfnt_div_fixed ((sfnt_sub (y[j], min_pos)
+ * 65536),
+ (sfnt_sub (max_pos, min_pos)
+ * 65536));
+
+ /* Load the current positions of pair_start and pair_end
+ along this axis. */
+ min_pos = MIN (glyph->simple->y_coordinates[pair_start],
+ glyph->simple->y_coordinates[pair_end]);
+ max_pos = MAX (glyph->simple->y_coordinates[pair_start],
+ glyph->simple->y_coordinates[pair_end]);
+
+ /* Lerp in between. */
+ delta = sfnt_sub (max_pos, min_pos);
+ delta = sfnt_mul_fixed (ratio, delta);
+ glyph->simple->y_coordinates[j] = min_pos + delta;
+ }
+ else
+ {
+ /* ... otherwise, move point j by the delta of the
+ nearest touched point. */
+
+ /* If min_pos and max_pos are the same, apply
+ pair_start's delta if it is identical to that of
+ pair_end, or apply nothing at all otherwise. */
+
+ if (min_pos == max_pos)
{
- /* If min_pos and max_pos are the same, apply
- pair_start's delta if it is identical to that of
- pair_end, or apply nothing at all otherwise. */
+ d1 = (glyph->simple->y_coordinates[pair_start]
+ - y[pair_start]);
+ d2 = (glyph->simple->y_coordinates[pair_end]
+ - y[pair_end]);
- if (min_pos == max_pos)
- {
- if ((glyph->simple->y_coordinates[pair_start]
- - y[pair_start])
- == (glyph->simple->y_coordinates[pair_end]
- - y[pair_end]))
- glyph->simple->y_coordinates[j]
- += (glyph->simple->y_coordinates[pair_start]
- - y[pair_start]);
+ if (d1 == d2)
+ glyph->simple->y_coordinates[j] += d1;
- continue;
- }
+ goto next;
+ }
- /* Interpolate between min_pos and max_pos. */
- ratio = sfnt_div_fixed ((sfnt_sub (y[j], min_pos)
- * 65536),
- (sfnt_sub (max_pos, min_pos)
- * 65536));
-
- /* Load the current positions of pair_start and pair_end
- along this axis. */
- min_pos = MIN (glyph->simple->y_coordinates[pair_start],
- glyph->simple->y_coordinates[pair_end]);
- max_pos = MAX (glyph->simple->y_coordinates[pair_start],
- glyph->simple->y_coordinates[pair_end]);
-
- /* Lerp in between. */
- delta = sfnt_sub (max_pos, min_pos);
- delta = sfnt_mul_fixed (ratio, delta);
- glyph->simple->y_coordinates[j] = min_pos + delta;
+ if (y[j] >= max_pos)
+ {
+ position = MAX (glyph->simple->y_coordinates[pair_start],
+ glyph->simple->y_coordinates[pair_end]);
+ delta = position - max_pos;
}
else
{
- /* ... otheriwse, move point j by the delta of the
- nearest touched point. */
-
- if (y[j] >= max_pos)
- {
- position = MAX (glyph->simple->y_coordinates[pair_start],
- glyph->simple->y_coordinates[pair_end]);
- delta = position - max_pos;
- }
- else
- {
- position = MIN (glyph->simple->y_coordinates[pair_start],
- glyph->simple->y_coordinates[pair_end]);
- delta = position - min_pos;
- }
-
- glyph->simple->y_coordinates[j] = y[j] + delta;
+ position = MIN (glyph->simple->y_coordinates[pair_start],
+ glyph->simple->y_coordinates[pair_end]);
+ delta = position - min_pos;
}
+
+ glyph->simple->y_coordinates[j] = y[j] + delta;
}
next:
- pair_start = i;
+ j++;
}
+}
- /* If pair_start is set, then lerp points between it and
- pair_first. */
-
- if (pair_start != (size_t) -1)
- {
- j = pair_start + 1;
-
- if (j > end)
- j = start;
-
- pair_end = pair_first;
-
- while (j != pair_first)
- {
- /* Consider the X axis. Set min_pos and max_pos to the
- smallest and greatest values along that axis. */
- min_pos = MIN (x[pair_start], x[pair_end]);
- max_pos = MAX (x[pair_start], x[pair_end]);
-
- /* Now see if the current point lies between min and
- max... */
- if (x[j] >= min_pos && x[j] <= max_pos)
- {
- /* If min_pos and max_pos are the same, apply
- pair_start's delta if it is identical to that of
- pair_end, or apply nothing at all otherwise. */
+/* Infer point positions for points that have been partially moved
+ within the contour in GLYPH denoted by START and END. */
- if (min_pos == max_pos)
- {
- if ((glyph->simple->x_coordinates[pair_start]
- - x[pair_start])
- == (glyph->simple->x_coordinates[pair_end]
- - x[pair_end]))
- glyph->simple->x_coordinates[j]
- += (glyph->simple->x_coordinates[pair_start]
- - x[pair_start]);
-
- goto next_1;
- }
+static void
+sfnt_infer_deltas_1 (struct sfnt_glyph *glyph, size_t start,
+ size_t end, bool *touched, sfnt_fword *x,
+ sfnt_fword *y)
+{
+ size_t i, pair_start, pair_end, pair_first;
- /* Interpolate between min_pos and max_pos. */
- ratio = sfnt_div_fixed ((sfnt_sub (x[j], min_pos)
- * 65536),
- (sfnt_sub (max_pos, min_pos)
- * 65536));
-
- /* Load the current positions of pair_start and pair_end
- along this axis. */
- min_pos = MIN (glyph->simple->x_coordinates[pair_start],
- glyph->simple->x_coordinates[pair_end]);
- max_pos = MAX (glyph->simple->x_coordinates[pair_start],
- glyph->simple->x_coordinates[pair_end]);
-
- /* Lerp in between. */
- delta = sfnt_sub (max_pos, min_pos);
- delta = sfnt_mul_fixed (ratio, delta);
- glyph->simple->x_coordinates[j] = min_pos + delta;
- }
- else
- {
- /* ... otheriwse, move point j by the delta of the
- nearest touched point. */
+ pair_start = pair_first = -1;
- if (x[j] >= max_pos)
- {
- position = MAX (glyph->simple->x_coordinates[pair_start],
- glyph->simple->x_coordinates[pair_end]);
- delta = position - max_pos;
- }
- else
- {
- position = MIN (glyph->simple->x_coordinates[pair_start],
- glyph->simple->x_coordinates[pair_end]);
- delta = position - min_pos;
- }
+ /* Look for pairs of touched points. */
- glyph->simple->x_coordinates[j] = x[j] + delta;
- }
+ for (i = start; i <= end; ++i)
+ {
+ if (!touched[i])
+ continue;
- /* Now, consider the Y axis. */
- min_pos = MIN (y[pair_start], y[pair_end]);
- max_pos = MAX (y[pair_start], y[pair_end]);
+ if (pair_start == -1)
+ {
+ pair_first = i;
+ goto next;
+ }
- /* Now see if the current point lies between min and
- max... */
- if (y[j] >= min_pos && y[j] <= max_pos)
- {
- /* If min_pos and max_pos are the same, apply
- pair_start's delta if it is identical to that of
- pair_end, or apply nothing at all otherwise. */
+ pair_end = i;
- if (min_pos == max_pos)
- {
- if ((glyph->simple->y_coordinates[pair_start]
- - y[pair_start])
- == (glyph->simple->y_coordinates[pair_end]
- - y[pair_end]))
- glyph->simple->y_coordinates[j]
- += (glyph->simple->y_coordinates[pair_start]
- - y[pair_start]);
-
- goto next_1;
- }
+ /* pair_start to pair_end are now a pair of points whose
+ intermediates should be interpolated. */
+ sfnt_infer_deltas_2 (glyph, pair_start, pair_end,
+ start, end, x, y);
- /* Interpolate between min_pos and max_pos. */
- ratio = sfnt_div_fixed ((sfnt_sub (y[j], min_pos)
- * 65536),
- (sfnt_sub (max_pos, min_pos)
- * 65536));
-
- /* Load the current positions of pair_start and pair_end
- along this axis. */
- min_pos = MIN (glyph->simple->y_coordinates[pair_start],
- glyph->simple->y_coordinates[pair_end]);
- max_pos = MAX (glyph->simple->y_coordinates[pair_start],
- glyph->simple->y_coordinates[pair_end]);
-
- /* Lerp in between. */
- delta = sfnt_sub (max_pos, min_pos);
- delta = sfnt_mul_fixed (ratio, delta);
- glyph->simple->y_coordinates[j] = min_pos + delta;
- }
- else
- {
- /* ... otheriwse, move point j by the delta of the
- nearest touched point. */
+ next:
+ pair_start = i;
+ }
- if (y[j] >= max_pos)
- {
- position = MAX (glyph->simple->y_coordinates[pair_start],
- glyph->simple->y_coordinates[pair_end]);
- delta = position - max_pos;
- }
- else
- {
- position = MIN (glyph->simple->y_coordinates[pair_start],
- glyph->simple->y_coordinates[pair_end]);
- delta = position - min_pos;
- }
+ /* If pair_start is set, then lerp points between it and
+ pair_first. */
- glyph->simple->y_coordinates[j] = y[j] + delta;
- }
+ if (pair_start != (size_t) -1)
+ {
+ pair_end = pair_first;
- next_1:
- j++;
- if (j > end)
- j = start;
- }
+ /* pair_start to pair_end are now a pair of points whose
+ intermediates should be interpolated. */
+ sfnt_infer_deltas_2 (glyph, pair_start, pair_end,
+ start, end, x, y);
}
}
@@ -14470,7 +15624,7 @@ sfnt_infer_deltas (struct sfnt_glyph *glyph, bool *touched,
of one or two coordinates for each axis. Each such list is
referred to as a ``tuple''.
- The deltas, one for each point, are multipled by the normalized
+ The deltas, one for each point, are multiplied by the normalized
value of each axis and applied to those points for each tuple that
is found to be applicable.
@@ -14586,7 +15740,7 @@ sfnt_vary_simple_glyph (struct sfnt_blend *blend, sfnt_glyph id,
coords = alloca (gvar->axis_count * sizeof *coords * 3);
intermediate_start = coords + gvar->axis_count;
- intermediate_end = coords + gvar->axis_count;
+ intermediate_end = intermediate_start + gvar->axis_count;
/* Allocate arrays of booleans and fwords to keep track of which
points have been touched. */
@@ -14761,14 +15915,20 @@ sfnt_vary_simple_glyph (struct sfnt_blend *blend, sfnt_glyph id,
* glyph->simple->number_of_points);
original_y = original_x + glyph->simple->number_of_points;
- memcpy (original_x, glyph->simple->x_coordinates,
- (sizeof *original_x
- * glyph->simple->number_of_points));
- memcpy (original_y, glyph->simple->y_coordinates,
- (sizeof *original_y
- * glyph->simple->number_of_points));
}
+ /* The array of original coordinates should reflect the
+ state of the glyph immediately before deltas from this
+ tuple are applied, in contrast to the state before any
+ deltas are applied. */
+
+ memcpy (original_x, glyph->simple->x_coordinates,
+ (sizeof *original_x
+ * glyph->simple->number_of_points));
+ memcpy (original_y, glyph->simple->y_coordinates,
+ (sizeof *original_y
+ * glyph->simple->number_of_points));
+
memset (touched, 0, (sizeof *touched
* glyph->simple->number_of_points));
@@ -14958,7 +16118,7 @@ sfnt_vary_compound_glyph (struct sfnt_blend *blend, sfnt_glyph id,
coords = alloca (gvar->axis_count * sizeof *coords * 3);
intermediate_start = coords + gvar->axis_count;
- intermediate_end = coords + gvar->axis_count;
+ intermediate_end = intermediate_start + gvar->axis_count;
while (ntuples--)
{
@@ -15272,7 +16432,7 @@ sfnt_vary_interpreter (struct sfnt_interpreter *interpreter,
/* Multiply the delta by the interpreter scale factor and
then the tuple scale factor. */
- delta = sfnt_mul_f26dot6_fixed (variation->deltas[j] * 64,
+ delta = sfnt_mul_f26dot6_fixed (variation->deltas[j],
interpreter->scale);
delta = sfnt_mul_fixed_round (delta, scale);
@@ -15287,6 +16447,173 @@ sfnt_vary_interpreter (struct sfnt_interpreter *interpreter,
+/* OS/2 metadata retrieval.
+
+ A font's `OS/2' table incorporates some miscellaneous information
+ that is consulted by the font scaler on MS-Windows. Emacs requires
+ one fragment of this information: the font foundry name. */
+
+/* Read an OS/2 table from the given font FD. Use the table directory
+ provided in SUBTABLE.
+
+ Return the OS/2 table if successful, NULL otherwise. */
+
+TEST_STATIC struct sfnt_OS_2_table *
+sfnt_read_OS_2_table (int fd, struct sfnt_offset_subtable *subtable)
+{
+ struct sfnt_OS_2_table *OS_2;
+ struct sfnt_table_directory *directory;
+ ssize_t rc;
+ size_t minimum, wanted;
+
+ /* Search for the OS/2 table within SUBTABLE. */
+
+ directory = sfnt_find_table (subtable, SFNT_TABLE_OS_2);
+
+ if (!directory)
+ return NULL;
+
+ /* Calculate how large the table must be. The field `panose' is the
+ last field aligned to natural boundaries, and thus contents must
+ be read twice: once to populate the table with information up to
+ `panose', and once again to retrieve the information
+ afterwards. */
+
+ minimum = (SFNT_ENDOF (struct sfnt_OS_2_table, panose,
+ unsigned char[10])
+ + SFNT_ENDOF (struct sfnt_OS_2_table, fs_last_char_index,
+ uint16_t)
+ - offsetof (struct sfnt_OS_2_table, ul_unicode_range));
+
+ /* If the table is too short, return. */
+ if (directory->length < minimum)
+ return NULL;
+
+ /* Seek to the location given in the directory. */
+ if (lseek (fd, directory->offset, SEEK_SET) == (off_t) -1)
+ return NULL;
+
+ OS_2 = xmalloc (sizeof *OS_2);
+
+ /* Read data up to the end of `panose'. */
+
+ wanted = SFNT_ENDOF (struct sfnt_OS_2_table, panose,
+ unsigned char[10]);
+ rc = read (fd, OS_2, wanted);
+
+ if (rc == -1 || rc != wanted)
+ {
+ xfree (OS_2);
+ return NULL;
+ }
+
+ /* Byte swap that data. */
+
+ sfnt_swap16 (&OS_2->version);
+ sfnt_swap16 (&OS_2->x_avg_char_width);
+ sfnt_swap16 (&OS_2->us_weight_class);
+ sfnt_swap16 (&OS_2->us_width_class);
+ sfnt_swap16 (&OS_2->fs_type);
+ sfnt_swap16 (&OS_2->y_subscript_x_size);
+ sfnt_swap16 (&OS_2->y_subscript_y_size);
+ sfnt_swap16 (&OS_2->y_subscript_x_offset);
+ sfnt_swap16 (&OS_2->y_subscript_y_offset);
+ sfnt_swap16 (&OS_2->y_superscript_x_size);
+ sfnt_swap16 (&OS_2->y_superscript_y_size);
+ sfnt_swap16 (&OS_2->y_superscript_x_offset);
+ sfnt_swap16 (&OS_2->y_superscript_y_offset);
+ sfnt_swap16 (&OS_2->y_strikeout_size);
+ sfnt_swap16 (&OS_2->y_strikeout_position);
+ sfnt_swap16 (&OS_2->s_family_class);
+
+ /* Read fields between ul_unicode_range and fs_last_char_index. */
+ wanted = (SFNT_ENDOF (struct sfnt_OS_2_table, fs_last_char_index,
+ uint16_t)
+ - offsetof (struct sfnt_OS_2_table, ul_unicode_range));
+ rc = read (fd, &OS_2->ul_unicode_range, wanted);
+
+ if (rc == -1 || rc != wanted)
+ {
+ xfree (OS_2);
+ return NULL;
+ }
+
+ /* Swap the remainder and return the table. */
+ sfnt_swap32 (&OS_2->ul_unicode_range[0]);
+ sfnt_swap32 (&OS_2->ul_unicode_range[1]);
+ sfnt_swap32 (&OS_2->ul_unicode_range[2]);
+ sfnt_swap32 (&OS_2->ul_unicode_range[3]);
+ sfnt_swap16 (&OS_2->fs_selection);
+ sfnt_swap16 (&OS_2->fs_first_char_index);
+ sfnt_swap16 (&OS_2->fs_last_char_index);
+ return OS_2;
+}
+
+
+
+/* PostScript metadata retrieval.
+
+ TrueType fonts electively incorporate a table of miscellaneous
+ information concerning such matters as the underline position or
+ whether the font is fixed pitch. This table also assigns
+ human-readable names to glyphs, subject to the table format, but
+ these names are not read by the functions defined below. */
+
+/* Read the header of a post table from the given font FD. Refer to
+ the table directory SUBTABLE for its location.
+
+ Return the post table header if successful, NULL otherwise. */
+
+TEST_STATIC struct sfnt_post_table *
+sfnt_read_post_table (int fd, struct sfnt_offset_subtable *subtable)
+{
+ struct sfnt_post_table *post;
+ struct sfnt_table_directory *directory;
+ ssize_t rc;
+
+ /* Search for the post table within SUBTABLE. */
+
+ directory = sfnt_find_table (subtable, SFNT_TABLE_POST);
+
+ if (!directory)
+ return NULL;
+
+ /* Although the size of the table is affected by its format, this
+ function is meant to read only its header; guarantee that the
+ directory is that large. */
+
+ if (directory->length < sizeof *post)
+ return NULL;
+
+ /* Seek to the location given in the directory. */
+ if (lseek (fd, directory->offset, SEEK_SET) == (off_t) -1)
+ return NULL;
+
+ post = xmalloc (sizeof *post);
+ rc = read (fd, post, sizeof *post);
+
+ if (rc == -1 || rc != sizeof *post)
+ {
+ xfree (post);
+ return NULL;
+ }
+
+ /* Byte swap the data retrieved. */
+ sfnt_swap32 (&post->format);
+ sfnt_swap32 (&post->italic_angle);
+ sfnt_swap16 (&post->underline_position);
+ sfnt_swap16 (&post->underline_thickness);
+ sfnt_swap32 (&post->is_fixed_pitch);
+ sfnt_swap32 (&post->min_mem_type_42);
+ sfnt_swap32 (&post->max_mem_type_42);
+ sfnt_swap32 (&post->min_mem_type_1);
+ sfnt_swap32 (&post->max_mem_type_1);
+
+ return post;
+}
+
+
+
#ifdef TEST
struct sfnt_test_dcontext
@@ -15371,9 +16698,9 @@ sfnt_test_get_metrics (sfnt_glyph glyph, struct sfnt_glyph_metrics *metrics,
struct sfnt_test_dcontext *tables;
tables = dcontext;
- return sfnt_lookup_glyph_metrics (glyph, -1, metrics,
+ return sfnt_lookup_glyph_metrics (glyph, metrics,
tables->hmtx, tables->hhea,
- NULL, tables->maxp);
+ tables->maxp);
}
static void
@@ -15683,7 +17010,7 @@ sfnt_x_raster (struct sfnt_raster **rasters,
ascent = sfnt_mul_fixed (hhea->ascent * 65536,
scale) / 65536;
- origin = 0;
+ origin = 5;
for (i = 0; i < nrasters; ++i)
{
@@ -16122,13 +17449,13 @@ sfnt_check_ssw (struct sfnt_interpreter *interpreter,
}
if (interpreter->state.single_width_value
- != sfnt_mul_f26dot6_fixed (-64, interpreter->scale))
+ != sfnt_mul_f26dot6_fixed (-1, interpreter->scale))
{
fprintf (stderr, "failed, got %d at scale %d,"
" expected %d\n",
interpreter->state.single_width_value,
interpreter->scale,
- sfnt_mul_f26dot6_fixed (-64, interpreter->scale));
+ sfnt_mul_f26dot6_fixed (-1, interpreter->scale));
return;
}
@@ -16300,7 +17627,7 @@ static struct sfnt_generic_test_args pushw_test_args =
static struct sfnt_generic_test_args stack_overflow_test_args =
{
- (uint32_t[]) { },
+ NULL,
0,
true,
0,
@@ -16308,8 +17635,7 @@ static struct sfnt_generic_test_args stack_overflow_test_args =
static struct sfnt_generic_test_args stack_underflow_test_args =
{
- /* GCC BUG, this should be []! */
- (uint32_t []) { },
+ NULL,
0,
true,
4,
@@ -16436,7 +17762,7 @@ static struct sfnt_generic_test_args jmpr_test_args =
static struct sfnt_generic_test_args dup_test_args =
{
- (uint32_t []) { },
+ NULL,
0,
true,
5,
@@ -16452,7 +17778,7 @@ static struct sfnt_generic_test_args pop_test_args =
static struct sfnt_generic_test_args clear_test_args =
{
- (uint32_t []) { },
+ NULL,
0,
false,
10,
@@ -16492,7 +17818,7 @@ static struct sfnt_generic_test_args mindex_test_args =
static struct sfnt_generic_test_args raw_test_args =
{
- (uint32_t []) { },
+ NULL,
0,
true,
0,
@@ -16516,7 +17842,7 @@ static struct sfnt_generic_test_args call_test_args =
static struct sfnt_generic_test_args fdef_test_args =
{
- (uint32_t []) { },
+ NULL,
0,
true,
4,
@@ -16524,7 +17850,7 @@ static struct sfnt_generic_test_args fdef_test_args =
static struct sfnt_generic_test_args fdef_1_test_args =
{
- (uint32_t []) { },
+ NULL,
0,
true,
9,
@@ -16532,7 +17858,7 @@ static struct sfnt_generic_test_args fdef_1_test_args =
static struct sfnt_generic_test_args endf_test_args =
{
- (uint32_t []) { },
+ NULL,
0,
true,
0,
@@ -16548,7 +17874,7 @@ static struct sfnt_generic_test_args ws_test_args =
static struct sfnt_generic_test_args rs_test_args =
{
- (uint32_t []) { },
+ NULL,
0,
true,
2,
@@ -16588,7 +17914,7 @@ static struct sfnt_generic_test_args mps_test_args =
static struct sfnt_generic_test_args debug_test_args =
{
- (uint32_t []) { },
+ NULL,
0,
false,
3,
@@ -16669,7 +17995,7 @@ static struct sfnt_generic_test_args if_test_args =
static struct sfnt_generic_test_args eif_test_args =
{
- (uint32_t []) { },
+ NULL,
0,
false,
3,
@@ -16701,7 +18027,7 @@ static struct sfnt_generic_test_args not_test_args =
static struct sfnt_generic_test_args sds_test_args =
{
- (uint32_t []) { },
+ NULL,
0,
true,
5,
@@ -16773,7 +18099,7 @@ static struct sfnt_generic_test_args ceiling_test_args =
static struct sfnt_generic_test_args round_test_args =
{
- (uint32_t []) { },
+ NULL,
0,
true,
0,
@@ -16949,7 +18275,7 @@ static struct sfnt_generic_test_args rdtg_test_args =
static struct sfnt_generic_test_args sangw_test_args =
{
- (uint32_t []) { },
+ NULL,
0,
false,
3,
@@ -16957,7 +18283,7 @@ static struct sfnt_generic_test_args sangw_test_args =
static struct sfnt_generic_test_args aa_test_args =
{
- (uint32_t []) { },
+ NULL,
0,
false,
3,
@@ -17017,7 +18343,7 @@ static struct sfnt_generic_test_args min_test_args =
static struct sfnt_generic_test_args scantype_test_args =
{
- (uint32_t []) { },
+ NULL,
0,
false,
3,
@@ -18946,6 +20272,11 @@ sfnt_identify_instruction (struct sfnt_interpreter *interpreter)
return buffer;
}
+/* Function called to rasterize a glyph outline. */
+#define TYPE struct sfnt_glyph_outline *
+static struct sfnt_raster *(*test_raster_glyph_outline) (TYPE);
+#undef TYPE
+
static void
sfnt_verbose (struct sfnt_interpreter *interpreter)
{
@@ -18955,6 +20286,7 @@ sfnt_verbose (struct sfnt_interpreter *interpreter)
unsigned char opcode;
const char *name;
static unsigned int instructions;
+ sfnt_fixed advance;
/* Build a temporary outline containing the values of the
interpreter's glyph zone. */
@@ -18968,7 +20300,7 @@ sfnt_verbose (struct sfnt_interpreter *interpreter)
temp.y_points = interpreter->glyph_zone->y_current;
temp.flags = interpreter->glyph_zone->flags;
- outline = sfnt_build_instructed_outline (&temp);
+ outline = sfnt_build_instructed_outline (&temp, &advance);
if (!outline)
return;
@@ -18979,7 +20311,7 @@ sfnt_verbose (struct sfnt_interpreter *interpreter)
sfnt_coerce_fixed (outline->xmax),
sfnt_coerce_fixed (outline->ymax));
- raster = sfnt_raster_glyph_outline (outline);
+ raster = (*test_raster_glyph_outline) (outline);
if (raster)
sfnt_test_raster (raster, NULL, 0);
@@ -19040,10 +20372,11 @@ static void
sfnt_test_uvs (int fd, struct sfnt_cmap_format_14 *format14)
{
struct sfnt_uvs_context *context;
- size_t i, j;
+ size_t i, j, k;
sfnt_glyph glyph;
sfnt_char c;
struct sfnt_nondefault_uvs_table *uvs;
+ struct sfnt_default_uvs_table *default_uvs;
context = sfnt_create_uvs_context (format14, fd);
@@ -19058,6 +20391,27 @@ sfnt_test_uvs (int fd, struct sfnt_cmap_format_14 *format14)
for (i = 0; i < context->num_records; ++i)
{
+ if (context->records[i].default_uvs)
+ {
+ default_uvs = context->records[i].default_uvs;
+
+ for (j = 0; j < default_uvs->num_unicode_value_ranges; ++j)
+ {
+ fprintf (stderr, " Default UVS: %u, %u\n",
+ default_uvs->ranges[j].start_unicode_value,
+ default_uvs->ranges[j].additional_count);
+
+ c = default_uvs->ranges[j].start_unicode_value;
+ k = 0;
+
+ for (; k <= default_uvs->ranges[j].additional_count; ++k)
+ {
+ if (!sfnt_is_character_default (default_uvs, c + k))
+ abort ();
+ }
+ }
+ }
+
if (!context->records[i].nondefault_uvs)
continue;
@@ -19150,6 +20504,8 @@ main (int argc, char **argv)
struct sfnt_gvar_table *gvar;
struct sfnt_avar_table *avar;
struct sfnt_cvar_table *cvar;
+ struct sfnt_OS_2_table *OS_2;
+ struct sfnt_post_table *post;
sfnt_fixed scale;
char *fancy;
int *advances;
@@ -19159,6 +20515,7 @@ main (int argc, char **argv)
struct sfnt_instance *instance;
struct sfnt_blend blend;
struct sfnt_metrics_distortion distortion;
+ sfnt_fixed advance;
if (argc < 2)
return 1;
@@ -19178,9 +20535,14 @@ main (int argc, char **argv)
exit (0);
}
+ if (getenv ("SFNT_EXACT_SCALING"))
+ test_raster_glyph_outline = sfnt_raster_glyph_outline_exact;
+ else
+ test_raster_glyph_outline = sfnt_raster_glyph_outline;
+
fd = open (argv[1], O_RDONLY);
- if (fd < 1)
+ if (fd < 0)
return 1;
ttc = NULL;
@@ -19269,8 +20631,8 @@ main (int argc, char **argv)
return 1;
}
-#define FANCY_PPEM 18
-#define EASY_PPEM 18
+#define FANCY_PPEM 44
+#define EASY_PPEM 44
interpreter = NULL;
head = sfnt_read_head_table (fd, font);
@@ -19285,6 +20647,8 @@ main (int argc, char **argv)
fvar = sfnt_read_fvar_table (fd, font);
gvar = sfnt_read_gvar_table (fd, font);
avar = sfnt_read_avar_table (fd, font);
+ OS_2 = sfnt_read_OS_2_table (fd, font);
+ post = sfnt_read_post_table (fd, font);
cvar = NULL;
hmtx = NULL;
@@ -19301,6 +20665,21 @@ main (int argc, char **argv)
loca_long = NULL;
loca_short = NULL;
+ if (OS_2)
+ fprintf (stderr, "OS/2 table found!\nach_vendor_id: %.4s\n",
+ OS_2->ach_vendor_id);
+
+ if (post)
+ fprintf (stderr, "post table: format: %g; italic-angle: %g;\n"
+ "underline_position: %"PRIi16"; underline_thickness: %"
+ PRIi16";\n"
+ "is_fixed_pitch: %"PRIu32"\n",
+ sfnt_coerce_fixed (post->format),
+ sfnt_coerce_fixed (post->italic_angle),
+ post->underline_position,
+ post->underline_thickness,
+ post->is_fixed_pitch);
+
if (fvar)
{
fprintf (stderr, "FVAR table found!\n"
@@ -19480,11 +20859,11 @@ main (int argc, char **argv)
if (instance && gvar)
sfnt_vary_simple_glyph (&blend, code, glyph,
&distortion);
+ else
+ memset (&distortion, 0, sizeof distortion);
- if (sfnt_lookup_glyph_metrics (code, -1,
- &metrics,
- hmtx, hhea,
- head, maxp))
+ if (sfnt_lookup_glyph_metrics (code, &metrics,
+ hmtx, hhea, maxp))
exit (4);
interpreter->state = state;
@@ -19497,14 +20876,17 @@ main (int argc, char **argv)
exit (5);
}
- outline = sfnt_build_instructed_outline (value);
+ outline = sfnt_build_instructed_outline (value, &advance);
+ advances[i] = (advance / 65536);
+
+ fprintf (stderr, "advance: %d\n", advances[i]);
if (!outline)
exit (6);
xfree (value);
- raster = sfnt_raster_glyph_outline (outline);
+ raster = (*test_raster_glyph_outline) (outline);
if (!raster)
exit (7);
@@ -19512,8 +20894,6 @@ main (int argc, char **argv)
xfree (outline);
rasters[i] = raster;
- advances[i] = (sfnt_mul_fixed (metrics.advance, scale)
- + sfnt_mul_fixed (distortion.advance, scale));
}
sfnt_x_raster (rasters, advances, length, hhea, scale);
@@ -19742,7 +21122,15 @@ main (int argc, char **argv)
printf ("variation failed!\n");
}
- if (sfnt_decompose_glyph (glyph, sfnt_test_move_to,
+ if (sfnt_lookup_glyph_metrics (code, &metrics,
+ hmtx, hhea, maxp))
+ {
+ printf ("metrics lookup failure");
+ memset (&metrics, 0, sizeof metrics);
+ }
+
+ if (sfnt_decompose_glyph (glyph, &metrics,
+ sfnt_test_move_to,
sfnt_test_line_to,
sfnt_test_curve_to,
sfnt_test_get_glyph,
@@ -19751,10 +21139,8 @@ main (int argc, char **argv)
&dcontext))
printf ("decomposition failure\n");
- if (sfnt_lookup_glyph_metrics (code, -1,
- &metrics,
- hmtx, hhea,
- head, maxp))
+ if (sfnt_lookup_glyph_metrics (code, &metrics,
+ hmtx, hhea, maxp))
{
printf ("metrics lookup failure");
memset (&metrics, 0, sizeof metrics);
@@ -19778,7 +21164,7 @@ main (int argc, char **argv)
fprintf (stderr, "outline origin, rbearing: %"
PRIi32" %"PRIi32"\n",
outline->origin,
- outline->ymax - outline->origin);
+ outline->xmax - outline->origin);
sfnt_test_max = outline->ymax - outline->ymin;
for (i = 0; i < outline->outline_used; i++)
@@ -19809,10 +21195,10 @@ main (int argc, char **argv)
clock_gettime (CLOCK_THREAD_CPUTIME_ID, &start);
- for (i = 0; i < 120; ++i)
+ for (i = 0; i < 12800; ++i)
{
xfree (raster);
- raster = sfnt_raster_glyph_outline (outline);
+ raster = (*test_raster_glyph_outline) (outline);
}
clock_gettime (CLOCK_THREAD_CPUTIME_ID, &end);
@@ -19834,13 +21220,19 @@ main (int argc, char **argv)
if (hmtx && head)
{
- if (!sfnt_lookup_glyph_metrics (code, EASY_PPEM,
- &metrics,
- hmtx, hhea,
- head, maxp))
- printf ("lbearing, advance: %g, %g\n",
- sfnt_coerce_fixed (metrics.lbearing),
- sfnt_coerce_fixed (metrics.advance));
+ sfnt_scale_metrics (&metrics, scale);
+ printf ("scaled lbearing, advance: %g, %g\n",
+ sfnt_coerce_fixed (metrics.lbearing),
+ sfnt_coerce_fixed (metrics.advance));
+
+ if (!sfnt_lookup_glyph_metrics (code, &metrics, hmtx,
+ hhea, maxp))
+ {
+ sfnt_scale_metrics (&metrics, scale);
+ printf ("lbearing, advance: %g, %g\n",
+ sfnt_coerce_fixed (metrics.lbearing),
+ sfnt_coerce_fixed (metrics.advance));
+ }
if (interpreter)
{
@@ -19853,10 +21245,8 @@ main (int argc, char **argv)
interpreter->pop_hook = sfnt_pop_hook;
}
- if (!sfnt_lookup_glyph_metrics (code, -1,
- &metrics,
- hmtx, hhea,
- head, maxp))
+ if (!sfnt_lookup_glyph_metrics (code, &metrics,
+ hmtx, hhea, maxp))
{
printf ("interpreting glyph\n");
interpreter->state = state;
@@ -19892,12 +21282,24 @@ main (int argc, char **argv)
printf ("rasterizing instructed outline\n");
if (outline)
xfree (outline);
- outline = sfnt_build_instructed_outline (value);
+ outline
+ = sfnt_build_instructed_outline (value,
+ &advance);
xfree (value);
+#define LB outline->xmin - outline->origin
+#define RB outline->xmax - outline->origin
+ printf ("instructed advance, lb, rb: %g %g %g\n",
+ sfnt_coerce_fixed (advance),
+ sfnt_coerce_fixed (LB),
+ sfnt_coerce_fixed (RB));
+#undef LB
+#undef RB
+
if (outline)
{
- raster = sfnt_raster_glyph_outline (outline);
+ raster
+ = (*test_raster_glyph_outline) (outline);
if (raster)
{
@@ -19923,7 +21325,8 @@ main (int argc, char **argv)
printf ("time spent building edges: %lld sec %ld nsec\n",
(long long) sub1.tv_sec, sub1.tv_nsec);
printf ("time spent rasterizing: %lld sec %ld nsec\n",
- (long long) sub2.tv_sec / 120, sub2.tv_nsec / 120);
+ (long long) sub2.tv_sec / 12800,
+ sub2.tv_nsec / 12800);
xfree (outline);
}
@@ -19963,6 +21366,8 @@ main (int argc, char **argv)
xfree (gvar);
xfree (avar);
xfree (cvar);
+ xfree (OS_2);
+ xfree (post);
return 0;
}
diff --git a/src/sfnt.h b/src/sfnt.h
index 0fb67e918a6..2b92f9f540a 100644
--- a/src/sfnt.h
+++ b/src/sfnt.h
@@ -1,6 +1,6 @@
/* sfnt format font support for GNU Emacs.
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
@@ -52,6 +52,8 @@ enum sfnt_table
SFNT_TABLE_GVAR,
SFNT_TABLE_CVAR,
SFNT_TABLE_AVAR,
+ SFNT_TABLE_OS_2,
+ SFNT_TABLE_POST,
};
#define SFNT_ENDOF(type, field, type1) \
@@ -121,6 +123,7 @@ typedef int16_t sfnt_fword;
typedef uint16_t sfnt_ufword;
#define sfnt_coerce_fixed(fixed) ((sfnt_fixed) (fixed) / 65535.0)
+#define sfnt_fixed_float(fixed) ((sfnt_fixed) (fixed) / 65535.0f)
typedef unsigned int sfnt_glyph;
typedef unsigned int sfnt_char;
@@ -364,6 +367,9 @@ struct sfnt_cmap_format_4
/* log2(searchRange/2) */
uint16_t entry_selector;
+ /* (2 * segCount) - searchRange */
+ uint16_t range_shift;
+
/* Variable-length data. */
uint16_t *end_code;
uint16_t *reserved_pad;
@@ -773,7 +779,7 @@ struct sfnt_edge
/* X position, top and bottom of edges. */
sfnt_fixed x, top, bottom;
- /* Amount to move X by upon each change of Y. */
+ /* Amount to move X by upon each change of Y, and vice versa. */
sfnt_fixed step_x;
};
@@ -1278,7 +1284,7 @@ struct sfnt_gvar_table
unsigned char *glyph_variation_data;
};
-/* Structure repesenting a set of axis coordinates and their
+/* Structure representing a set of axis coordinates and their
normalized equivalents.
To use this structure, call
@@ -1330,7 +1336,126 @@ struct sfnt_metrics_distortion
+/* OS/2 font metadata. */
+
+struct sfnt_OS_2_table
+{
+ /* Table version number. */
+ uint16_t version;
+
+ /* Average weighted advance width of lower case letters and
+ space. */
+ int16_t x_avg_char_width;
+
+ /* Wisual weight (degree of blackness or thickness) of stroke in
+ glyphs. */
+ uint16_t us_weight_class;
+
+ /* Relative change from the normal aspect ratio (width to height
+ ratio) as specified by a font designer for the glyphs in the
+ font. */
+ uint16_t us_width_class;
+
+ /* Miscellaneous font attributes. */
+ int16_t fs_type;
+
+ /* Recommended horizontal size in pixels for subscripts. */
+ int16_t y_subscript_x_size;
+
+ /* Recommended vertical subscript size. */
+ int16_t y_subscript_y_size;
+
+ /* Recommended horizontal offset for subscripts. */
+ int16_t y_subscript_x_offset;
+
+ /* Recommended vertical offset from the baseline for subscripts. */
+ int16_t y_subscript_y_offset;
+
+ /* Recommended horizontal size in pixels for superscripts. */
+ int16_t y_superscript_x_size;
+
+ /* Recommended vertical superscript size. */
+ int16_t y_superscript_y_size;
+
+ /* Recommended horizontal offset for superscripts. */
+ int16_t y_superscript_x_offset;
+
+ /* Recommended vertical offset from the baseline for superscripts. */
+ int16_t y_superscript_y_offset;
+
+ /* Width of the strikeout stroke. */
+ int16_t y_strikeout_size;
+
+ /* Position of the strikeout stroke relative to the baseline. */
+ int16_t y_strikeout_position;
+
+ /* Font family classification. */
+ int16_t s_family_class;
+
+ /* Microsoft ``panose'' classification. */
+ unsigned char panose[10];
+
+ /* Alignment boundary! */
+
+ /* Unicode range specification. */
+ uint32_t ul_unicode_range[4];
+
+ /* Font foundry name. */
+ char ach_vendor_id[4];
+
+ /* Two byte bitfield providing the nature of font patterns. */
+ uint16_t fs_selection;
+
+ /* The minimum Unicode codepoint covered. */
+ uint16_t fs_first_char_index;
+
+ /* The maximum Unicode codepoint covered. */
+ uint16_t fs_last_char_index;
+};
+
+
+
+/* PostScript metadata. */
+
+struct sfnt_post_table
+{
+ /* Format of this table. This is a fixed point number rather than
+ an integer. */
+ sfnt_fixed format;
+
+ /* Italic angle in degrees. */
+ sfnt_fixed italic_angle;
+
+ /* Underline position. */
+ sfnt_fword underline_position;
+
+ /* Underline thickness. */
+ sfnt_fword underline_thickness;
+
+ /* Whether the font is monospaced. */
+ uint32_t is_fixed_pitch;
+
+ /* Minimum memory usage (on a PostScript printer) when a TrueType
+ font is downloaded as a Type 42 font. */
+ uint32_t min_mem_type_42;
+
+ /* Maximum memory usage (on a PostScript printer) when a TrueType
+ font is downloaded as a Type 42 font. */
+ uint32_t max_mem_type_42;
+
+ /* Minimum memory usage (on a PostScript printer) when a TrueType
+ font is downloaded as a Type 42 font. */
+ uint32_t min_mem_type_1;
+
+ /* Maximum memory usage (on a PostScript printer) when a TrueType
+ font is downloaded as a Type 42 font. */
+ uint32_t max_mem_type_1;
+};
+
+
+
#define SFNT_CEIL_FIXED(fixed) (((fixed) + 0177777) & 037777600000)
+#define SFNT_ROUND_FIXED(fixed) (((fixed) + 0100000) & 037777600000)
#define SFNT_FLOOR_FIXED(fixed) ((fixed) & 037777600000)
@@ -1388,6 +1513,7 @@ extern void sfnt_prepare_raster (struct sfnt_raster *,
#define PROTOTYPE struct sfnt_glyph_outline *
extern struct sfnt_raster *sfnt_raster_glyph_outline (PROTOTYPE);
+extern struct sfnt_raster *sfnt_raster_glyph_outline_exact (PROTOTYPE);
#undef PROTOTYPE
#define PROTOTYPE \
@@ -1398,11 +1524,10 @@ extern struct sfnt_raster *sfnt_raster_glyph_outline (PROTOTYPE);
extern struct sfnt_hmtx_table *sfnt_read_hmtx_table (PROTOTYPE);
#undef PROTOTYPE
-extern int sfnt_lookup_glyph_metrics (sfnt_glyph, int,
+extern int sfnt_lookup_glyph_metrics (sfnt_glyph,
struct sfnt_glyph_metrics *,
struct sfnt_hmtx_table *,
struct sfnt_hhea_table *,
- struct sfnt_head_table *,
struct sfnt_maxp_table *);
extern void sfnt_scale_metrics (struct sfnt_glyph_metrics *,
@@ -1443,6 +1568,12 @@ extern sfnt_glyph sfnt_variation_glyph_for_char (PROTOTYPE);
#undef PROTOTYPE
+#define PROTOTYPE struct sfnt_default_uvs_table *, sfnt_char
+
+extern bool sfnt_is_character_default (PROTOTYPE);
+
+#undef PROTOTYPE
+
#ifdef HAVE_MMAP
@@ -1497,6 +1628,22 @@ extern int sfnt_vary_compound_glyph (struct sfnt_blend *, sfnt_glyph,
struct sfnt_glyph *,
struct sfnt_metrics_distortion *);
+
+
+#define PROTOTYPE int, struct sfnt_offset_subtable *
+
+extern struct sfnt_OS_2_table *sfnt_read_OS_2_table (PROTOTYPE);
+
+#undef PROTOTYPE
+
+
+
+#define PROTOTYPE int, struct sfnt_offset_subtable *
+
+extern struct sfnt_post_table *sfnt_read_post_table (PROTOTYPE);
+
+#undef PROTOTYPE
+
#endif /* TEST */
@@ -1955,7 +2102,7 @@ extern const char *sfnt_interpret_control_value_program (PROTOTYPE);
#undef PROTOTYPE
-#define PROTOTYPE struct sfnt_instructed_outline *
+#define PROTOTYPE struct sfnt_instructed_outline *, sfnt_fixed *
extern struct sfnt_glyph_outline *sfnt_build_instructed_outline (PROTOTYPE);
diff --git a/src/sfntfont-android.c b/src/sfntfont-android.c
index 53589078cda..9ead43a9c5d 100644
--- a/src/sfntfont-android.c
+++ b/src/sfntfont-android.c
@@ -1,6 +1,6 @@
/* sfnt format font driver for Android.
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
@@ -746,29 +746,54 @@ syms_of_sfntfont_android_for_pdumper (void)
void
init_sfntfont_android (void)
{
+ int api_level;
+
if (!android_init_gui)
return;
- /* Make sure to pick the right Sans Serif font depending on what
+ api_level = android_get_current_api_level ();
+
+ /* Make sure to pick the proper Sans Serif and Serif fonts for the
version of Android the device is running. */
- if (android_get_current_api_level () >= 15)
+
+ if (api_level >= 21)
+ /* Android 5.0 and later distribute Noto Serif in lieu of Droid
+ Serif. */
+ Vsfnt_default_family_alist
+ = list4 (Fcons (build_string ("Monospace"),
+ build_string ("Droid Sans Mono")),
+ /* Android doesn't come with a Monospace Serif font, so
+ this will have to do. */
+ Fcons (build_string ("Monospace Serif"),
+ build_string ("Droid Sans Mono")),
+ Fcons (build_string ("Sans Serif"),
+ build_string ("Roboto")),
+ Fcons (build_string ("DejaVu Serif"),
+ build_string ("Noto Serif")));
+ else if (api_level >= 15)
+ /* Android 4.0 and later distribute Roboto in lieu of Droid
+ Sans. */
Vsfnt_default_family_alist
- = list3 (Fcons (build_string ("Monospace"),
+ = list4 (Fcons (build_string ("Monospace"),
build_string ("Droid Sans Mono")),
/* Android doesn't come with a Monospace Serif font, so
this will have to do. */
Fcons (build_string ("Monospace Serif"),
build_string ("Droid Sans Mono")),
Fcons (build_string ("Sans Serif"),
- build_string ("Roboto")));
+ build_string ("Roboto")),
+ Fcons (build_string ("DejaVu Serif"),
+ build_string ("Droid Serif")));
else
Vsfnt_default_family_alist
- = list3 (Fcons (build_string ("Monospace"),
+ = list4 (Fcons (build_string ("Monospace"),
build_string ("Droid Sans Mono")),
Fcons (build_string ("Monospace Serif"),
build_string ("Droid Sans Mono")),
Fcons (build_string ("Sans Serif"),
- build_string ("Droid Sans")));
+ build_string ("Droid Sans")),
+ Fcons (build_string ("DejaVu Serif"),
+ build_string ("Droid Serif")));
/* Set up the user fonts directory. This directory is ``fonts'' in
the Emacs files directory. */
diff --git a/src/sfntfont.c b/src/sfntfont.c
index e2dfdaff3b6..1ad41deac70 100644
--- a/src/sfntfont.c
+++ b/src/sfntfont.c
@@ -1,6 +1,6 @@
/* sfnt format font driver for GNU Emacs.
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
@@ -109,7 +109,7 @@ struct sfnt_font_desc
/* Style name of the font. */
Lisp_Object style;
- /* Designer (foundry) of the font. */
+ /* The font foundry name, or `misc' if not present. */
Lisp_Object designer;
/* Style tokens that could not be parsed. */
@@ -136,9 +136,6 @@ struct sfnt_font_desc
present in the font. */
Lisp_Object char_cache;
- /* Whether or not the character map can't be used by Emacs. */
- bool cmap_invalid;
-
/* The header of the cmap being used. May be invalid, in which case
platform_id will be 500. */
struct sfnt_cmap_encoding_subtable subtable;
@@ -146,6 +143,9 @@ struct sfnt_font_desc
/* The offset of the table directory within PATH. */
off_t offset;
+ /* List of font tables. */
+ struct sfnt_font_tables *tables;
+
/* The number of glyphs in this font. Used to catch invalid cmap
tables. This is actually the number of glyphs - 1. */
int num_glyphs;
@@ -153,8 +153,15 @@ struct sfnt_font_desc
/* The number of references to the font tables below. */
int refcount;
- /* List of font tables. */
- struct sfnt_font_tables *tables;
+ /* The underline position and thickness if a post table supplies
+ this information. */
+ sfnt_fword underline_position, underline_thickness;
+
+ /* Whether an underline position is available. */
+ bool_bf underline_position_set : 1;
+
+ /* Whether or not the character map can't be used by Emacs. */
+ bool cmap_invalid : 1;
};
/* List of fonts. */
@@ -322,11 +329,30 @@ sfnt_decode_family_style (struct sfnt_name_table *name,
struct sfnt_name_record family_rec, style_rec;
unsigned char *family_data, *style_data;
- family_data = sfnt_find_name (name, SFNT_NAME_FONT_FAMILY,
+ /* Because MS-Windows is incapable of treating font families
+ comprising more than four styles correctly, the TrueType
+ specification incorporates additional PREFERRED_FAMILY and
+ PREFERRED_SUBFAMILY name resources that are meant to be consulted
+ over the traditional family and subfamily resources. When
+ present within fonts supplying unusual styles, these names hold
+ the ``actual'' typographic family and style of the font, in lieu
+ of the font family with the style affixed to the front and
+ Regular. */
+
+ family_data = sfnt_find_name (name, SFNT_NAME_PREFERRED_FAMILY,
&family_rec);
- style_data = sfnt_find_name (name, SFNT_NAME_FONT_SUBFAMILY,
+
+ if (!family_data)
+ family_data = sfnt_find_name (name, SFNT_NAME_FONT_FAMILY,
+ &family_rec);
+
+ style_data = sfnt_find_name (name, SFNT_NAME_PREFERRED_SUBFAMILY,
&style_rec);
+ if (!style_data)
+ style_data = sfnt_find_name (name, SFNT_NAME_FONT_SUBFAMILY,
+ &style_rec);
+
if (!family_data || !style_data)
return 1;
@@ -346,28 +372,6 @@ sfnt_decode_family_style (struct sfnt_name_table *name,
return (!NILP (*family) && !NILP (*style)) ? 0 : 1;
}
-/* Decode the foundry names from the name table NAME. Return the
- foundry name, or nil upon failure. */
-
-static Lisp_Object
-sfnt_decode_foundry_name (struct sfnt_name_table *name)
-{
- struct sfnt_name_record designer_rec;
- unsigned char *designer_data;
-
- designer_data = sfnt_find_name (name, SFNT_NAME_DESIGNER,
- &designer_rec);
-
- if (!designer_data)
- return Qnil;
-
- return sfnt_decode_font_string (designer_data,
- designer_rec.platform_id,
- designer_rec.platform_specific_id,
- designer_rec.language_id,
- designer_rec.length);
-}
-
/* Decode the name of the specified font INSTANCE using the given NAME
table. Return the name of that instance, or nil upon failure. */
@@ -471,6 +475,12 @@ sfnt_parse_style (Lisp_Object style_name, struct sfnt_font_desc *desc)
{
style = NULL;
+ if (!strcmp (single, "regular"))
+ /* ``Regular'' within a font family can represent either the
+ weight, slant or width of the font. Leave each value as
+ its default, but never append it to the adstyle. */
+ goto next;
+
if (desc->weight == 80)
{
/* Weight hasn't been found yet. Scan through the weight
@@ -542,6 +552,11 @@ sfnt_parse_style (Lisp_Object style_name, struct sfnt_font_desc *desc)
continue;
}
+ /* The adstyle must be a symbol, so intern it if it is set. */
+
+ if (!NILP (desc->adstyle))
+ desc->adstyle = Fintern (desc->adstyle, Qnil);
+
SAFE_FREE ();
}
@@ -953,9 +968,12 @@ sfnt_enum_font_1 (int fd, const char *file,
struct sfnt_meta_table *meta;
struct sfnt_maxp_table *maxp;
struct sfnt_fvar_table *fvar;
+ struct sfnt_OS_2_table *OS_2;
+ struct sfnt_post_table *post;
struct sfnt_font_desc temp;
Lisp_Object family, style, instance, style1;
int i;
+ char buffer[5];
/* Create the font desc and copy in the file name. */
desc = xzalloc (sizeof *desc + strlen (file) + 1);
@@ -994,10 +1012,33 @@ sfnt_enum_font_1 (int fd, const char *file,
/* Set the family. */
desc->family = family;
- desc->designer = sfnt_decode_foundry_name (name);
desc->char_cache = Qnil;
desc->subtable.platform_id = 500;
+ /* Now set the font foundry name. This information is located
+ within the OS/2 table's `ach_vendor_id' field, but use `misc' as
+ a recourse if it is not present. */
+
+ OS_2 = sfnt_read_OS_2_table (fd, subtables);
+
+ if (OS_2)
+ {
+ memcpy (buffer, OS_2->ach_vendor_id,
+ sizeof OS_2->ach_vendor_id);
+ buffer[sizeof OS_2->ach_vendor_id] = '\0';
+
+ /* If the foundry name is empty, use `misc' instead. */
+
+ if (!buffer[0])
+ desc->designer = Qmisc;
+ else
+ desc->designer = intern (buffer);
+
+ xfree (OS_2);
+ }
+ else
+ desc->designer = Qmisc;
+
/* Set the largest glyph identifier. */
desc->num_glyphs = maxp->num_glyphs;
@@ -1008,12 +1049,28 @@ sfnt_enum_font_1 (int fd, const char *file,
if (meta)
sfnt_parse_languages (meta, desc);
- /* Figure out the spacing. Some fancy test like what Fontconfig
- does is probably in order but not really necessary. */
- if (!NILP (Fstring_search (Fdowncase (family),
- build_string ("mono"),
- Qnil)))
- desc->spacing = 100; /* FC_MONO */
+ /* Check whether the font claims to be a fixed pitch font and forgo
+ the rudimentary detection below if so. */
+
+ post = sfnt_read_post_table (fd, subtables);
+
+ if (post)
+ {
+ desc->spacing = (post->is_fixed_pitch ? 100 : 0);
+ desc->underline_position = post->underline_position;
+ desc->underline_thickness = post->underline_thickness;
+ desc->underline_position_set = true;
+ xfree (post);
+ }
+ else
+ {
+ /* Figure out the spacing. Some fancy test like what Fontconfig
+ does is probably in order but not really necessary. */
+ if (!NILP (Fstring_search (Fdowncase (family),
+ build_string ("mono"),
+ Qnil)))
+ desc->spacing = 100; /* FC_MONO */
+ }
/* Finally add mac-style flags. Allow them to override styles that
have not been found. */
@@ -1116,7 +1173,9 @@ sfnt_enum_font_1 (int fd, const char *file,
int
sfnt_enum_font (const char *file)
{
- int fd, rc;
+ int fd;
+ int rc;
+ off_t seek;
struct sfnt_offset_subtable *subtables;
struct sfnt_ttc_header *ttc;
size_t i;
@@ -1147,8 +1206,9 @@ sfnt_enum_font (const char *file)
for (i = 0; i < ttc->num_fonts; ++i)
{
- if (lseek (fd, ttc->offset_table[i], SEEK_SET)
- != ttc->offset_table[i])
+ seek = lseek (fd, ttc->offset_table[i], SEEK_SET);
+
+ if (seek == -1 || seek != ttc->offset_table[i])
continue;
subtables = sfnt_read_table_directory (fd);
@@ -1288,7 +1348,7 @@ sfntfont_charset_for_cmap (struct sfnt_cmap_encoding_subtable subtable)
subtable in *SUBTABLE upon success, NULL otherwise.
If FORMAT14 is non-NULL, return any associated format 14 variation
- selection context in *FORMAT14 should the selected charcter map be
+ selection context in *FORMAT14 should the selected character map be
a Unicode character map. */
static struct sfnt_cmap_encoding_subtable_data *
@@ -1311,7 +1371,7 @@ sfntfont_select_cmap (struct sfnt_cmap_table *cmap,
if (!format14)
return data[i];
- /* Search for a correspoinding format 14 character map.
+ /* Search for a corresponding format 14 character map.
This is used in conjunction with the selected character
map to map variation sequences. */
@@ -1340,7 +1400,7 @@ sfntfont_select_cmap (struct sfnt_cmap_table *cmap,
if (!format14)
return data[i];
- /* Search for a correspoinding format 14 character map.
+ /* Search for a corresponding format 14 character map.
This is used in conjunction with the selected character
map to map variation sequences. */
@@ -1618,13 +1678,19 @@ sfntfont_list_1 (struct sfnt_font_desc *desc, Lisp_Object spec,
&& !sfntfont_registries_compatible_p (tem, desc->registry))
return 0;
+ /* If the font spacings disagree, reject this font also. */
+
+ tem = AREF (spec, FONT_SPACING_INDEX);
+ if (FIXNUMP (tem) && (XFIXNUM (tem) != desc->spacing))
+ return 0;
+
/* Check the style. If DESC is a fixed font, just check once.
Otherwise, check each instance. */
if (NILP (desc->instances))
{
tem = AREF (spec, FONT_ADSTYLE_INDEX);
- if (!NILP (tem) && NILP (Fequal (tem, desc->adstyle)))
+ if (!NILP (tem) && !EQ (tem, desc->adstyle))
return 0;
if (FONT_WIDTH_NUMERIC (spec) != -1
@@ -1824,11 +1890,7 @@ sfntfont_desc_to_entity (struct sfnt_font_desc *desc, int instance)
entity = font_make_entity ();
ASET (entity, FONT_TYPE_INDEX, sfnt_vendor_name);
-
- if (!NILP (desc->designer))
- ASET (entity, FONT_FOUNDRY_INDEX,
- Fintern (desc->designer, Qnil));
-
+ ASET (entity, FONT_FOUNDRY_INDEX, desc->designer);
ASET (entity, FONT_FAMILY_INDEX, Fintern (desc->family, Qnil));
ASET (entity, FONT_ADSTYLE_INDEX, Qnil);
ASET (entity, FONT_REGISTRY_INDEX,
@@ -1837,8 +1899,7 @@ sfntfont_desc_to_entity (struct sfnt_font_desc *desc, int instance)
/* Size of 0 means the font is scalable. */
ASET (entity, FONT_SIZE_INDEX, make_fixnum (0));
ASET (entity, FONT_AVGWIDTH_INDEX, make_fixnum (0));
- ASET (entity, FONT_SPACING_INDEX,
- make_fixnum (desc->spacing));
+ ASET (entity, FONT_SPACING_INDEX, make_fixnum (desc->spacing));
if (instance >= 1)
{
@@ -2054,9 +2115,8 @@ sfntfont_get_metrics (sfnt_glyph glyph, struct sfnt_glyph_metrics *metrics,
struct sfntfont_get_glyph_outline_dcontext *tables;
tables = dcontext;
- return sfnt_lookup_glyph_metrics (glyph, -1, metrics,
- tables->hmtx, tables->hhea,
- NULL, tables->maxp);
+ return sfnt_lookup_glyph_metrics (glyph, metrics, tables->hmtx,
+ tables->hhea, tables->maxp);
}
/* Dereference the outline OUTLINE. Free it once refcount reaches
@@ -2121,6 +2181,7 @@ sfntfont_get_glyph_outline (sfnt_glyph glyph_code,
const char *error;
struct sfnt_glyph_metrics temp;
struct sfnt_metrics_distortion distortion;
+ sfnt_fixed advance;
start = cache->next;
distortion.advance = 0;
@@ -2191,13 +2252,9 @@ sfntfont_get_glyph_outline (sfnt_glyph glyph_code,
/* Now load the glyph's unscaled metrics into TEMP. */
- if (sfnt_lookup_glyph_metrics (glyph_code, -1, &temp, hmtx, hhea,
- head, maxp))
+ if (sfnt_lookup_glyph_metrics (glyph_code, &temp, hmtx, hhea, maxp))
goto fail;
- /* Add the advance width distortion. */
- temp.advance += distortion.advance;
-
if (interpreter)
{
if (glyph->simple)
@@ -2223,34 +2280,50 @@ sfntfont_get_glyph_outline (sfnt_glyph glyph_code,
if (!error)
{
- outline = sfnt_build_instructed_outline (value);
+ /* Now record the advance with that measured from the
+ phantom points within the instructed glyph outline, and
+ subsequently replace it once metrics are scaled. */
+
+ outline = sfnt_build_instructed_outline (value,
+ &advance);
xfree (value);
+
+ if (outline)
+ {
+ /* Save the new advance width. This advance width is
+ rounded again, as the instruction code executed might
+ have moved both phantom points such that they no
+ longer measure a fractional distance. */
+ temp.advance = SFNT_ROUND_FIXED (advance);
+
+ /* Finally, adjust the left side bearing of the glyph
+ metrics by the origin point of the outline, should a
+ transformation have been applied by either
+ instruction code or glyph variation. The left side
+ bearing is the distance from the origin point to the
+ left most point on the X axis. */
+ temp.lbearing
+ = SFNT_FLOOR_FIXED (outline->xmin - outline->origin);
+ }
}
}
if (!outline)
{
- if (!interpreter)
- outline = sfnt_build_glyph_outline (glyph, scale,
- &temp,
- sfntfont_get_glyph,
- sfntfont_free_glyph,
- sfntfont_get_metrics,
- &dcontext);
- else
- outline = sfnt_build_glyph_outline (glyph, scale,
- &temp,
- sfntfont_get_glyph,
- sfntfont_free_glyph,
- sfntfont_get_metrics,
- &dcontext);
+ /* Build the outline. This will apply GX offsets within *GLYPH
+ to TEMP. */
+ outline = sfnt_build_glyph_outline (glyph, scale,
+ &temp,
+ sfntfont_get_glyph,
+ sfntfont_free_glyph,
+ sfntfont_get_metrics,
+ &dcontext);
+
+ /* At this point, the glyph metrics are unscaled. Scale them
+ up. If INTERPRETER is set, use the scale placed within. */
+ sfnt_scale_metrics (&temp, scale);
}
- /* At this point, the glyph metrics are unscaled. Scale them up.
- If INTERPRETER is set, use the scale placed within. */
-
- sfnt_scale_metrics (&temp, scale);
-
fail:
xfree (glyph);
@@ -2258,13 +2331,6 @@ sfntfont_get_glyph_outline (sfnt_glyph glyph_code,
if (!outline)
return NULL;
- if (index != -1)
- /* Finally, adjust the left side bearing of the glyph metrics by
- the origin point of the outline, should a distortion have been
- applied. The left side bearing is the distance from the origin
- point to the left most point on the X axis. */
- temp.lbearing = outline->xmin - outline->origin;
-
start = xmalloc (sizeof *start);
start->glyph = glyph_code;
start->outline = outline;
@@ -2383,7 +2449,11 @@ sfntfont_get_glyph_raster (sfnt_glyph glyph_code,
}
/* Not already cached. Raster the outline. */
- raster = sfnt_raster_glyph_outline (outline);
+
+ if (!sfnt_raster_glyphs_exactly)
+ raster = sfnt_raster_glyph_outline (outline);
+ else
+ raster = sfnt_raster_glyph_outline_exact (outline);
if (!raster)
return NULL;
@@ -2570,16 +2640,23 @@ sfntfont_lookup_glyph (struct sfnt_font_info *font_info, int c)
return glyph;
}
+static int sfntfont_measure_pcm (struct sfnt_font_info *, sfnt_glyph,
+ struct font_metrics *);
+
/* Probe and set FONT_INFO->font.average_width,
FONT_INFO->font.space_width, and FONT_INFO->font.min_width
- according to the tables contained therein. */
+ according to the tables contained therein.
+
+ As this function generates outlines for all glyphs, outlines for
+ all ASCII characters will be entered into the outline cache as
+ well. */
static void
sfntfont_probe_widths (struct sfnt_font_info *font_info)
{
int i, num_characters, total_width;
sfnt_glyph glyph;
- struct sfnt_glyph_metrics metrics;
+ struct font_metrics pcm;
num_characters = 0;
total_width = 0;
@@ -2591,36 +2668,34 @@ sfntfont_probe_widths (struct sfnt_font_info *font_info)
/* Next, loop through the common ASCII characters. Tally up their
advance widths and set space_width if necessary. */
- for (i = 0; i < 127; ++i)
+ for (i = 32; i < 127; ++i)
{
glyph = sfntfont_lookup_glyph (font_info, i);
if (!glyph)
continue;
- /* Now look up the metrics of this glyph. */
- if (sfnt_lookup_glyph_metrics (glyph, font_info->font.pixel_size,
- &metrics, font_info->hmtx,
- font_info->hhea, font_info->head,
- font_info->maxp))
+ /* Now look up the metrics of this glyph. Data from the metrics
+ table doesn't fit the bill, since variations and instruction
+ code is not applied to it. */
+ if (sfntfont_measure_pcm (font_info, glyph, &pcm))
continue;
/* Increase the number of characters. */
num_characters++;
/* Add the advance to total_width. */
- total_width += SFNT_CEIL_FIXED (metrics.advance) / 65536;
+ total_width += pcm.width;
/* Update min_width if it hasn't been set yet or is wider. */
if (font_info->font.min_width == 1
- || font_info->font.min_width > metrics.advance / 65536)
- font_info->font.min_width = metrics.advance / 65536;
+ || font_info->font.min_width > pcm.width)
+ font_info->font.min_width = pcm.width;
/* If i is the space character, set the space width. Make sure
to round this up. */
if (i == 32)
- font_info->font.space_width
- = SFNT_CEIL_FIXED (metrics.advance) / 65536;
+ font_info->font.space_width = pcm.width;
}
/* Now, if characters were found, set average_width. */
@@ -2648,6 +2723,18 @@ sfntfont_setup_interpreter (struct sfnt_font_info *info,
struct sfnt_interpreter *interpreter;
const char *error;
struct sfnt_graphics_state state;
+ Lisp_Object regexp;
+
+ /* If Vsfnt_uninstructable_family_regexp matches this font, then
+ return. */
+
+ regexp = Vsfnt_uninstructable_family_regexp;
+
+ if (STRINGP (regexp)
+ && (fast_string_match_ignore_case (regexp,
+ desc->family)
+ >= 0))
+ return;
/* Load the cvt, fpgm and prep already read. */
@@ -2740,7 +2827,9 @@ sfntfont_setup_interpreter (struct sfnt_font_info *info,
static void
sfnt_close_tables (struct sfnt_font_tables *tables)
{
+#ifdef HAVE_MMAP
int rc;
+#endif /* HAVE_MMAP */
xfree (tables->cmap);
xfree (tables->hhea);
@@ -2795,7 +2884,10 @@ sfnt_open_tables (struct sfnt_font_desc *desc)
{
struct sfnt_font_tables *tables;
struct sfnt_offset_subtable *subtable;
- int fd, i, rc;
+ int fd, i;
+#ifdef HAVE_MMAP
+ int rc;
+#endif /* HAVE_MMAP */
struct sfnt_cmap_encoding_subtable *subtables;
struct sfnt_cmap_encoding_subtable_data **data;
struct sfnt_cmap_format_14 *format14;
@@ -3155,10 +3247,12 @@ sfntfont_open (struct frame *f, Lisp_Object font_entity,
/* Figure out the font ascent and descent. */
font->ascent
= ceil (font_info->hhea->ascent
- * pixel_size * 1.0 / font_info->head->units_per_em);
+ * pixel_size
+ * (1.0 / font_info->head->units_per_em));
font->descent
- = -floor (font_info->hhea->descent
- * pixel_size * 1.0 / font_info->head->units_per_em);
+ = ceil ((-font_info->hhea->descent)
+ * pixel_size
+ * (1.0 / font_info->head->units_per_em));
font->height = font->ascent + font->descent;
/* Set font->max_width to the maximum advance width. */
@@ -3167,11 +3261,7 @@ sfntfont_open (struct frame *f, Lisp_Object font_entity,
/* Set generic attributes such as type and style. */
ASET (font_object, FONT_TYPE_INDEX, sfnt_vendor_name);
-
- if (!NILP (desc->designer))
- ASET (font_object, FONT_FOUNDRY_INDEX,
- Fintern (desc->designer, Qnil));
-
+ ASET (font_object, FONT_FOUNDRY_INDEX, desc->designer);
ASET (font_object, FONT_FAMILY_INDEX, Fintern (desc->family, Qnil));
ASET (font_object, FONT_ADSTYLE_INDEX, Qnil);
ASET (font_object, FONT_REGISTRY_INDEX,
@@ -3180,8 +3270,7 @@ sfntfont_open (struct frame *f, Lisp_Object font_entity,
/* Size of 0 means the font is scalable. */
ASET (font_object, FONT_SIZE_INDEX, make_fixnum (0));
ASET (font_object, FONT_AVGWIDTH_INDEX, make_fixnum (0));
- ASET (font_object, FONT_SPACING_INDEX,
- make_fixnum (desc->spacing));
+ ASET (font_object, FONT_SPACING_INDEX, make_fixnum (desc->spacing));
/* Set the font style. */
@@ -3194,16 +3283,26 @@ sfntfont_open (struct frame *f, Lisp_Object font_entity,
ASET (font_object, FONT_ADSTYLE_INDEX, Qnil);
- /* Find out the minimum, maximum and average widths. */
- sfntfont_probe_widths (font_info);
-
/* Clear various offsets. */
font_info->font.baseline_offset = 0;
font_info->font.relative_compose = 0;
font_info->font.default_ascent = 0;
font_info->font.vertical_centering = 0;
- font_info->font.underline_position = -1;
- font_info->font.underline_thickness = 0;
+
+ if (!desc->underline_position_set)
+ {
+ font_info->font.underline_position = -1;
+ font_info->font.underline_thickness = 0;
+ }
+ else
+ {
+ font_info->font.underline_position
+ = sfnt_coerce_fixed (-desc->underline_position
+ * font_info->scale) + 0.5;
+ font_info->font.underline_thickness
+ = sfnt_coerce_fixed (desc->underline_thickness
+ * font_info->scale) + 0.5;
+ }
/* Now try to set up grid fitting for this font. */
dpyinfo = FRAME_DISPLAY_INFO (f);
@@ -3273,8 +3372,12 @@ sfntfont_open (struct frame *f, Lisp_Object font_entity,
}
cancel_blend:
+
+ /* Find out the minimum, maximum and average widths. */
+ sfntfont_probe_widths (font_info);
+
/* Calculate the xfld name. */
- font->props[FONT_NAME_INDEX] = Ffont_xlfd_name (font_object, Qnil);
+ font->props[FONT_NAME_INDEX] = Ffont_xlfd_name (font_object, Qnil, Qt);
#ifdef HAVE_HARFBUZZ
/* HarfBuzz will potentially read font tables after the font has
@@ -3294,6 +3397,32 @@ sfntfont_open (struct frame *f, Lisp_Object font_entity,
open_fonts = font_info;
#endif /* HAVE_MMAP */
+ /* Now ascertain if vertical centering is desired by matching the
+ font XLFD against vertical-centering-font-regexp. */
+
+ if (!NILP (font->props[FONT_NAME_INDEX]))
+ font->vertical_centering
+ = (STRINGP (Vvertical_centering_font_regexp)
+ && (fast_string_match_ignore_case
+ (Vvertical_centering_font_regexp,
+ font->props[FONT_NAME_INDEX]) >= 0));
+
+ /* Set the name of the font file. */
+ font->props[FONT_FILE_INDEX]
+ = DECODE_FILE (build_unibyte_string (desc->path));
+
+ /* Encapsulate some information on the font useful while debugging
+ (along with being informative in general) in the font name. */
+
+ AUTO_STRING (format, "%s %s interpreted: %s upem: %s charset: %s"
+ " instance: %s");
+ font->props[FONT_FULLNAME_INDEX]
+ = CALLN (Fformat, format, desc->family, desc->style,
+ font_info->interpreter ? Qt : Qnil,
+ make_fixnum (font_info->head->units_per_em),
+ CHARSET_NAME (charset),
+ make_fixnum (instance));
+
/* All done. */
unblock_input ();
return font_object;
@@ -3360,12 +3489,12 @@ sfntfont_measure_pcm (struct sfnt_font_info *font, sfnt_glyph glyph,
if (!outline)
return 1;
- /* Round the left side bearing downwards. */
- pcm->lbearing = SFNT_FLOOR_FIXED (metrics.lbearing) / 65536;
+ /* The left side bearing has already been floored. */
+ pcm->lbearing = metrics.lbearing / 65536;
pcm->rbearing = SFNT_CEIL_FIXED (outline->xmax) / 65536;
- /* Round the advance, ascent and descent upwards. */
- pcm->width = SFNT_CEIL_FIXED (metrics.advance) / 65536;
+ /* The advance is already rounded; ceil the ascent and descent. */
+ pcm->width = metrics.advance / 65536;
pcm->ascent = SFNT_CEIL_FIXED (outline->ymax) / 65536;
pcm->descent = SFNT_CEIL_FIXED (-outline->ymin) / 65536;
@@ -3569,7 +3698,7 @@ sfntfont_draw (struct glyph_string *s, int from, int to,
if (s->padding_p)
current_x += 1;
else
- current_x += SFNT_CEIL_FIXED (metrics.advance) / 65536;
+ current_x += metrics.advance / 65536;
}
/* Call the window system function to put the glyphs to the
@@ -3597,7 +3726,7 @@ sfntfont_draw (struct glyph_string *s, int from, int to,
Lisp_Object
sfntfont_list_family (struct frame *f)
{
- Lisp_Object families;
+ Lisp_Object families, tem, next;
struct sfnt_font_desc *desc;
families = Qnil;
@@ -3606,8 +3735,30 @@ sfntfont_list_family (struct frame *f)
/* Add desc->family to the list. */
families = Fcons (desc->family, families);
- /* Not sure if deleting duplicates is worth it. Is this ever
- called? */
+ /* Sort families in preparation for removing duplicates. */
+ families = Fsort (families, Qstring_lessp);
+
+ /* Remove each duplicate within families. */
+
+ tem = families;
+ while (!NILP (tem) && !NILP ((next = XCDR (tem))))
+ {
+ /* If the two strings are equal. */
+ if (!NILP (Fstring_equal (XCAR (tem), XCAR (next))))
+ /* Set tem's cdr to the cons after the next item. */
+ XSETCDR (tem, XCDR (next));
+ else
+ /* Otherwise, start considering the next item. */
+ tem = next;
+ }
+
+ /* Intern each font family. */
+
+ tem = families;
+
+ FOR_EACH_TAIL (tem)
+ XSETCAR (tem, Fintern (XCAR (tem), Qnil));
+
return families;
}
@@ -3636,9 +3787,10 @@ sfntfont_get_variation_glyphs (struct font *font, int c,
unsigned variations[256])
{
struct sfnt_font_info *info;
- size_t i;
+ size_t i, index;
int n;
struct sfnt_mapped_variation_selector_record *record;
+ sfnt_glyph default_glyph;
info = (struct sfnt_font_info *) font;
n = 0;
@@ -3659,12 +3811,37 @@ sfntfont_get_variation_glyphs (struct font *font, int c,
&& info->uvs->records[i].selector < 0xfe00)
++i;
+ /* Get the glyph represented by C, used when C is present within a
+ default value table. */
+
+ default_glyph = sfntfont_lookup_glyph (info, c);
+
/* Fill in selectors 0 to 15. */
while (i < info->uvs->num_records
&& info->uvs->records[i].selector <= 0xfe0f)
{
record = &info->uvs->records[i];
+ index = info->uvs->records[i].selector - 0xfe00 + 16;
+
+ /* Handle invalid unsorted tables. */
+
+ if (record->selector < 0xfe00)
+ return 0;
+
+ /* If there are default mappings in this record, ascertain if
+ this glyph matches one of them. */
+
+ if (record->default_uvs
+ && sfnt_is_character_default (record->default_uvs, c))
+ {
+ variations[index] = default_glyph;
+
+ if (default_glyph)
+ ++n;
+
+ goto next_selector;
+ }
/* If record has no non-default mappings, continue on to the
next selector. */
@@ -3672,18 +3849,13 @@ sfntfont_get_variation_glyphs (struct font *font, int c,
if (!record->nondefault_uvs)
goto next_selector;
- /* Handle invalid unsorted tables. */
-
- if (record->selector < 0xfe00)
- return 0;
-
/* Find the glyph ID associated with C and put it in
VARIATIONS. */
- variations[info->uvs->records[i].selector - 0xfe00]
+ variations[index]
= sfnt_variation_glyph_for_char (record->nondefault_uvs, c);
- if (variations[info->uvs->records[i].selector - 0xfe00])
+ if (variations[index])
++n;
next_selector:
@@ -3703,6 +3875,26 @@ sfntfont_get_variation_glyphs (struct font *font, int c,
&& info->uvs->records[i].selector <= 0xe01ef)
{
record = &info->uvs->records[i];
+ index = info->uvs->records[i].selector - 0xe0100 + 16;
+
+ /* Handle invalid unsorted tables. */
+
+ if (record->selector < 0xe0100)
+ return 0;
+
+ /* If there are default mappings in this record, ascertain if
+ this glyph matches one of them. */
+
+ if (record->default_uvs
+ && sfnt_is_character_default (record->default_uvs, c))
+ {
+ variations[index] = default_glyph;
+
+ if (default_glyph)
+ ++n;
+
+ goto next_selector_1;
+ }
/* If record has no non-default mappings, continue on to the
next selector. */
@@ -3710,18 +3902,13 @@ sfntfont_get_variation_glyphs (struct font *font, int c,
if (!record->nondefault_uvs)
goto next_selector_1;
- /* Handle invalid unsorted tables. */
-
- if (record->selector < 0xe0100)
- return 0;
-
/* Find the glyph ID associated with C and put it in
VARIATIONS. */
- variations[info->uvs->records[i].selector - 0xe0100 + 16]
+ variations[index]
= sfnt_variation_glyph_for_char (record->nondefault_uvs, c);
- if (variations[info->uvs->records[i].selector - 0xe0100 + 16])
+ if (variations[index])
++n;
next_selector_1:
@@ -3757,7 +3944,7 @@ sfntfont_detect_sigbus (void *addr)
return false;
}
-#endif
+#endif /* HAVE_MMAP */
@@ -3910,6 +4097,12 @@ syms_of_sfntfont (void)
/* Char-table purpose. */
DEFSYM (Qfont_lookup_cache, "font-lookup-cache");
+ /* Default foundry name. */
+ DEFSYM (Qmisc, "misc");
+
+ /* Predicated employed for sorting font family lists. */
+ DEFSYM (Qstring_lessp, "string-lessp");
+
/* Set up staticpros. */
sfnt_vendor_name = Qnil;
staticpro (&sfnt_vendor_name);
@@ -3918,12 +4111,33 @@ syms_of_sfntfont (void)
of the font backend. */
DEFVAR_LISP ("sfnt-default-family-alist", Vsfnt_default_family_alist,
doc: /* Alist between "emulated" and actual font family names.
-
Much Emacs code assumes that font families named "Monospace" and "Sans
Serif" exist, and map to the default monospace and Sans Serif fonts on
a system. When the `sfnt' font driver is asked to look for a font
with one of the families in this alist, it uses its value instead. */);
Vsfnt_default_family_alist = Qnil;
+
+ DEFVAR_LISP ("sfnt-uninstructable-family-regexp",
+ Vsfnt_uninstructable_family_regexp,
+ doc: /* Regexp matching font families whose glyphs must not be instructed.
+If nil, instruction code supplied by all fonts will be executed. This
+variable takes effect when a font entity is opened, not after, and
+therefore won't affect the scaling of realized faces until their
+frames' font caches are cleared (see `clear-font-cache').
+
+TrueType fonts incorporate instruction code executed to fit each glyph
+to a pixel grid, so as to improve the visual fidelity of each glyph by
+eliminating artifacts and chance effects consequent upon the direct
+upscaling of glyph outline data. Instruction code is occasionally
+incompatible with Emacs and must be disregarded. */);
+ Vsfnt_uninstructable_family_regexp = Qnil;
+
+ DEFVAR_BOOL ("sfnt-raster-glyphs-exactly", sfnt_raster_glyphs_exactly,
+ doc: /* How font glyph outlines should be converted to graphics.
+If non-nil, glyphs will be displayed in a more precise manner, at the
+cost of performance on devices where floating-point math operations
+are slow. */);
+ sfnt_raster_glyphs_exactly = true;
}
void
diff --git a/src/sfntfont.h b/src/sfntfont.h
index 28267cdb1d6..0e57ee35028 100644
--- a/src/sfntfont.h
+++ b/src/sfntfont.h
@@ -1,6 +1,6 @@
/* sfnt format font driver for GNU Emacs.
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/sheap.c b/src/sheap.c
index 9ea0d91ef75..bab70c4e343 100644
--- a/src/sheap.c
+++ b/src/sheap.c
@@ -1,7 +1,7 @@
/* simulate `sbrk' with an array in .bss, for `unexec' support for Cygwin;
complete rewrite of xemacs Cygwin `unexec' code
- Copyright (C) 2004-2023 Free Software Foundation, Inc.
+ Copyright (C) 2004-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/sheap.h b/src/sheap.h
index b62adf4318f..92f7ba5e857 100644
--- a/src/sheap.h
+++ b/src/sheap.h
@@ -1,6 +1,6 @@
/* Static heap allocation for GNU Emacs.
-Copyright 2016-2023 Free Software Foundation, Inc.
+Copyright 2016-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/sort.c b/src/sort.c
index 706c057dab0..5f7a1ee2f53 100644
--- a/src/sort.c
+++ b/src/sort.c
@@ -1,6 +1,6 @@
/* Timsort for sequences.
-Copyright (C) 2022-2023 Free Software Foundation, Inc.
+Copyright (C) 2022-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/sound.c b/src/sound.c
index 9c023725da0..004015fc936 100644
--- a/src/sound.c
+++ b/src/sound.c
@@ -1,6 +1,6 @@
/* sound.c -- sound support.
-Copyright (C) 1998-1999, 2001-2023 Free Software Foundation, Inc.
+Copyright (C) 1998-1999, 2001-2024 Free Software Foundation, Inc.
Author: Gerd Moellmann <gerd@gnu.org>
diff --git a/src/sqlite.c b/src/sqlite.c
index fd528f2b0d5..7a018b28aa4 100644
--- a/src/sqlite.c
+++ b/src/sqlite.c
@@ -1,6 +1,6 @@
/* Support for accessing SQLite databases.
-Copyright (C) 2021-2023 Free Software Foundation, Inc.
+Copyright (C) 2021-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
@@ -716,7 +716,9 @@ Only modules on Emacs' list of allowed modules can be loaded. */)
"rtree",
"sha1",
"uuid",
+ "vector0",
"vfslog",
+ "vss0",
"zipfile",
NULL
};
diff --git a/src/syntax.c b/src/syntax.c
index 0cac923bba7..a4ad61328e6 100644
--- a/src/syntax.c
+++ b/src/syntax.c
@@ -1,5 +1,5 @@
/* GNU Emacs routines to deal with syntax tables; also word and list parsing.
- Copyright (C) 1985, 1987, 1993-1995, 1997-1999, 2001-2023 Free
+ Copyright (C) 1985, 1987, 1993-1995, 1997-1999, 2001-2024 Free
Software Foundation, Inc.
This file is part of GNU Emacs.
@@ -468,7 +468,7 @@ parse_sexp_propertize (ptrdiff_t charpos)
&& syntax_propertize__done < zv)
{
modiff_count modiffs = CHARS_MODIFF;
- safe_call1 (Qinternal__syntax_propertize,
+ safe_calln (Qinternal__syntax_propertize,
make_fixnum (min (zv, 1 + charpos)));
if (modiffs != CHARS_MODIFF)
error ("internal--syntax-propertize modified the buffer!");
diff --git a/src/syntax.h b/src/syntax.h
index 01982be25a0..34e53775a97 100644
--- a/src/syntax.h
+++ b/src/syntax.h
@@ -1,6 +1,6 @@
/* Declarations having to do with GNU Emacs syntax tables.
-Copyright (C) 1985, 1993-1994, 1997-1998, 2001-2023 Free Software
+Copyright (C) 1985, 1993-1994, 1997-1998, 2001-2024 Free Software
Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/sysdep.c b/src/sysdep.c
index 52fbfbd1eb1..3a6829dd27a 100644
--- a/src/sysdep.c
+++ b/src/sysdep.c
@@ -1,5 +1,5 @@
/* Interfaces to system-dependent kernel and library entries.
- Copyright (C) 1985-1988, 1993-1995, 1999-2023 Free Software
+ Copyright (C) 1985-1988, 1993-1995, 1999-2024 Free Software
Foundation, Inc.
This file is part of GNU Emacs.
@@ -36,7 +36,6 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include <utimens.h>
#include "lisp.h"
-#include "sheap.h"
#include "sysselect.h"
#include "blockinput.h"
@@ -3452,7 +3451,7 @@ make_lisp_timeval (struct timeval t)
#endif
-#if defined (GNU_LINUX) || defined (CYGWIN)
+#if defined (GNU_LINUX) || defined (CYGWIN) || defined __ANDROID__
static Lisp_Object
time_from_jiffies (unsigned long long ticks, Lisp_Object hz, Lisp_Object form)
@@ -3500,7 +3499,7 @@ get_up_time (void)
return up;
}
-# ifdef GNU_LINUX
+# if defined GNU_LINUX || defined __ANDROID__
#define MAJOR(d) (((unsigned)(d) >> 8) & 0xfff)
#define MINOR(d) (((unsigned)(d) & 0xff) | (((unsigned)(d) & 0xfff00000) >> 12))
@@ -3546,7 +3545,7 @@ procfs_ttyname (int rdev)
unblock_input ();
return build_string (name);
}
-# endif /* GNU_LINUX */
+# endif /* GNU_LINUX || __ANDROID__ */
static uintmax_t
procfs_get_total_memory (void)
@@ -3695,9 +3694,9 @@ system_process_attributes (Lisp_Object pid)
attrs = Fcons (Fcons (Qppid, INT_TO_INTEGER (ppid)), attrs);
attrs = Fcons (Fcons (Qpgrp, INT_TO_INTEGER (pgrp)), attrs);
attrs = Fcons (Fcons (Qsess, INT_TO_INTEGER (sess)), attrs);
-# ifdef GNU_LINUX
+# if defined GNU_LINUX || defined __ANDROID__
attrs = Fcons (Fcons (Qttname, procfs_ttyname (tty)), attrs);
-# endif
+# endif /* GNU_LINUX || __ANDROID__ */
attrs = Fcons (Fcons (Qtpgid, INT_TO_INTEGER (tpgid)), attrs);
attrs = Fcons (Fcons (Qminflt, INT_TO_INTEGER (minflt)), attrs);
attrs = Fcons (Fcons (Qmajflt, INT_TO_INTEGER (majflt)), attrs);
diff --git a/src/sysselect.h b/src/sysselect.h
index 6cde52911f4..ccb10c1d124 100644
--- a/src/sysselect.h
+++ b/src/sysselect.h
@@ -1,5 +1,5 @@
/* sysselect.h - System-dependent definitions for the select function.
- Copyright (C) 1995, 2001-2023 Free Software Foundation, Inc.
+ Copyright (C) 1995, 2001-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/syssignal.h b/src/syssignal.h
index 6aa3572b903..e5144588c75 100644
--- a/src/syssignal.h
+++ b/src/syssignal.h
@@ -1,6 +1,6 @@
/* syssignal.h - System-dependent definitions for signals.
-Copyright (C) 1993, 1999, 2001-2023 Free Software Foundation, Inc.
+Copyright (C) 1993, 1999, 2001-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/sysstdio.h b/src/sysstdio.h
index 8e9e5bec86c..3a3d23ee0a8 100644
--- a/src/sysstdio.h
+++ b/src/sysstdio.h
@@ -1,6 +1,6 @@
/* Standard I/O for Emacs.
-Copyright 2013-2023 Free Software Foundation, Inc.
+Copyright 2013-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/systhread.c b/src/systhread.c
index caa4dfd4443..ef40cb0a223 100644
--- a/src/systhread.c
+++ b/src/systhread.c
@@ -1,5 +1,5 @@
/* System thread definitions
-Copyright (C) 2012-2023 Free Software Foundation, Inc.
+Copyright (C) 2012-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/systhread.h b/src/systhread.h
index b8f078df071..c36a1ca6142 100644
--- a/src/systhread.h
+++ b/src/systhread.h
@@ -1,5 +1,5 @@
/* System thread definitions
-Copyright (C) 2012-2023 Free Software Foundation, Inc.
+Copyright (C) 2012-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/systime.h b/src/systime.h
index 936f1a50a96..fc93ea03233 100644
--- a/src/systime.h
+++ b/src/systime.h
@@ -1,5 +1,5 @@
/* systime.h - System-dependent definitions for time manipulations.
- Copyright (C) 1993-1994, 2002-2023 Free Software Foundation, Inc.
+ Copyright (C) 1993-1994, 2002-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/systty.h b/src/systty.h
index 918b4178905..7038cce27ef 100644
--- a/src/systty.h
+++ b/src/systty.h
@@ -1,5 +1,5 @@
/* systty.h - System-dependent definitions for terminals.
- Copyright (C) 1993-1994, 2001-2023 Free Software Foundation, Inc.
+ Copyright (C) 1993-1994, 2001-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/syswait.h b/src/syswait.h
index 80e2d8d39d0..f4790b725a9 100644
--- a/src/syswait.h
+++ b/src/syswait.h
@@ -1,5 +1,5 @@
/* Define wait system call interface for Emacs.
- Copyright (C) 1993-1995, 2000-2023 Free Software Foundation, Inc.
+ Copyright (C) 1993-1995, 2000-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/term.c b/src/term.c
index 9bcb2cb1386..d3c858c6bf2 100644
--- a/src/term.c
+++ b/src/term.c
@@ -1,5 +1,5 @@
/* Terminal control module for terminals described by TERMCAP
- Copyright (C) 1985-1987, 1993-1995, 1998, 2000-2023 Free Software
+ Copyright (C) 1985-1987, 1993-1995, 1998, 2000-2024 Free Software
Foundation, Inc.
This file is part of GNU Emacs.
@@ -76,7 +76,7 @@ static void set_tty_hooks (struct terminal *terminal);
static void dissociate_if_controlling_tty (int fd);
static void delete_tty (struct terminal *);
-#endif
+#endif /* !HAVE_ANDROID */
static AVOID maybe_fatal (bool, struct terminal *, const char *, const char *,
...)
@@ -2235,7 +2235,7 @@ set_tty_color_mode (struct tty_display_info *tty, struct frame *f)
tty->previous_color_mode = mode;
tty_setup_colors (tty , mode);
/* This recomputes all the faces given the new color definitions. */
- safe_call (1, intern ("tty-set-up-initial-frame-faces"));
+ safe_calln (intern ("tty-set-up-initial-frame-faces"));
}
}
@@ -2356,7 +2356,7 @@ A suspended tty may be resumed by calling `resume-tty' on it. */)
if (f != t->display_info.tty->output)
emacs_fclose (t->display_info.tty->output);
emacs_fclose (f);
-#endif
+#endif /* !MSDOS */
t->display_info.tty->input = 0;
t->display_info.tty->output = 0;
@@ -2368,10 +2368,11 @@ A suspended tty may be resumed by calling `resume-tty' on it. */)
/* Clear display hooks to prevent further output. */
clear_tty_hooks (t);
-#else
- /* This will always signal on Android. */
- decode_tty_terminal (tty);
-#endif
+#else /* HAVE_ANDROID */
+ /* Android doesn't support TTY terminal devices, so unconditionally
+ signal. */
+ error ("Attempt to suspend a non-text terminal device");
+#endif /* !HAVE_ANDROID */
return Qnil;
}
@@ -2428,7 +2429,7 @@ frame's terminal). */)
if (!O_IGNORE_CTTY && strcmp (t->display_info.tty->name, DEV_TTY) != 0)
dissociate_if_controlling_tty (fd);
-#endif
+#endif /* MSDOS */
add_keyboard_wait_descriptor (fd);
@@ -2457,9 +2458,11 @@ frame's terminal). */)
}
set_tty_hooks (t);
-#else
- decode_tty_terminal (tty);
-#endif
+#else /* HAVE_ANDROID */
+ /* Android doesn't support TTY terminal devices, so unconditionally
+ signal. */
+ error ("Attempt to suspend a non-text terminal device");
+#endif /* !HAVE_ANDROID */
return Qnil;
}
@@ -2504,7 +2507,7 @@ A value of zero means TTY uses the system's default value. */)
error ("Not a tty terminal");
}
-#endif
+#endif /* !HAVE_ANDROID */
/***********************************************************************
diff --git a/src/termcap.c b/src/termcap.c
index 1e989b6e2de..a8c1cef2456 100644
--- a/src/termcap.c
+++ b/src/termcap.c
@@ -1,5 +1,5 @@
/* Work-alike for termcap, plus extra features.
- Copyright (C) 1985-1986, 1993-1995, 2000-2008, 2011, 2013-2023 Free
+ Copyright (C) 1985-1986, 1993-1995, 2000-2008, 2011, 2013-2024 Free
Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
diff --git a/src/termchar.h b/src/termchar.h
index 5c47679a994..2d845107e11 100644
--- a/src/termchar.h
+++ b/src/termchar.h
@@ -1,5 +1,5 @@
/* Flags and parameters describing terminal's characteristics.
- Copyright (C) 1985-1986, 2001-2023 Free Software Foundation, Inc.
+ Copyright (C) 1985-1986, 2001-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/termhooks.h b/src/termhooks.h
index 6bf507aae33..8defebb20bd 100644
--- a/src/termhooks.h
+++ b/src/termhooks.h
@@ -1,6 +1,6 @@
/* Parameters and display hooks for terminal devices.
-Copyright (C) 1985-1986, 1993-1994, 2001-2023 Free Software Foundation,
+Copyright (C) 1985-1986, 1993-1994, 2001-2024 Free Software Foundation,
Inc.
This file is part of GNU Emacs.
diff --git a/src/terminal.c b/src/terminal.c
index 07c37883f0e..23a5582d4d9 100644
--- a/src/terminal.c
+++ b/src/terminal.c
@@ -1,5 +1,5 @@
/* Functions related to terminal devices.
- Copyright (C) 2005-2023 Free Software Foundation, Inc.
+ Copyright (C) 2005-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
@@ -389,7 +389,7 @@ but if the second argument FORCE is non-nil, you may do so. */)
Qdelete_terminal_functions, terminal),
pending_funcalls);
else
- safe_call2 (Qrun_hook_with_args, Qdelete_terminal_functions, terminal);
+ safe_calln (Qrun_hook_with_args, Qdelete_terminal_functions, terminal);
if (t->delete_terminal_hook)
(*t->delete_terminal_hook) (t);
diff --git a/src/terminfo.c b/src/terminfo.c
index 66820920d47..4feac32bedc 100644
--- a/src/terminfo.c
+++ b/src/terminfo.c
@@ -1,5 +1,5 @@
/* Interface from Emacs to terminfo.
- Copyright (C) 1985-1986, 2001-2023 Free Software Foundation, Inc.
+ Copyright (C) 1985-1986, 2001-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/termopts.h b/src/termopts.h
index 346c46bdaaa..f5df2464c23 100644
--- a/src/termopts.h
+++ b/src/termopts.h
@@ -1,5 +1,5 @@
/* Flags and parameters describing user options for handling the terminal.
- Copyright (C) 1985-1986, 1990, 2001-2023 Free Software Foundation,
+ Copyright (C) 1985-1986, 1990, 2001-2024 Free Software Foundation,
Inc.
This file is part of GNU Emacs.
diff --git a/src/textconv.c b/src/textconv.c
index 57daa7e53b6..2a7b0ed330d 100644
--- a/src/textconv.c
+++ b/src/textconv.c
@@ -1,6 +1,6 @@
/* String conversion support for graphics terminals.
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
@@ -23,7 +23,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
They may then request that the text editor remove or substitute
that text for something else, for example when providing the
ability to ``undo'' or ``edit'' previously composed text. This is
- most commonly seen in input methods for CJK laguages for X Windows,
+ most commonly seen in input methods for CJK languages for X Windows,
and is extensively used throughout Android by input methods for all
kinds of scripts.
@@ -616,6 +616,12 @@ really_commit_text (struct frame *f, EMACS_INT position,
end = max (mark, PT);
}
+ /* If it transpires that the start of the compose region is not
+ point, move point there. */
+
+ if (start != PT)
+ set_point (start);
+
/* Now delete whatever needs to go. */
del_range_1 (start, end, true, false);
@@ -635,7 +641,7 @@ really_commit_text (struct frame *f, EMACS_INT position,
record_buffer_change (start, PT, text);
}
- /* Move to a the position specified in POSITION. */
+ /* Move to the position specified in POSITION. */
if (position <= 0)
{
@@ -1154,6 +1160,135 @@ really_set_point_and_mark (struct frame *f, ptrdiff_t point,
unbind_to (count, Qnil);
}
+/* Remove the composing region. Replace the text between START and
+ END in F's selected window with TEXT, then set point to POSITION
+ relative to it. If the mark is active, deactivate it. */
+
+static void
+really_replace_text (struct frame *f, ptrdiff_t start, ptrdiff_t end,
+ Lisp_Object text, ptrdiff_t position)
+{
+ specpdl_ref count;
+ ptrdiff_t new_start, new_end, wanted;
+ struct window *w;
+
+ /* If F's old selected window is no longer alive, fail. */
+
+ if (!WINDOW_LIVE_P (f->old_selected_window))
+ return;
+
+ count = SPECPDL_INDEX ();
+ record_unwind_protect (restore_selected_window,
+ selected_window);
+
+ /* Make the composition region markers point elsewhere. */
+
+ if (!NILP (f->conversion.compose_region_start))
+ {
+ Fset_marker (f->conversion.compose_region_start, Qnil, Qnil);
+ Fset_marker (f->conversion.compose_region_end, Qnil, Qnil);
+ f->conversion.compose_region_start = Qnil;
+ f->conversion.compose_region_end = Qnil;
+
+ /* Notify the IME of an update to the composition region,
+ inasmuch as the point might not change if START and END are
+ identical and TEXT is empty, among other circumstances. */
+
+ if (text_interface
+ && text_interface->compose_region_changed)
+ (*text_interface->compose_region_changed) (f);
+ }
+
+ /* Delete the composition region overlay. */
+
+ if (!NILP (f->conversion.compose_region_overlay))
+ Fdelete_overlay (f->conversion.compose_region_overlay);
+
+ /* Temporarily switch to F's selected window at the time of the last
+ redisplay. */
+ select_window (f->old_selected_window, Qt);
+
+ /* Sort START and END by magnitude. */
+ new_start = min (start, end);
+ new_end = max (start, end);
+
+ /* Now constrain both to the accessible region. */
+
+ if (new_start < BEGV)
+ new_start = BEGV;
+ else if (new_start > ZV)
+ new_start = ZV;
+
+ if (new_end < BEGV)
+ new_end = BEGV;
+ else if (new_end > ZV)
+ new_end = ZV;
+
+ start = new_start;
+ end = new_end;
+
+ /* This should deactivate the mark. */
+ call0 (Qdeactivate_mark);
+
+ /* Go to start. */
+ set_point (start);
+
+ /* Now delete the text in between, and save PT before TEXT is
+ inserted. */
+ del_range_1 (start, end, true, false);
+ record_buffer_change (start, start, Qt);
+ wanted = PT;
+
+ /* So long as TEXT isn't empty, insert it now. */
+
+ if (SCHARS (text))
+ {
+ /* Insert the new text. Make sure to inherit text properties
+ from the surroundings: if this doesn't happen, CC Mode
+ fontification might grow confused and become very slow. */
+
+ insert_from_string (text, 0, 0, SCHARS (text),
+ SBYTES (text), true);
+ record_buffer_change (start, PT, text);
+ }
+
+ /* Now, move point to the position designated by POSITION. */
+
+ if (position <= 0)
+ {
+ if (INT_ADD_WRAPV (wanted, position, &wanted)
+ || wanted < BEGV)
+ wanted = BEGV;
+
+ if (wanted > ZV)
+ wanted = ZV;
+
+ set_point (wanted);
+ }
+ else
+ {
+ wanted = PT;
+
+ if (INT_ADD_WRAPV (wanted, position - 1, &wanted)
+ || wanted > ZV)
+ wanted = ZV;
+
+ if (wanted < BEGV)
+ wanted = BEGV;
+
+ set_point (wanted);
+ }
+
+ /* Print some debugging information. */
+ TEXTCONV_DEBUG ("text inserted: %s, point now: %zd",
+ SSDATA (text), PT);
+
+ /* Update the ephemeral last point. */
+ w = XWINDOW (selected_window);
+ w->ephemeral_last_point = PT;
+ unbind_to (count, Qnil);
+}
+
/* Complete the edit specified by the counter value inside *TOKEN. */
static void
@@ -1176,7 +1311,7 @@ struct complete_edit_check_context
/* Convert PTR to CONTEXT. If CONTEXT->check is false, then update
CONTEXT->w's ephemeral last point and give it to the input method,
- the assumption being that an editing operation signalled. */
+ the assumption being that an editing operation signaled. */
static void
complete_edit_check (void *ptr)
@@ -1244,7 +1379,7 @@ handle_pending_conversion_events_1 (struct frame *f,
or not the editing operation completed successfully. */
context.check = false;
- /* Make sure completion is signalled. */
+ /* Make sure completion is signaled. */
count = SPECPDL_INDEX ();
record_unwind_protect_ptr (complete_edit, &token);
w = NULL;
@@ -1325,6 +1460,13 @@ handle_pending_conversion_events_1 (struct frame *f,
if (w)
w->ephemeral_last_point = window_point (w);
break;
+
+ case TEXTCONV_REPLACE_TEXT:
+ really_replace_text (f, XFIXNUM (XCAR (data)),
+ XFIXNUM (XCAR (XCDR (data))),
+ XCAR (XCDR (XCDR (data))),
+ XFIXNUM (XCAR (XCDR (XCDR (XCDR (data))))));
+ break;
}
/* Signal success. */
@@ -1679,6 +1821,30 @@ textconv_barrier (struct frame *f, unsigned long counter)
input_pending = true;
}
+/* Remove the composing region. Replace the text between START and
+ END within F's selected window with TEXT; deactivate the mark if it
+ is active. Subsequently, set point to POSITION relative to TEXT,
+ much as `commit_text' would. */
+
+void
+replace_text (struct frame *f, ptrdiff_t start, ptrdiff_t end,
+ Lisp_Object text, ptrdiff_t position,
+ unsigned long counter)
+{
+ struct text_conversion_action *action, **last;
+
+ action = xmalloc (sizeof *action);
+ action->operation = TEXTCONV_REPLACE_TEXT;
+ action->data = list4 (make_fixnum (start), make_fixnum (end),
+ text, make_fixnum (position));
+ action->next = NULL;
+ action->counter = counter;
+ for (last = &f->conversion.actions; *last; last = &(*last)->next)
+ ;;
+ *last = action;
+ input_pending = true;
+}
+
/* Return N characters of text around point in frame F's old selected
window.
diff --git a/src/textconv.h b/src/textconv.h
index feac5b805af..61f13ebcb43 100644
--- a/src/textconv.h
+++ b/src/textconv.h
@@ -1,6 +1,6 @@
/* String conversion support for graphics terminals.
-Copyright (C) 2023 Free Software Foundation, Inc.
+Copyright (C) 2023-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
@@ -142,6 +142,9 @@ extern void delete_surrounding_text (struct frame *, ptrdiff_t,
ptrdiff_t, unsigned long);
extern void request_point_update (struct frame *, unsigned long);
extern void textconv_barrier (struct frame *, unsigned long);
+extern void replace_text (struct frame *, ptrdiff_t, ptrdiff_t,
+ Lisp_Object, ptrdiff_t, unsigned long);
+
extern char *get_extracted_text (struct frame *, ptrdiff_t, ptrdiff_t *,
ptrdiff_t *, ptrdiff_t *, ptrdiff_t *,
ptrdiff_t *, bool *);
diff --git a/src/textprop.c b/src/textprop.c
index f88fff19c59..7d9aae0d2c5 100644
--- a/src/textprop.c
+++ b/src/textprop.c
@@ -1,5 +1,5 @@
/* Interface code for dealing with text properties.
- Copyright (C) 1993-2023 Free Software Foundation, Inc.
+ Copyright (C) 1993-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/thread.c b/src/thread.c
index b8ca56fd372..040ca39511e 100644
--- a/src/thread.c
+++ b/src/thread.c
@@ -1,5 +1,5 @@
/* Threading code.
-Copyright (C) 2012-2023 Free Software Foundation, Inc.
+Copyright (C) 2012-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/thread.h b/src/thread.h
index 9b14cc44f35..6ce2b7f30df 100644
--- a/src/thread.h
+++ b/src/thread.h
@@ -1,5 +1,5 @@
/* Thread definitions
-Copyright (C) 2012-2023 Free Software Foundation, Inc.
+Copyright (C) 2012-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/timefns.c b/src/timefns.c
index 151f5b482a3..1541583b485 100644
--- a/src/timefns.c
+++ b/src/timefns.c
@@ -1,6 +1,6 @@
/* Timestamp functions for Emacs
-Copyright (C) 1985-1987, 1989, 1993-2023 Free Software Foundation, Inc.
+Copyright (C) 1985-1987, 1989, 1993-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/tparam.c b/src/tparam.c
index a0d2ee74d99..d19d484430d 100644
--- a/src/tparam.c
+++ b/src/tparam.c
@@ -1,5 +1,5 @@
/* Merge parameters into a termcap entry string.
- Copyright (C) 1985, 1987, 1993, 1995, 2000-2008, 2013-2023 Free
+ Copyright (C) 1985, 1987, 1993, 1995, 2000-2008, 2013-2024 Free
Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
@@ -183,7 +183,7 @@ tparam1 (const char *string, char *outstring, int len,
argp++;
break;
- case 'b': /* %b means back up one arg (and re-use it). */
+ case 'b': /* %b means back up one arg (and reuse it). */
argp--;
break;
diff --git a/src/tparam.h b/src/tparam.h
index 898ee38a64b..eab3613ffd3 100644
--- a/src/tparam.h
+++ b/src/tparam.h
@@ -1,6 +1,6 @@
/* Interface definitions for termcap entries.
-Copyright (C) 2011-2023 Free Software Foundation, Inc.
+Copyright (C) 2011-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/treesit.c b/src/treesit.c
index 550bc8b9ee0..12915ea9a10 100644
--- a/src/treesit.c
+++ b/src/treesit.c
@@ -1,6 +1,6 @@
/* Tree-sitter integration for GNU Emacs.
-Copyright (C) 2021-2023 Free Software Foundation, Inc.
+Copyright (C) 2021-2024 Free Software Foundation, Inc.
Maintainer: Yuan Fu <casouri@gmail.com>
@@ -80,6 +80,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#undef ts_tree_cursor_current_node
#undef ts_tree_cursor_delete
#undef ts_tree_cursor_goto_first_child
+#undef ts_tree_cursor_goto_first_child_for_byte
#undef ts_tree_cursor_goto_next_sibling
#undef ts_tree_cursor_goto_parent
#undef ts_tree_cursor_new
@@ -147,6 +148,7 @@ DEF_DLL_FN (TSTreeCursor, ts_tree_cursor_copy, (const TSTreeCursor *));
DEF_DLL_FN (TSNode, ts_tree_cursor_current_node, (const TSTreeCursor *));
DEF_DLL_FN (void, ts_tree_cursor_delete, (const TSTreeCursor *));
DEF_DLL_FN (bool, ts_tree_cursor_goto_first_child, (TSTreeCursor *));
+DEF_DLL_FN (int64_t, ts_tree_cursor_goto_first_child_for_byte, (TSTreeCursor *, uint32_t));
DEF_DLL_FN (bool, ts_tree_cursor_goto_next_sibling, (TSTreeCursor *));
DEF_DLL_FN (bool, ts_tree_cursor_goto_parent, (TSTreeCursor *));
DEF_DLL_FN (TSTreeCursor, ts_tree_cursor_new, (TSNode));
@@ -210,6 +212,7 @@ init_treesit_functions (void)
LOAD_DLL_FN (library, ts_tree_cursor_current_node);
LOAD_DLL_FN (library, ts_tree_cursor_delete);
LOAD_DLL_FN (library, ts_tree_cursor_goto_first_child);
+ LOAD_DLL_FN (library, ts_tree_cursor_goto_first_child_for_byte);
LOAD_DLL_FN (library, ts_tree_cursor_goto_next_sibling);
LOAD_DLL_FN (library, ts_tree_cursor_goto_parent);
LOAD_DLL_FN (library, ts_tree_cursor_new);
@@ -267,6 +270,7 @@ init_treesit_functions (void)
#define ts_tree_cursor_current_node fn_ts_tree_cursor_current_node
#define ts_tree_cursor_delete fn_ts_tree_cursor_delete
#define ts_tree_cursor_goto_first_child fn_ts_tree_cursor_goto_first_child
+#define ts_tree_cursor_goto_first_child_for_byte fn_ts_tree_cursor_goto_first_child_for_byte
#define ts_tree_cursor_goto_next_sibling fn_ts_tree_cursor_goto_next_sibling
#define ts_tree_cursor_goto_parent fn_ts_tree_cursor_goto_parent
#define ts_tree_cursor_new fn_ts_tree_cursor_new
@@ -596,8 +600,6 @@ treesit_load_language (Lisp_Object language_symbol,
/* First push just the filenames to the candidate list, which will
make dynlib_open look under standard system load paths. */
treesit_load_language_push_for_each_suffix (lib_base_name, &path_candidates);
- /* This is used for reporting errors (i.e., just filenames). */
- Lisp_Object base_candidates = path_candidates;
/* Then push ~/.emacs.d/tree-sitter paths. */
Lisp_Object lib_name
= Fexpand_file_name (concat2 (build_string ("tree-sitter/"), lib_base_name),
@@ -620,6 +622,7 @@ treesit_load_language (Lisp_Object language_symbol,
fail. */
dynlib_handle_ptr handle;
const char *error;
+ Lisp_Object error_list = Qnil;
tail = path_candidates;
error = NULL;
@@ -633,13 +636,17 @@ treesit_load_language (Lisp_Object language_symbol,
error = dynlib_error ();
if (error == NULL)
break;
+ else
+ error_list = Fcons (build_string (error), error_list);
}
if (error != NULL)
{
+ /* Yes, the error message list gets a bit verbose, but those
+ messages will be helpful for certain errors like libc version
+ mismatch. */
*signal_symbol = Qtreesit_load_language_error;
- *signal_data = list3 (Qnot_found, base_candidates,
- build_string ("No such file or directory"));
+ *signal_data = Fcons (Qnot_found, Fnreverse (error_list));
return NULL;
}
@@ -941,7 +948,10 @@ 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)->need_reparse = true;
+ XTS_PARSER (parser)->timestamp++;
+ }
/* Before we parse or set ranges, catch up with the narrowing
situation. We change visible_beg and visible_end to match
@@ -1036,7 +1046,7 @@ treesit_call_after_change_functions (TSTree *old_tree, TSTree *new_tree,
for each of them. */
Lisp_Object functions = XTS_PARSER (parser)->after_change_functions;
FOR_EACH_TAIL (functions)
- safe_call2 (XCAR (functions), lisp_ranges, parser);
+ safe_calln (XCAR (functions), lisp_ranges, parser);
unbind_to (count, Qnil);
}
@@ -1149,7 +1159,8 @@ treesit_read_buffer (void *parser, uint32_t byte_index,
machine. */
Lisp_Object
make_treesit_parser (Lisp_Object buffer, TSParser *parser,
- TSTree *tree, Lisp_Object language_symbol)
+ TSTree *tree, Lisp_Object language_symbol,
+ Lisp_Object tag)
{
struct Lisp_TS_Parser *lisp_parser;
@@ -1158,6 +1169,8 @@ make_treesit_parser (Lisp_Object buffer, TSParser *parser,
lisp_parser->language_symbol = language_symbol;
lisp_parser->after_change_functions = Qnil;
+ lisp_parser->tag = tag;
+ lisp_parser->last_set_ranges = Qnil;
lisp_parser->buffer = buffer;
lisp_parser->parser = parser;
lisp_parser->tree = tree;
@@ -1168,7 +1181,6 @@ make_treesit_parser (Lisp_Object buffer, TSParser *parser,
lisp_parser->visible_end = BUF_ZV_BYTE (XBUFFER (buffer));
lisp_parser->timestamp = 0;
lisp_parser->deleted = false;
- lisp_parser->has_range = false;
eassert (lisp_parser->visible_beg <= lisp_parser->visible_end);
return make_lisp_ptr (lisp_parser, Lisp_Vectorlike);
}
@@ -1375,24 +1387,29 @@ DEFUN ("treesit-node-parser",
DEFUN ("treesit-parser-create",
Ftreesit_parser_create, Streesit_parser_create,
- 1, 3, 0,
- doc: /* Create and return a parser in BUFFER for LANGUAGE.
+ 1, 4, 0,
+ doc: /* Create and return a parser in BUFFER for LANGUAGE with TAG.
The parser is automatically added to BUFFER's parser list, as returned
by `treesit-parser-list'. LANGUAGE is a language symbol. If BUFFER
is nil or omitted, it defaults to the current buffer. If BUFFER
-already has a parser for LANGUAGE, return that parser, but if NO-REUSE
-is non-nil, always create a new parser.
+already has a parser for LANGUAGE with TAG, return that parser, but if
+NO-REUSE is non-nil, always create a new parser.
+
+TAG can be any symbol except t, and defaults to nil. Different
+parsers can have the same tag.
If that buffer is an indirect buffer, its base buffer is used instead.
That is, indirect buffers use their base buffer's parsers. Lisp
programs should widen as necessary should they want to use a parser in
an indirect buffer. */)
- (Lisp_Object language, Lisp_Object buffer, Lisp_Object no_reuse)
+ (Lisp_Object language, Lisp_Object buffer, Lisp_Object no_reuse,
+ Lisp_Object tag)
{
treesit_initialize ();
CHECK_SYMBOL (language);
+ CHECK_SYMBOL (tag);
struct buffer *buf;
if (NILP (buffer))
buf = current_buffer;
@@ -1404,6 +1421,9 @@ an indirect buffer. */)
if (buf->base_buffer)
buf = buf->base_buffer;
+ if (EQ (tag, Qt))
+ xsignal2(Qwrong_type_argument, list2(Qnot, Qt), Qt);
+
treesit_check_buffer_size (buf);
/* See if we can reuse a parser. */
@@ -1413,7 +1433,8 @@ an indirect buffer. */)
FOR_EACH_TAIL (tail)
{
struct Lisp_TS_Parser *parser = XTS_PARSER (XCAR (tail));
- if (EQ (parser->language_symbol, language))
+ if (EQ (parser->tag, tag)
+ && EQ (parser->language_symbol, language))
return XCAR (tail);
}
}
@@ -1433,7 +1454,7 @@ an indirect buffer. */)
/* Create parser. */
Lisp_Object lisp_parser = make_treesit_parser (Fcurrent_buffer (),
parser, NULL,
- language);
+ language, tag);
/* Update parser-list. */
BVAR (buf, ts_parser_list) = Fcons (lisp_parser, BVAR (buf, ts_parser_list));
@@ -1462,13 +1483,19 @@ See `treesit-parser-list' for the buffer's parser list. */)
DEFUN ("treesit-parser-list",
Ftreesit_parser_list, Streesit_parser_list,
- 0, 1, 0,
- doc: /* Return BUFFER's parser list.
+ 0, 3, 0,
+ doc: /* Return BUFFER's parser list, filtered by LANGUAGE and TAG.
BUFFER defaults to the current buffer. If that buffer is an indirect
buffer, its base buffer is used instead. That is, indirect buffers
-use their base buffer's parsers. */)
- (Lisp_Object buffer)
+use their base buffer's parsers.
+
+If LANGUAGE is non-nil, only return parsers for that language.
+
+The returned list only contain parsers with TAG. TAG defaults to nil.
+If TAG is t, include parsers in the returned list regardless of their
+tag. */)
+ (Lisp_Object buffer, Lisp_Object language, Lisp_Object tag)
{
struct buffer *buf;
if (NILP (buffer))
@@ -1489,7 +1516,12 @@ use their base buffer's parsers. */)
tail = BVAR (buf, ts_parser_list);
FOR_EACH_TAIL (tail)
- return_list = Fcons (XCAR (tail), return_list);
+ {
+ struct Lisp_TS_Parser *parser = XTS_PARSER (XCAR (tail));
+ if ((NILP (language) || EQ (language, parser->language_symbol))
+ && (EQ (tag, Qt) || EQ (tag, parser->tag)))
+ return_list = Fcons (XCAR (tail), return_list);
+ }
return Freverse (return_list);
}
@@ -1517,6 +1549,16 @@ This symbol is the one used to create the parser. */)
return XTS_PARSER (parser)->language_symbol;
}
+DEFUN ("treesit-parser-tag",
+ Ftreesit_parser_tag, Streesit_parser_tag,
+ 1, 1, 0,
+ doc: /* Return PARSER's tag. */)
+ (Lisp_Object parser)
+{
+ treesit_check_parser (parser);
+ return XTS_PARSER (parser)->tag;
+}
+
/* Return true if PARSER is not deleted and its buffer is live. */
static bool
treesit_parser_live_p (Lisp_Object parser)
@@ -1620,6 +1662,10 @@ buffer. */)
treesit_check_parser (parser);
if (!NILP (ranges))
CHECK_CONS (ranges);
+
+ if (!NILP (Fequal (XTS_PARSER (parser)->last_set_ranges, ranges)))
+ return Qnil;
+
treesit_check_range_argument (ranges);
treesit_initialize ();
@@ -1627,10 +1673,10 @@ buffer. */)
treesit_check_buffer_size (XBUFFER (XTS_PARSER (parser)->buffer));
treesit_sync_visible_region (parser);
+ XTS_PARSER (parser)->last_set_ranges = ranges;
bool success;
if (NILP (ranges))
{
- XTS_PARSER (parser)->has_range = false;
/* If RANGES is nil, make parser to parse the whole document.
To do that we give tree-sitter a 0 length, the range is a
dummy. */
@@ -1641,8 +1687,6 @@ buffer. */)
else
{
/* Set ranges for PARSER. */
- XTS_PARSER (parser)->has_range = true;
-
if (list_length (ranges) > UINT32_MAX)
xsignal (Qargs_out_of_range, list2 (ranges, Flength (ranges)));
uint32_t len = (uint32_t) list_length (ranges);
@@ -1681,6 +1725,7 @@ buffer. */)
ranges);
XTS_PARSER (parser)->need_reparse = true;
+ XTS_PARSER (parser)->timestamp++;
return Qnil;
}
@@ -1698,10 +1743,10 @@ See also `treesit-parser-set-included-ranges'. */)
/* When the parser doesn't have a range set and we call
ts_parser_included_ranges on it, it doesn't return an empty list,
- but rather return some garbled data. (A single range where
- start_byte = 0, end_byte = UINT32_MAX). So we need to track
- whether the parser is ranged ourselves. */
- if (!XTS_PARSER (parser)->has_range)
+ but rather return DEFAULT_RANGE. (A single range where start_byte
+ = 0, end_byte = UINT32_MAX). So we need to track whether the
+ parser is ranged ourselves. */
+ if (NILP (XTS_PARSER (parser)->last_set_ranges))
return Qnil;
uint32_t len;
@@ -2170,7 +2215,10 @@ return nil. */)
static bool treesit_cursor_first_child_for_byte
(TSTreeCursor *cursor, ptrdiff_t pos, bool named)
{
- if (!ts_tree_cursor_goto_first_child (cursor))
+ /* ts_tree_cursor_goto_first_child_for_byte is significantly faster,
+ so despite it having problems, we try it first. */
+ if (ts_tree_cursor_goto_first_child_for_byte (cursor, pos) == -1
+ && !ts_tree_cursor_goto_first_child (cursor))
return false;
TSNode node = ts_tree_cursor_current_node (cursor);
@@ -2771,7 +2819,7 @@ static Lisp_Object treesit_resolve_node (Lisp_Object obj)
else if (SYMBOLP (obj))
{
Lisp_Object parser
- = Ftreesit_parser_create (obj, Fcurrent_buffer (), Qnil);
+ = Ftreesit_parser_create (obj, Fcurrent_buffer (), Qnil, Qnil);
return Ftreesit_parser_root_node (parser);
}
else
@@ -3027,7 +3075,8 @@ treesit_assume_true (bool val)
limit. */
static bool
treesit_cursor_helper_1 (TSTreeCursor *cursor, TSNode *target,
- uint32_t end_pos, ptrdiff_t limit)
+ uint32_t start_pos, uint32_t end_pos,
+ ptrdiff_t limit)
{
if (limit <= 0)
return false;
@@ -3036,23 +3085,21 @@ treesit_cursor_helper_1 (TSTreeCursor *cursor, TSNode *target,
if (ts_node_eq (cursor_node, *target))
return true;
- if (!ts_tree_cursor_goto_first_child (cursor))
+ /* ts_tree_cursor_goto_first_child_for_byte is significantly faster,
+ so despite it having problems (see bug#60127), we try it
+ first. */
+ if (ts_tree_cursor_goto_first_child_for_byte (cursor, start_pos) == -1
+ && !ts_tree_cursor_goto_first_child (cursor))
return false;
- /* Skip nodes that definitely don't contain TARGET. */
- while (ts_node_end_byte (cursor_node) < end_pos)
- {
- if (!ts_tree_cursor_goto_next_sibling (cursor))
- break;
- cursor_node = ts_tree_cursor_current_node (cursor);
- }
-
/* Go through each sibling that could contain TARGET. Because of
missing nodes (their width is 0), there could be multiple
siblings that could contain TARGET. */
while (ts_node_start_byte (cursor_node) <= end_pos)
{
- if (treesit_cursor_helper_1 (cursor, target, end_pos, limit - 1))
+ if (ts_node_end_byte (cursor_node) >= end_pos
+ && treesit_cursor_helper_1 (cursor, target, start_pos, end_pos,
+ limit - 1))
return true;
if (!ts_tree_cursor_goto_next_sibling (cursor))
@@ -3084,11 +3131,12 @@ treesit_cursor_helper_1 (TSTreeCursor *cursor, TSNode *target,
static bool
treesit_cursor_helper (TSTreeCursor *cursor, TSNode node, Lisp_Object parser)
{
+ uint32_t start_pos = ts_node_start_byte (node);
uint32_t end_pos = ts_node_end_byte (node);
TSNode root = ts_tree_root_node (XTS_PARSER (parser)->tree);
*cursor = ts_tree_cursor_new (root);
- bool success = treesit_cursor_helper_1 (cursor, &node, end_pos,
- TREESIT_RECURSION_LIMIT);
+ bool success = treesit_cursor_helper_1 (cursor, &node, start_pos,
+ end_pos, TREESIT_RECURSION_LIMIT);
if (!success)
ts_tree_cursor_delete (cursor);
return success;
@@ -3206,9 +3254,9 @@ treesit_traverse_child_helper (TSTreeCursor *cursor,
/* First go to the last child. */
while (ts_tree_cursor_goto_next_sibling (cursor));
- if (!named)
+ if (!named || (named && ts_node_is_named (ts_tree_cursor_current_node(cursor))))
return true;
- /* Else named... */
+ /* Else named is required and last child is not named node. */
if (treesit_traverse_sibling_helper(cursor, false, true))
return true;
else
@@ -3220,7 +3268,7 @@ treesit_traverse_child_helper (TSTreeCursor *cursor,
}
/* Given a symbol THING, and a language symbol LANGUAGE, find the
- corresponding predicate definition in treesit-things-settings.
+ corresponding predicate definition in treesit-thing-settings.
Don't check for the type of THING and LANGUAGE.
If there isn't one, return Qnil. */
@@ -3242,12 +3290,13 @@ treesit_traverse_get_predicate (Lisp_Object thing, Lisp_Object language)
}
/* Validate the PRED passed to treesit_traverse_match_predicate. If
- there's an error, set SIGNAL_DATA to something signal accepts, and
- return false, otherwise return true. This function also check for
- recusion levels: we place a arbitrary 100 level limit on recursive
+ there's an error, set SIGNAL_DATA to (ERR . DATA), where ERR is an
+ error symbol, and DATA is something signal accepts, and return
+ false, otherwise return true. This function also check for
+ recursion levels: we place a arbitrary 100 level limit on recursive
predicates. RECURSION_LEVEL is the current recursion level (that
- starts at 0), if it goes over 99, return false and set
- SIGNAL_DATA. LANGUAGE is a LANGUAGE symbol. */
+ starts at 0), if it goes over 99, return false and set SIGNAL_DATA.
+ LANGUAGE is a LANGUAGE symbol. */
static bool
treesit_traverse_validate_predicate (Lisp_Object pred,
Lisp_Object language,
@@ -3256,7 +3305,8 @@ treesit_traverse_validate_predicate (Lisp_Object pred,
{
if (recursion_level > 99)
{
- *signal_data = list1 (build_string ("Predicate recursion level "
+ *signal_data = list2 (Qtreesit_invalid_predicate,
+ build_string ("Predicate recursion level "
"exceeded: it must not exceed "
"100 levels"));
return false;
@@ -3271,7 +3321,8 @@ treesit_traverse_validate_predicate (Lisp_Object pred,
language);
if (NILP (definition))
{
- *signal_data = list2 (build_string ("Cannot find the definition "
+ *signal_data = list3 (Qtreesit_predicate_not_found,
+ build_string ("Cannot find the definition "
"of the predicate in "
"`treesit-thing-settings'"),
pred);
@@ -3290,7 +3341,8 @@ treesit_traverse_validate_predicate (Lisp_Object pred,
{
if (!CONSP (cdr))
{
- *signal_data = list2 (build_string ("Invalide `not' "
+ *signal_data = list3 (Qtreesit_invalid_predicate,
+ build_string ("Invalid `not' "
"predicate"),
pred);
return false;
@@ -3298,7 +3350,8 @@ treesit_traverse_validate_predicate (Lisp_Object pred,
/* At this point CDR must be a cons. */
if (XFIXNUM (Flength (cdr)) != 1)
{
- *signal_data = list2 (build_string ("`not' can only "
+ *signal_data = list3 (Qtreesit_invalid_predicate,
+ build_string ("`not' can only "
"have one argument"),
pred);
return false;
@@ -3312,7 +3365,8 @@ treesit_traverse_validate_predicate (Lisp_Object pred,
{
if (!CONSP (cdr) || NILP (cdr))
{
- *signal_data = list2 (build_string ("`or' must have a list "
+ *signal_data = list3 (Qtreesit_invalid_predicate,
+ build_string ("`or' must have a list "
"of patterns as "
"arguments "),
pred);
@@ -3331,7 +3385,8 @@ treesit_traverse_validate_predicate (Lisp_Object pred,
else if (STRINGP (car) && FUNCTIONP (cdr))
return true;
}
- *signal_data = list2 (build_string ("Invalid predicate, see `treesit-thing-settings' for valid forms of predicate"),
+ *signal_data = list3 (Qtreesit_invalid_predicate,
+ build_string ("Invalid predicate, see `treesit-thing-settings' for valid forms of predicate"),
pred);
return false;
}
@@ -3512,8 +3567,13 @@ DEFUN ("treesit-search-subtree",
doc: /* Traverse the parse tree of NODE depth-first using PREDICATE.
Traverse the subtree of NODE, and match PREDICATE with each node along
-the way. PREDICATE is a regexp string that matches against each
-node's type, or a function that takes a node and returns nil/non-nil.
+the way.
+
+PREDICATE can be a regexp string that matches against each node's
+type, a predicate function, and more. See `treesit-thing-settings'
+for the possible predicates. PREDICATE can also be a thing defined in
+`treesit-thing-settings'. Using an undefined thing doesn't raise an
+error.
By default, only traverse named nodes, but if ALL is non-nil, traverse
all nodes. If BACKWARD is non-nil, traverse backwards. If DEPTH is
@@ -3545,7 +3605,13 @@ Return the first matched node, or nil if none matches. */)
Lisp_Object signal_data = Qnil;
if (!treesit_traverse_validate_predicate (predicate, language,
&signal_data, 0))
- xsignal1 (Qtreesit_invalid_predicate, signal_data);
+ {
+ Lisp_Object err_symbol = XCAR (signal_data);
+ Lisp_Object data = XCDR (signal_data);
+ if (EQ (err_symbol, Qtreesit_predicate_not_found))
+ return Qnil;
+ xsignal1 (err_symbol, data);
+ }
Lisp_Object return_value = Qnil;
TSTreeCursor cursor;
@@ -3571,9 +3637,13 @@ DEFUN ("treesit-search-forward",
doc: /* Search for node matching PREDICATE in the parse tree of START.
Start traversing the tree from node START, and match PREDICATE with
-each node (except START itself) along the way. PREDICATE is a regexp
-string that matches against each node's type, or a function that takes
-a node and returns non-nil if it matches.
+each node (except START itself) along the way.
+
+PREDICATE can be a regexp string that matches against each node's
+type, a predicate function, and more. See `treesit-thing-settings'
+for the possible predicates. PREDICATE can also be a thing defined in
+`treesit-thing-settings'. Using an undefined thing doesn't raise an
+error.
By default, only search for named nodes, but if ALL is non-nil, search
for all nodes. If BACKWARD is non-nil, search backwards.
@@ -3610,7 +3680,13 @@ always traverse leaf nodes first, then upwards. */)
Lisp_Object signal_data = Qnil;
if (!treesit_traverse_validate_predicate (predicate, language,
&signal_data, 0))
- xsignal1 (Qtreesit_invalid_predicate, signal_data);
+ {
+ Lisp_Object err_symbol = XCAR (signal_data);
+ Lisp_Object data = XCDR (signal_data);
+ if (EQ (err_symbol, Qtreesit_predicate_not_found))
+ return Qnil;
+ xsignal1 (err_symbol, data);
+ }
Lisp_Object return_value = Qnil;
TSTreeCursor cursor;
@@ -3683,9 +3759,14 @@ DEFUN ("treesit-induce-sparse-tree",
Streesit_induce_sparse_tree, 2, 4, 0,
doc: /* Create a sparse tree of ROOT's subtree.
-This takes the subtree under ROOT, and combs it so only the nodes
-that match PREDICATE are left, like picking out grapes on the vine.
-PREDICATE is a regexp string that matches against each node's type.
+This takes the subtree under ROOT, and combs it so only the nodes that
+match PREDICATE are left, like picking out grapes on the vine.
+
+PREDICATE can be a regexp string that matches against each node's
+type, a predicate function, and more. See `treesit-thing-settings'
+for the possible predicates. PREDICATE can also be a thing defined in
+`treesit-thing-settings'. Using an undefined thing doesn't raise an
+error.
For a subtree on the left that consist of both numbers and letters, if
PREDICATE is "is letter", the returned tree is the one on the right.
@@ -3712,11 +3793,7 @@ ROOT. If DEPTH is nil or omitted, it defaults to 1000.
Each node in the returned tree looks like (NODE . (CHILD ...)). The
root of this tree might be nil, if ROOT doesn't match PREDICATE.
-If no node matches PREDICATE, return nil.
-
-PREDICATE can also be a function that takes a node and returns
-nil/non-nil, but it is slower and more memory consuming than using
-a regexp. */)
+If no node matches PREDICATE, return nil. */)
(Lisp_Object root, Lisp_Object predicate, Lisp_Object process_fn,
Lisp_Object depth)
{
@@ -3742,7 +3819,13 @@ a regexp. */)
Lisp_Object signal_data = Qnil;
if (!treesit_traverse_validate_predicate (predicate, language,
&signal_data, 0))
- xsignal1 (Qtreesit_invalid_predicate, signal_data);
+ {
+ Lisp_Object err_symbol = XCAR (signal_data);
+ Lisp_Object data = XCDR (signal_data);
+ if (EQ (err_symbol, Qtreesit_predicate_not_found))
+ return Qnil;
+ xsignal1 (err_symbol, data);
+ }
Lisp_Object parent = Fcons (Qnil, Qnil);
/* In this function we never traverse above NODE, so we don't need
@@ -3767,13 +3850,20 @@ a regexp. */)
DEFUN ("treesit-node-match-p",
Ftreesit_node_match_p,
- Streesit_node_match_p, 2, 2, 0,
+ Streesit_node_match_p, 2, 3, 0,
doc: /* Check whether NODE matches PREDICATE.
-PREDICATE can be a regexp matching node type, a predicate function,
-and more, see `treesit-thing-settings' for detail. Return non-nil
-if NODE matches PRED, nil otherwise. */)
- (Lisp_Object node, Lisp_Object predicate)
+PREDICATE can be a symbol representing a thing in
+`treesit-thing-settings', or a predicate, like regexp matching node
+type, etc. See `treesit-thing-settings' for more details.
+
+Return non-nil if NODE matches PREDICATE, nil otherwise.
+
+Signals `treesit-invalid-predicate' if there's no definition of THING
+in `treesit-thing-settings', or if PREDICATE is malformed. If
+IGNORE-MISSING is non-nil, don't signal an error for missing THING
+definition, but still signal for malformed PREDICATE. */)
+ (Lisp_Object node, Lisp_Object predicate, Lisp_Object ignore_missing)
{
CHECK_TS_NODE (node);
@@ -3783,7 +3873,16 @@ if NODE matches PRED, nil otherwise. */)
Lisp_Object signal_data = Qnil;
if (!treesit_traverse_validate_predicate (predicate, language,
&signal_data, 0))
- xsignal1 (Qtreesit_invalid_predicate, signal_data);
+ {
+ Lisp_Object err_symbol = XCAR (signal_data);
+ Lisp_Object data = XCDR (signal_data);
+
+ if (!NILP (ignore_missing)
+ && EQ (err_symbol, Qtreesit_predicate_not_found))
+ return Qnil;
+
+ xsignal1 (err_symbol, data);
+ }
TSTreeCursor cursor = ts_tree_cursor_new (XTS_NODE (node)->node);
@@ -3922,6 +4021,7 @@ syms_of_treesit (void)
DEFSYM (Qtreesit_parser_deleted, "treesit-parser-deleted");
DEFSYM (Qtreesit_pattern_expand, "treesit-pattern-expand");
DEFSYM (Qtreesit_invalid_predicate, "treesit-invalid-predicate");
+ DEFSYM (Qtreesit_predicate_not_found, "treesit-predicate-not-found");
DEFSYM (Qor, "or");
@@ -3994,20 +4094,20 @@ LANGUAGE is a language symbol, and DEFINITIONS is a list of
(THING PRED)
THING is a symbol representing the thing, like `defun', `sexp', or
-`block'; PRED defines what kind of node can be qualified as THING.
+`sentence'; PRED defines what kind of node can be qualified as THING.
PRED can be a regexp string that matches the type of the node; it can
be a predicate function that takes the node as the sole argument and
-returns t if the node is the thing; it can be a cons (REGEXP . FN),
-which is a combination of a regexp and a predicate function, and the
-node has to match both to qualify as the thing.
+returns t if the node is the thing, and nil otherwise; it can be a
+cons (REGEXP . FN), which is a combination of a regexp and a predicate
+function, and the node has to match both to qualify as the thing.
PRED can also be recursively defined. It can be (or PRED...), meaning
satisfying anyone of the inner PREDs qualifies the node; or (not
PRED), meaning not satisfying the inner PRED qualifies the node.
Finally, PRED can refer to other THINGs defined in this list by using
-the symbol of that THING. For example, (or block sexp). */);
+the symbol of that THING. For example, (or sexp sentence). */);
Vtreesit_thing_settings = Qnil;
staticpro (&Vtreesit_str_libtree_sitter);
@@ -4066,6 +4166,7 @@ the symbol of that THING. For example, (or block sexp). */);
defsubr (&Streesit_parser_list);
defsubr (&Streesit_parser_buffer);
defsubr (&Streesit_parser_language);
+ defsubr (&Streesit_parser_tag);
defsubr (&Streesit_parser_root_node);
/* defsubr (&Streesit_parse_string); */
diff --git a/src/treesit.h b/src/treesit.h
index 5382bc58817..bb81bf0e2b3 100644
--- a/src/treesit.h
+++ b/src/treesit.h
@@ -1,6 +1,6 @@
/* Header file for the tree-sitter integration.
-Copyright (C) 2021-2023 Free Software Foundation, Inc.
+Copyright (C) 2021-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
@@ -34,13 +34,21 @@ INLINE_HEADER_BEGIN
struct Lisp_TS_Parser
{
union vectorlike_header header;
- /* A symbol representing the language this parser uses. See the
+ /* A symbol representing the language this parser uses. See the
manual for more explanation. */
Lisp_Object language_symbol;
/* A list of functions to call after re-parse. Every function is
called with the changed ranges and the parser. The changed
ranges is a list of (BEG . END). */
Lisp_Object after_change_functions;
+ /* A tag (symbol) for the parser. Different parsers can have the
+ same tag. A tag is primarily used to differentiate between
+ parsers for the same language. */
+ Lisp_Object tag;
+ /* The Lisp ranges last set. This is use to compare to the new
+ ranges the users wants to set, and avoid reparse if the new
+ ranges is the same as the last set one. */
+ Lisp_Object last_set_ranges;
/* The buffer associated with this parser. */
Lisp_Object buffer;
/* The pointer to the tree-sitter parser. Never NULL. */
@@ -53,7 +61,9 @@ struct Lisp_TS_Parser
/* Re-parsing an unchanged buffer is not free for tree-sitter, so we
only make it re-parse when need_reparse == true. That usually
means some change is made in the buffer. But others could set
- this field to true to force tree-sitter to re-parse. */
+ this field to true to force tree-sitter to re-parse. When you
+ set this to true, you should _always_ also increment
+ timestamp. */
bool need_reparse;
/* These two positions record the buffer byte position (1-based) of
the "visible region" that tree-sitter sees. Before re-parse, we
@@ -72,9 +82,6 @@ struct Lisp_TS_Parser
/* If this field is true, parser functions raises
treesit-parser-deleted signal. */
bool deleted;
- /* If this field is true, the parser has ranges set. See
- Ftreesit_parser_included_ranges for why we need this. */
- bool has_range;
};
/* A wrapper around a tree-sitter node. */
@@ -183,7 +190,7 @@ INLINE_HEADER_END
extern void treesit_record_change (ptrdiff_t, ptrdiff_t, ptrdiff_t);
extern Lisp_Object make_treesit_parser (Lisp_Object, TSParser *, TSTree *,
- Lisp_Object);
+ Lisp_Object, Lisp_Object);
extern Lisp_Object make_treesit_node (Lisp_Object, TSNode);
extern bool treesit_node_uptodate_p (Lisp_Object);
diff --git a/src/undo.c b/src/undo.c
index 75cfd6058d2..afab89067ec 100644
--- a/src/undo.c
+++ b/src/undo.c
@@ -1,5 +1,5 @@
/* undo handling for GNU Emacs.
- Copyright (C) 1990, 1993-1994, 2000-2023 Free Software Foundation,
+ Copyright (C) 1990, 1993-1994, 2000-2024 Free Software Foundation,
Inc.
This file is part of GNU Emacs.
diff --git a/src/unexaix.c b/src/unexaix.c
index e50452c519a..f9bc39cf927 100644
--- a/src/unexaix.c
+++ b/src/unexaix.c
@@ -1,5 +1,5 @@
/* Dump an executable file.
- Copyright (C) 1985-1988, 1999, 2001-2023 Free Software Foundation,
+ Copyright (C) 1985-1988, 1999, 2001-2024 Free Software Foundation,
Inc.
This file is part of GNU Emacs.
diff --git a/src/unexcoff.c b/src/unexcoff.c
index 05a4edfe89d..4a981da4a04 100644
--- a/src/unexcoff.c
+++ b/src/unexcoff.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1985-1988, 1992-1994, 2001-2023 Free Software
+/* Copyright (C) 1985-1988, 1992-1994, 2001-2024 Free Software
* Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/unexcw.c b/src/unexcw.c
index fe2f120a01f..5c91498cc6c 100644
--- a/src/unexcw.c
+++ b/src/unexcw.c
@@ -1,7 +1,7 @@
/* unexec() support for Cygwin;
complete rewrite of xemacs Cygwin unexec() code
- Copyright (C) 2004-2023 Free Software Foundation, Inc.
+ Copyright (C) 2004-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/unexelf.c b/src/unexelf.c
index 607ac0cd6a2..feb26ffaeaf 100644
--- a/src/unexelf.c
+++ b/src/unexelf.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1985-1988, 1990, 1992, 1999-2023 Free Software
+/* Copyright (C) 1985-1988, 1990, 1992, 1999-2024 Free Software
Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/unexmacosx.c b/src/unexmacosx.c
index 33c20358116..7b2326441b4 100644
--- a/src/unexmacosx.c
+++ b/src/unexmacosx.c
@@ -1,5 +1,5 @@
/* Dump Emacs in Mach-O format for use on macOS.
- Copyright (C) 2001-2023 Free Software Foundation, Inc.
+ Copyright (C) 2001-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/unexw32.c b/src/unexw32.c
index 92e02b29850..d8329be522d 100644
--- a/src/unexw32.c
+++ b/src/unexw32.c
@@ -1,5 +1,5 @@
/* unexec for GNU Emacs on Windows NT.
- Copyright (C) 1994, 2001-2023 Free Software Foundation, Inc.
+ Copyright (C) 1994, 2001-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/verbose.mk.in b/src/verbose.mk.in
index 97799cee813..e72c182f276 100644
--- a/src/verbose.mk.in
+++ b/src/verbose.mk.in
@@ -1,6 +1,6 @@
### verbose.mk --- Makefile fragment for GNU Emacs
-## Copyright (C) 2021-2023 Free Software Foundation, Inc.
+## Copyright (C) 2021-2024 Free Software Foundation, Inc.
## This file is part of GNU Emacs.
diff --git a/src/vm-limit.c b/src/vm-limit.c
index a118f36edc5..698a1d8a7eb 100644
--- a/src/vm-limit.c
+++ b/src/vm-limit.c
@@ -1,5 +1,5 @@
/* Functions for memory limit warnings.
- Copyright (C) 1990, 1992, 2001-2023 Free Software Foundation, Inc.
+ Copyright (C) 1990, 1992, 2001-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/w16select.c b/src/w16select.c
index dce37fc1396..c8b91bfa883 100644
--- a/src/w16select.c
+++ b/src/w16select.c
@@ -1,6 +1,6 @@
/* 16-bit Windows Selection processing for emacs on MS-Windows
-Copyright (C) 1996-1997, 2001-2023 Free Software Foundation, Inc.
+Copyright (C) 1996-1997, 2001-2024 Free Software Foundation, Inc.
Author: Dale P. Smith <dpsm@en.com>
diff --git a/src/w32.c b/src/w32.c
index c75beb630e5..f365616db2b 100644
--- a/src/w32.c
+++ b/src/w32.c
@@ -1,6 +1,6 @@
/* Utility and Unix shadow routines for GNU Emacs on the Microsoft Windows API.
-Copyright (C) 1994-1995, 2000-2023 Free Software Foundation, Inc.
+Copyright (C) 1994-1995, 2000-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
@@ -9387,7 +9387,7 @@ sys_write (int fd, const void * buffer, unsigned int count)
break them into smaller chunks. See the Comments section of
the MSDN documentation of WriteFile for details behind the
choice of the value of CHUNK below. See also the thread
- http://thread.gmane.org/gmane.comp.version-control.git/145294
+ http://thread.gmane.org/gmane.comp.version-control.git/145294 [dead link]
in the git mailing list. */
const unsigned char *p = buffer;
const bool is_pipe = (fd < MAXDESC
diff --git a/src/w32.h b/src/w32.h
index a3d0b75359a..cf470ae9901 100644
--- a/src/w32.h
+++ b/src/w32.h
@@ -2,7 +2,7 @@
#define EMACS_W32_H
/* Support routines for the NT version of Emacs.
- Copyright (C) 1994, 2001-2023 Free Software Foundation, Inc.
+ Copyright (C) 1994, 2001-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/w32common.h b/src/w32common.h
index 26b114441ef..9475481b64e 100644
--- a/src/w32common.h
+++ b/src/w32common.h
@@ -1,5 +1,5 @@
/* Common functions for Microsoft Windows builds of Emacs
- Copyright (C) 2012-2023 Free Software Foundation, Inc.
+ Copyright (C) 2012-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/w32console.c b/src/w32console.c
index bb7d2162403..c2b87928cc1 100644
--- a/src/w32console.c
+++ b/src/w32console.c
@@ -1,5 +1,5 @@
/* Terminal hooks for GNU Emacs on the Microsoft Windows API.
- Copyright (C) 1992, 1999, 2001-2023 Free Software Foundation, Inc.
+ Copyright (C) 1992, 1999, 2001-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/w32cygwinx.c b/src/w32cygwinx.c
index dd1c4044e8e..7fd670499d1 100644
--- a/src/w32cygwinx.c
+++ b/src/w32cygwinx.c
@@ -1,6 +1,6 @@
/* Common functions for the Microsoft Windows and Cygwin builds.
-Copyright (C) 2018-2023 Free Software Foundation, Inc.
+Copyright (C) 2018-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/w32fns.c b/src/w32fns.c
index 07b389df84a..f8de45da7c9 100644
--- a/src/w32fns.c
+++ b/src/w32fns.c
@@ -1,6 +1,6 @@
/* Graphical user interface functions for the Microsoft Windows API.
-Copyright (C) 1989, 1992-2023 Free Software Foundation, Inc.
+Copyright (C) 1989, 1992-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
@@ -1732,6 +1732,11 @@ w32_change_tab_bar_height (struct frame *f, int height)
leading to the tab bar height being incorrectly set upon the next
call to x_set_font. (bug#59285) */
int lines = height / unit;
+
+ /* Even so, HEIGHT might be less than unit if the tab bar face is
+ not so tall as the frame's font height; which if true lines will
+ be set to 0 and the tab bar will thus vanish. */
+
if (lines == 0 && height != 0)
lines = 1;
diff --git a/src/w32font.c b/src/w32font.c
index 0371b24e1d1..c4718053a34 100644
--- a/src/w32font.c
+++ b/src/w32font.c
@@ -1,5 +1,5 @@
/* Font backend for the Microsoft Windows API.
- Copyright (C) 2007-2023 Free Software Foundation, Inc.
+ Copyright (C) 2007-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
@@ -1072,7 +1072,7 @@ w32font_open_internal (struct frame *f, Lisp_Object font_entity,
name to be usable in x-list-fonts. Eventually we expect to change
x-list-fonts and other places that use fonts so that this can be
an fcname or similar. */
- font->props[FONT_NAME_INDEX] = Ffont_xlfd_name (font_object, Qnil);
+ font->props[FONT_NAME_INDEX] = Ffont_xlfd_name (font_object, Qnil, Qt);
return 1;
}
diff --git a/src/w32font.h b/src/w32font.h
index 3f1c86adff9..3f780c1d866 100644
--- a/src/w32font.h
+++ b/src/w32font.h
@@ -1,5 +1,5 @@
/* Shared GDI and Uniscribe Font backend declarations for the Windows API.
- Copyright (C) 2007-2023 Free Software Foundation, Inc.
+ Copyright (C) 2007-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/w32gui.h b/src/w32gui.h
index 55e2e90c634..739a790911e 100644
--- a/src/w32gui.h
+++ b/src/w32gui.h
@@ -1,5 +1,5 @@
/* Definitions and headers for communication on the Microsoft Windows API.
- Copyright (C) 1995, 2001-2023 Free Software Foundation, Inc.
+ Copyright (C) 1995, 2001-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/w32heap.c b/src/w32heap.c
index 628fc28e3c5..601686f5331 100644
--- a/src/w32heap.c
+++ b/src/w32heap.c
@@ -1,5 +1,5 @@
/* Heap management routines for GNU Emacs on the Microsoft Windows API.
- Copyright (C) 1994, 2001-2023 Free Software Foundation, Inc.
+ Copyright (C) 1994, 2001-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
@@ -123,7 +123,7 @@ typedef struct _RTL_HEAP_PARAMETERS {
# if defined _WIN64 || defined WIDE_EMACS_INT
# define DUMPED_HEAP_SIZE (28*1024*1024)
# else
-# define DUMPED_HEAP_SIZE (18*1024*1024)
+# define DUMPED_HEAP_SIZE (24*1024*1024)
# endif
#endif
diff --git a/src/w32heap.h b/src/w32heap.h
index 2f0ac61e6a0..24b02fabbfc 100644
--- a/src/w32heap.h
+++ b/src/w32heap.h
@@ -1,5 +1,5 @@
/* Heap management routines (including unexec) for GNU Emacs on Windows NT.
- Copyright (C) 1994, 2001-2023 Free Software Foundation, Inc.
+ Copyright (C) 1994, 2001-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/w32image.c b/src/w32image.c
index 32967bab9e8..9010338a267 100644
--- a/src/w32image.c
+++ b/src/w32image.c
@@ -1,6 +1,6 @@
/* Implementation of MS-Windows native image API via the GDI+ library.
-Copyright (C) 2020-2023 Free Software Foundation, Inc.
+Copyright (C) 2020-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/w32inevt.c b/src/w32inevt.c
index 29717954cfd..35d3420e39f 100644
--- a/src/w32inevt.c
+++ b/src/w32inevt.c
@@ -1,5 +1,5 @@
/* Input event support for Emacs on the Microsoft Windows API.
- Copyright (C) 1992-1993, 1995, 2001-2023 Free Software Foundation,
+ Copyright (C) 1992-1993, 1995, 2001-2024 Free Software Foundation,
Inc.
This file is part of GNU Emacs.
@@ -496,7 +496,7 @@ do_mouse_event (MOUSE_EVENT_RECORD *event,
if (!NILP (Vmouse_autoselect_window))
{
Lisp_Object mouse_window = window_from_coordinates (f, mx, my,
- 0, 0, 0);
+ 0, 0, 0, 0);
/* A window will be selected only when it is not
selected now, and the last mouse movement event was
not in it. A minibuffer window will be selected iff
diff --git a/src/w32inevt.h b/src/w32inevt.h
index 9310873c872..da8f0f7d06f 100644
--- a/src/w32inevt.h
+++ b/src/w32inevt.h
@@ -1,5 +1,5 @@
/* Input routines for GNU Emacs on the Microsoft Windows API.
- Copyright (C) 1995, 2001-2023 Free Software Foundation, Inc.
+ Copyright (C) 1995, 2001-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/w32menu.c b/src/w32menu.c
index 239355946fc..cea4f4892a4 100644
--- a/src/w32menu.c
+++ b/src/w32menu.c
@@ -1,5 +1,5 @@
/* Menu support for GNU Emacs on the Microsoft Windows API.
- Copyright (C) 1986, 1988, 1993-1994, 1996, 1998-1999, 2001-2023 Free
+ Copyright (C) 1986, 1988, 1993-1994, 1996, 1998-1999, 2001-2024 Free
Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/w32notify.c b/src/w32notify.c
index 541d2f0fcd4..9f8a62a1daa 100644
--- a/src/w32notify.c
+++ b/src/w32notify.c
@@ -1,6 +1,6 @@
/* Filesystem notifications support for GNU Emacs on the Microsoft Windows API.
-Copyright (C) 2012-2023 Free Software Foundation, Inc.
+Copyright (C) 2012-2024 Free Software Foundation, Inc.
Author: Eli Zaretskii <eliz@gnu.org>
diff --git a/src/w32proc.c b/src/w32proc.c
index edc4394b17f..55ead13647b 100644
--- a/src/w32proc.c
+++ b/src/w32proc.c
@@ -1,6 +1,6 @@
/* Process support for GNU Emacs on the Microsoft Windows API.
-Copyright (C) 1992, 1995, 1999-2023 Free Software Foundation, Inc.
+Copyright (C) 1992, 1995, 1999-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/w32reg.c b/src/w32reg.c
index 9c390d6cd41..16ade86b436 100644
--- a/src/w32reg.c
+++ b/src/w32reg.c
@@ -1,6 +1,6 @@
/* Emulate the X Resource Manager through the registry.
-Copyright (C) 1990, 1993-1994, 2001-2023 Free Software Foundation, Inc.
+Copyright (C) 1990, 1993-1994, 2001-2024 Free Software Foundation, Inc.
Author: Kevin Gallo
diff --git a/src/w32select.c b/src/w32select.c
index 193bc00c6e0..006bf408b47 100644
--- a/src/w32select.c
+++ b/src/w32select.c
@@ -1,6 +1,6 @@
/* Selection processing for Emacs on the Microsoft Windows API.
-Copyright (C) 1993-1994, 2001-2023 Free Software Foundation, Inc.
+Copyright (C) 1993-1994, 2001-2024 Free Software Foundation, Inc.
Author: Kevin Gallo
Benjamin Riefenstahl
diff --git a/src/w32select.h b/src/w32select.h
index e4ef82aff46..07b85401c0e 100644
--- a/src/w32select.h
+++ b/src/w32select.h
@@ -1,6 +1,6 @@
/* Selection processing for Emacs on the Microsoft W32 API.
-Copyright (C) 1993-1994, 2001-2023 Free Software Foundation, Inc.
+Copyright (C) 1993-1994, 2001-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/w32term.c b/src/w32term.c
index a5f17a18213..816584a13be 100644
--- a/src/w32term.c
+++ b/src/w32term.c
@@ -1,6 +1,6 @@
/* Implementation of GUI terminal on the Microsoft Windows API.
-Copyright (C) 1989, 1993-2023 Free Software Foundation, Inc.
+Copyright (C) 1989, 1993-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
@@ -3376,7 +3376,7 @@ w32_construct_mouse_wheel (struct input_event *result, W32Msg *msg,
if (w32_wheel_scroll_lines == UINT_MAX)
{
Lisp_Object window = window_from_coordinates (f, p.x, p.y, NULL,
- false, false);
+ false, false, false);
if (!WINDOWP (window))
{
result->kind = NO_EVENT;
@@ -5335,7 +5335,7 @@ w32_read_socket (struct terminal *terminal,
{
static Lisp_Object last_mouse_window;
Lisp_Object window = window_from_coordinates
- (f, LOWORD (msg.msg.lParam), HIWORD (msg.msg.lParam), 0, 0, 0);
+ (f, LOWORD (msg.msg.lParam), HIWORD (msg.msg.lParam), 0, 0, 0, 0);
/* Window will be selected only when it is not
selected now and last mouse movement event was
@@ -5407,7 +5407,7 @@ w32_read_socket (struct terminal *terminal,
int x = XFIXNAT (inev.x);
int y = XFIXNAT (inev.y);
- window = window_from_coordinates (f, x, y, 0, 1, 1);
+ window = window_from_coordinates (f, x, y, 0, 1, 1, 1);
if (EQ (window, f->tab_bar_window))
{
@@ -5435,7 +5435,7 @@ w32_read_socket (struct terminal *terminal,
int x = XFIXNAT (inev.x);
int y = XFIXNAT (inev.y);
- window = window_from_coordinates (f, x, y, 0, 1, 1);
+ window = window_from_coordinates (f, x, y, 0, 1, 1, 1);
if (EQ (window, f->tool_bar_window)
/* Make sure the tool bar was previously
diff --git a/src/w32term.h b/src/w32term.h
index 68237bfff1d..29ace0b2797 100644
--- a/src/w32term.h
+++ b/src/w32term.h
@@ -1,5 +1,5 @@
/* Definitions and headers for communication on the Microsoft Windows API.
- Copyright (C) 1995, 2001-2023 Free Software Foundation, Inc.
+ Copyright (C) 1995, 2001-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/w32uniscribe.c b/src/w32uniscribe.c
index 67df0c8aebd..a73c0de06f9 100644
--- a/src/w32uniscribe.c
+++ b/src/w32uniscribe.c
@@ -1,6 +1,6 @@
/* Font backend for the Microsoft W32 Uniscribe API.
Windows-specific parts of the HarfBuzz font backend.
- Copyright (C) 2008-2023 Free Software Foundation, Inc.
+ Copyright (C) 2008-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/w32xfns.c b/src/w32xfns.c
index 2df9577460f..fa7d5fbdb61 100644
--- a/src/w32xfns.c
+++ b/src/w32xfns.c
@@ -1,5 +1,5 @@
/* Functions taken directly from X sources for use with the Microsoft Windows API.
- Copyright (C) 1989, 1992-1995, 1999, 2001-2023 Free Software
+ Copyright (C) 1989, 1992-1995, 1999, 2001-2024 Free Software
Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/widget.c b/src/widget.c
index 26696a975e3..d22732ff93a 100644
--- a/src/widget.c
+++ b/src/widget.c
@@ -1,5 +1,5 @@
/* The emacs frame widget.
- Copyright (C) 1992-1993, 2000-2023 Free Software Foundation, Inc.
+ Copyright (C) 1992-1993, 2000-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/widget.h b/src/widget.h
index 317b14cc523..116e909a643 100644
--- a/src/widget.h
+++ b/src/widget.h
@@ -1,5 +1,5 @@
/* The emacs frame widget public header file.
- Copyright (C) 1993, 2001-2023 Free Software Foundation, Inc.
+ Copyright (C) 1993, 2001-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/widgetprv.h b/src/widgetprv.h
index e264d157edb..b9cd72a4bc2 100644
--- a/src/widgetprv.h
+++ b/src/widgetprv.h
@@ -1,5 +1,5 @@
/* The emacs frame widget private header file.
- Copyright (C) 1993, 2001-2023 Free Software Foundation, Inc.
+ Copyright (C) 1993, 2001-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/window.c b/src/window.c
index 968b982c135..90e47dd7278 100644
--- a/src/window.c
+++ b/src/window.c
@@ -1,6 +1,6 @@
/* Window creation, deletion and examination for GNU Emacs.
Does not include redisplay.
- Copyright (C) 1985-1987, 1993-1998, 2000-2023 Free Software
+ Copyright (C) 1985-1987, 1993-1998, 2000-2024 Free Software
Foundation, Inc.
This file is part of GNU Emacs.
@@ -526,7 +526,7 @@ select_window (Lisp_Object window, Lisp_Object norecord,
/* Do not select a tooltip window (Bug#47207). */
error ("Cannot select a tooltip window");
- /* We deinitely want to select WINDOW, not the mini-window. */
+ /* We definitely want to select WINDOW, not the mini-window. */
f->select_mini_window_flag = false;
/* Make the selected window's buffer current. */
@@ -1680,7 +1680,8 @@ check_window_containing (struct window *w, void *user_data)
Lisp_Object
window_from_coordinates (struct frame *f, int x, int y,
- enum window_part *part, bool tab_bar_p, bool tool_bar_p)
+ enum window_part *part, bool menu_bar_p,
+ bool tab_bar_p, bool tool_bar_p)
{
Lisp_Object window;
struct check_window_data cw;
@@ -1693,6 +1694,21 @@ window_from_coordinates (struct frame *f, int x, int y,
cw.window = &window, cw.x = x, cw.y = y; cw.part = part;
foreach_window (f, check_window_containing, &cw);
+#if defined (HAVE_WINDOW_SYSTEM) && ! defined (HAVE_EXT_MENU_BAR)
+ /* If not found above, see if it's in the menu bar window, if a menu
+ bar exists. */
+ if (NILP (window)
+ && menu_bar_p
+ && WINDOWP (f->menu_bar_window)
+ && WINDOW_TOTAL_LINES (XWINDOW (f->menu_bar_window)) > 0
+ && (coordinates_in_window (XWINDOW (f->menu_bar_window), x, y)
+ != ON_NOTHING))
+ {
+ *part = ON_TEXT;
+ window = f->menu_bar_window;
+ }
+#endif
+
#if defined (HAVE_WINDOW_SYSTEM)
/* If not found above, see if it's in the tab bar window, if a tab
bar exists. */
@@ -1746,7 +1762,7 @@ function returns nil. */)
+ FRAME_INTERNAL_BORDER_WIDTH (f)),
(FRAME_PIXEL_Y_FROM_CANON_Y (f, y)
+ FRAME_INTERNAL_BORDER_WIDTH (f)),
- 0, false, false);
+ 0, false, false, false);
}
ptrdiff_t
@@ -3813,7 +3829,7 @@ run_window_change_functions_1 (Lisp_Object symbol, Lisp_Object buffer,
frame. Make sure to record changes for each live frame
in window_change_record later. */
window_change_record_frames = true;
- safe_call1 (XCAR (funs), window_or_frame);
+ safe_calln (XCAR (funs), window_or_frame);
}
funs = XCDR (funs);
diff --git a/src/window.h b/src/window.h
index 413293420fd..31fcbbd5541 100644
--- a/src/window.h
+++ b/src/window.h
@@ -1,5 +1,5 @@
/* Window definitions for GNU Emacs.
- Copyright (C) 1985-1986, 1993, 1995, 1997-2023 Free Software
+ Copyright (C) 1985-1986, 1993, 1995, 1997-2024 Free Software
Foundation, Inc.
This file is part of GNU Emacs.
@@ -292,7 +292,7 @@ struct window
`last_point' is normally used during redisplay to indicate the
position of point as seem by the input method. However, it is
- not updated if consequtive conversions are processed at the
+ not updated if consecutive conversions are processed at the
same time.
This `ephemeral_last_point' field is either the last point as
@@ -1111,7 +1111,7 @@ extern Lisp_Object minibuf_selected_window;
extern Lisp_Object make_window (void);
extern Lisp_Object window_from_coordinates (struct frame *, int, int,
- enum window_part *, bool, bool);
+ enum window_part *, bool, bool, bool);
extern void resize_frame_windows (struct frame *, int, bool);
extern void restore_window_configuration (Lisp_Object);
extern void delete_all_child_windows (Lisp_Object);
diff --git a/src/xdisp.c b/src/xdisp.c
index 8970d5aaaf2..aeaf8b34652 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -1,6 +1,6 @@
/* Display generation from window structure and buffer text.
-Copyright (C) 1985-2023 Free Software Foundation, Inc.
+Copyright (C) 1985-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
@@ -2778,7 +2778,7 @@ remember_mouse_glyph (struct frame *f, int gx, int gy, NativeRectangle *rect)
goto virtual_glyph;
}
else if (!f->glyphs_initialized_p
- || (window = window_from_coordinates (f, gx, gy, &part, false, false),
+ || (window = window_from_coordinates (f, gx, gy, &part, false, false, false),
NILP (window)))
{
width = FRAME_SMALLEST_CHAR_WIDTH (f);
@@ -3031,10 +3031,10 @@ hscrolling_current_line_p (struct window *w)
Lisp form evaluation
***********************************************************************/
-/* Error handler for safe_eval and safe_call. */
+/* Error handler for dsafe_eval and dsafe_call. */
static Lisp_Object
-safe_eval_handler (Lisp_Object arg, ptrdiff_t nargs, Lisp_Object *args)
+dsafe_eval_handler (Lisp_Object arg, ptrdiff_t nargs, Lisp_Object *args)
{
add_to_log ("Error during redisplay: %S signaled %S",
Flist (nargs, args), arg);
@@ -3045,8 +3045,11 @@ safe_eval_handler (Lisp_Object arg, ptrdiff_t nargs, Lisp_Object *args)
following. Return the result, or nil if something went
wrong. Prevent redisplay during the evaluation. */
+/* FIXME: What's the guiding principle behind the choice
+ of which calls should set 'inhibit_quit' and which don't. */
static Lisp_Object
-safe__call (bool inhibit_quit, ptrdiff_t nargs, Lisp_Object func, va_list ap)
+dsafe__call (bool inhibit_quit, Lisp_Object (f) (ptrdiff_t, Lisp_Object *),
+ ptrdiff_t nargs, Lisp_Object *args)
{
Lisp_Object val;
@@ -3054,84 +3057,38 @@ safe__call (bool inhibit_quit, ptrdiff_t nargs, Lisp_Object func, va_list ap)
val = Qnil;
else
{
- ptrdiff_t i;
specpdl_ref count = SPECPDL_INDEX ();
- Lisp_Object *args;
- USE_SAFE_ALLOCA;
- SAFE_ALLOCA_LISP (args, nargs);
-
- args[0] = func;
- for (i = 1; i < nargs; i++)
- args[i] = va_arg (ap, Lisp_Object);
specbind (Qinhibit_redisplay, Qt);
if (inhibit_quit)
specbind (Qinhibit_quit, Qt);
/* Use Qt to ensure debugger does not run,
so there is no possibility of wanting to redisplay. */
- val = internal_condition_case_n (Ffuncall, nargs, args, Qt,
- safe_eval_handler);
- val = SAFE_FREE_UNBIND_TO (count, val);
+ val = internal_condition_case_n (f, nargs, args, Qt,
+ dsafe_eval_handler);
+ val = unbind_to (count, val);
}
return val;
}
-Lisp_Object
-safe_call (ptrdiff_t nargs, Lisp_Object func, ...)
-{
- Lisp_Object retval;
- va_list ap;
-
- va_start (ap, func);
- retval = safe__call (false, nargs, func, ap);
- va_end (ap);
- return retval;
-}
-
-/* Call function FN with one argument ARG.
- Return the result, or nil if something went wrong. */
-
-Lisp_Object
-safe_call1 (Lisp_Object fn, Lisp_Object arg)
-{
- return safe_call (2, fn, arg);
-}
+#define SAFE_CALLMANY(inhibit_quit, f, array) \
+ dsafe__call ((inhibit_quit), f, ARRAYELTS (array), array)
+#define dsafe_calln(inhibit_quit, ...) \
+ SAFE_CALLMANY ((inhibit_quit), Ffuncall, ((Lisp_Object []) {__VA_ARGS__}))
static Lisp_Object
-safe__call1 (bool inhibit_quit, Lisp_Object fn, ...)
+dsafe_call1 (Lisp_Object f, Lisp_Object arg)
{
- Lisp_Object retval;
- va_list ap;
-
- va_start (ap, fn);
- retval = safe__call (inhibit_quit, 2, fn, ap);
- va_end (ap);
- return retval;
-}
-
-Lisp_Object
-safe_eval (Lisp_Object sexpr)
-{
- return safe__call1 (false, Qeval, sexpr);
+ return dsafe_calln (false, f, arg);
}
static Lisp_Object
-safe__eval (bool inhibit_quit, Lisp_Object sexpr)
-{
- return safe__call1 (inhibit_quit, Qeval, sexpr);
-}
-
-/* Call function FN with two arguments ARG1 and ARG2.
- Return the result, or nil if something went wrong. */
-
-Lisp_Object
-safe_call2 (Lisp_Object fn, Lisp_Object arg1, Lisp_Object arg2)
+dsafe_eval (Lisp_Object sexpr)
{
- return safe_call (3, fn, arg1, arg2);
+ return dsafe_calln (true, Qeval, sexpr, Qt);
}
-
/***********************************************************************
Debugging
@@ -3766,18 +3723,25 @@ start_display (struct it *it, struct window *w, struct text_pos pos)
/* Don't reseat to previous visible line start if current start
position is in a string or image. */
- if (it->method == GET_FROM_BUFFER && it->line_wrap != TRUNCATE)
+ if (it->line_wrap != TRUNCATE)
{
- int first_y = it->current_y;
+ enum it_method method = it->method;
- /* If window start is not at a line start, skip forward to POS to
- get the correct continuation lines width. */
+ /* If window start is not at a line start, skip forward to POS
+ from the beginning of physical line to get the correct
+ continuation lines width. */
bool start_at_line_beg_p = (CHARPOS (pos) == BEGV
|| FETCH_BYTE (BYTEPOS (pos) - 1) == '\n');
if (!start_at_line_beg_p)
{
+ int first_y = it->current_y;
+ int continuation_width;
+ void *itdata = NULL;
+ struct it it2;
int new_x;
+ if (method != GET_FROM_BUFFER)
+ SAVE_IT (it2, *it, itdata);
reseat_at_previous_visible_line_start (it);
move_it_to (it, CHARPOS (pos), -1, -1, -1, MOVE_TO_POS);
@@ -3824,6 +3788,17 @@ start_display (struct it *it, struct window *w, struct text_pos pos)
else if (it->current.dpvec_index >= 0)
it->current.dpvec_index = 0;
+ continuation_width = it->continuation_lines_width;
+ /* If we started from a position in something other than a
+ buffer, restore the original iterator state, keeping only
+ the continuation_lines_width, since we could now be very
+ far from the original position. */
+ if (method != GET_FROM_BUFFER)
+ {
+ RESTORE_IT (it, &it2, itdata);
+ it->continuation_lines_width = continuation_width;
+ }
+
/* We're starting a new display line, not affected by the
height of the continued line, so clear the appropriate
fields in the iterator structure. */
@@ -4597,7 +4572,7 @@ handle_fontified_prop (struct it *it)
it->f->inhibit_clear_image_cache = true;
if (!CONSP (val) || EQ (XCAR (val), Qlambda))
- safe_call1 (val, pos);
+ dsafe_call1 (val, pos);
else
{
Lisp_Object fns, fn;
@@ -4621,11 +4596,11 @@ handle_fontified_prop (struct it *it)
{
fn = XCAR (fns);
if (!EQ (fn, Qt))
- safe_call1 (fn, pos);
+ dsafe_call1 (fn, pos);
}
}
else
- safe_call1 (fn, pos);
+ dsafe_call1 (fn, pos);
}
}
@@ -5837,7 +5812,7 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
/* Save and restore the bidi cache, since FORM could be crazy
enough to re-enter redisplay, e.g., by calling 'message'. */
itdata = bidi_shelve_cache ();
- form = safe_eval (form);
+ form = dsafe_eval (form);
bidi_unshelve_cache (itdata, false);
form = unbind_to (count, form);
}
@@ -5879,7 +5854,7 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
struct face *face = FACE_FROM_ID (it->f, it->face_id);
Lisp_Object height;
itdata = bidi_shelve_cache ();
- height = safe_call1 (it->font_height,
+ height = dsafe_call1 (it->font_height,
face->lface[LFACE_HEIGHT_INDEX]);
bidi_unshelve_cache (itdata, false);
if (NUMBERP (height))
@@ -5904,7 +5879,7 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
specbind (Qheight, face->lface[LFACE_HEIGHT_INDEX]);
itdata = bidi_shelve_cache ();
- value = safe_eval (it->font_height);
+ value = dsafe_eval (it->font_height);
bidi_unshelve_cache (itdata, false);
value = unbind_to (count, value);
@@ -11418,7 +11393,7 @@ window_text_pixel_size (Lisp_Object window, Lisp_Object from, Lisp_Object to,
/* Start at the beginning of the line containing FROM. Otherwise
IT.current_x will be incorrectly set to zero at some arbitrary
non-zero X coordinate. */
- reseat_at_previous_visible_line_start (&it);
+ move_it_by_lines (&it, 0);
it.current_x = it.hpos = 0;
if (IT_CHARPOS (it) != start)
{
@@ -11448,7 +11423,6 @@ window_text_pixel_size (Lisp_Object window, Lisp_Object from, Lisp_Object to,
else
move_it_in_display_line (&it, start, it1_x + 1,
MOVE_TO_POS | MOVE_TO_X);
- move_it_to (&it, start - 1, -1, -1, -1, MOVE_TO_POS);
start_x = it.current_x;
/* If we didn't change our buffer position, the pixel
width of what's here was not yet accounted for; do it
@@ -11496,6 +11470,8 @@ window_text_pixel_size (Lisp_Object window, Lisp_Object from, Lisp_Object to,
the width of the last buffer position manually. */
if (IT_CHARPOS (it) > end)
{
+ int end_y = it.current_y;
+
end--;
RESTORE_IT (&it, &it2, it2data);
x = move_it_to (&it, end, to_x, max_y, -1, move_op);
@@ -11508,14 +11484,29 @@ window_text_pixel_size (Lisp_Object window, Lisp_Object from, Lisp_Object to,
/* DTRT if ignore_line_at_end is t. */
if (!NILP (ignore_line_at_end))
- doff = (max (it.max_ascent, it.ascent)
- + max (it.max_descent, it.descent));
+ {
+ /* If END-1 is on the previous screen line, we need to
+ account for the vertical dimensions of previous line. */
+ if (it.current_y < end_y)
+ doff = (max (it.max_ascent, it.ascent)
+ + max (it.max_descent, it.descent));
+ }
else
{
it.max_ascent = max (it.max_ascent, it.ascent);
it.max_descent = max (it.max_descent, it.descent);
}
}
+ else if (IT_CHARPOS (it) > end
+ && it.line_wrap == TRUNCATE
+ && it.current_x - it.first_visible_x >= it.last_visible_x)
+ {
+ /* If the display property at END is at the beginning of the
+ line, and the previous line was truncated, we are at END,
+ but it.current_y is not yet updated to reflect that. */
+ it.current_y += max (it.max_ascent, it.ascent)
+ + max (it.max_descent, it.descent);
+ }
}
else
bidi_unshelve_cache (it2data, true);
@@ -11809,7 +11800,7 @@ vadd_to_log (char const *format, va_list ap)
eassert (nargs <= ARRAYELTS (args));
AUTO_STRING (args0, format);
args[0] = args0;
- for (ptrdiff_t i = 1; i <= nargs; i++)
+ for (ptrdiff_t i = 1; i < nargs; i++)
args[i] = va_arg (ap, Lisp_Object);
Lisp_Object msg = Qnil;
msg = Fformat_message (nargs, args);
@@ -12767,7 +12758,7 @@ resize_mini_window (struct window *w, bool exact_p)
displaying changes from under them. Such a resizing can happen,
for instance, when which-func prints a long message while
we are running fontification-functions. We're running these
- functions with safe_call which binds inhibit-redisplay to t. */
+ functions with dsafe_call which binds inhibit-redisplay to t. */
if (!NILP (Vinhibit_redisplay))
return false;
@@ -12786,7 +12777,7 @@ resize_mini_window (struct window *w, bool exact_p)
if (FRAME_MINIBUF_ONLY_P (f))
{
if (!NILP (resize_mini_frames))
- safe_call1 (Qwindow__resize_mini_frame, WINDOW_FRAME (w));
+ dsafe_call1 (Qwindow__resize_mini_frame, WINDOW_FRAME (w));
}
else
{
@@ -13033,7 +13024,7 @@ set_message (Lisp_Object string)
{
specpdl_ref count = SPECPDL_INDEX ();
specbind (Qinhibit_quit, Qt);
- message = safe_call1 (Vset_message_function, string);
+ message = dsafe_call1 (Vset_message_function, string);
unbind_to (count, Qnil);
if (STRINGP (message))
@@ -13112,7 +13103,7 @@ clear_message (bool current_p, bool last_displayed_p)
{
specpdl_ref count = SPECPDL_INDEX ();
specbind (Qinhibit_quit, Qt);
- preserve = safe_call (1, Vclear_message_function);
+ preserve = dsafe_calln (false, Vclear_message_function);
unbind_to (count, Qnil);
}
@@ -13723,7 +13714,7 @@ prepare_menu_bars (void)
windows = Fcons (this, windows);
}
}
- safe__call1 (true, Vpre_redisplay_function, windows);
+ dsafe_calln (true, Vpre_redisplay_function, windows);
}
/* Update all frame titles based on their buffer names, etc. We do
@@ -18066,7 +18057,8 @@ set_cursor_from_row (struct window *w, struct glyph_row *row,
else if (dpos == 0)
match_with_avoid_cursor = true;
}
- else if (STRINGP (glyph->object))
+ else if (STRINGP (glyph->object)
+ && !glyph->avoid_cursor_p)
{
Lisp_Object chprop;
ptrdiff_t glyph_pos = glyph->charpos;
@@ -18292,7 +18284,8 @@ set_cursor_from_row (struct window *w, struct glyph_row *row,
/* Any glyphs that come from the buffer are here because
of bidi reordering. Skip them, and only pay
attention to glyphs that came from some string. */
- if (STRINGP (glyph->object))
+ if (STRINGP (glyph->object)
+ && !glyph->avoid_cursor_p)
{
Lisp_Object str;
ptrdiff_t tem;
@@ -18555,11 +18548,8 @@ run_window_scroll_functions (Lisp_Object window, struct text_pos startp)
if (!NILP (Vwindow_scroll_functions))
{
- specpdl_ref count = SPECPDL_INDEX ();
- specbind (Qinhibit_quit, Qt);
safe_run_hooks_2
(Qwindow_scroll_functions, window, make_fixnum (CHARPOS (startp)));
- unbind_to (count, Qnil);
SET_TEXT_POS_FROM_MARKER (startp, w->start);
/* In case the hook functions switch buffers. */
set_buffer_internal (XBUFFER (w->contents));
@@ -18611,7 +18601,7 @@ cursor_row_fully_visible_p (struct window *w, bool force_p,
XSETWINDOW (window, w);
/* Implementation note: if the function we call here signals an
error, we will NOT scroll when the cursor is partially-visible. */
- Lisp_Object val = safe_call1 (mclfv_p, window);
+ Lisp_Object val = dsafe_call1 (mclfv_p, window);
if (NILP (val))
return true;
else if (just_test_user_preference_p)
@@ -19171,7 +19161,7 @@ try_cursor_movement (Lisp_Object window, struct text_pos startp,
&& !f->cursor_type_changed
&& NILP (Vshow_trailing_whitespace)
/* When display-line-numbers is in relative mode, moving point
- requires to redraw the entire window. */
+ requires redrawing the entire window. */
&& !EQ (Vdisplay_line_numbers, Qrelative)
&& !EQ (Vdisplay_line_numbers, Qvisual)
/* When the current line number should be displayed in a
@@ -20179,7 +20169,7 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
propagated its info to `w' anyway. */
w->redisplay = false;
XBUFFER (w->contents)->text->redisplay = false;
- safe__call1 (true, Vpre_redisplay_function, Fcons (window, Qnil));
+ dsafe_calln (true, Vpre_redisplay_function, Fcons (window, Qnil));
if (w->redisplay || XBUFFER (w->contents)->text->redisplay
|| ((EQ (Vdisplay_line_numbers, Qrelative)
@@ -27056,7 +27046,7 @@ display_mode_lines (struct window *w)
can reasonably tell whether a mouse click will select w. */
XSETWINDOW (window, w);
if (FUNCTIONP (default_help))
- wset_mode_line_help_echo (w, safe_call1 (default_help, window));
+ wset_mode_line_help_echo (w, dsafe_call1 (default_help, window));
else if (STRINGP (default_help))
wset_mode_line_help_echo (w, default_help);
else
@@ -27395,6 +27385,7 @@ display_mode_element (struct it *it, int depth, int field_width, int precision,
/* PROPS might cause set-text-properties to signal
an error, so we call it via internal_condition_case_n,
to avoid an infloop in redisplay due to the error. */
+ /* FIXME: Use 'SAFE_CALLMANY'? */
internal_condition_case_n (safe_set_text_properties,
4,
((Lisp_Object [])
@@ -27402,7 +27393,7 @@ display_mode_element (struct it *it, int depth, int field_width, int precision,
Flength (elt),
props,
elt}),
- Qt, safe_eval_handler);
+ Qt, dsafe_eval_handler);
/* Add this item to mode_line_proptrans_alist. */
mode_line_proptrans_alist
= Fcons (Fcons (elt, props),
@@ -27655,7 +27646,7 @@ display_mode_element (struct it *it, int depth, int field_width, int precision,
if (CONSP (XCDR (elt)))
{
Lisp_Object spec;
- spec = safe__eval (true, XCAR (XCDR (elt)));
+ spec = dsafe_eval (XCAR (XCDR (elt)));
/* The :eval form could delete the frame stored in the
iterator, which will cause a crash if we try to
access faces and other fields (e.g., FRAME_KBOARD)
@@ -28627,7 +28618,7 @@ decode_mode_spec (struct window *w, register int c, int field_width,
Lisp_Object val = Qnil;
if (STRINGP (curdir))
- val = safe_call1 (intern ("file-remote-p"), curdir);
+ val = dsafe_call1 (intern ("file-remote-p"), curdir);
val = unbind_to (count, val);
@@ -29639,9 +29630,9 @@ get_char_face_and_encoding (struct frame *f, int c, int face_id,
}
-/* Get face and two-byte form of character glyph GLYPH on frame F.
- The encoding of GLYPH->u.ch is returned in *CHAR2B. Value is
- a pointer to a realized face that is ready for display. */
+/* Get face glyph GLYPH on frame F, and if a character glyph, its
+ multi-byte character form in *CHAR2B. Value is a pointer to a
+ realized face that is ready for display. */
static struct face *
get_glyph_face_and_encoding (struct frame *f, struct glyph *glyph,
@@ -29650,25 +29641,28 @@ get_glyph_face_and_encoding (struct frame *f, struct glyph *glyph,
struct face *face;
unsigned code = 0;
- eassert (glyph->type == CHAR_GLYPH);
face = FACE_FROM_ID (f, glyph->face_id);
/* Make sure X resources of the face are allocated. */
prepare_face_for_display (f, face);
- if (face->font)
+ if (glyph->type == CHAR_GLYPH)
{
- if (CHAR_BYTE8_P (glyph->u.ch))
- code = CHAR_TO_BYTE8 (glyph->u.ch);
- else
- code = face->font->driver->encode_char (face->font, glyph->u.ch);
+ if (face->font)
+ {
+ if (CHAR_BYTE8_P (glyph->u.ch))
+ code = CHAR_TO_BYTE8 (glyph->u.ch);
+ else
+ code = face->font->driver->encode_char (face->font, glyph->u.ch);
- if (code == FONT_INVALID_CODE)
- code = 0;
+ if (code == FONT_INVALID_CODE)
+ code = 0;
+ }
+
+ /* Ensure that the code is only 2 bytes wide. */
+ *char2b = code & 0xFFFF;
}
- /* Ensure that the code is only 2 bytes wide. */
- *char2b = code & 0xFFFF;
return face;
}
@@ -30168,17 +30162,28 @@ normal_char_height (struct font *font, int c)
void
gui_get_glyph_overhangs (struct glyph *glyph, struct frame *f, int *left, int *right)
{
+ unsigned char2b;
+ struct face *face;
+
*left = *right = 0;
+ face = get_glyph_face_and_encoding (f, glyph, &char2b);
if (glyph->type == CHAR_GLYPH)
{
- unsigned char2b;
- struct face *face = get_glyph_face_and_encoding (f, glyph, &char2b);
if (face->font)
{
- struct font_metrics *pcm = get_per_char_metric (face->font, &char2b);
+ struct font_metrics *pcm
+ = get_per_char_metric (face->font, &char2b);
+
if (pcm)
{
+ /* Overstruck text is displayed twice, the second time
+ one pixel to the right. Increase the right-side
+ bearing to match. */
+
+ if (face->overstrike)
+ pcm->rbearing++;
+
if (pcm->rbearing > pcm->width)
*right = pcm->rbearing - pcm->width;
if (pcm->lbearing < 0)
@@ -30191,8 +30196,18 @@ gui_get_glyph_overhangs (struct glyph *glyph, struct frame *f, int *left, int *r
if (! glyph->u.cmp.automatic)
{
struct composition *cmp = composition_table[glyph->u.cmp.id];
+ int rbearing;
+
+ rbearing = cmp->rbearing;
+
+ /* Overstruck text is displayed twice, the second time one
+ pixel to the right. Increase the right-side bearing to
+ match. */
+
+ if (face->overstrike)
+ rbearing++;
- if (cmp->rbearing > cmp->pixel_width)
+ if (rbearing > cmp->pixel_width)
*right = cmp->rbearing - cmp->pixel_width;
if (cmp->lbearing < 0)
*left = - cmp->lbearing;
@@ -30204,6 +30219,14 @@ gui_get_glyph_overhangs (struct glyph *glyph, struct frame *f, int *left, int *r
composition_gstring_width (gstring, glyph->slice.cmp.from,
glyph->slice.cmp.to + 1, &metrics);
+
+ /* Overstruck text is displayed twice, the second time one
+ pixel to the right. Increase the right-side bearing to
+ match. */
+
+ if (face->overstrike)
+ metrics.rbearing++;
+
if (metrics.rbearing > metrics.width)
*right = metrics.rbearing - metrics.width;
if (metrics.lbearing < 0)
@@ -30917,6 +30940,26 @@ draw_glyphs (struct window *w, int x, struct glyph_row *row,
}
}
+#ifdef HAVE_RSVG
+ /* Update SVG image glyphs with mouse face features. FIXME: it
+ should be possible to have this behaviour with transparent
+ background PNG. */
+ if (hl == DRAW_MOUSE_FACE)
+ {
+ Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
+ for (s = head; s; s = s->next)
+ if (s->first_glyph->type == IMAGE_GLYPH)
+ if (s->img
+ && (EQ (image_spec_value (s->img->spec, QCtype, NULL), Qsvg)))
+ {
+ ptrdiff_t id;
+ id = lookup_image (f, s->img->spec, hlinfo->mouse_face_face_id);
+ s->img = IMAGE_FROM_ID (f, id);
+ prepare_image_for_display (f, s->img);
+ }
+ }
+#endif
+
/* Draw all strings. */
for (s = head; s; s = s->next)
FRAME_RIF (f)->draw_glyph_string (s);
@@ -31292,9 +31335,16 @@ produce_image_glyph (struct it *it)
take_vertical_position_into_account (it);
- /* Automatically crop wide image glyphs at right edge so we can
- draw the cursor on same display row. */
- if ((crop = it->pixel_width - (it->last_visible_x - it->current_x), crop > 0)
+ /* Automatically crop wide image glyphs at right edge so we can draw
+ the cursor on same display row. But don't do that under
+ word-wrap, unless the image starts at column zero, because
+ wrapping correctly needs the real pixel width of the image. */
+ if ((it->line_wrap != WORD_WRAP
+ || it->hpos == 0
+ /* Always crop images larger than the window-width, minus 1 space. */
+ || it->pixel_width > it->last_visible_x - FRAME_COLUMN_WIDTH (it->f))
+ && (crop = it->pixel_width - (it->last_visible_x - it->current_x),
+ crop > 0)
&& (it->hpos == 0 || it->pixel_width > it->last_visible_x / 4))
{
it->pixel_width -= crop;
@@ -32312,6 +32362,14 @@ gui_produce_glyphs (struct it *it)
if (get_char_glyph_code (it->char_to_display, font, &char2b))
{
pcm = get_per_char_metric (font, &char2b);
+
+ /* Overstruck text is displayed twice, the second time
+ one pixel to the right. Increase the right-side
+ bearing to match. */
+
+ if (pcm && face->overstrike)
+ pcm->rbearing++;
+
if (pcm->width == 0
&& pcm->rbearing == 0 && pcm->lbearing == 0)
pcm = NULL;
@@ -32704,6 +32762,13 @@ gui_produce_glyphs (struct it *it)
/* Initialize the bounding box. */
if (pcm)
{
+ /* Overstruck text is displayed twice, the second time
+ one pixel to the right. Increase the right-side
+ bearing to match. */
+
+ if (face->overstrike)
+ pcm->rbearing++;
+
width = cmp->glyph_len > 0 ? pcm->width : 0;
ascent = pcm->ascent;
descent = pcm->descent;
@@ -32765,6 +32830,13 @@ gui_produce_glyphs (struct it *it)
cmp->offsets[i * 2] = cmp->offsets[i * 2 + 1] = 0;
else
{
+ /* Overstruck text is displayed twice, the second
+ time one pixel to the right. Increase the
+ right-side bearing to match. */
+
+ if (face->overstrike)
+ pcm->rbearing++;
+
width = pcm->width;
ascent = pcm->ascent;
descent = pcm->descent;
@@ -33493,13 +33565,18 @@ notice_overwritten_cursor (struct window *w, enum glyph_row_area area,
void
gui_fix_overlapping_area (struct window *w, struct glyph_row *row,
- enum glyph_row_area area, int overlaps)
+ enum glyph_row_area area, int overlaps)
{
int i, x;
block_input ();
- x = 0;
+ /* row->x might be smaller than zero when produced from an iterator
+ under horizontal scrolling. Offset all measurements by this
+ basic value, lest hscrolled text with overlaps be displayed with
+ its overlapping portions misaligned. */
+ x = row->x;
+
for (i = 0; i < row->used[area];)
{
if (row->glyphs[area][i].overlaps_vertically_p)
@@ -35439,7 +35516,7 @@ note_mouse_highlight (struct frame *f, int x, int y)
return;
/* Which window is that in? */
- window = window_from_coordinates (f, x, y, &part, true, true);
+ window = window_from_coordinates (f, x, y, &part, true, true, true);
/* If displaying active text in another window, clear that. */
if (! EQ (window, hlinfo->mouse_face_window)
@@ -35538,6 +35615,16 @@ note_mouse_highlight (struct frame *f, int x, int y)
w = XWINDOW (window);
frame_to_window_pixel_xy (w, &x, &y);
+#if defined (HAVE_WINDOW_SYSTEM) && ! defined (HAVE_EXT_MENU_BAR)
+ /* Handle menu-bar window differently since it doesn't display a
+ buffer. */
+ if (EQ (window, f->menu_bar_window))
+ {
+ cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
+ goto set_cursor;
+ }
+#endif
+
#if defined (HAVE_WINDOW_SYSTEM)
/* Handle tab-bar window differently since it doesn't display a
buffer. */
@@ -35545,12 +35632,10 @@ note_mouse_highlight (struct frame *f, int x, int y)
{
note_tab_bar_highlight (f, x, y);
if (tab_bar__dragging_in_progress)
- {
cursor = FRAME_OUTPUT_DATA (f)->hand_cursor;
- goto set_cursor;
- }
else
- return;
+ cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
+ goto set_cursor;
}
else
{
@@ -35568,7 +35653,8 @@ note_mouse_highlight (struct frame *f, int x, int y)
if (EQ (window, f->tool_bar_window))
{
note_tool_bar_highlight (f, x, y);
- return;
+ cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
+ goto set_cursor;
}
#endif
@@ -37047,14 +37133,15 @@ See also `overlay-arrow-string'. */);
Voverlay_arrow_position = Qnil;
DEFVAR_LISP ("overlay-arrow-string", Voverlay_arrow_string,
- doc: /* String to display as an arrow in non-window frames.
+ doc: /* String to display as an arrow in text-mode frames.
See also `overlay-arrow-position'. */);
Voverlay_arrow_string = build_pure_c_string ("=>");
DEFVAR_LISP ("overlay-arrow-variable-list", Voverlay_arrow_variable_list,
doc: /* List of variables (symbols) which hold markers for overlay arrows.
The symbols on this list are examined during redisplay to determine
-where to display overlay arrows. */);
+where to display overlay arrows.
+See also `overlay-arrow-string'. */);
Voverlay_arrow_variable_list
= list1 (intern_c_string ("overlay-arrow-position"));
@@ -37814,13 +37901,13 @@ composed on display. */);
DEFVAR_INT ("max-redisplay-ticks", max_redisplay_ticks,
doc: /* Maximum number of redisplay ticks before aborting redisplay of a window.
-This allows to abort the display of a window if the amount of low-level
-redisplay operations exceeds the value of this variable. When display of
-a window is aborted due to this reason, the buffer shown in that window
-will not have its windows redisplayed until the buffer is modified or until
-you type \\[recenter-top-bottom] with one of its windows selected.
-You can also decide to kill the buffer and visit it in some
-other way, like under `so-long-mode' or literally.
+This enables aborting the display of a window if the amount of
+low-level redisplay operations exceeds the value of this variable.
+When display of a window is aborted due to this reason, the buffer
+shown in that window will not have its windows redisplayed until the
+buffer is modified or until you type \\[recenter-top-bottom] with one
+of its windows selected. You can also decide to kill the buffer and
+visit it in some other way, like under `so-long-mode' or literally.
The default value is zero, which disables this feature.
The recommended non-zero value is between 100000 and 1000000,
diff --git a/src/xfaces.c b/src/xfaces.c
index 30487c0e8fb..e30c2fac70c 100644
--- a/src/xfaces.c
+++ b/src/xfaces.c
@@ -1,6 +1,6 @@
/* xfaces.c -- "Face" primitives.
-Copyright (C) 1993-1994, 1998-2023 Free Software Foundation, Inc.
+Copyright (C) 1993-1994, 1998-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
@@ -1629,7 +1629,7 @@ the face font sort order, see `face-font-selection-order'. */)
make_fixnum
(FONT_SPACING_PROPORTIONAL)))
? Qnil : Qt,
- Ffont_xlfd_name (font, Qnil),
+ Ffont_xlfd_name (font, Qnil, Qt),
AREF (font, FONT_REGISTRY_INDEX));
result = Fcons (v, result);
}
@@ -1738,7 +1738,7 @@ the WIDTH times as wide as FACE on FRAME. */)
ASET (font_entity, FONT_SIZE_INDEX,
AREF (font_spec, FONT_SIZE_INDEX));
}
- XSETCAR (tail, Ffont_xlfd_name (font_entity, Qnil));
+ XSETCAR (tail, Ffont_xlfd_name (font_entity, Qnil, Qt));
}
if (NILP (frame))
/* We don't have to check fontsets. */
@@ -2232,7 +2232,7 @@ merge_face_heights (Lisp_Object from, Lisp_Object to, Lisp_Object invalid)
{
/* Call function with current height as argument.
From is the new height. */
- result = safe_call1 (from, to);
+ result = safe_calln (from, to);
/* Ensure that if TO was absolute, so is the result. */
if (FIXNUMP (to) && !FIXNUMP (result))
@@ -3371,12 +3371,13 @@ FRAME 0 means change the face on all frames, and change the default
if (!CONSP (tem))
break;
v = XCAR (tem);
- tem = XCDR (tem);
if (EQ (k, QCline_width))
{
- if ((!CONSP(v) || !FIXNUMP (XCAR (v)) || XFIXNUM (XCAR (v)) == 0
- || !FIXNUMP (XCDR (v)) || XFIXNUM (XCDR (v)) == 0)
+ if ((!CONSP(v)
+ || !FIXNUMP (XCAR (v))
+ || XFIXNUM (XCAR (v)) == 0
+ || !FIXNUMP (XCDR (v)) || XFIXNUM (XCDR (v)) == 0)
&& (!FIXNUMP (v) || XFIXNUM (v) == 0))
break;
}
@@ -3387,12 +3388,16 @@ FRAME 0 means change the face on all frames, and change the default
}
else if (EQ (k, QCstyle))
{
- if (!EQ (v, Qpressed_button) && !EQ (v, Qreleased_button)
- && !EQ(v, Qflat_button))
+ if (!NILP (v)
+ && !EQ (v, Qpressed_button)
+ && !EQ (v, Qreleased_button)
+ && !EQ (v, Qflat_button))
break;
}
else
break;
+
+ tem = XCDR (tem);
}
valid_p = NILP (tem);
@@ -4018,7 +4023,8 @@ x_update_menu_appearance (struct frame *f)
|| !UNSPECIFIEDP (LFACE_SLANT (lface))
|| !UNSPECIFIEDP (LFACE_HEIGHT (lface))))
{
- Lisp_Object xlfd = Ffont_xlfd_name (LFACE_FONT (lface), Qnil);
+ Lisp_Object xlfd = Ffont_xlfd_name (LFACE_FONT (lface), Qnil,
+ Qnil);
#ifdef USE_MOTIF
const char *suffix = "List";
bool motif = true;
diff --git a/src/xfns.c b/src/xfns.c
index aea2f4b880e..d610c839bfc 100644
--- a/src/xfns.c
+++ b/src/xfns.c
@@ -1,6 +1,6 @@
/* Functions for the X Window System.
-Copyright (C) 1989, 1992-2023 Free Software Foundation, Inc.
+Copyright (C) 1989, 1992-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
@@ -1792,6 +1792,11 @@ x_change_tab_bar_height (struct frame *f, int height)
leading to the tab bar height being incorrectly set upon the next
call to x_set_font. (bug#59285) */
int lines = height / unit;
+
+ /* Even so, HEIGHT might be less than unit if the tab bar face is
+ not so tall as the frame's font height; which if true lines will
+ be set to 0 and the tab bar will thus vanish. */
+
if (lines == 0 && height != 0)
lines = 1;
@@ -4021,6 +4026,7 @@ initial_set_up_x_back_buffer (struct frame *f)
}
#if defined HAVE_XINPUT2
+
static void
setup_xi_event_mask (struct frame *f)
{
@@ -4069,8 +4075,7 @@ setup_xi_event_mask (struct frame *f)
XISetMask (m, XI_GesturePinchEnd);
}
#endif /* HAVE_XINPUT2_4 */
- XISelectEvents (FRAME_X_DISPLAY (f),
- FRAME_X_WINDOW (f),
+ XISelectEvents (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
&mask, 1);
/* Fortunately `xi_masks' isn't used on GTK 3, where we really have
@@ -4085,11 +4090,8 @@ setup_xi_event_mask (struct frame *f)
#ifdef USE_X_TOOLKIT
XISetMask (m, XI_KeyPress);
XISetMask (m, XI_KeyRelease);
- XISetMask (m, XI_FocusIn);
- XISetMask (m, XI_FocusOut);
- XISelectEvents (FRAME_X_DISPLAY (f),
- FRAME_OUTER_WINDOW (f),
+ XISelectEvents (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
&mask, 1);
memset (m, 0, l);
#endif /* USE_X_TOOLKIT */
@@ -4135,6 +4137,7 @@ setup_xi_event_mask (struct frame *f)
unblock_input ();
}
+
#endif
#ifdef USE_X_TOOLKIT
diff --git a/src/xfont.c b/src/xfont.c
index ce32c7a2188..b112bb4fb39 100644
--- a/src/xfont.c
+++ b/src/xfont.c
@@ -1,5 +1,5 @@
/* xfont.c -- X core font driver.
- Copyright (C) 2006-2023 Free Software Foundation, Inc.
+ Copyright (C) 2006-2024 Free Software Foundation, Inc.
Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011
National Institute of Advanced Industrial Science and Technology (AIST)
Registration Number H13PRO009
@@ -238,7 +238,7 @@ xfont_chars_supported (Lisp_Object chars, XFontStruct *xfont,
static Lisp_Object xfont_scripts_cache;
-/* Re-usable vector to store characteristic font properties. */
+/* Reusable vector to store characteristic font properties. */
static Lisp_Object xfont_scratch_props;
/* Return a list of scripts supported by the font of FONTNAME whose
diff --git a/src/xftfont.c b/src/xftfont.c
index 4d5b855f178..41941509bc2 100644
--- a/src/xftfont.c
+++ b/src/xftfont.c
@@ -1,5 +1,5 @@
/* xftfont.c -- XFT font driver.
- Copyright (C) 2006-2023 Free Software Foundation, Inc.
+ Copyright (C) 2006-2024 Free Software Foundation, Inc.
Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011
National Institute of Advanced Industrial Science and Technology (AIST)
Registration Number H13PRO009
diff --git a/src/xgselect.c b/src/xgselect.c
index 7f4f2b04811..252f430b0ec 100644
--- a/src/xgselect.c
+++ b/src/xgselect.c
@@ -1,6 +1,6 @@
/* Function for handling the GLib event loop.
-Copyright (C) 2009-2023 Free Software Foundation, Inc.
+Copyright (C) 2009-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/xgselect.h b/src/xgselect.h
index cfc872558b7..87b3591f8cc 100644
--- a/src/xgselect.h
+++ b/src/xgselect.h
@@ -1,6 +1,6 @@
/* Header for xg_select.
-Copyright (C) 2009-2023 Free Software Foundation, Inc.
+Copyright (C) 2009-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/xmenu.c b/src/xmenu.c
index 2d405d54deb..ef1eeb5925f 100644
--- a/src/xmenu.c
+++ b/src/xmenu.c
@@ -1,6 +1,6 @@
/* X Communication module for terminals which understand the X protocol.
-Copyright (C) 1986, 1988, 1993-1994, 1996, 1999-2023 Free Software
+Copyright (C) 1986, 1988, 1993-1994, 1996, 1999-2024 Free Software
Foundation, Inc.
Author: Jon Arnold
diff --git a/src/xml.c b/src/xml.c
index b4c849e6a65..85f16746289 100644
--- a/src/xml.c
+++ b/src/xml.c
@@ -1,5 +1,5 @@
/* Interface to libxml2.
- Copyright (C) 2010-2023 Free Software Foundation, Inc.
+ Copyright (C) 2010-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/xrdb.c b/src/xrdb.c
index 046200f0d19..548b1ffca30 100644
--- a/src/xrdb.c
+++ b/src/xrdb.c
@@ -1,5 +1,5 @@
/* Deal with the X Resource Manager.
- Copyright (C) 1990, 1993-1994, 2000-2023 Free Software Foundation,
+ Copyright (C) 1990, 1993-1994, 2000-2024 Free Software Foundation,
Inc.
Author: Joseph Arceneaux
diff --git a/src/xselect.c b/src/xselect.c
index c38a1f8b6a9..bb82798bb62 100644
--- a/src/xselect.c
+++ b/src/xselect.c
@@ -1,5 +1,5 @@
/* X Selection processing for Emacs.
- Copyright (C) 1993-1997, 2000-2023 Free Software Foundation, Inc.
+ Copyright (C) 1993-1997, 2000-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
@@ -897,7 +897,7 @@ x_start_selection_transfer (struct x_display_info *dpyinfo, Window requestor,
/* Find a valid (non-zero) serial for the selection transfer.
Any asynchronously trapped errors will then cause the
- selection transfer to be cancelled. */
+ selection transfer to be canceled. */
transfer->serial = (++selection_serial
? selection_serial
: ++selection_serial);
diff --git a/src/xsettings.c b/src/xsettings.c
index f366c9d7fc5..764ccd04a09 100644
--- a/src/xsettings.c
+++ b/src/xsettings.c
@@ -1,6 +1,6 @@
/* Functions for handling font and other changes dynamically.
-Copyright (C) 2009-2023 Free Software Foundation, Inc.
+Copyright (C) 2009-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/xsettings.h b/src/xsettings.h
index f1c6f7af1f1..06fcbe183bc 100644
--- a/src/xsettings.h
+++ b/src/xsettings.h
@@ -1,6 +1,6 @@
/* Functions for handle font changes dynamically.
-Copyright (C) 2009-2023 Free Software Foundation, Inc.
+Copyright (C) 2009-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/xsmfns.c b/src/xsmfns.c
index 3cf5165242e..8827d08af3e 100644
--- a/src/xsmfns.c
+++ b/src/xsmfns.c
@@ -1,7 +1,7 @@
/* Session management module for systems which understand the X Session
management protocol.
-Copyright (C) 2002-2023 Free Software Foundation, Inc.
+Copyright (C) 2002-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/xterm.c b/src/xterm.c
index 6a1642ff56e..1f398b2e39a 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -1,6 +1,6 @@
/* X Communication module for terminals which understand the X protocol.
-Copyright (C) 1989, 1993-2023 Free Software Foundation, Inc.
+Copyright (C) 1989, 1993-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
@@ -616,9 +616,9 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
- x_clear_errors
Callers using this set should consult the comment(s) on top of the
- aformentioned functions. They should not be used when the requests
+ aforementioned functions. They should not be used when the requests
being made do not require roundtrips to the X server, and obtaining
- the details of any error generated is unecessary, as
+ the details of any error generated is unnecessary, as
`x_uncatch_errors' will always synchronize with the X server, which
is a potentially slow operation. */
@@ -1167,7 +1167,7 @@ static struct terminal *x_create_terminal (struct x_display_info *);
static void x_frame_rehighlight (struct x_display_info *);
static void x_clip_to_row (struct window *, struct glyph_row *,
- enum glyph_row_area, GC);
+ enum glyph_row_area, GC, XRectangle *);
static struct scroll_bar *x_window_to_scroll_bar (Display *, Window, int);
static struct frame *x_window_to_frame (struct x_display_info *, int);
static void x_scroll_bar_report_motion (struct frame **, Lisp_Object *,
@@ -5036,7 +5036,7 @@ x_dnd_note_self_drop (struct x_display_info *dpyinfo, Window target,
XSETFRAME (lval, f);
x_dnd_action = None;
x_dnd_action_symbol
- = safe_call2 (Vx_dnd_native_test_function,
+ = safe_calln (Vx_dnd_native_test_function,
Fposn_at_x_y (make_fixnum (win_x),
make_fixnum (win_y),
lval, Qnil),
@@ -5173,7 +5173,7 @@ record_event (char *locus, int type)
-/* Miscelaneous event handling functions. */
+/* Miscellaneous event handling functions. */
static void
x_toolkit_position (struct frame *f, int x, int y,
@@ -7842,9 +7842,10 @@ x_draw_fringe_bitmap (struct window *w, struct glyph_row *row,
Display *display = FRAME_X_DISPLAY (f);
GC gc = f->output_data.x->normal_gc;
struct face *face = p->face;
+ XRectangle clip_rect;
/* Must clip because of partially visible lines. */
- x_clip_to_row (w, row, ANY_AREA, gc);
+ x_clip_to_row (w, row, ANY_AREA, gc, &clip_rect);
if (p->bx >= 0 && !p->overlay_p)
{
@@ -7914,6 +7915,29 @@ x_draw_fringe_bitmap (struct window *w, struct glyph_row *row,
memset (&attrs, 0, sizeof attrs);
#endif
+ XRectangle image_rect, dest;
+ int px, py, pwidth, pheight;
+
+ /* Intersect the destination rectangle with that of the row.
+ Setting a clip mask overrides the clip rectangles provided by
+ x_clip_to_row, so clipping must be performed by hand. */
+
+ image_rect.x = p->x;
+ image_rect.y = p->y;
+ image_rect.width = p->wd;
+ image_rect.height = p->h;
+
+ if (!gui_intersect_rectangles (&clip_rect, &image_rect, &dest))
+ /* The entire destination rectangle falls outside the row. */
+ goto undo_clip;
+
+ /* Extrapolate the source rectangle from the difference between
+ the destination and image rectangles. */
+
+ px = dest.x - image_rect.x;
+ py = dest.y - image_rect.y;
+ pwidth = dest.width;
+ pheight = dest.height;
if (p->wd > 8)
bits = (char *) (p->bits + p->dh);
@@ -7985,15 +8009,16 @@ x_draw_fringe_bitmap (struct window *w, struct glyph_row *row,
x_xr_apply_ext_clip (f, gc);
XRenderComposite (display, PictOpSrc, picture,
None, FRAME_X_PICTURE (f),
- 0, 0, 0, 0, p->x, p->y, p->wd, p->h);
+ px, py, px, py, dest.x, dest.y,
+ pwidth, pheight);
x_xr_reset_ext_clip (f);
XRenderFreePicture (display, picture);
}
else
#endif
- XCopyArea (display, pixmap, drawable, gc, 0, 0,
- p->wd, p->h, p->x, p->y);
+ XCopyArea (display, pixmap, drawable, gc, px, py,
+ pwidth, pheight, dest.x, dest.y);
XFreePixmap (display, pixmap);
if (p->overlay_p)
@@ -8003,6 +8028,8 @@ x_draw_fringe_bitmap (struct window *w, struct glyph_row *row,
XFreePixmap (display, clipmask);
}
}
+
+ undo_clip:
#endif /* not USE_CAIRO */
x_reset_clip_rectangles (f, gc);
@@ -11269,7 +11296,7 @@ x_clear_frame (struct frame *f)
/* Send a message to frame F telling the event loop to track whether
or not an hourglass is being displayed. This is required to ignore
- the right events when the hourglass is mapped without callig XSync
+ the right events when the hourglass is mapped without calling XSync
after displaying or hiding the hourglass. */
static void
@@ -11793,7 +11820,9 @@ x_frame_highlight (struct frame *f)
x_stop_ignoring_errors (dpyinfo);
unblock_input ();
gui_update_cursor (f, true);
- x_set_frame_alpha (f);
+
+ if (!FRAME_X_OUTPUT (f)->alpha_identical_p)
+ x_set_frame_alpha (f);
}
static void
@@ -11817,7 +11846,15 @@ x_frame_unhighlight (struct frame *f)
unblock_input ();
gui_update_cursor (f, true);
- x_set_frame_alpha (f);
+
+ /* Eschew modifying the frame alpha when the alpha values for
+ focused and background frames are identical; otherwise, this will
+ upset the order in which changes to the alpha property
+ immediately subsequent to a focus change are propagated into a
+ frame's alpha property. (bug#66398) */
+
+ if (!FRAME_X_OUTPUT (f)->alpha_identical_p)
+ x_set_frame_alpha (f);
}
/* The focus has changed. Update the frames as necessary to reflect
@@ -12527,7 +12564,7 @@ x_dnd_process_quit (struct frame *f, Time timestamp)
/* This function is defined far away from the rest of the XDND code so
it can utilize `x_any_window_to_frame'. */
-/* Implementors beware! On most other platforms (where drag-and-drop
+/* Implementers beware! On most other platforms (where drag-and-drop
data is not provided via selections, but some kind of serialization
mechanism), it is usually much easier to implement a suitable
primitive instead of copying the C code here, and then to build
@@ -13170,6 +13207,12 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction,
#ifdef HAVE_XINPUT2
+/* Disable per-device keyboard focus tracking within X toolkit and GTK
+ 2.x builds, given that these builds receive updates to the keyboard
+ input focus as core events. */
+
+#if !defined USE_X_TOOLKIT && (!defined USE_GTK || defined HAVE_GTK3)
+
/* Since the input extension assigns a keyboard focus to each master
device, there is no longer a 1:1 correspondence between the
selected frame and the focus frame immediately after the keyboard
@@ -13381,6 +13424,8 @@ xi_focus_handle_for_device (struct x_display_info *dpyinfo,
xi_handle_focus_change (dpyinfo);
}
+#endif /* !USE_X_TOOLKIT && (!USE_GTK || HAVE_GTK3) */
+
static void
xi_handle_delete_frame (struct x_display_info *dpyinfo,
struct frame *f)
@@ -13409,6 +13454,7 @@ xi_handle_interaction (struct x_display_info *dpyinfo,
struct frame *f, struct xi_device_t *device,
Time time)
{
+#if !defined USE_X_TOOLKIT && (!defined USE_GTK || defined HAVE_GTK3)
bool change;
/* If DEVICE is a pointer, use its attached keyboard device. */
@@ -13435,6 +13481,7 @@ xi_handle_interaction (struct x_display_info *dpyinfo,
/* If F isn't currently focused, update the focus state. */
if (change && f != dpyinfo->x_focus_frame)
xi_handle_focus_change (dpyinfo);
+#endif /* !USE_X_TOOLKIT && (!USE_GTK || HAVE_GTK3) */
}
/* Return whether or not XEV actually represents a change in the
@@ -20198,15 +20245,24 @@ handle_one_xevent (struct x_display_info *dpyinfo,
#ifdef HAVE_XKB
int overflow;
unsigned int consumed;
+ KeySym sym;
if (dpyinfo->xkb_desc)
{
+ /* Translate the keycode into the keysym it
+ represents, using STATE. CONSUMED is set to the
+ modifier bits consumed while undertaking this
+ translation and should be subsequently ignored
+ during keysym translation. */
+
if (!XkbTranslateKeyCode (dpyinfo->xkb_desc,
xkey.keycode, xkey.state,
&consumed, &keysym))
goto done_keysym;
- overflow = 0;
+ /* Save the original keysym in case
+ XkbTranslateKeysym overflows. */
+ sym = keysym, overflow = 0;
nbytes = XkbTranslateKeySym (dpyinfo->display, &keysym,
xkey.state & ~consumed,
@@ -20218,7 +20274,11 @@ handle_one_xevent (struct x_display_info *dpyinfo,
copy_bufptr = SAFE_ALLOCA ((copy_bufsiz += overflow)
* sizeof *copy_bufptr);
overflow = 0;
- nbytes = XkbTranslateKeySym (dpyinfo->display, &keysym,
+
+ /* Use the original keysym derived from the
+ keycode translation in this second call to
+ XkbTranslateKeysym. */
+ nbytes = XkbTranslateKeySym (dpyinfo->display, &sym,
xkey.state & ~consumed,
(char *) copy_bufptr,
copy_bufsiz, &overflow);
@@ -20247,20 +20307,23 @@ handle_one_xevent (struct x_display_info *dpyinfo,
/* See if keysym should make Emacs quit. */
- if (keysym == dpyinfo->quit_keysym
- && (xkey.time - dpyinfo->quit_keysym_time
- <= 350))
+ if (dpyinfo->quit_keysym)
{
- Vquit_flag = Qt;
- goto done_keysym;
- }
+ if (keysym == dpyinfo->quit_keysym
+ && (xkey.time - dpyinfo->quit_keysym_time
+ <= 350))
+ {
+ Vquit_flag = Qt;
+ goto done_keysym;
+ }
- if (keysym == dpyinfo->quit_keysym)
- {
- /* Otherwise, set the last time that keysym was
- pressed. */
- dpyinfo->quit_keysym_time = xkey.time;
- goto done_keysym;
+ if (keysym == dpyinfo->quit_keysym)
+ {
+ /* Otherwise, set the last time that keysym was
+ pressed. */
+ dpyinfo->quit_keysym_time = xkey.time;
+ goto done_keysym;
+ }
}
/* If not using XIM/XIC, and a compose sequence is in progress,
@@ -20562,6 +20625,14 @@ handle_one_xevent (struct x_display_info *dpyinfo,
}
#endif
+ /* Apply the fix for bug#57468 on GTK 3.x and no toolkit builds,
+ but not GTK+ 2.x and X toolkit builds, where it is required
+ to treat implicit focus correctly. (bug#65919) */
+#if defined USE_X_TOOLKIT || (defined USE_GTK && !defined HAVE_GTK3)
+ if (x_top_window_to_frame (dpyinfo, event->xcrossing.window))
+ x_detect_focus_change (dpyinfo, any, event, &inev.ie);
+#endif /* defined USE_X_TOOLKIT || (defined USE_GTK && !defined HAVE_GTK3) */
+
#ifdef HAVE_XINPUT2
/* For whatever reason, the X server continues to deliver
EnterNotify and LeaveNotify events despite us selecting for
@@ -20572,10 +20643,14 @@ handle_one_xevent (struct x_display_info *dpyinfo,
if (dpyinfo->supports_xi2)
goto OTHER;
-#endif
+#endif /* HAVE_XINPUT2 */
+ /* Apply the fix for bug#57468 on GTK 3.x and no toolkit
+ builds. */
+#if !defined USE_X_TOOLKIT || (!defined USE_GTK || defined HAVE_GTK3)
if (x_top_window_to_frame (dpyinfo, event->xcrossing.window))
x_detect_focus_change (dpyinfo, any, event, &inev.ie);
+#endif /* !defined USE_X_TOOLKIT || (!defined USE_GTK || defined HAVE_GTK3) */
f = any;
@@ -20636,8 +20711,8 @@ handle_one_xevent (struct x_display_info *dpyinfo,
https://lists.gnu.org/archive/html/emacs-devel/2017-02/msg00133.html.
That is fixed above but bites us here again.
- The option x_set_frame_visibility_more_laxly allows to override
- the default behavior (Bug#49955, Bug#53298). */
+ The option x_set_frame_visibility_more_laxly enables
+ overriding the default behavior (Bug#49955, Bug#53298). */
if (EQ (x_set_frame_visibility_more_laxly, Qfocus_in)
|| EQ (x_set_frame_visibility_more_laxly, Qt))
#endif /* USE_GTK */
@@ -20660,6 +20735,14 @@ handle_one_xevent (struct x_display_info *dpyinfo,
x_display_set_last_user_time (dpyinfo, event->xcrossing.time,
event->xcrossing.send_event, false);
+ /* Apply the fix for bug#57468 on GTK 3.x and no toolkit builds,
+ but not GTK+ 2.x and X toolkit builds, where it is required
+ to treat implicit focus correctly. */
+#if defined USE_X_TOOLKIT || (defined USE_GTK && !defined HAVE_GTK3)
+ if (x_top_window_to_frame (dpyinfo, event->xcrossing.window))
+ x_detect_focus_change (dpyinfo, any, event, &inev.ie);
+#endif /* defined USE_X_TOOLKIT || (defined USE_GTK && !defined HAVE_GTK3) */
+
#ifdef HAVE_XINPUT2
/* For whatever reason, the X server continues to deliver
EnterNotify and LeaveNotify events despite us selecting for
@@ -20672,7 +20755,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
{
#if !defined USE_X_TOOLKIT && (!defined USE_GTK || defined HAVE_GTK3)
goto OTHER;
-#else
+#else /* USE_X_TOOLKIT || (USE_GTK && !HAVE_GTK3) */
/* Unfortunately, X toolkit popups generate LeaveNotify
events due to the core grabs they acquire (and our
releasing of the device grab). This leads to the mouse
@@ -20681,9 +20764,16 @@ handle_one_xevent (struct x_display_info *dpyinfo,
outside the frame, in which case no XI_Enter event is
generated for the grab. */
goto just_clear_mouse_face;
-#endif
+#endif /* !USE_X_TOOLKIT && (!USE_GTK || HAVE_GTK3) */
}
-#endif
+#endif /* HAVE_XINPUT2 */
+
+ /* Apply the fix for bug#57468 on GTK 3.x and no toolkit
+ builds. */
+#if !defined USE_X_TOOLKIT || (!defined USE_GTK || defined HAVE_GTK3)
+ if (x_top_window_to_frame (dpyinfo, event->xcrossing.window))
+ x_detect_focus_change (dpyinfo, any, event, &inev.ie);
+#endif /* !defined USE_X_TOOLKIT || (!defined USE_GTK || defined HAVE_GTK3) */
#ifdef HAVE_XWIDGETS
{
@@ -20699,9 +20789,6 @@ handle_one_xevent (struct x_display_info *dpyinfo,
}
#endif
- if (x_top_window_to_frame (dpyinfo, event->xcrossing.window))
- x_detect_focus_change (dpyinfo, any, event, &inev.ie);
-
#if defined HAVE_XINPUT2 \
&& (defined USE_X_TOOLKIT || (defined USE_GTK && !defined HAVE_GTK3))
just_clear_mouse_face:
@@ -21084,7 +21171,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
}
Lisp_Object window = window_from_coordinates
- (f, xmotion.x, xmotion.y, 0, false, false);
+ (f, xmotion.x, xmotion.y, 0, false, false, false);
/* A window will be autoselected only when it is not
selected now and the last mouse movement event was
@@ -21815,7 +21902,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
int x = event->xbutton.x;
int y = event->xbutton.y;
- window = window_from_coordinates (f, x, y, 0, true, true);
+ window = window_from_coordinates (f, x, y, 0, true, true, true);
tab_bar_p = EQ (window, f->tab_bar_window);
if (tab_bar_p)
@@ -21836,7 +21923,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
int x = event->xbutton.x;
int y = event->xbutton.y;
- window = window_from_coordinates (f, x, y, 0, true, true);
+ window = window_from_coordinates (f, x, y, 0, true, true, true);
tool_bar_p = (EQ (window, f->tool_bar_window)
&& (event->xbutton.type != ButtonRelease
|| f->last_tool_bar_item != -1));
@@ -22069,6 +22156,10 @@ handle_one_xevent (struct x_display_info *dpyinfo,
switch (event->xcookie.evtype)
{
+ /* XI focus events aren't employed under X toolkit or GTK+
+ 2.x because windows created by these two toolkits are
+ incompatible with input extension focus events. */
+#if !defined USE_X_TOOLKIT && (!defined USE_GTK || defined HAVE_GTK3)
case XI_FocusIn:
{
XIFocusInEvent *focusin;
@@ -22078,17 +22169,19 @@ handle_one_xevent (struct x_display_info *dpyinfo,
#ifdef USE_GTK
/* Some WMs (e.g. Mutter in Gnome Shell), don't unmap
- minimized/iconified windows; thus, for those WMs we won't get
- a MapNotify when unminimizing/deiconifying. Check here if we
- are deiconizing a window (Bug42655).
+ minimized/iconified windows; thus, for those WMs we
+ won't get a MapNotify when unminimizing/deiconifying.
+ Check here if we are deiconizing a window (Bug42655).
- But don't do that by default on GTK since it may cause a plain
- invisible frame get reported as iconified, compare
+ But don't do that by default on GTK since it may
+ cause a plain invisible frame get reported as
+ iconified, compare
https://lists.gnu.org/archive/html/emacs-devel/2017-02/msg00133.html.
That is fixed above but bites us here again.
- The option x_set_frame_visibility_more_laxly allows to override
- the default behavior (Bug#49955, Bug#53298). */
+ The option x_set_frame_visibility_more_laxly enables
+ overriding the default behavior (Bug#49955,
+ Bug#53298). */
if (EQ (x_set_frame_visibility_more_laxly, Qfocus_in)
|| EQ (x_set_frame_visibility_more_laxly, Qt))
#endif /* USE_GTK */
@@ -22119,6 +22212,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
goto XI_OTHER;
}
+#endif /* !USE_X_TOOLKIT && (!USE_GTK || HAVE_GTK3) */
case XI_Enter:
{
@@ -22164,8 +22258,11 @@ handle_one_xevent (struct x_display_info *dpyinfo,
passive focus from non-top windows at all, since they
are an inferiors of the frame's top window, which will
get virtual events. */
+
+#if !defined USE_X_TOOLKIT && (!defined USE_GTK || defined HAVE_GTK3)
if (any)
xi_focus_handle_for_device (dpyinfo, any, xi_event);
+#endif /* !USE_X_TOOLKIT && (!USE_GTK || HAVE_GTK3) */
if (!any)
any = x_any_window_to_frame (dpyinfo, enter->event);
@@ -22345,8 +22442,10 @@ handle_one_xevent (struct x_display_info *dpyinfo,
}
#endif
+#if !defined USE_X_TOOLKIT && (!defined USE_GTK || defined HAVE_GTK3)
if (any)
xi_focus_handle_for_device (dpyinfo, any, xi_event);
+#endif /* !USE_X_TOOLKIT && (!USE_GTK || HAVE_GTK3) */
#ifndef USE_X_TOOLKIT
f = x_top_window_to_frame (dpyinfo, leave->event);
@@ -22557,7 +22656,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
continue;
window = window_from_coordinates (f, real_x, real_y, NULL,
- false, false);
+ false, false, false);
if (WINDOWP (window))
scroll_height = XWINDOW (window)->pixel_height;
@@ -23000,7 +23099,8 @@ handle_one_xevent (struct x_display_info *dpyinfo,
|| !NILP (focus_follows_mouse)))
{
static Lisp_Object last_mouse_window;
- Lisp_Object window = window_from_coordinates (f, ev.x, ev.y, 0, false, false);
+ Lisp_Object window = window_from_coordinates (f, ev.x, ev.y, 0, false, false,
+ false);
/* A window will be autoselected only when it is not
selected now and the last mouse movement event was
@@ -23578,7 +23678,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
int x = bv.x;
int y = bv.y;
- window = window_from_coordinates (f, x, y, 0, true, true);
+ window = window_from_coordinates (f, x, y, 0, true, true, true);
tab_bar_p = EQ (window, f->tab_bar_window);
if (tab_bar_p)
@@ -23599,7 +23699,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
int x = bv.x;
int y = bv.y;
- window = window_from_coordinates (f, x, y, 0, true, true);
+ window = window_from_coordinates (f, x, y, 0, true, true, true);
/* Ignore button release events if the mouse
wasn't previously pressed on the tool bar.
We do this because otherwise selecting some
@@ -23725,7 +23825,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
Lisp_Object c;
#ifdef HAVE_XKB
unsigned int mods_rtrn;
-#endif
+#endif /* HAVE_XKB */
int keycode = xev->detail;
KeySym keysym;
char copy_buffer[81];
@@ -23734,15 +23834,123 @@ handle_one_xevent (struct x_display_info *dpyinfo,
ptrdiff_t i;
unsigned int old_state;
struct xi_device_t *device, *source;
+ XKeyPressedEvent xkey;
coding = Qlatin_1;
+ /* The code under this label is quite desultory. There
+ are also several important discrepancies with the
+ core KeyPress code to mind.
+
+ There are three principal objectives:
+
+ The first is to produce a core or GDK translation of
+ this XI_KeyPress event, which is relayed to the
+ toolkit. This transpires by setting `copy' to a
+ close copy of XEV, which is later copied or
+ dispatched to the toolkit by the code beneath the
+ OTHER label.
+
+ The second objective is to filter the event through
+ an input method, by generating a second copy of the
+ event expressly tailored for such a purpose. The
+ core KeyPress code does not endeavor to do so;
+ instead, this action is taken prior to calling
+ handle_one_xevent. Calls to `x_filter_event' or
+ `xg_filter_key' serve to implement this objective.
+
+ If the event is not removed by the input method's
+ filter, the third objective is to establish either a
+ keysym or a sequence of characters to insert, using
+ the information supplied within the key event.
+
+ When an input method connection is available, this
+ responsibility is vested in the hands of the input
+ method -- yet another copy of XEV as a core event is
+ produced, and the input method is responsible for
+ deriving a keysym or text to insert.
+
+ Otherwise, if the XKB extension is available, calls
+ are made to XkbTranslateKeyCode and
+ XkbTranslateKeySym.
+
+ And if all else fails, XEV is transformed into a core
+ event and provided to XLookupString, in a manner
+ analogous to the core event processing under the
+ KeyPress label.
+
+ A wide number of variables are employed during this
+ translation process. The most pertinent ones are:
+
+ `copy'
+
+ This variable is defined when an X toolkit
+ incognizant of input extension events is being
+ employed. If a popup is active, Emacs copies
+ fields of interest from the extension event to
+ COPY, sets the `use_copy' flag, and jumps to the
+ XI_OTHER label. `copy' is then relayed to the
+ toolkit.
+
+ `xkey'
+
+ This variable is defined to a copy of the event
+ used by input methods or XLookupString at various
+ points during the execution of this label.
+
+ `coding'
+
+ This variable is consulted at the conclusion of
+ event generation, and holds the coding system
+ for any generated string.
+
+ `keysym'
+
+ This variable is eventually set to the keysym tied
+ to the event, which may be directly provided within
+ a generated struct input_event, should it bear a
+ direct relation to an ASCII or Unicode character,
+ or if it is a control key.
+
+ `copy_buffer', `copy_bufptr', `copy_bufsiz'
+
+ These variables hold the buffer that incorporates
+ characters generated during the keycode-to-keysym
+ conversion process.
+
+ `nbytes'
+
+ Holds the number of characters within that buffer,
+ in bytes. These characters are encoded using the
+ coding system in `coding'.
+
+ If greater than 0 and KEYSYM does not immediately
+ relate to a function key, control key or character,
+ it is provided as the string to insert within a
+ MULTIBYTE_CHAR_KEYSTROKE_EVENT.
+
+ `state'
+
+ Holds the keyboard and group (but not button)
+ state. After event filtering concludes, modifier
+ bits within `extra_keyboard_modifiers' are also
+ introduced.
+
+ This illustration may reflect the treatment taken
+ towards core key events to some degree. */
+
device = xi_device_from_id (dpyinfo, xev->deviceid);
source = xi_device_from_id (dpyinfo, xev->sourceid);
if (!device)
goto XI_OTHER;
+ /* Convert the keyboard state within XEV to a core
+ modifier mask, later supplied as arguments to XKB and
+ core functions. This encompasses the keyboard group
+ and effective modifiers but not the button state. */
+ state = xi_convert_event_keyboard_state (xev);
+
#if defined (USE_X_TOOLKIT) || defined (USE_GTK)
/* Dispatch XI_KeyPress events when in menu. */
if (popup_activated ())
@@ -23758,7 +23966,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
copy.xkey.root = xev->root;
copy.xkey.subwindow = xev->child;
copy.xkey.time = xev->time;
- copy.xkey.state = xi_convert_event_keyboard_state (xev);
+ copy.xkey.state = state;
xi_convert_button_state (&xev->buttons, &copy.xkey.state);
copy.xkey.x = lrint (xev->event_x);
@@ -23767,10 +23975,10 @@ handle_one_xevent (struct x_display_info *dpyinfo,
copy.xkey.y_root = lrint (xev->root_y);
copy.xkey.keycode = xev->detail;
copy.xkey.same_screen = True;
-#endif
+#endif /* USE_LUCID */
goto XI_OTHER;
}
-#endif
+#endif /* USE_X_TOOLKIT || USE_GTK */
x_display_set_last_user_time (dpyinfo, xev->time,
xev->send_event, true);
@@ -23790,7 +23998,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
#ifdef USE_GTK
if (f)
x_set_gtk_user_time (f, xev->time);
-#endif
+#endif /* USE_GTK */
if (f)
{
@@ -23802,7 +24010,9 @@ handle_one_xevent (struct x_display_info *dpyinfo,
xev->time);
}
- XKeyPressedEvent xkey;
+ /* Convert the XI event into a core event structure
+ provided to old Xlib functions and input method
+ filter functions. */
memset (&xkey, 0, sizeof xkey);
@@ -23814,8 +24024,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
xkey.root = xev->root;
xkey.subwindow = xev->child;
xkey.time = xev->time;
- xkey.state = xi_convert_event_keyboard_state (xev);
-
+ xkey.state = state;
xkey.x = lrint (xev->event_x);
xkey.y = lrint (xev->event_y);
xkey.x_root = lrint (xev->root_x);
@@ -23844,7 +24053,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
*finish = X_EVENT_DROP;
goto XI_OTHER;
}
-#else
+#else /* !USE_GTK */
if (x_filter_event (dpyinfo, (XEvent *) &xkey))
{
/* Try to attribute core key events from the input
@@ -23856,8 +24065,8 @@ handle_one_xevent (struct x_display_info *dpyinfo,
*finish = X_EVENT_DROP;
goto XI_OTHER;
}
-#endif
-#elif USE_GTK
+#endif /* HAVE_X_I18N */
+#elif USE_GTK /* && !HAVE_X_I18N */
if ((x_gtk_use_native_input
|| dpyinfo->prefer_native_input)
&& xg_filter_key (any, event))
@@ -23871,48 +24080,17 @@ handle_one_xevent (struct x_display_info *dpyinfo,
*finish = X_EVENT_DROP;
goto XI_OTHER;
}
-#endif
+#endif /* HAVE_X_I18N || USE_GTK */
state |= x_emacs_to_x_modifiers (dpyinfo, extra_keyboard_modifiers);
-#ifdef HAVE_XKB
- if (dpyinfo->xkb_desc)
- {
- unsigned int xkb_state;
-
- xkb_state = state & ~(1 << 13 | 1 << 14);
- xkb_state |= xev->group.effective << 13;
-
- if (!XkbTranslateKeyCode (dpyinfo->xkb_desc, keycode,
- xkb_state, &mods_rtrn, &keysym))
- goto XI_OTHER;
- }
- else
- {
-#endif
- int keysyms_per_keycode_return;
- KeySym *ksms = XGetKeyboardMapping (dpyinfo->display, keycode, 1,
- &keysyms_per_keycode_return);
- if (!(keysym = ksms[0]))
- {
- XFree (ksms);
- goto XI_OTHER;
- }
- XFree (ksms);
-#ifdef HAVE_XKB
- }
-#endif
-
- if (keysym == NoSymbol)
- goto XI_OTHER;
-
/* If mouse-highlight is an integer, input clears out
mouse highlighting. */
if (!hlinfo->mouse_face_hidden && FIXNUMP (Vmouse_highlight)
&& (f == 0
#if ! defined (USE_GTK)
|| !EQ (f->tool_bar_window, hlinfo->mouse_face_window)
-#endif
+#endif /* !USE_GTK */
|| !EQ (f->tab_bar_window, hlinfo->mouse_face_window))
)
{
@@ -23933,7 +24111,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
dialogs because in that case popup_activated is nonzero
(see above). */
*finish = X_EVENT_DROP;
-#endif
+#endif /* USE_GTK */
XSETFRAME (inev.ie.frame_or_window, f);
inev.ie.timestamp = xev->time;
@@ -23970,25 +24148,54 @@ handle_one_xevent (struct x_display_info *dpyinfo,
emacs_abort ();
}
else
-#endif
+#endif /* HAVE_X_I18N */
{
#ifdef HAVE_XKB
- int overflow = 0;
- KeySym sym = keysym;
-
if (dpyinfo->xkb_desc)
{
- nbytes = XkbTranslateKeySym (dpyinfo->display, &sym,
- state & ~mods_rtrn, copy_bufptr,
- copy_bufsiz, &overflow);
+ KeySym sym;
+ int overflow;
+
+ /* Translate the keycode into the keysym it
+ represents, using STATE. MODS_RTRN is
+ set to the modifier bits consumed while
+ undertaking this translation and should
+ be subsequently ignored during keysym
+ translation. */
+
+ if (!XkbTranslateKeyCode (dpyinfo->xkb_desc,
+ keycode, state,
+ &mods_rtrn, &keysym))
+ goto xi_done_keysym;
+
+ /* Save the original keysym in case
+ XkbTranslateKeySym overflows. */
+ sym = keysym, overflow = 0;
+
+ /* Translate this keysym and its modifier
+ state into the actual symbol and string
+ it represents. */
+ nbytes = XkbTranslateKeySym (dpyinfo->display,
+ &keysym,
+ state & ~mods_rtrn,
+ copy_bufptr,
+ copy_bufsiz,
+ &overflow);
if (overflow)
{
- copy_bufptr = SAFE_ALLOCA ((copy_bufsiz += overflow)
- * sizeof *copy_bufptr);
+ copy_bufptr
+ = SAFE_ALLOCA ((copy_bufsiz += overflow)
+ * sizeof *copy_bufptr);
overflow = 0;
- nbytes = XkbTranslateKeySym (dpyinfo->display, &sym,
- state & ~mods_rtrn, copy_bufptr,
- copy_bufsiz, &overflow);
+
+ /* Use the original keysym derived from
+ the keycode translation. */
+ nbytes = XkbTranslateKeySym (dpyinfo->display,
+ &sym,
+ state & ~mods_rtrn,
+ copy_bufptr,
+ copy_bufsiz,
+ &overflow);
if (overflow)
nbytes = 0;
@@ -23997,8 +24204,14 @@ handle_one_xevent (struct x_display_info *dpyinfo,
coding = Qnil;
}
else
-#endif
+#endif /* HAVE_XKB */
{
+ /* Save the state within XKEY, then remove
+ all modifier keys Emacs understands from
+ it, forestalling any attempt by
+ XLookupString to introduce control
+ characters. */
+
old_state = xkey.state;
xkey.state &= ~ControlMask;
xkey.state &= ~(dpyinfo->meta_mod_mask
@@ -24024,24 +24237,27 @@ handle_one_xevent (struct x_display_info *dpyinfo,
x_dnd_xm_use_help = true;
goto xi_done_keysym;
}
-#endif
+#endif /* XK_F1 */
/* See if keysym should make Emacs quit. */
- if (keysym == dpyinfo->quit_keysym
- && (xev->time - dpyinfo->quit_keysym_time
- <= 350))
+ if (dpyinfo->quit_keysym)
{
- Vquit_flag = Qt;
- goto xi_done_keysym;
- }
+ if (keysym == dpyinfo->quit_keysym
+ && (xev->time - dpyinfo->quit_keysym_time
+ <= 350))
+ {
+ Vquit_flag = Qt;
+ goto xi_done_keysym;
+ }
- if (keysym == dpyinfo->quit_keysym)
- {
- /* Otherwise, set the last time that keysym was
- pressed. */
- dpyinfo->quit_keysym_time = xev->time;
- goto xi_done_keysym;
+ if (keysym == dpyinfo->quit_keysym)
+ {
+ /* Otherwise, set the last time that keysym
+ was pressed. */
+ dpyinfo->quit_keysym_time = xev->time;
+ goto xi_done_keysym;
+ }
}
/* First deal with keysyms which have defined
@@ -24304,9 +24520,11 @@ handle_one_xevent (struct x_display_info *dpyinfo,
XIDeviceInfo *info;
int i, ndevices, n_disabled, *disabled;
struct xi_device_t *device;
+#if !defined USE_X_TOOLKIT && (!defined USE_GTK || defined HAVE_GTK3)
bool any_changed;
any_changed = false;
+#endif /* !USE_X_TOOLKIT && (!USE_GTK || HAVE_GTK3) */
hev = (XIHierarchyEvent *) xi_event;
disabled = SAFE_ALLOCA (sizeof *disabled * hev->num_info);
n_disabled = 0;
@@ -24323,10 +24541,12 @@ handle_one_xevent (struct x_display_info *dpyinfo,
xi_disable_devices (dpyinfo, disabled, n_disabled);
n_disabled = 0;
+#if !defined USE_X_TOOLKIT && (!defined USE_GTK || defined HAVE_GTK3)
/* This flag really just means that disabled
devices were handled early and should be
used in conjunction with n_disabled. */
any_changed = true;
+#endif /* !USE_X_TOOLKIT && (!USE_GTK || HAVE_GTK3) */
}
/* Under unknown circumstances, multiple
@@ -24393,12 +24613,14 @@ handle_one_xevent (struct x_display_info *dpyinfo,
event. */
xi_disable_devices (dpyinfo, disabled, n_disabled);
+#if !defined USE_X_TOOLKIT && (!defined USE_GTK || defined HAVE_GTK3)
/* If the device hierarchy has been changed, recompute
focus. This might seem like a micro-optimization but
it actually keeps the focus from changing in some
cases where it would be undesierable. */
if (any_changed || n_disabled)
xi_handle_focus_change (dpyinfo);
+#endif /* !USE_X_TOOLKIT && (!USE_GTK || HAVE_GTK3) */
goto XI_OTHER;
}
@@ -24483,7 +24705,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
int x = xev->event_x;
int y = xev->event_y;
- window = window_from_coordinates (f, x, y, 0, true, true);
+ window = window_from_coordinates (f, x, y, 0, true, true, true);
/* Ignore button release events if the mouse
wasn't previously pressed on the tool bar.
We do this because otherwise selecting some
@@ -25468,13 +25690,17 @@ XTread_socket (struct terminal *terminal, struct input_event *hold_quit)
/* Set clipping for output in glyph row ROW. W is the window in which
we operate. GC is the graphics context to set clipping in.
+ If RECT_RETURN is non-NULL, return the clip rectangle within
+ *RECT_RETURN.
+
ROW may be a text row or, e.g., a mode line. Text rows must be
clipped to the interior of the window dedicated to text display,
mode lines must be clipped to the whole window. */
static void
x_clip_to_row (struct window *w, struct glyph_row *row,
- enum glyph_row_area area, GC gc)
+ enum glyph_row_area area, GC gc,
+ XRectangle *rect_return)
{
struct frame *f = XFRAME (WINDOW_FRAME (w));
XRectangle clip_rect;
@@ -25489,6 +25715,9 @@ x_clip_to_row (struct window *w, struct glyph_row *row,
clip_rect.height = row->visible_height;
x_set_clip_rectangles (f, gc, &clip_rect, 1);
+
+ if (rect_return)
+ *rect_return = clip_rect;
}
@@ -25537,7 +25766,7 @@ x_draw_hollow_cursor (struct window *w, struct glyph_row *row)
wd -= 1;
}
/* Set clipping, draw the rectangle, and reset clipping again. */
- x_clip_to_row (w, row, TEXT_AREA, gc);
+ x_clip_to_row (w, row, TEXT_AREA, gc, NULL);
x_draw_rectangle (f, gc, x, y, wd, h - 1);
x_reset_clip_rectangles (f, gc);
}
@@ -25607,7 +25836,7 @@ x_draw_bar_cursor (struct window *w, struct glyph_row *row, int width, enum text
FRAME_DISPLAY_INFO (f)->scratch_cursor_gc = gc;
}
- x_clip_to_row (w, row, TEXT_AREA, gc);
+ x_clip_to_row (w, row, TEXT_AREA, gc, NULL);
if (kind == BAR_CURSOR)
{
@@ -26973,7 +27202,7 @@ xim_open_dpy (struct x_display_info *dpyinfo, char *resource_name)
/* Now try to determine the coding system that should be
used. locale is in Host Portable Character Encoding, and
as such can be passed to build_string as is. */
- dpyinfo->xim_coding = safe_call1 (Vx_input_coding_function,
+ dpyinfo->xim_coding = safe_calln (Vx_input_coding_function,
build_string (locale));
}
}
@@ -29326,6 +29555,7 @@ x_free_frame_resources (struct frame *f)
dpyinfo->last_mouse_frame = NULL;
#ifdef HAVE_XINPUT2
+#if !defined USE_X_TOOLKIT && (!defined USE_GTK || defined HAVE_GTK3)
/* Consider a frame being unfocused with no following FocusIn event
while an older focus from another seat exists. The client
pointer should then revert to the other seat, so handle potential
@@ -29333,7 +29563,8 @@ x_free_frame_resources (struct frame *f)
if (dpyinfo->supports_xi2)
xi_handle_focus_change (dpyinfo);
-#endif
+#endif /* !USE_X_TOOLKIT && (!USE_GTK || HAVE_GTK3) */
+#endif /* HAVE_XINPUT2 */
unblock_input ();
}
@@ -30430,7 +30661,7 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
terminal_list = terminal->next_terminal;
unblock_input ();
kset_system_key_alist (terminal->kboard,
- safe_call1 (Qvendor_specific_keysyms,
+ safe_calln (Qvendor_specific_keysyms,
(vendor
? build_string (vendor)
: empty_unibyte_string)));
@@ -30973,7 +31204,17 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
XkbNewKeyboardNotifyMask | XkbMapNotifyMask,
XkbNewKeyboardNotifyMask | XkbMapNotifyMask);
}
-#endif
+
+ /* XFree86 extends XKBlib with a new Xlib control `ControlFallback',
+ which enables a search for symbols designating ASCII characters
+ within inactive groups during keycode translation when
+ ControlMask is set. Users find this behavior gratuitous, so
+ disable it if present. */
+
+#ifdef XkbLC_ControlFallback
+ XkbSetXlibControls (dpyinfo->display, XkbLC_ControlFallback, 0);
+#endif /* XkbLC_ControlFallback */
+#endif /* HAVE_XKB */
#ifdef HAVE_XFIXES
int xfixes_error_base;
@@ -31853,7 +32094,7 @@ x_initialize (void)
#ifdef HAVE_X_I18N
-/* Notice that a change has occured on F that requires its input
+/* Notice that a change has occurred on F that requires its input
method state to be reset. */
static void
@@ -32588,17 +32829,12 @@ frame placement via frame parameters, `set-frame-position', and
This is used to support quitting on devices that do not have any kind
of physical keyboard, or where the physical keyboard is incapable of
-entering `C-g'. It defaults to `XF86XK_AudioLowerVolume' on XFree86
-and X.Org servers, and is unset.
+entering `C-g'.
The value is an alist associating between strings, describing X server
vendor names, and a single number describing the keysym to use. The
keysym to use for each display connection is determined upon
connection setup, and does not reflect further changes to this
variable. */);
- Vx_quit_keysym
- = list2 (Fcons (build_string ("The X.Org Foundation"),
- make_int (269025041)),
- Fcons (build_string ("The XFree86 Project, Inc."),
- make_int (269025041)));
+ Vx_quit_keysym = Qnil;
}
diff --git a/src/xterm.h b/src/xterm.h
index cb477645bfa..3c128148270 100644
--- a/src/xterm.h
+++ b/src/xterm.h
@@ -1,5 +1,5 @@
/* Definitions and headers for communication with X protocol.
- Copyright (C) 1989, 1993-1994, 1998-2023 Free Software Foundation,
+ Copyright (C) 1989, 1993-1994, 1998-2024 Free Software Foundation,
Inc.
This file is part of GNU Emacs.
diff --git a/src/xwidget.c b/src/xwidget.c
index 7f30e48c954..58910459142 100644
--- a/src/xwidget.c
+++ b/src/xwidget.c
@@ -1,6 +1,6 @@
/* Support for embedding graphical components in a buffer.
-Copyright (C) 2011-2023 Free Software Foundation, Inc.
+Copyright (C) 2011-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/src/xwidget.h b/src/xwidget.h
index 171924e0aaa..34cae383abf 100644
--- a/src/xwidget.h
+++ b/src/xwidget.h
@@ -1,6 +1,6 @@
/* Support for embedding graphical components in a buffer.
-Copyright (C) 2011-2023 Free Software Foundation, Inc.
+Copyright (C) 2011-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/test/ChangeLog.1 b/test/ChangeLog.1
index 2c412a64519..9693f59c311 100644
--- a/test/ChangeLog.1
+++ b/test/ChangeLog.1
@@ -2952,7 +2952,7 @@
;; coding: utf-8
;; End:
- Copyright (C) 2008-2023 Free Software Foundation, Inc.
+ Copyright (C) 2008-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/test/Makefile.in b/test/Makefile.in
index 4e53efeb9a8..720f5c7ff8c 100644
--- a/test/Makefile.in
+++ b/test/Makefile.in
@@ -1,6 +1,6 @@
### @configure_input@
-# Copyright (C) 2010-2023 Free Software Foundation, Inc.
+# Copyright (C) 2010-2024 Free Software Foundation, Inc.
# This file is part of GNU Emacs.
diff --git a/test/README b/test/README
index 9255dbed513..7a3cf871a57 100644
--- a/test/README
+++ b/test/README
@@ -1,4 +1,4 @@
-Copyright (C) 2008-2023 Free Software Foundation, Inc.
+Copyright (C) 2008-2024 Free Software Foundation, Inc.
See the end of the file for license conditions.
This directory contains files intended to test various aspects of
diff --git a/test/infra/Dockerfile.emba b/test/infra/Dockerfile.emba
index 584e4444dc1..8e583fade9f 100644
--- a/test/infra/Dockerfile.emba
+++ b/test/infra/Dockerfile.emba
@@ -1,4 +1,4 @@
-# Copyright (C) 2021-2023 Free Software Foundation, Inc.
+# Copyright (C) 2021-2024 Free Software Foundation, Inc.
#
# This file is part of GNU Emacs.
#
@@ -126,6 +126,7 @@ RUN src/emacs -Q --batch \
(java "https://github.com/tree-sitter/tree-sitter-java") \
(javascript "https://github.com/tree-sitter/tree-sitter-javascript") \
(json "https://github.com/tree-sitter/tree-sitter-json") \
+ (lua "https://github.com/MunifTanjim/tree-sitter-lua") \
(python "https://github.com/tree-sitter/tree-sitter-python") \
(ruby "https://github.com/tree-sitter/tree-sitter-ruby") \
(tsx "https://github.com/tree-sitter/tree-sitter-typescript" "master" "tsx/src") \
diff --git a/test/infra/Makefile.in b/test/infra/Makefile.in
index fff7281b566..5ae32e7e005 100644
--- a/test/infra/Makefile.in
+++ b/test/infra/Makefile.in
@@ -1,6 +1,6 @@
### @configure_input@
-# Copyright (C) 2021-2023 Free Software Foundation, Inc.
+# Copyright (C) 2021-2024 Free Software Foundation, Inc.
# This file is part of GNU Emacs.
diff --git a/test/infra/gitlab-ci.yml b/test/infra/gitlab-ci.yml
index 6884c32848e..5299aee746b 100644
--- a/test/infra/gitlab-ci.yml
+++ b/test/infra/gitlab-ci.yml
@@ -1,4 +1,4 @@
-# Copyright (C) 2017-2023 Free Software Foundation, Inc.
+# Copyright (C) 2017-2024 Free Software Foundation, Inc.
#
# This file is part of GNU Emacs.
#
@@ -193,10 +193,10 @@ default:
- if: '$CI_PIPELINE_SOURCE == "schedule"'
changes:
- "**.in"
- - lisp/emacs-lisp/comp.el
- - lisp/emacs-lisp/comp-cstr.el
+ - lisp/emacs-lisp/comp*.el
- src/comp.{h,m}
- test/infra/*
+ - test/lisp/emacs-lisp/comp*-tests.el
- test/src/comp-resources/*.el
- test/src/comp-tests.el
timeout: 8 hours
diff --git a/test/infra/test-jobs.yml b/test/infra/test-jobs.yml
index 2f6e0dab4d5..1f5d607eda4 100644
--- a/test/infra/test-jobs.yml
+++ b/test/infra/test-jobs.yml
@@ -580,6 +580,7 @@ test-src-inotify:
lisp/progmodes/go-ts-mode-tests.log
lisp/progmodes/heex-ts-mode-tests.log
lisp/progmodes/java-ts-mode-tests.log
+ lisp/progmodes/lua-ts-mode-tests.log
lisp/progmodes/ruby-ts-mode-tests.log
lisp/progmodes/typescript-ts-mode-tests.log
src/treesit-tests.log
diff --git a/test/lib-src/emacsclient-tests.el b/test/lib-src/emacsclient-tests.el
index 8e44f4fe4bf..d7001b0fe9b 100644
--- a/test/lib-src/emacsclient-tests.el
+++ b/test/lib-src/emacsclient-tests.el
@@ -1,6 +1,6 @@
;;; emacsclient-tests.el --- Test emacsclient -*- lexical-binding:t -*-
-;; Copyright (C) 2016-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2016-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/abbrev-tests.el b/test/lisp/abbrev-tests.el
index abac8dd6f0b..bfdfac8be1b 100644
--- a/test/lisp/abbrev-tests.el
+++ b/test/lisp/abbrev-tests.el
@@ -1,6 +1,6 @@
;;; abbrev-tests.el --- Test suite for abbrevs -*- lexical-binding: t; -*-
-;; Copyright (C) 2015-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2024 Free Software Foundation, Inc.
;; Author: Eli Zaretskii <eliz@gnu.org>
;; Keywords: abbrevs
diff --git a/test/lisp/align-resources/lua-ts-mode.erts b/test/lisp/align-resources/lua-ts-mode.erts
new file mode 100644
index 00000000000..b0473ad6cdf
--- /dev/null
+++ b/test/lisp/align-resources/lua-ts-mode.erts
@@ -0,0 +1,67 @@
+Name: align assignments
+
+=-=
+local first=1
+local s <const> =2
+local last=3
+=-=
+local first = 1
+local s <const> = 2
+local last = 3
+=-=-=
+
+Name: align fields
+
+=-=
+local Table={
+first=1,
+second=2,
+last=3,
+}
+=-=
+local Table = {
+ first = 1,
+ second = 2,
+ last = 3,
+}
+=-=-=
+
+Name: align comments
+
+=-=
+local first-- 1
+local second -- 2
+local last -- 3
+=-=
+local first -- 1
+local second -- 2
+local last -- 3
+=-=-=
+
+Name: align assignments and comments
+
+=-=
+local first=1-- one
+local second=2 -- two
+local last=3 -- three
+=-=
+local first = 1 -- one
+local second = 2 -- two
+local last = 3 -- three
+=-=-=
+
+Name: align fields and comments
+
+=-=
+local T={
+first=1,--one
+second=2, --two
+last=3, --three
+}
+=-=
+local T = {
+ first = 1, --one
+ second = 2, --two
+ last = 3, --three
+}
+=-=-=
diff --git a/test/lisp/align-tests.el b/test/lisp/align-tests.el
index a4d9303827f..cd309ea07bf 100644
--- a/test/lisp/align-tests.el
+++ b/test/lisp/align-tests.el
@@ -1,6 +1,6 @@
;;; align-tests.el --- Test suite for aligns -*- lexical-binding: t; -*-
-;; Copyright (C) 2015-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -49,6 +49,15 @@
(ert-test-erts-file (ert-resource-file "latex-mode.erts")
(test-align-transform-fun #'latex-mode)))
+(autoload 'treesit-ready-p "treesit")
+
+(ert-deftest align-lua ()
+ (skip-unless (treesit-ready-p 'lua))
+ (let ((comment-column 20)
+ (indent-tabs-mode nil))
+ (ert-test-erts-file (ert-resource-file "lua-ts-mode.erts")
+ (test-align-transform-fun #'lua-ts-mode))))
+
(ert-deftest align-python ()
(ert-test-erts-file (ert-resource-file "python-mode.erts")
(test-align-transform-fun #'python-mode)))
diff --git a/test/lisp/allout-tests.el b/test/lisp/allout-tests.el
index 9b70f86c09a..bdf159f54e4 100644
--- a/test/lisp/allout-tests.el
+++ b/test/lisp/allout-tests.el
@@ -1,6 +1,6 @@
;;; allout-tests.el --- Tests for allout.el -*- lexical-binding: t -*-
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/allout-widgets-tests.el b/test/lisp/allout-widgets-tests.el
index 67b796d69c5..24f5d3dc6b9 100644
--- a/test/lisp/allout-widgets-tests.el
+++ b/test/lisp/allout-widgets-tests.el
@@ -1,6 +1,6 @@
;;; allout-widgets-tests.el --- Tests for allout-widgets.el -*- lexical-binding: t -*-
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/ansi-color-tests.el b/test/lisp/ansi-color-tests.el
index 996a0512814..a1257a063f0 100644
--- a/test/lisp/ansi-color-tests.el
+++ b/test/lisp/ansi-color-tests.el
@@ -1,6 +1,6 @@
;;; ansi-color-tests.el --- Test suite for ansi-color -*- lexical-binding: t; -*-
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
;; Author: Pablo Barbáchano <pablob@amazon.com>
diff --git a/test/lisp/ansi-osc-tests.el b/test/lisp/ansi-osc-tests.el
index 616ea0d0d34..c0a5f3c640a 100644
--- a/test/lisp/ansi-osc-tests.el
+++ b/test/lisp/ansi-osc-tests.el
@@ -1,6 +1,6 @@
;;; osc-tests.el --- Tests for osc.el -*- lexical-binding: t; -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;; Author: Matthias Meulien <orontee@gmail.com>
;; Keywords:
diff --git a/test/lisp/apropos-tests.el b/test/lisp/apropos-tests.el
index c899087634b..fd484ca699c 100644
--- a/test/lisp/apropos-tests.el
+++ b/test/lisp/apropos-tests.el
@@ -1,6 +1,6 @@
;;; apropos-tests.el --- Tests for apropos.el -*- lexical-binding: t; -*-
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
;; Author: Simen Heggestøyl <simenheg@gmail.com>
;; Keywords:
diff --git a/test/lisp/arc-mode-tests.el b/test/lisp/arc-mode-tests.el
index c42fd8d432c..acc416d6f78 100644
--- a/test/lisp/arc-mode-tests.el
+++ b/test/lisp/arc-mode-tests.el
@@ -1,6 +1,6 @@
;;; arc-mode-tests.el --- Test suite for arc-mode. -*- lexical-binding: t -*-
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/auth-source-pass-tests.el b/test/lisp/auth-source-pass-tests.el
index ed14289bade..6455c3393d5 100644
--- a/test/lisp/auth-source-pass-tests.el
+++ b/test/lisp/auth-source-pass-tests.el
@@ -1,6 +1,6 @@
;;; auth-source-pass-tests.el --- Tests for auth-source-pass.el -*- lexical-binding: t; -*-
-;; Copyright (C) 2013, 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2013, 2017-2024 Free Software Foundation, Inc.
;; Author: Damien Cassou <damien.cassou@gmail.com>
diff --git a/test/lisp/auth-source-tests.el b/test/lisp/auth-source-tests.el
index ab1a437b303..5452501b861 100644
--- a/test/lisp/auth-source-tests.el
+++ b/test/lisp/auth-source-tests.el
@@ -1,6 +1,6 @@
;;; auth-source-tests.el --- Tests for auth-source.el -*- lexical-binding: t; -*-
-;; Copyright (C) 2015-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2024 Free Software Foundation, Inc.
;; Author: Damien Cassou <damien@cassou.me>,
;; Nicolas Petton <nicolas@petton.fr>
diff --git a/test/lisp/autoinsert-tests.el b/test/lisp/autoinsert-tests.el
index fc4e2bdab5b..8c2279d8371 100644
--- a/test/lisp/autoinsert-tests.el
+++ b/test/lisp/autoinsert-tests.el
@@ -1,6 +1,6 @@
;;; autoinsert-tests.el --- Tests for autoinsert.el -*- lexical-binding: t; -*-
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
;; Author: Simen Heggestøyl <simenheg@gmail.com>
;; Keywords:
diff --git a/test/lisp/autorevert-tests.el b/test/lisp/autorevert-tests.el
index 8dbb5d2a496..c202970e0b2 100644
--- a/test/lisp/autorevert-tests.el
+++ b/test/lisp/autorevert-tests.el
@@ -1,6 +1,6 @@
;;; autorevert-tests.el --- Tests of auto-revert -*- lexical-binding: t -*-
-;; Copyright (C) 2015-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2024 Free Software Foundation, Inc.
;; Author: Michael Albinus <michael.albinus@gmx.de>
@@ -257,7 +257,7 @@ This expects `auto-revert--messages' to be bound by
;; Repeated unpredictable failures, bug#32645.
:tags '(:unstable)
;; Unlikely to be hydra-specific?
- ;; (skip-unless (not (getenv "EMACS_HYDRA_CI")))
+ ;; (skip-when (getenv "EMACS_HYDRA_CI"))
(with-auto-revert-test
(ert-with-temp-file tmpfile
(let (;; Try to catch bug#32645.
diff --git a/test/lisp/battery-tests.el b/test/lisp/battery-tests.el
index e8fa1a6d017..f1796a4b628 100644
--- a/test/lisp/battery-tests.el
+++ b/test/lisp/battery-tests.el
@@ -1,6 +1,6 @@
;;; battery-tests.el --- tests for battery.el -*- lexical-binding: t -*-
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/bookmark-tests.el b/test/lisp/bookmark-tests.el
index 12a9f24e66e..b1eef38b165 100644
--- a/test/lisp/bookmark-tests.el
+++ b/test/lisp/bookmark-tests.el
@@ -1,6 +1,6 @@
;;; bookmark-tests.el --- Tests for bookmark.el -*- lexical-binding: t -*-
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
;; Author: Stefan Kangas <stefankangas@gmail.com>
diff --git a/test/lisp/buff-menu-tests.el b/test/lisp/buff-menu-tests.el
index b3a54093c54..c4817ad61c5 100644
--- a/test/lisp/buff-menu-tests.el
+++ b/test/lisp/buff-menu-tests.el
@@ -1,6 +1,6 @@
;;; buff-menu-tests.el --- Test suite for buff-menu.el -*- lexical-binding: t -*-
-;; Copyright (C) 2016-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2016-2024 Free Software Foundation, Inc.
;; Author: Tino Calancha <tino.calancha@gmail.com>
diff --git a/test/lisp/button-tests.el b/test/lisp/button-tests.el
index 46371b01f3f..b923b0ddd6a 100644
--- a/test/lisp/button-tests.el
+++ b/test/lisp/button-tests.el
@@ -1,6 +1,6 @@
;;; button-tests.el --- tests for button.el -*- lexical-binding: t -*-
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/calc/calc-tests.el b/test/lisp/calc/calc-tests.el
index 5b11dd950ba..a44a5898055 100644
--- a/test/lisp/calc/calc-tests.el
+++ b/test/lisp/calc/calc-tests.el
@@ -1,6 +1,6 @@
;;; calc-tests.el --- tests for calc -*- lexical-binding: t; -*-
-;; Copyright (C) 2014-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2014-2024 Free Software Foundation, Inc.
;; Author: Leo Liu <sdl.web@gmail.com>
;; Keywords: maint
@@ -816,5 +816,43 @@ An existing calc stack is reused, otherwise a new one is created."
(x (calc-tests--calc-to-number (math-pow 8 '(frac 1 6)))))
(should (< (abs (- x (sqrt 2.0))) 1.0e-10))))
+(require 'calc-aent)
+
+(ert-deftest calc-math-read-preprocess-string ()
+ "Test replacement of allowed special Unicode symbols."
+ ;; ... doesn't change an empty string
+ (should (string= "" (math-read-preprocess-string "")))
+ ;; ... doesn't change a string without characters from
+ ;; ‘math-read-replacement-list’
+ (let ((str "don't replace here"))
+ (should (string= str (math-read-preprocess-string str))))
+ ;; ... replaces irrespective of position in input string
+ (should (string= "^(1)" (math-read-preprocess-string "¹")))
+ (should (string= "some^(1)" (math-read-preprocess-string "some¹")))
+ (should (string= "^(1)time" (math-read-preprocess-string "¹time")))
+ (should (string= "some^(1)else" (math-read-preprocess-string "some¹else")))
+ ;; ... replaces every element of ‘math-read-replacement-list’ correctly,
+ ;; in particular combining consecutive super-/subscripts into one
+ ;; exponent/subscript
+ (should (string= (concat "+/-*:-/*inf<=>=<=>=μ(1:4)(1:2)(3:4)(1:3)(2:3)"
+ "(1:5)(2:5)(3:5)(4:5)(1:6)(5:6)"
+ "(1:8)(3:8)(5:8)(7:8)1:^(0123456789+-()ni)"
+ "_(0123456789+-())")
+ (math-read-preprocess-string
+ (mapconcat #'car math-read-replacement-list))))
+ ;; ... replaces strings of more than a single character correctly
+ (let ((math-read-replacement-list (append
+ math-read-replacement-list
+ '(("𝚤𝚥" "ij"))
+ '(("¼½" "(1:4)(1:2)")))))
+ (should (string= "(1:4)(1:2)ij"
+ (math-read-preprocess-string "¼½𝚤𝚥"))))
+ ;; ... handles an empty replacement list gracefully
+ (let ((math-read-replacement-list '()))
+ (should (string= "¼" (math-read-preprocess-string "¼"))))
+ ;; ... signals an error if the argument is not a string
+ (should-error (math-read-preprocess-string nil))
+ (should-error (math-read-preprocess-string 42)))
+
(provide 'calc-tests)
;;; calc-tests.el ends here
diff --git a/test/lisp/calculator-tests.el b/test/lisp/calculator-tests.el
index 8786d5c6c3b..5b485fe6dc5 100644
--- a/test/lisp/calculator-tests.el
+++ b/test/lisp/calculator-tests.el
@@ -1,6 +1,6 @@
;;; calculator-tests.el --- Test suite for calculator. -*- lexical-binding: t -*-
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/calendar/cal-french-tests.el b/test/lisp/calendar/cal-french-tests.el
index aad0eae5514..160bbe6ce1c 100644
--- a/test/lisp/calendar/cal-french-tests.el
+++ b/test/lisp/calendar/cal-french-tests.el
@@ -1,6 +1,6 @@
;;; cal-french-tests.el --- tests for cal-french.el -*- lexical-binding: t -*-
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/calendar/cal-julian-tests.el b/test/lisp/calendar/cal-julian-tests.el
index 4207d1ee285..072087e70a7 100644
--- a/test/lisp/calendar/cal-julian-tests.el
+++ b/test/lisp/calendar/cal-julian-tests.el
@@ -1,6 +1,6 @@
;;; cal-julian-tests.el --- tests for calendar/cal-julian.el -*- lexical-binding:t -*-
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
;; Author: Stefan Kangas <stefankangas@gmail.com>
diff --git a/test/lisp/calendar/icalendar-tests.el b/test/lisp/calendar/icalendar-tests.el
index 9071607005d..7d3af25ea49 100644
--- a/test/lisp/calendar/icalendar-tests.el
+++ b/test/lisp/calendar/icalendar-tests.el
@@ -1,6 +1,6 @@
;;; icalendar-tests.el --- Test suite for icalendar.el -*- lexical-binding:t -*-
-;; Copyright (C) 2005, 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2005, 2008-2024 Free Software Foundation, Inc.
;; Author: Ulf Jasper <ulf.jasper@web.de>
;; Created: March 2005
diff --git a/test/lisp/calendar/iso8601-tests.el b/test/lisp/calendar/iso8601-tests.el
index f68ea2a4e4d..aef221df7a0 100644
--- a/test/lisp/calendar/iso8601-tests.el
+++ b/test/lisp/calendar/iso8601-tests.el
@@ -1,6 +1,6 @@
;;; iso8601-tests.el --- tests for calendar/iso8601.el -*- lexical-binding:t -*-
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/calendar/lunar-tests.el b/test/lisp/calendar/lunar-tests.el
index e19965d1034..d9f6f6ca56a 100644
--- a/test/lisp/calendar/lunar-tests.el
+++ b/test/lisp/calendar/lunar-tests.el
@@ -1,6 +1,6 @@
;;; lunar-tests.el --- tests for calendar/lunar.el -*- lexical-binding:t -*-
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
;; Author: Stefan Kangas <stefankangas@gmail.com>
diff --git a/test/lisp/calendar/parse-time-tests.el b/test/lisp/calendar/parse-time-tests.el
index 95f1b83d851..5db0035e7bf 100644
--- a/test/lisp/calendar/parse-time-tests.el
+++ b/test/lisp/calendar/parse-time-tests.el
@@ -1,6 +1,6 @@
;;; parse-time-tests.el --- Test suite for parse-time.el -*- lexical-binding:t -*-
-;; Copyright (C) 2016-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2016-2024 Free Software Foundation, Inc.
;; Author: Lars Ingebrigtsen <larsi@gnus.org>
diff --git a/test/lisp/calendar/solar-tests.el b/test/lisp/calendar/solar-tests.el
index 1f1ad0578f6..4b1417b3ba8 100644
--- a/test/lisp/calendar/solar-tests.el
+++ b/test/lisp/calendar/solar-tests.el
@@ -1,6 +1,6 @@
;;; solar-tests.el --- tests for solar.el -*- lexical-binding: t -*-
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/calendar/time-date-tests.el b/test/lisp/calendar/time-date-tests.el
index 53afd372057..01f9f8a5108 100644
--- a/test/lisp/calendar/time-date-tests.el
+++ b/test/lisp/calendar/time-date-tests.el
@@ -1,6 +1,6 @@
;;; time-date-tests.el --- tests for calendar/time-date.el -*- lexical-binding:t -*-
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/calendar/todo-mode-tests.el b/test/lisp/calendar/todo-mode-tests.el
index 3b49dd56b69..8c76792ec41 100644
--- a/test/lisp/calendar/todo-mode-tests.el
+++ b/test/lisp/calendar/todo-mode-tests.el
@@ -1,6 +1,6 @@
;;; todo-mode-tests.el --- tests for todo-mode.el -*- lexical-binding: t; -*-
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
;; Author: Stephen Berman <stephen.berman@gmx.net>
;; Keywords: calendar
diff --git a/test/lisp/cedet/cedet-files-tests.el b/test/lisp/cedet/cedet-files-tests.el
index 751101065ba..d10dad4be24 100644
--- a/test/lisp/cedet/cedet-files-tests.el
+++ b/test/lisp/cedet/cedet-files-tests.el
@@ -1,6 +1,6 @@
;;; cedet-files-tests.el --- Tests for cedet-files.el -*- lexical-binding:t -*-
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/test/lisp/cedet/semantic-utest-c.el b/test/lisp/cedet/semantic-utest-c.el
index 2569c1c9478..05ad47976c3 100644
--- a/test/lisp/cedet/semantic-utest-c.el
+++ b/test/lisp/cedet/semantic-utest-c.el
@@ -1,6 +1,6 @@
;;; semantic-utest-c.el --- C based parsing tests. -*- lexical-binding:t -*-
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/test/lisp/cedet/semantic-utest-ia-resources/test.srt b/test/lisp/cedet/semantic-utest-ia-resources/test.srt
index b1094ffb52f..69c3b772812 100644
--- a/test/lisp/cedet/semantic-utest-ia-resources/test.srt
+++ b/test/lisp/cedet/semantic-utest-ia-resources/test.srt
@@ -1,6 +1,6 @@
;; test.srt --- unit test support file for semantic-utest-ia
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/test/lisp/cedet/semantic-utest-ia-resources/testdoublens.cpp b/test/lisp/cedet/semantic-utest-ia-resources/testdoublens.cpp
index e192c4f7f83..e7b4d06e7a2 100644
--- a/test/lisp/cedet/semantic-utest-ia-resources/testdoublens.cpp
+++ b/test/lisp/cedet/semantic-utest-ia-resources/testdoublens.cpp
@@ -1,6 +1,6 @@
// testdoublens.cpp --- semantic-ia-utest completion engine unit tests
-// Copyright (C) 2008-2023 Free Software Foundation, Inc.
+// Copyright (C) 2008-2024 Free Software Foundation, Inc.
// Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/test/lisp/cedet/semantic-utest-ia-resources/testdoublens.hpp b/test/lisp/cedet/semantic-utest-ia-resources/testdoublens.hpp
index 5c55a0fc6f0..580a023f6cb 100644
--- a/test/lisp/cedet/semantic-utest-ia-resources/testdoublens.hpp
+++ b/test/lisp/cedet/semantic-utest-ia-resources/testdoublens.hpp
@@ -1,6 +1,6 @@
// testdoublens.hpp --- Header file used in one of the Semantic tests
-// Copyright (C) 2008-2023 Free Software Foundation, Inc.
+// Copyright (C) 2008-2024 Free Software Foundation, Inc.
// Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/test/lisp/cedet/semantic-utest-ia-resources/testjavacomp.java b/test/lisp/cedet/semantic-utest-ia-resources/testjavacomp.java
index 639ed95e9da..43c3ee8290c 100644
--- a/test/lisp/cedet/semantic-utest-ia-resources/testjavacomp.java
+++ b/test/lisp/cedet/semantic-utest-ia-resources/testjavacomp.java
@@ -1,6 +1,6 @@
// testjavacomp.java --- Semantic unit test for Java
-// Copyright (C) 2009-2023 Free Software Foundation, Inc.
+// Copyright (C) 2009-2024 Free Software Foundation, Inc.
// Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/test/lisp/cedet/semantic-utest-ia-resources/testlocalvars.cpp b/test/lisp/cedet/semantic-utest-ia-resources/testlocalvars.cpp
index fbe20dade9c..f43e61eb45d 100644
--- a/test/lisp/cedet/semantic-utest-ia-resources/testlocalvars.cpp
+++ b/test/lisp/cedet/semantic-utest-ia-resources/testlocalvars.cpp
@@ -1,6 +1,6 @@
// testlocalvars.java --- Semantic unit test for Java
-// Copyright (C) 2009-2023 Free Software Foundation, Inc.
+// Copyright (C) 2009-2024 Free Software Foundation, Inc.
// Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/test/lisp/cedet/semantic-utest-ia-resources/testnsp.cpp b/test/lisp/cedet/semantic-utest-ia-resources/testnsp.cpp
index e88bd37c808..9881243269c 100644
--- a/test/lisp/cedet/semantic-utest-ia-resources/testnsp.cpp
+++ b/test/lisp/cedet/semantic-utest-ia-resources/testnsp.cpp
@@ -1,6 +1,6 @@
/* testnsp.cpp --- semantic-ia-utest completion engine unit tests
- Copyright (C) 2008-2023 Free Software Foundation, Inc.
+ Copyright (C) 2008-2024 Free Software Foundation, Inc.
Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/test/lisp/cedet/semantic-utest-ia-resources/testsppcomplete.c b/test/lisp/cedet/semantic-utest-ia-resources/testsppcomplete.c
index 2458bf433aa..1c8efe9082e 100644
--- a/test/lisp/cedet/semantic-utest-ia-resources/testsppcomplete.c
+++ b/test/lisp/cedet/semantic-utest-ia-resources/testsppcomplete.c
@@ -1,6 +1,6 @@
/* testesppcomplete.cpp --- semantic-ia-utest completion engine unit tests
- Copyright (C) 2008-2023 Free Software Foundation, Inc.
+ Copyright (C) 2008-2024 Free Software Foundation, Inc.
Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/test/lisp/cedet/semantic-utest-ia-resources/teststruct.cpp b/test/lisp/cedet/semantic-utest-ia-resources/teststruct.cpp
index 894f53754ea..c06f4b35c25 100644
--- a/test/lisp/cedet/semantic-utest-ia-resources/teststruct.cpp
+++ b/test/lisp/cedet/semantic-utest-ia-resources/teststruct.cpp
@@ -1,6 +1,6 @@
// teststruct.cpp --- semantic-ia-utest completion engine unit tests
-// Copyright (C) 2008-2023 Free Software Foundation, Inc.
+// Copyright (C) 2008-2024 Free Software Foundation, Inc.
// Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/test/lisp/cedet/semantic-utest-ia-resources/testsubclass.cpp b/test/lisp/cedet/semantic-utest-ia-resources/testsubclass.cpp
index a507f1bf418..30971feef61 100644
--- a/test/lisp/cedet/semantic-utest-ia-resources/testsubclass.cpp
+++ b/test/lisp/cedet/semantic-utest-ia-resources/testsubclass.cpp
@@ -1,6 +1,6 @@
// testsubclass.cpp --- unit test for analyzer and complex C++ inheritance
-// Copyright (C) 2007-2023 Free Software Foundation, Inc.
+// Copyright (C) 2007-2024 Free Software Foundation, Inc.
// Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/test/lisp/cedet/semantic-utest-ia-resources/testsubclass.hh b/test/lisp/cedet/semantic-utest-ia-resources/testsubclass.hh
index a6c31ac8fab..79e12f2fe27 100644
--- a/test/lisp/cedet/semantic-utest-ia-resources/testsubclass.hh
+++ b/test/lisp/cedet/semantic-utest-ia-resources/testsubclass.hh
@@ -1,6 +1,6 @@
// testsubclass.hh --- unit test for analyzer and complex C++ inheritance
-// Copyright (C) 2007-2023 Free Software Foundation, Inc.
+// Copyright (C) 2007-2024 Free Software Foundation, Inc.
// Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/test/lisp/cedet/semantic-utest-ia-resources/testtemplates.cpp b/test/lisp/cedet/semantic-utest-ia-resources/testtemplates.cpp
index f4c48edd562..b3c64ba8574 100644
--- a/test/lisp/cedet/semantic-utest-ia-resources/testtemplates.cpp
+++ b/test/lisp/cedet/semantic-utest-ia-resources/testtemplates.cpp
@@ -1,6 +1,6 @@
// testtemplates.cpp --- semantic-ia-utest completion engine unit tests
-// Copyright (C) 2008-2023 Free Software Foundation, Inc.
+// Copyright (C) 2008-2024 Free Software Foundation, Inc.
// Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/test/lisp/cedet/semantic-utest-ia-resources/testtypedefs.cpp b/test/lisp/cedet/semantic-utest-ia-resources/testtypedefs.cpp
index 13f0f288212..b0bf22d16c2 100644
--- a/test/lisp/cedet/semantic-utest-ia-resources/testtypedefs.cpp
+++ b/test/lisp/cedet/semantic-utest-ia-resources/testtypedefs.cpp
@@ -1,6 +1,6 @@
// testtypedefs.cpp --- Sample with some fake bits out of std::string
-// Copyright (C) 2008-2023 Free Software Foundation, Inc.
+// Copyright (C) 2008-2024 Free Software Foundation, Inc.
// Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/test/lisp/cedet/semantic-utest-ia-resources/testusing.cpp b/test/lisp/cedet/semantic-utest-ia-resources/testusing.cpp
index 940e7caa0cf..a0e763f072a 100644
--- a/test/lisp/cedet/semantic-utest-ia-resources/testusing.cpp
+++ b/test/lisp/cedet/semantic-utest-ia-resources/testusing.cpp
@@ -1,6 +1,6 @@
// testusing.cpp --- semantic-ia-utest completion engine unit tests
-// Copyright (C) 2008-2023 Free Software Foundation, Inc.
+// Copyright (C) 2008-2024 Free Software Foundation, Inc.
// Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/test/lisp/cedet/semantic-utest-ia-resources/testusing.hh b/test/lisp/cedet/semantic-utest-ia-resources/testusing.hh
index 1effa00686d..bb130732fec 100644
--- a/test/lisp/cedet/semantic-utest-ia-resources/testusing.hh
+++ b/test/lisp/cedet/semantic-utest-ia-resources/testusing.hh
@@ -1,6 +1,6 @@
// testusing.hh --- semantic-ia-utest completion engine unit tests
-// Copyright (C) 2008-2023 Free Software Foundation, Inc.
+// Copyright (C) 2008-2024 Free Software Foundation, Inc.
// Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/test/lisp/cedet/semantic-utest-ia-resources/testvarnames.c b/test/lisp/cedet/semantic-utest-ia-resources/testvarnames.c
index f8202296385..b027bd24d20 100644
--- a/test/lisp/cedet/semantic-utest-ia-resources/testvarnames.c
+++ b/test/lisp/cedet/semantic-utest-ia-resources/testvarnames.c
@@ -1,6 +1,6 @@
/* testvarnames.cpp --- semantic-ia-utest completion engine unit tests
- Copyright (C) 2008-2023 Free Software Foundation, Inc.
+ Copyright (C) 2008-2024 Free Software Foundation, Inc.
Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/test/lisp/cedet/semantic-utest-ia-resources/testvarnames.java b/test/lisp/cedet/semantic-utest-ia-resources/testvarnames.java
index 8934bb8d97d..1e4df4956f7 100644
--- a/test/lisp/cedet/semantic-utest-ia-resources/testvarnames.java
+++ b/test/lisp/cedet/semantic-utest-ia-resources/testvarnames.java
@@ -1,6 +1,6 @@
// testvarnames.java --- Semantic unit test for Java
-// Copyright (C) 2009-2023 Free Software Foundation, Inc.
+// Copyright (C) 2009-2024 Free Software Foundation, Inc.
// Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/test/lisp/cedet/semantic-utest-ia-resources/testwisent.wy b/test/lisp/cedet/semantic-utest-ia-resources/testwisent.wy
index e00f2eb102e..8e260fe974a 100644
--- a/test/lisp/cedet/semantic-utest-ia-resources/testwisent.wy
+++ b/test/lisp/cedet/semantic-utest-ia-resources/testwisent.wy
@@ -1,6 +1,6 @@
;; testwisent.wy --- unit test support file for semantic-utest-ia
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/test/lisp/cedet/semantic-utest-ia.el b/test/lisp/cedet/semantic-utest-ia.el
index f2b2dbc5a7d..ed18b41770d 100644
--- a/test/lisp/cedet/semantic-utest-ia.el
+++ b/test/lisp/cedet/semantic-utest-ia.el
@@ -1,6 +1,6 @@
;;; semantic-utest-ia.el --- Analyzer unit tests -*- lexical-binding:t -*-
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/test/lisp/cedet/semantic-utest.el b/test/lisp/cedet/semantic-utest.el
index f53b7c41005..ca338a60046 100644
--- a/test/lisp/cedet/semantic-utest.el
+++ b/test/lisp/cedet/semantic-utest.el
@@ -1,6 +1,6 @@
;;; semantic-utest.el --- Tests for semantic's parsing system. -*- lexical-binding:t -*-
-;; Copyright (C) 2003-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/test/lisp/cedet/semantic/bovine/gcc-tests.el b/test/lisp/cedet/semantic/bovine/gcc-tests.el
index 5437d65d139..bfdf2a22286 100644
--- a/test/lisp/cedet/semantic/bovine/gcc-tests.el
+++ b/test/lisp/cedet/semantic/bovine/gcc-tests.el
@@ -1,6 +1,6 @@
;;; gcc-tests.el --- Tests for semantic/bovine/gcc.el -*- lexical-binding:t -*-
-;; Copyright (C) 2003-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
@@ -31,62 +31,88 @@
;;; From bovine-gcc:
-;; Example output of "gcc -v"
-(defvar semantic-gcc-test-strings
- '(;; My old box:
- "Reading specs from /usr/lib/gcc-lib/i386-redhat-linux/3.2.2/specs
+(defmacro semantic-gcc-test (str)
+ `(let ((fields (semantic-gcc-fields ,str)))
+ (let-alist fields
+ (message "%S" fields)
+ ;; No longer test for prefixes.
+ ;; (should .--prefix)
+ (should .version)
+ (should (or .target
+ .--target
+ .--host)))))
+
+;; A bunch of sample gcc -v outputs from different machines.
+
+(ert-deftest semantic-gcc-test/1 ()
+ ;; My old box:
+ (semantic-gcc-test "Reading specs from /usr/lib/gcc-lib/i386-redhat-linux/3.2.2/specs
Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --enable-shared --enable-threads=posix --disable-checking --with-system-zlib --enable-__cxa_atexit --host=i386-redhat-linux
Thread model: posix
-gcc version 3.2.2 20030222 (Red Hat Linux 3.2.2-5)"
- ;; Alex Ott:
- "Using built-in specs.
+gcc version 3.2.2 20030222 (Red Hat Linux 3.2.2-5)"))
+
+(ert-deftest semantic-gcc-test/2 ()
+ ;; Alex Ott:
+ (semantic-gcc-test "Using built-in specs.
Target: i486-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 4.3.1-9ubuntu1' --with-bugurl=file:///usr/share/doc/gcc-4.3/README.Bugs --enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr --enable-shared --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --enable-nls --with-gxx-include-dir=/usr/include/c++/4.3 --program-suffix=-4.3 --enable-clocale=gnu --enable-libstdcxx-debug --enable-objc-gc --enable-mpfr --enable-targets=all --enable-checking=release --build=i486-linux-gnu --host=i486-linux-gnu --target=i486-linux-gnu
Thread model: posix
-gcc version 4.3.1 (Ubuntu 4.3.1-9ubuntu1)"
- ;; My debian box:
- "Using built-in specs.
+gcc version 4.3.1 (Ubuntu 4.3.1-9ubuntu1)"))
+
+(ert-deftest semantic-gcc-test/3 ()
+ ;; My Debian box:
+ (semantic-gcc-test "Using built-in specs.
Target: x86_64-unknown-linux-gnu
Configured with: ../../../sources/gcc/configure --prefix=/usr/local/glibc-2.3.6/x86_64/apps/gcc-4.2.3 --with-gmp=/usr/local/gcc/gmp --with-mpfr=/usr/local/gcc/mpfr --enable-languages=c,c++,fortran --with-as=/usr/local/glibc-2.3.6/x86_64/apps/gcc-4.2.3/bin/as --with-ld=/usr/local/glibc-2.3.6/x86_64/apps/gcc-4.2.3/bin/ld --disable-multilib
Thread model: posix
-gcc version 4.2.3"
- ;; My mac:
- "Using built-in specs.
+gcc version 4.2.3"))
+
+(ert-deftest semantic-gcc-test/4 ()
+ ;; My mac:
+ (semantic-gcc-test "Using built-in specs.
Target: i686-apple-darwin8
Configured with: /private/var/tmp/gcc/gcc-5341.obj~1/src/configure --disable-checking -enable-werror --prefix=/usr --mandir=/share/man --enable-languages=c,objc,c++,obj-c++ --program-transform-name=/^[cg][^.-]*$/s/$/-4.0/ --with-gxx-include-dir=/include/c++/4.0.0 --with-slibdir=/usr/lib --build=powerpc-apple-darwin8 --with-arch=pentium-m --with-tune=prescott --program-prefix= --host=i686-apple-darwin8 --target=i686-apple-darwin8
Thread model: posix
-gcc version 4.0.1 (Apple Computer, Inc. build 5341)"
- ;; Ubuntu Intrepid
- "Using built-in specs.
+gcc version 4.0.1 (Apple Computer, Inc. build 5341)"))
+
+(ert-deftest semantic-gcc-test/5 ()
+ ;; Ubuntu Intrepid
+ (semantic-gcc-test "Using built-in specs.
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 4.3.2-1ubuntu12' --with-bugurl=file:///usr/share/doc/gcc-4.3/README.Bugs --enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr --enable-shared --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --enable-nls --with-gxx-include-dir=/usr/include/c++/4.3 --program-suffix=-4.3 --enable-clocale=gnu --enable-libstdcxx-debug --enable-objc-gc --enable-mpfr --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
Thread model: posix
-gcc version 4.3.2 (Ubuntu 4.3.2-1ubuntu12)"
- ;; Red Hat EL4
- "Reading specs from /usr/lib/gcc/x86_64-redhat-linux/3.4.6/specs
+gcc version 4.3.2 (Ubuntu 4.3.2-1ubuntu12)"))
+
+(ert-deftest semantic-gcc-test/6 ()
+ ;; Red Hat EL4
+ (semantic-gcc-test "Reading specs from /usr/lib/gcc/x86_64-redhat-linux/3.4.6/specs
Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --enable-shared --enable-threads=posix --disable-checking --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-java-awt=gtk --host=x86_64-redhat-linux
Thread model: posix
-gcc version 3.4.6 20060404 (Red Hat 3.4.6-10)"
- ;; Red Hat EL5
- "Using built-in specs.
+gcc version 3.4.6 20060404 (Red Hat 3.4.6-10)"))
+
+(ert-deftest semantic-gcc-test/7 ()
+ ;; Red Hat EL5
+ (semantic-gcc-test "Using built-in specs.
Target: x86_64-redhat-linux
Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-libgcj-multifile --enable-languages=c,c++,objc,obj-c++,java,fortran,ada --enable-java-awt=gtk --disable-dssi --enable-plugin --with-java-home=/usr/lib/jvm/java-1.4.2-gcj-1.4.2.0/jre --with-cpu=generic --host=x86_64-redhat-linux
Thread model: posix
-gcc version 4.1.2 20080704 (Red Hat 4.1.2-44)"
- ;; David Engster's german gcc on ubuntu 4.3
- "Es werden eingebaute Spezifikationen verwendet.
+gcc version 4.1.2 20080704 (Red Hat 4.1.2-44)"))
+
+(ert-deftest semantic-gcc-test/8 ()
+ ;; David Engster's german gcc on ubuntu 4.3
+ (semantic-gcc-test "Es werden eingebaute Spezifikationen verwendet.
Ziel: i486-linux-gnu
Konfiguriert mit: ../src/configure -v --with-pkgversion='Ubuntu 4.3.2-1ubuntu12' --with-bugurl=file:///usr/share/doc/gcc-4.3/README.Bugs --enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr --enable-shared --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --enable-nls --with-gxx-include-dir=/usr/include/c++/4.3 --program-suffix=-4.3 --enable-clocale=gnu --enable-libstdcxx-debug --enable-objc-gc --enable-mpfr --enable-targets=all --enable-checking=release --build=i486-linux-gnu --host=i486-linux-gnu --target=i486-linux-gnu
Thread-Modell: posix
-gcc-Version 4.3.2 (Ubuntu 4.3.2-1ubuntu12)"
- ;; Damien Deville bsd
- "Using built-in specs.
+gcc-Version 4.3.2 (Ubuntu 4.3.2-1ubuntu12)"))
+
+(ert-deftest semantic-gcc-test/9 ()
+ ;; Damien Deville bsd
+ (semantic-gcc-test "Using built-in specs.
Target: i386-undermydesk-freebsd
Configured with: FreeBSD/i386 system compiler
Thread model: posix
-gcc version 4.2.1 20070719 [FreeBSD]"
- )
- "A bunch of sample gcc -v outputs from different machines.")
+gcc version 4.2.1 20070719 [FreeBSD]"))
(defvar semantic-gcc-test-strings-fail
'(;; A really old solaris box I found
@@ -95,19 +121,8 @@ gcc version 2.95.2 19991024 (release)"
)
"A bunch of sample gcc -v outputs that fail to provide the info we want.")
-(defun semantic-gcc-test-output-parser ()
+(ert-deftest semantic-gcc-test-output-parser/fail ()
"Test the output parser against some collected strings."
- (dolist (S semantic-gcc-test-strings)
- (let* ((fields (semantic-gcc-fields S))
- (v (cdr (assoc 'version fields)))
- (h (or (cdr (assoc 'target fields))
- (cdr (assoc '--target fields))
- (cdr (assoc '--host fields))))
- (p (cdr (assoc '--prefix fields))))
- ;; No longer test for prefixes.
- (when (not (and v h))
- (let ((strs (split-string S "\n")))
- (error "Test failed on %S\nV H P:\n%S %S %S" (car strs) v h p)))))
(dolist (S semantic-gcc-test-strings-fail)
(let* ((fields (semantic-gcc-fields S))
(v (cdr (assoc 'version fields)))
@@ -118,14 +133,10 @@ gcc version 2.95.2 19991024 (release)"
(when (and v h p)
(error "Negative test failed on %S" S)))))
-(ert-deftest semantic-gcc-test-output-parser ()
- (semantic-gcc-test-output-parser))
-
-(ert-deftest semantic-gcc-test-output-parser-this-machine ()
+(ert-deftest semantic-gcc-test-output-parser/this-machine ()
"Test the output parser against the machine currently running Emacs."
(skip-unless (and (executable-find "gcc")
(not (ert-gcc-is-clang-p))))
- (let ((semantic-gcc-test-strings (list (semantic-gcc-query "gcc" "-v"))))
- (semantic-gcc-test-output-parser)))
+ (semantic-gcc-test (semantic-gcc-query "gcc" "-v")))
;;; gcc-tests.el ends here
diff --git a/test/lisp/cedet/semantic/format-resources/test-fmt.cpp b/test/lisp/cedet/semantic/format-resources/test-fmt.cpp
index 3b04542dcc1..211d9e28092 100644
--- a/test/lisp/cedet/semantic/format-resources/test-fmt.cpp
+++ b/test/lisp/cedet/semantic/format-resources/test-fmt.cpp
@@ -1,6 +1,6 @@
/** test-fmt.cpp --- Signatures, and format answers for testing
*
- * Copyright (C) 2012, 2016, 2019-2023 Free Software Foundation, Inc.
+ * Copyright (C) 2012, 2016, 2019-2024 Free Software Foundation, Inc.
*
* Author: Eric M. Ludlam <zappo@gnu.org>
*
diff --git a/test/lisp/cedet/semantic/format-resources/test-fmt.el b/test/lisp/cedet/semantic/format-resources/test-fmt.el
index 3cef50e2395..a1bfdd0333d 100644
--- a/test/lisp/cedet/semantic/format-resources/test-fmt.el
+++ b/test/lisp/cedet/semantic/format-resources/test-fmt.el
@@ -1,6 +1,6 @@
;;; test-fmt.el --- test semantic tag formatting -*- lexical-binding: t -*-
-;; Copyright (C) 2012-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2012-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/test/lisp/cedet/semantic/format-tests.el b/test/lisp/cedet/semantic/format-tests.el
index cc2bcc40ae3..3b922355d76 100644
--- a/test/lisp/cedet/semantic/format-tests.el
+++ b/test/lisp/cedet/semantic/format-tests.el
@@ -1,6 +1,6 @@
;;; semantic/format-tests.el --- Parsing / Formatting tests -*- lexical-binding:t -*-
-;; Copyright (C) 2003-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/test/lisp/cedet/semantic/fw-tests.el b/test/lisp/cedet/semantic/fw-tests.el
index 6da2632aa39..0363ef4f657 100644
--- a/test/lisp/cedet/semantic/fw-tests.el
+++ b/test/lisp/cedet/semantic/fw-tests.el
@@ -1,6 +1,6 @@
;;; fw-tests.el --- Tests for semantic/fw.el -*- lexical-binding:t -*-
-;; Copyright (C) 2003-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/test/lisp/cedet/srecode-utest-getset.el b/test/lisp/cedet/srecode-utest-getset.el
index c3c1e41c3d2..bfdae2d4c86 100644
--- a/test/lisp/cedet/srecode-utest-getset.el
+++ b/test/lisp/cedet/srecode-utest-getset.el
@@ -1,6 +1,6 @@
;;; srecode/test-getset.el --- Test the getset inserter. -*- lexical-binding:t -*-
-;; Copyright (C) 2008-2009, 2011, 2019-2023 Free Software Foundation,
+;; Copyright (C) 2008-2009, 2011, 2019-2024 Free Software Foundation,
;; Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/cedet/srecode-utest-template.el b/test/lisp/cedet/srecode-utest-template.el
index a43ea43ba30..37ddc57cc39 100644
--- a/test/lisp/cedet/srecode-utest-template.el
+++ b/test/lisp/cedet/srecode-utest-template.el
@@ -1,6 +1,6 @@
;;; srecode-utest-template.el --- SRecode Core Template tests. -*- lexical-binding:t -*-
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/cedet/srecode/document-tests.el b/test/lisp/cedet/srecode/document-tests.el
index b5f7f83e0cb..3f6f6adae73 100644
--- a/test/lisp/cedet/srecode/document-tests.el
+++ b/test/lisp/cedet/srecode/document-tests.el
@@ -1,6 +1,6 @@
;;; document-tests.el --- Tests for srecode/document.el -*- lexical-binding:t -*-
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/test/lisp/cedet/srecode/fields-tests.el b/test/lisp/cedet/srecode/fields-tests.el
index 21c2b329120..8b195bdcf71 100644
--- a/test/lisp/cedet/srecode/fields-tests.el
+++ b/test/lisp/cedet/srecode/fields-tests.el
@@ -1,6 +1,6 @@
;;; srecode/fields-tests.el --- Tests for srecode/fields.el -*- lexical-binding: t -*-
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/test/lisp/char-fold-tests.el b/test/lisp/char-fold-tests.el
index 6e265a5eb27..9a44ce11205 100644
--- a/test/lisp/char-fold-tests.el
+++ b/test/lisp/char-fold-tests.el
@@ -1,6 +1,6 @@
;;; char-fold-tests.el --- Tests for char-fold.el -*- lexical-binding: t; -*-
-;; Copyright (C) 2013-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2024 Free Software Foundation, Inc.
;; Author: Artur Malabarba <bruce.connor.am@gmail.com>
diff --git a/test/lisp/color-tests.el b/test/lisp/color-tests.el
index d47373bf023..9b6b8c1f8dc 100644
--- a/test/lisp/color-tests.el
+++ b/test/lisp/color-tests.el
@@ -1,6 +1,6 @@
;;; color-tests.el --- Tests for color.el -*- lexical-binding: t; -*-
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
;; Author: Simen Heggestøyl <simenheg@gmail.com>
;; Keywords:
diff --git a/test/lisp/comint-tests.el b/test/lisp/comint-tests.el
index 6d435908b35..10a4ff34239 100644
--- a/test/lisp/comint-tests.el
+++ b/test/lisp/comint-tests.el
@@ -1,6 +1,6 @@
;;; comint-tests.el --- Tests for comint.el -*- lexical-binding:t -*-
-;; Copyright (C) 2010-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2010-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/completion-preview-tests.el b/test/lisp/completion-preview-tests.el
new file mode 100644
index 00000000000..190764e9125
--- /dev/null
+++ b/test/lisp/completion-preview-tests.el
@@ -0,0 +1,184 @@
+;;; completion-preview-tests.el --- tests for completion-preview.el -*- lexical-binding: t -*-
+
+;; Copyright (C) 2023-2024 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert)
+(require 'completion-preview)
+
+(defun completion-preview-tests--capf (completions &rest props)
+ (lambda ()
+ (when-let ((bounds (bounds-of-thing-at-point 'symbol)))
+ (append (list (car bounds) (cdr bounds) completions) props))))
+
+(defun completion-preview-tests--check-preview (string &optional exact)
+ "Check that the completion preview is showing STRING.
+
+If EXACT is non-nil, check that STRING has the
+`completion-preview-exact' face. Otherwise check that STRING has
+the `completion-preview' face.
+
+If STRING is nil, check that there is no completion preview
+instead."
+ (if (not string)
+ (should (not completion-preview--overlay))
+ (should completion-preview--overlay)
+ (let ((after-string (completion-preview--get 'after-string)))
+ (should (string= after-string string))
+ (should (eq (get-text-property 0 'face after-string)
+ (if exact
+ 'completion-preview-exact
+ 'completion-preview))))))
+
+(ert-deftest completion-preview ()
+ "Test Completion Preview mode."
+ (with-temp-buffer
+ (setq-local completion-at-point-functions
+ (list (completion-preview-tests--capf '("foobarbaz"))))
+
+ (insert "foo")
+ (let ((this-command 'self-insert-command))
+ (completion-preview--post-command))
+
+ ;; Exact match
+ (completion-preview-tests--check-preview "barbaz" 'exact)
+
+ (insert "v")
+ (let ((this-command 'self-insert-command))
+ (completion-preview--post-command))
+
+ ;; No match, no preview
+ (completion-preview-tests--check-preview nil)
+
+ (delete-char -1)
+ (let ((this-command 'delete-backward-char))
+ (completion-preview--post-command))
+
+ ;; Exact match again
+ (completion-preview-tests--check-preview "barbaz" 'exact)))
+
+(ert-deftest completion-preview-multiple-matches ()
+ "Test Completion Preview mode with multiple matching candidates."
+ (with-temp-buffer
+ (setq-local completion-at-point-functions
+ (list (completion-preview-tests--capf
+ '("foobar" "foobaz"))))
+ (insert "foo")
+ (let ((this-command 'self-insert-command))
+ (completion-preview--post-command))
+
+ ;; Multiple matches, the preview shows the first one
+ (completion-preview-tests--check-preview "bar")
+
+ (completion-preview-next-candidate 1)
+
+ ;; Next match
+ (completion-preview-tests--check-preview "baz")))
+
+(ert-deftest completion-preview-exact-match-only ()
+ "Test `completion-preview-exact-match-only'."
+ (with-temp-buffer
+ (setq-local completion-at-point-functions
+ (list (completion-preview-tests--capf
+ '("spam" "foobar" "foobaz")))
+ completion-preview-exact-match-only t)
+ (insert "foo")
+ (let ((this-command 'self-insert-command))
+ (completion-preview--post-command))
+
+ ;; Multiple matches, so no preview
+ (completion-preview-tests--check-preview nil)
+
+ (delete-region (point-min) (point-max))
+ (insert "spa")
+ (let ((this-command 'self-insert-command))
+ (completion-preview--post-command))
+
+ ;; Exact match
+ (completion-preview-tests--check-preview "m" 'exact)))
+
+(ert-deftest completion-preview-function-capfs ()
+ "Test Completion Preview mode with capfs that return a function."
+ (with-temp-buffer
+ (setq-local completion-at-point-functions
+ (list
+ (lambda () #'ignore)
+ (completion-preview-tests--capf
+ '("foobar" "foobaz"))))
+ (insert "foo")
+ (let ((this-command 'self-insert-command))
+ (completion-preview--post-command))
+ (completion-preview-tests--check-preview "bar")))
+
+(ert-deftest completion-preview-non-exclusive-capfs ()
+ "Test Completion Preview mode with non-exclusive capfs."
+ (with-temp-buffer
+ (setq-local completion-at-point-functions
+ (list
+ (completion-preview-tests--capf
+ '("spam") :exclusive 'no)
+ (completion-preview-tests--capf
+ '("foobar" "foobaz") :exclusive 'no)
+ (completion-preview-tests--capf
+ '("foobarbaz"))))
+ (insert "foo")
+ (let ((this-command 'self-insert-command))
+ (completion-preview--post-command))
+ (completion-preview-tests--check-preview "bar")
+ (setq-local completion-preview-exact-match-only t)
+ (let ((this-command 'self-insert-command))
+ (completion-preview--post-command))
+ (completion-preview-tests--check-preview "barbaz" 'exact)))
+
+(ert-deftest completion-preview-face-updates ()
+ "Test updating the face in completion preview when match is no longer exact."
+ (with-temp-buffer
+ (setq-local completion-at-point-functions
+ (list
+ (completion-preview-tests--capf
+ '("foobarbaz" "food"))))
+ (insert "foo")
+ (let ((this-command 'self-insert-command))
+ (completion-preview--post-command))
+ (completion-preview-tests--check-preview "d")
+ (insert "b")
+ (let ((this-command 'self-insert-command))
+ (completion-preview--post-command))
+ (completion-preview-tests--check-preview "arbaz" 'exact)
+ (delete-char -1)
+ (let ((this-command 'delete-backward-char))
+ (completion-preview--post-command))
+ (completion-preview-tests--check-preview "d")))
+
+(ert-deftest completion-preview-capf-errors ()
+ "Test Completion Preview mode with capfs that signal errors.
+
+`dabbrev-capf' is one example of such a capf."
+ (with-temp-buffer
+ (setq-local completion-at-point-functions
+ (list
+ (lambda () (user-error "bad"))
+ (completion-preview-tests--capf
+ '("foobarbaz"))))
+ (insert "foo")
+ (let ((this-command 'self-insert-command))
+ (completion-preview--post-command))
+ (completion-preview-tests--check-preview "barbaz" 'exact)))
+
+;;; completion-preview-tests.el ends here
diff --git a/test/lisp/completion-tests.el b/test/lisp/completion-tests.el
index d34691d93ae..33bafed625e 100644
--- a/test/lisp/completion-tests.el
+++ b/test/lisp/completion-tests.el
@@ -1,6 +1,6 @@
;;; completion-tests.el --- Tests for completion.el -*- lexical-binding: t -*-
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/cus-edit-tests.el b/test/lisp/cus-edit-tests.el
index 9ceab16e194..535711e02cf 100644
--- a/test/lisp/cus-edit-tests.el
+++ b/test/lisp/cus-edit-tests.el
@@ -1,6 +1,6 @@
;;; cus-edit-tests.el --- Tests for cus-edit.el -*- lexical-binding: t -*-
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/custom-tests.el b/test/lisp/custom-tests.el
index 376a13d5df5..c009abfe0d1 100644
--- a/test/lisp/custom-tests.el
+++ b/test/lisp/custom-tests.el
@@ -1,6 +1,6 @@
;;; custom-tests.el --- tests for custom.el -*- lexical-binding: t -*-
-;; Copyright (C) 2018-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2018-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/dabbrev-tests.el b/test/lisp/dabbrev-tests.el
index 48677a0b415..c7574403949 100644
--- a/test/lisp/dabbrev-tests.el
+++ b/test/lisp/dabbrev-tests.el
@@ -1,6 +1,6 @@
;;; dabbrev-tests.el --- Test suite for dabbrev. -*- lexical-binding:t -*-
-;; Copyright (C) 2016-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2016-2024 Free Software Foundation, Inc.
;; Author: Alan Third <alan@idiocy.org>
;; Keywords: dabbrev
diff --git a/test/lisp/delim-col-tests.el b/test/lisp/delim-col-tests.el
index a2721d8cdf8..f2d5d72f57f 100644
--- a/test/lisp/delim-col-tests.el
+++ b/test/lisp/delim-col-tests.el
@@ -1,6 +1,6 @@
;;; delim-col-tests.el --- Tests for delim-col.el -*- lexical-binding: t; -*-
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
;; Author: Stefan Kangas <stefankangas@gmail.com>
diff --git a/test/lisp/descr-text-tests.el b/test/lisp/descr-text-tests.el
index 96c5d90e449..a263c099a0c 100644
--- a/test/lisp/descr-text-tests.el
+++ b/test/lisp/descr-text-tests.el
@@ -1,6 +1,6 @@
;;; descr-text-tests.el --- ERT tests for descr-text.el -*- lexical-binding: t -*-
-;; Copyright (C) 2014, 2016-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2014, 2016-2024 Free Software Foundation, Inc.
;; Author: Michal Nazarewicz <mina86@mina86.com>
diff --git a/test/lisp/desktop-tests.el b/test/lisp/desktop-tests.el
index 07f0be6c90e..164e1ab1c36 100644
--- a/test/lisp/desktop-tests.el
+++ b/test/lisp/desktop-tests.el
@@ -1,6 +1,6 @@
;;; desktop-tests.el --- Tests for desktop.el -*- lexical-binding: t -*-
-;; Copyright (C) 2020, 2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020, 2023-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/dired-aux-tests.el b/test/lisp/dired-aux-tests.el
index 62011d8b0f0..f1542cb5e83 100644
--- a/test/lisp/dired-aux-tests.el
+++ b/test/lisp/dired-aux-tests.el
@@ -1,6 +1,6 @@
;;; dired-aux-tests.el --- Test suite for dired-aux. -*- lexical-binding: t -*-
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/dired-tests.el b/test/lisp/dired-tests.el
index 8f2b9af09c0..651b77500a1 100644
--- a/test/lisp/dired-tests.el
+++ b/test/lisp/dired-tests.el
@@ -1,6 +1,6 @@
;;; dired-tests.el --- Test suite. -*- lexical-binding: t -*-
-;; Copyright (C) 2015-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -270,8 +270,8 @@
"Test for https://debbugs.gnu.org/27631 ."
;; For dired using 'ls' emulation we test for this bug in
;; ls-lisp-tests.el and em-ls-tests.el.
- (skip-unless (and (not (featurep 'ls-lisp))
- (not (featurep 'eshell))))
+ (skip-unless (not (or (featurep 'ls-lisp)
+ (featurep 'eshell))))
(ert-with-temp-directory dir
(let* ((dir1 (expand-file-name "dir1" dir))
(dir2 (expand-file-name "dir2" dir))
diff --git a/test/lisp/dired-x-tests.el b/test/lisp/dired-x-tests.el
index b64b115e69f..166ec54f9dd 100644
--- a/test/lisp/dired-x-tests.el
+++ b/test/lisp/dired-x-tests.el
@@ -1,6 +1,6 @@
;;; dired-x-tests.el --- Test suite for dired-x. -*- lexical-binding: t -*-
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/dnd-tests.el b/test/lisp/dnd-tests.el
index 9f97d739cec..3d4f28b9ae1 100644
--- a/test/lisp/dnd-tests.el
+++ b/test/lisp/dnd-tests.el
@@ -1,6 +1,6 @@
;;; dnd-tests.el --- Tests for window system independent DND support -*- lexical-binding: t; -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -33,6 +33,7 @@
(require 'tramp)
(require 'select)
(require 'ert-x)
+(require 'browse-url)
(defvar dnd-tests-selection-table nil
"Alist of selection names to their values.")
@@ -437,5 +438,162 @@ This function only tries to handle strings."
(ignore-errors
(delete-file normal-temp-file)))))
+
+
+(defvar dnd-tests-list-1 '("file:///usr/openwin/include/pixrect/pr_impl.h"
+ "file:///usr/openwin/include/pixrect/pr_io.h")
+ "Sample data for tests concerning the treatment of drag-and-drop URLs.")
+
+(defvar dnd-tests-list-2 '("file:///usr/openwin/include/pixrect/pr_impl.h"
+ "file://remote/usr/openwin/include/pixrect/pr_io.h")
+ "Sample data for tests concerning the treatment of drag-and-drop URLs.")
+
+(defvar dnd-tests-list-3 (append dnd-tests-list-2 '("http://example.com"))
+ "Sample data for tests concerning the treatment of drag-and-drop URLs.")
+
+(defvar dnd-tests-list-4 (append dnd-tests-list-3 '("scheme1://foo.bar"
+ "scheme2://foo.bar"))
+ "Sample data for tests concerning the treatment of drag-and-drop URLs.")
+
+(defun dnd-tests-local-file-function (urls _action)
+ "Signal an error if URLS doesn't match `dnd-tests-list-1'.
+ACTION is ignored. Return the symbol `copy' otherwise."
+ (should (equal urls dnd-tests-list-1))
+ 'copy)
+
+(put 'dnd-tests-local-file-function 'dnd-multiple-handler t)
+
+(defun dnd-tests-remote-file-function (urls _action)
+ "Signal an error if URLS doesn't match `dnd-tests-list-2'.
+ACTION is ignored. Return the symbol `copy' otherwise."
+ (should (equal urls dnd-tests-list-2))
+ 'copy)
+
+(put 'dnd-tests-remote-file-function 'dnd-multiple-handler t)
+
+(defun dnd-tests-http-scheme-function (url _action)
+ "Signal an error if URLS doesn't match `dnd-tests-list-3''s third element.
+ACTION is ignored. Return the symbol `private' otherwise."
+ (should (equal url (car (last dnd-tests-list-3))))
+ 'private)
+
+(defun dnd-tests-browse-url-handler (url &rest _ignored)
+ "Verify URL is `dnd-tests-list-4''s fourth element."
+ (should (equal url (nth 3 dnd-tests-list-4))))
+
+(put 'dnd-tests-browse-url-handler 'browse-url-browser-kind 'internal)
+
+(ert-deftest dnd-tests-receive-multiple-urls ()
+ (let ((dnd-protocol-alist '(("^file:///" . dnd-tests-local-file-function)
+ ("^file:" . error)
+ ("^unrelated-scheme:" . error)))
+ (browse-url-handlers nil))
+ ;; Check that the order of the alist is respected when the
+ ;; precedences of two handlers are equal.
+ (should (equal (dnd-handle-multiple-urls (selected-window)
+ (copy-sequence
+ dnd-tests-list-1)
+ 'copy)
+ 'copy))
+ ;; Check that sorting handlers by precedence functions correctly.
+ (setq dnd-protocol-alist '(("^file:///" . error)
+ ("^file:" . dnd-tests-remote-file-function)
+ ("^unrelated-scheme:" . error)))
+ (should (equal (dnd-handle-multiple-urls (selected-window)
+ (copy-sequence
+ dnd-tests-list-2)
+ 'copy)
+ 'copy))
+ ;; Check that multiple handlers can be called at once, and actions
+ ;; are properly "downgraded" to private when multiple handlers
+ ;; return inconsistent values.
+ (setq dnd-protocol-alist '(("^file:" . dnd-tests-remote-file-function)
+ ("^file:///" . error)
+ ("^http://" . dnd-tests-http-scheme-function)))
+ (should (equal (dnd-handle-multiple-urls (selected-window)
+ (copy-sequence
+ dnd-tests-list-3)
+ 'copy)
+ 'private))
+ ;; Now verify that the function's documented fallback behavior
+ ;; functions correctly. Set browse-url-handlers to an association
+ ;; list incorporating a test function, then guarantee that is
+ ;; called.
+ (setq browse-url-handlers '(("^scheme1://" . dnd-tests-browse-url-handler)))
+ ;; Furthermore, guarantee the fifth argument of the test data is
+ ;; inserted, for no apposite handler exists.
+ (save-window-excursion
+ (set-window-buffer nil (get-buffer-create " *dnd-tests*"))
+ (set-buffer (get-buffer-create " *dnd-tests*"))
+ (erase-buffer)
+ (should (equal (dnd-handle-multiple-urls (selected-window)
+ (copy-sequence
+ dnd-tests-list-4)
+ 'copy)
+ 'private))
+ (should (equal (buffer-string) (nth 4 dnd-tests-list-4))))
+ ;; Check that a handler enumerated twice in the handler list
+ ;; receives URIs assigned to it only once.
+ (let* ((received-p nil)
+ (lambda (lambda (uri _action)
+ (should (equal uri "scheme1://test"))
+ (should (null received-p))
+ (setq received-p 'copy))))
+ (setq dnd-protocol-alist (list (cons "scheme1://" lambda)
+ (cons "scheme1://" lambda)))
+ (should (equal (dnd-handle-multiple-urls (selected-window)
+ (list "scheme1://test")
+ 'copy)
+ 'copy)))))
+
+(ert-deftest dnd-tests-default-file-name-handlers ()
+ (let* ((local-files-opened nil)
+ (remote-files-opened nil)
+ (function-1 (lambda (file _uri)
+ (push file local-files-opened)
+ 'copy))
+ (function-2 (lambda (file _uri)
+ (push file remote-files-opened)
+ 'copy)))
+ (unwind-protect
+ (progn
+ (advice-add #'dnd-open-local-file :override
+ function-1)
+ (advice-add #'dnd-open-file :override
+ function-2)
+ ;; Guarantee that file names are properly categorized as either
+ ;; local or remote by the default dnd-protocol-alist.
+ (dnd-handle-multiple-urls
+ (selected-window)
+ (list
+ ;; These are run-of-the-mill local file URIs.
+ "file:///usr/include/sys/acct.h"
+ "file:///usr/include/sys/acctctl.h"
+ ;; These URIs incorporate a host; they should match
+ ;; function-2 but never function-1.
+ "file://remotehost/usr/src/emacs/configure.ac"
+ "file://remotehost/usr/src/emacs/configure"
+ ;; These URIs are generated by drag-and-drop event
+ ;; handlers from local file names alone; they are not
+ ;; echt URIs in and of themselves, but a product of our
+ ;; drag and drop code.
+ "file:/etc/vfstab"
+ "file:/etc/dfs/sharetab"
+ ;; These URIs are generated under MS-Windows.
+ "file:c:/path/to/file/name"
+ "file:d:/path/to/file/name")
+ 'copy)
+ (should (equal (sort local-files-opened #'string<)
+ '("file:///usr/include/sys/acct.h"
+ "file:///usr/include/sys/acctctl.h"
+ "file:/etc/dfs/sharetab"
+ "file:/etc/vfstab"
+ "file:c:/path/to/file/name"
+ "file:d:/path/to/file/name")))
+ (should (equal (sort remote-files-opened #'string<)
+ '("file://remotehost/usr/src/emacs/configure"
+ "file://remotehost/usr/src/emacs/configure.ac"))))
+ (advice-remove #'dnd-open-local-file function-2))))
+
(provide 'dnd-tests)
;;; dnd-tests.el ends here
diff --git a/test/lisp/dom-tests.el b/test/lisp/dom-tests.el
index abb586435a7..8cbfb9ad9df 100644
--- a/test/lisp/dom-tests.el
+++ b/test/lisp/dom-tests.el
@@ -1,6 +1,6 @@
;;; dom-tests.el --- Tests for dom.el -*- lexical-binding: t; -*-
-;; Copyright (C) 2016-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2016-2024 Free Software Foundation, Inc.
;; Author: Simen Heggestøyl <simenheg@gmail.com>
;; Keywords:
diff --git a/test/lisp/edmacro-tests.el b/test/lisp/edmacro-tests.el
index f79529a2000..fb968d8e6da 100644
--- a/test/lisp/edmacro-tests.el
+++ b/test/lisp/edmacro-tests.el
@@ -1,6 +1,6 @@
;;; edmacro-tests.el --- Tests for edmacro.el -*- lexical-binding:t -*-
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/electric-tests.el b/test/lisp/electric-tests.el
index c577229c322..720313511a6 100644
--- a/test/lisp/electric-tests.el
+++ b/test/lisp/electric-tests.el
@@ -1,6 +1,6 @@
;;; electric-tests.el --- tests for electric.el -*- lexical-binding: t; -*-
-;; Copyright (C) 2013-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2024 Free Software Foundation, Inc.
;; Author: João Távora <joaotavora@gmail.com>
;; Keywords:
diff --git a/test/lisp/elide-head-tests.el b/test/lisp/elide-head-tests.el
index 40a9d365f37..3f1db75928a 100644
--- a/test/lisp/elide-head-tests.el
+++ b/test/lisp/elide-head-tests.el
@@ -1,6 +1,6 @@
;;; elide-head-tests.el --- Tests for elide-head.el -*- lexical-binding: t; -*-
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
;; Author: Simen Heggestøyl <simenheg@gmail.com>
diff --git a/test/lisp/emacs-lisp/backquote-tests.el b/test/lisp/emacs-lisp/backquote-tests.el
index 79155cc0450..66764f40ec2 100644
--- a/test/lisp/emacs-lisp/backquote-tests.el
+++ b/test/lisp/emacs-lisp/backquote-tests.el
@@ -1,6 +1,6 @@
;;; backquote-tests.el --- Tests for backquote.el -*- lexical-binding: t -*-
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/emacs-lisp/backtrace-tests.el b/test/lisp/emacs-lisp/backtrace-tests.el
index e5899446ee4..3248403078f 100644
--- a/test/lisp/emacs-lisp/backtrace-tests.el
+++ b/test/lisp/emacs-lisp/backtrace-tests.el
@@ -1,6 +1,6 @@
;;; backtrace-tests.el --- Tests for backtraces -*- lexical-binding: t; -*-
-;; Copyright (C) 2018-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2018-2024 Free Software Foundation, Inc.
;; Author: Gemini Lasswell
diff --git a/test/lisp/emacs-lisp/benchmark-tests.el b/test/lisp/emacs-lisp/benchmark-tests.el
index 99b5b142c37..72095ea5b09 100644
--- a/test/lisp/emacs-lisp/benchmark-tests.el
+++ b/test/lisp/emacs-lisp/benchmark-tests.el
@@ -1,6 +1,6 @@
;;; benchmark-tests.el --- Test suite for benchmark. -*- lexical-binding: t -*-
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -25,8 +25,8 @@
(ert-deftest benchmark-tests ()
;; Avoid fork failures on Cygwin. See bug#62450 and etc/PROBLEMS
;; ("Fork failures in a build with native compilation").
- (skip-unless (not (and (eq system-type 'cygwin)
- (featurep 'native-compile))))
+ (skip-when (and (eq system-type 'cygwin)
+ (featurep 'native-compile)))
(let (str t-long t-short m)
(should (consp (benchmark-run nil (setq m (1+ 0)))))
(should (consp (benchmark-run 1 (setq m (1+ 0)))))
diff --git a/test/lisp/emacs-lisp/bindat-tests.el b/test/lisp/emacs-lisp/bindat-tests.el
index 1e4a511d036..99de0635aee 100644
--- a/test/lisp/emacs-lisp/bindat-tests.el
+++ b/test/lisp/emacs-lisp/bindat-tests.el
@@ -1,6 +1,6 @@
;;; bindat-tests.el --- tests for bindat.el -*- lexical-binding: t -*-
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/emacs-lisp/byte-run-tests.el b/test/lisp/emacs-lisp/byte-run-tests.el
new file mode 100644
index 00000000000..6180022f198
--- /dev/null
+++ b/test/lisp/emacs-lisp/byte-run-tests.el
@@ -0,0 +1,32 @@
+;;; byte-run-tests.el --- Tests for byte-run.el -*- lexical-binding: t -*-
+
+;; Copyright (C) 2023-2024 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert)
+
+(ert-deftest make-obsolete ()
+ (should-error (make-obsolete nil 'foo "30.1"))
+ (should-error (make-obsolete t 'foo "30.1") ))
+
+(ert-deftest make-obsolete-variable ()
+ (should-error (make-obsolete-variable nil 'foo "30.1"))
+ (should-error (make-obsolete-variable t 'foo "30.1")))
+
+;;; byte-run-tests.el ends here
diff --git a/test/lisp/emacs-lisp/bytecomp-resources/no-byte-compile.el b/test/lisp/emacs-lisp/bytecomp-resources/no-byte-compile.el
index 00ad1947507..1de5cf66b66 100644
--- a/test/lisp/emacs-lisp/bytecomp-resources/no-byte-compile.el
+++ b/test/lisp/emacs-lisp/bytecomp-resources/no-byte-compile.el
@@ -1 +1 @@
-;; -*- no-byte-compile: t; -*-
+;; -*- no-byte-compile: t; lexical-binding: t; -*-
diff --git a/test/lisp/emacs-lisp/bytecomp-tests.el b/test/lisp/emacs-lisp/bytecomp-tests.el
index 26325c1ef11..293d3025420 100644
--- a/test/lisp/emacs-lisp/bytecomp-tests.el
+++ b/test/lisp/emacs-lisp/bytecomp-tests.el
@@ -1,6 +1,6 @@
;;; bytecomp-tests.el --- Tests for bytecomp.el -*- lexical-binding:t -*-
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
;; Author: Shigeru Fukaya <shigeru.fukaya@gmail.com>
;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
@@ -643,6 +643,16 @@ inner loops respectively."
(funcall (car f) 3)
(list a b))
+ (let ((x (list 1)))
+ (let ((y x)
+ (z (setq x (vector x))))
+ (list x y z)))
+
+ (let ((x (list 1)))
+ (let* ((y x)
+ (z (setq x (vector x))))
+ (list x y z)))
+
(cond)
(mapcar (lambda (x) (cond ((= x 0)))) '(0 1))
@@ -707,7 +717,7 @@ inner loops respectively."
(set (make-local-variable 'bytecomp-tests--xx) 2)
bytecomp-tests--xx)
- ;; Check for-effect optimisation of `condition-case' body form.
+ ;; Check for-effect optimization of `condition-case' body form.
;; With `condition-case' in for-effect context:
(let ((x (bytecomp-test-identity ?A))
(r nil))
@@ -787,7 +797,7 @@ inner loops respectively."
(let ((x 0))
(list (= (setq x 1))
x))
- ;; Aristotelian identity optimisation
+ ;; Aristotelian identity optimization
(let ((x (bytecomp-test-identity 1)))
(list (eq x x) (eql x x) (equal x x)))
)
@@ -838,6 +848,11 @@ byte-compiled. Run with dynamic binding."
(should (equal (bytecomp-tests--eval-interpreted form)
(bytecomp-tests--eval-compiled form)))))))
+(defmacro bytecomp-tests--with-fresh-warnings (&rest body)
+ `(let ((macroexp--warned ; oh dear
+ (make-hash-table :test #'equal :weakness 'key)))
+ ,@body))
+
(defun test-byte-comp-compile-and-load (compile &rest forms)
(declare (indent 1))
(ert-with-temp-file elfile
@@ -852,7 +867,8 @@ byte-compiled. Run with dynamic binding."
(if compile
(let ((byte-compile-dest-file-function
(lambda (e) elcfile)))
- (byte-compile-file elfile)))
+ (bytecomp-tests--with-fresh-warnings
+ (byte-compile-file elfile))))
(load elfile nil 'nomessage))))
(ert-deftest test-byte-comp-macro-expansion ()
@@ -923,23 +939,25 @@ byte-compiled. Run with dynamic binding."
(declare (indent 1))
(with-current-buffer (get-buffer-create "*Compile-Log*")
(let ((inhibit-read-only t)) (erase-buffer))
- (let ((text-quoting-style 'grave)
- (macroexp--warned ; oh dear
- (make-hash-table :test #'equal :weakness 'key)))
(ert-info ((prin1-to-string form) :prefix "form: ")
- (byte-compile form)
+ (let ((text-quoting-style 'grave))
+ (bytecomp-tests--with-fresh-warnings
+ (byte-compile form)))
(ert-info ((prin1-to-string (buffer-string)) :prefix "buffer: ")
(should (re-search-forward
- (string-replace " " "[ \n]+" re-warning))))))))
+ (string-replace " " "[ \n]+" re-warning)))))))
+
+(defun bytecomp--without-warning-test (form)
+ (bytecomp--with-warning-test "\\`\\'" form))
(ert-deftest bytecomp-warn--ignore ()
(bytecomp--with-warning-test "unused"
'(lambda (y) 6))
- (bytecomp--with-warning-test "\\`\\'" ;No warning!
+ (bytecomp--without-warning-test
'(lambda (y) (ignore y) 6))
(bytecomp--with-warning-test "assq"
'(lambda (x y) (progn (assq x y) 5)))
- (bytecomp--with-warning-test "\\`\\'" ;No warning!
+ (bytecomp--without-warning-test
'(lambda (x y) (progn (ignore (assq x y)) 5))))
(ert-deftest bytecomp-warn-wrong-args ()
@@ -964,6 +982,34 @@ byte-compiled. Run with dynamic binding."
(bytecomp--with-warning-test "defvar.*foo.*wider than.*characters"
`(defvar foo t ,bytecomp-tests--docstring)))
+(ert-deftest bytecomp-warn-wide-docstring/cl-defsubst ()
+ (bytecomp--without-warning-test
+ `(cl-defsubst short-name ()
+ "Do something."))
+ (bytecomp--without-warning-test
+ `(cl-defsubst long-name-with-less-80-characters-but-still-quite-a-bit ()
+ "Do something."))
+ (bytecomp--with-warning-test "wider than.*characters"
+ `(cl-defsubst long-name-with-more-than-80-characters-yes-this-is-a-very-long-name-but-why-not!! ()
+ "Do something.")))
+
+(ert-deftest bytecomp-warn-wide-docstring/cl-defstruct ()
+ (bytecomp--without-warning-test
+ `(cl-defstruct short-name
+ field))
+ (bytecomp--without-warning-test
+ `(cl-defstruct short-name
+ long-name-with-less-80-characters-but-still-quite-a-bit))
+ (bytecomp--without-warning-test
+ `(cl-defstruct long-name-with-less-80-characters-but-still-quite-a-bit
+ field))
+ (bytecomp--with-warning-test "wider than.*characters"
+ `(cl-defstruct short-name
+ long-name-with-more-than-80-characters-yes-this-is-a-very-long-name-but-why-not!!))
+ (bytecomp--with-warning-test "wider than.*characters"
+ `(cl-defstruct long-name-with-more-than-80-characters-yes-this-is-a-very-long-name-but-why-not!!
+ field)))
+
(ert-deftest bytecomp-warn-quoted-condition ()
(bytecomp--with-warning-test
"Warning: `condition-case' condition should not be quoted: 'arith-error"
@@ -1064,7 +1110,7 @@ byte-compiled. Run with dynamic binding."
"fails to specify containing group")
(bytecomp--define-warning-file-test "warn-defcustom-notype.el"
- "fails to specify type")
+ "missing :type keyword parameter")
(bytecomp--define-warning-file-test "warn-defvar-lacks-prefix.el"
"var.*foo.*lacks a prefix")
@@ -1266,6 +1312,30 @@ byte-compiled. Run with dynamic binding."
(let ((elc (concat ,file-name-var ".elc")))
(if (file-exists-p elc) (delete-file elc))))))
+(defun bytecomp-tests--log-from-compilation (source)
+ "Compile the string SOURCE and return the compilation log output."
+ (let ((text-quoting-style 'grave)
+ (byte-compile-log-buffer (generate-new-buffer " *Compile-Log*")))
+ (with-current-buffer byte-compile-log-buffer
+ (let ((inhibit-read-only t)) (erase-buffer)))
+ (bytecomp-tests--with-temp-file el-file
+ (write-region source nil el-file)
+ (byte-compile-file el-file))
+ (with-current-buffer byte-compile-log-buffer
+ (buffer-string))))
+
+(ert-deftest bytecomp-tests--lexical-binding-cookie ()
+ (cl-flet ((cookie-warning (source)
+ (string-search
+ "file has no `lexical-binding' directive on its first line"
+ (bytecomp-tests--log-from-compilation source))))
+ (let ((some-code "(defun my-fun () 12)\n"))
+ (should-not (cookie-warning
+ (concat ";;; -*-lexical-binding:t-*-\n" some-code)))
+ (should-not (cookie-warning
+ (concat ";;; -*-lexical-binding:nil-*-\n" some-code)))
+ (should (cookie-warning some-code)))))
+
(ert-deftest bytecomp-tests--unescaped-char-literals ()
"Check that byte compiling warns about unescaped character
literals (Bug#20852)."
@@ -1274,7 +1344,9 @@ literals (Bug#20852)."
(byte-compile-debug t)
(text-quoting-style 'grave))
(bytecomp-tests--with-temp-file source
- (write-region "(list ?) ?( ?; ?\" ?[ ?])" nil source)
+ (write-region (concat ";;; -*-lexical-binding:t-*-\n"
+ "(list ?) ?( ?; ?\" ?[ ?])")
+ nil source)
(bytecomp-tests--with-temp-file destination
(let* ((byte-compile-dest-file-function (lambda (_) destination))
(err (should-error (byte-compile-file source))))
@@ -1286,7 +1358,9 @@ literals (Bug#20852)."
"`?\\]' expected!")))))))
;; But don't warn in subsequent compilations (Bug#36068).
(bytecomp-tests--with-temp-file source
- (write-region "(list 1 2 3)" nil source)
+ (write-region (concat ";;; -*-lexical-binding:t-*-\n"
+ "(list 1 2 3)")
+ nil source)
(bytecomp-tests--with-temp-file destination
(let ((byte-compile-dest-file-function (lambda (_) destination)))
(should (byte-compile-file source)))))))
@@ -1294,6 +1368,7 @@ literals (Bug#20852)."
(ert-deftest bytecomp-tests-function-put ()
"Check `function-put' operates during compilation."
(bytecomp-tests--with-temp-file source
+ (insert ";;; -*-lexical-binding:t-*-\n")
(dolist (form '((function-put 'bytecomp-tests--foo 'foo 1)
(function-put 'bytecomp-tests--foo 'bar 2)
(defmacro bytecomp-tests--foobar ()
@@ -1508,6 +1583,15 @@ literals (Bug#20852)."
"Warning: `unwind-protect' without unwind forms")
(test-suppression
+ '(defun zot (x)
+ (cond
+ ((zerop x) 'zero)
+ (t 'nonzero)
+ (happy puppy)))
+ '((suspicious cond))
+ "Warning: Useless clause following default `cond' clause")
+
+ (test-suppression
'(defun zot ()
(let ((_ 1))
))
@@ -1591,7 +1675,8 @@ writable (Bug#44631)."
(byte-compile-error-on-warn t))
(unwind-protect
(progn
- (write-region "" nil input-file nil nil nil 'excl)
+ (write-region ";;; -*-lexical-binding:t-*-\n"
+ nil input-file nil nil nil 'excl)
(write-region "" nil output-file nil nil nil 'excl)
(set-file-modes input-file #o400)
(set-file-modes output-file #o200)
@@ -1622,7 +1707,8 @@ mountpoint (Bug#44631)."
(byte-compile-error-on-warn t))
(should-not (file-remote-p input-file))
(should-not (file-remote-p output-file))
- (write-region "" nil input-file nil nil nil 'excl)
+ (write-region ";;; -*-lexical-binding:t-*-\n"
+ nil input-file nil nil nil 'excl)
(write-region "" nil output-file nil nil nil 'excl)
(unwind-protect
(progn
@@ -1655,7 +1741,8 @@ mountpoint (Bug#44631)."
(let* ((default-directory directory)
(byte-compile-dest-file-function (lambda (_) "test.elc"))
(byte-compile-error-on-warn t))
- (write-region "" nil "test.el" nil nil nil 'excl)
+ (write-region ";;; -*-lexical-binding:t-*-\n"
+ nil "test.el" nil nil nil 'excl)
(should (byte-compile-file "test.el"))
(should (file-regular-p "test.elc"))
(should (cl-plusp (file-attribute-size
@@ -1829,12 +1916,53 @@ EXPECTED-POINT BINDINGS (MODES \\='\\='(ruby-mode js-mode python-mode)) \
(TEST-IN-COMMENTS t) (TEST-IN-STRINGS t) (TEST-IN-CODE t) \
(FIXTURE-FN \\='#\\='electric-pair-mode))" fill-column)))
-(ert-deftest bytecomp-test-defcustom-type-quoted ()
- (should-not (byte-compile--defcustom-type-quoted 'integer))
- (should-not (byte-compile--defcustom-type-quoted
- '(choice (const :tag "foo" bar))))
- (should (byte-compile--defcustom-type-quoted
- '(choice (const :tag "foo" 'bar)))))
+(ert-deftest bytecomp-test-defcustom-type ()
+ (cl-flet ((dc (type) `(defcustom mytest nil "doc" :type ',type :group 'test)))
+ (bytecomp--with-warning-test
+ (rx "type should not be quoted") (dc ''integer))
+ (bytecomp--with-warning-test
+ (rx "type should not be quoted") (dc '(choice '(repeat boolean))))
+ (bytecomp--with-warning-test
+ (rx "misplaced :tag keyword") (dc '(choice (const b :tag "a"))))
+ (bytecomp--with-warning-test
+ (rx "`choice' without any types inside") (dc '(choice :tag "a")))
+ (bytecomp--with-warning-test
+ (rx "`other' not last in `choice'")
+ (dc '(choice (const a) (other b) (const c))))
+ (bytecomp--with-warning-test
+ (rx "duplicated value in `choice': `a'")
+ (dc '(choice (const a) (const b) (const a))))
+ (bytecomp--with-warning-test
+ (rx "duplicated :tag string in `choice': \"X\"")
+ (dc '(choice (const :tag "X" a) (const :tag "Y" b) (other :tag "X" c))))
+ (bytecomp--with-warning-test
+ (rx "`cons' requires 2 type specs, found 1")
+ (dc '(cons :tag "a" integer)))
+ (bytecomp--with-warning-test
+ (rx "`repeat' without type specs")
+ (dc '(repeat :tag "a")))
+ (bytecomp--with-warning-test
+ (rx "`const' with too many values")
+ (dc '(const :tag "a" x y)))
+ (bytecomp--with-warning-test
+ (rx "`const' with quoted value")
+ (dc '(const :tag "a" 'x)))
+ (bytecomp--with-warning-test
+ (rx "`bool' is not a valid type")
+ (dc '(bool :tag "a")))
+ (bytecomp--with-warning-test
+ (rx "irregular type `:tag'")
+ (dc '(:tag "a")))
+ (bytecomp--with-warning-test
+ (rx "irregular type `\"string\"'")
+ (dc '(list "string")))
+ (bytecomp--with-warning-test
+ (rx "`list' without arguments")
+ (dc 'list))
+ (bytecomp--with-warning-test
+ (rx "`integerp' is not a valid type")
+ (dc 'integerp))
+ ))
(ert-deftest bytecomp-function-attributes ()
;; Check that `byte-compile' keeps the declarations, interactive spec and
@@ -1992,7 +2120,7 @@ EXPECTED-POINT BINDINGS (MODES \\='\\='(ruby-mode js-mode python-mode)) \
))
(ert-deftest bytecomp--byte-op-error-backtrace ()
- "Check that signalling byte ops show up in the backtrace."
+ "Check that signaling byte ops show up in the backtrace."
(dolist (case bytecomp-tests--byte-op-error-cases)
(ert-info ((prin1-to-string case) :prefix "case: ")
(let* ((call (nth 0 case))
@@ -2023,7 +2151,7 @@ EXPECTED-POINT BINDINGS (MODES \\='\\='(ruby-mode js-mode python-mode)) \
call))))))))))
(ert-deftest bytecomp--eq-symbols-with-pos-enabled ()
- ;; Verify that we don't optimise away a binding of
+ ;; Verify that we don't optimize away a binding of
;; `symbols-with-pos-enabled' around an application of `eq' (bug#65017).
(let* ((sym-with-pos1 (read-positioning-symbols "sym"))
(sym-with-pos2 (read-positioning-symbols " sym")) ; <- space!
diff --git a/test/lisp/emacs-lisp/cconv-tests.el b/test/lisp/emacs-lisp/cconv-tests.el
index 6facd3452ea..8cab859b5b5 100644
--- a/test/lisp/emacs-lisp/cconv-tests.el
+++ b/test/lisp/emacs-lisp/cconv-tests.el
@@ -1,6 +1,6 @@
;;; cconv-tests.el --- Tests for cconv.el -*- lexical-binding: t -*-
-;; Copyright (C) 2018-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2018-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/emacs-lisp/check-declare-tests.el b/test/lisp/emacs-lisp/check-declare-tests.el
index 840b6d22e1e..2d445542cb7 100644
--- a/test/lisp/emacs-lisp/check-declare-tests.el
+++ b/test/lisp/emacs-lisp/check-declare-tests.el
@@ -1,6 +1,6 @@
;;; check-declare-tests.el --- Tests for check-declare.el -*- lexical-binding: t; -*-
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
;; Author: Simen Heggestøyl <simenheg@gmail.com>
;; Keywords:
diff --git a/test/lisp/emacs-lisp/checkdoc-tests.el b/test/lisp/emacs-lisp/checkdoc-tests.el
index 57694bd424b..049d2d953a0 100644
--- a/test/lisp/emacs-lisp/checkdoc-tests.el
+++ b/test/lisp/emacs-lisp/checkdoc-tests.el
@@ -1,6 +1,6 @@
;;; checkdoc-tests.el --- unit tests for checkdoc.el -*- lexical-binding: t; -*-
-;; Copyright (C) 2016-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2016-2024 Free Software Foundation, Inc.
;; Author: Philipp Stephani <phst@google.com>
@@ -37,6 +37,15 @@
(insert "(defun foo())")
(should-error (checkdoc-defun) :type 'user-error)))
+(ert-deftest checkdoc-docstring-avoid-false-positive-ok ()
+ "Check that Bug#68002 is fixed."
+ (with-temp-buffer
+ (emacs-lisp-mode)
+ (insert "(defvar org-element--cache-interrupt-C-g-count 0
+ \"Current number of `org-element--cache-sync' calls.
+See `org-element--cache-interrupt-C-g'.\")")
+ (checkdoc-defun)))
+
(ert-deftest checkdoc-cl-defmethod-ok ()
"Checkdoc should be happy with a simple correct cl-defmethod."
(with-temp-buffer
diff --git a/test/lisp/emacs-lisp/cl-extra-tests.el b/test/lisp/emacs-lisp/cl-extra-tests.el
index 84f878900b5..020a0d93f78 100644
--- a/test/lisp/emacs-lisp/cl-extra-tests.el
+++ b/test/lisp/emacs-lisp/cl-extra-tests.el
@@ -1,6 +1,6 @@
;;; cl-extra-tests.el --- tests for emacs-lisp/cl-extra.el -*- lexical-binding:t -*-
-;; Copyright (C) 2013-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/emacs-lisp/cl-generic-tests.el b/test/lisp/emacs-lisp/cl-generic-tests.el
index 57b9c949342..086ac399352 100644
--- a/test/lisp/emacs-lisp/cl-generic-tests.el
+++ b/test/lisp/emacs-lisp/cl-generic-tests.el
@@ -1,6 +1,6 @@
;;; cl-generic-tests.el --- Tests for cl-generic.el functionality -*- lexical-binding: t; -*-
-;; Copyright (C) 2015-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2024 Free Software Foundation, Inc.
;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
diff --git a/test/lisp/emacs-lisp/cl-lib-tests.el b/test/lisp/emacs-lisp/cl-lib-tests.el
index b14731c4d0a..14ff8628fb8 100644
--- a/test/lisp/emacs-lisp/cl-lib-tests.el
+++ b/test/lisp/emacs-lisp/cl-lib-tests.el
@@ -1,6 +1,6 @@
;;; cl-lib-tests.el --- tests for emacs-lisp/cl-lib.el -*- lexical-binding:t -*-
-;; Copyright (C) 2013-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -530,27 +530,29 @@
(ert-deftest old-struct ()
(cl-defstruct foo x)
- (let ((x (vector 'cl-struct-foo))
- (saved cl-old-struct-compat-mode))
- (cl-old-struct-compat-mode -1)
- (should (eq (type-of x) 'vector))
+ (with-suppressed-warnings ((obsolete cl-old-struct-compat-mode))
+ (let ((x (vector 'cl-struct-foo))
+ (saved cl-old-struct-compat-mode))
+ (cl-old-struct-compat-mode -1)
+ (should (eq (type-of x) 'vector))
- (cl-old-struct-compat-mode 1)
- (defvar cl-struct-foo)
- (let ((cl-struct-foo (cl--struct-get-class 'foo)))
- (setf (symbol-function 'cl-struct-foo) :quick-object-witness-check)
- (should (eq (type-of x) 'foo))
- (should (eq (type-of (vector 'foo)) 'vector)))
+ (cl-old-struct-compat-mode 1)
+ (defvar cl-struct-foo)
+ (let ((cl-struct-foo (cl--struct-get-class 'foo)))
+ (setf (symbol-function 'cl-struct-foo) :quick-object-witness-check)
+ (should (eq (type-of x) 'foo))
+ (should (eq (type-of (vector 'foo)) 'vector)))
- (cl-old-struct-compat-mode (if saved 1 -1))))
+ (cl-old-struct-compat-mode (if saved 1 -1)))))
(ert-deftest cl-lib-old-struct ()
- (let ((saved cl-old-struct-compat-mode))
- (cl-old-struct-compat-mode -1)
- (cl-struct-define 'foo "" 'cl-structure-object nil nil nil
- 'cl-struct-foo-tags 'cl-struct-foo t)
- (should cl-old-struct-compat-mode)
- (cl-old-struct-compat-mode (if saved 1 -1))))
+ (with-suppressed-warnings ((obsolete cl-old-struct-compat-mode))
+ (let ((saved cl-old-struct-compat-mode))
+ (cl-old-struct-compat-mode -1)
+ (cl-struct-define 'foo "" 'cl-structure-object nil nil nil
+ 'cl-struct-foo-tags 'cl-struct-foo t)
+ (should cl-old-struct-compat-mode)
+ (cl-old-struct-compat-mode (if saved 1 -1)))))
(ert-deftest cl-constantly ()
(should (equal (mapcar (cl-constantly 3) '(a b c d))
diff --git a/test/lisp/emacs-lisp/cl-macs-tests.el b/test/lisp/emacs-lisp/cl-macs-tests.el
index 56a49fd865a..3fabcbc50c9 100644
--- a/test/lisp/emacs-lisp/cl-macs-tests.el
+++ b/test/lisp/emacs-lisp/cl-macs-tests.el
@@ -1,6 +1,6 @@
;;; cl-macs-tests.el --- tests for emacs-lisp/cl-macs.el -*- lexical-binding:t -*-
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/emacs-lisp/cl-preloaded-tests.el b/test/lisp/emacs-lisp/cl-preloaded-tests.el
index 7c863b4d3eb..01c70478830 100644
--- a/test/lisp/emacs-lisp/cl-preloaded-tests.el
+++ b/test/lisp/emacs-lisp/cl-preloaded-tests.el
@@ -1,6 +1,6 @@
;;; cl-preloaded-tests.el --- unit tests for cl-preloaded.el -*- lexical-binding: t; -*-
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
;; Author: Philipp Stephani <phst@google.com>
;; This file is part of GNU Emacs.
diff --git a/test/lisp/emacs-lisp/cl-print-tests.el b/test/lisp/emacs-lisp/cl-print-tests.el
index 3073a42e39d..c752afaaf24 100644
--- a/test/lisp/emacs-lisp/cl-print-tests.el
+++ b/test/lisp/emacs-lisp/cl-print-tests.el
@@ -1,6 +1,6 @@
;;; cl-print-tests.el --- Test suite for the cl-print facility. -*- lexical-binding:t -*-
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -60,18 +60,20 @@
(ert-deftest cl-print-tests-ellipsis-string ()
"Ellipsis expansion works in strings."
- (let ((print-length 4)
- (print-level 3))
+ (let ((cl-print-string-length 4))
(cl-print-tests-check-ellipsis-expansion
"abcdefg" "\"abcd...\"" "efg")
(cl-print-tests-check-ellipsis-expansion
"abcdefghijk" "\"abcd...\"" "efgh...")
- (cl-print-tests-check-ellipsis-expansion
- '(1 (2 (3 #("abcde" 0 5 (test t)))))
- "(1 (2 (3 ...)))" "#(\"abcd...\" 0 5 (test t))")
- (cl-print-tests-check-ellipsis-expansion
- #("abcd" 0 1 (bold t) 1 2 (invisible t) 3 4 (italic t))
- "#(\"abcd\" 0 1 (bold t) ...)" "1 2 (invisible t) ...")))
+ (let ((print-length 4)
+ (print-level 3))
+ (cl-print-tests-check-ellipsis-expansion
+ '(1 (2 (3 #("abcde" 0 5 (test t)))))
+ "(1 (2 (3 ...)))" "#(\"abcd...\" 0 5 (test t))"))
+ (let ((print-length 4))
+ (cl-print-tests-check-ellipsis-expansion
+ #("abcd" 0 1 (bold t) 1 2 (invisible t) 3 4 (italic t))
+ "#(\"abcd\" 0 1 (bold t) ...)" "1 2 (invisible t) ..."))))
(ert-deftest cl-print-tests-ellipsis-struct ()
"Ellipsis expansion works in structures."
diff --git a/test/lisp/emacs-lisp/cl-seq-tests.el b/test/lisp/emacs-lisp/cl-seq-tests.el
index adb74f0a6d5..bc05b17d007 100644
--- a/test/lisp/emacs-lisp/cl-seq-tests.el
+++ b/test/lisp/emacs-lisp/cl-seq-tests.el
@@ -1,6 +1,6 @@
;;; cl-seq-tests.el --- Tests for cl-seq.el functionality -*- lexical-binding: t; -*-
-;; Copyright (C) 2015-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2024 Free Software Foundation, Inc.
;; Author: Nicolas Richard <youngfrog@members.fsf.org>
diff --git a/test/lisp/emacs-lisp/comp-cstr-tests.el b/test/lisp/emacs-lisp/comp-cstr-tests.el
index 78d9bb49b98..fb1770f1f4a 100644
--- a/test/lisp/emacs-lisp/comp-cstr-tests.el
+++ b/test/lisp/emacs-lisp/comp-cstr-tests.el
@@ -1,6 +1,6 @@
;;; comp-cstr-tests.el --- unit tests for src/comp.c -*- lexical-binding: t; -*-
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
;; Author: Andrea Corallo <acorallo@gnu.org>
@@ -42,14 +42,14 @@
',expected-type-spec))))
(defconst comp-cstr-typespec-tests-alist
- `(;; 1
+ '(;; 1
(symbol . symbol)
;; 2
((or string array) . array)
;; 3
((or symbol number) . (or number symbol))
;; 4
- ((or cons atom) . (or atom cons)) ;; SBCL return T
+ ((or cons atom) . t) ;; SBCL return T
;; 5
((or integer number) . number)
;; 6
@@ -191,7 +191,7 @@
;; 74
((and boolean (or number marker)) . nil)
;; 75
- ((and atom (or number marker)) . (or marker number))
+ ((and atom (or number marker)) . number-or-marker)
;; 76
((and symbol (or number marker)) . nil)
;; 77
@@ -217,7 +217,20 @@
;; 87
((and (or null integer) (not (or null integer))) . nil)
;; 88
- ((and (or (member a b c)) (not (or (member a b)))) . (member c)))
+ ((and (or (member a b c)) (not (or (member a b)))) . (member c))
+ ;; 89
+ ((or cons symbol) . (or list symbol)) ;; FIXME: Why `list'?
+ ;; 90
+ ((or string char-table bool-vector vector) . array)
+ ;; 91
+ ((or string char-table bool-vector vector number) . (or array number))
+ ;; 92
+ ((or string char-table bool-vector vector cons symbol number) .
+ (or number sequence symbol))
+ ;; 93?
+ ;; FIXME: I get `cons' rather than `list'?
+ ;;((or null cons) . list)
+ )
"Alist type specifier -> expected type specifier."))
(defmacro comp-cstr-synthesize-tests ()
diff --git a/test/lisp/emacs-lisp/comp-tests.el b/test/lisp/emacs-lisp/comp-tests.el
index 79345ac9a4e..44c8acf790a 100644
--- a/test/lisp/emacs-lisp/comp-tests.el
+++ b/test/lisp/emacs-lisp/comp-tests.el
@@ -1,6 +1,6 @@
;;; comp-tests.el --- Tests for comp.el -*- lexical-binding:t -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/emacs-lisp/copyright-tests.el b/test/lisp/emacs-lisp/copyright-tests.el
index 5f8b5c67896..f69bb9f02d2 100644
--- a/test/lisp/emacs-lisp/copyright-tests.el
+++ b/test/lisp/emacs-lisp/copyright-tests.el
@@ -1,6 +1,6 @@
;;; copyright-tests.el --- tests for copyright.el -*- lexical-binding: t -*-
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/emacs-lisp/derived-tests.el b/test/lisp/emacs-lisp/derived-tests.el
index ca462c935f5..fa08b37c67d 100644
--- a/test/lisp/emacs-lisp/derived-tests.el
+++ b/test/lisp/emacs-lisp/derived-tests.el
@@ -1,6 +1,6 @@
;;; derived-tests.el --- tests for derived.el -*- lexical-binding: t; -*-
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/emacs-lisp/easy-mmode-tests.el b/test/lisp/emacs-lisp/easy-mmode-tests.el
index 6d65c22f5f2..26b5450d072 100644
--- a/test/lisp/emacs-lisp/easy-mmode-tests.el
+++ b/test/lisp/emacs-lisp/easy-mmode-tests.el
@@ -1,6 +1,6 @@
;;; easy-mmode-tests.el --- tests for easy-mmode.el -*- lexical-binding: t -*-
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/emacs-lisp/edebug-resources/edebug-test-code.el b/test/lisp/emacs-lisp/edebug-resources/edebug-test-code.el
index b0211c915e6..ea1f7991a68 100644
--- a/test/lisp/emacs-lisp/edebug-resources/edebug-test-code.el
+++ b/test/lisp/emacs-lisp/edebug-resources/edebug-test-code.el
@@ -1,6 +1,6 @@
;;; edebug-test-code.el --- Sample code for the Edebug test suite -*- lexical-binding:t -*-
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
;; Author: Gemini Lasswell
diff --git a/test/lisp/emacs-lisp/edebug-tests.el b/test/lisp/emacs-lisp/edebug-tests.el
index 28a7f38c576..8c0f729dc39 100644
--- a/test/lisp/emacs-lisp/edebug-tests.el
+++ b/test/lisp/emacs-lisp/edebug-tests.el
@@ -1,6 +1,6 @@
;;; edebug-tests.el --- Edebug test suite -*- lexical-binding:t -*-
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
;; Author: Gemini Lasswell
diff --git a/test/lisp/emacs-lisp/eieio-tests/eieio-test-methodinvoke.el b/test/lisp/emacs-lisp/eieio-tests/eieio-test-methodinvoke.el
index bb19a579e83..b244a56779a 100644
--- a/test/lisp/emacs-lisp/eieio-tests/eieio-test-methodinvoke.el
+++ b/test/lisp/emacs-lisp/eieio-tests/eieio-test-methodinvoke.el
@@ -1,6 +1,6 @@
;;; eieio-test-methodinvoke.el --- eieio tests for method invocation -*- lexical-binding:t -*-
-;; Copyright (C) 2005, 2008, 2010, 2013-2023 Free Software Foundation,
+;; Copyright (C) 2005, 2008, 2010, 2013-2024 Free Software Foundation,
;; Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/test/lisp/emacs-lisp/eieio-tests/eieio-test-persist.el b/test/lisp/emacs-lisp/eieio-tests/eieio-test-persist.el
index 4f13881dbd4..1bb75ae81f8 100644
--- a/test/lisp/emacs-lisp/eieio-tests/eieio-test-persist.el
+++ b/test/lisp/emacs-lisp/eieio-tests/eieio-test-persist.el
@@ -1,6 +1,6 @@
;;; eieio-test-persist.el --- Tests for eieio-persistent class -*- lexical-binding:t -*-
-;; Copyright (C) 2011-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2011-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/test/lisp/emacs-lisp/eieio-tests/eieio-tests.el b/test/lisp/emacs-lisp/eieio-tests/eieio-tests.el
index c9993341f98..83fc476c911 100644
--- a/test/lisp/emacs-lisp/eieio-tests/eieio-tests.el
+++ b/test/lisp/emacs-lisp/eieio-tests/eieio-tests.el
@@ -1,6 +1,6 @@
;;; eieio-tests.el --- eieio test routines -*- lexical-binding: t -*-
-;; Copyright (C) 1999-2003, 2005-2010, 2012-2023 Free Software
+;; Copyright (C) 1999-2003, 2005-2010, 2012-2024 Free Software
;; Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
@@ -1046,6 +1046,27 @@ Subclasses to override slot attributes."))
(should (eq (eieio-test--struct-a x) 1))
(should-error (setf (slot-value x 'c) 3) :type 'eieio-read-only)))
+(defclass foo-bug-66938 (eieio-instance-inheritor)
+ ((x :initarg :x
+ :accessor ref-x
+ :reader get-x))
+ "A class to test that delegation occurs under certain
+circumstances when using an accessor function, as it would when
+using the reader function.")
+
+(ert-deftest eieio-test-use-accessor-function-with-cloned-object ()
+ "The class FOO-BUG-66938 is a subclass of
+`eieio-instance-inheritor'. Therefore, given an instance OBJ1 of
+FOO-BUG-66938, and a clone (OBJ2), OBJ2 should delegate to OBJ1
+when accessing an unbound slot.
+
+In particular, its behavior should be identical to that of the
+reader function, when reading a slot."
+ (let* ((obj1 (foo-bug-66938 :x 4))
+ (obj2 (clone obj1)))
+ (should (eql (ref-x obj2) 4))
+ (should (eql (get-x obj2) (ref-x obj2)))))
+
(provide 'eieio-tests)
;;; eieio-tests.el ends here
diff --git a/test/lisp/emacs-lisp/ert-font-lock-resources/broken.js b/test/lisp/emacs-lisp/ert-font-lock-resources/broken.js
new file mode 100644
index 00000000000..69c1c5cca88
--- /dev/null
+++ b/test/lisp/emacs-lisp/ert-font-lock-resources/broken.js
@@ -0,0 +1,3 @@
+var abc = function(d) {
+// ^ wrong-face
+};
diff --git a/test/lisp/emacs-lisp/ert-font-lock-resources/correct.js b/test/lisp/emacs-lisp/ert-font-lock-resources/correct.js
new file mode 100644
index 00000000000..5e614c64755
--- /dev/null
+++ b/test/lisp/emacs-lisp/ert-font-lock-resources/correct.js
@@ -0,0 +1,3 @@
+var abc = function(d) {
+// ^ font-lock-variable-name-face
+};
diff --git a/test/lisp/emacs-lisp/ert-font-lock-tests.el b/test/lisp/emacs-lisp/ert-font-lock-tests.el
new file mode 100644
index 00000000000..e0ba1e949b2
--- /dev/null
+++ b/test/lisp/emacs-lisp/ert-font-lock-tests.el
@@ -0,0 +1,464 @@
+;;; ert-font-lock-tests.el --- ERT Font Lock tests -*- lexical-binding: t -*-
+
+;; Copyright (C) 2023-2024 Free Software Foundation, Inc.
+
+;; Author: Vladimir Kazanov
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; This file is part of ERT Font Lock, an extension to the Emacs Lisp
+;; Regression Test library (ERT) providing a convenient way to check
+;; syntax highlighting provided by font-lock.
+;;
+;; See ert-font-lock.el for details, and below for example usage of
+;; ert-font-lock facilities.
+
+(require 'ert)
+(require 'ert-x)
+(require 'ert-font-lock)
+
+;;; Helpers
+;;
+
+(defmacro with-temp-buffer-str-mode (mode str &rest body)
+ "Create a buffer with STR contents and MODE. "
+ (declare (indent 1) (debug t))
+ `(with-temp-buffer
+ (insert ,str)
+ (,mode)
+ (goto-char (point-min))
+ ,@body))
+
+;;; Comment parsing tests
+;;
+
+(ert-deftest test-line-comment-p--fundamental ()
+ (with-temp-buffer-str-mode fundamental-mode
+ "// comment\n"
+ (should-not (ert-font-lock--line-comment-p))))
+
+(ert-deftest test-line-comment-p--emacs-lisp ()
+ (with-temp-buffer-str-mode emacs-lisp-mode
+ "not comment
+;; comment
+"
+ (should-not (ert-font-lock--line-comment-p))
+ (forward-line)
+ (should (ert-font-lock--line-comment-p))
+ (forward-line)
+ (should-not (ert-font-lock--line-comment-p))))
+
+(ert-deftest test-line-comment-p--shell-script ()
+ (with-temp-buffer-str-mode shell-script-mode
+ "echo Not a comment
+# comment
+"
+ (should-not (ert-font-lock--line-comment-p))
+ (forward-line)
+ (should (ert-font-lock--line-comment-p))))
+
+(declare-function php-mode "php-mode")
+(ert-deftest test-line-comment-p--php ()
+ (skip-unless (featurep 'php-mode))
+
+ (with-temp-buffer-str-mode php-mode
+ "echo 'Not a comment'
+// comment
+/* comment */
+"
+ (should-not (ert-font-lock--line-comment-p))
+ (forward-line)
+ (should (ert-font-lock--line-comment-p))
+ (forward-line)
+ (should (ert-font-lock--line-comment-p))))
+
+
+(ert-deftest test-line-comment-p--javascript ()
+ (with-temp-buffer-str-mode javascript-mode
+ "// comment
+
+ // comment, after a blank line
+
+var abc = function(d) {};
+"
+ (should (ert-font-lock--line-comment-p))
+
+ (forward-line)
+ (should-not (ert-font-lock--line-comment-p))
+
+ (forward-line)
+ (should (ert-font-lock--line-comment-p))
+
+ (forward-line)
+ (should-not (ert-font-lock--line-comment-p))
+
+ (forward-line)
+ (should-not (ert-font-lock--line-comment-p))))
+
+(ert-deftest test-line-comment-p--python ()
+
+ (with-temp-buffer-str-mode python-mode
+ "# comment
+
+ # comment
+print(\"Hello, world!\")"
+ (should (ert-font-lock--line-comment-p))
+
+ (forward-line)
+ (should-not (ert-font-lock--line-comment-p))
+
+ (forward-line)
+ (should (ert-font-lock--line-comment-p))
+
+ (forward-line)
+ (should-not (ert-font-lock--line-comment-p))))
+
+(ert-deftest test-line-comment-p--c ()
+
+ (with-temp-buffer-str-mode c-mode
+ "// comment
+/* also comment */"
+ (should (ert-font-lock--line-comment-p))
+
+ (forward-line)
+ (should (ert-font-lock--line-comment-p))))
+
+(ert-deftest test-parse-comments--single-line-error ()
+ (let* ((str "// ^ face.face1"))
+ (with-temp-buffer
+ (insert str)
+ (javascript-mode)
+
+ (should-error (ert-font-lock--parse-comments)))))
+
+(ert-deftest test-parse-comments--single-line-single-caret ()
+ (let* ((str "
+first
+// ^ face.face1
+")
+ asserts)
+ (with-temp-buffer
+ (insert str)
+ (javascript-mode)
+
+ (setq asserts (ert-font-lock--parse-comments))
+ (should (eql (length asserts) 1))
+ (should (equal (car asserts)
+ '(:line-checked 2 :line-assert 3 :column-checked 3 :face "face.face1" :negation nil))))))
+
+(ert-deftest test-parse-comments--caret-negation ()
+ (let* ((str "
+first
+// ^ !face
+// ^ face
+")
+ asserts)
+ (with-temp-buffer
+ (insert str)
+ (javascript-mode)
+
+ (setq asserts (ert-font-lock--parse-comments))
+ (should (eql (length asserts) 2))
+ (should (equal asserts
+ '((:line-checked 2 :line-assert 3 :column-checked 3 :face "face" :negation t)
+ (:line-checked 2 :line-assert 4 :column-checked 3 :face "face" :negation nil)))))))
+
+
+(ert-deftest test-parse-comments--single-line-multiple-carets ()
+ (let* ((str "
+first
+// ^ face1
+// ^ face.face2
+// ^ face-face.face3
+ // ^ face_face.face4
+")
+ asserts)
+
+ (with-temp-buffer
+ (insert str)
+ (javascript-mode)
+
+ (setq asserts (ert-font-lock--parse-comments))
+ (should (eql (length asserts) 4))
+ (should (equal asserts
+ '((:line-checked 2 :line-assert 3 :column-checked 3 :face "face1" :negation nil)
+ (:line-checked 2 :line-assert 4 :column-checked 7 :face "face.face2" :negation nil)
+ (:line-checked 2 :line-assert 5 :column-checked 7 :face "face-face.face3" :negation nil)
+ (:line-checked 2 :line-assert 6 :column-checked 7 :face "face_face.face4" :negation nil)))))))
+
+(ert-deftest test-parse-comments--multiple-line-multiple-carets ()
+ (let* ((str "
+first
+// ^ face1
+second
+// ^ face2
+// ^ face3
+third
+")
+ asserts)
+ (with-temp-buffer
+ (insert str)
+ (javascript-mode)
+
+ (setq asserts (ert-font-lock--parse-comments))
+ (should (eql (length asserts) 3))
+ (should (equal asserts
+ '((:line-checked 2 :line-assert 3 :column-checked 3 :face "face1" :negation nil)
+ (:line-checked 4 :line-assert 5 :column-checked 3 :face "face2" :negation nil)
+ (:line-checked 4 :line-assert 6 :column-checked 5 :face "face3" :negation nil)))))))
+
+
+(ert-deftest test-parse-comments--arrow-single-line-single ()
+ (let* ((str "
+first
+// <- face1
+")
+ asserts)
+ (with-temp-buffer
+ (insert str)
+ (javascript-mode)
+
+ (setq asserts (ert-font-lock--parse-comments))
+ (should (eql (length asserts) 1))
+ (should (equal (car asserts)
+ '(:line-checked 2 :line-assert 3 :column-checked 0 :face "face1" :negation nil))))))
+
+
+(ert-deftest test-parse-comments-arrow-multiple-line-single ()
+ (let* ((str "
+first
+// <- face1
+ // <- face2
+ // <- face3
+")
+ asserts)
+ (with-temp-buffer
+ (insert str)
+ (javascript-mode)
+
+ (setq asserts (ert-font-lock--parse-comments))
+ (should (eql (length asserts) 3))
+ (should (equal asserts
+ '((:line-checked 2 :line-assert 3 :column-checked 0 :face "face1" :negation nil)
+ (:line-checked 2 :line-assert 4 :column-checked 2 :face "face2" :negation nil)
+ (:line-checked 2 :line-assert 5 :column-checked 4 :face "face3" :negation nil)))))))
+
+(ert-deftest test-parse-comments--non-assert-comment-single ()
+ (let* ((str "
+// first
+// ^ comment-face
+")
+ asserts)
+ (with-temp-buffer
+ (insert str)
+ (javascript-mode)
+
+ (setq asserts (ert-font-lock--parse-comments))
+ (should (eql (length asserts) 1))
+ (should (equal (car asserts)
+ '(:line-checked 2 :line-assert 3 :column-checked 4 :face "comment-face" :negation nil))))))
+
+(ert-deftest test-parse-comments--non-assert-comment-multiple ()
+ (let* ((str "
+// first second third
+// ^ comment-face
+// ^ comment-face
+// ^ comment-face
+")
+ asserts)
+ (with-temp-buffer
+ (insert str)
+ (javascript-mode)
+
+ (setq asserts (ert-font-lock--parse-comments))
+ (should (eql (length asserts) 3))
+ (should (equal asserts
+ '((:line-checked 2 :line-assert 3 :column-checked 4 :face "comment-face" :negation nil)
+ (:line-checked 2 :line-assert 4 :column-checked 10 :face "comment-face" :negation nil)
+ (:line-checked 2 :line-assert 5 :column-checked 18 :face "comment-face" :negation nil)))))))
+
+
+(ert-deftest test-parse-comments--multiline-comment-single ()
+ (let* ((str "
+/*
+ this is a comment
+ ^ comment-face
+ */
+")
+ asserts)
+ (with-temp-buffer
+ (insert str)
+ (c-mode)
+
+ (setq asserts (ert-font-lock--parse-comments))
+ (should (eql (length asserts) 1))
+ (should (equal (car asserts)
+ '(:line-checked 3 :line-assert 4 :column-checked 3 :face "comment-face" :negation nil))))))
+
+(ert-deftest test-parse-comments--multiline-comment-multiple ()
+ (let* ((str "
+/*
+ this is a comment
+ ^ comment-face
+ another comment
+ ^ comment-face
+ */
+")
+ asserts)
+ (with-temp-buffer
+ (insert str)
+ (c-mode)
+
+ (setq asserts (ert-font-lock--parse-comments))
+ (should (eql (length asserts) 2))
+ (should (equal asserts
+ '((:line-checked 3 :line-assert 4 :column-checked 3 :face "comment-face" :negation nil)
+ (:line-checked 5 :line-assert 6 :column-checked 4 :face "comment-face" :negation nil)))))))
+
+;;; Syntax highlighting assertion tests
+;;
+
+(ert-deftest test-syntax-highlight-inline--caret-multiple-faces ()
+ (let ((str "
+var abc = function(d) {
+// ^ font-lock-variable-name-face
+ // ^ font-lock-keyword-face
+ // ^ font-lock-variable-name-face
+};
+
+"))
+ (with-temp-buffer
+ (insert str)
+ (javascript-mode)
+ (font-lock-ensure)
+
+ (ert-font-lock--check-faces
+ (ert-font-lock--parse-comments)))))
+
+(ert-deftest test-syntax-highlight-inline--caret-wrong-face ()
+ (let* ((str "
+var abc = function(d) {
+// ^ not-a-face
+};
+"))
+ (with-temp-buffer
+ (insert str)
+ (javascript-mode)
+ (font-lock-ensure)
+
+ (should-error (ert-font-lock--check-faces
+ (ert-font-lock--parse-comments))))))
+
+
+(ert-deftest test-syntax-highlight-inline--comment-face ()
+ (let* ((str "
+// this is a comment
+// ^ font-lock-comment-face
+// ^ font-lock-comment-face
+// ^ font-lock-comment-face
+"))
+ (with-temp-buffer
+ (insert str)
+ (javascript-mode)
+ (font-lock-ensure)
+
+ (ert-font-lock--check-faces
+ (ert-font-lock--parse-comments)))))
+
+
+(ert-deftest test-syntax-highlight-inline--multiline-comment-face ()
+ (let* ((str "
+/*
+ this is a comment
+ ^ font-lock-comment-face
+ another comment
+ more comments
+ ^ font-lock-comment-face
+ */
+"))
+ (with-temp-buffer
+ (insert str)
+ (c-mode)
+ (font-lock-ensure)
+
+ (ert-font-lock--check-faces
+ (ert-font-lock--parse-comments)))))
+
+
+(ert-deftest test-font-lock-test-string--correct ()
+ (ert-font-lock-test-string
+ "
+var abc = function(d) {
+// <- font-lock-keyword-face
+// ^ font-lock-variable-name-face
+ // ^ font-lock-keyword-face
+ // ^ font-lock-variable-name-face
+};
+
+"
+ 'javascript-mode))
+
+(ert-deftest test-font-lock-test-file--correct ()
+ (ert-font-lock-test-file
+ (ert-resource-file "correct.js")
+ 'javascript-mode))
+
+(ert-deftest test-font-lock-test-file--wrong ()
+ :expected-result :failed
+ (ert-font-lock-test-file
+ (ert-resource-file "broken.js")
+ 'javascript-mode))
+
+;;; Macro tests
+;;
+
+(ert-font-lock-deftest test-macro-test--correct-highlighting
+ emacs-lisp-mode
+ "
+(defun fun ())
+;; ^ font-lock-keyword-face
+;; ^ font-lock-function-name-face")
+
+(ert-font-lock-deftest test-macro-test--docstring
+ "A test with a docstring."
+ emacs-lisp-mode
+ "
+(defun fun ())
+;; ^ font-lock-keyword-face"
+ )
+
+(ert-font-lock-deftest test-macro-test--failing
+ "A failing test."
+ :expected-result :failed
+ emacs-lisp-mode
+ "
+(defun fun ())
+;; ^ wrong-face")
+
+(ert-font-lock-deftest-file test-macro-test--file
+ "Test reading correct assertions from a file"
+ javascript-mode
+ "correct.js")
+
+(ert-font-lock-deftest-file test-macro-test--file-failing
+ "Test reading wrong assertions from a file"
+ :expected-result :failed
+ javascript-mode
+ "broken.js")
+
+;;; ert-font-lock-tests.el ends here
diff --git a/test/lisp/emacs-lisp/ert-tests.el b/test/lisp/emacs-lisp/ert-tests.el
index 7713a0f6e38..768a3a726aa 100644
--- a/test/lisp/emacs-lisp/ert-tests.el
+++ b/test/lisp/emacs-lisp/ert-tests.el
@@ -1,6 +1,6 @@
;;; ert-tests.el --- ERT's self-tests -*- lexical-binding: t -*-
-;; Copyright (C) 2007-2008, 2010-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2007-2008, 2010-2024 Free Software Foundation, Inc.
;; Author: Christian Ohler <ohler@gnu.org>
@@ -304,6 +304,20 @@ failed or if there was a problem."
(cl-macrolet ((test () (error "Foo")))
(should-error (test))))
+(ert-deftest ert-test-skip-when ()
+ ;; Don't skip.
+ (let ((test (make-ert-test :body (lambda () (skip-when nil)))))
+ (let ((result (ert-run-test test)))
+ (should (ert-test-passed-p result))))
+ ;; Skip.
+ (let ((test (make-ert-test :body (lambda () (skip-when t)))))
+ (let ((result (ert-run-test test)))
+ (should (ert-test-skipped-p result))))
+ ;; Skip in case of error.
+ (let ((test (make-ert-test :body (lambda () (skip-when (error "Foo"))))))
+ (let ((result (ert-run-test test)))
+ (should (ert-test-skipped-p result)))))
+
(ert-deftest ert-test-skip-unless ()
;; Don't skip.
(let ((test (make-ert-test :body (lambda () (skip-unless t)))))
diff --git a/test/lisp/emacs-lisp/ert-x-tests.el b/test/lisp/emacs-lisp/ert-x-tests.el
index 6be2ca18ff1..71ccab52834 100644
--- a/test/lisp/emacs-lisp/ert-x-tests.el
+++ b/test/lisp/emacs-lisp/ert-x-tests.el
@@ -1,6 +1,6 @@
;;; ert-x-tests.el --- Tests for ert-x.el -*- lexical-binding:t -*-
-;; Copyright (C) 2008, 2010-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008, 2010-2024 Free Software Foundation, Inc.
;; Author: Phil Hagelberg
;; Christian Ohler <ohler@gnu.org>
diff --git a/test/lisp/emacs-lisp/faceup-resources/faceup-test-mode.el b/test/lisp/emacs-lisp/faceup-resources/faceup-test-mode.el
index 4988babcfbd..9dc4f70a121 100644
--- a/test/lisp/emacs-lisp/faceup-resources/faceup-test-mode.el
+++ b/test/lisp/emacs-lisp/faceup-resources/faceup-test-mode.el
@@ -1,6 +1,6 @@
;;; faceup-test-mode.el --- Dummy major mode for testing `faceup'. -*- lexical-binding:t -*-
-;; Copyright (C) 2014-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2014-2024 Free Software Foundation, Inc.
;; Author: Anders Lindgren
;; Keywords: languages, faces
diff --git a/test/lisp/emacs-lisp/faceup-resources/faceup-test-this-file-directory.el b/test/lisp/emacs-lisp/faceup-resources/faceup-test-this-file-directory.el
index 9d677f48872..f92a8a9c421 100644
--- a/test/lisp/emacs-lisp/faceup-resources/faceup-test-this-file-directory.el
+++ b/test/lisp/emacs-lisp/faceup-resources/faceup-test-this-file-directory.el
@@ -1,6 +1,6 @@
;;; faceup-test-this-file-directory.el --- Support file for faceup tests -*- lexical-binding:t -*-
-;; Copyright (C) 2014-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2014-2024 Free Software Foundation, Inc.
;; Author: Anders Lindgren
;; Keywords: languages, faces
diff --git a/test/lisp/emacs-lisp/faceup-tests/faceup-test-basics.el b/test/lisp/emacs-lisp/faceup-tests/faceup-test-basics.el
index c162354aa36..3f4f3835639 100644
--- a/test/lisp/emacs-lisp/faceup-tests/faceup-test-basics.el
+++ b/test/lisp/emacs-lisp/faceup-tests/faceup-test-basics.el
@@ -1,6 +1,6 @@
;;; faceup-test-basics.el --- Tests for the `faceup' package. -*- lexical-binding:t -*-
-;; Copyright (C) 2014-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2014-2024 Free Software Foundation, Inc.
;; Author: Anders Lindgren
;; Keywords: languages, faces
diff --git a/test/lisp/emacs-lisp/faceup-tests/faceup-test-files.el b/test/lisp/emacs-lisp/faceup-tests/faceup-test-files.el
index 99d3223f311..9c00505d93e 100644
--- a/test/lisp/emacs-lisp/faceup-tests/faceup-test-files.el
+++ b/test/lisp/emacs-lisp/faceup-tests/faceup-test-files.el
@@ -1,6 +1,6 @@
;;; faceup-test-files.el --- Self test of `faceup' using dummy major mode. -*- lexical-binding:t -*-
-;; Copyright (C) 2014-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2014-2024 Free Software Foundation, Inc.
;; Author: Anders Lindgren
;; Keywords: languages, faces
diff --git a/test/lisp/emacs-lisp/find-func-tests.el b/test/lisp/emacs-lisp/find-func-tests.el
index 7251b76157b..a685a6cbabb 100644
--- a/test/lisp/emacs-lisp/find-func-tests.el
+++ b/test/lisp/emacs-lisp/find-func-tests.el
@@ -1,6 +1,6 @@
;;; find-func-tests.el --- Unit tests for find-func.el -*- lexical-binding: t; -*-
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
;; Keywords:
@@ -32,7 +32,7 @@
(ert-deftest find-func-tests--library-completion () ;bug#43393
;; FIXME: How can we make this work in batch (see also
;; `mule-cmds--test-universal-coding-system-argument')?
- ;; (skip-unless (not noninteractive))
+ ;; (skip-when noninteractive)
;; Check that `partial-completion' works when completing library names.
(should (equal "org/org"
(ert-simulate-keys
diff --git a/test/lisp/emacs-lisp/float-sup-tests.el b/test/lisp/emacs-lisp/float-sup-tests.el
index f0e192d1e76..0d00050f75d 100644
--- a/test/lisp/emacs-lisp/float-sup-tests.el
+++ b/test/lisp/emacs-lisp/float-sup-tests.el
@@ -1,6 +1,6 @@
;;; float-sup-tests.el --- Tests for float-sup.el -*- lexical-binding:t -*-
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/emacs-lisp/generator-tests.el b/test/lisp/emacs-lisp/generator-tests.el
index fa4df77b9b7..68fdc9324e2 100644
--- a/test/lisp/emacs-lisp/generator-tests.el
+++ b/test/lisp/emacs-lisp/generator-tests.el
@@ -1,6 +1,6 @@
;;; generator-tests.el --- Testing generators -*- lexical-binding: t -*-
-;; Copyright (C) 2015-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2024 Free Software Foundation, Inc.
;; Author: Daniel Colascione <dancol@dancol.org>
;; Keywords:
diff --git a/test/lisp/emacs-lisp/gv-tests.el b/test/lisp/emacs-lisp/gv-tests.el
index f57b2c69fe4..4cc235c141f 100644
--- a/test/lisp/emacs-lisp/gv-tests.el
+++ b/test/lisp/emacs-lisp/gv-tests.el
@@ -1,6 +1,6 @@
;;; gv-tests.el --- tests for gv.el -*- lexical-binding: t; -*-
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/emacs-lisp/icons-tests.el b/test/lisp/emacs-lisp/icons-tests.el
index fdfbd1ff7cb..fa320a49866 100644
--- a/test/lisp/emacs-lisp/icons-tests.el
+++ b/test/lisp/emacs-lisp/icons-tests.el
@@ -1,6 +1,6 @@
;;; icons-tests.el --- Tests for icons.el -*- lexical-binding: t; -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/emacs-lisp/let-alist-tests.el b/test/lisp/emacs-lisp/let-alist-tests.el
index cf4cba50367..235e5908cc0 100644
--- a/test/lisp/emacs-lisp/let-alist-tests.el
+++ b/test/lisp/emacs-lisp/let-alist-tests.el
@@ -1,6 +1,6 @@
;;; let-alist.el --- tests for file handling. -*- lexical-binding: t; -*-
-;; Copyright (C) 2012-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2012-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/emacs-lisp/lisp-mnt-tests.el b/test/lisp/emacs-lisp/lisp-mnt-tests.el
index c056761f0f9..e32480ada46 100644
--- a/test/lisp/emacs-lisp/lisp-mnt-tests.el
+++ b/test/lisp/emacs-lisp/lisp-mnt-tests.el
@@ -1,6 +1,6 @@
;;; lisp-mnt-tests.el --- Tests for lisp-mnt -*- lexical-binding: t; -*-
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
@@ -30,6 +30,26 @@
'(("Bob Weiner" . "rsw@gnu.org")
("Mats Lidell" . "matsl@gnu.org")))))
+(ert-deftest lm--tests-lm-package-requires ()
+ (with-temp-buffer
+ (insert ";; Package-Requires: ((emacs 29.1))")
+ (should (equal (lm-package-requires) '((emacs 29.1)))))
+ (with-temp-buffer
+ (insert ";; Package-Requires: ((emacs \"26.3\") (jsonrpc \"1.0.16\") (flymake \"1.2.1\") (project \"0.9.8\") (xref \"1.6.2\") (eldoc \"1.14.0\") (seq \"2.23\") (external-completion \"0.1\"))")
+ (should (equal (lm-package-requires)
+ '((emacs "26.3") (jsonrpc "1.0.16") (flymake "1.2.1")
+ (project "0.9.8") (xref "1.6.2") (eldoc "1.14.0")
+ (seq "2.23") (external-completion "0.1")))))
+ (with-temp-buffer
+ (insert ";; Package-Requires: ((emacs \"26.3\") (jsonrpc \"1.0.16\") (flymake \"1.2.1\")\n"
+ ";; (project \"0.9.8\") (xref \"1.6.2\") (eldoc \"1.14.0\")\n"
+ ";; (seq \"2.23\") (external-completion \"0.1\"))")
+ (should (equal (lm-package-requires)
+ '((emacs "26.3") (jsonrpc "1.0.16") (flymake "1.2.1")
+ (project "0.9.8") (xref "1.6.2") (eldoc "1.14.0")
+ (seq "2.23") (external-completion "0.1"))))))
+
+
(ert-deftest lm--tests-lm-website ()
(with-temp-buffer
(insert ";; URL: https://example.org/foo")
diff --git a/test/lisp/emacs-lisp/lisp-mode-tests.el b/test/lisp/emacs-lisp/lisp-mode-tests.el
index 825e6b6ab80..da02be65d03 100644
--- a/test/lisp/emacs-lisp/lisp-mode-tests.el
+++ b/test/lisp/emacs-lisp/lisp-mode-tests.el
@@ -1,6 +1,6 @@
;;; lisp-mode-tests.el --- Test Lisp editing commands -*- lexical-binding: t; -*-
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/emacs-lisp/lisp-tests.el b/test/lisp/emacs-lisp/lisp-tests.el
index 2e5e2a740b1..0d627b01151 100644
--- a/test/lisp/emacs-lisp/lisp-tests.el
+++ b/test/lisp/emacs-lisp/lisp-tests.el
@@ -1,6 +1,6 @@
;;; lisp-tests.el --- Test Lisp editing commands -*- lexical-binding: t; -*-
-;; Copyright (C) 2013-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2024 Free Software Foundation, Inc.
;; Author: Aaron S. Hawley <aaron.s.hawley@gmail.com>
;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
diff --git a/test/lisp/emacs-lisp/macroexp-resources/m1.el b/test/lisp/emacs-lisp/macroexp-resources/m1.el
index 5b35f60ad3d..940630cc319 100644
--- a/test/lisp/emacs-lisp/macroexp-resources/m1.el
+++ b/test/lisp/emacs-lisp/macroexp-resources/m1.el
@@ -1,6 +1,6 @@
;;; m1.el --- Some sample code for macroexp-tests -*- lexical-binding: t; -*-
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
;; Keywords:
diff --git a/test/lisp/emacs-lisp/macroexp-resources/m2.el b/test/lisp/emacs-lisp/macroexp-resources/m2.el
index fb11b56c378..981ade30b4e 100644
--- a/test/lisp/emacs-lisp/macroexp-resources/m2.el
+++ b/test/lisp/emacs-lisp/macroexp-resources/m2.el
@@ -1,6 +1,6 @@
;;; m2.el --- More sample code for macroexp-tests -*- lexical-binding: t; -*-
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
;; Keywords:
diff --git a/test/lisp/emacs-lisp/macroexp-resources/vk.el b/test/lisp/emacs-lisp/macroexp-resources/vk.el
index c892b279923..460b7a8e516 100644
--- a/test/lisp/emacs-lisp/macroexp-resources/vk.el
+++ b/test/lisp/emacs-lisp/macroexp-resources/vk.el
@@ -1,6 +1,6 @@
;;; vk.el --- test code for macroexp-tests -*- lexical-binding: t -*-
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/emacs-lisp/macroexp-tests.el b/test/lisp/emacs-lisp/macroexp-tests.el
index d0efbfd28c1..2a57de248a2 100644
--- a/test/lisp/emacs-lisp/macroexp-tests.el
+++ b/test/lisp/emacs-lisp/macroexp-tests.el
@@ -1,6 +1,6 @@
;;; macroexp-tests.el --- Tests for macroexp.el -*- lexical-binding: t; -*-
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
;; Keywords:
diff --git a/test/lisp/emacs-lisp/map-tests.el b/test/lisp/emacs-lisp/map-tests.el
index 2204743f794..dc8121b0582 100644
--- a/test/lisp/emacs-lisp/map-tests.el
+++ b/test/lisp/emacs-lisp/map-tests.el
@@ -1,6 +1,6 @@
;;; map-tests.el --- Tests for map.el -*- lexical-binding:t -*-
-;; Copyright (C) 2015-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2024 Free Software Foundation, Inc.
;; Author: Nicolas Petton <nicolas@petton.fr>
;; Maintainer: emacs-devel@gnu.org
diff --git a/test/lisp/emacs-lisp/memory-report-tests.el b/test/lisp/emacs-lisp/memory-report-tests.el
index 1bca74ca7c4..52dcb14b540 100644
--- a/test/lisp/emacs-lisp/memory-report-tests.el
+++ b/test/lisp/emacs-lisp/memory-report-tests.el
@@ -1,6 +1,6 @@
;;; memory-report-tests.el --- tests for memory-report.el -*- lexical-binding: t -*-
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/emacs-lisp/multisession-tests.el b/test/lisp/emacs-lisp/multisession-tests.el
index 639a8ab5219..edbc6bf02c4 100644
--- a/test/lisp/emacs-lisp/multisession-tests.el
+++ b/test/lisp/emacs-lisp/multisession-tests.el
@@ -1,6 +1,6 @@
;;; multisession-tests.el --- Tests for multisession.el -*- lexical-binding: t; -*-
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/emacs-lisp/nadvice-tests.el b/test/lisp/emacs-lisp/nadvice-tests.el
index 7dfa936214a..1a0b8468841 100644
--- a/test/lisp/emacs-lisp/nadvice-tests.el
+++ b/test/lisp/emacs-lisp/nadvice-tests.el
@@ -1,6 +1,6 @@
;;; nadvice-tests.el --- Test suite for the new advice thingy. -*- lexical-binding:t -*-
-;; Copyright (C) 2012-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2012-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/emacs-lisp/oclosure-tests.el b/test/lisp/emacs-lisp/oclosure-tests.el
index a7f2d1017a9..4760f403158 100644
--- a/test/lisp/emacs-lisp/oclosure-tests.el
+++ b/test/lisp/emacs-lisp/oclosure-tests.el
@@ -1,6 +1,6 @@
;;; oclosure-tests.e; --- Tests for Open Closures -*- lexical-binding: t; -*-
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/emacs-lisp/package-resources/signed/update-signatures.sh b/test/lisp/emacs-lisp/package-resources/signed/update-signatures.sh
index 3f3e2fc70d2..8bb66da26dc 100755
--- a/test/lisp/emacs-lisp/package-resources/signed/update-signatures.sh
+++ b/test/lisp/emacs-lisp/package-resources/signed/update-signatures.sh
@@ -2,7 +2,7 @@
# Generate a new key and update the signatures for tests.
-# Copyright (C) 2020-2023 Free Software Foundation, Inc.
+# Copyright (C) 2020-2024 Free Software Foundation, Inc.
# This file is part of GNU Emacs.
diff --git a/test/lisp/emacs-lisp/package-tests.el b/test/lisp/emacs-lisp/package-tests.el
index 113b4ec12a8..d95b94f2145 100644
--- a/test/lisp/emacs-lisp/package-tests.el
+++ b/test/lisp/emacs-lisp/package-tests.el
@@ -1,6 +1,6 @@
;;; package-tests.el --- Tests for the Emacs package system -*- lexical-binding:t -*-
-;; Copyright (C) 2013-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2024 Free Software Foundation, Inc.
;; Author: Daniel Hackney <dan@haxney.org>
;; Version: 1.0
@@ -125,6 +125,7 @@
abbreviated-home-dir
package--initialized
package-alist
+ package-selected-packages
,@(if update-news
'(package-update-news-on-upload t)
(list (cl-gensym)))
@@ -307,6 +308,21 @@ Must called from within a `tar-mode' buffer."
(package-delete (cadr (assq 'v7-withsub package-alist))))
))
+(ert-deftest package-test-bug65475 ()
+ "Deleting the last package clears `package-selected-packages'."
+ (with-package-test (:basedir (ert-resource-directory))
+ (package-initialize)
+ (let* ((pkg-el "simple-single-1.3.el")
+ (source-file (expand-file-name pkg-el (ert-resource-directory))))
+ (package-install-file source-file)
+ (should package-alist)
+ (should package-selected-packages)
+ (let ((desc (cadr (assq 'simple-single package-alist))))
+ (should desc)
+ (package-delete desc))
+ (should-not package-alist)
+ (should-not package-selected-packages))))
+
(ert-deftest package-test-install-file-EOLs ()
"Install same file multiple time with `package-install-file'
but with a different end of line convention (bug#48137)."
diff --git a/test/lisp/emacs-lisp/pcase-tests.el b/test/lisp/emacs-lisp/pcase-tests.el
index 799e8d36647..d062965952a 100644
--- a/test/lisp/emacs-lisp/pcase-tests.el
+++ b/test/lisp/emacs-lisp/pcase-tests.el
@@ -1,6 +1,6 @@
;;; pcase-tests.el --- Test suite for pcase macro. -*- lexical-binding:t -*-
-;; Copyright (C) 2012-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2012-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/emacs-lisp/pp-tests.el b/test/lisp/emacs-lisp/pp-tests.el
index 1b248e19a31..b663fb365a8 100644
--- a/test/lisp/emacs-lisp/pp-tests.el
+++ b/test/lisp/emacs-lisp/pp-tests.el
@@ -1,6 +1,6 @@
;;; pp-tests.el --- Test suite for pretty printer. -*- lexical-binding: t -*-
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/emacs-lisp/range-tests.el b/test/lisp/emacs-lisp/range-tests.el
index c35a95a4c1e..c680ab5a9cd 100644
--- a/test/lisp/emacs-lisp/range-tests.el
+++ b/test/lisp/emacs-lisp/range-tests.el
@@ -1,6 +1,6 @@
;;; range-tests.el --- Tests for range.el -*- lexical-binding: t; -*-
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/emacs-lisp/regexp-opt-tests.el b/test/lisp/emacs-lisp/regexp-opt-tests.el
index 1eefd7b210c..1f168d2895c 100644
--- a/test/lisp/emacs-lisp/regexp-opt-tests.el
+++ b/test/lisp/emacs-lisp/regexp-opt-tests.el
@@ -1,6 +1,6 @@
;;; regexp-opt-tests.el --- Tests for regexp-opt.el -*- lexical-binding: t -*-
-;; Copyright (C) 2013-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2024 Free Software Foundation, Inc.
;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
;; Keywords: internal
diff --git a/test/lisp/emacs-lisp/ring-tests.el b/test/lisp/emacs-lisp/ring-tests.el
index f8f2cfc37de..8cf81818c39 100644
--- a/test/lisp/emacs-lisp/ring-tests.el
+++ b/test/lisp/emacs-lisp/ring-tests.el
@@ -1,6 +1,6 @@
;;; ring-tests.el --- Tests for ring.el -*- lexical-binding: t; -*-
-;; Copyright (C) 2016-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2016-2024 Free Software Foundation, Inc.
;; Author: Simen Heggestøyl <simenheg@gmail.com>
;; Keywords:
diff --git a/test/lisp/emacs-lisp/rmc-tests.el b/test/lisp/emacs-lisp/rmc-tests.el
index bf0ff59151d..b1fbcd25bd0 100644
--- a/test/lisp/emacs-lisp/rmc-tests.el
+++ b/test/lisp/emacs-lisp/rmc-tests.el
@@ -1,6 +1,6 @@
;;; rmc-tests.el --- Test suite for rmc.el -*- lexical-binding: t -*-
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
;; Author: Tino Calancha <tino.calancha@gmail.com>
;; Keywords:
diff --git a/test/lisp/emacs-lisp/rx-tests.el b/test/lisp/emacs-lisp/rx-tests.el
index e773ddf158e..072209bcbcc 100644
--- a/test/lisp/emacs-lisp/rx-tests.el
+++ b/test/lisp/emacs-lisp/rx-tests.el
@@ -1,6 +1,6 @@
;;; rx-tests.el --- tests for rx.el -*- lexical-binding: t -*-
-;; Copyright (C) 2016-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2016-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/emacs-lisp/seq-tests.el b/test/lisp/emacs-lisp/seq-tests.el
index 71ff991c215..c06ceb00bdb 100644
--- a/test/lisp/emacs-lisp/seq-tests.el
+++ b/test/lisp/emacs-lisp/seq-tests.el
@@ -1,6 +1,6 @@
;;; seq-tests.el --- Tests for seq.el -*- lexical-binding:t -*-
-;; Copyright (C) 2014-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2014-2024 Free Software Foundation, Inc.
;; Author: Nicolas Petton <nicolas@petton.fr>
;; Maintainer: emacs-devel@gnu.org
diff --git a/test/lisp/emacs-lisp/shadow-tests.el b/test/lisp/emacs-lisp/shadow-tests.el
index d3b18aa5987..3c88bd42f06 100644
--- a/test/lisp/emacs-lisp/shadow-tests.el
+++ b/test/lisp/emacs-lisp/shadow-tests.el
@@ -1,6 +1,6 @@
;;; shadow-tests.el --- Test suite for shadow. -*- lexical-binding: t -*-
-;; Copyright (C) 2018-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2018-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/emacs-lisp/shortdoc-tests.el b/test/lisp/emacs-lisp/shortdoc-tests.el
index 596b47d2543..3aaccff707c 100644
--- a/test/lisp/emacs-lisp/shortdoc-tests.el
+++ b/test/lisp/emacs-lisp/shortdoc-tests.el
@@ -1,6 +1,6 @@
;;; shortdoc-tests.el --- tests for shortdoc.el -*- lexical-binding: t -*-
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/emacs-lisp/subr-x-tests.el b/test/lisp/emacs-lisp/subr-x-tests.el
index 63d8fcd080c..162cad23b88 100644
--- a/test/lisp/emacs-lisp/subr-x-tests.el
+++ b/test/lisp/emacs-lisp/subr-x-tests.el
@@ -1,6 +1,6 @@
;;; subr-x-tests.el --- Testing the extended lisp routines -*- lexical-binding:t -*-
-;; Copyright (C) 2014-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2014-2024 Free Software Foundation, Inc.
;; Author: Fabián E. Gallina <fgallina@gnu.org>
;; Keywords:
diff --git a/test/lisp/emacs-lisp/syntax-tests.el b/test/lisp/emacs-lisp/syntax-tests.el
index 6cdbca984ac..5b3a0fe32a8 100644
--- a/test/lisp/emacs-lisp/syntax-tests.el
+++ b/test/lisp/emacs-lisp/syntax-tests.el
@@ -1,6 +1,6 @@
;;; syntax-tests.el --- tests for syntax.el -*- lexical-binding: t; -*-
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/emacs-lisp/tabulated-list-tests.el b/test/lisp/emacs-lisp/tabulated-list-tests.el
index 115a7e735a2..8be2be3139e 100644
--- a/test/lisp/emacs-lisp/tabulated-list-tests.el
+++ b/test/lisp/emacs-lisp/tabulated-list-tests.el
@@ -1,6 +1,6 @@
;;; tabulated-list-tests.el --- Tests for emacs-lisp/tabulated-list.el -*- lexical-binding: t; -*-
-;; Copyright (C) 2015-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2024 Free Software Foundation, Inc.
;; Author: Artur Malabarba <bruce.connor.am@gmail.com>
diff --git a/test/lisp/emacs-lisp/testcover-resources/testcases.el b/test/lisp/emacs-lisp/testcover-resources/testcases.el
index 48c73648259..fd1ff0e1aa1 100644
--- a/test/lisp/emacs-lisp/testcover-resources/testcases.el
+++ b/test/lisp/emacs-lisp/testcover-resources/testcases.el
@@ -1,6 +1,6 @@
;;;; testcases.el -- Test cases for testcover-tests.el
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
;; Author: Gemini Lasswell
diff --git a/test/lisp/emacs-lisp/testcover-tests.el b/test/lisp/emacs-lisp/testcover-tests.el
index 989dd40b646..f0f30feecf4 100644
--- a/test/lisp/emacs-lisp/testcover-tests.el
+++ b/test/lisp/emacs-lisp/testcover-tests.el
@@ -1,6 +1,6 @@
;;; testcover-tests.el --- Testcover test suite -*- lexical-binding:t -*-
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
;; Author: Gemini Lasswell
diff --git a/test/lisp/emacs-lisp/text-property-search-tests.el b/test/lisp/emacs-lisp/text-property-search-tests.el
index 2c701c2c8e4..73946cba8ea 100644
--- a/test/lisp/emacs-lisp/text-property-search-tests.el
+++ b/test/lisp/emacs-lisp/text-property-search-tests.el
@@ -1,6 +1,6 @@
;;; text-property-search-tests.el --- Testing text-property-search -*- lexical-binding:t -*-
-;; Copyright (C) 2018-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2018-2024 Free Software Foundation, Inc.
;; Author: Lars Ingebrigtsen <larsi@gnus.org>
;; Keywords:
diff --git a/test/lisp/emacs-lisp/thunk-tests.el b/test/lisp/emacs-lisp/thunk-tests.el
index 5ae0e2a3d7d..440e66ae30d 100644
--- a/test/lisp/emacs-lisp/thunk-tests.el
+++ b/test/lisp/emacs-lisp/thunk-tests.el
@@ -1,6 +1,6 @@
;;; thunk-tests.el --- Tests for thunk.el -*- lexical-binding: t -*-
-;; Copyright (C) 2015-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2024 Free Software Foundation, Inc.
;; Author: Nicolas Petton <nicolas@petton.fr>
;; Maintainer: emacs-devel@gnu.org
diff --git a/test/lisp/emacs-lisp/timer-tests.el b/test/lisp/emacs-lisp/timer-tests.el
index 7652b324493..ab1b57eec0d 100644
--- a/test/lisp/emacs-lisp/timer-tests.el
+++ b/test/lisp/emacs-lisp/timer-tests.el
@@ -1,6 +1,6 @@
;;; timer-tests.el --- tests for timers -*- lexical-binding:t -*-
-;; Copyright (C) 2013-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/emacs-lisp/unsafep-tests.el b/test/lisp/emacs-lisp/unsafep-tests.el
index 368eee796ea..8a41707b6a5 100644
--- a/test/lisp/emacs-lisp/unsafep-tests.el
+++ b/test/lisp/emacs-lisp/unsafep-tests.el
@@ -2,7 +2,7 @@
;; Author: Jonathan Yavner <jyavner@member.fsf.org>
-;; Copyright (C) 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/emacs-lisp/vtable-tests.el b/test/lisp/emacs-lisp/vtable-tests.el
index 2da1bbaabb1..08fdf1594a4 100644
--- a/test/lisp/emacs-lisp/vtable-tests.el
+++ b/test/lisp/emacs-lisp/vtable-tests.el
@@ -1,6 +1,6 @@
;;; vtable-tests.el --- Tests for vtable.el -*- lexical-binding: t; -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/emacs-lisp/warnings-tests.el b/test/lisp/emacs-lisp/warnings-tests.el
index 22520d0e84f..a0ef2ffd332 100644
--- a/test/lisp/emacs-lisp/warnings-tests.el
+++ b/test/lisp/emacs-lisp/warnings-tests.el
@@ -2,7 +2,7 @@
;; Author: Stefan Kangas <stefankangas@gmail.com>
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/emulation/viper-tests.el b/test/lisp/emulation/viper-tests.el
index a0b1a823909..96c467e621f 100644
--- a/test/lisp/emulation/viper-tests.el
+++ b/test/lisp/emulation/viper-tests.el
@@ -1,6 +1,6 @@
;;; viper-tests.el --- tests for viper. -*- lexical-binding:t -*-
-;; Copyright (C) 2016-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2016-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/env-tests.el b/test/lisp/env-tests.el
index 579f73b1b21..4ccec5f3c41 100644
--- a/test/lisp/env-tests.el
+++ b/test/lisp/env-tests.el
@@ -1,6 +1,6 @@
;;; env-tests.el --- Tests for env.el -*- lexical-binding: t -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/epg-config-tests.el b/test/lisp/epg-config-tests.el
index 51d2052c27d..09fb18e32f0 100644
--- a/test/lisp/epg-config-tests.el
+++ b/test/lisp/epg-config-tests.el
@@ -1,6 +1,6 @@
;;; epg-config-tests.el --- Test suite for epg.el -*- lexical-binding: t -*-
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/epg-tests.el b/test/lisp/epg-tests.el
index 3659a922fe3..a1748b39f74 100644
--- a/test/lisp/epg-tests.el
+++ b/test/lisp/epg-tests.el
@@ -1,6 +1,6 @@
;;; epg-tests.el --- Test suite for epg.el -*- lexical-binding: t -*-
-;; Copyright (C) 2013-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -111,14 +111,23 @@ jA0ECQMCdW8+qtS9Tin/0jUBO1/9Oz69BWPmtFKEeBM62WpFP4o1+bNzdxogdyeg
-----END PGP MESSAGE-----
")))))
+(defun epg--gnupg-version-is-not-buggy ()
+ ;; We need to skip some versions of GnuPG, as they make tests hang.
+ ;; See Bug#63256 and https://dev.gnupg.org/T6481 as well as PROBLEMS.
+ ;; Known bad versions for now are 2.4.1--2.4.3.
+ (not (string-match (rx bos "gpg (GnuPG) 2.4." (+ digit))
+ (shell-command-to-string "gpg --version"))))
+
(ert-deftest epg-roundtrip-1 ()
- :expected-result (if (getenv "EMACS_HYDRA_CI") :failed :passed) ; fixme
+ :expected-result (if (getenv "EMACS_HYDRA_CI") :failed :passed) ; fixme
+ (skip-unless (epg--gnupg-version-is-not-buggy))
(with-epg-tests (:require-passphrase t)
(let ((cipher (epg-encrypt-string epg-tests-context "symmetric" nil)))
(should (equal "symmetric"
(epg-decrypt-string epg-tests-context cipher))))))
(ert-deftest epg-roundtrip-2 ()
+ (skip-unless (epg--gnupg-version-is-not-buggy))
(with-epg-tests (:require-passphrase t
:require-public-key t
:require-secret-key t)
diff --git a/test/lisp/erc/erc-button-tests.el b/test/lisp/erc/erc-button-tests.el
index 3dacf95a59f..ba6fe9fd8c1 100644
--- a/test/lisp/erc/erc-button-tests.el
+++ b/test/lisp/erc/erc-button-tests.el
@@ -1,6 +1,6 @@
;;; erc-button-tests.el --- Tests for erc-button -*- lexical-binding:t -*-
-;; Copyright (C) 2023 Free Software Foundation, Inc.
+;; Copyright (C) 2023-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
;;
@@ -21,12 +21,15 @@
;;; Code:
+(require 'ert-x) ; cl-lib
+(eval-and-compile
+ (let ((load-path (cons (ert-resource-directory) load-path)))
+ (require 'erc-tests-common)))
+
(require 'erc-button)
(ert-deftest erc-button-alist--url ()
- (setq erc-server-process
- (start-process "sleep" (current-buffer) "sleep" "1"))
- (set-process-query-on-exit-flag erc-server-process nil)
+ (erc-tests-common-init-server-proc "sleep" "1")
(with-current-buffer (erc--open-target "#chan")
(let ((verify
(lambda (p url)
@@ -65,9 +68,7 @@
(apply #'erc-button-add-button rest))
(defun erc-button-tests--erc-button-alist--function-as-form (func)
- (setq erc-server-process
- (start-process "sleep" (current-buffer) "sleep" "1"))
- (set-process-query-on-exit-flag erc-server-process nil)
+ (erc-tests-common-init-server-proc "sleep" "1")
(with-current-buffer (erc--open-target "#chan")
(let* ((erc-button-tests--form nil)
@@ -102,9 +103,7 @@
(apply #'erc-button-add-button r))))
(defun erc-button-tests--erc-button-alist--nil-form (form)
- (setq erc-server-process
- (start-process "sleep" (current-buffer) "sleep" "1"))
- (set-process-query-on-exit-flag erc-server-process nil)
+ (erc-tests-common-init-server-proc "sleep" "1")
(with-current-buffer (erc--open-target "#chan")
(let* ((erc-button-tests--form nil)
@@ -228,11 +227,9 @@
(inhibit-message noninteractive)
erc-modules
erc-kill-channel-hook erc-kill-server-hook erc-kill-buffer-hook)
- (erc-mode)
- (setq erc-server-process
- (start-process "sleep" (current-buffer) "sleep" "1"))
- (set-process-query-on-exit-flag erc-server-process nil)
- (erc--initialize-markers (point) nil)
+ (erc-tests-common-prep-for-insertion)
+ (erc-tests-common-init-server-proc "sleep" "1")
+
(erc-button-mode +1)
(should (equal (erc-button--display-error-notice-with-keys
"If \\[erc-bol] fails, "
@@ -274,6 +271,34 @@
"abc" " %d def" " 45%s" 123 '\6)
"*** abc 123 def 456")))
+ (ert-info ("Respects buffer as first argument when given")
+ (should (equal (erc-button--display-error-notice-with-keys
+ (make-erc-response) "abc") ; compat
+ "*** abc"))
+ (should (equal (erc-button--display-error-notice-with-keys
+ (current-buffer) "abc")
+ "*** abc")))
+
+ (ert-info ("Accounts for nil members when concatenating")
+ (should (equal (erc-button--display-error-notice-with-keys
+ "a" nil)
+ "*** a"))
+ (should (equal (erc-button--display-error-notice-with-keys
+ "a" nil " b")
+ "*** a b"))
+ (should (equal (erc-button--display-error-notice-with-keys
+ "a: %d" nil 1)
+ "*** a: 1"))
+ (should (equal (erc-button--display-error-notice-with-keys
+ "a: %d %s" 1 nil)
+ "*** a: 1 nil"))
+ (should (equal (erc-button--display-error-notice-with-keys
+ "a: " "%d %s" 1 nil)
+ "*** a: 1 nil"))
+ (should (equal (erc-button--display-error-notice-with-keys
+ "a: " nil "%d %s" 1 nil)
+ "*** a: 1 nil")))
+
(when noninteractive
(unless mode
(erc-button-mode -1))
diff --git a/test/lisp/erc/erc-dcc-tests.el b/test/lisp/erc/erc-dcc-tests.el
index a750c96c80f..a2fb0392727 100644
--- a/test/lisp/erc/erc-dcc-tests.el
+++ b/test/lisp/erc/erc-dcc-tests.el
@@ -1,6 +1,6 @@
;;; erc-dcc-tests.el --- Tests for erc-dcc -*- lexical-binding:t -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
;;
diff --git a/test/lisp/erc/erc-fill-tests.el b/test/lisp/erc/erc-fill-tests.el
index b81d0c15558..0f19b481f37 100644
--- a/test/lisp/erc/erc-fill-tests.el
+++ b/test/lisp/erc/erc-fill-tests.el
@@ -1,6 +1,6 @@
;;; erc-fill-tests.el --- Tests for erc-fill -*- lexical-binding:t -*-
-;; Copyright (C) 2023 Free Software Foundation, Inc.
+;; Copyright (C) 2023-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
;;
@@ -24,17 +24,31 @@
;;; Code:
(require 'ert-x)
+(eval-and-compile
+ (let ((load-path (cons (ert-resource-directory) load-path)))
+ (require 'erc-tests-common)))
+
(require 'erc-fill)
(defvar erc-fill-tests--buffers nil)
-(defvar erc-fill-tests--time-vals (lambda () 0))
+(defvar erc-fill-tests--current-time-value nil)
+
+(cl-defmethod erc-stamp--current-time
+ (&context (erc-fill-tests--current-time-value integer))
+ erc-fill-tests--current-time-value)
(defun erc-fill-tests--insert-privmsg (speaker &rest msg-parts)
(declare (indent 1))
- (let ((msg (erc-format-privmessage speaker
- (apply #'concat msg-parts) nil t)))
- (put-text-property 0 (length msg) 'erc-command 'PRIVMSG msg)
- (erc-display-message nil nil (current-buffer) msg)))
+ (let* ((erc--msg-prop-overrides `((erc--msg . msg)))
+ (msg (erc-format-privmessage speaker
+ (apply #'concat msg-parts) nil t))
+ (parsed (make-erc-response :unparsed (format ":%s PRIVMSG #chan :%s"
+ speaker msg)
+ :sender speaker
+ :command "PRIVMSG"
+ :command-args (list "#chan" msg)
+ :contents msg)))
+ (erc-display-message parsed nil (current-buffer) msg)))
(defun erc-fill-tests--wrap-populate (test)
(let ((original-window-buffer (window-buffer (selected-window)))
@@ -42,16 +56,13 @@
(erc-fill-function 'erc-fill-wrap)
(pre-command-hook pre-command-hook)
(inhibit-message noninteractive)
+ (erc-fill-tests--current-time-value 0)
erc-insert-post-hook
extended-command-history
erc-kill-channel-hook erc-kill-server-hook erc-kill-buffer-hook)
- (cl-letf (((symbol-function 'erc-stamp--current-time)
- (lambda () (funcall erc-fill-tests--time-vals)))
- ((symbol-function 'erc-server-connect)
+ (cl-letf (((symbol-function 'erc-server-connect)
(lambda (&rest _)
- (setq erc-server-process
- (start-process "sleep" (current-buffer) "sleep" "1"))
- (set-process-query-on-exit-flag erc-server-process nil))))
+ (erc-tests-common-init-server-proc "sleep" "1"))))
(with-current-buffer
(car (push (erc-open "localhost" 6667 "tester" "Tester" 'connect
nil nil nil nil nil "tester" 'foonet)
@@ -75,8 +86,8 @@
(erc-fill-tests--insert-privmsg "alice"
"bob: come, you are a tedious fool: to the purpose. "
- "What was done to Elbow's wife, that he hath cause to complain of? "
- "Come me to what was done to her.")
+ "What was done to Elbow's wife, that he hath cause to complain of?"
+ " Come me to what was done to her.")
;; Introduce an artificial gap in properties `line-prefix' and
;; `wrap-prefix' and later ensure they're not incremented twice.
@@ -97,10 +108,9 @@
(when set-transient-map-timer
(timer-event-handler set-transient-map-timer))
(set-window-buffer (selected-window) original-window-buffer)
- (when noninteractive
- (while-let ((buf (pop erc-fill-tests--buffers)))
- (kill-buffer buf))
- (kill-buffer))))))))
+ (when (or noninteractive (getenv "ERC_TESTS_GRAPHICAL"))
+ (erc-tests-common-kill-buffers erc-fill-tests--buffers)
+ (setq erc-fill-tests--buffers nil))))))))
(defun erc-fill-tests--wrap-check-prefixes (&rest prefixes)
;; Check that prefix props are applied over correct intervals.
@@ -111,58 +121,35 @@
(should (get-text-property (pos-bol) 'line-prefix))
(should (get-text-property (1- (pos-eol)) 'line-prefix))
(should-not (get-text-property (pos-eol) 'line-prefix))
+ ;; Spans entire line uninterrupted.
+ (let* ((val (get-text-property (pos-bol) 'line-prefix))
+ (end (text-property-not-all (pos-bol) (point-max)
+ 'line-prefix val)))
+ (when (and (/= end (pos-eol)) (= ?? (char-before end)))
+ (setq end (text-property-not-all (1+ end) (point-max)
+ 'line-prefix val)))
+ (should (eq end (pos-eol))))
(should (equal (get-text-property (pos-bol) 'wrap-prefix)
'(space :width erc-fill--wrap-value)))
(should-not (get-text-property (pos-eol) 'wrap-prefix))
(should (equal (get-text-property (1- (pos-eol)) 'wrap-prefix)
'(space :width erc-fill--wrap-value))))))
-;; Set this variable to t to generate new snapshots after carefully
-;; reviewing the output of *each* snapshot (not just first and last).
-;; Obviously, only run one test at a time.
-(defvar erc-fill-tests--save-p nil)
-
;; On graphical displays, echo .graphic >> .git/info/exclude
-(defvar erc-fill-tests--graphic-dir "fill/snapshots/.graphic")
+(defvar erc-fill-tests--graphic-dir "fill/snapshots/.graphic/")
(defun erc-fill-tests--compare (name)
- (let* ((dir (expand-file-name (if (display-graphic-p)
- erc-fill-tests--graphic-dir
- "fill/snapshots/")
- (ert-resource-directory)))
- (expect-file (file-name-with-extension (expand-file-name name dir)
- "eld"))
- (erc--own-property-names
- (seq-difference `(font-lock-face ,@erc--own-property-names)
- '(field display wrap-prefix line-prefix)
- #'eq))
- (print-circle t)
- (print-escape-newlines t)
- (print-escape-nonascii t)
- (got (erc--remove-text-properties
- (buffer-substring (point-min) erc-insert-marker)))
- (repr (string-replace "erc-fill--wrap-value"
- (number-to-string erc-fill--wrap-value)
- (prin1-to-string got))))
- (with-current-buffer (generate-new-buffer name)
- (push name erc-fill-tests--buffers)
- (with-silent-modifications
- (insert (setq got (read repr))))
- (erc-mode))
- (if erc-fill-tests--save-p
- (with-temp-file expect-file
- (insert repr))
- (if (file-exists-p expect-file)
- ;; Compare set-equal over intervals. This comparison is
- ;; less useful for messages treated by other modules because
- ;; it doesn't compare "nested" props belonging to
- ;; string-valued properties, like timestamps.
- (should (equal-including-properties
- (read repr)
- (read (with-temp-buffer
- (insert-file-contents-literally expect-file)
- (buffer-string)))))
- (message "Snapshot file missing: %S" expect-file)))))
+ (let ((dir (expand-file-name (if (display-graphic-p)
+ erc-fill-tests--graphic-dir
+ "fill/snapshots/" )
+ (ert-resource-directory)))
+ (transform-fn (lambda (got)
+ (string-replace "erc-fill--wrap-value"
+ (number-to-string erc-fill--wrap-value)
+ got)))
+ (buffer-setup-fn (lambda ()
+ (push (current-buffer) erc-fill-tests--buffers))))
+ (erc-tests-common-snapshot-compare name dir transform-fn buffer-setup-fn)))
;; To inspect variable pitch, set `erc-mode-hook' to
;;
@@ -171,43 +158,55 @@
;; or similar.
(ert-deftest erc-fill-wrap--monospace ()
- :tags '(:unstable)
+ :tags `(:unstable
+ ,@(and (getenv "ERC_TESTS_GRAPHICAL") '(:erc--graphical)))
(unless (>= emacs-major-version 29)
(ert-skip "Emacs version too low, missing `buffer-text-pixel-size'"))
- (erc-fill-tests--wrap-populate
-
- (lambda ()
- (should (= erc-fill--wrap-value 27))
- (erc-fill-tests--wrap-check-prefixes "*** " "<alice> " "<bob> ")
- (erc-fill-tests--compare "monospace-01-start")
-
- (ert-info ("Shift right by one (plus)")
- ;; Args are all `erc-fill-wrap-nudge' +1 because interactive "p"
- (ert-with-message-capture messages
- ;; M-x erc-fill-wrap-nudge RET =
- (ert-simulate-command '(erc-fill-wrap-nudge 2))
- (should (string-match (rx "for further adjustment") messages)))
- (should (= erc-fill--wrap-value 29))
- (erc-fill-tests--wrap-check-prefixes "*** " "<alice> " "<bob> ")
- (erc-fill-tests--compare "monospace-02-right"))
-
- (ert-info ("Shift left by five")
- ;; "M-x erc-fill-wrap-nudge RET -----"
- (ert-simulate-command '(erc-fill-wrap-nudge -4))
- (should (= erc-fill--wrap-value 25))
- (erc-fill-tests--wrap-check-prefixes "*** " "<alice> " "<bob> ")
- (erc-fill-tests--compare "monospace-03-left"))
+ (let ((erc-prompt (lambda () "ABC>")))
+ (erc-fill-tests--wrap-populate
- (ert-info ("Reset")
- ;; M-x erc-fill-wrap-nudge RET 0
- (ert-simulate-command '(erc-fill-wrap-nudge 0))
+ (lambda ()
(should (= erc-fill--wrap-value 27))
(erc-fill-tests--wrap-check-prefixes "*** " "<alice> " "<bob> ")
- (erc-fill-tests--compare "monospace-04-reset")))))
+ (erc-fill-tests--compare "monospace-01-start")
+
+ (ert-info ("Shift right by one (plus)")
+ ;; Args are all `erc-fill-wrap-nudge' +1 because interactive "p"
+ (ert-with-message-capture messages
+ ;; M-x erc-fill-wrap-nudge RET =
+ (ert-simulate-command '(erc-fill-wrap-nudge 2))
+ (should (string-match (rx "for further adjustment") messages)))
+ (should (= erc-fill--wrap-value 29))
+ (erc-fill-tests--wrap-check-prefixes "*** " "<alice> " "<bob> ")
+ (erc-fill-tests--compare "monospace-02-right"))
+
+ (ert-info ("Shift left by five")
+ ;; "M-x erc-fill-wrap-nudge RET -----"
+ (ert-simulate-command '(erc-fill-wrap-nudge -4))
+ (should (= erc-fill--wrap-value 25))
+ (erc-fill-tests--wrap-check-prefixes "*** " "<alice> " "<bob> ")
+ (erc-fill-tests--compare "monospace-03-left"))
+
+ (ert-info ("Reset")
+ ;; M-x erc-fill-wrap-nudge RET 0
+ (ert-simulate-command '(erc-fill-wrap-nudge 0))
+ (should (= erc-fill--wrap-value 27))
+ (erc-fill-tests--wrap-check-prefixes "*** " "<alice> " "<bob> ")
+ (erc-fill-tests--compare "monospace-04-reset"))
+
+ (erc--assert-input-bounds)))))
+
+(defun erc-fill-tests--simulate-refill ()
+ ;; Simulate `erc-fill-wrap-refill-buffer' synchronously and without
+ ;; a progress reporter.
+ (save-excursion
+ (with-silent-modifications
+ (erc-fill--wrap-rejigger-region (point-min) erc-insert-marker nil nil))))
(ert-deftest erc-fill-wrap--merge ()
- :tags '(:unstable)
+ :tags `(:unstable
+ ,@(and (getenv "ERC_TESTS_GRAPHICAL") '(:erc--graphical)))
(unless (>= emacs-major-version 29)
(ert-skip "Emacs version too low, missing `buffer-text-pixel-size'"))
@@ -217,8 +216,10 @@
(erc-update-channel-member
"#chan" "Dummy" "Dummy" t nil nil nil nil nil "fake" "~u" nil nil t)
- ;; Set this here so that the first few messages are from 1970
- (let ((erc-fill-tests--time-vals (lambda () 1680332400)))
+ ;; Set this here so that the first few messages are from 1970.
+ ;; Following the current date stamp, the speaker isn't merged
+ ;; even though it's continued: "<bob> zero."
+ (let ((erc-fill-tests--current-time-value 1680332400))
(erc-fill-tests--insert-privmsg "bob" "zero.")
(erc-fill-tests--insert-privmsg "alice" "one.")
(erc-fill-tests--insert-privmsg "alice" "two.")
@@ -239,29 +240,37 @@
(erc-fill-tests--wrap-check-prefixes
"*** " "<alice> " "<bob> "
"<bob> " "<alice> " "<alice> " "<bob> " "<bob> " "<Dummy> " "<Dummy> ")
- (erc-fill-tests--compare "merge-02-right")))))
+ (erc-fill-tests--compare "merge-02-right")
-(ert-deftest erc-fill-wrap--merge-action ()
- :tags '(:unstable)
+ (ert-info ("Command `erc-fill-wrap-refill-buffer' is idempotent")
+ (kill-buffer (pop erc-fill-tests--buffers))
+ (erc-fill-tests--simulate-refill) ; idempotent
+ (erc-fill-tests--compare "merge-02-right"))))))
+
+(defun erc-fill-wrap-tests--merge-action (compare-file)
(unless (>= emacs-major-version 29)
(ert-skip "Emacs version too low, missing `buffer-text-pixel-size'"))
(erc-fill-tests--wrap-populate
(lambda ()
- ;; Set this here so that the first few messages are from 1970
- (let ((erc-fill-tests--time-vals (lambda () 1680332400)))
+ ;; Allow prior messages to be from 1970.
+ (let ((erc-fill-tests--current-time-value 1680332400))
(erc-fill-tests--insert-privmsg "bob" "zero.")
+ (erc-fill-tests--insert-privmsg "bob" "0.5")
(erc-process-ctcp-query
erc-server-process
(make-erc-response
- :unparsed ":bob!~u@fake PRIVMSG #chan :\1ACTION one\1"
- :sender "bob!~u@fake" :command "PRIVMSG"
- :command-args '("#chan" "\1ACTION one\1") :contents "\1ACTION one\1")
+ :unparsed ":bob!~u@fake PRIVMSG #chan :\1ACTION one.\1"
+ :sender "bob!~u@fake"
+ :command "PRIVMSG"
+ :command-args '("#chan" "\1ACTION one.\1")
+ :contents "\1ACTION one.\1")
"bob" "~u" "fake")
(erc-fill-tests--insert-privmsg "bob" "two.")
+ (erc-fill-tests--insert-privmsg "bob" "2.5")
;; Compat switch to opt out of overhanging speaker.
(let (erc-fill--wrap-action-dedent-p)
@@ -279,10 +288,30 @@
(should (= erc-fill--wrap-value 27))
(erc-fill-tests--wrap-check-prefixes
"*** " "<alice> " "<bob> " "<bob> " "* bob " "<bob> " "* " "<bob> ")
- (erc-fill-tests--compare "merge-wrap-01"))))
+ (erc-fill-tests--compare compare-file))))
+
+(ert-deftest erc-fill-wrap--merge-action ()
+ :tags `(:unstable
+ ,@(and (getenv "ERC_TESTS_GRAPHICAL") '(:erc--graphical)))
+ (erc-fill-wrap-tests--merge-action "merge-wrap-01"))
+
+(ert-deftest erc-fill-wrap--merge-action/indicator-pre ()
+ :tags `(:unstable
+ ,@(and (getenv "ERC_TESTS_GRAPHICAL") '(:erc--graphical)))
+ (let ((erc-fill-wrap-merge-indicator '(pre ?> shadow)))
+ (erc-fill-wrap-tests--merge-action "merge-wrap-indicator-pre-01")))
+
+;; One crucial thing this test asserts is that the indicator is
+;; omitted when the previous line ends in a stamp.
+(ert-deftest erc-fill-wrap--merge-action/indicator-post ()
+ :tags `(:unstable
+ ,@(and (getenv "ERC_TESTS_GRAPHICAL") '(:erc--graphical)))
+ (let ((erc-fill-wrap-merge-indicator '(post ?~ shadow)))
+ (erc-fill-wrap-tests--merge-action "merge-wrap-indicator-post-01")))
(ert-deftest erc-fill-line-spacing ()
- :tags '(:unstable)
+ :tags `(:unstable
+ ,@(and (getenv "ERC_TESTS_GRAPHICAL") '(:erc--graphical)))
(unless (>= emacs-major-version 29)
(ert-skip "Emacs version too low, missing `buffer-text-pixel-size'"))
@@ -296,7 +325,8 @@
(erc-fill-tests--compare "spacing-01-mono")))))
(ert-deftest erc-fill-wrap-visual-keys--body ()
- :tags '(:unstable)
+ :tags `(:unstable
+ ,@(and (getenv "ERC_TESTS_GRAPHICAL") '(:erc--graphical)))
(erc-fill-tests--wrap-populate
(lambda ()
@@ -338,7 +368,8 @@
(should-not (looking-at (rx "<alice> ")))))))
(ert-deftest erc-fill-wrap-visual-keys--prompt ()
- :tags '(:unstable)
+ :tags `(:unstable
+ ,@(and (getenv "ERC_TESTS_GRAPHICAL") '(:erc--graphical)))
(erc-fill-tests--wrap-populate
(lambda ()
@@ -381,7 +412,8 @@
(execute-kbd-macro "\C-a")))))
(ert-deftest erc-fill--left-hand-stamps ()
- :tags '(:unstable)
+ :tags `(:unstable
+ ,@(and (getenv "ERC_TESTS_GRAPHICAL") '(:erc--graphical)))
(unless (>= emacs-major-version 29)
(ert-skip "Emacs version too low, missing `buffer-text-pixel-size'"))
diff --git a/test/lisp/erc/erc-goodies-tests.el b/test/lisp/erc/erc-goodies-tests.el
index cdf861e2018..b8e00c57ef5 100644
--- a/test/lisp/erc/erc-goodies-tests.el
+++ b/test/lisp/erc/erc-goodies-tests.el
@@ -1,6 +1,6 @@
;;; erc-goodies-tests.el --- Tests for erc-goodies -*- lexical-binding:t -*-
-;; Copyright (C) 2023 Free Software Foundation, Inc.
+;; Copyright (C) 2023-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
;;
@@ -20,6 +20,10 @@
;;; Commentary:
;;; Code:
(require 'ert-x)
+(eval-and-compile
+ (let ((load-path (cons (ert-resource-directory) load-path)))
+ (require 'erc-tests-common)))
+
(require 'erc-goodies)
(defun erc-goodies-tests--assert-face (beg end-str present &optional absent)
@@ -247,7 +251,7 @@
(defun erc-goodies-tests--assert-kp-indicator-on ()
(should erc--keep-place-indicator-overlay)
- (should (local-variable-p 'window-configuration-change-hook))
+ (should (local-variable-p 'window-buffer-change-functions))
(should window-configuration-change-hook)
(should (memq 'erc-keep-place erc-insert-pre-hook))
(should (eq erc-keep-place-mode
@@ -255,7 +259,7 @@
(defun erc-goodies-tests--assert-kp-indicator-off ()
(should-not (local-variable-p 'erc-insert-pre-hook))
- (should-not (local-variable-p 'window-configuration-change-hook))
+ (should-not (local-variable-p 'window-buffer-change-functions))
(should-not erc--keep-place-indicator-overlay))
(defun erc-goodies-tests--kp-indicator-populate ()
@@ -420,4 +424,21 @@
(goto-char (overlay-start erc--keep-place-indicator-overlay))
(should (looking-at (rx "*** This buffer is for text")))))))
+(ert-deftest erc--get-inserted-msg-beg/readonly ()
+ (erc-tests-common-assert-get-inserted-msg-readonly-with
+ #'erc-tests-common-assert-get-inserted-msg/basic
+ (lambda (arg) (should (= 3 (erc--get-inserted-msg-beg arg))))))
+
+(ert-deftest erc--get-inserted-msg-end/readonly ()
+ (erc-tests-common-assert-get-inserted-msg-readonly-with
+ #'erc-tests-common-assert-get-inserted-msg/basic
+ (lambda (arg) (should (= 11 (erc--get-inserted-msg-end arg))))))
+
+(ert-deftest erc--get-inserted-msg-bounds/readonly ()
+ (erc-tests-common-assert-get-inserted-msg-readonly-with
+ #'erc-tests-common-assert-get-inserted-msg/basic
+ (lambda (arg)
+ (should (equal '(3 . 11) (erc--get-inserted-msg-bounds arg))))))
+
+
;;; erc-goodies-tests.el ends here
diff --git a/test/lisp/erc/erc-join-tests.el b/test/lisp/erc/erc-join-tests.el
index e293c9976a1..830f0711dde 100644
--- a/test/lisp/erc/erc-join-tests.el
+++ b/test/lisp/erc/erc-join-tests.el
@@ -1,6 +1,6 @@
;;; erc-join-tests.el --- Tests for erc-join. -*- lexical-binding:t -*-
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
;;
diff --git a/test/lisp/erc/erc-match-tests.el b/test/lisp/erc/erc-match-tests.el
index 748ccd02ddf..34610fc0438 100644
--- a/test/lisp/erc/erc-match-tests.el
+++ b/test/lisp/erc/erc-match-tests.el
@@ -1,6 +1,6 @@
;;; erc-match-tests.el --- Tests for erc-match. -*- lexical-binding:t -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/erc/erc-networks-tests.el b/test/lisp/erc/erc-networks-tests.el
index e95d99c128f..d8d8c6fa9cd 100644
--- a/test/lisp/erc/erc-networks-tests.el
+++ b/test/lisp/erc/erc-networks-tests.el
@@ -1,6 +1,6 @@
;;; erc-networks-tests.el --- Tests for erc-networks. -*- lexical-binding:t -*-
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
;;
@@ -20,25 +20,21 @@
;;; Code:
(require 'ert-x) ; cl-lib
-(require 'erc)
+(eval-and-compile
+ (let ((load-path (cons (ert-resource-directory) load-path)))
+ (require 'erc-tests-common)))
(defun erc-networks-tests--create-dead-proc (&optional buf)
(let ((p (start-process "true" (or buf (current-buffer)) "true")))
(while (process-live-p p) (sit-for 0.1))
p))
-(defun erc-networks-tests--create-live-proc (&optional buf)
- (let ((proc (start-process "sleep" (or buf (current-buffer)) "sleep" "1")))
- (set-process-query-on-exit-flag proc nil)
- proc))
+(defun erc-networks-tests--create-live-proc ()
+ (erc-tests-common-init-server-proc "sleep" "1"))
;; When we drop 27, call `get-buffer-create with INHIBIT-BUFFER-HOOKS.
(defun erc-networks-tests--clean-bufs ()
- (let (erc-kill-channel-hook
- erc-kill-server-hook
- erc-kill-buffer-hook)
- (dolist (buf (erc-buffer-list))
- (kill-buffer buf))))
+ (erc-tests-common-kill-buffers))
(defun erc-networks-tests--bufnames (prefix)
(let* ((case-fold-search)
@@ -623,11 +619,6 @@
:symbol 'foonet/dummy
:parts [foonet "dummy"]
:len 2)
- ;; `erc-kill-buffer-function' uses legacy target detection
- ;; but falls back on buffer name, so no need for:
- ;;
- ;; erc-default-recipients '("#a")
- ;;
erc--target (erc--target-from-string "#a")
erc-server-process (with-temp-buffer
(erc-networks-tests--create-dead-proc)))
@@ -1206,7 +1197,7 @@
calls)
(erc-mode)
- (cl-letf (((symbol-function 'erc-display-line)
+ (cl-letf (((symbol-function 'erc--route-insertion)
(lambda (&rest r) (push r calls))))
(ert-info ("Signals when `erc-server-announced-name' unset")
@@ -1447,10 +1438,12 @@
(let* (erc-kill-server-hook
erc-insert-modify-hook
(old-buf (get-buffer-create "FooNet"))
- (old-proc (erc-networks-tests--create-live-proc old-buf))) ; live
+ ;;
+ old-proc) ; live
(with-current-buffer old-buf
(erc-mode)
+ (setq old-proc (erc-networks-tests--create-live-proc))
(erc--initialize-markers (point) nil)
(insert "*** Old buf")
(setq erc-network 'FooNet
diff --git a/test/lisp/erc/erc-nicks-tests.el b/test/lisp/erc/erc-nicks-tests.el
index 3e5804734ec..08080d249d5 100644
--- a/test/lisp/erc/erc-nicks-tests.el
+++ b/test/lisp/erc/erc-nicks-tests.el
@@ -1,6 +1,6 @@
;;; erc-nicks-tests.el --- Tests for erc-nicks -*- lexical-binding:t -*-
-;; Copyright (C) 2023 Free Software Foundation, Inc.
+;; Copyright (C) 2023-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -409,7 +409,7 @@
(push-button)
(should (search-forward-regexp
(rx "Foreground: #" (group (+ xdigit)) eol)))
- (forward-button 1)
+ (forward-button 2) ; skip Inherit:...
(push-button))
(ert-info ("First entry's sample is rendered correctly")
@@ -493,7 +493,7 @@
(should (equal (erc-nicks--gen-key-from-format-spec "bob")
"bob@Libera.Chat/tester"))))
-(ert-deftest erc-nicks--create-pool ()
+(ert-deftest erc-nicks--create-culled-pool ()
(let ((erc-nicks--bg-luminance 1.0)
(erc-nicks--bg-mode-value 'light)
(erc-nicks--fg-rgb '(0.0 0.0 0.0))
@@ -502,37 +502,70 @@
(erc-nicks--colors-rejects '(t)))
;; Reject
- (should-not (erc-nicks--create-pool '(erc-nicks-invert) '("white")))
+ (should-not (erc-nicks--create-culled-pool '(erc-nicks-invert) '("white")))
(should (equal (pop erc-nicks--colors-rejects) "white")) ; too close
- (should-not (erc-nicks--create-pool '(erc-nicks-cap-contrast) '("black")))
+ (should-not
+ (erc-nicks--create-culled-pool '(erc-nicks-cap-contrast) '("black")))
(should (equal (pop erc-nicks--colors-rejects) "black")) ; too far
- (should-not (erc-nicks--create-pool '(erc-nicks-ensaturate) '("white")))
+ (should-not
+ (erc-nicks--create-culled-pool '(erc-nicks-ensaturate) '("white")))
(should (equal (pop erc-nicks--colors-rejects) "white")) ; lacks color
- (should-not (erc-nicks--create-pool '(erc-nicks-ensaturate) '("red")))
+ (should-not
+ (erc-nicks--create-culled-pool '(erc-nicks-ensaturate) '("red")))
(should (equal (pop erc-nicks--colors-rejects) "red")) ; too much color
;; Safe
- (should
- (equal (erc-nicks--create-pool '(erc-nicks-invert) '("black"))
- '("black")))
- (should
- (equal (erc-nicks--create-pool '(erc-nicks-add-contrast) '("black"))
- '("black")))
- (should
- (equal (erc-nicks--create-pool '(erc-nicks-cap-contrast) '("white"))
- '("white")))
+ (should (equal (erc-nicks--create-culled-pool '(erc-nicks-invert)
+ '("black"))
+ '("black")))
+ (should (equal (erc-nicks--create-culled-pool '(erc-nicks-add-contrast)
+ '("black"))
+ '("black")))
+ (should (equal (erc-nicks--create-culled-pool '(erc-nicks-cap-contrast)
+ '("white"))
+ '("white")))
(let ((erc-nicks-saturation-range '(0.5 . 1.0)))
- (should
- (equal (erc-nicks--create-pool '(erc-nicks-ensaturate) '("green"))
- '("green"))))
+ (should (equal (erc-nicks--create-culled-pool '(erc-nicks-ensaturate)
+ '("green"))
+ '("green"))))
(let ((erc-nicks-saturation-range '(0.0 . 0.5)))
- (should
- (equal (erc-nicks--create-pool '(erc-nicks-ensaturate) '("gray"))
- '("gray"))))
+ (should (equal (erc-nicks--create-culled-pool '(erc-nicks-ensaturate)
+ '("gray"))
+ '("gray"))))
(unless noninteractive
- (should
- (equal (erc-nicks--create-pool '(erc-nicks-ensaturate) '("firebrick"))
- '("firebrick"))))
+ (should (equal (erc-nicks--create-culled-pool '(erc-nicks-ensaturate)
+ '("firebrick"))
+ '("firebrick"))))
+ (should (equal erc-nicks--colors-rejects '(t)))))
+
+(ert-deftest erc-nicks--create-coerced-pool ()
+ (let ((erc-nicks--bg-luminance 1.0)
+ (erc-nicks--bg-mode-value 'light)
+ (erc-nicks--fg-rgb '(0.0 0.0 0.0))
+ (erc-nicks-bg-color "white")
+ (num-colors (length (defined-colors)))
+ ;;
+ (erc-nicks--colors-rejects '(t)))
+
+ ;; Deduplication.
+ (when (= 8 num-colors)
+ (should (equal (erc-nicks--create-coerced-pool '(erc-nicks-ensaturate)
+ '("#ee0000" "#f80000"))
+ '("red")))
+ (should (equal (pop erc-nicks--colors-rejects) "#f80000")))
+
+ ;; "Coercion" in Xterm.
+ (unless noninteractive
+ (when (= 665 num-colors)
+ (pcase-dolist (`(,adjustments ,candidates ,result)
+ '(((erc-nicks-invert) ("white") ("gray10"))
+ ((erc-nicks-cap-contrast) ("black") ("gray20"))
+ ((erc-nicks-ensaturate) ("white") ("lavenderblush2"))
+ ((erc-nicks-ensaturate) ("red") ("firebrick"))))
+ (should (equal (erc-nicks--create-coerced-pool adjustments
+ candidates)
+ result)))))
+
(should (equal erc-nicks--colors-rejects '(t)))))
;;; erc-nicks-tests.el ends here
diff --git a/test/lisp/erc/erc-sasl-tests.el b/test/lisp/erc/erc-sasl-tests.el
index 767a8f56f54..afe55f522dd 100644
--- a/test/lisp/erc/erc-sasl-tests.el
+++ b/test/lisp/erc/erc-sasl-tests.el
@@ -1,6 +1,6 @@
;;; erc-sasl-tests.el --- Tests for erc-sasl. -*- lexical-binding:t -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;;
;; This file is part of GNU Emacs.
;;
diff --git a/test/lisp/erc/erc-scenarios-auth-source.el b/test/lisp/erc/erc-scenarios-auth-source.el
index 641b881666e..f0a7a4cbaca 100644
--- a/test/lisp/erc/erc-scenarios-auth-source.el
+++ b/test/lisp/erc/erc-scenarios-auth-source.el
@@ -1,6 +1,6 @@
;;; erc-scenarios-auth-source.el --- auth-source scenarios -*- lexical-binding: t -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -56,7 +56,7 @@
(should (string= (buffer-name) (if id
(symbol-name id)
(format "127.0.0.1:%d" port))))
- (erc-d-t-wait-for 5 (eq erc-network 'FooNet))))))
+ (erc-d-t-wait-for 10 (eq erc-network 'FooNet))))))
(ert-deftest erc-scenarios-base-auth-source-server--dialed ()
:tags '(:expensive-test)
diff --git a/test/lisp/erc/erc-scenarios-base-association-nick.el b/test/lisp/erc/erc-scenarios-base-association-nick.el
index 5f90f0d2bcd..57e8abda73c 100644
--- a/test/lisp/erc/erc-scenarios-base-association-nick.el
+++ b/test/lisp/erc/erc-scenarios-base-association-nick.el
@@ -1,6 +1,6 @@
;;; erc-scenarios-base-association-nick.el --- base assoc scenarios -*- lexical-binding: t -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/erc/erc-scenarios-base-association-query.el b/test/lisp/erc/erc-scenarios-base-association-query.el
index e9472617918..3ee71a70e96 100644
--- a/test/lisp/erc/erc-scenarios-base-association-query.el
+++ b/test/lisp/erc/erc-scenarios-base-association-query.el
@@ -1,6 +1,6 @@
;;; erc-scenarios-base-association-query.el --- assoc query scenarios -*- lexical-binding: t -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/erc/erc-scenarios-base-association-samenet.el b/test/lisp/erc/erc-scenarios-base-association-samenet.el
index c64a3f6725b..07d9102f5f0 100644
--- a/test/lisp/erc/erc-scenarios-base-association-samenet.el
+++ b/test/lisp/erc/erc-scenarios-base-association-samenet.el
@@ -1,6 +1,6 @@
;;; erc-scenarios-base-association-samenet.el --- assoc samenet scenarios -*- lexical-binding: t -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/erc/erc-scenarios-base-association.el b/test/lisp/erc/erc-scenarios-base-association.el
index a40a4cb7550..deac0e0cac7 100644
--- a/test/lisp/erc/erc-scenarios-base-association.el
+++ b/test/lisp/erc/erc-scenarios-base-association.el
@@ -1,6 +1,6 @@
;;; erc-scenarios-base-association.el --- base assoc scenarios -*- lexical-binding: t -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -78,7 +78,7 @@
(with-current-buffer "#chan@foonet"
(funcall expect 3 "bob")
(funcall expect 3 "was created on")
- (funcall expect 3 "prosperous")))
+ (funcall expect 10 "prosperous")))
(ert-info ("All #chan@barnet output consumed")
(with-current-buffer "#chan@barnet"
diff --git a/test/lisp/erc/erc-scenarios-base-attach.el b/test/lisp/erc/erc-scenarios-base-attach.el
index ccf5d1f9582..dcd16ed6bca 100644
--- a/test/lisp/erc/erc-scenarios-base-attach.el
+++ b/test/lisp/erc/erc-scenarios-base-attach.el
@@ -1,6 +1,6 @@
;;; erc-scenarios-base-attach.el --- Reattach scenarios -*- lexical-binding: t -*-
-;; Copyright (C) 2023 Free Software Foundation, Inc.
+;; Copyright (C) 2023-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -47,11 +47,11 @@
;; Author: Mario Lang <mlang@delysid.org>
;; AuthorDate: Mon Nov 26 18:33:19 2001 +0000
;;
-;; * new function erc-BBDB-NICK to handle nickname anotation ...
+;; * new function erc-BBDB-NICK to handle nickname annotation ...
;; * Applied antifuchs/mhp patches, the latest on erc-help, unmodified
;; * New variable: erc-reuse-buffers default to t.
;; * Modified erc-generate-new-buffer-name to use it. it checks if
-;; server and port are the same, then one can assume thats the same
+;; server and port are the same, then one can assume that's the same
;; channel/query target again.
;;; Code:
diff --git a/test/lisp/erc/erc-scenarios-base-auto-recon.el b/test/lisp/erc/erc-scenarios-base-auto-recon.el
index 40e2c23408b..808b1d8c4d4 100644
--- a/test/lisp/erc/erc-scenarios-base-auto-recon.el
+++ b/test/lisp/erc/erc-scenarios-base-auto-recon.el
@@ -1,6 +1,6 @@
;;; erc-scenarios-base-auto-recon.el --- auto-recon scenarios -*- lexical-binding: t -*-
-;; Copyright (C) 2023 Free Software Foundation, Inc.
+;; Copyright (C) 2023-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/erc/erc-scenarios-base-buffer-display.el b/test/lisp/erc/erc-scenarios-base-buffer-display.el
index df292a8c113..5c3c526f86d 100644
--- a/test/lisp/erc/erc-scenarios-base-buffer-display.el
+++ b/test/lisp/erc/erc-scenarios-base-buffer-display.el
@@ -1,6 +1,6 @@
;;; erc-scenarios-base-buffer-display.el --- Buffer display scenarios -*- lexical-binding: t -*-
-;; Copyright (C) 2023 Free Software Foundation, Inc.
+;; Copyright (C) 2023-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -27,7 +27,10 @@
(eval-when-compile (require 'erc-join))
;; These first couple `erc-auto-reconnect-display' tests used to live
-;; in erc-scenarios-base-reconnect but have since been renamed.
+;; in erc-scenarios-base-reconnect but have since been renamed. Note
+;; that these are somewhat difficult to reason about because the user
+;; joins a second channel after reconnecting, and the first is
+;; controlled by `autojoin'.
(defun erc-scenarios-base-buffer-display--reconnect-common
(assert-server assert-chan assert-rest)
@@ -55,6 +58,7 @@
(ert-info ("Wait for some output in channels")
(with-current-buffer (erc-d-t-wait-for 10 (get-buffer "#chan"))
(funcall assert-chan expect)
+ (funcall expect 10 "welcome")
(funcall expect 10 "welcome")))
(ert-info ("Server buffer shows connection failed")
@@ -68,6 +72,10 @@
(ert-info ("Wait for auto reconnect")
(with-current-buffer "FooNet" (funcall expect 10 "still in debug mode")))
+ (ert-info ("Lone window still shows messages buffer")
+ (should (eq (window-buffer) (messages-buffer)))
+ (should (frame-root-window-p (selected-window))))
+
(funcall assert-rest expect)
(ert-info ("Wait for activity to recommence in both channels")
@@ -76,40 +84,50 @@
(with-current-buffer (erc-d-t-wait-for 10 (get-buffer "#spam"))
(funcall expect 10 "her elves come here anon")))))
+;; Interactively issuing a slash command resets the auto-reconnect
+;; count, making ERC ignore the option `erc-auto-reconnect-display'
+;; when next displaying a newly set up buffer. In the case of a
+;; /JOIN, the option `erc-interactive-display' takes precedence.
(ert-deftest erc-scenarios-base-buffer-display--defwin-recbury-intbuf ()
:tags '(:expensive-test)
(should (eq erc-buffer-display 'bury))
(should (eq erc-interactive-display 'window))
(should-not erc-auto-reconnect-display)
- (let ((erc-buffer-display 'window)
- (erc-interactive-display 'buffer)
- (erc-auto-reconnect-display 'bury))
+ (let ((erc-buffer-display 'window) ; defwin
+ (erc-interactive-display 'buffer) ; intbuf
+ (erc-auto-reconnect-display 'bury)) ; recbury
(erc-scenarios-base-buffer-display--reconnect-common
(lambda (_)
- (should (eq (window-buffer) (current-buffer)))
- (should-not (frame-root-window-p (selected-window))))
+ (ert-info ("New server buffer appears in a selected split")
+ (should (eq (window-buffer) (current-buffer)))
+ (should-not (frame-root-window-p (selected-window)))))
(lambda (_)
- (should (eq (window-buffer) (current-buffer)))
- (should (equal (get-buffer "FooNet") (window-buffer (next-window)))))
+ (ert-info ("New channel buffer appears in other window")
+ (should (eq (window-buffer) (current-buffer))) ; selected
+ (should (equal (get-buffer "FooNet") (window-buffer (next-window))))))
+
+ (lambda (expect)
+ ;; If we /JOIN #spam now, we'll cancel the auto-reconnect
+ ;; timer, and "#chan" may well pop up in a split before we can
+ ;; verify that the lone window displays #spam (a race, IOW).
+ (ert-info ("Autojoined channel #chan buried on JOIN")
+ (with-current-buffer "#chan"
+ (funcall expect 10 "You have joined channel #chan"))
+ (should (frame-root-window-p (selected-window)))
+ (should (eq (window-buffer) (messages-buffer))))
- (lambda (_)
- (with-current-buffer "FooNet"
- (should (eq (window-buffer) (messages-buffer)))
- (should (frame-root-window-p (selected-window))))
-
- ;; A manual /JOIN command tells ERC we're done auto-reconnecting
(with-current-buffer "FooNet" (erc-scenarios-common-say "/JOIN #spam"))
- (ert-info ("#spam ignores `erc-auto-reconnect-display'")
- ;; Uses `erc-interactive-display' instead.
+ (ert-info ("A /JOIN ignores `erc-auto-reconnect-display'")
(with-current-buffer (erc-d-t-wait-for 10 (get-buffer "#spam"))
(should (eq (window-buffer) (get-buffer "#spam")))
- ;; Option `buffer' replaces entire window (no split)
- (erc-d-t-wait-for 5 (frame-root-window-p (selected-window)))))))))
+ ;; Option `erc-interactive-display' being `buffer' means
+ ;; Emacs reuses the selected window (no split).
+ (should (frame-root-window-p (selected-window)))))))))
(ert-deftest erc-scenarios-base-buffer-display--defwino-recbury-intbuf ()
:tags '(:expensive-test)
@@ -117,7 +135,7 @@
(should (eq erc-interactive-display 'window))
(should-not erc-auto-reconnect-display)
- (let ((erc-buffer-display 'window-noselect)
+ (let ((erc-buffer-display 'window-noselect) ; defwino
(erc-auto-reconnect-display 'bury)
(erc-interactive-display 'buffer))
(erc-scenarios-base-buffer-display--reconnect-common
@@ -139,26 +157,24 @@
(should (eq (current-buffer) (window-buffer (next-window)))))
(lambda (_)
- (with-current-buffer "FooNet"
- (should (eq (window-buffer) (messages-buffer)))
- (should (frame-root-window-p (selected-window))))
-
- ;; A non-interactive JOIN command doesn't signal that we're
- ;; done auto-reconnecting, and `erc-interactive-display' is
- ;; ignored, so `erc-buffer-display' is again in charge (here,
- ;; that means `window-noselect').
- (ert-info ("Join chan noninteractively and open a /QUERY")
+ ;; A JOIN command sent from lisp code is "non-interactive" and
+ ;; doesn't reset the auto-reconnect count, so ERC treats the
+ ;; response as possibly server-initiated or otherwise the
+ ;; result of an autojoin and continues to favor
+ ;; `erc-auto-reconnect-display'.
+ (ert-info ("Join chan non-interactively and open a /QUERY")
(with-current-buffer "FooNet"
- (erc-cmd-JOIN "#spam")
- ;; However this will reset the option.
- (erc-scenarios-common-say "/QUERY bob")
+ (erc-cmd-JOIN "#spam") ; "non-interactive" according to ERC
+ (erc-scenarios-common-say "/QUERY bob") ; resets count
(should (eq (window-buffer) (get-buffer "bob")))
(should (frame-root-window-p (selected-window)))))
+ ;; The /QUERY above resets the count, and `erc-buffer-display'
+ ;; again decides how #spam is displayed.
(ert-info ("Newly joined chan ignores `erc-auto-reconnect-display'")
(with-current-buffer (erc-d-t-wait-for 10 (get-buffer "#spam"))
(should (eq (window-buffer) (get-buffer "bob")))
- (should-not (frame-root-window-p (selected-window)))
+ (should-not (frame-root-window-p (selected-window))) ; noselect
(should (eq (current-buffer) (window-buffer (next-window))))))))))
(ert-deftest erc-scenarios-base-buffer-display--count-reset-timeout ()
@@ -177,24 +193,22 @@
(lambda (_)
(with-current-buffer "FooNet"
- (should erc--server-reconnect-display-timer)
- (should (eq (window-buffer) (messages-buffer)))
- (should (frame-root-window-p (selected-window))))
+ (erc-d-t-wait-for 1 erc--server-reconnect-display-timer))
;; A non-interactive JOIN command doesn't signal that we're
- ;; done auto-reconnecting
- (ert-info ("Join chan noninteractively")
+ ;; done auto-reconnecting.
+ (ert-info ("Join channel #spam non-interactively")
(with-current-buffer "FooNet"
(erc-d-t-wait-for 1 (null erc--server-reconnect-display-timer))
- (erc-cmd-JOIN "#spam")))
+ (erc-cmd-JOIN "#spam"))) ; not processed as a /JOIN
- (ert-info ("Newly joined chan ignores `erc-auto-reconnect-display'")
- (with-current-buffer (erc-d-t-wait-for 10 (get-buffer "#spam"))
- (should (eq (window-buffer) (messages-buffer)))
- ;; If `erc-auto-reconnect-display-timeout' were left alone, this
- ;; would be (frame-root-window-p #<window 1 on *scratch*>).
- (should-not (frame-root-window-p (selected-window)))
- (should (eq (current-buffer) (window-buffer (next-window))))))))))
+ (ert-info ("Option `erc-auto-reconnect-display' ignored w/o timer")
+ (should (eq (window-buffer) (messages-buffer)))
+ (erc-d-t-wait-for 10 (get-buffer "#spam"))
+ ;; If `erc-auto-reconnect-display-timeout' were left alone,
+ ;; this would be (frame-root-window-p #<window 1 on scratch*>).
+ (should-not (frame-root-window-p (selected-window)))
+ (should (eq (get-buffer "#spam") (window-buffer (next-window)))))))))
;; This shows that the option `erc-interactive-display' overrides
;; `erc-join-buffer' during cold opens and interactive /JOINs.
diff --git a/test/lisp/erc/erc-scenarios-base-chan-modes.el b/test/lisp/erc/erc-scenarios-base-chan-modes.el
new file mode 100644
index 00000000000..73fba65acf4
--- /dev/null
+++ b/test/lisp/erc/erc-scenarios-base-chan-modes.el
@@ -0,0 +1,84 @@
+;;; erc-scenarios-base-chan-modes.el --- Channel mode scenarios -*- lexical-binding: t -*-
+
+;; Copyright (C) 2023-2024 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert-x)
+(eval-and-compile
+ (let ((load-path (cons (ert-resource-directory) load-path)))
+ (require 'erc-scenarios-common)))
+
+;; This asserts that a bug present in ERC 5.4+ is now absent.
+;; Previously, ERC would attempt to parse a nullary channel mode as if
+;; it were a status prefix update, which led to a wrong-type error.
+;; This test does not address similar collisions with unary modes,
+;; such as "MODE +q foo!*@*", but it should.
+(ert-deftest erc-scenarios-base-chan-modes--plus-q ()
+ :tags '(:expensive-test)
+ (erc-scenarios-common-with-cleanup
+ ((erc-scenarios-common-dialog "base/modes")
+ (erc-server-flood-penalty 0.1)
+ (dumb-server (erc-d-run "localhost" t 'chan-changed))
+ (erc-modules (cons 'fill-wrap erc-modules))
+ (erc-autojoin-channels-alist '((Libera.Chat "#chan")))
+ (expect (erc-d-t-make-expecter)))
+
+ (ert-info ("Connect to Libera.Chat")
+ (with-current-buffer (erc :server "127.0.0.1"
+ :port (process-contact dumb-server :service)
+ :nick "tester"
+ :full-name "tester")
+ (funcall expect 5 "changed mode")))
+
+ (with-current-buffer (erc-d-t-wait-for 5 (get-buffer "#chan"))
+ (should-not erc-channel-key)
+ (should-not erc-channel-user-limit)
+
+ (ert-info ("Receive notice that mode has changed")
+ (erc-d-t-wait-for 10 (equal erc-channel-modes '("n" "t")))
+ (erc-scenarios-common-say "ready before")
+ (funcall expect 10 "<Chad> before")
+ (funcall expect 10 " has changed mode for #chan to +Qu")
+ (erc-d-t-wait-for 10 (equal erc-channel-modes '("Q" "n" "t" "u"))))
+
+ (ert-info ("Key stored locally")
+ (erc-scenarios-common-say "ready key")
+ (funcall expect 10 "<Chad> doing key")
+ (funcall expect 10 " has changed mode for #chan to +k hunter2")
+ (should (equal erc-channel-key "hunter2")))
+
+ (ert-info ("Limit stored locally")
+ (erc-scenarios-common-say "ready limit")
+ (funcall expect 10 "<Chad> doing limit")
+ (funcall expect 10 " has changed mode for #chan to +l 3")
+ (erc-d-t-wait-for 10 (eql erc-channel-user-limit 3))
+ (should (equal erc-channel-modes '("Q" "n" "t" "u"))))
+
+ (ert-info ("Modes removed and local state deletion succeeds")
+ (erc-scenarios-common-say "ready drop")
+ (funcall expect 10 "<Chad> dropping")
+ (funcall expect 10 " has changed mode for #chan to -lu")
+ (funcall expect 10 " has changed mode for #chan to -Qk *")
+ (erc-d-t-wait-for 10 (equal erc-channel-modes '("n" "t"))))
+
+ (should-not erc-channel-key)
+ (should-not erc-channel-user-limit)
+ (funcall expect 10 "<Chad> after"))))
+
+;;; erc-scenarios-base-chan-modes.el ends here
diff --git a/test/lisp/erc/erc-scenarios-base-compat-rename-bouncer.el b/test/lisp/erc/erc-scenarios-base-compat-rename-bouncer.el
index 9275aba2875..d1124269e0a 100644
--- a/test/lisp/erc/erc-scenarios-base-compat-rename-bouncer.el
+++ b/test/lisp/erc/erc-scenarios-base-compat-rename-bouncer.el
@@ -1,6 +1,6 @@
;;; erc-scenarios-base-compat-rename-bouncer.el --- Compat-rename scenarios -*- lexical-binding: t -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/erc/erc-scenarios-base-local-module-modes.el b/test/lisp/erc/erc-scenarios-base-local-module-modes.el
index 7b91e28dc83..a3612070f7e 100644
--- a/test/lisp/erc/erc-scenarios-base-local-module-modes.el
+++ b/test/lisp/erc/erc-scenarios-base-local-module-modes.el
@@ -1,6 +1,6 @@
;;; erc-scenarios-base-local-module-modes.el --- More local-mod ERC tests -*- lexical-binding: t -*-
-;; Copyright (C) 2023 Free Software Foundation, Inc.
+;; Copyright (C) 2023-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/erc/erc-scenarios-base-local-modules.el b/test/lisp/erc/erc-scenarios-base-local-modules.el
index d6dbd87c8cc..9604c6ea17c 100644
--- a/test/lisp/erc/erc-scenarios-base-local-modules.el
+++ b/test/lisp/erc/erc-scenarios-base-local-modules.el
@@ -1,6 +1,6 @@
;;; erc-scenarios-base-local-modules.el --- Local-module tests for ERC -*- lexical-binding: t -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/erc/erc-scenarios-base-misc-regressions.el b/test/lisp/erc/erc-scenarios-base-misc-regressions.el
index c1915d088a0..df2aa8e82ec 100644
--- a/test/lisp/erc/erc-scenarios-base-misc-regressions.el
+++ b/test/lisp/erc/erc-scenarios-base-misc-regressions.el
@@ -1,6 +1,6 @@
;;; erc-scenarios-base-misc-regressions.el --- misc regressions scenarios -*- lexical-binding: t -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -77,7 +77,7 @@ Originally from scenario rebuffed/gapless as explained in Bug#48598:
(with-current-buffer (erc-d-t-wait-for 20 (get-buffer "#bar"))
(funcall expect 10 "was created on")
- (funcall expect 2 "his second fit"))
+ (funcall expect 10 "his second fit"))
(with-current-buffer (erc-d-t-wait-for 20 (get-buffer "#foo"))
(funcall expect 10 "was created on")
@@ -108,7 +108,7 @@ Originally from scenario rebuffed/gapless as explained in Bug#48598:
(should (string= (buffer-name) (format "127.0.0.1:%d" port)))))
(ert-info ("Server buffer is unique and temp name is absent")
- (erc-d-t-wait-for 1 (get-buffer "FooNet"))
+ (erc-d-t-wait-for 10 (get-buffer "FooNet"))
(should-not (erc-scenarios-common-buflist "127.0.0.1"))
(with-current-buffer erc-server-buffer-foo
(erc-cmd-JOIN "#chan")))
@@ -124,48 +124,4 @@ Originally from scenario rebuffed/gapless as explained in Bug#48598:
(with-current-buffer (erc-d-t-wait-for 5 (get-buffer "#chan"))
(erc-d-t-search-for 10 "and be prosperous")))))
-;; This defends against a partial regression in which an /MOTD caused
-;; 376 and 422 handlers in erc-networks to run.
-
-(ert-deftest erc-cmd-MOTD ()
- :tags '(:expensive-test)
- (erc-scenarios-common-with-cleanup
- ((erc-scenarios-common-dialog "base/commands")
- (erc-server-flood-penalty 0.1)
- (dumb-server (erc-d-run "localhost" t 'motd))
- (port (process-contact dumb-server :service))
- (expect (erc-d-t-make-expecter)))
-
- (ert-info ("Connect to server")
- (with-current-buffer (erc :server "127.0.0.1"
- :port port
- :nick "tester"
- :full-name "tester")
- (funcall expect 10 "This is the default Ergo MOTD")
- (funcall expect 10 "debug mode")))
-
- (ert-info ("Send plain MOTD")
- (with-current-buffer "foonet"
- (erc-cmd-MOTD)
- (funcall expect -0.2 "Unexpected state detected")
- (funcall expect 10 "This is the default Ergo MOTD")))
-
- (ert-info ("Send MOTD with known target")
- (with-current-buffer "foonet"
- (erc-scenarios-common-say "/MOTD irc1.foonet.org")
- (funcall expect -0.2 "Unexpected state detected")
- (funcall expect 10 "This is the default Ergo MOTD")))
-
- (ert-info ("Send MOTD with erroneous target")
- (with-current-buffer "foonet"
- (erc-scenarios-common-say "/MOTD fake.foonet.org")
- (funcall expect -0.2 "Unexpected state detected")
- (funcall expect 10 "No such server")
- ;; Message may show up before the handler runs.
- (erc-d-t-wait-for 10
- (not (local-variable-p 'erc-server-402-functions)))
- (should-not (local-variable-p 'erc-server-376-functions))
- (should-not (local-variable-p 'erc-server-422-functions))
- (erc-cmd-QUIT "")))))
-
;;; erc-scenarios-base-misc-regressions.el ends here
diff --git a/test/lisp/erc/erc-scenarios-base-netid-bouncer-id.el b/test/lisp/erc/erc-scenarios-base-netid-bouncer-id.el
index 876f2e3cade..4e5c535b40a 100644
--- a/test/lisp/erc/erc-scenarios-base-netid-bouncer-id.el
+++ b/test/lisp/erc/erc-scenarios-base-netid-bouncer-id.el
@@ -1,6 +1,6 @@
;;; erc-scenarios-base-netid-bouncer-id.el --- net-id bouncer ID scenarios -*- lexical-binding: t -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/erc/erc-scenarios-base-netid-bouncer-recon-base.el b/test/lisp/erc/erc-scenarios-base-netid-bouncer-recon-base.el
index d3d07493e9e..e5453c40e56 100644
--- a/test/lisp/erc/erc-scenarios-base-netid-bouncer-recon-base.el
+++ b/test/lisp/erc/erc-scenarios-base-netid-bouncer-recon-base.el
@@ -1,6 +1,6 @@
;;; erc-scenarios-base-netid-bouncer-recon-base.el --- net-id base scenarios -*- lexical-binding: t -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/erc/erc-scenarios-base-netid-bouncer-recon-both.el b/test/lisp/erc/erc-scenarios-base-netid-bouncer-recon-both.el
index b76633f3e3e..09ddcef5fa3 100644
--- a/test/lisp/erc/erc-scenarios-base-netid-bouncer-recon-both.el
+++ b/test/lisp/erc/erc-scenarios-base-netid-bouncer-recon-both.el
@@ -1,6 +1,6 @@
;;; erc-scenarios-base-netid-bouncer-recon-both.el --- net-id both scenarios -*- lexical-binding: t -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;;
;; This file is part of GNU Emacs.
;;
diff --git a/test/lisp/erc/erc-scenarios-base-netid-bouncer-recon-id.el b/test/lisp/erc/erc-scenarios-base-netid-bouncer-recon-id.el
index 66d3c25f7da..253ab4f72c9 100644
--- a/test/lisp/erc/erc-scenarios-base-netid-bouncer-recon-id.el
+++ b/test/lisp/erc/erc-scenarios-base-netid-bouncer-recon-id.el
@@ -1,6 +1,6 @@
;;; erc-scenarios-base-netid-bouncer-recon-id.el --- recon ID scenarios -*- lexical-binding: t -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/erc/erc-scenarios-base-netid-bouncer.el b/test/lisp/erc/erc-scenarios-base-netid-bouncer.el
index a658a17601b..1a3946db45e 100644
--- a/test/lisp/erc/erc-scenarios-base-netid-bouncer.el
+++ b/test/lisp/erc/erc-scenarios-base-netid-bouncer.el
@@ -1,6 +1,6 @@
;;; erc-scenarios-base-netid-bouncer.el --- net-id bouncer scenarios -*- lexical-binding: t -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/erc/erc-scenarios-base-netid-samenet.el b/test/lisp/erc/erc-scenarios-base-netid-samenet.el
index 997dab93735..fee7d78f0e2 100644
--- a/test/lisp/erc/erc-scenarios-base-netid-samenet.el
+++ b/test/lisp/erc/erc-scenarios-base-netid-samenet.el
@@ -1,6 +1,6 @@
;;; erc-scenarios-base-netid-samenet.el --- One-network net-ID scenarios -*- lexical-binding: t -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/erc/erc-scenarios-base-reconnect.el b/test/lisp/erc/erc-scenarios-base-reconnect.el
index 7bd16d1ed14..6f968b9fcbc 100644
--- a/test/lisp/erc/erc-scenarios-base-reconnect.el
+++ b/test/lisp/erc/erc-scenarios-base-reconnect.el
@@ -1,6 +1,6 @@
;;; erc-scenarios-base-reconnect.el --- Base-reconnect scenarios -*- lexical-binding: t -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -171,7 +171,7 @@
(funcall expect 2 "Canceled")
(funcall expect 3 "Opening connection")
(funcall expect 2 "Password incorrect")
- (funcall expect 2 "Connection failed!")
+ (funcall expect 10 "Connection failed!")
(funcall expect 2 "Re-establishing connection"))
(ert-info ("Explicitly cancel timer")
(erc-cmd-RECONNECT "cancel")
diff --git a/test/lisp/erc/erc-scenarios-base-renick.el b/test/lisp/erc/erc-scenarios-base-renick.el
index 2bf3ef46257..ca22728b152 100644
--- a/test/lisp/erc/erc-scenarios-base-renick.el
+++ b/test/lisp/erc/erc-scenarios-base-renick.el
@@ -1,6 +1,6 @@
;;; erc-scenarios-base-renick.el --- Re-nicking scenarios -*- lexical-binding: t -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -173,7 +173,7 @@
(with-current-buffer erc-server-buffer-foo
(should (string= (buffer-name) (format "127.0.0.1:%d" port)))))
- (erc-d-t-wait-for 1 (get-buffer "foonet"))
+ (erc-d-t-wait-for 10 (get-buffer "foonet"))
(ert-info ("Joined by bouncer to #foo, pal persent")
(with-current-buffer (erc-d-t-wait-for 1 (get-buffer "#foo"))
@@ -267,7 +267,7 @@
(ert-info ("Sync convo for rando@foonet")
(with-current-buffer "rando@foonet"
- (funcall expect 1 "u are dumb")
+ (funcall expect 10 "u are dumb")
(erc-scenarios-common-say "not so")))
(ert-info ("Sync convo for rando@barnet")
diff --git a/test/lisp/erc/erc-scenarios-base-reuse-buffers.el b/test/lisp/erc/erc-scenarios-base-reuse-buffers.el
index 71027a0c138..f07b7024bf3 100644
--- a/test/lisp/erc/erc-scenarios-base-reuse-buffers.el
+++ b/test/lisp/erc/erc-scenarios-base-reuse-buffers.el
@@ -1,6 +1,6 @@
;;; erc-scenarios-base-reuse-buffers.el --- base-reuse-buffers scenarios -*- lexical-binding: t -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -124,6 +124,7 @@ Adapted from scenario clash-of-chans/uniquify described in Bug#48598:
(erc-d-t-search-for 1 "shake my sword")
(erc-cmd-PART "#chan")
(funcall expect 3 "You have left channel #chan")
+ (should-not (erc-get-channel-user (erc-current-nick)))
(erc-cmd-JOIN "#chan")))
(ert-info ("Part #chan@barnet")
@@ -139,6 +140,7 @@ Adapted from scenario clash-of-chans/uniquify described in Bug#48598:
(get-buffer "#chan/127.0.0.1<3>"))
(ert-info ("Activity continues in new, <n>-suffixed #chan@foonet buffer")
+ ;; The first /JOIN did not cause the same buffer to be reused.
(with-current-buffer "#chan/127.0.0.1"
(should-not (erc-get-channel-user (erc-current-nick))))
(with-current-buffer "#chan/127.0.0.1<3>"
diff --git a/test/lisp/erc/erc-scenarios-base-send-message.el b/test/lisp/erc/erc-scenarios-base-send-message.el
new file mode 100644
index 00000000000..729c94f5ab7
--- /dev/null
+++ b/test/lisp/erc/erc-scenarios-base-send-message.el
@@ -0,0 +1,126 @@
+;;; erc-scenarios-base-send-message.el --- `send-message' scenarios -*- lexical-binding: t -*-
+
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert-x)
+(eval-and-compile
+ (let ((load-path (cons (ert-resource-directory) load-path)))
+ (require 'erc-scenarios-common)))
+
+;; So-called "noncommands" are those that massage input submitted at
+;; the prompt and send it on behalf of the user.
+
+(ert-deftest erc-scenarios-base-send-message--noncommands ()
+ :tags '(:expensive-test)
+ (erc-scenarios-common-with-cleanup
+ ((erc-scenarios-common-dialog "base/send-message")
+ (erc-server-flood-penalty 0.1)
+ (dumb-server (erc-d-run "localhost" t 'noncommands))
+ (erc-modules (cons 'fill-wrap erc-modules))
+ (erc-autojoin-channels-alist '((foonet "#chan")))
+ (expect (erc-d-t-make-expecter)))
+
+ (ert-info ("Connect to foonet")
+ (with-current-buffer (erc :server "127.0.0.1"
+ :port (process-contact dumb-server :service)
+ :nick "tester"
+ :full-name "tester")
+ (funcall expect 5 "debug mode")))
+
+ (with-current-buffer (erc-d-t-wait-for 5 (get-buffer "#chan"))
+ (ert-info ("Send CTCP ACTION")
+ (funcall expect 10 "<bob> alice: For hands, to do Rome")
+ (erc-scenarios-common-say "/me sad")
+ (funcall expect 10 "* tester sad"))
+
+ (ert-info ("Send literal command")
+ (funcall expect 10 "<alice> bob: Spotted, detested")
+ (erc-scenarios-common-say "/say /me sad")
+ (funcall expect 10 "<tester> /me sad"))
+
+ (ert-info ("\"Nested\" `noncommands'")
+
+ (ert-info ("Send version via /SV")
+ (funcall expect 10 "<bob> Marcus, my brother!")
+ (erc-scenarios-common-say "/sv")
+ (funcall expect 10 "<tester> I'm using ERC"))
+
+ (ert-info ("Send module list via /SM")
+ (funcall expect 10 "<bob> alice: You still wrangle")
+ (erc-scenarios-common-say "/sm")
+ (funcall expect 10 "<tester> I'm using the following modules: ")
+ (funcall expect 10 "<alice> No, not till Thursday;"))))))
+
+
+;; This asserts that the `command-indicator' module only inserts
+;; prompt-like prefixes for normal slash commands, like /JOIN.
+
+(ert-deftest erc-scenarios-base-send-message--command-indicator ()
+ :tags '(:expensive-test)
+ (erc-scenarios-common-with-cleanup
+ ((erc-scenarios-common-dialog "base/send-message")
+ (erc-server-flood-penalty 0.1)
+ (dumb-server (erc-d-run "localhost" t 'noncommands))
+ (erc-modules `(command-indicator fill-wrap ,@erc-modules))
+ (expect (erc-d-t-make-expecter)))
+
+ (ert-info ("Connect to foonet")
+ (with-current-buffer (erc :server "127.0.0.1"
+ :port (process-contact dumb-server :service)
+ :nick "tester"
+ :full-name "tester")
+ (funcall expect 5 "debug mode")
+ (erc-scenarios-common-say "/join #chan")
+ (funcall expect 10 "ERC> /join #chan")))
+
+ (with-current-buffer (erc-d-t-wait-for 5 (get-buffer "#chan"))
+ (ert-info ("Prompt absent for CTCP ACTION")
+ (funcall expect 10 "<bob> alice: For hands, to do Rome")
+ (erc-scenarios-common-say "/me sad")
+ (funcall expect -0.1 "ERC> /me sad")
+ (funcall expect 10 "* tester sad"))
+
+ (ert-info ("Prompt absent for literal command")
+ (funcall expect 10 "<alice> bob: Spotted, detested")
+ (erc-scenarios-common-say "/say /me sad")
+ (funcall expect -0.1 "ERC> /say /me sad")
+ (funcall expect 10 "<tester> /me sad"))
+
+ (ert-info ("Prompt absent for /SV")
+ (funcall expect 10 "<bob> Marcus, my brother!")
+ (erc-scenarios-common-say "/sv")
+ (funcall expect -0.1 "ERC> /sv")
+ (funcall expect 10 "<tester> I'm using ERC"))
+
+ (ert-info ("Prompt absent module list via /SM")
+ (funcall expect 10 "<bob> alice: You still wrangle")
+ (erc-scenarios-common-say "/sm")
+ (funcall expect -0.1 "ERC> /sm")
+ (funcall expect 10 "<tester> I'm using the following modules: ")
+ (funcall expect 10 "<alice> No, not till Thursday;"))
+
+ (ert-info ("Prompt present for /QUIT in issuing buffer")
+ (erc-scenarios-common-say "/quit")
+ (funcall expect 10 "ERC> /quit"))
+
+ (with-current-buffer "foonet"
+ (funcall expect 10 "ERC finished")))))
+
+;;; erc-scenarios-base-send-message.el ends here
diff --git a/test/lisp/erc/erc-scenarios-base-split-line.el b/test/lisp/erc/erc-scenarios-base-split-line.el
index f6d888c1f28..dee5950f8ef 100644
--- a/test/lisp/erc/erc-scenarios-base-split-line.el
+++ b/test/lisp/erc/erc-scenarios-base-split-line.el
@@ -1,6 +1,6 @@
;;; erc-scenarios-base-split-line.el --- ERC line splitting -*- lexical-binding: t -*-
-;; Copyright (C) 2023 Free Software Foundation, Inc.
+;; Copyright (C) 2023-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/erc/erc-scenarios-base-statusmsg.el b/test/lisp/erc/erc-scenarios-base-statusmsg.el
new file mode 100644
index 00000000000..480ba7fa8d0
--- /dev/null
+++ b/test/lisp/erc/erc-scenarios-base-statusmsg.el
@@ -0,0 +1,103 @@
+;;; erc-scenarios-base-statusmsg.el --- statusmsg tests -*- lexical-binding: t -*-
+
+;; Copyright (C) 2023-2024 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert-x)
+(eval-and-compile
+ (let ((load-path (cons (ert-resource-directory) load-path)))
+ (require 'erc-scenarios-common)))
+
+(ert-deftest erc-scenarios-base-statusmsg ()
+
+ (erc-scenarios-common-with-cleanup
+ ((erc-scenarios-common-dialog "base/display-message")
+ (dumb-server (erc-d-run "localhost" t 'statusmsg))
+ (erc-autojoin-channels-alist '((foonet "#mine")))
+ (erc-modules (cons 'fill-wrap erc-modules))
+ (port (process-contact dumb-server :service))
+ (erc-show-speaker-membership-status nil)
+ (erc-server-flood-penalty 0.1)
+ (expect (erc-d-t-make-expecter)))
+
+ (ert-info ("Connect")
+ (with-current-buffer (erc :server "127.0.0.1"
+ :port port
+ :nick "tester"
+ :user "tester"
+ :full-name "tester")
+ (funcall expect 5 "This server is in debug mode")))
+
+ (with-current-buffer (erc-d-t-wait-for 10 (get-buffer "#mine"))
+
+ (ert-info ("Receive status messages unprefixed")
+ (funcall expect 5 "+dummy")
+ (funcall expect 5 "(dummy+) hello")
+ (should (eq 'statusmsg (erc--get-inserted-msg-prop 'erc--msg)))
+ (should (equal "dummy" (erc--get-inserted-msg-prop 'erc--spkr)))
+ (should (eq (get-text-property (1- (point)) 'font-lock-face)
+ 'erc-default-face))
+ (funcall expect 5 "(dummy+) there")
+ (should (equal "" (get-text-property (pos-bol) 'display)))
+
+ ;; CTCP ACTION
+ (funcall expect 5 "* (dummy+) sad")
+ (should (eq 'ctcp-action-statusmsg
+ (erc--get-inserted-msg-prop 'erc--msg)))
+ (should (eq (get-text-property (1- (point)) 'font-lock-face)
+ 'erc-action-face))
+ (funcall expect 5 "* (dummy+) glad")
+ (should (equal "" (get-text-property (pos-bol) 'display))))
+
+ (ert-info ("Send status messages")
+ ;; We don't have `echo-message' yet, so ERC doesn't currently
+ ;; insert commands like "/msg +#mine foo".
+ (let ((erc-default-recipients '("+#mine")))
+ (erc-send-message "howdy"))
+ (funcall expect 5 "(@tester+) howdy")
+ (should (eq 'statusmsg-input (erc--get-inserted-msg-prop 'erc--msg)))
+ (should (equal "tester" (erc--get-inserted-msg-prop 'erc--spkr)))
+ (should (eq (get-text-property (1- (point)) 'font-lock-face)
+ 'erc-input-face))
+ (let ((erc-default-recipients '("+#mine")))
+ (erc-send-message "tenderfoot"))
+ (funcall expect 5 "(@tester+) tenderfoot")
+ (should (equal "" (get-text-property (pos-bol) 'display)))
+
+ ;; Simulate some "echoed" CTCP ACTION messages since we don't
+ ;; actually support that yet.
+ (funcall expect 5 "* (@tester+) mad")
+ (should (eq 'ctcp-action-statusmsg-input
+ (erc--get-inserted-msg-prop 'erc--msg)))
+ (should (equal (get-text-property (1- (point)) 'font-lock-face)
+ '(erc-input-face erc-action-face)))
+ (funcall expect 5 "* (@tester+) chad")
+ (should (equal "" (get-text-property (pos-bol) 'display))))
+
+ (ert-info ("Receive status messages prefixed")
+ (setq erc-show-speaker-membership-status t)
+ (erc-scenarios-common-say "/me ready") ; sync
+ (funcall expect 5 "* @tester ready")
+ (funcall expect 5 "(+dummy+) okie")
+
+ ;; CTCP ACTION
+ (funcall expect 5 "* (+dummy+) dokie")
+ (funcall expect 5 "* +dummy out")))))
+
+;;; erc-scenarios-base-statusmsg.el ends here
diff --git a/test/lisp/erc/erc-scenarios-base-unstable.el b/test/lisp/erc/erc-scenarios-base-unstable.el
index 2ccf8880b95..a88d8e17077 100644
--- a/test/lisp/erc/erc-scenarios-base-unstable.el
+++ b/test/lisp/erc/erc-scenarios-base-unstable.el
@@ -1,6 +1,6 @@
;;; erc-scenarios-base-unstable.el --- base unstable scenarios -*- lexical-binding: t -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/erc/erc-scenarios-base-upstream-recon-soju.el b/test/lisp/erc/erc-scenarios-base-upstream-recon-soju.el
index fc8be982f65..cf7af1ae9a7 100644
--- a/test/lisp/erc/erc-scenarios-base-upstream-recon-soju.el
+++ b/test/lisp/erc/erc-scenarios-base-upstream-recon-soju.el
@@ -1,6 +1,6 @@
;;; erc-scenarios-base-upstream-recon-soju.el --- Bouncer recon scenario -*- lexical-binding: t -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/erc/erc-scenarios-base-upstream-recon-znc.el b/test/lisp/erc/erc-scenarios-base-upstream-recon-znc.el
index 461dac27b21..bbd9c79f593 100644
--- a/test/lisp/erc/erc-scenarios-base-upstream-recon-znc.el
+++ b/test/lisp/erc/erc-scenarios-base-upstream-recon-znc.el
@@ -1,6 +1,6 @@
;;; erc-scenarios-base-upstream-recon-znc.el --- Bouncer recon scenario -*- lexical-binding: t -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/erc/erc-scenarios-display-message.el b/test/lisp/erc/erc-scenarios-display-message.el
new file mode 100644
index 00000000000..8e9c355576e
--- /dev/null
+++ b/test/lisp/erc/erc-scenarios-display-message.el
@@ -0,0 +1,63 @@
+;;; erc-scenarios-display-message.el --- erc-display-message -*- lexical-binding: t -*-
+
+;; Copyright (C) 2023-2024 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert-x)
+(eval-and-compile
+ (let ((load-path (cons (ert-resource-directory) load-path)))
+ (require 'erc-scenarios-common)))
+
+(ert-deftest erc-scenarios-display-message--multibuf ()
+ :tags '(:expensive-test)
+ (erc-scenarios-common-with-cleanup
+ ((erc-scenarios-common-dialog "base/display-message")
+ (dumb-server (erc-d-run "localhost" t 'multibuf))
+ (port (process-contact dumb-server :service))
+ (erc-server-flood-penalty 0.1)
+ (erc-modules (cons 'fill-wrap erc-modules))
+ (erc-autojoin-channels-alist '((foonet "#chan")))
+ (expect (erc-d-t-make-expecter)))
+
+ (ert-info ("Connect to foonet")
+ (with-current-buffer (erc :server "127.0.0.1"
+ :port port
+ :nick "tester"
+ :full-name "tester")
+ (funcall expect 10 "debug mode")))
+
+ (ert-info ("User dummy is a member of #chan")
+ (with-current-buffer (erc-d-t-wait-for 5 (get-buffer "#chan"))
+ (funcall expect 10 "dummy")))
+
+ (ert-info ("Dummy's QUIT notice in query contains metadata props")
+ (with-current-buffer (erc-d-t-wait-for 5 (get-buffer "dummy"))
+ (funcall expect 10 "<dummy> hi")
+ (funcall expect 10 "*** dummy (~u@rdjcgiwfuwqmc.irc) has quit")
+ (should (eq 'QUIT (get-text-property (match-beginning 0) 'erc--msg)))))
+
+ (ert-info ("Dummy's QUIT notice in #chan contains metadata props")
+ (with-current-buffer (erc-d-t-wait-for 5 (get-buffer "#chan"))
+ (funcall expect 10 "*** dummy (~u@rdjcgiwfuwqmc.irc) has quit")
+ (should (eq 'QUIT (get-text-property (match-beginning 0) 'erc--msg)))))
+
+ (with-current-buffer "foonet"
+ (erc-cmd-QUIT ""))))
+
+;;; erc-scenarios-display-message.el ends here
diff --git a/test/lisp/erc/erc-scenarios-internal.el b/test/lisp/erc/erc-scenarios-internal.el
index 18eb94e24b0..6911bcc9aac 100644
--- a/test/lisp/erc/erc-scenarios-internal.el
+++ b/test/lisp/erc/erc-scenarios-internal.el
@@ -1,6 +1,6 @@
;;; erc-scenarios-internal.el --- Proxy file for erc-d tests -*- lexical-binding: t -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -24,8 +24,37 @@
(when (and (getenv "EMACS_TEST_DIRECTORY")
(getenv "EMACS_TEST_JUNIT_REPORT"))
(setq ert-load-file-name (or (macroexp-file-name) buffer-file-name)))
- (let ((load-path (cons (expand-file-name "erc-d" (ert-resource-directory))
- load-path)))
- (load "erc-d-tests" nil 'silent)))
+ (let ((load-path `(,(expand-file-name "erc-d" (ert-resource-directory))
+ ,(ert-resource-directory)
+ ,@load-path)))
+ ;; Run all tests in ./resources/erc-d/erc-d-tests.el.
+ (load "erc-d-tests" nil 'silent)
+ (require 'erc-tests-common)))
+
+;; Run all tests tagged `:erc--graphical' in an "interactive"
+;; subprocess. Time out after 90 seconds.
+(ert-deftest erc-scenarios-internal--run-graphical-all ()
+ :tags '(:expensive-test :unstable)
+ (unless (and (getenv "ERC_TESTS_GRAPHICAL_ALL")
+ (not (getenv "ERC_TESTS_GRAPHICAL"))
+ (not (getenv "CI")))
+ (ert-skip "Environmental conditions unmet"))
+
+ (let* ((default-directory (expand-file-name "../" (ert-resource-directory)))
+ (libs (directory-files default-directory 'full (rx ".el" eot)))
+ (process-environment (cons "ERC_TESTS_GRAPHICAL=1"
+ process-environment))
+ (program '(progn (ert (quote (tag :erc--graphical)))
+ (with-current-buffer ert--output-buffer-name
+ (kill-emacs (ert--stats-failed-unexpected
+ ert--results-stats)))))
+ (proc (erc-tests-common-create-subprocess program
+ '( "-L" "." "-l" "ert")
+ libs)))
+
+ (erc-d-t-wait-for 90 "interactive tests to complete"
+ (not (process-live-p proc)))
+
+ (should (zerop (process-exit-status proc)))))
;;; erc-scenarios-internal.el ends here
diff --git a/test/lisp/erc/erc-scenarios-join-auth-source.el b/test/lisp/erc/erc-scenarios-join-auth-source.el
index 6ed5bc2db37..b04700e6311 100644
--- a/test/lisp/erc/erc-scenarios-join-auth-source.el
+++ b/test/lisp/erc/erc-scenarios-join-auth-source.el
@@ -1,6 +1,6 @@
;;; erc-scenarios-join-auth-source.el --- join-auth-source scenarios -*- lexical-binding: t -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/erc/erc-scenarios-join-display-context.el b/test/lisp/erc/erc-scenarios-join-display-context.el
index 32b782d2af1..84297de7acd 100644
--- a/test/lisp/erc/erc-scenarios-join-display-context.el
+++ b/test/lisp/erc/erc-scenarios-join-display-context.el
@@ -1,6 +1,6 @@
;;; erc-scenarios-join-display-context.el --- buffer-display autojoin ctx -*- lexical-binding: t -*-
-;; Copyright (C) 2023 Free Software Foundation, Inc.
+;; Copyright (C) 2023-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/erc/erc-scenarios-join-netid-newcmd-id.el b/test/lisp/erc/erc-scenarios-join-netid-newcmd-id.el
index 812ac1c3b56..3f1f864179b 100644
--- a/test/lisp/erc/erc-scenarios-join-netid-newcmd-id.el
+++ b/test/lisp/erc/erc-scenarios-join-netid-newcmd-id.el
@@ -1,6 +1,6 @@
;;; erc-scenarios-join-netid-newcmd-id.el --- join netid newcmd scenarios -*- lexical-binding: t -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/erc/erc-scenarios-join-netid-newcmd.el b/test/lisp/erc/erc-scenarios-join-netid-newcmd.el
index c8e9d66906e..955ea465f79 100644
--- a/test/lisp/erc/erc-scenarios-join-netid-newcmd.el
+++ b/test/lisp/erc/erc-scenarios-join-netid-newcmd.el
@@ -1,6 +1,6 @@
;;; erc-scenarios-join-netid-newcmd.el --- join netid newcmd scenarios -*- lexical-binding: t -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/erc/erc-scenarios-join-netid-recon-id.el b/test/lisp/erc/erc-scenarios-join-netid-recon-id.el
index 0e0fc9132b8..9910cd95b22 100644
--- a/test/lisp/erc/erc-scenarios-join-netid-recon-id.el
+++ b/test/lisp/erc/erc-scenarios-join-netid-recon-id.el
@@ -1,6 +1,6 @@
;;; erc-scenarios-join-netid-recon-id.el --- join-netid-recon scenarios -*- lexical-binding: t -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/erc/erc-scenarios-join-netid-recon.el b/test/lisp/erc/erc-scenarios-join-netid-recon.el
index 0f76617faa5..3943c139465 100644
--- a/test/lisp/erc/erc-scenarios-join-netid-recon.el
+++ b/test/lisp/erc/erc-scenarios-join-netid-recon.el
@@ -1,6 +1,6 @@
;;; erc-scenarios-join-netid-recon.el --- join-netid-recon scenarios -*- lexical-binding: t -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/erc/erc-scenarios-keep-place-indicator.el b/test/lisp/erc/erc-scenarios-keep-place-indicator.el
new file mode 100644
index 00000000000..b8ff59f4e02
--- /dev/null
+++ b/test/lisp/erc/erc-scenarios-keep-place-indicator.el
@@ -0,0 +1,141 @@
+;;; erc-scenarios-keep-place-indicator.el --- erc-keep-place-indicator-mode -*- lexical-binding: t -*-
+
+;; Copyright (C) 2023-2024 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert-x)
+(eval-and-compile
+ (let ((load-path (cons (ert-resource-directory) load-path)))
+ (require 'erc-scenarios-common)))
+
+(require 'erc-goodies)
+
+;; This test shows that the indicator does not update when at least
+;; one window remains. When the last window showing a buffer switches
+;; away, the indicator is updated if it's earlier in the buffer.
+(ert-deftest erc-scenarios-keep-place-indicator--follow ()
+ :tags `(:expensive-test
+ ,@(and (getenv "ERC_TESTS_GRAPHICAL") '(:erc--graphical)))
+ (when (version< emacs-version "29") (ert-skip "Times out"))
+ ;; XXX verify that this continues to be the case ^.
+
+ (should-not erc-scrolltobottom-all)
+ (should-not erc-scrolltobottom-mode)
+ (should-not erc-keep-place-mode)
+
+ (erc-scenarios-common-with-noninteractive-in-term
+ ((erc-scenarios-common-dialog "keep-place")
+ (dumb-server (erc-d-run "localhost" t 'follow))
+ (port (process-contact dumb-server :service))
+ (erc-modules `( keep-place-indicator scrolltobottom fill-wrap
+ ,@erc-modules))
+ (erc-keep-place-indicator-follow t)
+ (erc-scrolltobottom-all t)
+ (erc-server-flood-penalty 0.1)
+ (erc-autojoin-channels-alist '((foonet "#chan" "#spam")))
+ (expect (erc-d-t-make-expecter)))
+
+ (ert-info ("Connect")
+ (with-current-buffer (erc :server "127.0.0.1"
+ :port port
+ :full-name "tester"
+ :nick "tester"
+ :user "tester")
+ (funcall expect 10 "debug mode")))
+
+ (with-current-buffer (erc-d-t-wait-for 10 (get-buffer "#chan"))
+ (set-window-buffer nil (current-buffer))
+ (delete-other-windows)
+ (split-window-below)
+ (funcall expect 10 "<bob> tester, welcome!")
+ (recenter 0)
+ (other-window 1)
+ (funcall expect 10 "<alice> tester, welcome!")
+ (recenter 0)
+ (should (= 2 (length (window-list))))
+
+ (ert-info ("Last window to switch away has point earlier in buffer")
+ ;; Lower window, with point later in buffer, switches away first.
+ (switch-to-buffer (erc-d-t-wait-for 10 (get-buffer "#spam"))) ; lower
+ (other-window 1)
+ (switch-to-buffer "#spam") ; upper
+ (erc-scenarios-common-say "one")
+ (funcall expect 10 "Ay, the heads")
+
+ ;; Overlay has moved to upper window start.
+ (switch-to-buffer "#chan")
+ (redisplay) ; force overlay to update
+ (save-excursion
+ (goto-char (window-point))
+ (should (looking-back (rx "<bob> tester, welcome!")))
+ (should (= (pos-bol) (window-start)))
+ (should (= (overlay-start erc--keep-place-indicator-overlay)
+ (pos-bol))))
+ ;; Lower window is still centered at start.
+ (other-window 1)
+ (switch-to-buffer "#chan")
+ (save-excursion
+ (goto-char (window-point))
+ (should (looking-back (rx "<alice> tester, welcome!")))
+ (should (= (pos-bol) (window-start)))))
+
+ (ert-info ("Last window to switch away has point later in buffer")
+ ;; Lower window advances.
+ (funcall expect 10 "<bob> alice: Since you can cog")
+ (recenter 0)
+ (redisplay) ; force ^ to appear on first line
+
+ (other-window 1) ; upper still at indicator, swtiches first
+ (switch-to-buffer "#spam")
+ (other-window 1)
+ (switch-to-buffer "#spam") ; lower follows, speaks to sync
+ (erc-scenarios-common-say "two")
+ (funcall expect 10 "<bob> Cause they take")
+ (goto-char (point-max))
+
+ ;; Upper switches back first, finds indicator gone.
+ (other-window 1)
+ (switch-to-buffer "#chan")
+ (save-excursion
+ (goto-char (window-point))
+ (should (looking-back (rx "<bob> tester, welcome!")))
+ (should (= (pos-bol) (window-start)))
+ (should (> (overlay-start erc--keep-place-indicator-overlay)
+ (pos-eol))))
+
+ ;; Lower window follows, window-start preserved.
+ (other-window 1)
+ (switch-to-buffer "#chan")
+ (save-excursion
+ (goto-char (window-point))
+ (should (looking-back (rx "you can cog")))
+ (should (= (pos-bol) (window-start)))
+ (should (= (overlay-start erc--keep-place-indicator-overlay)
+ (pos-bol)))))
+
+ (ert-info ("description")
+ (erc-send-input-line "#spam" "three")
+ (save-excursion (erc-d-t-search-for 10 "Ready"))
+ (switch-to-buffer "#spam")
+ (should (< (point) erc-input-marker))))
+
+ (erc-keep-place-mode -1)
+ (erc-scrolltobottom-mode -1)))
+
+;;; erc-scenarios-keep-place-indicator.el ends here
diff --git a/test/lisp/erc/erc-scenarios-log.el b/test/lisp/erc/erc-scenarios-log.el
index c37e6b323aa..3c738822f96 100644
--- a/test/lisp/erc/erc-scenarios-log.el
+++ b/test/lisp/erc/erc-scenarios-log.el
@@ -1,6 +1,6 @@
;;; erc-scenarios-log.el --- erc-log scenarios -*- lexical-binding: t -*-
-;; Copyright (C) 2023 Free Software Foundation, Inc.
+;; Copyright (C) 2023-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -81,6 +81,7 @@
(ert-deftest erc-scenarios-log--clear-stamp ()
:tags '(:expensive-test)
+ (require 'erc-stamp)
(erc-scenarios-common-with-cleanup
((erc-scenarios-common-dialog "base/assoc/bouncer-history")
(dumb-server (erc-d-run "localhost" t 'foonet))
@@ -148,7 +149,7 @@
(when noninteractive (delete-directory tempdir :recursive))))
(ert-deftest erc-scenarios-log--truncate ()
- :tags '(:expensive-test)
+ :tags '(:expensive-test :unstable)
(erc-scenarios-common-with-cleanup
((erc-scenarios-common-dialog "base/assoc/bouncer-history")
(dumb-server (erc-d-run "localhost" t 'foonet))
@@ -202,6 +203,62 @@
(funcall expect -0.1 "please your lordship")))
(erc-log-mode -1)
+ (erc-truncate-mode -1)
+ (when noninteractive (delete-directory tempdir :recursive))))
+
+(defvar erc-insert-timestamp-function)
+(declare-function erc-insert-timestamp-left "erc-stamp" (string))
+
+(ert-deftest erc-scenarios-log--save-buffer-in-logs/truncate-on-save ()
+ :tags '(:expensive-test)
+ (erc-scenarios-common-with-cleanup
+ ((erc-scenarios-common-dialog "base/assoc/bouncer-history")
+ (dumb-server (erc-d-run "localhost" t 'foonet))
+ (tempdir (make-temp-file "erc-tests-log." t nil nil))
+ (erc-log-channels-directory tempdir)
+ (erc-modules (cons 'log erc-modules))
+ (port (process-contact dumb-server :service))
+ (erc-truncate-buffer-on-save t)
+ (logchan (expand-file-name (format "#chan!tester@127.0.0.1:%d.txt" port)
+ tempdir))
+ (erc-server-flood-penalty 0.1)
+ (erc-insert-timestamp-function #'erc-insert-timestamp-left)
+ (expect (erc-d-t-make-expecter)))
+
+ (unless noninteractive
+ (add-hook 'kill-emacs-hook
+ (lambda () (delete-directory tempdir :recursive))))
+
+ (ert-info ("Connect to foonet")
+ (with-current-buffer (erc :server "127.0.0.1"
+ :port port
+ :nick "tester"
+ :password "foonet:changeme"
+ :full-name "tester")
+ (should (string= (buffer-name) (format "127.0.0.1:%d" port)))))
+
+ (with-current-buffer (erc-d-t-wait-for 5 (get-buffer "#chan"))
+ (funcall expect 10 "<someone> [07:04:10] hi everyone")
+ (should-not (file-exists-p logchan))
+ ;; Simulate an M-x erc-save-buffer-in-logs RET
+ (cl-letf (((symbol-function 'called-interactively-p) #'always))
+ (call-interactively #'erc-save-buffer-in-logs))
+ (should (file-exists-p logchan))
+ (funcall expect 10 "<alice> bob: As't please your lordship")
+ (erc-save-buffer-in-logs)
+ ;; Not truncated when called by lisp code.
+ (should (> (buffer-size) 400)))
+
+ (ert-info ("No double entries")
+ (with-temp-buffer
+ (insert-file-contents logchan)
+ (funcall expect 0.1 "hi everyone")
+ (funcall expect -0.1 "hi everyone")
+ (funcall expect 0.1 "Playback Complete")
+ (funcall expect -0.1 "Playback Complete")
+ (funcall expect 10 "<alice> bob: As't")))
+
+ (erc-log-mode -1)
(when noninteractive (delete-directory tempdir :recursive))))
;;; erc-scenarios-log.el ends here
diff --git a/test/lisp/erc/erc-scenarios-match.el b/test/lisp/erc/erc-scenarios-match.el
index cd899fddb98..22e34a8efe8 100644
--- a/test/lisp/erc/erc-scenarios-match.el
+++ b/test/lisp/erc/erc-scenarios-match.el
@@ -1,6 +1,6 @@
;;; erc-scenarios-match.el --- Misc `erc-match' scenarios -*- lexical-binding: t -*-
-;; Copyright (C) 2023 Free Software Foundation, Inc.
+;; Copyright (C) 2023-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -55,7 +55,8 @@
:nick "tester")
;; Module `timestamp' follows `match' in insertion hooks.
(should (memq 'erc-add-timestamp
- (memq 'erc-match-message erc-insert-modify-hook)))
+ (memq 'erc-match-message
+ (default-value 'erc-insert-modify-hook))))
;; The "match type" is `current-nick'.
(funcall expect 5 "tester")
(should (eq (get-text-property (1- (point)) 'font-lock-face)
@@ -91,7 +92,8 @@
:nick "tester")
;; Module `timestamp' follows `match' in insertion hooks.
(should (memq 'erc-add-timestamp
- (memq 'erc-match-message erc-insert-modify-hook)))
+ (memq 'erc-match-message
+ (default-value 'erc-insert-modify-hook))))
(funcall expect 5 "This server is in debug mode")))
(ert-info ("Ensure lines featuring \"bob\" are invisible")
@@ -132,7 +134,7 @@
;; Leading stamp has combined `invisible' property value.
(should (equal (get-text-property (pos-bol) 'invisible)
- '(timestamp match-fools)))
+ '(match-fools timestamp)))
;; Message proper has the `invisible' property `match-fools'.
(let ((msg-beg (next-single-property-change (pos-bol) 'invisible)))
@@ -151,29 +153,13 @@
(= (next-single-property-change msg-beg 'invisible nil (pos-eol))
(pos-eol))))))))
-(defun erc-scenarios-match--find-bol ()
- (save-excursion
- (should (get-text-property (1- (point)) 'erc-command))
- (goto-char (should (previous-single-property-change (point) 'erc-command)))
- (pos-bol)))
-
-(defun erc-scenarios-match--find-eol ()
- (save-excursion
- (if-let ((next (next-single-property-change (point) 'erc-command)))
- (goto-char next)
- ;; We're already at the end of the message.
- (should (get-text-property (1- (point)) 'erc-command)))
- (pos-eol)))
-
;; In most cases, `erc-hide-fools' makes line endings invisible.
(defun erc-scenarios-match--stamp-right-fools-invisible ()
- :tags '(:expensive-test)
(let ((erc-insert-timestamp-function #'erc-insert-timestamp-right))
(erc-scenarios-match--invisible-stamp
(lambda ()
- (let ((beg (erc-scenarios-match--find-bol))
- (end (erc-scenarios-match--find-eol)))
+ (pcase-let ((`(,beg . ,end) (erc--get-inserted-msg-bounds)))
;; The end of the message is a newline.
(should (= ?\n (char-after end)))
@@ -182,7 +168,7 @@
;; Stamps have a combined `invisible' property value.
(should (equal (get-text-property (1- end) 'invisible)
- '(timestamp match-fools)))
+ '(match-fools timestamp)))
;; The final newline is hidden by `match', not `stamps'
(with-suppressed-warnings ((obsolete erc-legacy-invisible-bounds-p))
@@ -198,14 +184,14 @@
;; It ends just before the timestamp.
(let ((msg-end (next-single-property-change (pos-bol) 'invisible)))
(should (equal (get-text-property msg-end 'invisible)
- '(timestamp match-fools)))
+ '(match-fools timestamp)))
;; Stamp's `invisible' property extends throughout the stamp
;; and ends before the trailing newline.
(should (= (next-single-property-change msg-end 'invisible) end)))))
(lambda ()
- (let ((end (erc-scenarios-match--find-eol)))
+ (let ((end (erc--get-inserted-msg-end (point))))
;; This message has a time stamp like all the others.
(should (eq (field-at-pos (1- end)) 'erc-timestamp))
@@ -244,7 +230,7 @@
;; Stamps have a combined `invisible' property value.
(should (equal (get-text-property (1- (pos-eol)) 'invisible)
- '(timestamp match-fools)))
+ '(match-fools timestamp)))
;; The message proper has the `invisible' property `match-fools',
;; which starts at the preceding newline...
@@ -253,7 +239,7 @@
;; ... and ends just before the timestamp.
(let ((msgend (next-single-property-change (1- (pos-bol)) 'invisible)))
(should (equal (get-text-property msgend 'invisible)
- '(timestamp match-fools)))
+ '(match-fools timestamp)))
;; The newline before `erc-insert-marker' is still visible.
(should-not (get-text-property (pos-eol) 'invisible))
@@ -271,7 +257,172 @@
(let ((inv-beg (next-single-property-change (1- (pos-bol)) 'invisible)))
(should (eq (get-text-property inv-beg 'invisible) 'timestamp)))))))
-(defun erc-scenarios-match--stamp-both-invisible-fill-static ()
+(defun erc-scenarios-match--fill-wrap-stamp-dedented-p (point)
+ (pcase (get-text-property point 'line-prefix)
+ (`(space :width (- erc-fill--wrap-value (,n)))
+ (if (display-graphic-p) (< 100 n 200) (< 10 n 30)))
+ (`(space :width (- erc-fill--wrap-value ,n))
+ (< 10 n 30))))
+
+(ert-deftest erc-scenarios-match--hide-fools/stamp-both/fill-wrap ()
+
+ ;; Rewind the clock to known date artificially. We should probably
+ ;; use a ticks/hz cons on 29+.
+ (let ((erc-stamp--current-time 704591940)
+ (erc-stamp--tz t)
+ (erc-fill-function #'erc-fill-wrap)
+ (bob-utterance-counter 0))
+
+ (erc-scenarios-match--invisible-stamp
+
+ (lambda ()
+ (ert-info ("Baseline check")
+ ;; False date printed initially before anyone speaks.
+ (when (zerop bob-utterance-counter)
+ (save-excursion
+ (goto-char (point-min))
+ (search-forward "[Wed Apr 29 1992]")
+ ;; First stamp in a buffer is not invisible from previous
+ ;; newline (before stamp's own leading newline).
+ (should (= 4 (match-beginning 0)))
+ (should (get-text-property 3 'invisible))
+ (should-not (get-text-property 2 'invisible))
+ (should (erc-scenarios-match--fill-wrap-stamp-dedented-p 4))
+ (search-forward "[23:59]"))))
+
+ (ert-info ("Line endings in Bob's messages are invisible")
+ ;; The message proper has the `invisible' property `match-fools'.
+ (should (eq (get-text-property (pos-bol) 'invisible) 'match-fools))
+ (pcase-let ((`(,mbeg . ,mend) (erc--get-inserted-msg-bounds)))
+ (should (= (char-after mend) ?\n))
+ (should-not (field-at-pos mend))
+ (should-not (field-at-pos mbeg))
+
+ (when (= bob-utterance-counter 1)
+ (let ((right-stamp (field-end mbeg)))
+ (should (eq 'erc-timestamp (field-at-pos right-stamp)))
+ (should (= mend (field-end right-stamp)))
+ (should (eq (field-at-pos (1- mend)) 'erc-timestamp))))
+
+ ;; The `erc--ts' property is present in prop stack.
+ (should (get-text-property (pos-bol) 'erc--ts))
+ (should-not (next-single-property-change (1+ (pos-bol)) 'erc--ts))
+
+ ;; Line ending has the `invisible' property `match-fools'.
+ (should (eq (get-text-property mbeg 'invisible) 'match-fools))
+ (should-not (get-text-property mend 'invisible))))
+
+ ;; Only the message right after Alice speaks contains stamps.
+ (when (= 1 bob-utterance-counter)
+
+ (ert-info ("Date stamp occupying previous line is invisible")
+ (should (eq 'match-fools (get-text-property (point) 'invisible)))
+ (save-excursion
+ (forward-line -1)
+ (goto-char (pos-bol))
+ (should (looking-at (rx "[Mon May 4 1992]")))
+ (ert-info ("Stamp's NL `invisible' as fool, not timestamp")
+ (let ((end (match-end 0)))
+ (should (eq (char-after end) ?\n))
+ (should (eq 'timestamp
+ (get-text-property (1- end) 'invisible)))
+ (should (eq 'match-fools
+ (get-text-property end 'invisible)))))
+ (should (erc-scenarios-match--fill-wrap-stamp-dedented-p (point)))
+ ;; Date stamp has a combined `invisible' property value
+ ;; that starts at the previous message's trailing newline
+ ;; and extends until the start of the message proper.
+ (should (equal ?\n (char-before (point))))
+ (should (equal ?\n (char-before (1- (point)))))
+ (let ((val (get-text-property (- (point) 2) 'invisible)))
+ (should (equal val 'timestamp))
+ (should (= (text-property-not-all (- (point) 2) (point-max)
+ 'invisible val)
+ (pos-eol))))))
+
+ (ert-info ("Current message's RHS stamp is hidden")
+ ;; Right stamp has `match-fools' property.
+ (save-excursion
+ (should-not (field-at-pos (point)))
+ (should (eq (field-at-pos (1- (pos-eol))) 'erc-timestamp)))
+
+ ;; Stamp invisibility starts where message's ends.
+ (let ((msgend (next-single-property-change (pos-bol) 'invisible)))
+ ;; Stamp has a combined `invisible' property value.
+ (should (equal (get-text-property msgend 'invisible)
+ '(match-fools timestamp)))
+
+ ;; Combined `invisible' property spans entire timestamp.
+ (should (= (next-single-property-change msgend 'invisible)
+ (pos-eol))))))
+
+ (cl-incf bob-utterance-counter))
+
+ ;; Alice.
+ (lambda ()
+ ;; Set clock ahead a week or so.
+ (setq erc-stamp--current-time 704962800)
+
+ ;; This message has no time stamp and is completely visible.
+ (should-not (eq (field-at-pos (1- (pos-eol))) 'erc-timestamp))
+ (should-not (next-single-property-change (pos-bol) 'invisible))))))
+
+;; This asserts that speaker hiding by `erc-fill-wrap-merge' doesn't
+;; take place after a series of hidden fool messages with an
+;; intervening outgoing message followed immediately by a non-fool
+;; message from the last non-hidden speaker (other than the user).
+(ert-deftest erc-scenarios-match--hide-fools/stamp-both/fill-wrap/speak ()
+
+ (erc-scenarios-common-with-cleanup
+ ((erc-scenarios-common-dialog "match/fools")
+ (erc-stamp--current-time 704591940)
+ (dumb-server (erc-d-run "localhost" t 'fill-wrap))
+ (erc-stamp--tz t)
+ (erc-fill-function #'erc-fill-wrap)
+ (port (process-contact dumb-server :service))
+ (erc-server-flood-penalty 0.1)
+ (erc-timestamp-only-if-changed-flag nil)
+ (erc-fools '("bob"))
+ (erc-text-matched-hook '(erc-hide-fools))
+ (erc-autojoin-channels-alist '((FooNet "#chan")))
+ (expect (erc-d-t-make-expecter)))
+
+ (ert-info ("Connect")
+ (with-current-buffer (erc :server "127.0.0.1"
+ :port port
+ :full-name "tester"
+ :password "changeme"
+ :nick "tester")
+ ;; Module `timestamp' follows `match' in insertion hooks.
+ (should (memq 'erc-add-timestamp
+ (memq 'erc-match-message
+ (default-value 'erc-insert-modify-hook))))
+ (funcall expect 5 "This server is in debug mode")))
+
+ (ert-info ("Ensure lines featuring \"bob\" are invisible")
+ (with-current-buffer (erc-d-t-wait-for 10 (get-buffer "#chan"))
+ (should (funcall expect 10 "<alice> None better than"))
+ (should (funcall expect 10 "<alice> bob: Still we went"))
+ (should (funcall expect 10 "<bob> alice: Give me your hand"))
+ (erc-scenarios-common-say "hey")
+ (should (funcall expect 10 "<bob> You have paid the heavens"))
+ (should (funcall expect 10 "<alice> bob: In the sick air"))
+ (should (funcall expect 10 "<alice> The web of our life"))
+
+ ;; Regression (see leading comment).
+ (should-not (equal "" (get-text-property (pos-bol) 'display)))
+
+ ;; No remaining meta-data positions, no more timestamps.
+ (should-not (next-single-property-change (1+ (pos-bol)) 'erc--ts))
+ ;; No remaining invisible messages.
+ (should-not (text-property-not-all (pos-bol) erc-insert-marker
+ 'invisible nil))
+
+ (should (funcall expect 10 "ERC>"))
+ (should-not (get-text-property (pos-bol) 'invisible))
+ (should-not (get-text-property (point) 'invisible))))))
+
+(defun erc-scenarios-match--stamp-both-invisible-fill-static (assert-ds)
(should (eq erc-insert-timestamp-function
#'erc-insert-timestamp-left-and-right))
@@ -295,21 +446,20 @@
(ert-info ("Line endings in Bob's messages are invisible")
;; The message proper has the `invisible' property `match-fools'.
(should (eq (get-text-property (pos-bol) 'invisible) 'match-fools))
- (let* ((mbeg (next-single-property-change (pos-bol) 'erc-command))
- (mend (next-single-property-change mbeg 'erc-command)))
+ (pcase-let ((`(,mbeg . ,mend) (erc--get-inserted-msg-bounds)))
- (if (/= 1 bob-utterance-counter)
- (should-not (field-at-pos mend))
+ (should (= (char-after mend) ?\n))
+ (should-not (field-at-pos mbeg))
+ (should-not (field-at-pos mend))
+ (when (= 1 bob-utterance-counter)
;; For Bob's stamped message, check newline after stamp.
- (should (eq (field-at-pos mend) 'erc-timestamp))
- (setq mend (field-end mend)))
+ (should (eq (field-at-pos (field-end mbeg)) 'erc-timestamp))
+ (should (eq (field-at-pos (1- mend)) 'erc-timestamp)))
- ;; The `erc-timestamp' property spans entire messages,
- ;; including stamps and filled text, which makes for
- ;; convenient traversal when `erc-stamp-mode' is enabled.
- (should (get-text-property (pos-bol) 'erc-timestamp))
- (should (= (next-single-property-change (pos-bol) 'erc-timestamp)
- mend))
+ ;; The `erc--ts' property is present in the message's
+ ;; width 1 prop collection at its first char.
+ (should (get-text-property (pos-bol) 'erc--ts))
+ (should-not (next-single-property-change (1+ (pos-bol)) 'erc--ts))
;; Line ending has the `invisible' property `match-fools'.
(should (= (char-after mend) ?\n))
@@ -327,12 +477,8 @@
(forward-line -1)
(goto-char (pos-bol))
(should (looking-at (rx "[Mon May 4 1992]")))
- ;; Date stamp has a combined `invisible' property value
- ;; that extends until the start of the message proper.
- (should (equal (get-text-property (point) 'invisible)
- '(timestamp match-fools)))
- (should (= (next-single-property-change (point) 'invisible)
- (1+ (pos-eol))))))
+ (should (= ?\n (char-after (- (point) 2)))) ; welcome!\n
+ (funcall assert-ds))) ; "assert date stamp"
(ert-info ("Folding preserved despite invisibility")
;; Message has a trailing time stamp, but it's been folded
@@ -346,7 +492,7 @@
(let ((msgend (next-single-property-change (pos-bol) 'invisible)))
;; Stamp has a combined `invisible' property value.
(should (equal (get-text-property msgend 'invisible)
- '(timestamp match-fools)))
+ '(match-fools timestamp)))
;; Combined `invisible' property spans entire timestamp.
(should (= (next-single-property-change msgend 'invisible)
@@ -365,13 +511,45 @@
(ert-deftest erc-scenarios-match--stamp-both-invisible-fill-static ()
:tags '(:expensive-test)
- (erc-scenarios-match--stamp-both-invisible-fill-static))
+ (erc-scenarios-match--stamp-both-invisible-fill-static
+
+ (lambda ()
+ ;; Date stamp has an `invisible' property that starts from the
+ ;; newline delimiting the current and previous messages and
+ ;; extends until the stamp's final newline. It is not combined
+ ;; with the old value, `match-fools'.
+ (let ((delim-pos (- (point) 2)))
+ (should (equal 'timestamp (get-text-property delim-pos 'invisible)))
+ ;; Stamp-only invisibility ends before its last newline.
+ (should (= (text-property-not-all delim-pos (point-max)
+ 'invisible 'timestamp)
+ (match-end 0))))))) ; pos-eol
(ert-deftest erc-scenarios-match--stamp-both-invisible-fill-static--nooffset ()
:tags '(:expensive-test)
(with-suppressed-warnings ((obsolete erc-legacy-invisible-bounds-p))
(should-not erc-legacy-invisible-bounds-p)
+
(let ((erc-legacy-invisible-bounds-p t))
- (erc-scenarios-match--stamp-both-invisible-fill-static))))
+ (erc-scenarios-match--stamp-both-invisible-fill-static
+
+ (lambda ()
+ ;; Date stamp has an `invisible' property that covers its
+ ;; format string exactly. It is not combined with the old
+ ;; value, `match-fools'.
+ (let ((delim-prev (- (point) 2)))
+ (should-not (get-text-property delim-prev 'invisible))
+ (should (eq 'erc-timestamp (field-at-pos (point))))
+ (should (= (next-single-property-change delim-prev 'invisible)
+ (field-beginning (point))))
+ (should (equal 'timestamp
+ (get-text-property (1- (point)) 'invisible)))
+ ;; Field stops before final newline because the date stamp
+ ;; is (now, as of ERC 5.6) its own standalone message.
+ (should (= ?\n (char-after (field-end (point)))))
+ ;; Stamp-only invisibility includes last newline.
+ (should (= (text-property-not-all (1- (point)) (point-max)
+ 'invisible 'timestamp)
+ (1+ (field-end (point)))))))))))
;;; erc-scenarios-match.el ends here
diff --git a/test/lisp/erc/erc-scenarios-misc-commands.el b/test/lisp/erc/erc-scenarios-misc-commands.el
new file mode 100644
index 00000000000..d6ed53b5358
--- /dev/null
+++ b/test/lisp/erc/erc-scenarios-misc-commands.el
@@ -0,0 +1,126 @@
+;;; erc-scenarios-misc-commands.el --- Misc commands for ERC -*- lexical-binding: t -*-
+
+;; Copyright (C) 2023-2024 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert-x)
+(eval-and-compile
+ (let ((load-path (cons (ert-resource-directory) load-path)))
+ (require 'erc-scenarios-common)))
+
+;; This defends against a partial regression in which an /MOTD caused
+;; 376 and 422 handlers in erc-networks to run.
+
+(ert-deftest erc-scenarios-misc-commands--MOTD ()
+ :tags '(:expensive-test)
+ (erc-scenarios-common-with-cleanup
+ ((erc-scenarios-common-dialog "commands")
+ (erc-server-flood-penalty 0.1)
+ (dumb-server (erc-d-run "localhost" t 'motd))
+ (port (process-contact dumb-server :service))
+ (expect (erc-d-t-make-expecter)))
+
+ (ert-info ("Connect to server")
+ (with-current-buffer (erc :server "127.0.0.1"
+ :port port
+ :nick "tester"
+ :full-name "tester")
+ (funcall expect 10 "This is the default Ergo MOTD")
+ (funcall expect 10 "debug mode")))
+
+ (ert-info ("Send plain MOTD")
+ (with-current-buffer "foonet"
+ (erc-cmd-MOTD)
+ (funcall expect -0.2 "Unexpected state detected")
+ (funcall expect 10 "This is the default Ergo MOTD")))
+
+ (ert-info ("Send MOTD with known target")
+ (with-current-buffer "foonet"
+ (erc-scenarios-common-say "/MOTD irc1.foonet.org")
+ (funcall expect -0.2 "Unexpected state detected")
+ (funcall expect 10 "This is the default Ergo MOTD")))
+
+ (ert-info ("Send MOTD with erroneous target")
+ (with-current-buffer "foonet"
+ (erc-scenarios-common-say "/MOTD fake.foonet.org")
+ (funcall expect -0.2 "Unexpected state detected")
+ (funcall expect 10 "No such server")
+ ;; Message may show up before the handler runs.
+ (erc-d-t-wait-for 10
+ (not (local-variable-p 'erc-server-402-functions)))
+ (should-not (local-variable-p 'erc-server-376-functions))
+ (should-not (local-variable-p 'erc-server-422-functions))
+ (erc-cmd-QUIT "")))))
+
+
+(ert-deftest erc-scenarios-misc-commands--SQUERY ()
+ :tags '(:expensive-test)
+ (erc-scenarios-common-with-cleanup
+ ((erc-scenarios-common-dialog "commands")
+ (erc-server-flood-penalty 0.1)
+ (dumb-server (erc-d-run "localhost" t 'squery))
+ (port (process-contact dumb-server :service))
+ (expect (erc-d-t-make-expecter)))
+
+ (ert-info ("Connect to server")
+ (with-current-buffer (erc :server "127.0.0.1"
+ :port port
+ :nick "tester"
+ :full-name "tester")
+ (funcall expect 10 "Your connection is secure")))
+
+ (ert-info ("Send SQUERY")
+ (with-current-buffer "IRCnet"
+ (erc-scenarios-common-say "/SQUERY alis help list")
+ (funcall expect -0.1 "Incorrect arguments")
+ (funcall expect 10 "See also: HELP EXAMPLES")))))
+
+;; Note that as of ERC 5.6, there is no actual slash-command function
+;; named `erc-cmd-vhost'. At the moment, this test merely exists to
+;; assert that the `erc-server-396' response handler updates the rolls
+;; correctly.
+(ert-deftest erc-scenarios-misc-commands--VHOST ()
+ :tags '(:expensive-test)
+ (erc-scenarios-common-with-cleanup
+ ((erc-scenarios-common-dialog "commands")
+ (erc-server-flood-penalty 0.1)
+ (dumb-server (erc-d-run "localhost" t 'vhost))
+ ;; As of ERC 5.6, we must join a channel before ERC adds itself
+ ;; to `erc-server-users'. Without such an entry, there's
+ ;; nothing to update when the 396 arrives.
+ (erc-autojoin-channels-alist '((foonet "#chan")))
+ (port (process-contact dumb-server :service))
+ (expect (erc-d-t-make-expecter)))
+
+ (ert-info ("Connect to server")
+ (with-current-buffer (erc :server "127.0.0.1"
+ :port port
+ :nick "tester"
+ :password "changeme"
+ :full-name "tester")
+ (funcall expect 10 "debug mode")))
+
+ (ert-info ("Send VHOST")
+ (with-current-buffer (erc-d-t-wait-for 10 (get-buffer "#chan"))
+ (erc-scenarios-common-say "/VHOST tester changeme")
+ (funcall expect 10 "visible host")
+ (should (string= (erc-server-user-host (erc-get-server-user "tester"))
+ "some.host.test.cc"))))))
+
+;;; erc-scenarios-misc-commands.el ends here
diff --git a/test/lisp/erc/erc-scenarios-misc.el b/test/lisp/erc/erc-scenarios-misc.el
index bb925eed836..8f6042de5c2 100644
--- a/test/lisp/erc/erc-scenarios-misc.el
+++ b/test/lisp/erc/erc-scenarios-misc.el
@@ -1,6 +1,6 @@
;;; erc-scenarios-misc.el --- Misc scenarios for ERC -*- lexical-binding: t -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -75,7 +75,7 @@
(ert-info ("All output sent")
(with-current-buffer "#chan/foonet"
- (funcall expect 8 "Some man or other"))
+ (funcall expect 16 "Some man or other"))
(with-current-buffer "#chan/barnet"
(funcall expect 10 "That's he that was Othello")))))
diff --git a/test/lisp/erc/erc-scenarios-prompt-format.el b/test/lisp/erc/erc-scenarios-prompt-format.el
new file mode 100644
index 00000000000..613ad87ccf5
--- /dev/null
+++ b/test/lisp/erc/erc-scenarios-prompt-format.el
@@ -0,0 +1,117 @@
+;;; erc-scenarios-prompt-format.el --- erc-prompt-format-mode -*- lexical-binding: t -*-
+
+;; Copyright (C) 2023-2024 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert-x)
+(eval-and-compile
+ (let ((load-path (cons (ert-resource-directory) load-path)))
+ (require 'erc-scenarios-common)))
+
+(defvar erc-fill-wrap-align-prompt)
+(defvar erc-fill-wrap-use-pixels)
+
+(defun erc-scenarios-prompt-format--assert (needle &rest props)
+ (save-excursion
+ (goto-char erc-insert-marker)
+ (should (search-forward needle nil t))
+ (pcase-dolist (`(,k . ,v) props)
+ (should (equal (get-text-property (point) k) v)))))
+
+;; This makes assertions about the option `erc-fill-wrap-align-prompt'
+;; as well as the standard value of `erc-prompt-format'. One minor
+;; omission is that this doesn't check behavior in query buffers.
+(ert-deftest erc-scenarios-prompt-format ()
+ :tags '(:expensive-test)
+ (erc-scenarios-common-with-cleanup
+ ((erc-scenarios-common-dialog "base/modes")
+ (erc-server-flood-penalty 0.1)
+ (dumb-server (erc-d-run "localhost" t 'chan-changed))
+ (erc-modules (cons 'fill-wrap erc-modules))
+ (erc-fill-wrap-align-prompt t)
+ (erc-fill-wrap-use-pixels nil)
+ (erc-prompt #'erc-prompt-format)
+ (erc-autojoin-channels-alist '((Libera.Chat "#chan")))
+ (expect (erc-d-t-make-expecter))
+ ;; Collect samples of `line-prefix' to verify deltas as the
+ ;; prompt grows and shrinks.
+ (line-prefixes nil)
+ (stash-pfx (lambda ()
+ (pcase (get-text-property erc-insert-marker 'line-prefix)
+ (`(space :width (- erc-fill--wrap-value ,n))
+ (car (push n line-prefixes)))))))
+
+ (ert-info ("Connect to Libera.Chat")
+ (with-current-buffer (erc :server "127.0.0.1"
+ :port (process-contact dumb-server :service)
+ :nick "tester"
+ :full-name "tester")
+ (funcall expect 5 "Welcome to the Libera.Chat")
+ (funcall stash-pfx)
+ (funcall expect 5 "changed mode")
+ ;; New prompt is shorter than default with placeholders, like
+ ;; "(foo?)(bar?)" (assuming we win the inherent race).
+ (should (>= (car line-prefixes) (funcall stash-pfx)))
+ (erc-scenarios-prompt-format--assert "user-" '(display . ("Ziw")))))
+
+ (with-current-buffer (erc-d-t-wait-for 5 (get-buffer "#chan"))
+ (should-not erc-channel-key)
+ (should-not erc-channel-user-limit)
+
+ (ert-info ("Receive notice that mode has changed")
+ (erc-d-t-wait-for 10 (equal erc-channel-modes '("n" "t")))
+ (funcall stash-pfx)
+ (erc-scenarios-common-say "ready before")
+ (funcall expect 10 " has changed mode for #chan to +Qu")
+ (erc-d-t-wait-for 10 (equal erc-channel-modes '("Q" "n" "t" "u")))
+ ;; Prompt is longer now, so too is the `line-prefix' subtrahend.
+ (should (< (car line-prefixes) (funcall stash-pfx)))
+ (erc-scenarios-prompt-format--assert "Qntu")
+ (erc-scenarios-prompt-format--assert "#chan>"))
+
+ (ert-info ("Key stored locally")
+ (erc-scenarios-common-say "ready key")
+ (funcall expect 10 " has changed mode for #chan to +k hunter2")
+ ;; Prompt has grown by 1.
+ (should (< (car line-prefixes) (funcall stash-pfx)))
+ (erc-scenarios-prompt-format--assert "Qkntu"))
+
+ (ert-info ("Limit stored locally")
+ (erc-scenarios-common-say "ready limit")
+ (funcall expect 10 " has changed mode for #chan to +l 3")
+ (erc-d-t-wait-for 10 (eql erc-channel-user-limit 3))
+ (should (equal erc-channel-modes '("Q" "n" "t" "u")))
+ ;; Prompt has grown by 1 again.
+ (should (< (car line-prefixes) (funcall stash-pfx)))
+ (erc-scenarios-prompt-format--assert "Qklntu"))
+
+ (ert-info ("Modes removed and local state deletion succeeds")
+ (erc-scenarios-common-say "ready drop")
+ (funcall expect 10 " has changed mode for #chan to -lu")
+ (funcall expect 10 " has changed mode for #chan to -Qk *")
+ (erc-d-t-wait-for 10 (equal erc-channel-modes '("n" "t")))
+ ;; Prompt has shrunk.
+ (should (> (car line-prefixes) (funcall stash-pfx)))
+ (erc-scenarios-prompt-format--assert "nt"))
+
+ (should-not erc-channel-key)
+ (should-not erc-channel-user-limit)
+ (funcall expect 10 "<Chad> after"))))
+
+;;; erc-scenarios-prompt-format.el ends here
diff --git a/test/lisp/erc/erc-scenarios-sasl.el b/test/lisp/erc/erc-scenarios-sasl.el
index ab652d72dd2..e070c675446 100644
--- a/test/lisp/erc/erc-scenarios-sasl.el
+++ b/test/lisp/erc/erc-scenarios-sasl.el
@@ -1,6 +1,6 @@
;;; erc-scenarios-sasl.el --- SASL tests for ERC -*- lexical-binding: t -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -149,23 +149,26 @@
(erc-modules (cons 'sasl erc-modules))
(erc-sasl-password "wrong")
(erc-sasl-mechanism 'plain)
- (expect (erc-d-t-make-expecter))
- (buf nil))
+ (erc--warnings-buffer-name "*ERC test warnings*")
+ (warnings-buffer (get-buffer-create erc--warnings-buffer-name))
+ (inhibit-message noninteractive)
+ (expect (erc-d-t-make-expecter)))
- (ert-info ("Connect")
- (setq buf (erc :server "127.0.0.1"
- :port port
- :nick "tester"
- :user "tester"
- :full-name "tester"))
- (let ((err (should-error
- (with-current-buffer buf
- (funcall expect 20 "Connection failed!")))))
- (should (string-search "please review" (cadr err)))
- (with-current-buffer buf
- (funcall expect 10 "Opening connection")
- (funcall expect 20 "SASL authentication failed")
- (should-not (erc-server-process-alive)))))))
+ (with-current-buffer (erc :server "127.0.0.1"
+ :port port
+ :nick "tester"
+ :user "tester"
+ :full-name "tester")
+ (funcall expect 10 "Opening connection")
+ (funcall expect 20 "SASL authentication failed")
+ (funcall expect 20 "Connection failed!")
+ (should-not (erc-server-process-alive)))
+
+ (with-current-buffer warnings-buffer
+ (funcall expect 10 "please review SASL settings")))
+
+ (when noninteractive
+ (should-not (get-buffer "*ERC test warnings*"))))
(defun erc-scenarios--common--sasl (mech)
(erc-scenarios-common-with-cleanup
diff --git a/test/lisp/erc/erc-scenarios-scrolltobottom-relaxed.el b/test/lisp/erc/erc-scenarios-scrolltobottom-relaxed.el
new file mode 100644
index 00000000000..c7260500b7d
--- /dev/null
+++ b/test/lisp/erc/erc-scenarios-scrolltobottom-relaxed.el
@@ -0,0 +1,140 @@
+;;; erc-scenarios-scrolltobottom-relaxed.el --- erc-scrolltobottom-all relaxed -*- lexical-binding: t -*-
+
+;; Copyright (C) 2023-2024 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;; TODO assert behavior of prompt input spanning multiple lines, with
+;; and without line endings.
+
+;;; Code:
+
+(require 'ert-x)
+(eval-and-compile
+ (let ((load-path (cons (ert-resource-directory) load-path)))
+ (require 'erc-scenarios-common)))
+
+(require 'erc-goodies)
+
+(ert-deftest erc-scenarios-scrolltobottom--relaxed ()
+ :tags `(:expensive-test
+ ,@(and (getenv "ERC_TESTS_GRAPHICAL") '(:erc--graphical)))
+ (when (version< emacs-version "29") (ert-skip "Times out"))
+
+ (should-not erc-scrolltobottom-all)
+
+ (erc-scenarios-common-with-noninteractive-in-term
+ ((erc-scenarios-common-dialog "scrolltobottom")
+ (dumb-server (erc-d-run "localhost" t 'help))
+ (port (process-contact dumb-server :service))
+ (erc-modules `(scrolltobottom fill-wrap ,@erc-modules))
+ (erc-scrolltobottom-all 'relaxed)
+ (erc-server-flood-penalty 0.1)
+ (expect (erc-d-t-make-expecter))
+ lower upper)
+
+ (ert-info ("Connect")
+ (with-current-buffer (erc :server "127.0.0.1"
+ :port port
+ :full-name "tester"
+ :nick "tester")
+ (funcall expect 10 "debug mode")))
+
+ (with-current-buffer "foonet"
+ (should (looking-at " and"))
+ (set-window-buffer nil (current-buffer))
+ (delete-other-windows)
+ (split-window-below 15)
+ (recenter 0)
+
+ (ert-info ("Moving into prompt does not trigger scroll")
+ (with-selected-window (next-window)
+ (should-not (erc-scenarios-common--at-win-end-p))
+ (recenter 0)
+ (goto-char (1- erc-insert-marker))
+ (execute-kbd-macro "\C-n")
+ (should-not (erc-scenarios-common--at-win-end-p))
+ (should (= (point) (point-max)))
+ (setq lower (count-screen-lines (window-start) (window-point)))))
+
+ (ert-info ("Module `move-to-prompt' still works")
+ ;; Prompt is somewhere in the middle of the window.
+ (should (erc-scenarios-common--above-win-end-p))
+ (should-not (= (point-max) (point)))
+ ;; Hitting a self-insert key triggers `move-to-prompt' but not
+ ;; a scroll (to bottom).
+ (execute-kbd-macro "hi")
+ ;; Prompt and input appear on same line.
+ (should (= (point-max) (point)))
+ (setq upper (count-screen-lines (window-start) (window-point)))
+ (should-not (= upper (window-body-height))))
+
+ (ert-info ("Command `recenter-top-bottom' allowed at prompt")
+ ;; Hitting C-l recenters the window.
+ (should (= upper (count-screen-lines (window-start) (window-point))))
+ (let ((lines (list upper)))
+ (erc-scenarios-common--recenter-top-bottom)
+ (push (count-screen-lines (window-start) (window-point)) lines)
+ (erc-scenarios-common--recenter-top-bottom)
+ (push (count-screen-lines (window-start) (window-point)) lines)
+ (erc-scenarios-common--recenter-top-bottom)
+ (push (count-screen-lines (window-start) (window-point)) lines)
+ (setq lines (delete-dups lines))
+ (should (= (length lines) 4))))
+
+ (ert-info ("Command `beginning-of-buffer' allowed at prompt")
+ ;; Hitting C-< goes to beginning of buffer.
+ (execute-kbd-macro "\M-<")
+ (should (= 1 (point)))
+ (redisplay)
+ (should (zerop (count-screen-lines (window-start) (window-point))))
+ (should (erc-scenarios-common--prompt-past-win-end-p)))
+
+ (ert-info ("New message doesn't trigger scroll when away from prompt")
+ ;; Arriving insertions don't trigger a scroll when away from the
+ ;; prompt. New output not seen.
+ (erc-cmd-MSG "NickServ help register")
+ (save-excursion (erc-d-t-search-for 10 "End of NickServ"))
+ (should (= 1 (point)))
+ (should (zerop (count-screen-lines (window-start) (window-point))))
+ (should (erc-scenarios-common--prompt-past-win-end-p)))
+
+ (ert-info ("New insertion keeps prompt stationary in other window")
+ (let ((w (next-window)))
+ ;; We're at prompt and completely stationary.
+ (should (>= (window-point w) erc-input-marker))
+ (erc-d-t-wait-for 10
+ (= lower (count-screen-lines (window-start w) (window-point w))))
+ (erc-d-t-ensure-for 0.5
+ (= lower (count-screen-lines (window-start w)
+ (window-point w))))))
+
+ (should (= 2 (length (window-list))))
+ (ert-info ("New message does not trigger a scroll when at prompt")
+ ;; Recenter so prompt is above rather than at window's end.
+ (funcall expect 10 "End of NickServ HELP")
+ (recenter 0)
+ (set-window-point nil (point-max))
+ (setq upper (count-screen-lines (window-start) (window-point)))
+ ;; Prompt is somewhere in the middle of the window.
+ (erc-d-t-wait-for 10 (erc-scenarios-common--above-win-end-p))
+ (erc-scenarios-common-say "/msg NickServ help identify")
+ ;; New arriving messages don't move prompt.
+ (erc-d-t-ensure-for 1
+ (= upper (count-screen-lines (window-start) (window-point))))
+ (funcall expect 10 "IDENTIFY lets you login")))))
+
+;;; erc-scenarios-scrolltobottom-relaxed.el ends here
diff --git a/test/lisp/erc/erc-scenarios-scrolltobottom.el b/test/lisp/erc/erc-scenarios-scrolltobottom.el
new file mode 100644
index 00000000000..d35d3654cd5
--- /dev/null
+++ b/test/lisp/erc/erc-scenarios-scrolltobottom.el
@@ -0,0 +1,68 @@
+;;; erc-scenarios-scrolltobottom.el --- erc-scrolltobottom-mode -*- lexical-binding: t -*-
+
+;; Copyright (C) 2023-2024 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert-x)
+(eval-and-compile
+ (let ((load-path (cons (ert-resource-directory) load-path)))
+ (require 'erc-scenarios-common)))
+
+(require 'erc-goodies)
+
+;; These two actually seem to run fine on Emacs 28, but skip them for
+;; now to stay in sync with `erc-scenarios-scrolltobottom--relaxed'.
+
+(ert-deftest erc-scenarios-scrolltobottom--normal ()
+ :tags `(:expensive-test ,@(and (getenv "ERC_TESTS_GRAPHICAL")
+ '(:erc--graphical)))
+ (when (version< emacs-version "29") (ert-skip "Times out"))
+
+ (should-not erc-scrolltobottom-all)
+
+ (erc-scenarios-common-scrolltobottom--normal
+ (lambda ()
+ (ert-info ("New insertion doesn't anchor prompt in other window")
+ (let ((w (next-window)))
+ ;; We're at prompt but not aligned to bottom.
+ (should (>= (window-point w) erc-input-marker))
+ (erc-d-t-wait-for 10
+ (not (erc-scenarios-common--at-win-end-p w))))))))
+
+(ert-deftest erc-scenarios-scrolltobottom--all ()
+ :tags `(:expensive-test ,@(and (getenv "ERC_TESTS_GRAPHICAL")
+ '(:erc--graphical)))
+ (when (version< emacs-version "29") (ert-skip "Times out"))
+
+ (should-not erc-scrolltobottom-all)
+
+ (let ((erc-scrolltobottom-all t))
+
+ (erc-scenarios-common-scrolltobottom--normal
+ (lambda ()
+ (ert-info ("New insertion anchors prompt in other window")
+ (let ((w (next-window)))
+ ;; We're at prompt and aligned to bottom.
+ (should (>= (window-point w) erc-input-marker))
+ (erc-d-t-wait-for 10
+ (erc-scenarios-common--at-win-end-p w))
+ (erc-d-t-ensure-for 0.5
+ (erc-scenarios-common--at-win-end-p w))))))))
+
+;;; erc-scenarios-scrolltobottom.el ends here
diff --git a/test/lisp/erc/erc-scenarios-services-misc.el b/test/lisp/erc/erc-scenarios-services-misc.el
index 1113849578f..ab4a97c5724 100644
--- a/test/lisp/erc/erc-scenarios-services-misc.el
+++ b/test/lisp/erc/erc-scenarios-services-misc.el
@@ -1,6 +1,6 @@
;;; erc-scenarios-services-misc.el --- Services-misc scenarios -*- lexical-binding: t -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/erc/erc-scenarios-stamp.el b/test/lisp/erc/erc-scenarios-stamp.el
new file mode 100644
index 00000000000..3a10f709548
--- /dev/null
+++ b/test/lisp/erc/erc-scenarios-stamp.el
@@ -0,0 +1,181 @@
+;;; erc-scenarios-stamp.el --- Misc `erc-stamp' scenarios -*- lexical-binding: t -*-
+
+;; Copyright (C) 2023-2024 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert-x)
+(eval-and-compile
+ (let ((load-path (cons (ert-resource-directory) load-path)))
+ (require 'erc-scenarios-common)))
+
+(require 'erc-stamp)
+
+(defvar erc-scenarios-stamp--user-marker nil)
+
+(defun erc-scenarios-stamp--on-post-modify ()
+ (when-let (((erc--check-msg-prop 'erc--cmd 4)))
+ (set-marker erc-scenarios-stamp--user-marker (point-max))
+ (ert-info ("User marker correctly placed at `erc-insert-marker'")
+ (should (= ?\n (char-before erc-scenarios-stamp--user-marker)))
+ (should (= erc-scenarios-stamp--user-marker erc-insert-marker))
+ (save-excursion
+ (goto-char erc-scenarios-stamp--user-marker)
+ ;; The raw message ends in " Iabefhkloqv". However,
+ ;; `erc-server-004' only prints up to the 5th parameter.
+ (should (looking-back "CEIMRUabefhiklmnoqstuv\n"))))))
+
+(ert-deftest erc-scenarios-stamp--left/display-margin-mode ()
+
+ (erc-scenarios-common-with-cleanup
+ ((erc-scenarios-common-dialog "base/reconnect")
+ (dumb-server (erc-d-run "localhost" t 'unexpected-disconnect))
+ (port (process-contact dumb-server :service))
+ (erc-scenarios-stamp--user-marker (make-marker))
+ (erc-stamp--current-time 704591940)
+ (erc-stamp--tz t)
+ (erc-server-flood-penalty 0.1)
+ (erc-insert-timestamp-function #'erc-insert-timestamp-left)
+ (erc-modules (cons 'fill-wrap erc-modules))
+ (erc-timestamp-only-if-changed-flag nil)
+ (expect (erc-d-t-make-expecter)))
+
+ (ert-info ("Connect")
+ (with-current-buffer (erc :server "127.0.0.1"
+ :port port
+ :full-name "tester"
+ :nick "tester")
+
+ (add-hook 'erc-insert-post-hook #'erc-scenarios-stamp--on-post-modify
+ nil t)
+ (funcall expect 5 "This server is in debug mode")
+
+ (ert-info ("Stamps appear in left margin and are invisible")
+ (should (eq 'erc-timestamp (field-at-pos (pos-bol))))
+ (should (= (pos-bol) (field-beginning (pos-bol))))
+ (should (eq 'query-notice (get-text-property (pos-bol) 'erc--msg)))
+ (should (eq 'NOTICE (get-text-property (pos-bol) 'erc--cmd)))
+ (should (= ?- (char-after (field-end (pos-bol)))))
+ (should (equal (get-text-property (1+ (field-end (pos-bol)))
+ 'erc--speaker)
+ "irc.foonet.org"))
+ (should (pcase (get-text-property (pos-bol) 'display)
+ (`((margin left-margin) ,s)
+ (eq 'timestamp (get-text-property 0 'invisible s))))))
+
+ ;; We set a third-party marker at the end of 004's message (on
+ ;; then "\n"), post-insertion.
+ (ert-info ("User markers untouched by subsequent message left stamp")
+ (save-excursion
+ (goto-char erc-scenarios-stamp--user-marker)
+ (should (looking-back "CEIMRUabefhiklmnoqstuv\n"))
+ (should (looking-at (rx "[")))))))))
+
+(ert-deftest erc-scenarios-stamp--legacy-date-stamps ()
+ (with-suppressed-warnings ((obsolete erc-stamp-prepend-date-stamps-p))
+ (erc-scenarios-common-with-cleanup
+ ((erc-scenarios-common-dialog "base/reconnect")
+ (erc-stamp-prepend-date-stamps-p t)
+ (dumb-server (erc-d-run "localhost" t 'unexpected-disconnect))
+ (port (process-contact dumb-server :service))
+ (erc-server-flood-penalty 0.1)
+ (expect (erc-d-t-make-expecter)))
+
+ (ert-info ("Connect")
+ (with-current-buffer (erc :server "127.0.0.1"
+ :port port
+ :full-name "tester"
+ :nick "tester")
+ (funcall expect 5 "Opening connection")
+ (goto-char (1- (match-beginning 0)))
+ (should (eq 'erc-timestamp (field-at-pos (point))))
+ (should (eq 'unknown (erc--get-inserted-msg-prop 'erc--msg)))
+ ;; Force redraw of date stamp.
+ (setq erc-timestamp-last-inserted-left nil)
+
+ (funcall expect 5 "This server is in debug mode")
+ (while (and (zerop (forward-line -1))
+ (not (eq 'erc-timestamp (field-at-pos (point))))))
+ (should (erc--get-inserted-msg-prop 'erc--cmd)))))))
+
+;; This user-owned hook member places a marker on the first message in
+;; a buffer. Inserting a date stamp in front of it shouldn't move the
+;; marker.
+(defun erc-scenarios-stamp--on-insert-modify ()
+ (unless (marker-position erc-scenarios-stamp--user-marker)
+ (set-marker erc-scenarios-stamp--user-marker (point-min))
+ (save-excursion
+ (goto-char erc-scenarios-stamp--user-marker)
+ (should (looking-at "Opening"))))
+
+ ;; Sometime after the first message ("Opening connection.."), assert
+ ;; that the marker we just placed hasn't moved.
+ (when (erc--check-msg-prop 'erc--cmd 2)
+ (save-restriction
+ (widen)
+ (ert-info ("Date stamp preserves opening user marker")
+ (goto-char erc-scenarios-stamp--user-marker)
+ (should-not (eq 'erc-timestamp (field-at-pos (point))))
+ (should (looking-at "Opening"))
+ (should (eq 'unknown (get-text-property (point) 'erc--msg))))))
+
+ ;; On 003 ("*** This server was created on"), clear state to force a
+ ;; new date stamp on the next message.
+ (when (erc--check-msg-prop 'erc--cmd 3)
+ (setq erc-timestamp-last-inserted-left nil)
+ (set-marker erc-scenarios-stamp--user-marker erc-insert-marker)))
+
+(ert-deftest erc-scenarios-stamp--date-mode/left-and-right ()
+
+ (should (eq erc-insert-timestamp-function
+ #'erc-insert-timestamp-left-and-right))
+
+ (erc-scenarios-common-with-cleanup
+ ((erc-scenarios-common-dialog "base/reconnect")
+ (dumb-server (erc-d-run "localhost" t 'unexpected-disconnect))
+ (port (process-contact dumb-server :service))
+ (erc-scenarios-stamp--user-marker (make-marker))
+ (erc-server-flood-penalty 0.1)
+ (erc-modules (if (zerop (random 2))
+ (cons 'fill-wrap erc-modules)
+ erc-modules))
+ (expect (erc-d-t-make-expecter))
+ (erc-mode-hook
+ (cons (lambda ()
+ (add-hook 'erc-insert-modify-hook
+ #'erc-scenarios-stamp--on-insert-modify -99 t))
+ erc-mode-hook)))
+
+ (ert-info ("Connect")
+ (with-current-buffer (erc :server "127.0.0.1"
+ :port port
+ :full-name "tester"
+ :nick "tester")
+
+ (funcall expect 5 "Welcome to the foonet")
+ (funcall expect 5 "*** AWAYLEN=390")
+
+ (ert-info ("Date stamp preserves other user marker")
+ (goto-char erc-scenarios-stamp--user-marker)
+ (should-not (eq 'erc-timestamp (field-at-pos (point))))
+ (should (looking-at (rx "*** irc.foonet.org oragono")))
+ (should (eq 's004 (get-text-property (point) 'erc--msg))))
+
+ (funcall expect 5 "This server is in debug mode")))))
+
+;;; erc-scenarios-stamp.el ends here
diff --git a/test/lisp/erc/erc-scenarios-status-sidebar.el b/test/lisp/erc/erc-scenarios-status-sidebar.el
index 92229121c9f..2523ff9ee46 100644
--- a/test/lisp/erc/erc-scenarios-status-sidebar.el
+++ b/test/lisp/erc/erc-scenarios-status-sidebar.el
@@ -1,6 +1,6 @@
;;; erc-scenarios-status-sidebar.el --- erc-sidebar/speedbar tests -*- lexical-binding: t -*-
-;; Copyright (C) 2023 Free Software Foundation, Inc.
+;; Copyright (C) 2023-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -64,8 +64,7 @@
(let ((obuf (window-buffer))) ; *scratch*
(set-window-buffer (selected-window) "#foo")
(erc-d-t-wait-for 5
- (when noninteractive
- (erc-status-sidebar-refresh))
+ (erc-status-sidebar-refresh)
(with-current-buffer "*ERC Status*"
(and (marker-position erc-status-sidebar--active-marker)
(goto-char erc-status-sidebar--active-marker)
@@ -94,13 +93,14 @@
;; terminal, and we lack a fixture for that. Please try running this
;; test interactively with both graphical Emacs and non.
(declare-function erc-nickbar-mode "erc-speedbar" (arg))
-(declare-function erc-speedbar-close-nicknames-window "erc-speedbar" (kill))
+(declare-function erc-speedbar--get-timers "erc-speedbar" nil)
(declare-function speedbar-timer-fn "speedbar" nil)
(defvar erc-nickbar-mode)
(defvar speedbar-buffer)
(ert-deftest erc-scenarios-status-sidebar--nickbar ()
- :tags '(:unstable :expensive-test)
+ :tags `(:expensive-test :unstable ,@(and (getenv "ERC_TESTS_GRAPHICAL")
+ '(:erc--graphical)))
(when noninteractive (ert-skip "Interactive only"))
(erc-scenarios-common-with-cleanup
@@ -154,16 +154,21 @@
(ert-info ("Core toggle and kill commands work")
;; Avoid using API, e.g., `erc-status-sidebar-buffer-exists-p',
;; etc. for testing commands that call those same functions.
- (erc-nickbar-mode -1)
+ (call-interactively #'erc-nickbar-mode)
+ (should-not erc-nickbar-mode)
(should-not (and speedbar-buffer
(get-buffer-window speedbar-buffer)))
+ (should speedbar-buffer)
+
(erc-nickbar-mode +1)
(should (and speedbar-buffer
(get-buffer-window speedbar-buffer)))
(should (get-buffer " SPEEDBAR"))
- (erc-speedbar-close-nicknames-window 'kill)
+ (erc-nickbar-mode -1)
(should-not (get-buffer " SPEEDBAR"))
(should-not erc-nickbar-mode)
- (should-not (cdr (frame-list)))))))
+ (should-not (cdr (frame-list)))))
+
+ (should-not (erc-speedbar--get-timers))))
;;; erc-scenarios-status-sidebar.el ends here
diff --git a/test/lisp/erc/erc-services-tests.el b/test/lisp/erc/erc-services-tests.el
index 6cbba02a37e..9bafba98dc6 100644
--- a/test/lisp/erc/erc-services-tests.el
+++ b/test/lisp/erc/erc-services-tests.el
@@ -1,6 +1,6 @@
;;; erc-services-tests.el --- Tests for erc-services. -*- lexical-binding:t -*-
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
;;
diff --git a/test/lisp/erc/erc-stamp-tests.el b/test/lisp/erc/erc-stamp-tests.el
index c448416cd69..ef292ccb618 100644
--- a/test/lisp/erc/erc-stamp-tests.el
+++ b/test/lisp/erc/erc-stamp-tests.el
@@ -1,6 +1,6 @@
;;; erc-stamp-tests.el --- Tests for erc-stamp. -*- lexical-binding:t -*-
-;; Copyright (C) 2023 Free Software Foundation, Inc.
+;; Copyright (C) 2023-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
;;
@@ -21,6 +21,10 @@
;;; Code:
(require 'ert-x)
+(eval-and-compile
+ (let ((load-path (cons (ert-resource-directory) load-path)))
+ (require 'erc-tests-common)))
+
(require 'erc-stamp)
(require 'erc-goodies) ; for `erc-make-read-only'
@@ -44,9 +48,7 @@
(erc-mode)
(erc-munge-invisibility-spec)
(erc--initialize-markers (point) nil)
- (setq erc-server-process (start-process "p" (current-buffer)
- "sleep" "1"))
- (set-process-query-on-exit-flag erc-server-process nil)
+ (erc-tests-common-init-server-proc "sleep" "1")
(funcall test)
@@ -223,13 +225,13 @@
(erc-timestamp-intangible t) ; default changed to nil in 2014
(erc-hide-timestamps t)
(erc-insert-timestamp-function 'erc-insert-timestamp-left)
- (erc-server-process (start-process "true" (current-buffer) "true"))
(erc-insert-modify-hook '(erc-make-read-only erc-add-timestamp))
msg
erc-kill-channel-hook erc-kill-server-hook erc-kill-buffer-hook)
(should (not cursor-sensor-inhibit))
- (set-process-query-on-exit-flag erc-server-process nil)
+
(erc-mode)
+ (erc-tests-common-init-server-proc "true")
(with-current-buffer (get-buffer-create "*erc-timestamp-intangible*")
(erc-mode)
(erc--initialize-markers (point) nil)
@@ -274,4 +276,77 @@
(when noninteractive
(kill-buffer)))))
+(ert-deftest erc-echo-timestamp ()
+ :tags (and (null (getenv "CI")) '(:unstable))
+
+ (should-not erc-echo-timestamps)
+ (should-not erc-stamp--last-stamp)
+ (insert (propertize "a" 'erc--ts 433483200 'erc--msg 'msg) "bc")
+ (goto-char (point-min))
+ (let ((inhibit-message t)
+ (erc-echo-timestamp-format "%Y-%m-%d %H:%M:%S %Z")
+ (erc-echo-timestamp-zone (list (* 60 60 -4) "EDT")))
+
+ ;; No-op when non-interactive and option is nil
+ (should-not (erc--echo-ts-csf nil nil 'entered))
+ (should-not erc-stamp--last-stamp)
+
+ ;; Non-interactive (cursor sensor function)
+ (let ((erc-echo-timestamps t))
+ (should (equal (erc--echo-ts-csf nil nil 'entered)
+ "1983-09-27 00:00:00 EDT")))
+ (should (= 433483200 erc-stamp--last-stamp))
+
+ ;; Interactive
+ (should (equal (call-interactively #'erc-echo-timestamp)
+ "1983-09-27 00:00:00 EDT"))
+ ;; Interactive with zone
+ (let ((current-prefix-arg '(4)))
+ (should (member (call-interactively #'erc-echo-timestamp)
+ '("1983-09-27 04:00:00 GMT"
+ "1983-09-27 04:00:00 UTC"))))
+ (let ((current-prefix-arg -7))
+ (should (equal (call-interactively #'erc-echo-timestamp)
+ "1983-09-26 21:00:00 -07")))))
+
+(defun erc-stamp-tests--assert-get-inserted-msg/stamp (test-fn)
+ (let ((erc-insert-modify-hook erc-insert-modify-hook)
+ (erc-insert-timestamp-function 'erc-insert-timestamp-right)
+ (erc-timestamp-use-align-to 0)
+ (erc-timestamp-format "[00:00]"))
+ (cl-pushnew 'erc-add-timestamp erc-insert-modify-hook)
+ (erc-tests-common-get-inserted-msg-setup))
+ (goto-char 19)
+ (should (looking-back (rx "<bob> hi [00:00]")))
+ (erc-tests-common-assert-get-inserted-msg 3 19 test-fn))
+
+(ert-deftest erc--get-inserted-msg-beg/stamp ()
+ (erc-stamp-tests--assert-get-inserted-msg/stamp
+ (lambda (arg) (should (= 3 (erc--get-inserted-msg-beg arg))))))
+
+(ert-deftest erc--get-inserted-msg-beg/readonly/stamp ()
+ (erc-tests-common-assert-get-inserted-msg-readonly-with
+ #'erc-stamp-tests--assert-get-inserted-msg/stamp
+ (lambda (arg) (should (= 3 (erc--get-inserted-msg-beg arg))))))
+
+(ert-deftest erc--get-inserted-msg-end/stamp ()
+ (erc-stamp-tests--assert-get-inserted-msg/stamp
+ (lambda (arg) (should (= 19 (erc--get-inserted-msg-end arg))))))
+
+(ert-deftest erc--get-inserted-msg-end/readonly/stamp ()
+ (erc-tests-common-assert-get-inserted-msg-readonly-with
+ #'erc-stamp-tests--assert-get-inserted-msg/stamp
+ (lambda (arg) (should (= 19 (erc--get-inserted-msg-end arg))))))
+
+(ert-deftest erc--get-inserted-msg-bounds/stamp ()
+ (erc-stamp-tests--assert-get-inserted-msg/stamp
+ (lambda (arg)
+ (should (equal '(3 . 19) (erc--get-inserted-msg-bounds arg))))))
+
+(ert-deftest erc--get-inserted-msg-bounds/readonly/stamp ()
+ (erc-tests-common-assert-get-inserted-msg-readonly-with
+ #'erc-stamp-tests--assert-get-inserted-msg/stamp
+ (lambda (arg)
+ (should (equal '(3 . 19) (erc--get-inserted-msg-bounds arg))))))
+
;;; erc-stamp-tests.el ends here
diff --git a/test/lisp/erc/erc-tests.el b/test/lisp/erc/erc-tests.el
index 327ee46a736..2cd47ec3f89 100644
--- a/test/lisp/erc/erc-tests.el
+++ b/test/lisp/erc/erc-tests.el
@@ -1,6 +1,6 @@
;;; erc-tests.el --- Tests for erc. -*- lexical-binding:t -*-
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
;; Author: Lars Ingebrigtsen <larsi@gnus.org>
@@ -22,7 +22,10 @@
;;; Code:
(require 'ert-x)
-(require 'erc)
+(eval-and-compile
+ (let ((load-path (cons (ert-resource-directory) load-path)))
+ (require 'erc-tests-common)))
+
(require 'erc-ring)
(ert-deftest erc--read-time-period ()
@@ -69,26 +72,25 @@
(with-current-buffer (get-buffer-create "#foo")
(erc-mode)
(setq erc-server-process proc-exnet)
- (setq erc-default-recipients '("#foo")))
+ (setq erc--target (erc--target-from-string "#foo")))
(with-current-buffer (get-buffer-create "#spam")
(erc-mode)
(setq erc-server-process proc-onet)
- (setq erc-default-recipients '("#spam")))
+ (setq erc--target (erc--target-from-string "#spam")))
(with-current-buffer (get-buffer-create "#bar")
(erc-mode)
(setq erc-server-process proc-onet)
- (setq erc-default-recipients '("#bar")))
+ (setq erc--target (erc--target-from-string "#bar")))
(with-current-buffer (get-buffer-create "#baz")
(erc-mode)
(setq erc-server-process proc-exnet)
- (setq erc-default-recipients '("#baz")))
+ (setq erc--target (erc--target-from-string "#baz")))
(should (eq (get-buffer-process "ExampleNet") proc-exnet))
- (erc-with-all-buffers-of-server (get-buffer-process "ExampleNet")
- nil
+ (erc-with-all-buffers-of-server (get-buffer-process "ExampleNet") nil
(kill-buffer))
(should-not (get-buffer "ExampleNet"))
@@ -102,8 +104,7 @@
(calls 0)
(get-test (lambda () (cl-incf calls) test)))
- (erc-with-all-buffers-of-server proc-onet
- (funcall get-test)
+ (erc-with-all-buffers-of-server proc-onet (funcall get-test)
(kill-buffer))
(should (= calls 1)))
@@ -115,16 +116,22 @@
(ert-deftest erc-with-server-buffer ()
(setq erc-away 1)
- (erc-tests--set-fake-server-process "sleep" "1")
+ (erc-tests-common-init-server-proc "sleep" "1")
- (let (calls)
- (advice-add 'buffer-local-value :after (lambda (&rest r) (push r calls))
+ (let (mockingp calls)
+ (advice-add 'buffer-local-value :after
+ (lambda (&rest r) (when mockingp (push r calls)))
'((name . erc-with-server-buffer)))
- (should (= 1 (erc-with-server-buffer erc-away)))
+ (should (= 1 (prog2 (setq mockingp t)
+ (erc-with-server-buffer erc-away)
+ (setq mockingp nil))))
+
(should (equal (pop calls) (list 'erc-away (current-buffer))))
- (should (= 1 (erc-with-server-buffer (ignore 'me) erc-away)))
+ (should (= 1 (prog2 (setq mockingp t)
+ (erc-with-server-buffer (ignore 'me) erc-away)
+ (setq mockingp nil))))
(should-not calls)
(advice-remove 'buffer-local-value 'erc-with-server-buffer)))
@@ -132,38 +139,41 @@
(ert-deftest erc--with-dependent-type-match ()
(should (equal (macroexpand-1
'(erc--with-dependent-type-match (repeat face) erc-match))
- '(backquote
- (repeat :match ,(lambda (w v)
- (require 'erc-match)
- (widget-editable-list-match w v))
- face)))))
-
-(defun erc-tests--send-prep ()
- ;; Caller should probably shadow `erc-insert-modify-hook' or
- ;; populate user tables for erc-button.
- (erc-mode)
- (erc--initialize-markers (point) nil)
- (should (= (point) erc-input-marker)))
-
-(defun erc-tests--set-fake-server-process (&rest args)
- (setq erc-server-process
- (apply #'start-process (car args) (current-buffer) args))
- (set-process-query-on-exit-flag erc-server-process nil))
+ '(backquote-list*
+ 'repeat :match (lambda (w v)
+ (require 'erc-match)
+ (widget-editable-list-match w v))
+ '(face)))))
+
+(ert-deftest erc--doarray ()
+ (let ((array "abcdefg")
+ out)
+ ;; No return form.
+ (should-not (erc--doarray (c array) (push c out)))
+ (should (equal out '(?g ?f ?e ?d ?c ?b ?a)))
+
+ ;; Return form evaluated upon completion.
+ (setq out nil)
+ (should (= 42 (erc--doarray (c array (+ 39 (length out)))
+ (when (cl-evenp c) (push c out)))))
+ (should (equal out '(?f ?d ?b)))))
(ert-deftest erc-hide-prompt ()
- (let (erc-kill-channel-hook erc-kill-server-hook erc-kill-buffer-hook)
+ (let ((erc-hide-prompt erc-hide-prompt)
+ ;;
+ erc-kill-channel-hook erc-kill-server-hook erc-kill-buffer-hook)
(with-current-buffer (get-buffer-create "ServNet")
- (erc-tests--send-prep)
+ (erc-tests-common-prep-for-insertion)
(goto-char erc-insert-marker)
(should (looking-at-p (regexp-quote erc-prompt)))
- (erc-tests--set-fake-server-process "sleep" "1")
+ (erc-tests-common-init-server-proc "sleep" "1")
(set-process-sentinel erc-server-process #'ignore)
(setq erc-network 'ServNet)
(set-process-query-on-exit-flag erc-server-process nil))
(with-current-buffer (get-buffer-create "#chan")
- (erc-tests--send-prep)
+ (erc-tests-common-prep-for-insertion)
(goto-char erc-insert-marker)
(should (looking-at-p (regexp-quote erc-prompt)))
(setq erc-server-process (buffer-local-value 'erc-server-process
@@ -171,7 +181,7 @@
erc--target (erc--target-from-string "#chan")))
(with-current-buffer (get-buffer-create "bob")
- (erc-tests--send-prep)
+ (erc-tests-common-prep-for-insertion)
(goto-char erc-insert-marker)
(should (looking-at-p (regexp-quote erc-prompt)))
(setq erc-server-process (buffer-local-value 'erc-server-process
@@ -183,101 +193,101 @@
(with-current-buffer "ServNet"
(should (= (point) erc-insert-marker))
(erc--hide-prompt erc-server-process)
- (should (string= ">" (get-text-property (point) 'display))))
+ (should (string= ">" (get-char-property (point) 'display))))
(with-current-buffer "#chan"
(goto-char erc-insert-marker)
- (should (string= ">" (get-text-property (point) 'display)))
+ (should (string= ">" (get-char-property (point) 'display)))
(should (memq #'erc--unhide-prompt-on-self-insert pre-command-hook))
(goto-char erc-input-marker)
(ert-simulate-command '(self-insert-command 1 ?/))
(goto-char erc-insert-marker)
- (should-not (get-text-property (point) 'display))
+ (should-not (get-char-property (point) 'display))
(should-not (memq #'erc--unhide-prompt-on-self-insert
pre-command-hook)))
(with-current-buffer "bob"
(goto-char erc-insert-marker)
- (should (string= ">" (get-text-property (point) 'display)))
+ (should (string= ">" (get-char-property (point) 'display)))
(should (memq #'erc--unhide-prompt-on-self-insert pre-command-hook))
(goto-char erc-input-marker)
(ert-simulate-command '(self-insert-command 1 ?/))
(goto-char erc-insert-marker)
- (should-not (get-text-property (point) 'display))
+ (should-not (get-char-property (point) 'display))
(should-not (memq #'erc--unhide-prompt-on-self-insert
pre-command-hook)))
(with-current-buffer "ServNet"
- (should (get-text-property erc-insert-marker 'display))
+ (should (get-char-property erc-insert-marker 'display))
(should (memq #'erc--unhide-prompt-on-self-insert pre-command-hook))
(erc--unhide-prompt)
(should-not (memq #'erc--unhide-prompt-on-self-insert
pre-command-hook))
- (should-not (get-text-property erc-insert-marker 'display))))
+ (should-not (get-char-property erc-insert-marker 'display))))
(ert-info ("Value: server")
(setq erc-hide-prompt '(server))
(with-current-buffer "ServNet"
(erc--hide-prompt erc-server-process)
(should (eq (get-text-property erc-insert-marker 'erc-prompt) 'hidden))
- (should (string= ">" (get-text-property erc-insert-marker 'display))))
+ (should (string= ">" (get-char-property erc-insert-marker 'display))))
(with-current-buffer "#chan"
- (should-not (get-text-property erc-insert-marker 'display)))
+ (should-not (get-char-property erc-insert-marker 'display)))
(with-current-buffer "bob"
- (should-not (get-text-property erc-insert-marker 'display)))
+ (should-not (get-char-property erc-insert-marker 'display)))
(with-current-buffer "ServNet"
(erc--unhide-prompt)
(should (eq (get-text-property erc-insert-marker 'erc-prompt) t))
- (should-not (get-text-property erc-insert-marker 'display))))
+ (should-not (get-char-property erc-insert-marker 'display))))
(ert-info ("Value: channel")
(setq erc-hide-prompt '(channel))
(with-current-buffer "ServNet"
(erc--hide-prompt erc-server-process)
- (should-not (get-text-property erc-insert-marker 'display)))
+ (should-not (get-char-property erc-insert-marker 'display)))
(with-current-buffer "bob"
- (should-not (get-text-property erc-insert-marker 'display)))
+ (should-not (get-char-property erc-insert-marker 'display)))
(with-current-buffer "#chan"
- (should (string= ">" (get-text-property erc-insert-marker 'display)))
+ (should (string= ">" (get-char-property erc-insert-marker 'display)))
(should (eq (get-text-property erc-insert-marker 'erc-prompt) 'hidden))
(erc--unhide-prompt)
(should (eq (get-text-property erc-insert-marker 'erc-prompt) t))
- (should-not (get-text-property erc-insert-marker 'display))))
+ (should-not (get-char-property erc-insert-marker 'display))))
(ert-info ("Value: query")
(setq erc-hide-prompt '(query))
(with-current-buffer "ServNet"
(erc--hide-prompt erc-server-process)
- (should-not (get-text-property erc-insert-marker 'display)))
+ (should-not (get-char-property erc-insert-marker 'display)))
(with-current-buffer "bob"
- (should (string= ">" (get-text-property erc-insert-marker 'display)))
+ (should (string= ">" (get-char-property erc-insert-marker 'display)))
(should (eq (get-text-property erc-insert-marker 'erc-prompt) 'hidden))
(erc--unhide-prompt)
(should (eq (get-text-property erc-insert-marker 'erc-prompt) t))
- (should-not (get-text-property erc-insert-marker 'display)))
+ (should-not (get-char-property erc-insert-marker 'display)))
(with-current-buffer "#chan"
- (should-not (get-text-property erc-insert-marker 'display))))
+ (should-not (get-char-property erc-insert-marker 'display))))
(ert-info ("Value: nil")
(setq erc-hide-prompt nil)
(with-current-buffer "ServNet"
(erc--hide-prompt erc-server-process)
- (should-not (get-text-property erc-insert-marker 'display)))
+ (should-not (get-char-property erc-insert-marker 'display)))
(with-current-buffer "bob"
- (should-not (get-text-property erc-insert-marker 'display)))
+ (should-not (get-char-property erc-insert-marker 'display)))
(with-current-buffer "#chan"
- (should-not (get-text-property erc-insert-marker 'display))
+ (should-not (get-char-property erc-insert-marker 'display))
(erc--unhide-prompt) ; won't blow up when prompt already showing
- (should-not (get-text-property erc-insert-marker 'display))))
+ (should-not (get-char-property erc-insert-marker 'display))))
(when noninteractive
(kill-buffer "#chan")
@@ -292,15 +302,17 @@
(cl-incf counter))))
erc-accidental-paste-threshold-seconds
erc-insert-modify-hook
- erc--input-review-functions
+ (erc-modules (remq 'stamp erc-modules))
+ (erc-send-input-line-function #'ignore)
+ (erc--input-review-functions erc--input-review-functions)
erc-send-completed-hook)
(ert-info ("Server buffer")
(with-current-buffer (get-buffer-create "ServNet")
- (erc-tests--send-prep)
+ (erc-tests-common-prep-for-insertion)
(goto-char erc-insert-marker)
(should (looking-at-p "ServNet 3>"))
- (erc-tests--set-fake-server-process "sleep" "1")
+ (erc-tests-common-init-server-proc "sleep" "1")
(set-process-sentinel erc-server-process #'ignore)
(setq erc-network 'ServNet
erc-server-current-nick "tester"
@@ -317,7 +329,7 @@
(insert "Howdy")
(erc-send-current-line)
(save-excursion (forward-line -1)
- (should (looking-at "No target"))
+ (should (looking-at (rx "*** No target")))
(forward-line -1)
(should (looking-at "<tester> Howdy")))
(should (looking-back "ServNet 6> "))
@@ -332,7 +344,7 @@
(ert-info ("Channel buffer")
(with-current-buffer (get-buffer-create "#chan")
- (erc-tests--send-prep)
+ (erc-tests-common-prep-for-insertion)
(goto-char erc-insert-marker)
(should (looking-at-p "#chan 9>"))
(goto-char erc-input-marker)
@@ -356,7 +368,11 @@
(should (looking-back "#chan@ServNet 11> "))
(should (= (point) erc-input-marker))
(insert "/query bob")
- (erc-send-current-line)
+ (let (erc-modules)
+ (erc-send-current-line))
+ ;; Last command not inserted
+ (save-excursion (forward-line -1)
+ (should (looking-at "<tester> Howdy")))
;; Query does not redraw (nor /help, only message input)
(should (looking-back "#chan@ServNet 11> "))
;; No sign of old prompts
@@ -521,7 +537,7 @@
(ert-deftest erc-setup-buffer--custom-action ()
(erc-mode)
- (erc-tests--set-fake-server-process "sleep" "1")
+ (erc-tests-common-init-server-proc "sleep" "1")
(setq erc--server-last-reconnect-count 0)
(let ((owin (selected-window))
(obuf (window-buffer))
@@ -560,6 +576,36 @@
(pop calls)))
(should-not calls)))
+ ;; Mimic simplistic version of example in "(erc) display-buffer".
+ (when (>= emacs-major-version 29)
+ (let ((proc erc-server-process))
+ (with-temp-buffer
+ (should-not (eq (window-buffer) (current-buffer)))
+ (erc-mode)
+ (setq erc-server-process proc)
+
+ (cl-letf (((symbol-function 'erc--test-fun-p)
+ (lambda (buf action)
+ (should (eql 1 (alist-get 'erc-buffer-display action)))
+ (push (cons 'erc--test-fun-p buf) calls)))
+ ((symbol-function 'action-fn)
+ (lambda (buf action)
+ (should (eql 1 (alist-get 'erc-buffer-display action)))
+ (should (eql 42 (alist-get 'foo action)))
+ (push (cons 'action-fn buf) calls)
+ (selected-window))))
+
+ (let ((erc--display-context '((erc-buffer-display . 1)))
+ (display-buffer-alist
+ `(((and (major-mode . erc-mode) erc--test-fun-p)
+ action-fn (foo . 42))))
+ (erc-buffer-display 'display-buffer))
+
+ (erc-setup-buffer (current-buffer))
+ (should (equal 'action-fn (car (pop calls))))
+ (should (equal 'erc--test-fun-p (car (pop calls))))
+ (should-not calls))))))
+
(should (eq owin (selected-window)))
(should (eq obuf (window-buffer)))))
@@ -576,6 +622,339 @@
(setq erc-lurker-ignore-chars "_-`") ; set of chars, not character alts
(should (string= "nick" (erc-lurker-maybe-trim "nick-_`")))))
+(ert-deftest erc-parse-user ()
+ (should (equal '("" "" "") (erc-parse-user "!@")))
+ (should (equal '("" "!" "") (erc-parse-user "!!@")))
+ (should (equal '("" "" "@") (erc-parse-user "!@@")))
+ (should (equal '("" "!" "@") (erc-parse-user "!!@@")))
+
+ (should (equal '("abc" "" "") (erc-parse-user "abc")))
+ (should (equal '("" "123" "fake") (erc-parse-user "!123@fake")))
+ (should (equal '("abc" "" "123") (erc-parse-user "abc!123")))
+
+ (should (equal '("abc" "123" "fake") (erc-parse-user "abc!123@fake")))
+ (should (equal '("abc" "!123" "@xy") (erc-parse-user "abc!!123@@xy")))
+
+ (should (equal '("de" "fg" "xy") (erc-parse-user "abc\nde!fg@xy"))))
+
+(ert-deftest erc--parse-nuh ()
+ (should (equal '(nil nil nil) (erc--parse-nuh "!@")))
+ (should (equal '(nil nil nil) (erc--parse-nuh "@")))
+ (should (equal '(nil nil nil) (erc--parse-nuh "!")))
+ (should (equal '(nil "!" nil) (erc--parse-nuh "!!@")))
+ (should (equal '(nil "@" nil) (erc--parse-nuh "!@@")))
+ (should (equal '(nil "!@" nil) (erc--parse-nuh "!!@@")))
+
+ (should (equal '("abc" nil nil) (erc--parse-nuh "abc!")))
+ (should (equal '(nil "abc" nil) (erc--parse-nuh "abc@")))
+ (should (equal '(nil "abc" nil) (erc--parse-nuh "!abc@")))
+
+ (should (equal '("abc" "123" "fake") (erc--parse-nuh "abc!123@fake")))
+ (should (equal '("abc" "!123@" "xy") (erc--parse-nuh "abc!!123@@xy")))
+
+ ;; Missing leading components.
+ (should (equal '(nil "abc" "123") (erc--parse-nuh "abc@123")))
+ (should (equal '(nil "123" "fake") (erc--parse-nuh "!123@fake")))
+ (should (equal '(nil nil "gnu.org") (erc--parse-nuh "@gnu.org")))
+
+ ;; Host "wins" over nick and user (sans "@").
+ (should (equal '(nil nil "abc") (erc--parse-nuh "abc")))
+ (should (equal '(nil nil "gnu.org") (erc--parse-nuh "gnu.org")))
+ (should (equal '(nil nil "gnu.org") (erc--parse-nuh "!gnu.org")))
+ (should (equal '("abc" nil "123") (erc--parse-nuh "abc!123")))
+
+ ;; No fallback behavior.
+ (should-not (erc--parse-nuh "abc\nde!fg@xy")))
+
+(ert-deftest erc--parsed-prefix ()
+ (erc-tests-common-make-server-buf (buffer-name))
+
+ ;; Uses fallback values when no PREFIX parameter yet received, thus
+ ;; ensuring caller can use slot accessors immediately instead of
+ ;; checking if null beforehand.
+ (should-not erc--parsed-prefix)
+ (should (equal (erc--parsed-prefix)
+ #s(erc--parsed-prefix nil "qaohv" "~&@%+"
+ ((?q . ?~) (?a . ?&)
+ (?o . ?@) (?h . ?%) (?v . ?+)))))
+ (let ((cached (should erc--parsed-prefix)))
+ (should (eq (erc--parsed-prefix) cached)))
+
+ ;; Cache broken. (Notice not setting `erc--parsed-prefix' to nil).
+ (setq erc-server-parameters '(("PREFIX" . "(ov)@+")))
+
+ (let ((proc erc-server-process)
+ (expected '((?o . ?@) (?v . ?+)))
+ cached)
+
+ (with-temp-buffer
+ (erc-mode)
+ (setq erc-server-process proc)
+ (should (equal expected
+ (erc--parsed-prefix-alist (erc--parsed-prefix)))))
+
+ (should (equal expected (erc--parsed-prefix-alist erc--parsed-prefix)))
+ (setq cached erc--parsed-prefix)
+ (should (equal cached
+ #s(erc--parsed-prefix ("(ov)@+") "ov" "@+"
+ ((?o . ?@) (?v . ?+)))))
+ ;; Second target buffer reuses cached value.
+ (with-temp-buffer
+ (erc-mode)
+ (setq erc-server-process proc)
+ (should (eq cached (erc--parsed-prefix))))
+
+ ;; New value computed when cache broken.
+ (puthash 'PREFIX (list "(qh)~%") erc--isupport-params)
+ (with-temp-buffer
+ (erc-mode)
+ (setq erc-server-process proc)
+ (should-not (eq cached (erc--parsed-prefix)))
+ (should (equal (erc--parsed-prefix-alist
+ (erc-with-server-buffer erc--parsed-prefix))
+ '((?q . ?~) (?h . ?%)))))))
+
+;; This exists as a reference to assert legacy behavior in order to
+;; preserve and incorporate it as a fallback in the 5.6+ replacement.
+(ert-deftest erc-parse-modes ()
+ (with-suppressed-warnings ((obsolete erc-parse-modes))
+ (should (equal (erc-parse-modes "+u") '(("u") nil nil)))
+ (should (equal (erc-parse-modes "-u") '(nil ("u") nil)))
+ (should (equal (erc-parse-modes "+o bob") '(nil nil (("o" on "bob")))))
+ (should (equal (erc-parse-modes "-o bob") '(nil nil (("o" off "bob")))))
+ (should (equal (erc-parse-modes "+uo bob") '(("u") nil (("o" on "bob")))))
+ (should (equal (erc-parse-modes "+o-u bob") '(nil ("u") (("o" on "bob")))))
+ (should (equal (erc-parse-modes "+uo-tv bob alice")
+ '(("u") ("t") (("o" on "bob") ("v" off "alice")))))
+
+ (ert-info ("Modes of type B are always grouped as unary")
+ (should (equal (erc-parse-modes "+k h2") '(nil nil (("k" on "h2")))))
+ ;; Channel key args are thrown away.
+ (should (equal (erc-parse-modes "-k *") '(nil nil (("k" off nil))))))
+
+ (ert-info ("Modes of type C are grouped as unary even when disabling")
+ (should (equal (erc-parse-modes "+l 3") '(nil nil (("l" on "3")))))
+ (should (equal (erc-parse-modes "-l") '(nil nil (("l" off nil))))))))
+
+(ert-deftest erc--update-channel-modes ()
+ (erc-mode)
+ (setq erc-channel-users (make-hash-table :test #'equal)
+ erc-server-users (make-hash-table :test #'equal)
+ erc--isupport-params (make-hash-table)
+ erc--target (erc--target-from-string "#test"))
+ (erc-tests-common-init-server-proc "sleep" "1")
+
+ (let ((orig-handle-fn (symbol-function 'erc--handle-channel-mode))
+ calls)
+ (cl-letf (((symbol-function 'erc--handle-channel-mode)
+ (lambda (&rest r) (push r calls) (apply orig-handle-fn r)))
+ ((symbol-function 'erc-update-mode-line) #'ignore))
+
+ (ert-info ("Unknown user not created")
+ (erc--update-channel-modes "+o" "bob")
+ (should-not (erc-get-channel-user "bob")))
+
+ (ert-info ("Status updated when user known")
+ (puthash "bob" (cons (erc-add-server-user
+ "bob" (make-erc-server-user
+ :nickname "bob"
+ :buffers (list (current-buffer))))
+ (make-erc-channel-user))
+ erc-channel-users)
+ ;; Also asserts fallback behavior for traditional prefixes.
+ (should-not (erc-channel-user-op-p "bob"))
+ (erc--update-channel-modes "+o" "bob")
+ (should (erc-channel-user-op-p "bob"))
+ (erc--update-channel-modes "-o" "bob") ; status revoked
+ (should-not (erc-channel-user-op-p "bob")))
+
+ (ert-info ("Unknown nullary added and removed")
+ (should-not erc--channel-modes)
+ (should-not erc-channel-modes)
+ (erc--update-channel-modes "+u")
+ (should (equal erc-channel-modes '("u")))
+ (should (eq t (gethash ?u erc--channel-modes)))
+ (should (equal (pop calls) '(?d ?u t nil)))
+ (erc--update-channel-modes "-u")
+ (should (equal (pop calls) '(?d ?u nil nil)))
+ (should-not (gethash ?u erc--channel-modes))
+ (should-not erc-channel-modes)
+ (should-not calls))
+
+ (ert-info ("Fallback for Type B includes mode letter k")
+ (erc--update-channel-modes "+k" "h2")
+ (should (equal (pop calls) '(?b ?k t "h2")))
+ (should-not erc-channel-modes)
+ (should (equal "h2" (gethash ?k erc--channel-modes)))
+ (erc--update-channel-modes "-k" "*")
+ (should (equal (pop calls) '(?b ?k nil "*")))
+ (should-not calls)
+ (should-not (gethash ?k erc--channel-modes))
+ (should-not erc-channel-modes))
+
+ (ert-info ("Fallback for Type C includes mode letter l")
+ (erc--update-channel-modes "+l" "3")
+ (should (equal (pop calls) '(?c ?l t "3")))
+ (should-not erc-channel-modes)
+ (should (equal "3" (gethash ?l erc--channel-modes)))
+ (erc--update-channel-modes "-l" nil)
+ (should (equal (pop calls) '(?c ?l nil nil)))
+ (should-not (gethash ?l erc--channel-modes))
+ (should-not erc-channel-modes))
+
+ (ert-info ("Advertised supersedes heuristics")
+ (setq erc-server-parameters
+ '(("PREFIX" . "(ov)@+")
+ ;; Add phony 5th type for this CHANMODES value for
+ ;; robustness in case some server gets creative.
+ ("CHANMODES" . "eIbq,k,flj,CFLMPQRSTcgimnprstuz,FAKE")))
+ (erc--update-channel-modes "+qu" "fool!*@*")
+ (should (equal (pop calls) '(?d ?u t nil)))
+ (should (equal (pop calls) '(?a ?q t "fool!*@*")))
+ (should (equal 1 (gethash ?q erc--channel-modes)))
+ (should (eq t (gethash ?u erc--channel-modes)))
+ (should (equal erc-channel-modes '("u")))
+ (should-not (erc-channel-user-owner-p "bob"))
+
+ ;; Remove fool!*@* from list mode "q".
+ (erc--update-channel-modes "-uq" "fool!*@*")
+ (should (equal (pop calls) '(?a ?q nil "fool!*@*")))
+ (should (equal (pop calls) '(?d ?u nil nil)))
+ (should-not (gethash ?u erc--channel-modes))
+ (should-not erc-channel-modes)
+ (should (equal 0 (gethash ?q erc--channel-modes))))
+
+ (should-not calls))))
+
+(ert-deftest erc--channel-modes ()
+ :tags (and (null (getenv "CI")) '(:unstable))
+
+ (setq erc--isupport-params (make-hash-table)
+ erc--target (erc--target-from-string "#test")
+ erc-server-parameters
+ '(("CHANMODES" . "eIbq,k,flj,CFLMPQRSTcgimnprstuz")))
+
+ (erc-tests-common-init-server-proc "sleep" "1")
+
+ (cl-letf (((symbol-function 'erc-update-mode-line) #'ignore))
+ (erc--update-channel-modes "+bltk" "fool!*@*" "3" "h2"))
+
+ (should (equal (erc--channel-modes 'string) "klt"))
+ (should (equal (erc--channel-modes 'strings) '("k" "l" "t")))
+ (should (equal (erc--channel-modes) '((?k . "h2") (?l . "3") (?t))))
+ (should (equal (erc--channel-modes 3 ",") "klt h2,3"))
+
+ ;; The function this tests behaves differently in different
+ ;; environments. For example, on one GNU Linux system, it returns
+ ;; truncation ellipsis when run interactively. Rather than have
+ ;; hard-to-read "nondeterministic" comparisons against sets of
+ ;; acceptable values, we use separate tests.
+ (when (display-graphic-p) (ert-pass))
+
+ ;; Truncation cache populated and used.
+ (let ((cache (erc--channel-mode-types-shortargs erc--channel-mode-types))
+ first-run)
+ (should (zerop (hash-table-count cache)))
+ (should (equal (erc--channel-modes 1 ",") "klt h,3"))
+ (should (equal (setq first-run (map-pairs cache)) '(((1 ?k "h2") . "h"))))
+
+ ;; Second call uses cache.
+ (cl-letf (((symbol-function 'truncate-string-to-width)
+ (lambda (&rest _) (ert-fail "Shouldn't run"))))
+ (should (equal (erc--channel-modes 1 ",") "klt h,3")))
+
+ ;; Same key for only entry matches that of first result.
+ (should (pcase (map-pairs cache)
+ ((and '(((1 ?k "h2") . "h")) second-run)
+ (eq (pcase first-run (`((,k . ,_)) k))
+ (pcase second-run (`((,k . ,_)) k)))))))
+
+ (should (equal (erc--channel-modes 0 ",") "klt ,"))
+ (should (equal (erc--channel-modes 2) "klt h2 3"))
+ (should (equal (erc--channel-modes 1) "klt h 3"))
+ (should (equal (erc--channel-modes 0) "klt "))) ; 2 spaces
+
+(ert-deftest erc--channel-modes/graphic-p ()
+ :tags `(:unstable ,@(and (getenv "ERC_TESTS_GRAPHICAL")
+ '(:erc--graphical)))
+ (unless (display-graphic-p) (ert-skip "See non-/graphic-p variant"))
+
+ (erc-tests-common-init-server-proc "sleep" "1")
+ (setq erc--isupport-params (make-hash-table)
+ erc--target (erc--target-from-string "#test")
+ erc-server-parameters
+ '(("CHANMODES" . "eIbq,k,flj,CFLMPQRSTcgimnprstuz")))
+
+ (cl-letf (((symbol-function 'erc-update-mode-line) #'ignore))
+ (erc--update-channel-modes "+bltk" "fool!*@*" "3" "hun2"))
+
+ ;; Truncation cache populated and used.
+ (let ((cache (erc--channel-mode-types-shortargs erc--channel-mode-types))
+ first-run)
+ (should (zerop (hash-table-count cache)))
+ (should (equal (erc--channel-modes 2 ",") "klt h…,3" ))
+ (should (equal (setq first-run (map-pairs cache))
+ '(((2 ?k "hun2") . "h…"))))
+
+ ;; Second call uses cache.
+ (cl-letf (((symbol-function 'truncate-string-to-width)
+ (lambda (&rest _) (ert-fail "Shouldn't run"))))
+ (should (equal (erc--channel-modes 2 ",") "klt h…,3" )))
+
+ ;; Same key for only entry matches that of first result.
+ (should (pcase (map-pairs cache)
+ ((and `(((2 ?k "hun2") . "h…")) second-run)
+ (eq (pcase first-run (`((,k . ,_)) k))
+ (pcase second-run (`((,k . ,_)) k)))))))
+
+ ;; A max length of 0 is nonsensical anyway, so skip those.
+ (should (equal (erc--channel-modes 3) "klt hu… 3"))
+ (should (equal (erc--channel-modes 2) "klt h… 3"))
+ (should (equal (erc--channel-modes 1) "klt … 3")))
+
+(ert-deftest erc--update-user-modes ()
+ (let ((erc--user-modes (list ?a)))
+ (should (equal (erc--update-user-modes "+a") '(?a)))
+ (should (equal (erc--update-user-modes "-b") '(?a)))
+ (should (equal erc--user-modes '(?a))))
+
+ (let ((erc--user-modes (list ?b)))
+ (should (equal (erc--update-user-modes "+ac") '(?a ?b ?c)))
+ (should (equal (erc--update-user-modes "+a-bc") '(?a)))
+ (should (equal erc--user-modes '(?a)))))
+
+(ert-deftest erc--user-modes ()
+ (let ((erc--user-modes '(?a ?b)))
+ (should (equal (erc--user-modes) '(?a ?b)))
+ (should (equal (erc--user-modes 'string) "ab"))
+ (should (equal (erc--user-modes 'strings) '("a" "b")))))
+
+(ert-deftest erc--parse-user-modes ()
+ (should (equal (erc--parse-user-modes "a" '(?a)) '(() ())))
+ (should (equal (erc--parse-user-modes "+a" '(?a)) '(() ())))
+ (should (equal (erc--parse-user-modes "a" '()) '((?a) ())))
+ (should (equal (erc--parse-user-modes "+a" '()) '((?a) ())))
+ (should (equal (erc--parse-user-modes "-a" '()) '(() ())))
+ (should (equal (erc--parse-user-modes "-a" '(?a)) '(() (?a))))
+
+ (should (equal (erc--parse-user-modes "+a-b" '(?a)) '(() ())))
+ (should (equal (erc--parse-user-modes "+a-b" '(?b)) '((?a) (?b))))
+ (should (equal (erc--parse-user-modes "+ab-c" '(?b)) '((?a) ())))
+ (should (equal (erc--parse-user-modes "+ab-c" '(?b ?c)) '((?a) (?c))))
+ (should (equal (erc--parse-user-modes "+a-c+b" '(?b ?c)) '((?a) (?c))))
+ (should (equal (erc--parse-user-modes "-c+ab" '(?b ?c)) '((?a) (?c))))
+
+ ;; Param `extrap' returns groups of redundant chars.
+ (should (equal (erc--parse-user-modes "+a" '() t) '((?a) () () ())))
+ (should (equal (erc--parse-user-modes "+a" '(?a) t) '(() () (?a) ())))
+ (should (equal (erc--parse-user-modes "-a" '() t) '(() () () (?a))))
+ (should (equal (erc--parse-user-modes "-a" '(?a) t) '(() (?a) () ())))
+
+ (should (equal (erc--parse-user-modes "+a-b" '(?a) t) '(() () (?a) (?b))))
+ (should (equal (erc--parse-user-modes "-b+a" '(?a) t) '(() () (?a) (?b))))
+ (should (equal (erc--parse-user-modes "+a-b" '(?b) t) '((?a) (?b) () ())))
+ (should (equal (erc--parse-user-modes "-b+a" '(?b) t) '((?a) (?b) () ()))))
+
(ert-deftest erc--parse-isupport-value ()
(should (equal (erc--parse-isupport-value "a,b") '("a" "b")))
(should (equal (erc--parse-isupport-value "a,b,c") '("a" "b" "c")))
@@ -730,23 +1109,20 @@
(should (erc--valid-local-channel-p "&local")))))
(ert-deftest erc--restore-initialize-priors ()
- ;; This `pcase' expands to 100+k. Guess we could do something like
- ;; (and `(,_ ((,e . ,_) . ,_) . ,_) v) first and then return a
- ;; (equal `(if-let* ((,e ...)...)...) v) to cut it down to < 1k.
(should (pcase (macroexpand-1 '(erc--restore-initialize-priors erc-my-mode
foo (ignore 1 2 3)
- bar #'spam))
- (`(if-let* ((,e (or erc--server-reconnecting erc--target-priors))
- ((alist-get 'erc-my-mode ,e)))
- (setq foo (alist-get 'foo ,e)
- bar (alist-get 'bar ,e))
- (setq foo (ignore 1 2 3)
- bar #'spam))
+ bar #'spam
+ baz nil))
+ (`(let* ((,p (or erc--server-reconnecting erc--target-priors))
+ (,q (and ,p (alist-get 'erc-my-mode ,p))))
+ (setq foo (if ,q (alist-get 'foo ,p) (ignore 1 2 3))
+ bar (if ,q (alist-get 'bar ,p) #'spam)
+ baz (if ,q (alist-get 'baz ,p) nil)))
t))))
(ert-deftest erc--target-from-string ()
(should (equal (erc--target-from-string "#chan")
- #s(erc--target-channel "#chan" \#chan)))
+ #s(erc--target-channel "#chan" \#chan nil)))
(should (equal (erc--target-from-string "Bob")
#s(erc--target "Bob" bob)))
@@ -754,7 +1130,7 @@
(let ((erc--isupport-params (make-hash-table)))
(puthash 'CHANTYPES '("&#") erc--isupport-params)
(should (equal (erc--target-from-string "&Bitlbee")
- #s(erc--target-channel-local "&Bitlbee" &bitlbee)))))
+ #s(erc--target-channel-local "&Bitlbee" &bitlbee nil)))))
(ert-deftest erc--modify-local-map ()
(when (and (bound-and-true-p erc-irccontrols-mode)
@@ -813,12 +1189,13 @@
(ert-deftest erc-ring-previous-command ()
(with-current-buffer (get-buffer-create "*#fake*")
(erc-mode)
- (erc-tests--send-prep)
+ (erc-tests-common-prep-for-insertion)
+ (setq erc-server-current-nick "tester")
(setq-local erc-last-input-time 0)
(should-not (local-variable-if-set-p 'erc-send-completed-hook))
(set (make-local-variable 'erc-send-completed-hook) nil) ; skip t (globals)
;; Just in case erc-ring-mode is already on
- (setq-local erc--input-review-functions nil)
+ (setq-local erc--input-review-functions erc--input-review-functions)
(add-hook 'erc--input-review-functions #'erc-add-to-input-ring)
;;
(cl-letf (((symbol-function 'erc-process-input-line)
@@ -993,66 +1370,8 @@
(should (equal '("" "" "") (split-string "\n\n" p)))
(should (equal '("" "" "") (split-string "\n\r" p)))))
-(ert-deftest erc--blank-in-multiline-input-p ()
- (let ((check (lambda (s)
- (erc--blank-in-multiline-input-p
- (split-string s erc--input-line-delim-regexp)))))
-
- (ert-info ("With `erc-send-whitespace-lines'")
- (let ((erc-send-whitespace-lines t))
- (should (funcall check ""))
- (should-not (funcall check "\na"))
- (should-not (funcall check "/msg a\n")) ; real /cmd
- (should-not (funcall check "a\n\nb")) ; "" allowed
- (should-not (funcall check "/msg a\n\nb")) ; non-/cmd
- (should-not (funcall check " "))
- (should-not (funcall check "\t"))
- (should-not (funcall check "a\nb"))
- (should-not (funcall check "a\n "))
- (should-not (funcall check "a\n \t"))
- (should-not (funcall check "a\n \f"))
- (should-not (funcall check "a\n \nb"))
- (should-not (funcall check "a\n \t\nb"))
- (should-not (funcall check "a\n \f\nb"))))
-
- (should (funcall check ""))
- (should (funcall check " "))
- (should (funcall check "\t"))
- (should (funcall check "a\n\nb"))
- (should (funcall check "a\n\nb"))
- (should (funcall check "a\n "))
- (should (funcall check "a\n \t"))
- (should (funcall check "a\n \f"))
- (should (funcall check "a\n \nb"))
- (should (funcall check "a\n \t\nb"))
-
- (should-not (funcall check "a\rb"))
- (should-not (funcall check "a\nb"))
- (should-not (funcall check "a\r\nb"))))
-
-(defun erc-tests--with-process-input-spy (test)
- (with-current-buffer (get-buffer-create "FakeNet")
- (let* ((erc--input-review-functions
- (remove #'erc-add-to-input-ring erc--input-review-functions))
- (erc-pre-send-functions
- (remove #'erc-add-to-input-ring erc-pre-send-functions)) ; for now
- (inhibit-message noninteractive)
- (erc-server-current-nick "tester")
- (erc-last-input-time 0)
- erc-accidental-paste-threshold-seconds
- erc-send-modify-hook
- ;;
- calls)
- (cl-letf (((symbol-function 'erc-process-input-line)
- (lambda (&rest r) (push r calls)))
- ((symbol-function 'erc-server-buffer)
- (lambda () (current-buffer))))
- (erc-tests--send-prep)
- (funcall test (lambda () (pop calls)))))
- (when noninteractive (kill-buffer))))
-
(ert-deftest erc--check-prompt-input-functions ()
- (erc-tests--with-process-input-spy
+ (erc-tests-common-with-process-input-spy
(lambda (next)
(ert-info ("Errors when point not in prompt area") ; actually just dings
@@ -1064,9 +1383,9 @@
(ert-info ("Input remains untouched")
(should (save-excursion (erc-bol) (looking-at "/msg #chan hi")))))
- (ert-info ("Errors when no process running")
+ (ert-info ("Errors when server buffer absent")
(let ((e (should-error (erc-send-current-line))))
- (should (equal "ERC: No process running" (cadr e))))
+ (should (equal "Server buffer missing" (cadr e))))
(ert-info ("Input remains untouched")
(should (save-excursion (erc-bol) (looking-at "/msg #chan hi")))))
@@ -1075,7 +1394,7 @@
(delete-region (point) (point-max))
(insert "one\n")
(let ((e (should-error (erc-send-current-line))))
- (should (equal "Blank line - ignoring..." (cadr e))))
+ (should (string-prefix-p "Trailing line detected" (cadr e))))
(goto-char (point-max))
(ert-info ("Input remains untouched")
(should (save-excursion (goto-char erc-input-marker)
@@ -1087,9 +1406,9 @@
;; These also indirectly tests `erc-send-input'
(ert-deftest erc-send-current-line ()
- (erc-tests--with-process-input-spy
+ (erc-tests-common-with-process-input-spy
(lambda (next)
- (erc-tests--set-fake-server-process "sleep" "1")
+ (erc-tests-common-init-server-proc "sleep" "1")
(should (= 0 erc-last-input-time))
(ert-info ("Simple command")
@@ -1117,10 +1436,141 @@
(should (consp erc-last-input-time)))))
+(ert-deftest erc--discard-trailing-multiline-nulls ()
+ (pcase-dolist (`(,input ,want) '((("") (""))
+ (("" "") (""))
+ (("a") ("a"))
+ (("a" "") ("a"))
+ (("" "a") ("" "a"))
+ (("" "a" "") ("" "a"))))
+ (ert-info ((format "Input: %S, want: %S" input want))
+ (let ((s (make-erc--input-split :lines input)))
+ (erc--discard-trailing-multiline-nulls s)
+ (should (equal (erc--input-split-lines s) want))))))
+
+(ert-deftest erc--count-blank-lines ()
+ (pcase-dolist (`(,input ,want) '((() (0 0 0))
+ (("") (1 1 0))
+ (("" "") (2 1 1))
+ (("" "" "") (3 1 2))
+ ((" " "") (2 0 1))
+ ((" " "" "") (3 0 2))
+ (("" " " "") (3 1 1))
+ (("" "" " ") (3 2 0))
+ (("a") (0 0 0))
+ (("a" "") (1 0 1))
+ (("a" " " "") (2 0 1))
+ (("a" "" "") (2 0 2))
+ (("a" "b") (0 0 0))
+ (("a" "" "b") (1 1 0))
+ (("a" " " "b") (1 0 0))
+ (("" "a") (1 1 0))
+ ((" " "a") (1 0 0))
+ (("" "a" "") (2 1 1))
+ (("" " " "a" "" " ") (4 2 0))
+ (("" " " "a" "" " " "") (5 2 1))))
+ (ert-info ((format "Input: %S, want: %S" input want))
+ (should (equal (erc--count-blank-lines input) want)))))
+
+;; Opt `wb': `erc-warn-about-blank-lines'
+;; Opt `sw': `erc-send-whitespace-lines'
+;; `s': " \n",`a': "a\n",`b': "b\n"
+(defvar erc-tests--check-prompt-input--expect
+ ;; opts "" " " "\n" "\n " " \n" "\n\n" "a\n" "a\n " "a\n \nb"
+ '(((+wb -sw) err err err err err err err err err)
+ ((-wb -sw) nop nop nop nop nop nop nop nop nop)
+ ((+wb +sw) err (s) (0 s) (1 s s) (s) (0 s) (0 a) (a s) (a s b))
+ ((-wb +sw) nop (s) (s) (s s) (s) (s) (a) (a s) (a s b))))
+
+;; Help messages echoed (not IRC message) was emitted
+(defvar erc-tests--check-prompt-input-messages
+ '("Stripping" "Padding"))
+
+(ert-deftest erc--check-prompt-input-for-multiline-blanks ()
+ (erc-tests-common-with-process-input-spy
+ (lambda (next)
+ (erc-tests-common-init-server-proc "sleep" "10")
+ (should-not erc-send-whitespace-lines)
+ (should erc-warn-about-blank-lines)
+
+ (pcase-dolist (`((,wb ,sw) . ,ex) erc-tests--check-prompt-input--expect)
+ (let ((print-escape-newlines t)
+ (erc-warn-about-blank-lines (eq wb '+wb))
+ (erc-send-whitespace-lines (eq sw '+sw))
+ (samples '("" " " "\n" "\n " " \n" "\n\n"
+ "a\n" "a\n " "a\n \nb")))
+ (setq ex `(,@ex (a) (a b)) ; baseline, same for all combos
+ samples `(,@samples "a" "a\nb"))
+ (dolist (input samples)
+ (insert input)
+ (ert-info ((format "Opts: %S, Input: %S, want: %S"
+ (list wb sw) input (car ex)))
+ (ert-with-message-capture messages
+ (pcase-exhaustive (pop ex)
+ ('err (let ((e (should-error (erc-send-current-line))))
+ (should (string-match (rx (| "trailing" "blank"))
+ (cadr e))))
+ (should (equal (erc-user-input) input))
+ (should-not (funcall next)))
+ ('nop (erc-send-current-line)
+ (should (equal (erc-user-input) input))
+ (should-not (funcall next)))
+ ('clr (erc-send-current-line)
+ (should (string-empty-p (erc-user-input)))
+ (should-not (funcall next)))
+ ((and (pred consp) v)
+ (erc-send-current-line)
+ (should (string-empty-p (erc-user-input)))
+ (setq v (reverse v)) ; don't use `nreverse' here
+ (while v
+ (pcase (pop v)
+ ((and (pred integerp) n)
+ (should (string-search
+ (nth n erc-tests--check-prompt-input-messages)
+ messages)))
+ ('s (should (equal " \n" (car (funcall next)))))
+ ('a (should (equal "a\n" (car (funcall next)))))
+ ('b (should (equal "b\n" (car (funcall next)))))))
+ (should-not (funcall next))))))
+ (delete-region erc-input-marker (point-max))))))))
+
+(ert-deftest erc--check-prompt-input-for-multiline-blanks/explanations ()
+ (should erc-warn-about-blank-lines)
+ (should-not erc-send-whitespace-lines)
+
+ (let ((erc-send-whitespace-lines t))
+ (pcase-dolist (`(,input ,msg)
+ '((("") "Padding (1) blank line")
+ (("" " ") "Padding (1) blank line")
+ ((" " "") "Stripping (1) blank line")
+ (("a" "") "Stripping (1) blank line")
+ (("" "") "Stripping (1) and padding (1) blank lines")
+ (("" "" "") "Stripping (2) and padding (1) blank lines")
+ (("" "a" "" "b" "" "c" "" "")
+ "Stripping (2) and padding (3) blank lines")))
+ (ert-info ((format "Input: %S, Msg: %S" input msg))
+ (let (erc--check-prompt-explanation)
+ (should-not (erc--check-prompt-input-for-multiline-blanks nil input))
+ (should (equal (list msg) erc--check-prompt-explanation))))))
+
+ (pcase-dolist (`(,input ,msg)
+ '((("") "Blank line detected")
+ (("" " ") "2 blank lines detected")
+ ((" " "") "2 blank (1 trailing) lines detected")
+ (("a" "") "Trailing line detected")
+ (("" "") "2 blank (1 trailing) lines detected")
+ (("a" "" "") "2 trailing lines detected")
+ (("" "a" "" "b" "" "c" "" "")
+ "5 blank (2 trailing) lines detected")))
+ (ert-info ((format "Input: %S, Msg: %S" input msg))
+ (let ((rv (erc--check-prompt-input-for-multiline-blanks nil input)))
+ (should (equal (concat msg " (see `erc-send-whitespace-lines')")
+ rv ))))))
+
(ert-deftest erc-send-whitespace-lines ()
- (erc-tests--with-process-input-spy
+ (erc-tests-common-with-process-input-spy
(lambda (next)
- (erc-tests--set-fake-server-process "sleep" "1")
+ (erc-tests-common-init-server-proc "sleep" "1")
(setq-local erc-send-whitespace-lines t)
(ert-info ("Multiline hunk with blank line correctly split")
@@ -1133,7 +1583,7 @@
(erc-bol)
(should (eq (point) (point-max))))
(should (equal (funcall next) '("two\n" nil t)))
- (should (equal (funcall next) '("\n" nil t)))
+ (should (equal (funcall next) '(" \n" nil t)))
(should (equal (funcall next) '("one\n" nil t))))
(ert-info ("Multiline hunk with trailing newline filtered")
@@ -1155,17 +1605,12 @@
(should-not (funcall next)))
(ert-info ("Multiline command with trailing blank filtered")
- (pcase-dolist (`(,p . ,q)
- '(("/a b\r" "/a b\n") ("/a b\n" "/a b\n")
- ("/a b\n\n" "/a b\n") ("/a b\r\n" "/a b\n")
- ("/a b\n\n\n" "/a b\n")))
+ (dolist (p '("/a b" "/a b\n" "/a b\n\n" "/a b\n\n\n"))
(insert p)
(erc-send-current-line)
(erc-bol)
(should (eq (point) (point-max)))
- (while q
- (should (pcase (funcall next)
- (`(,cmd ,_ nil) (equal cmd (pop q))))))
+ (should (pcase (funcall next) (`(,cmd ,_ nil) (equal cmd "/a b\n"))))
(should-not (funcall next))))
(ert-info ("Multiline command with non-blanks errors")
@@ -1220,7 +1665,7 @@
(erc-default-recipients '("#chan"))
calls)
(with-temp-buffer
- (erc-tests--set-fake-server-process "sleep" "1")
+ (erc-tests-common-init-server-proc "sleep" "1")
(cl-letf (((symbol-function 'erc-cmd-MSG)
(lambda (line)
(push line calls)
@@ -1278,21 +1723,142 @@
(should-not calls))))))
-(defmacro erc-tests--equal-including-properties (a b)
- (list (if (< emacs-major-version 29)
- 'ert-equal-including-properties
- 'equal-including-properties)
- a b))
+(ert-deftest erc--get-inserted-msg-beg/basic ()
+ (erc-tests-common-assert-get-inserted-msg/basic
+ (lambda (arg) (should (= 3 (erc--get-inserted-msg-beg arg))))))
+
+(ert-deftest erc--get-inserted-msg-end/basic ()
+ (erc-tests-common-assert-get-inserted-msg/basic
+ (lambda (arg) (should (= 11 (erc--get-inserted-msg-end arg))))))
+
+(ert-deftest erc--get-inserted-msg-bounds/basic ()
+ (erc-tests-common-assert-get-inserted-msg/basic
+ (lambda (arg)
+ (should (equal '(3 . 11) (erc--get-inserted-msg-bounds arg))))))
+
+(ert-deftest erc--delete-inserted-message ()
+ (erc-mode)
+ (erc--initialize-markers (point) nil)
+ ;; Put unique invisible properties on the line endings.
+ (erc-display-message nil 'notice nil "one")
+ (put-text-property (1- erc-insert-marker) erc-insert-marker 'invisible 'a)
+ (let ((erc--msg-prop-overrides '((erc--msg . datestamp) (erc--ts . 0))))
+ (erc-display-message nil nil nil
+ (propertize "\n[date]" 'field 'erc-timestamp)))
+ (put-text-property (1- erc-insert-marker) erc-insert-marker 'invisible 'b)
+ (erc-display-message nil 'notice nil "two")
+
+ (ert-info ("Date stamp deleted cleanly")
+ (goto-char 11)
+ (should (looking-at (rx "\n[date]")))
+ (should (eq 'datestamp (get-text-property (point) 'erc--msg)))
+ (should (eq (point) (field-beginning (1+ (point)))))
+
+ (erc--delete-inserted-message (point))
+
+ ;; Preceding line ending clobbered, replaced by trailing.
+ (should (looking-back (rx "*** one\n")))
+ (should (looking-at (rx "*** two")))
+ (should (eq 'b (get-text-property (1- (point)) 'invisible))))
+
+ (ert-info ("Markers at pos-bol preserved")
+ (erc-display-message nil 'notice nil "three")
+ (should (looking-at (rx "*** two")))
+
+ (let ((m (point-marker))
+ (n (point-marker))
+ (p (point)))
+ (set-marker-insertion-type m t)
+ (goto-char (point-max))
+ (erc--delete-inserted-message p)
+ (should (= (marker-position n) p))
+ (should (= (marker-position m) p))
+ (goto-char p)
+ (set-marker m nil)
+ (set-marker n nil)
+ (should (looking-back (rx "*** one\n")))
+ (should (looking-at (rx "*** three")))))
+
+ (ert-info ("Compat")
+ (erc-display-message nil 'notice nil "four")
+ (should (looking-at (rx "*** three\n")))
+ (with-suppressed-warnings ((obsolete erc-legacy-invisible-bounds-p))
+ (let ((erc-legacy-invisible-bounds-p t))
+ (erc--delete-inserted-message (point))))
+ (should (looking-at (rx "*** four\n"))))
+
+ (ert-info ("Deleting most recent message preserves markers")
+ (let ((m (point-marker))
+ (n (point-marker))
+ (p (point)))
+ (should (equal "*** four\n" (buffer-substring p erc-insert-marker)))
+ (set-marker-insertion-type m t)
+ (goto-char (point-max))
+ (erc--delete-inserted-message p)
+ (should (= (marker-position m) p))
+ (should (= (marker-position n) p))
+ (goto-char p)
+ (should (looking-back (rx "*** one\n")))
+ (should (looking-at erc-prompt))
+ (erc--assert-input-bounds)
+
+ ;; However, `m' is now forever "trapped" at `erc-insert-marker'.
+ (erc-display-message nil 'notice nil "two")
+ (should (= m erc-insert-marker))
+ (goto-char n)
+ (should (looking-at (rx "*** two\n")))
+ (set-marker m nil)
+ (set-marker n nil))))
+
+(ert-deftest erc--order-text-properties-from-hash ()
+ (let ((table (map-into '((a . 1)
+ (erc--ts . 0)
+ (erc--msg . s005)
+ (b . 2)
+ (erc--cmd . 5)
+ (erc--spkr . "X")
+ (c . 3))
+ 'hash-table)))
+ (with-temp-buffer
+ (erc-mode)
+ (insert "abc\n")
+ (add-text-properties 1 2 (erc--order-text-properties-from-hash table))
+ (should (equal '( erc--msg s005
+ erc--spkr "X"
+ erc--ts 0
+ erc--cmd 5
+ a 1
+ b 2
+ c 3)
+ (text-properties-at (point-min)))))))
+
+(ert-deftest erc--check-msg-prop ()
+ (let ((erc--msg-props (map-into '((a . 1) (b . x)) 'hash-table)))
+ (should (eq 1 (erc--check-msg-prop 'a)))
+ (should (erc--check-msg-prop 'a 1))
+ (should-not (erc--check-msg-prop 'a 2))
+
+ (should (eq 'x (erc--check-msg-prop 'b)))
+ (should (erc--check-msg-prop 'b 'x))
+ (should-not (erc--check-msg-prop 'b 1))
+
+ (should (erc--check-msg-prop 'a '(1 42)))
+ (should-not (erc--check-msg-prop 'a '(2 42)))
+
+ (let ((props '(42 x)))
+ (should (erc--check-msg-prop 'b props)))
+ (let ((v '(42 y)))
+ (should-not (erc--check-msg-prop 'b v)))))
(ert-deftest erc--merge-prop ()
(with-current-buffer (get-buffer-create "*erc-test*")
;; Baseline.
(insert "abc\n")
(erc--merge-prop 1 3 'erc-test 'x)
- (should (erc-tests--equal-including-properties
+ (should (erc-tests-common-equal-with-props
(buffer-substring 1 4) #("abc" 0 2 (erc-test x))))
(erc--merge-prop 1 3 'erc-test 'y)
- (should (erc-tests--equal-including-properties
+ (should (erc-tests-common-equal-with-props
(buffer-substring 1 4) #("abc" 0 2 (erc-test (y x)))))
;; Multiple intervals.
@@ -1300,11 +1866,11 @@
(insert "def\n")
(erc--merge-prop 1 2 'erc-test 'x)
(erc--merge-prop 2 3 'erc-test 'y)
- (should (erc-tests--equal-including-properties
+ (should (erc-tests-common-equal-with-props
(buffer-substring 1 4)
#("def" 0 1 (erc-test x) 1 2 (erc-test y))))
(erc--merge-prop 1 3 'erc-test 'z)
- (should (erc-tests--equal-including-properties
+ (should (erc-tests-common-equal-with-props
(buffer-substring 1 4)
#("def" 0 1 (erc-test (z x)) 1 2 (erc-test (z y)))))
@@ -1312,13 +1878,194 @@
(goto-char (point-min))
(insert "ghi\n")
(erc--merge-prop 2 3 'erc-test '(y z))
- (should (erc-tests--equal-including-properties
+ (should (erc-tests-common-equal-with-props
(buffer-substring 1 4) #("ghi" 1 2 (erc-test (y z)))))
(erc--merge-prop 1 3 'erc-test '(w x))
- (should (erc-tests--equal-including-properties
+ (should (erc-tests-common-equal-with-props
(buffer-substring 1 4)
#("ghi" 0 1 (erc-test (w x)) 1 2 (erc-test (w x y z)))))
+ ;; Flag `erc--merge-prop-behind-p'.
+ (goto-char (point-min))
+ (insert "jkl\n")
+ (erc--merge-prop 2 3 'erc-test '(y z))
+ (should (erc-tests-common-equal-with-props
+ (buffer-substring 1 4) #("jkl" 1 2 (erc-test (y z)))))
+ (let ((erc--merge-prop-behind-p t))
+ (erc--merge-prop 1 3 'erc-test '(w x)))
+ (should (erc-tests-common-equal-with-props
+ (buffer-substring 1 4)
+ #("jkl" 0 1 (erc-test (w x)) 1 2 (erc-test (y z w x)))))
+
+ (when noninteractive
+ (kill-buffer))))
+
+(ert-deftest erc--remove-from-prop-value-list ()
+ (with-current-buffer (get-buffer-create "*erc-test*")
+ ;; Non-list match.
+ (insert "abc\n")
+ (put-text-property 1 2 'erc-test 'a)
+ (put-text-property 2 3 'erc-test 'b)
+ (put-text-property 3 4 'erc-test 'c)
+ (should (erc-tests-common-equal-with-props
+ (buffer-substring 1 4) #("abc"
+ 0 1 (erc-test a)
+ 1 2 (erc-test b)
+ 2 3 (erc-test c))))
+
+ (erc--remove-from-prop-value-list 1 4 'erc-test 'b)
+ (should (erc-tests-common-equal-with-props
+ (buffer-substring 1 4) #("abc"
+ 0 1 (erc-test a)
+ 2 3 (erc-test c))))
+ (erc--remove-from-prop-value-list 1 4 'erc-test 'a)
+ (should (erc-tests-common-equal-with-props
+ (buffer-substring 1 4) #("abc" 2 3 (erc-test c))))
+ (erc--remove-from-prop-value-list 1 4 'erc-test 'c)
+ (should (erc-tests-common-equal-with-props
+ (buffer-substring 1 4) "abc"))
+
+ ;; List match.
+ (goto-char (point-min))
+ (insert "def\n")
+ (put-text-property 1 2 'erc-test '(d x))
+ (put-text-property 2 3 'erc-test '(e y))
+ (put-text-property 3 4 'erc-test '(f z))
+ (should (erc-tests-common-equal-with-props
+ (buffer-substring 1 4) #("def"
+ 0 1 (erc-test (d x))
+ 1 2 (erc-test (e y))
+ 2 3 (erc-test (f z)))))
+ (erc--remove-from-prop-value-list 1 4 'erc-test 'y)
+ (should (erc-tests-common-equal-with-props
+ (buffer-substring 1 4) #("def"
+ 0 1 (erc-test (d x))
+ 1 2 (erc-test e)
+ 2 3 (erc-test (f z)))))
+ (erc--remove-from-prop-value-list 1 4 'erc-test 'd)
+ (erc--remove-from-prop-value-list 1 4 'erc-test 'f)
+ (should (erc-tests-common-equal-with-props
+ (buffer-substring 1 4) #("def"
+ 0 1 (erc-test x)
+ 1 2 (erc-test e)
+ 2 3 (erc-test z))))
+ (erc--remove-from-prop-value-list 1 4 'erc-test 'e)
+ (erc--remove-from-prop-value-list 1 4 'erc-test 'z)
+ (erc--remove-from-prop-value-list 1 4 'erc-test 'x)
+ (should (erc-tests-common-equal-with-props
+ (buffer-substring 1 4) "def"))
+
+ ;; List match.
+ (goto-char (point-min))
+ (insert "ghi\n")
+ (put-text-property 1 2 'erc-test '(g x))
+ (put-text-property 2 3 'erc-test '(h x))
+ (put-text-property 3 4 'erc-test '(i y))
+ (should (erc-tests-common-equal-with-props
+ (buffer-substring 1 4) #("ghi"
+ 0 1 (erc-test (g x))
+ 1 2 (erc-test (h x))
+ 2 3 (erc-test (i y)))))
+ (erc--remove-from-prop-value-list 1 4 'erc-test 'x)
+ (should (erc-tests-common-equal-with-props
+ (buffer-substring 1 4) #("ghi"
+ 0 1 (erc-test g)
+ 1 2 (erc-test h)
+ 2 3 (erc-test (i y)))))
+ (erc--remove-from-prop-value-list 1 2 'erc-test 'g) ; narrowed
+ (erc--remove-from-prop-value-list 3 4 'erc-test 'i) ; narrowed
+ (should (erc-tests-common-equal-with-props
+ (buffer-substring 1 4) #("ghi"
+ 1 2 (erc-test h)
+ 2 3 (erc-test y))))
+
+ ;; Pathological (,c) case (hopefully not created by ERC)
+ (goto-char (point-min))
+ (insert "jkl\n")
+ (put-text-property 1 2 'erc-test '(j x))
+ (put-text-property 2 3 'erc-test '(k))
+ (put-text-property 3 4 'erc-test '(k))
+ (erc--remove-from-prop-value-list 1 4 'erc-test 'k)
+ (should (erc-tests-common-equal-with-props
+ (buffer-substring 1 4) #("jkl" 0 1 (erc-test (j x)))))
+
+ (when noninteractive
+ (kill-buffer))))
+
+(ert-deftest erc--remove-from-prop-value-list/many ()
+ (with-current-buffer (get-buffer-create "*erc-test*")
+ ;; Non-list match.
+ (insert "abc\n")
+ (put-text-property 1 2 'erc-test 'a)
+ (put-text-property 2 3 'erc-test 'b)
+ (put-text-property 3 4 'erc-test 'c)
+ (should (erc-tests-common-equal-with-props
+ (buffer-substring 1 4) #("abc"
+ 0 1 (erc-test a)
+ 1 2 (erc-test b)
+ 2 3 (erc-test c))))
+
+ (erc--remove-from-prop-value-list 1 4 'erc-test '(a b))
+ (should (erc-tests-common-equal-with-props
+ (buffer-substring 1 4) #("abc" 2 3 (erc-test c))))
+ (erc--remove-from-prop-value-list 1 4 'erc-test 'a)
+ (should (erc-tests-common-equal-with-props
+ (buffer-substring 1 4) #("abc" 2 3 (erc-test c))))
+ (erc--remove-from-prop-value-list 1 4 'erc-test '(c))
+ (should (erc-tests-common-equal-with-props
+ (buffer-substring 1 4) "abc"))
+
+ ;; List match.
+ (goto-char (point-min))
+ (insert "def\n")
+ (put-text-property 1 2 'erc-test '(d x y))
+ (put-text-property 2 3 'erc-test '(e y))
+ (put-text-property 3 4 'erc-test '(f z))
+ (should (erc-tests-common-equal-with-props
+ (buffer-substring 1 4) #("def"
+ 0 1 (erc-test (d x y))
+ 1 2 (erc-test (e y))
+ 2 3 (erc-test (f z)))))
+ (erc--remove-from-prop-value-list 1 4 'erc-test '(d y f))
+ (should (erc-tests-common-equal-with-props
+ (buffer-substring 1 4) #("def"
+ 0 1 (erc-test x)
+ 1 2 (erc-test e)
+ 2 3 (erc-test z))))
+ (erc--remove-from-prop-value-list 1 4 'erc-test '(e z x))
+ (should (erc-tests-common-equal-with-props
+ (buffer-substring 1 4) "def"))
+
+ ;; Narrowed beg.
+ (goto-char (point-min))
+ (insert "ghi\n")
+ (put-text-property 1 2 'erc-test '(g x))
+ (put-text-property 2 3 'erc-test '(h x))
+ (put-text-property 3 4 'erc-test '(i x))
+ (should (erc-tests-common-equal-with-props
+ (buffer-substring 1 4) #("ghi"
+ 0 1 (erc-test (g x))
+ 1 2 (erc-test (h x))
+ 2 3 (erc-test (i x)))))
+ (erc--remove-from-prop-value-list 1 3 'erc-test '(x g i))
+ (should (erc-tests-common-equal-with-props
+ (buffer-substring 1 4) #("ghi"
+ 1 2 (erc-test h)
+ 2 3 (erc-test (i x)))))
+
+ ;; Narrowed middle.
+ (goto-char (point-min))
+ (insert "jkl\n")
+ (put-text-property 1 2 'erc-test '(j x))
+ (put-text-property 2 3 'erc-test '(k))
+ (put-text-property 3 4 'erc-test '(l y z))
+ (erc--remove-from-prop-value-list 3 4 'erc-test '(k x y z))
+ (should (erc-tests-common-equal-with-props
+ (buffer-substring 1 4) #("jkl"
+ 0 1 (erc-test (j x))
+ 1 2 (erc-test (k))
+ 2 3 (erc-test l))))
+
(when noninteractive
(kill-buffer))))
@@ -1447,10 +2194,11 @@
erc-pre-send-functions
(lambda (o) (setf (erc-input-string o) "foo bar baz"
(erc-input-refoldp o) t)))
- (let ((erc-split-line-length 8))
+ (let* ((split (make-erc--input-split :string "foo" :lines '("foo")))
+ (erc--current-line-input-split split)
+ (erc-split-line-length 8))
(should
- (pcase (erc--run-send-hooks (make-erc--input-split
- :string "foo" :lines '("foo")))
+ (pcase (erc--run-send-hooks split)
((cl-struct erc--input-split
(string "foo") (sendp 't) (insertp 't)
(lines '("foo bar " "baz")) (cmdp 'nil))
@@ -1464,7 +2212,8 @@
calls
erc-kill-channel-hook erc-kill-server-hook erc-kill-buffer-hook)
(cl-letf (((symbol-function 'erc-display-message)
- (lambda (_ _ _ line) (push line calls)))
+ (lambda (_ _ _ msg &rest args)
+ (push (apply #'erc-format-message msg args) calls)))
((symbol-function 'erc-server-send)
(lambda (line _) (push line calls)))
((symbol-function 'erc-server-buffer)
@@ -1483,6 +2232,7 @@
(erc-mode)
(setq erc-server-process (buffer-local-value 'erc-server-process
(get-buffer "ExampleNet"))
+ erc--target (erc--target-from-string "#chan")
erc-default-recipients '("#chan")
erc-channel-users (make-hash-table :test 'equal)
erc-network 'ExampleNet)
@@ -1505,7 +2255,7 @@
(should-not erc-server-last-peers)
(erc-message "PRIVMSG" ". hi")
(should-not erc-server-last-peers)
- (should (eq 'no-target (pop calls)))
+ (should (equal "No target" (pop calls)))
(erc-message "PRIVMSG" ", hi")
(should-not erc-server-last-peers)
(should (string-match "alice :hi" (pop calls)))))
@@ -1538,42 +2288,332 @@
(kill-buffer "ExampleNet")
(kill-buffer "#chan")))
-(ert-deftest erc-format-privmessage ()
- ;; Basic PRIVMSG
- (should (erc-tests--equal-including-properties
- (erc-format-privmessage (copy-sequence "bob")
- (copy-sequence "oh my")
- nil 'msgp)
- #("<bob> oh my"
- 0 1 (font-lock-face erc-default-face)
- 1 4 (erc-speaker "bob" font-lock-face erc-nick-default-face)
- 4 11 (font-lock-face erc-default-face))))
-
- ;; Basic NOTICE
- (should (erc-tests--equal-including-properties
- (erc-format-privmessage (copy-sequence "bob")
- (copy-sequence "oh my")
- nil nil)
- #("-bob- oh my"
- 0 1 (font-lock-face erc-default-face)
- 1 4 (erc-speaker "bob" font-lock-face erc-nick-default-face)
- 4 11 (font-lock-face erc-default-face))))
-
- ;; Prefixed PRIVMSG
- (let* ((user (make-erc-server-user :nickname (copy-sequence "Bob")))
+(ert-deftest erc-get-channel-membership-prefix ()
+ (ert-info ("Uses default prefixes when `erc--parsed-prefix' not available")
+ (should-not (erc--parsed-prefix))
+ ;; Baseline.
+ (should-not (erc-get-channel-membership-prefix nil))
+ (should (equal (erc-get-channel-membership-prefix "Bob") ""))
+ (should (equal (erc-get-channel-membership-prefix (make-erc-channel-user))
+ ""))
+ ;; Defaults.
+ (should
+ (erc-tests-common-equal-with-props
+ (erc-get-channel-membership-prefix (make-erc-channel-user :owner t))
+ #("~" 0 1 (help-echo "owner"))))
+ (should
+ (erc-tests-common-equal-with-props
+ (erc-get-channel-membership-prefix (make-erc-channel-user :admin t))
+ #("&" 0 1 (help-echo "admin"))))
+ (should
+ (erc-tests-common-equal-with-props
+ (erc-get-channel-membership-prefix (make-erc-channel-user :op t))
+ #("@" 0 1 (help-echo "operator"))))
+ (should
+ (erc-tests-common-equal-with-props
+ (erc-get-channel-membership-prefix (make-erc-channel-user :halfop t))
+ #("%" 0 1 (help-echo "half-op"))))
+ (should
+ (erc-tests-common-equal-with-props
+ (erc-get-channel-membership-prefix (make-erc-channel-user :voice t))
+ #("+" 0 1 (help-echo "voice")))))
+
+ (ert-info ("Uses advertised prefixes when `erc--parsed-prefix' is available")
+ (erc-tests-common-make-server-buf (buffer-name))
+ (push '("PREFIX" . "(ov)@+") erc-server-parameters)
+ (should (erc--parsed-prefix))
+
+ (with-current-buffer (erc--open-target "#chan")
+ (erc-update-current-channel-member "Bob" nil t nil nil 'on)
+
+ ;; Baseline.
+ (should-not (erc-get-channel-membership-prefix nil))
+ (should (string-empty-p (erc-get-channel-membership-prefix
+ (make-erc-channel-user))))
+
+ ;; Defaults.
+ (should (string-empty-p (erc-get-channel-membership-prefix
+ (make-erc-channel-user :owner t))))
+ (should (string-empty-p (erc-get-channel-membership-prefix
+ (make-erc-channel-user :admin t))))
+ (should (string-empty-p (erc-get-channel-membership-prefix
+ (make-erc-channel-user :halfop t))))
+
+ (should (erc-tests-common-equal-with-props
+ (erc-get-channel-membership-prefix "Bob")
+ #("@" 0 1 (help-echo "operator"))))
+ (should (erc-tests-common-equal-with-props
+ (erc-get-channel-membership-prefix
+ (make-erc-channel-user :voice t))
+ #("+" 0 1 (help-echo "voice"))))
+
+ (kill-buffer))))
+
+;; This is an adapter that uses formatting templates from the
+;; `-speaker' catalog to mimic `erc-format-privmessage', for testing
+;; purposes.
+(defun erc-tests--format-privmessage (nick msg privp msgp &optional inputp pfx)
+ (let ((erc-current-message-catalog erc--message-speaker-catalog))
+ (apply #'erc-format-message
+ (erc--determine-speaker-message-format-args nick msg privp msgp
+ inputp nil pfx))))
+
+;; This asserts that `erc--determine-speaker-message-format-args'
+;; behaves identically to `erc-format-privmessage', the function whose
+;; role it basically replaced.
+(ert-deftest erc--determine-speaker-message-format-args ()
+ ;; Basic PRIVMSG.
+ (let ((expect #("<bob> oh my"
+ 0 1 (font-lock-face erc-default-face)
+ 1 4 (erc--speaker "bob" font-lock-face erc-nick-default-face)
+ 4 11 (font-lock-face erc-default-face)))
+ (args (list (concat "bob") (concat "oh my") nil 'msgp)))
+ (should (erc-tests-common-equal-with-props
+ (apply #'erc-format-privmessage args)
+ expect))
+ (should (erc-tests-common-equal-with-props
+ (apply #'erc-tests--format-privmessage args)
+ expect)))
+
+ ;; Basic NOTICE.
+ (let ((expect #("-bob- oh my"
+ 0 1 (font-lock-face erc-default-face)
+ 1 4 (erc--speaker "bob" font-lock-face erc-nick-default-face)
+ 4 11 (font-lock-face erc-default-face)))
+ (args (list (copy-sequence "bob") (copy-sequence "oh my") nil nil)))
+ (should (erc-tests-common-equal-with-props
+ (apply #'erc-format-privmessage args)
+ expect))
+ (should (erc-tests-common-equal-with-props
+ (apply #'erc-tests--format-privmessage args)
+ expect)))
+
+ ;; Status-prefixed PRIVMSG.
+ (let* ((expect
+ #("<@Bob> oh my"
+ 0 1 (font-lock-face erc-default-face)
+ 1 2 (font-lock-face erc-nick-prefix-face help-echo "operator")
+ 2 5 (erc--speaker "Bob" font-lock-face erc-nick-default-face)
+ 5 12 (font-lock-face erc-default-face)))
+ (user (make-erc-server-user :nickname (copy-sequence "Bob")))
(cuser (make-erc-channel-user :op t))
(erc-channel-users (make-hash-table :test #'equal)))
(puthash "bob" (cons user cuser) erc-channel-users)
- (should (erc-tests--equal-including-properties
- (erc-format-privmessage (erc-format-@nick user cuser)
- (copy-sequence "oh my")
- nil 'msgp)
- #("<@Bob> oh my"
+ (with-suppressed-warnings ((obsolete erc-format-@nick))
+ (should (erc-tests-common-equal-with-props
+ (erc-format-privmessage (erc-format-@nick user cuser)
+ (copy-sequence "oh my")
+ nil 'msgp)
+ expect)))
+ (let ((nick "Bob")
+ (msg "oh my"))
+ (should (erc-tests-common-equal-with-props
+ (erc-tests--format-privmessage nick msg nil 'msgp nil cuser)
+ expect)) ; overloaded on PREFIX arg
+ (should (erc-tests-common-equal-with-props
+ (erc-tests--format-privmessage nick msg nil 'msgp nil t)
+ expect))
+ ;; The new version makes a copy instead of adding properties to
+ ;; the input.
+ (should-not
+ (text-property-not-all 0 (length nick) 'font-lock-face nil nick))
+ (should-not
+ (text-property-not-all 0 (length msg) 'font-lock-face nil msg)))))
+
+(ert-deftest erc--determine-speaker-message-format-args/queries-as-channel ()
+ (should erc-format-query-as-channel-p)
+
+ (with-current-buffer (get-buffer-create "bob")
+ (erc-mode)
+ (setq erc--target (erc--target-from-string "alice"))
+
+ (insert "PRIVMSG\n"
+ (erc-tests--format-privmessage "bob" "oh my" 'queryp 'msgp))
+ (should (erc-tests-common-equal-with-props
+ #("<bob> oh my"
+ 0 1 (font-lock-face erc-default-face)
+ 1 4 (erc--speaker "bob" font-lock-face erc-nick-default-face)
+ 4 11 (font-lock-face erc-default-face))
+ (buffer-substring (pos-bol) (pos-eol))))
+
+ (insert "\nNOTICE\n"
+ (erc-tests--format-privmessage "bob" "oh my" 'queryp nil))
+ (should (erc-tests-common-equal-with-props
+ #("-bob- oh my"
+ 0 1 (font-lock-face erc-default-face)
+ 1 4 (erc--speaker "bob" font-lock-face erc-nick-default-face)
+ 4 11 (font-lock-face erc-default-face))
+ (buffer-substring (pos-bol) (pos-eol))))
+
+ (insert "\nInput PRIVMSG\n"
+ (erc-tests--format-privmessage "bob" "oh my"
+ 'queryp 'privmsgp 'inputp))
+ (should (erc-tests-common-equal-with-props
+ #("<bob> oh my"
+ 0 1 (font-lock-face erc-default-face)
+ 1 4 (erc--speaker "bob" font-lock-face erc-my-nick-face)
+ 4 6 (font-lock-face erc-default-face)
+ 6 11 (font-lock-face erc-input-face))
+ (buffer-substring (pos-bol) (pos-eol))))
+
+ (insert "\nInput NOTICE\n"
+ (erc-tests--format-privmessage "bob" "oh my" 'queryp nil 'inputp))
+ (should (erc-tests-common-equal-with-props
+ #("-bob- oh my"
0 1 (font-lock-face erc-default-face)
- 1 2 (font-lock-face erc-nick-prefix-face help-echo "operator")
- 2 5 (erc-speaker "Bob" font-lock-face erc-nick-default-face)
- 5 12 (font-lock-face erc-default-face))))))
+ 1 4 (erc--speaker "bob" font-lock-face erc-my-nick-face)
+ 4 6 (font-lock-face erc-default-face)
+ 6 11 (font-lock-face erc-input-face))
+ (buffer-substring (pos-bol) (pos-eol))))
+
+ (when noninteractive (kill-buffer))))
+
+(ert-deftest erc--determine-speaker-message-format-args/queries ()
+ (should erc-format-query-as-channel-p)
+
+ (with-current-buffer (get-buffer-create "bob")
+ (erc-mode)
+ (setq-local erc-format-query-as-channel-p nil)
+ (setq erc--target (erc--target-from-string "alice"))
+
+ (insert "PRIVMSG\n"
+ (erc-tests--format-privmessage "bob" "oh my" 'queryp 'msgp))
+ (should (erc-tests-common-equal-with-props
+ #("*bob* oh my"
+ 0 1 (font-lock-face erc-direct-msg-face)
+ 1 4 (erc--speaker "bob" font-lock-face erc-nick-msg-face)
+ 4 11 (font-lock-face erc-direct-msg-face))
+ (buffer-substring (pos-bol) (pos-eol))))
+
+ (insert "\nNOTICE\n"
+ (erc-tests--format-privmessage "bob" "oh my" 'queryp nil))
+ (should (erc-tests-common-equal-with-props
+ #("-bob- oh my"
+ 0 1 (font-lock-face erc-direct-msg-face)
+ 1 4 (erc--speaker "bob" font-lock-face erc-nick-msg-face)
+ 4 11 (font-lock-face erc-direct-msg-face))
+ (buffer-substring (pos-bol) (pos-eol))))
+
+ (insert "\nInput PRIVMSG\n"
+ (erc-tests--format-privmessage "bob" "oh my"
+ 'queryp 'privmsgp 'inputp))
+ (should (erc-tests-common-equal-with-props
+ #("*bob* oh my"
+ 0 1 (font-lock-face erc-direct-msg-face)
+ 1 4 (erc--speaker "bob" font-lock-face erc-my-nick-face)
+ 4 6 (font-lock-face erc-direct-msg-face)
+ 6 11 (font-lock-face erc-input-face))
+ (buffer-substring (pos-bol) (pos-eol))))
+
+ (insert "\nInput NOTICE\n"
+ (erc-tests--format-privmessage "bob" "oh my" 'queryp nil 'inputp))
+ (should (erc-tests-common-equal-with-props
+ #("-bob- oh my"
+ 0 1 (font-lock-face erc-direct-msg-face)
+ 1 4 (erc--speaker "bob" font-lock-face erc-my-nick-face)
+ 4 6 (font-lock-face erc-direct-msg-face)
+ 6 11 (font-lock-face erc-input-face))
+ (buffer-substring (pos-bol) (pos-eol))))
+
+ (when noninteractive (kill-buffer))))
+
+(defun erc-tests--format-my-nick (message)
+ (concat (erc-format-my-nick)
+ (propertize message 'font-lock-face 'erc-input-face)))
+
+;; This tests that the default behavior of the replacement formatting
+;; function for prompt input, `erc--format-speaker-input-message'
+;; matches that of the original being replaced, `erc-format-my-nick',
+;; though it only handled the speaker portion.
+(ert-deftest erc--format-speaker-input-message ()
+ ;; No status prefix.
+ (let ((erc-server-current-nick "tester")
+ (expect #("<tester> oh my"
+ 0 1 (font-lock-face erc-default-face)
+ 1 7 (font-lock-face erc-my-nick-face erc--speaker "tester")
+ 7 9 (font-lock-face erc-default-face)
+ 9 14 (font-lock-face erc-input-face))))
+ (should (equal (erc-tests--format-my-nick "oh my") expect))
+ (should (equal (erc--format-speaker-input-message "oh my") expect)))
+
+ ;; With channel-operator status prefix.
+ (let* ((erc-server-current-nick "tester")
+ (cmem (cons (make-erc-server-user :nickname "tester")
+ (make-erc-channel-user :op t)))
+ (erc-channel-users (map-into (list "tester" cmem)
+ '(hash-table :test equal)))
+ (expect #("<@tester> oh my"
+ 0 1 (font-lock-face erc-default-face)
+ 1 2 (font-lock-face erc-my-nick-prefix-face)
+ 2 5 (font-lock-face erc-my-nick-face erc--speaker "bob")
+ 5 7 (font-lock-face erc-default-face)
+ 7 12 (font-lock-face erc-input-face))))
+ (should (equal (erc-tests--format-my-nick "oh my") expect))
+ (should (equal (erc--format-speaker-input-message "oh my") expect))))
+
+(ert-deftest erc--route-insertion ()
+ (erc-tests-common-prep-for-insertion)
+ (erc-tests-common-init-server-proc "sleep" "1")
+ (setq erc-networks--id (erc-networks--id-create 'foonet))
+
+ (let* ((erc-modules) ; for `erc--open-target'
+ (server-buffer (current-buffer))
+ (spam-buffer (save-excursion (erc--open-target "#spam")))
+ (chan-buffer (save-excursion (erc--open-target "#chan")))
+ calls)
+ (cl-letf (((symbol-function 'erc-insert-line)
+ (lambda (&rest r) (push (cons 'line-1 r) calls))))
+
+ (with-current-buffer chan-buffer
+
+ (ert-info ("Null `buffer' routes to live server-buffer")
+ (erc--route-insertion "null" nil)
+ (should (equal (pop calls) `(line-1 "null" ,server-buffer)))
+ (should-not calls))
+
+ (ert-info ("Cons `buffer' routes to live members")
+ ;; Copies a let-bound `erc--msg-props' before mutating.
+ (let* ((table (map-into '(erc--msg msg) 'hash-table))
+ (erc--msg-props table))
+ (erc--route-insertion "cons" (list server-buffer spam-buffer))
+ (should-not (eq table erc--msg-props)))
+ (should (equal (pop calls) `(line-1 "cons" ,spam-buffer)))
+ (should (equal (pop calls) `(line-1 "cons" ,server-buffer)))
+ (should-not calls))
+
+ (ert-info ("Variant `all' inserts in all session buffers")
+ (erc--route-insertion "all" 'all)
+ (should (equal (pop calls) `(line-1 "all" ,chan-buffer)))
+ (should (equal (pop calls) `(line-1 "all" ,spam-buffer)))
+ (should (equal (pop calls) `(line-1 "all" ,server-buffer)))
+ (should-not calls))
+
+ (ert-info ("Variant `active' routes to active buffer if alive")
+ (should (eq chan-buffer (erc-with-server-buffer erc-active-buffer)))
+ (erc-set-active-buffer spam-buffer)
+ (erc--route-insertion "act" 'active)
+ (should (equal (pop calls) `(line-1 "act" ,spam-buffer)))
+ (should (eq (erc-active-buffer) spam-buffer))
+ (should-not calls))
+
+ (ert-info ("Variant `active' falls back to current buffer")
+ (should (eq spam-buffer (erc-active-buffer)))
+ (kill-buffer "#spam")
+ (erc--route-insertion "nact" 'active)
+ (should (equal (pop calls) `(line-1 "nact" ,server-buffer)))
+ (should (eq (erc-with-server-buffer erc-active-buffer)
+ server-buffer))
+ (should-not calls))
+
+ (ert-info ("Dead single buffer defaults to live server-buffer")
+ (should-not (get-buffer "#spam"))
+ (erc--route-insertion "dead" 'spam-buffer)
+ (should (equal (pop calls) `(line-1 "dead" ,server-buffer)))
+ (should-not calls))))
+
+ (should-not (buffer-live-p spam-buffer))
+ (kill-buffer chan-buffer)))
(defvar erc-tests--ipv6-examples
'("1:2:3:4:5:6:7:8"
@@ -1900,30 +2940,6 @@
(erc-server-connect-function
erc-open-network-stream))))))))
-(defun erc-tests--make-server-buf (name)
- (with-current-buffer (get-buffer-create name)
- (erc-mode)
- (setq erc-server-process (start-process "sleep" (current-buffer)
- "sleep" "1")
- erc-session-server (concat "irc." name ".org")
- erc-session-port 6667
- erc-network (intern name))
- (set-process-query-on-exit-flag erc-server-process nil)
- (current-buffer)))
-
-(defun erc-tests--make-client-buf (server name)
- (unless (bufferp server)
- (setq server (get-buffer server)))
- (with-current-buffer (get-buffer-create name)
- (erc-mode)
- (setq erc--target (erc--target-from-string name))
- (dolist (v '(erc-server-process
- erc-session-server
- erc-session-port
- erc-network))
- (set v (buffer-local-value v server)))
- (current-buffer)))
-
(ert-deftest erc-handle-irc-url ()
(let* (calls
rvbuf
@@ -1937,10 +2953,10 @@
(cl-letf (((symbol-function 'erc-cmd-JOIN)
(lambda (&rest r) (push r calls))))
- (with-current-buffer (erc-tests--make-server-buf "foonet")
+ (with-current-buffer (erc-tests-common-make-server-buf "foonet")
(setq rvbuf (current-buffer)))
- (erc-tests--make-server-buf "barnet")
- (erc-tests--make-server-buf "baznet")
+ (erc-tests-common-make-server-buf "barnet")
+ (erc-tests-common-make-server-buf "baznet")
(ert-info ("Unknown network")
(erc-handle-irc-url "irc.foonet.org" 6667 "#chan" nil nil "irc")
@@ -1964,7 +2980,8 @@
(should-not calls))
(ert-info ("Known network, existing chan with key")
- (erc-tests--make-client-buf "foonet" "#chan")
+ (save-excursion
+ (with-current-buffer "foonet" (erc--open-target "#chan")))
(erc-handle-irc-url "irc.foonet.org" nil "#chan?sec" nil nil "irc")
(should (equal '("#chan" "sec") (pop calls)))
(should-not calls))
@@ -1977,7 +2994,7 @@
(ert-info ("Unknown network, connect, chan")
(with-current-buffer "foonet"
(should-not (local-variable-p 'erc-after-connect)))
- (setq rvbuf (lambda () (erc-tests--make-server-buf "gnu")))
+ (setq rvbuf (lambda () (erc-tests-common-make-server-buf "gnu")))
(erc-handle-irc-url "irc.gnu.org" nil "#spam" nil nil "irc")
(should (equal '("irc" :server "irc.gnu.org") (pop calls)))
(should-not calls)
@@ -1989,13 +3006,62 @@
(should-not calls))))
(when noninteractive
- (kill-buffer "foonet")
- (kill-buffer "barnet")
- (kill-buffer "baznet")
- (kill-buffer "#chan")))
+ (erc-tests-common-kill-buffers)))
+
+(ert-deftest erc-channel-user ()
+ ;; Traditional and alternate constructor swapped for compatibility.
+ (should (= 0 (erc-channel-user-status (erc-channel-user--make))))
+ (should-not (erc-channel-user-last-message-time (erc-channel-user--make)))
+
+ (should (= 42 (erc-channel-user-last-message-time
+ (make-erc-channel-user :last-message-time 42))))
+
+ (should (zerop (erc-channel-user-status (make-erc-channel-user))))
+
+ (let ((u (make-erc-channel-user)))
+
+ (ert-info ("Add voice status to user")
+ (should (= 0 (erc-channel-user-status u)))
+ (should-not (erc-channel-user-voice u))
+ (should (eq t (setf (erc-channel-user-voice u) t)))
+ (should (eq t (erc-channel-user-voice u))))
+
+ (ert-info ("Add op status to user")
+ (should (= 1 (erc-channel-user-status u)))
+ (should-not (erc-channel-user-op u))
+ (should (eq t (setf (erc-channel-user-op u) t)))
+ (should (eq t (erc-channel-user-op u))))
+
+ (ert-info ("Add owner status to user")
+ (should (= 5 (erc-channel-user-status u)))
+ (should-not (erc-channel-user-owner u))
+ (should (eq t (setf (erc-channel-user-owner u) t)))
+ (should (eq t (erc-channel-user-owner u))))
+
+ (ert-info ("Remove owner status from user")
+ (should (= 21 (erc-channel-user-status u)))
+ (should-not (setf (erc-channel-user-owner u) nil))
+ (should-not (erc-channel-user-owner u)))
+
+ (ert-info ("Remove op status from user")
+ (should (= 5 (erc-channel-user-status u)))
+ (should-not (setf (erc-channel-user-op u) nil))
+ (should-not (erc-channel-user-op u)))
+
+ (ert-info ("Remove voice status from user")
+ (should (= 1 (erc-channel-user-status u)))
+ (should-not (setf (erc-channel-user-voice u) nil))
+ (should-not (erc-channel-user-voice u)))
+
+ (ert-info ("Remove voice status from zeroed user")
+ (should (= 0 (erc-channel-user-status u)))
+ (should-not (setf (erc-channel-user-voice u) nil))
+ (should-not (erc-channel-user-voice u))
+ (should (= 0 (erc-channel-user-status u))))))
(defconst erc-tests--modules
- '( autoaway autojoin bufbar button capab-identify completion dcc fill identd
+ '( autoaway autojoin bufbar button capab-identify
+ command-indicator completion dcc fill identd
imenu irccontrols keep-place list log match menu move-to-prompt netsplit
networks nickbar nicks noncommands notifications notify page readonly
replace ring sasl scrolltobottom services smiley sound
@@ -2031,36 +3097,11 @@
(should (eq (erc--normalize-module-symbol 'nickserv) 'services)))
(defun erc-tests--assert-printed-in-subprocess (code expected)
- (let* ((package (if-let* ((found (getenv "ERC_PACKAGE_NAME"))
- ((string-prefix-p "erc-" found)))
- (intern found)
- 'erc))
- ;; This is for integrations testing with managed configs
- ;; ("starter kits") that use a different package manager.
- (init (and-let* ((found (getenv "ERC_TESTS_INIT"))
- (files (split-string found ","))
- ((seq-every-p #'file-exists-p files)))
- (mapcan (lambda (f) (list "-l" f)) files)))
- (prog
- `(progn
- ,@(and (not init) (featurep 'compat)
- `((require 'package)
- (let ((package-load-list '((compat t) (,package t))))
- (package-initialize))))
- (require 'erc)
- (cl-assert (equal erc-version ,erc-version) t)
- ,code))
- (proc (apply #'start-process
- (symbol-name (ert-test-name (ert-running-test)))
- (current-buffer)
- (concat invocation-directory invocation-name)
- `("-batch" ,@(or init '("-Q"))
- "-eval" ,(format "%S" prog)))))
- (set-process-query-on-exit-flag proc t)
+ (let ((proc (erc-tests-common-create-subprocess code '("-batch") nil)))
(while (accept-process-output proc 10))
(goto-char (point-min))
(unless (equal (read (current-buffer)) expected)
- (message "Exepcted: %S\nGot: %s" expected (buffer-string))
+ (message "Expected: %S\nGot: %s" expected (buffer-string))
(ert-fail "Mismatch"))))
;; Worrying about which library a module comes from is mostly not
@@ -2093,14 +3134,14 @@
'( :erc-insert-modify-hook (erc-controls-highlight ; 0
erc-button-add-buttons ; 30
- erc-fill ; 40
erc-match-message ; 50
- erc-add-timestamp) ; 60
+ erc-fill ; 60
+ erc-add-timestamp) ; 70
:erc-send-modify-hook ( erc-controls-highlight ; 0
erc-button-add-buttons ; 30
erc-fill ; 40
- erc-add-timestamp)))) ; 50
+ erc-add-timestamp)))) ; 70
(ert-deftest erc-migrate-modules ()
(should (equal (erc-migrate-modules '(autojoin timestamp button))
@@ -2141,65 +3182,129 @@
(should (eq (erc--find-group 'smiley nil) 'erc))
(should (eq (erc--find-group 'unmorse nil) 'erc)))
-(ert-deftest erc--update-modules ()
- (let (calls
- erc-modules
- erc-kill-channel-hook erc-kill-server-hook erc-kill-buffer-hook)
+(ert-deftest erc--sort-modules ()
+ (should (equal (erc--sort-modules '(networks foo fill bar fill stamp bar))
+ ;; Third-party mods appear in original order.
+ '(fill networks stamp foo bar))))
+
+(defun erc-tests--update-modules (fn)
+ (let* ((calls nil)
+ (custom-modes nil)
+ (on-load nil)
+ (text-quoting-style 'grave)
+
+ (get-calls (lambda () (prog1 (nreverse calls) (setq calls nil))))
+
+ (add-onload (lambda (m k v)
+ (put (intern m) 'erc--feature k)
+ (push (cons k (lambda () (funcall v m))) on-load)))
- ;; This `lbaz' module is unknown, so ERC looks for it via the
- ;; symbol proerty `erc--feature' and, failing that, by
- ;; `require'ing its "erc-" prefixed symbol.
- (should-not (intern-soft "erc-lbaz-mode"))
+ (mk-cmd (lambda (module)
+ (let ((mode (intern (format "erc-%s-mode" module))))
+ (fset mode (lambda (n) (push (cons mode n) calls))))))
+
+ (mk-builtin (lambda (module-string)
+ (let ((s (intern module-string)))
+ (put s 'erc--module s))))
+
+ (mk-global (lambda (module)
+ (push (intern (format "erc-%s-mode" module))
+ custom-modes))))
(cl-letf (((symbol-function 'require)
(lambda (s &rest _)
- (when (eq s 'erc--lbaz-feature)
- (fset (intern "erc-lbaz-mode") ; local module
- (lambda (n) (push (cons 'lbaz n) calls))))
- (push s calls)))
-
- ;; Local modules
- ((symbol-function 'erc-lbar-mode)
- (lambda (n) (push (cons 'lbar n) calls)))
- ((get 'lbaz 'erc--feature) 'erc--lbaz-feature)
-
- ;; Global modules
- ((symbol-function 'erc-gfoo-mode)
- (lambda (n) (push (cons 'gfoo n) calls)))
- ((get 'erc-gfoo-mode 'standard-value) 'ignore)
+ ;; Simulate library being loaded, things defined.
+ (when-let ((h (alist-get s on-load))) (funcall h))
+ (push (cons 'req s) calls)))
+
+ ;; Spoof global module detection.
+ ((symbol-function 'custom-variable-p)
+ (lambda (v) (memq v custom-modes))))
+
+ (funcall fn get-calls add-onload mk-cmd mk-builtin mk-global))
+ (should-not erc--aberrant-modules)))
+
+(ert-deftest erc--update-modules/unknown ()
+ (erc-tests--update-modules
+
+ (lambda (get-calls _ mk-cmd _ mk-global)
+
+ (ert-info ("Baseline")
+ (let* ((erc-modules '(foo))
+ (obarray (obarray-make))
+ (err (should-error (erc--update-modules erc-modules))))
+ (should (equal (cadr err) "`foo' is not a known ERC module"))
+ (should (equal (mapcar #'prin1-to-string (funcall get-calls))
+ '("(req . erc-foo)")))))
+
+ ;; Module's mode command exists but lacks an associated file.
+ (ert-info ("Bad autoload flagged as suspect")
+ (should-not erc--aberrant-modules)
+ (let* ((erc--aberrant-modules nil)
+ (obarray (obarray-make))
+ (erc-modules (list (intern "foo"))))
+
+ ;; Create a mode-activation command and make mode-var global.
+ (funcall mk-cmd "foo")
+ (funcall mk-global "foo")
+
+ ;; No local modules to return.
+ (should-not (erc--update-modules erc-modules))
+ (should (equal (mapcar #'prin1-to-string erc--aberrant-modules)
+ '("foo")))
+ ;; ERC requires the library via prefixed module name.
+ (should (equal (mapcar #'prin1-to-string (funcall get-calls))
+ '("(req . erc-foo)" "(erc-foo-mode . 1)"))))))))
+
+;; A local module (here, `lo2') lacks a mode toggle, so ERC tries to
+;; load its defining library, first via the symbol property
+;; `erc--feature', and then via an "erc-" prefixed symbol.
+(ert-deftest erc--update-modules/local ()
+ (erc-tests--update-modules
+
+ (lambda (get-calls add-onload mk-cmd mk-builtin mk-global)
+
+ (let* ((obarray (obarray-make 20))
+ (erc-modules (mapcar #'intern '("glo" "lo1" "lo2"))))
+
+ ;; Create a global and a local module.
+ (mapc mk-cmd '("glo" "lo1"))
+ (mapc mk-builtin '("glo" "lo1"))
+ (funcall mk-global "glo")
+ (funcall add-onload "lo2" 'explicit-feature-lib mk-cmd)
+
+ ;; Returns local modules.
+ (should (equal (mapcar #'symbol-name (erc--update-modules erc-modules))
+ '("erc-lo2-mode" "erc-lo1-mode")))
+
+ ;; Requiring `erc-lo2' defines `erc-lo2-mode'.
+ (should (equal (mapcar #'prin1-to-string (funcall get-calls))
+ `("(erc-glo-mode . 1)"
+ "(req . explicit-feature-lib)")))))))
+
+(ert-deftest erc--update-modules/realistic ()
+ (let ((calls nil)
+ ;; Module `pcomplete' "resolves" to `completion'.
+ (erc-modules '(pcomplete autojoin networks)))
+ (cl-letf (((symbol-function 'require)
+ (lambda (s &rest _) (push (cons 'req s) calls)))
+
+ ;; Spoof global module detection.
+ ((symbol-function 'custom-variable-p)
+ (lambda (v)
+ (memq v '(erc-autojoin-mode erc-networks-mode
+ erc-completion-mode))))
+ ;; Mock and spy real builtins.
((symbol-function 'erc-autojoin-mode)
(lambda (n) (push (cons 'autojoin n) calls)))
- ((get 'erc-autojoin-mode 'standard-value) 'ignore)
((symbol-function 'erc-networks-mode)
(lambda (n) (push (cons 'networks n) calls)))
- ((get 'erc-networks-mode 'standard-value) 'ignore)
((symbol-function 'erc-completion-mode)
- (lambda (n) (push (cons 'completion n) calls)))
- ((get 'erc-completion-mode 'standard-value) 'ignore))
+ (lambda (n) (push (cons 'completion n) calls))))
- (ert-info ("Unknown module")
- (setq erc-modules '(lfoo))
- (should-error (erc--update-modules))
- (should (equal (pop calls) 'erc-lfoo))
- (should-not calls))
-
- (ert-info ("Local modules")
- (setq erc-modules '(gfoo lbar lbaz))
- ;; Don't expose the mode here
- (should (equal (mapcar #'symbol-name (erc--update-modules))
- '("erc-lbaz-mode" "erc-lbar-mode")))
- ;; Lbaz required because unknown.
- (should (equal (nreverse calls) '((gfoo . 1) erc--lbaz-feature)))
- (fmakunbound (intern "erc-lbaz-mode"))
- (unintern (intern "erc-lbaz-mode") obarray)
- (setq calls nil))
-
- (ert-info ("Global modules") ; `pcomplete' resolved to `completion'
- (setq erc-modules '(pcomplete autojoin networks))
- (should-not (erc--update-modules)) ; no locals
- (should (equal (nreverse calls)
- '((completion . 1) (autojoin . 1) (networks . 1))))
- (setq calls nil)))))
+ (should-not (erc--update-modules erc-modules)) ; no locals
+ (should (equal (nreverse calls)
+ '((completion . 1) (autojoin . 1) (networks . 1)))))))
(ert-deftest erc--merge-local-modes ()
(cl-letf (((get 'erc-b-mode 'erc-module) 'b)
@@ -2340,4 +3445,86 @@ connection."
(put 'erc-mname-enable 'definition-name 'mname)
(put 'erc-mname-disable 'definition-name 'mname))))))
+(ert-deftest erc-tests-common-string-to-propertized-parts ()
+ :tags '(:unstable) ; only run this locally
+ (unless (>= emacs-major-version 28) (ert-skip "Missing `object-intervals'"))
+
+ (should (equal (erc-tests-common-string-to-propertized-parts
+ #("abc"
+ 0 1 (face default foo 1)
+ 1 3 (face (default italic) bar "2")))
+ '(concat (propertize "a" 'foo 1 'face 'default)
+ (propertize "bc" 'bar "2" 'face '(default italic)))))
+ (should (equal #("abc"
+ 0 1 (face default foo 1)
+ 1 3 (face (default italic) bar "2"))
+ (concat (propertize "a" 'foo 1 'face 'default)
+ (propertize "bc" 'bar "2" 'face '(default italic))))))
+
+(ert-deftest erc--make-message-variable-name ()
+ (should (erc--make-message-variable-name 'english 'QUIT 'softp))
+ (should (erc--make-message-variable-name 'english 'QUIT nil))
+
+ (let ((obarray (obarray-make)))
+ (should-not (erc--make-message-variable-name 'testcat 'testkey 'softp))
+ (should (erc--make-message-variable-name 'testcat 'testkey nil))
+ (should (intern-soft "erc-message-testcat-testkey" obarray))
+ (should-not (erc--make-message-variable-name 'testcat 'testkey 'softp))
+ (set (intern "erc-message-testcat-testkey" obarray) "hello world")
+ (should (equal (symbol-value
+ (erc--make-message-variable-name 'testcat 'testkey nil))
+ "hello world")))
+
+ ;; Hyphenated (internal catalog).
+ (let ((obarray (obarray-make)))
+ (should-not (erc--make-message-variable-name '-testcat 'testkey 'softp))
+ (should (erc--make-message-variable-name '-testcat 'testkey nil))
+ (should (intern-soft "erc--message-testcat-testkey" obarray))
+ (should-not (erc--make-message-variable-name '-testcat 'testkey 'softp))
+ (set (intern "erc--message-testcat-testkey" obarray) "hello world")
+ (should (equal (symbol-value
+ (erc--make-message-variable-name '-testcat 'testkey nil))
+ "hello world"))))
+
+(ert-deftest erc-retrieve-catalog-entry ()
+ (should (eq 'english erc-current-message-catalog))
+ (should (equal (erc-retrieve-catalog-entry 's221) "User modes for %n: %m"))
+
+ ;; Local binding.
+ (with-temp-buffer
+ (should (equal (erc-retrieve-catalog-entry 's221) "User modes for %n: %m"))
+ (setq erc-current-message-catalog 'test)
+ ;; No catalog named `test'.
+ (should (equal (erc-retrieve-catalog-entry 's221) "User modes for %n: %m"))
+
+ (let ((obarray (obarray-make)))
+ (set (intern "erc-message-test-s221") "test 221 val")
+ (should (equal (erc-retrieve-catalog-entry 's221) "test 221 val"))
+ (set (intern "erc-message-english-s221") "eng 221 val")
+
+ (let ((erc-current-message-catalog 'english))
+ (should (equal (erc-retrieve-catalog-entry 's221) "eng 221 val")))
+
+ (with-temp-buffer
+ (should (equal (erc-retrieve-catalog-entry 's221) "eng 221 val"))
+ (let ((erc-current-message-catalog 'test))
+ (should (equal (erc-retrieve-catalog-entry 's221) "test 221 val"))))
+
+ (should (equal (erc-retrieve-catalog-entry 's221) "test 221 val")))
+
+ (should (equal (erc-retrieve-catalog-entry 's221) "User modes for %n: %m"))
+ (should (equal erc-current-message-catalog 'test)))
+
+ ;; Default top-level value.
+ (set-default-toplevel-value 'erc-current-message-catalog 'test-top)
+ (should (equal (erc-retrieve-catalog-entry 's221) "User modes for %n: %m"))
+ (set (intern "erc-message-test-top-s221") "test-top 221 val")
+ (should (equal (erc-retrieve-catalog-entry 's221) "test-top 221 val"))
+
+ (setq erc-current-message-catalog 'test-local)
+ (should (equal (erc-retrieve-catalog-entry 's221) "test-top 221 val"))
+
+ (makunbound (intern "erc-message-test-top-s221"))
+ (unintern "erc-message-test-top-s221" obarray))
+
;;; erc-tests.el ends here
diff --git a/test/lisp/erc/erc-track-tests.el b/test/lisp/erc/erc-track-tests.el
index ab8d708b721..3288c42a42e 100644
--- a/test/lisp/erc/erc-track-tests.el
+++ b/test/lisp/erc/erc-track-tests.el
@@ -1,6 +1,6 @@
;;; erc-track-tests.el --- Tests for erc-track. -*- lexical-binding:t -*-
-;; Copyright (C) 2016-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2016-2024 Free Software Foundation, Inc.
;; Author: Mario Lang <mlang@delysid.org>
;; Author: Vivek Dasmohapatra <vivek@etla.org>
@@ -104,6 +104,42 @@
'("#emacs" "#vi"))
'("#e" "#v"))) ))
+(ert-deftest erc-track--shortened-names ()
+ (let (erc-track--shortened-names
+ erc-track--shortened-names-current-hash
+ results)
+
+ (with-memoization (erc-track--shortened-names-get
+ '("apple" "banana" "cherries"))
+ '("a" "b" "c"))
+ (should (integerp (car erc-track--shortened-names)))
+ (should (equal (cdr erc-track--shortened-names) '("a" "b" "c")))
+ (push erc-track--shortened-names results)
+
+ ;; Redundant call doesn't run.
+ (with-memoization (erc-track--shortened-names-get
+ '("apple" "banana" "cherries"))
+ (should-not 'run)
+ '("a" "b" "c"))
+ (should (equal erc-track--shortened-names (car results)))
+
+ ;; Change in environment or context forces run.
+ (with-temp-buffer
+ (with-memoization (erc-track--shortened-names-get
+ '("apple" "banana" "cherries"))
+ '("x" "y" "z")))
+ (should (and (integerp (car erc-track--shortened-names))
+ (/= (car erc-track--shortened-names) (caar results))))
+ (should (equal (cdr erc-track--shortened-names) '("x" "y" "z")))
+ (push erc-track--shortened-names results)
+
+ (with-memoization (erc-track--shortened-names-get
+ '("apple" "banana" "cherries"))
+ '("1" "2" "3"))
+ (should (and (integerp (car erc-track--shortened-names))
+ (/= (car erc-track--shortened-names) (caar results))))
+ (should (equal (cdr erc-track--shortened-names) '("1" "2" "3")))))
+
(ert-deftest erc-track--erc-faces-in ()
"`erc-faces-in' should pick up both 'face and 'font-lock-face properties."
(let ((str0 (copy-sequence "is bold"))
@@ -120,4 +156,134 @@
(should (erc-faces-in str0))
(should (erc-faces-in str1)) ))
+;; This simulates an alternating bold/non-bold [#c] in the mode-line,
+;; i.e., an `erc-modified-channels-alist' that vacillates between
+;;
+;; ((#<buffer #chan> 42 . erc-default-face))
+;;
+;; and
+;;
+;; ((#<buffer #chan> 42 erc-nick-default-face erc-default-face))
+;;
+;; This is a fairly typical scenario where consecutive messages
+;; feature speaker and addressee button highlighting and otherwise
+;; plain message bodies. This mapping of phony to real faces
+;; describes the picture in 5.6:
+;;
+;; `1': (erc-button erc-default-face) ; URL
+;; `2': (erc-nick-default-face erc-default-face) ; mention
+;; `3': erc-default-face ; body
+;; `_': (erc-nick-default-face erc-nick-default-face) ; speaker
+;;
+;; The `_' represents a commonly occurring face (a <speaker>) that's
+;; not present in either option's default (standard) value. It's a
+;; no-op from the POV of `erc-track-select-mode-line-face'.
+
+(ert-deftest erc-track-select-mode-line-face ()
+
+ ;; Observed (see key above).
+ (let ((erc-track-faces-priority-list '(1 2 3))
+ (erc-track-faces-normal-list '(1 2 3)))
+
+ (should (equal 2 (erc-track-select-mode-line-face 3 '(2 _ 3))))
+ (should (equal 2 (erc-track-select-mode-line-face 2 '(2 _ 3))))
+ (should (equal 3 (erc-track-select-mode-line-face 2 '(_ 3))))
+ (should (equal 2 (erc-track-select-mode-line-face 3 '(2 3))))
+ (should (equal 3 (erc-track-select-mode-line-face 2 '(3))))
+
+ (should (equal 1 (erc-track-select-mode-line-face 1 '(2 1 3))))
+ (should (equal 1 (erc-track-select-mode-line-face 1 '(1 3))))
+ (should (equal 1 (erc-track-select-mode-line-face 1 '(1 3 2))))
+ (should (equal 1 (erc-track-select-mode-line-face 1 '(3 1)))))
+
+ ;; When the current face outranks all new faces and doesn't appear
+ ;; among them, it's eligible to be replaced with a fellow "normal"
+ ;; from those new faces. But if it does appear among them, it's
+ ;; never replaced.
+ (let ((erc-track-faces-priority-list '(a b))
+ (erc-track-faces-normal-list '(a b)))
+
+ (should (equal 'a (erc-track-select-mode-line-face 'a '(b a))))
+ (should (equal 'a (erc-track-select-mode-line-face 'a '(a b))))
+ (should (equal 'a (erc-track-select-mode-line-face 'b '(b a))))
+ (should (equal 'a (erc-track-select-mode-line-face 'b '(a b))))
+
+ (should (equal 'a (erc-track-select-mode-line-face 'b '(a))))
+ (should (equal 'b (erc-track-select-mode-line-face 'a '(b)))))
+
+ ;; The ordering of the "normal" list doesn't matter.
+ (let ((erc-track-faces-priority-list '(a b))
+ (erc-track-faces-normal-list '(b a)))
+
+ (should (equal 'a (erc-track-select-mode-line-face 'a '(b a))))
+ (should (equal 'a (erc-track-select-mode-line-face 'a '(a b))))
+ (should (equal 'a (erc-track-select-mode-line-face 'b '(b a))))
+ (should (equal 'a (erc-track-select-mode-line-face 'b '(a b))))))
+
+(defun erc-track-tests--select-mode-line-face (ranked normals cases)
+ (setq normals (map-into (mapcar (lambda (f) (cons f t)) normals)
+ '(hash-table :test equal)))
+ (pcase-dolist (`(,want ,cur-face ,new-faces) cases)
+
+ (ert-info ((format "Observed: {cur: %S, new: %S, want: %S}"
+ cur-face new-faces want))
+ (setq new-faces (cons (map-into
+ (mapcar (lambda (f) (cons f t)) new-faces)
+ '(hash-table :test equal))
+ (reverse new-faces)))
+ (should (equal want (funcall #'erc-track--select-mode-line-face
+ cur-face new-faces ranked normals))))))
+
+;; The main difference between these variants is that with the above,
+;; when given alternating lines like
+;;
+;; CUR NEW CHOICE
+;; text (mention $speaker text) => mention
+;; mention ($speaker text) => text
+;;
+;; we see the effect of alternating faces in the indicator. But when
+;; given consecutive lines with a similar composition, like
+;;
+;; text (mention $speaker text) => mention
+;; text (mention $speaker text) => mention
+;;
+;; we lose the effect. With the variant below, we get
+;;
+;; text (mention $speaker text) => mention
+;; text (mention $speaker text) => text
+;;
+
+(ert-deftest erc-track--select-mode-line-face ()
+ (should-not erc-track-ignore-normal-contenders-p)
+
+ ;; These are the same test cases from the previous test. The syntax
+ ;; is (expected cur-face new-faces).
+ (erc-track-tests--select-mode-line-face
+ '(1 2 3) '(1 2 3)
+ '((2 3 (2 _ 3))
+ (3 2 (2 _ 3))
+ (3 2 (_ 3))
+ (2 3 (2 3))
+ (3 2 (3))
+ (2 1 (2 1 3))
+ (3 1 (1 3))
+ (2 1 (1 3 2))
+ (3 1 (3 1))))
+
+ (erc-track-tests--select-mode-line-face
+ '(a b) '(a b)
+ '((b a (b a))
+ (b a (a b))
+ (a b (b a))
+ (a b (a b))
+ (a b (a))
+ (b a (b))))
+
+ (erc-track-tests--select-mode-line-face
+ '(a b) '(b a)
+ '((b a (b a))
+ (b a (a b))
+ (a b (b a))
+ (a b (a b)))))
+
;;; erc-track-tests.el ends here
diff --git a/test/lisp/erc/resources/base/assoc/bouncer-history/barnet.eld b/test/lisp/erc/resources/base/assoc/bouncer-history/barnet.eld
index 35a9a570b6d..060f4178723 100644
--- a/test/lisp/erc/resources/base/assoc/bouncer-history/barnet.eld
+++ b/test/lisp/erc/resources/base/assoc/bouncer-history/barnet.eld
@@ -17,7 +17,7 @@
(0 ":irc.barnet.org 266 tester 3 3 :Current global users 3, max 3")
(0 ":irc.barnet.org 422 tester :MOTD File is missing"))
-((mode-user 3.2 "MODE tester +i")
+((mode-user 10 "MODE tester +i")
;; No mode answer ^
(0 ":irc.znc.in 306 tester :You have been marked as being away")
(0 ":tester!~u@xrir8fpe4d7ak.irc JOIN #chan")
@@ -34,7 +34,7 @@
(0 ":irc.barnet.org NOTICE tester :[07:00:01] This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect.")
(0 ":irc.barnet.org 305 tester :You are no longer marked as being away"))
-((mode 6 "MODE #chan")
+((mode 10 "MODE #chan")
(0 ":irc.barnet.org 324 tester #chan +nt")
(0 ":irc.barnet.org 329 tester #chan 1619593200")
(0.25 ":joe!~u@svpn88yjcdj42.irc PRIVMSG #chan :mike: But, in defense, by mercy, 'tis most just.")
diff --git a/test/lisp/erc/resources/base/assoc/bouncer-history/foonet.eld b/test/lisp/erc/resources/base/assoc/bouncer-history/foonet.eld
index f34ae02f4e4..ecde8adaec4 100644
--- a/test/lisp/erc/resources/base/assoc/bouncer-history/foonet.eld
+++ b/test/lisp/erc/resources/base/assoc/bouncer-history/foonet.eld
@@ -17,7 +17,7 @@
(0 ":irc.foonet.org 266 tester 3 3 :Current global users 3, max 3")
(0 ":irc.foonet.org 422 tester :MOTD File is missing"))
-((mode-user 3.2 "MODE tester +i")
+((mode-user 10 "MODE tester +i")
;; No mode answer ^
(0 ":irc.znc.in 306 tester :You have been marked as being away")
(0 ":tester!~u@nvfhxvqm92rm6.irc JOIN #chan")
@@ -39,7 +39,7 @@
(0 ":irc.foonet.org NOTICE tester :[07:00:32] This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect.")
(0 ":irc.foonet.org 305 tester :You are no longer marked as being away"))
-((mode 6 "MODE #chan")
+((mode 10 "MODE #chan")
(0 ":irc.foonet.org 324 tester #chan +nt")
(0 ":irc.foonet.org 329 tester #chan 1619593200")
(0.9 ":alice!~u@svpn88yjcdj42.irc PRIVMSG #chan :bob: Grows, lives, and dies, in single blessedness.")
diff --git a/test/lisp/erc/resources/base/assoc/bumped/again.eld b/test/lisp/erc/resources/base/assoc/bumped/again.eld
index ab3c7b06214..aef164b6237 100644
--- a/test/lisp/erc/resources/base/assoc/bumped/again.eld
+++ b/test/lisp/erc/resources/base/assoc/bumped/again.eld
@@ -1,10 +1,10 @@
;; -*- mode: lisp-data; -*-
-((nick 1 "NICK tester"))
-((user 1 "USER user 0 * :tester")
+((nick 10 "NICK tester"))
+((user 10 "USER user 0 * :tester")
(0.0 ":irc.foonet.org 433 * tester :Nickname is reserved by a different account")
(0.0 ":irc.foonet.org FAIL NICK NICKNAME_RESERVED tester :Nickname is reserved by a different account"))
-((nick 3 "NICK tester`")
+((nick 10 "NICK tester`")
(0.1 ":irc.foonet.org 001 tester` :Welcome to the foonet IRC Network tester`")
(0.0 ":irc.foonet.org 002 tester` :Your host is irc.foonet.org, running version oragono-2.6.1-937b9b02368748e5")
(0.0 ":irc.foonet.org 003 tester` :This server was created Fri, 24 Sep 2021 01:38:36 UTC")
@@ -21,10 +21,10 @@
(0.2 ":irc.foonet.org 266 tester` 3 3 :Current global users 3, max 3")
(0.0 ":irc.foonet.org 422 tester` :MOTD File is missing"))
-((mode-user 3.2 "MODE tester` +i")
+((mode-user 10 "MODE tester` +i")
(0.0 ":irc.foonet.org 221 tester` +i")
(0.0 ":irc.foonet.org NOTICE tester` :This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect."))
-((privmsg 42.6 "PRIVMSG NickServ :IDENTIFY tester changeme")
+((privmsg 10 "PRIVMSG NickServ :IDENTIFY tester changeme")
(0.01 ":tester`!~u@rpaau95je67ci.irc NICK tester")
(0.0 ":NickServ!NickServ@localhost NOTICE tester :You're now logged in as tester"))
diff --git a/test/lisp/erc/resources/base/assoc/bumped/foisted.eld b/test/lisp/erc/resources/base/assoc/bumped/foisted.eld
index 5c36e58d9d3..0f7aadac564 100644
--- a/test/lisp/erc/resources/base/assoc/bumped/foisted.eld
+++ b/test/lisp/erc/resources/base/assoc/bumped/foisted.eld
@@ -1,6 +1,6 @@
;; -*- mode: lisp-data; -*-
-((nick 1 "NICK tester"))
-((user 1 "USER user 0 * :tester")
+((nick 10 "NICK tester"))
+((user 10 "USER user 0 * :tester")
(0.0 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester")
(0.0 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version oragono-2.6.1-937b9b02368748e5")
(0.0 ":irc.foonet.org 003 tester :This server was created Fri, 24 Sep 2021 01:38:36 UTC")
@@ -17,14 +17,14 @@
(0.0 ":irc.foonet.org 266 tester 3 3 :Current global users 3, max 3")
(0.0 ":irc.foonet.org 422 tester :MOTD File is missing"))
-((mode-user 1.2 "MODE tester +i")
+((mode-user 10 "MODE tester +i")
(0.0 ":irc.foonet.org 221 tester +i")
(0.0 ":irc.foonet.org NOTICE tester :This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect."))
-((privmsg 17.21 "PRIVMSG bob :hi")
+((privmsg 10 "PRIVMSG bob :hi")
(0.02 ":bob!~u@ecnnh95wr67pv.net PRIVMSG tester :hola")
(0.01 ":bob!~u@ecnnh95wr67pv.net PRIVMSG tester :how r u?"))
-((quit 18.19 "QUIT :" quit)
+((quit 10 "QUIT :" quit)
(0.01 ":tester!~u@rpaau95je67ci.irc QUIT :Quit: " quit))
((drop 1 DROP))
diff --git a/test/lisp/erc/resources/base/assoc/bumped/refoisted.eld b/test/lisp/erc/resources/base/assoc/bumped/refoisted.eld
index 33e4168ac46..63366d3f576 100644
--- a/test/lisp/erc/resources/base/assoc/bumped/refoisted.eld
+++ b/test/lisp/erc/resources/base/assoc/bumped/refoisted.eld
@@ -1,6 +1,6 @@
;; -*- mode: lisp-data; -*-
-((nick 1 "NICK tester"))
-((user 1 "USER user 0 * :tester")
+((nick 10 "NICK tester"))
+((user 10 "USER user 0 * :tester")
(0.1 ":irc.foonet.org 001 dummy :Welcome to the foonet IRC Network dummy")
(0.0 ":irc.foonet.org 002 dummy :Your host is irc.foonet.org, running version oragono-2.6.1-937b9b02368748e5")
(0.0 ":irc.foonet.org 003 dummy :This server was created Fri, 24 Sep 2021 01:38:36 UTC")
@@ -22,10 +22,10 @@
(0.01 ":bob!~u@ecnnh95wr67pv.net PRIVMSG dummy :back?")
)
-((mode-user 1.2 "MODE dummy +i")
+((mode-user 10 "MODE dummy +i")
(0.0 ":irc.foonet.org 221 dummy +i")
(0.0 ":irc.foonet.org NOTICE dummy :This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect."))
-((renick 42.6 "NICK tester")
+((renick 10 "NICK tester")
(0.01 ":dummy!~u@rpaau95je67ci.irc NICK tester")
(0.0 ":NickServ!NickServ@localhost NOTICE dummy :You're now logged in as tester"))
diff --git a/test/lisp/erc/resources/base/assoc/multi-net/barnet.eld b/test/lisp/erc/resources/base/assoc/multi-net/barnet.eld
index c62a22a11c7..4c2b1d61e24 100644
--- a/test/lisp/erc/resources/base/assoc/multi-net/barnet.eld
+++ b/test/lisp/erc/resources/base/assoc/multi-net/barnet.eld
@@ -1,7 +1,7 @@
;; -*- mode: lisp-data; -*-
-((pass 1 "PASS :changeme"))
-((nick 1 "NICK tester"))
-((user 1 "USER user 0 * :tester")
+((pass 10 "PASS :changeme"))
+((nick 10 "NICK tester"))
+((user 10 "USER user 0 * :tester")
(0 ":irc.barnet.org 001 tester :Welcome to the barnet IRC Network tester")
(0 ":irc.barnet.org 002 tester :Your host is irc.barnet.org, running version oragono-2.6.0-7481bf0385b95b16")
(0 ":irc.barnet.org 003 tester :This server was created Tue, 04 May 2021 05:06:19 UTC")
@@ -18,16 +18,16 @@
(0 ":irc.barnet.org 266 tester 3 3 :Current global users 3, max 3")
(0 ":irc.barnet.org 422 tester :MOTD File is missing"))
-((mode-user 8 "MODE tester +i")
+((mode-user 10 "MODE tester +i")
(0 ":irc.barnet.org 221 tester +i")
(0 ":irc.barnet.org NOTICE tester :This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect."))
-((join 2 "JOIN #chan")
+((join 10 "JOIN #chan")
(0 ":tester!~u@jnu48g2wrycbw.irc JOIN #chan")
(0 ":irc.barnet.org 353 tester = #chan :@mike joe tester")
(0 ":irc.barnet.org 366 tester #chan :End of NAMES list"))
-((mode 2 "MODE #chan")
+((mode 10 "MODE #chan")
(0 ":irc.barnet.org 324 tester #chan +nt")
(0 ":irc.barnet.org 329 tester #chan 1620104779")
(0.1 ":mike!~u@kd7gmjbnbkn8c.irc PRIVMSG #chan :tester, welcome!")
diff --git a/test/lisp/erc/resources/base/assoc/multi-net/foonet.eld b/test/lisp/erc/resources/base/assoc/multi-net/foonet.eld
index f30b7deca11..bfa324642ce 100644
--- a/test/lisp/erc/resources/base/assoc/multi-net/foonet.eld
+++ b/test/lisp/erc/resources/base/assoc/multi-net/foonet.eld
@@ -1,7 +1,7 @@
;; -*- mode: lisp-data; -*-
-((pass 1 "PASS :changeme"))
-((nick 1 "NICK tester"))
-((user 1 "USER user 0 * :tester")
+((pass 10 "PASS :changeme"))
+((nick 10 "NICK tester"))
+((user 10 "USER user 0 * :tester")
(0 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester")
(0 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version oragono-2.6.0-7481bf0385b95b16")
(0 ":irc.foonet.org 003 tester :This server was created Tue, 04 May 2021 05:06:18 UTC")
@@ -18,16 +18,16 @@
(0 ":irc.foonet.org 266 tester 3 3 :Current global users 3, max 3")
(0 ":irc.foonet.org 422 tester :MOTD File is missing"))
-((mode-user 8 "MODE tester +i")
+((mode-user 10 "MODE tester +i")
(0 ":irc.foonet.org 221 tester +i")
(0 ":irc.foonet.org NOTICE tester :This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect."))
-((join 2 "JOIN #chan")
+((join 10 "JOIN #chan")
(0 ":tester!~u@9g6b728983yd2.irc JOIN #chan")
(0 ":irc.foonet.org 353 tester = #chan :alice tester @bob")
(0 ":irc.foonet.org 366 tester #chan :End of NAMES list"))
-((mode 2 "MODE #chan")
+((mode 10 "MODE #chan")
(0 ":irc.foonet.org 324 tester #chan +nt")
(0 ":irc.foonet.org 329 tester #chan 1620104779")
(0.1 ":bob!~u@rz2v467q4rwhy.irc PRIVMSG #chan :tester, welcome!")
diff --git a/test/lisp/erc/resources/base/assoc/reconplay/foonet.eld b/test/lisp/erc/resources/base/assoc/reconplay/foonet.eld
index f916fea2374..15bcca2a623 100644
--- a/test/lisp/erc/resources/base/assoc/reconplay/foonet.eld
+++ b/test/lisp/erc/resources/base/assoc/reconplay/foonet.eld
@@ -1,5 +1,5 @@
;; -*- mode: lisp-data; -*-
-((pass 1 "PASS :changeme"))
+((pass 10 "PASS :changeme"))
((nick 1 "NICK tester"))
((user 1 "USER user 0 * :tester")
(0.0 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester")
diff --git a/test/lisp/erc/resources/base/display-message/multibuf.eld b/test/lisp/erc/resources/base/display-message/multibuf.eld
new file mode 100644
index 00000000000..424a687e749
--- /dev/null
+++ b/test/lisp/erc/resources/base/display-message/multibuf.eld
@@ -0,0 +1,45 @@
+;; -*- mode: lisp-data; -*-
+((nick 10 "NICK tester"))
+((user 10 "USER user 0 * :tester")
+ (0.00 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester")
+ (0.01 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version ergo-v2.11.1")
+ (0.01 ":irc.foonet.org 003 tester :This server was created Sat, 14 Oct 2023 16:08:20 UTC")
+ (0.02 ":irc.foonet.org 004 tester irc.foonet.org ergo-v2.11.1 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0.00 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# CHATHISTORY=1000 ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX :are supported by this server")
+ (0.01 ":irc.foonet.org 005 tester KICKLEN=390 MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=foonet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8ONLY WHOX :are supported by this server")
+ (0.01 ":irc.foonet.org 005 tester draft/CHATHISTORY=1000 :are supported by this server")
+ (0.00 ":irc.foonet.org 251 tester :There are 0 users and 5 invisible on 1 server(s)")
+ (0.00 ":irc.foonet.org 252 tester 0 :IRC Operators online")
+ (0.00 ":irc.foonet.org 253 tester 0 :unregistered connections")
+ (0.00 ":irc.foonet.org 254 tester 2 :channels formed")
+ (0.00 ":irc.foonet.org 255 tester :I have 5 clients and 0 servers")
+ (0.00 ":irc.foonet.org 265 tester 5 5 :Current local users 5, max 5")
+ (0.02 ":irc.foonet.org 266 tester 5 5 :Current global users 5, max 5")
+ (0.01 ":irc.foonet.org 422 tester :MOTD File is missing")
+ (0.00 ":irc.foonet.org 221 tester +i")
+ (0.01 ":irc.foonet.org NOTICE tester :This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect."))
+
+((mode 10 "MODE tester +i")
+ (0.00 ":irc.foonet.org 221 tester +i"))
+
+((join 10 "JOIN #chan")
+ (0.03 ":tester!~u@rdjcgiwfuwqmc.irc JOIN #chan")
+ (0.03 ":irc.foonet.org 353 tester = #chan :@fsbot bob alice dummy tester")
+ (0.01 ":irc.foonet.org 366 tester #chan :End of NAMES list")
+ (0.00 ":bob!~u@uee7kge7ua5sy.irc PRIVMSG #chan :tester, welcome!")
+ (0.01 ":alice!~u@uee7kge7ua5sy.irc PRIVMSG #chan :tester, welcome!"))
+
+((mode 10 "MODE #chan")
+ (0.01 ":bob!~u@uee7kge7ua5sy.irc PRIVMSG #chan :alice: Persuade this rude wretch willingly to die.")
+ (0.01 ":irc.foonet.org 324 tester #chan +Cnt")
+ (0.01 ":irc.foonet.org 329 tester #chan 1697299707")
+ (0.03 ":alice!~u@uee7kge7ua5sy.irc PRIVMSG #chan :bob: It might be yours or hers, for aught I know.")
+ (0.07 ":bob!~u@uee7kge7ua5sy.irc PRIVMSG #chan :Would all themselves laugh mortal.")
+ (0.04 ":dummy!~u@rdjcgiwfuwqmc.irc PRIVMSG tester :hi")
+ (0.06 ":bob!~u@uee7kge7ua5sy.irc PRIVMSG #chan :alice: It hath pleased the devil drunkenness to give place to the devil wrath; one unperfectness shows me another, to make me frankly despise myself.")
+ (0.05 ":dummy!~u@rdjcgiwfuwqmc.irc QUIT :Quit: \2ERC\2 5.x (IRC client for GNU Emacs)")
+ (0.08 ":alice!~u@uee7kge7ua5sy.irc PRIVMSG #chan :You speak of him when he was less furnished than now he is with that which makes him both without and within."))
+
+((quit 10 "QUIT :\2ERC\2")
+ (0.04 ":tester!~u@rdjcgiwfuwqmc.irc QUIT :Quit: \2ERC\2 5.x (IRC client for GNU Emacs)")
+ (0.02 "ERROR :Quit: \2ERC\2 5.x (IRC client for GNU Emacs)"))
diff --git a/test/lisp/erc/resources/base/display-message/statusmsg.eld b/test/lisp/erc/resources/base/display-message/statusmsg.eld
new file mode 100644
index 00000000000..7c42117080c
--- /dev/null
+++ b/test/lisp/erc/resources/base/display-message/statusmsg.eld
@@ -0,0 +1,47 @@
+;; -*- mode: lisp-data; -*-
+((nick 10 "NICK tester"))
+((user 10 "USER tester 0 * :tester")
+ (0.00 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester")
+ (0.02 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version ergo-v2.11.1")
+ (0.01 ":irc.foonet.org 003 tester :This server was created Thu, 07 Dec 2023 08:04:35 UTC")
+ (0.00 ":irc.foonet.org 004 tester irc.foonet.org ergo-v2.11.1 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0.00 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# CHATHISTORY=1000 ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX :are supported by this server")
+ (0.01 ":irc.foonet.org 005 tester KICKLEN=390 MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=foonet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8ONLY WHOX :are supported by this server")
+ (0.01 ":irc.foonet.org 005 tester draft/CHATHISTORY=1000 :are supported by this server")
+ (0.00 ":irc.foonet.org 251 tester :There are 0 users and 4 invisible on 1 server(s)")
+ (0.00 ":irc.foonet.org 252 tester 0 :IRC Operators online")
+ (0.00 ":irc.foonet.org 253 tester 0 :unregistered connections")
+ (0.00 ":irc.foonet.org 254 tester 2 :channels formed")
+ (0.00 ":irc.foonet.org 255 tester :I have 4 clients and 0 servers")
+ (0.02 ":irc.foonet.org 265 tester 4 5 :Current local users 4, max 5")
+ (0.00 ":irc.foonet.org 266 tester 4 5 :Current global users 4, max 5")
+ (0.00 ":irc.foonet.org 422 tester :MOTD File is missing")
+ (0.00 ":irc.foonet.org 221 tester +i")
+ (0.00 ":irc.foonet.org NOTICE tester :This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect."))
+
+((mode-tester 10 "MODE tester +i"))
+
+((join-mine 10 "JOIN #mine")
+ (0.01 ":irc.foonet.org 221 tester +i")
+ (0.00 ":tester!~u@2jv6nwu4af69s.irc JOIN #mine")
+ (0.02 ":irc.foonet.org 353 tester = #mine :@tester +dummy")
+ (0.01 ":irc.foonet.org 366 tester #mine :End of NAMES list"))
+
+((mode-mine 10 "MODE #mine")
+ (0.00 ":irc.foonet.org 324 tester #mine +Cnt")
+ (0.02 ":irc.foonet.org 329 tester #mine 1702026418")
+ (0.04 ":dummy!~u@2jv6nwu4af69s.irc PRIVMSG +#mine :hello")
+ (0.03 ":dummy!~u@2jv6nwu4af69s.irc PRIVMSG +#mine :there")
+ (0.05 ":dummy!~u@2jv6nwu4af69s.irc PRIVMSG +#mine :\1ACTION sad\1")
+ (0.03 ":dummy!~u@2jv6nwu4af69s.irc PRIVMSG +#mine :\1ACTION glad\1"))
+
+((privmsg-statusmsg 10 "PRIVMSG +#mine :howdy"))
+((privmsg-statusmsg-action 10 "PRIVMSG +#mine :tenderfoot")
+ ;; These are simulated "echoed messages"
+ (0.05 ":tester!~u@2jv6nwu4af69s.irc PRIVMSG +#mine :\1ACTION mad\1")
+ (0.05 ":tester!~u@2jv6nwu4af69s.irc PRIVMSG +#mine :\1ACTION chad\1"))
+
+((privmsg-prefixed 10 "PRIVMSG #mine :\1ACTION ready\1")
+ (0.04 ":dummy!~u@2jv6nwu4af69s.irc PRIVMSG +#mine :okie")
+ (0.05 ":dummy!~u@2jv6nwu4af69s.irc PRIVMSG +#mine :\1ACTION dokie\1")
+ (0.04 ":dummy!~u@2jv6nwu4af69s.irc PRIVMSG #mine :\1ACTION out\1"))
diff --git a/test/lisp/erc/resources/base/flood/soju.eld b/test/lisp/erc/resources/base/flood/soju.eld
index 05266ca9411..9e936499a2d 100644
--- a/test/lisp/erc/resources/base/flood/soju.eld
+++ b/test/lisp/erc/resources/base/flood/soju.eld
@@ -8,7 +8,7 @@
(0.0 ":soju.im 005 tester CHATHISTORY=1000 CASEMAPPING=ascii NETWORK=Soju :are supported")
(0.0 ":soju.im 422 tester :No MOTD"))
-((mode 1 "MODE tester +i")
+((mode 10 "MODE tester +i")
(0.0 ":tester!tester@10.0.2.100 JOIN #chan/foonet")
(0.25 ":soju.im 331 tester #chan/foonet :No topic is set")
(0.0 ":soju.im 353 tester = #chan/foonet :@bob/foonet alice/foonet tester")
diff --git a/test/lisp/erc/resources/base/local-modules/first.eld b/test/lisp/erc/resources/base/local-modules/first.eld
index f9181a80fb7..4e923270e24 100644
--- a/test/lisp/erc/resources/base/local-modules/first.eld
+++ b/test/lisp/erc/resources/base/local-modules/first.eld
@@ -1,7 +1,7 @@
;; -*- mode: lisp-data; -*-
((cap 10 "CAP REQ :sasl"))
-((nick 1 "NICK tester"))
-((user 1 "USER tester 0 * :tester"))
+((nick 10 "NICK tester"))
+((user 10 "USER tester 0 * :tester"))
((authenticate 5 "AUTHENTICATE PLAIN")
(0.0 ":irc.foonet.org CAP * ACK sasl")
@@ -11,7 +11,7 @@
(0.0 ":irc.foonet.org 900 * * tester :You are now logged in as tester")
(0.01 ":irc.foonet.org 903 * :Authentication successful"))
-((cap 3.2 "CAP END")
+((cap 10 "CAP END")
(0.0 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester")
(0.0 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version ergo-v2.8.0")
(0.2 ":irc.foonet.org 003 tester :This server was created Sun, 20 Nov 2022 23:10:36 UTC")
diff --git a/test/lisp/erc/resources/base/local-modules/second.eld b/test/lisp/erc/resources/base/local-modules/second.eld
index a96103b2aa1..5823d63b874 100644
--- a/test/lisp/erc/resources/base/local-modules/second.eld
+++ b/test/lisp/erc/resources/base/local-modules/second.eld
@@ -41,7 +41,7 @@
(0.07 ":alice!~u@2fzfcku68ehqa.irc PRIVMSG #chan :bob: To you that know them not. This to my mother.")
(0.00 ":bob!~u@2fzfcku68ehqa.irc PRIVMSG #chan :alice: Some enigma, some riddle: come, thy l'envoy; begin."))
-((quit 1 "QUIT :\2ERC\2")
+((quit 10 "QUIT :\2ERC\2")
(0.03 ":tester`!~u@u9iqi96sfwk9s.irc QUIT"))
((drop 0 DROP))
diff --git a/test/lisp/erc/resources/base/local-modules/third.eld b/test/lisp/erc/resources/base/local-modules/third.eld
index 19bdd6efcce..e24825c3217 100644
--- a/test/lisp/erc/resources/base/local-modules/third.eld
+++ b/test/lisp/erc/resources/base/local-modules/third.eld
@@ -37,7 +37,7 @@
(0.00 ":alice!~u@2fzfcku68ehqa.irc PRIVMSG #chan :bob: No remedy, my lord, when walls are so wilful to hear without warning.")
(0.01 ":bob!~u@2fzfcku68ehqa.irc PRIVMSG #chan :alice: Let our reciprocal vows be remembered. You have many opportunities to cut him off; if your will want not, time and place will be fruitfully offered. There is nothing done if he return the conqueror; then am I the prisoner, and his bed my gaol; from the loathed warmth whereof deliver me, and supply the place for your labor."))
-((quit 1 "QUIT :\2ERC\2")
+((quit 10 "QUIT :\2ERC\2")
(0.03 ":tester`!~u@u9iqi96sfwk9s.irc QUIT :Quit"))
((drop 0 DROP))
diff --git a/test/lisp/erc/resources/base/modes/chan-changed.eld b/test/lisp/erc/resources/base/modes/chan-changed.eld
new file mode 100644
index 00000000000..6cf6596b0b2
--- /dev/null
+++ b/test/lisp/erc/resources/base/modes/chan-changed.eld
@@ -0,0 +1,55 @@
+;; -*- mode: lisp-data; -*-
+((nick 10 "NICK tester"))
+((user 10 "USER user 0 * :tester")
+ (0.03 ":cadmium.libera.chat 001 tester :Welcome to the Libera.Chat Internet Relay Chat Network tester")
+ (0.02 ":cadmium.libera.chat 002 tester :Your host is cadmium.libera.chat[103.196.37.95/6697], running version solanum-1.0-dev")
+ (0.01 ":cadmium.libera.chat 003 tester :This server was created Wed Jan 25 2023 at 10:22:45 UTC")
+ (0.01 ":cadmium.libera.chat 004 tester cadmium.libera.chat solanum-1.0-dev DGMQRSZaghilopsuwz CFILMPQRSTbcefgijklmnopqrstuvz bkloveqjfI")
+ (0.00 ":cadmium.libera.chat 005 tester CALLERID=g WHOX ETRACE FNC SAFELIST ELIST=CMNTU KNOCK MONITOR=100 CHANTYPES=# EXCEPTS INVEX CHANMODES=eIbq,k,flj,CFLMPQRSTcgimnprstuz :are supported by this server")
+ (0.01 ":cadmium.libera.chat 005 tester CHANLIMIT=#:250 PREFIX=(ov)@+ MAXLIST=bqeI:100 MODES=4 NETWORK=Libera.Chat STATUSMSG=@+ CASEMAPPING=rfc1459 NICKLEN=16 MAXNICKLEN=16 CHANNELLEN=50 TOPICLEN=390 DEAF=D :are supported by this server")
+ (0.01 ":cadmium.libera.chat 005 tester TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,PRIVMSG:4,NOTICE:4,ACCEPT:,MONITOR: EXTBAN=$,ajrxz :are supported by this server")
+ (0.01 ":cadmium.libera.chat 251 tester :There are 70 users and 42996 invisible on 28 servers")
+ (0.02 ":cadmium.libera.chat 252 tester 38 :IRC Operators online")
+ (0.01 ":cadmium.libera.chat 253 tester 57 :unknown connection(s)")
+ (0.01 ":cadmium.libera.chat 254 tester 22912 :channels formed")
+ (0.01 ":cadmium.libera.chat 255 tester :I have 2499 clients and 1 servers")
+ (0.01 ":cadmium.libera.chat 265 tester 2499 4187 :Current local users 2499, max 4187")
+ (0.01 ":cadmium.libera.chat 266 tester 43066 51827 :Current global users 43066, max 51827")
+ (0.01 ":cadmium.libera.chat 250 tester :Highest connection count: 4188 (4187 clients) (319420 connections received)")
+ (0.01 ":cadmium.libera.chat 375 tester :- cadmium.libera.chat Message of the Day - ")
+ (0.01 ":cadmium.libera.chat 372 tester :- This server kindly provided by Mach Dilemma (www.m-d.net)")
+ (0.01 ":cadmium.libera.chat 372 tester :- Welcome to Libera Chat, the IRC network for")
+ (0.00 ":cadmium.libera.chat 372 tester :- Email: support@libera.chat")
+ (0.00 ":cadmium.libera.chat 376 tester :End of /MOTD command.")
+ (0.00 ":tester MODE tester :+Ziw"))
+
+((mode-tester 10 "MODE tester +i"))
+
+((join-chan 10 "JOIN #chan")
+ (0.09 ":tester!~tester@127.0.0.1 JOIN #chan"))
+
+((mode-chan 10 "MODE #chan")
+ (0.03 ":cadmium.libera.chat 353 tester = #chan :tester @Chad dummy")
+ (0.02 ":cadmium.libera.chat 366 tester #chan :End of /NAMES list.")
+ (0.00 ":cadmium.libera.chat 324 tester #chan +nt")
+ (0.01 ":cadmium.libera.chat 329 tester #chan 1621432263"))
+
+((privmsg-before 10 "PRIVMSG #chan :ready before")
+ (0.02 ":Chad!~u@ggpg6r3a68wak.irc PRIVMSG #chan before")
+ (0.00 ":Chad!~u@ggpg6r3a68wak.irc MODE #chan +Qu"))
+
+((privmsg-key 10 "PRIVMSG #chan :ready key")
+ (0.02 ":Chad!~u@ggpg6r3a68wak.irc PRIVMSG #chan :doing key")
+ (0.00 ":Chad!~u@ggpg6r3a68wak.irc MODE #chan +k hunter2"))
+
+((privmsg-limit 10 "PRIVMSG #chan :ready limit")
+ (0.02 ":Chad!~u@ggpg6r3a68wak.irc PRIVMSG #chan :doing limit")
+ (0.00 ":Chad!~u@ggpg6r3a68wak.irc MODE #chan +l 3"))
+
+((privmsg-drop 10 "PRIVMSG #chan :ready drop")
+ (0.02 ":Chad!~u@ggpg6r3a68wak.irc PRIVMSG #chan dropping")
+ (0.00 ":Chad!~u@ggpg6r3a68wak.irc MODE #chan -lu")
+ (0.00 ":Chad!~u@ggpg6r3a68wak.irc MODE #chan -Qk *")
+ (0.02 ":Chad!~u@ggpg6r3a68wak.irc PRIVMSG #chan after"))
+
+((drop 0 DROP))
diff --git a/test/lisp/erc/resources/base/netid/bouncer/barnet-drop.eld b/test/lisp/erc/resources/base/netid/bouncer/barnet-drop.eld
index 686a47f68a3..04959954c4f 100644
--- a/test/lisp/erc/resources/base/netid/bouncer/barnet-drop.eld
+++ b/test/lisp/erc/resources/base/netid/bouncer/barnet-drop.eld
@@ -22,14 +22,14 @@
(0 ":irc.znc.in 306 tester :You have been marked as being away")
(0 ":irc.barnet.org 305 tester :You are no longer marked as being away"))
-((join 1 "JOIN #chan")
+((join 10 "JOIN #chan")
(0 ":tester!~u@awyxgybtkx7uq.irc JOIN #chan")
(0 ":irc.barnet.org 353 tester = #chan :@joe mike tester")
(0 ":irc.barnet.org 366 tester #chan :End of NAMES list")
(0.1 ":joe!~u@awyxgybtkx7uq.irc PRIVMSG #chan :tester, welcome!")
(0 ":mike!~u@awyxgybtkx7uq.irc PRIVMSG #chan :tester, welcome!"))
-((mode 1 "MODE #chan")
+((mode 10 "MODE #chan")
(0 ":irc.barnet.org 324 tester #chan +nt")
(0 ":irc.barnet.org 329 tester #chan 1620805269")
(0.1 ":mike!~u@awyxgybtkx7uq.irc PRIVMSG #chan :joe: But you have outfaced them all.")
diff --git a/test/lisp/erc/resources/base/netid/bouncer/barnet.eld b/test/lisp/erc/resources/base/netid/bouncer/barnet.eld
index 204d01fef77..596383c2699 100644
--- a/test/lisp/erc/resources/base/netid/bouncer/barnet.eld
+++ b/test/lisp/erc/resources/base/netid/bouncer/barnet.eld
@@ -38,4 +38,4 @@
(0.05 ":joe!~u@awyxgybtkx7uq.irc PRIVMSG #chan :mike: As he regards his aged father's life.")
(0.05 ":mike!~u@awyxgybtkx7uq.irc PRIVMSG #chan :joe: It is a rupture that you may easily heal; and the cure of it not only saves your brother, but keeps you from dishonor in doing it."))
-((linger 1 LINGER))
+((linger 2 LINGER))
diff --git a/test/lisp/erc/resources/base/netid/bouncer/foonet-drop.eld b/test/lisp/erc/resources/base/netid/bouncer/foonet-drop.eld
index b99621cc311..d0445cd1dd5 100644
--- a/test/lisp/erc/resources/base/netid/bouncer/foonet-drop.eld
+++ b/test/lisp/erc/resources/base/netid/bouncer/foonet-drop.eld
@@ -1,5 +1,5 @@
;; -*- mode: lisp-data; -*-
-((pass 1 "PASS :foonet:changeme"))
+((pass 10 "PASS :foonet:changeme"))
((nick 1 "NICK tester"))
((user 1 "USER user 0 * :tester")
(0 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester")
@@ -22,14 +22,14 @@
(0 ":irc.znc.in 306 tester :You have been marked as being away")
(0 ":irc.foonet.org 305 tester :You are no longer marked as being away"))
-((join 1 "JOIN #chan")
+((join 10 "JOIN #chan")
(0 ":tester!~u@ertp7idh9jtgi.irc JOIN #chan")
(0 ":irc.foonet.org 353 tester = #chan :@alice bob tester")
(0 ":irc.foonet.org 366 tester #chan :End of NAMES list")
(0.1 ":alice!~u@ertp7idh9jtgi.irc PRIVMSG #chan :tester, welcome!")
(0 ":bob!~u@ertp7idh9jtgi.irc PRIVMSG #chan :tester, welcome!"))
-((mode 1 "MODE #chan")
+((mode 10 "MODE #chan")
(0 ":irc.foonet.org 324 tester #chan +nt")
(0 ":irc.foonet.org 329 tester #chan 1620805271")
(0.1 ":alice!~u@ertp7idh9jtgi.irc PRIVMSG #chan :bob: He cannot be heard of. Out of doubt he is transported.")
diff --git a/test/lisp/erc/resources/base/netid/bouncer/foonet.eld b/test/lisp/erc/resources/base/netid/bouncer/foonet.eld
index 4445350ca0c..2e1a3ac27da 100644
--- a/test/lisp/erc/resources/base/netid/bouncer/foonet.eld
+++ b/test/lisp/erc/resources/base/netid/bouncer/foonet.eld
@@ -43,4 +43,4 @@
(0.1 ":alice!~u@ertp7idh9jtgi.irc PRIVMSG #chan :bob: Orlando, my liege; the youngest son of Sir Rowland de Boys.")
(0.1 ":bob!~u@ertp7idh9jtgi.irc PRIVMSG #chan :alice: The ape is dead, and I must conjure him."))
-((linger 1 LINGER))
+((linger 2 LINGER))
diff --git a/test/lisp/erc/resources/base/reconnect/aborted-dupe.eld b/test/lisp/erc/resources/base/reconnect/aborted-dupe.eld
index 8e299ec44c0..35906f608b5 100644
--- a/test/lisp/erc/resources/base/reconnect/aborted-dupe.eld
+++ b/test/lisp/erc/resources/base/reconnect/aborted-dupe.eld
@@ -19,7 +19,7 @@
(-0.02 ":irc.foonet.org 266 tester 3 3 :Current global users 3, max 3")
(-0.02 ":irc.foonet.org 422 tester :MOTD File is missing"))
-((~mode-user 3.2 "MODE tester +i")
+((~mode-user 10 "MODE tester +i")
(-0.02 ":irc.foonet.org 221 tester +i")
(-0.02 ":irc.foonet.org NOTICE tester :This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect."))
diff --git a/test/lisp/erc/resources/base/reconnect/aborted.eld b/test/lisp/erc/resources/base/reconnect/aborted.eld
index 5c32070d85f..e3abcdf8415 100644
--- a/test/lisp/erc/resources/base/reconnect/aborted.eld
+++ b/test/lisp/erc/resources/base/reconnect/aborted.eld
@@ -18,7 +18,7 @@
(0 ":irc.foonet.org 266 tester 3 3 :Current global users 3, max 3")
(0 ":irc.foonet.org 422 tester :MOTD File is missing"))
-((mode-user 3.2 "MODE tester +i")
+((mode-user 10 "MODE tester +i")
(0 ":irc.foonet.org 221 tester +i")
(0 ":irc.foonet.org NOTICE tester :This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect."))
diff --git a/test/lisp/erc/resources/base/reconnect/options-again.eld b/test/lisp/erc/resources/base/reconnect/options-again.eld
index f1fcc439cc3..8a3264fda9c 100644
--- a/test/lisp/erc/resources/base/reconnect/options-again.eld
+++ b/test/lisp/erc/resources/base/reconnect/options-again.eld
@@ -32,13 +32,13 @@
(0 ":irc.foonet.org 353 tester = #spam :alice tester @bob")
(0 ":irc.foonet.org 366 tester #spam :End of NAMES list"))
-((~mode-chan 4 "MODE #chan")
+((~mode-chan 10 "MODE #chan")
(0 ":irc.foonet.org 324 tester #chan +nt")
(0 ":irc.foonet.org 329 tester #chan 1620104779")
(0.1 ":bob!~u@rz2v467q4rwhy.irc PRIVMSG #chan :alice: But, as it seems, did violence on herself.")
(0.1 ":alice!~u@rz2v467q4rwhy.irc PRIVMSG #chan :bob: Well, this is the forest of Arden."))
-((mode-spam 4 "MODE #spam")
+((mode-spam 20 "MODE #spam")
(0 ":irc.foonet.org 324 tester #spam +nt")
(0 ":irc.foonet.org 329 tester #spam 1620104779")
(0.1 ":bob!~u@rz2v467q4rwhy.irc PRIVMSG #spam :alice: Signior Iachimo will not from it. Pray, let us follow 'em.")
diff --git a/test/lisp/erc/resources/base/renick/queries/solo.eld b/test/lisp/erc/resources/base/renick/queries/solo.eld
index 12fa7d264e9..fa4c075adac 100644
--- a/test/lisp/erc/resources/base/renick/queries/solo.eld
+++ b/test/lisp/erc/resources/base/renick/queries/solo.eld
@@ -30,7 +30,7 @@
(0 ":irc.foonet.org NOTICE tester :[09:56:57] This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect.")
(0 ":irc.foonet.org 305 tester :You are no longer marked as being away"))
-((mode 1 "MODE #foo")
+((mode 10 "MODE #foo")
(0 ":irc.foonet.org 324 tester #foo +nt")
(0 ":irc.foonet.org 329 tester #foo 1622454985")
(0.1 ":alice!~u@gq7yjr7gsu7nn.irc PRIVMSG #foo :bob: Farewell, pretty lady: you must hold the credit of your father.")
diff --git a/test/lisp/erc/resources/base/renick/self/qual-chester.eld b/test/lisp/erc/resources/base/renick/self/qual-chester.eld
index 75b50fe68bd..a224e0451d7 100644
--- a/test/lisp/erc/resources/base/renick/self/qual-chester.eld
+++ b/test/lisp/erc/resources/base/renick/self/qual-chester.eld
@@ -18,7 +18,7 @@
(0 ":irc.foonet.org 266 chester 3 4 :Current global users 3, max 4")
(0 ":irc.foonet.org 422 chester :MOTD File is missing"))
-((mode-user 1.2 "MODE chester +i")
+((mode-user 10 "MODE chester +i")
(0 ":irc.foonet.org 221 chester +i")
(0 ":irc.foonet.org NOTICE chester :This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect."))
diff --git a/test/lisp/erc/resources/base/renick/self/qual-tester.eld b/test/lisp/erc/resources/base/renick/self/qual-tester.eld
index 25199226658..27061c65223 100644
--- a/test/lisp/erc/resources/base/renick/self/qual-tester.eld
+++ b/test/lisp/erc/resources/base/renick/self/qual-tester.eld
@@ -18,7 +18,7 @@
(0 ":irc.foonet.org 266 tester 4 4 :Current global users 4, max 4")
(0 ":irc.foonet.org 422 tester :MOTD File is missing"))
-((mode-user 1.2 "MODE tester +i")
+((mode-user 10 "MODE tester +i")
(0 ":irc.foonet.org 221 tester +i")
(0 ":irc.foonet.org NOTICE tester :This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect."))
diff --git a/test/lisp/erc/resources/base/reuse-buffers/channel/barnet.eld b/test/lisp/erc/resources/base/reuse-buffers/channel/barnet.eld
index efc2506fd6f..d106a45cf66 100644
--- a/test/lisp/erc/resources/base/reuse-buffers/channel/barnet.eld
+++ b/test/lisp/erc/resources/base/reuse-buffers/channel/barnet.eld
@@ -56,7 +56,7 @@
(0.1 ":mike!~u@wvys46tx8tpmk.irc PRIVMSG #chan :tester, welcome!")
(0 ":joe!~u@wvys46tx8tpmk.irc PRIVMSG #chan :tester, welcome!"))
-((mode 1 "MODE #chan")
+((mode 10 "MODE #chan")
(0 ":irc.barnet.org 324 tester #chan +nt")
(0 ":irc.barnet.org 329 tester #chan 1620205534")
(0.1 ":mike!~u@wvys46tx8tpmk.irc PRIVMSG #chan :joe: Chi non te vede, non te pretia.")
diff --git a/test/lisp/erc/resources/base/reuse-buffers/channel/foonet.eld b/test/lisp/erc/resources/base/reuse-buffers/channel/foonet.eld
index a11cfac2e73..603afa2fc3e 100644
--- a/test/lisp/erc/resources/base/reuse-buffers/channel/foonet.eld
+++ b/test/lisp/erc/resources/base/reuse-buffers/channel/foonet.eld
@@ -52,7 +52,7 @@
(0.1 ":alice!~u@yppdd5tt4admc.irc PRIVMSG #chan :tester, welcome!")
(0 ":bob!~u@yppdd5tt4admc.irc PRIVMSG #chan :tester, welcome!"))
-((mode 1 "MODE #chan")
+((mode 10 "MODE #chan")
(0 ":irc.foonet.org 324 tester #chan +nt")
(0 ":irc.foonet.org 329 tester #chan 1620205534")
(0.1 ":bob!~u@yppdd5tt4admc.irc PRIVMSG #chan :alice: Thou desirest me to stop in my tale against the hair.")
diff --git a/test/lisp/erc/resources/base/reuse-buffers/server/barnet.eld b/test/lisp/erc/resources/base/reuse-buffers/server/barnet.eld
index cc7aff10076..5b64a58c98f 100644
--- a/test/lisp/erc/resources/base/reuse-buffers/server/barnet.eld
+++ b/test/lisp/erc/resources/base/reuse-buffers/server/barnet.eld
@@ -1,7 +1,7 @@
;; -*- mode: lisp-data; -*-
-((pass 1 "PASS :barnet:changeme"))
-((nick 1 "NICK tester"))
-((user 2 "USER user 0 * :tester")
+((pass 10 "PASS :barnet:changeme"))
+((nick 10 "NICK tester"))
+((user 10 "USER user 0 * :tester")
(0 ":irc.barnet.org 001 tester :Welcome to the barnet IRC Network tester")
(0 ":irc.barnet.org 002 tester :Your host is irc.barnet.org, running version oragono-2.6.0-7481bf0385b95b16")
(0 ":irc.barnet.org 003 tester :This server was created Sun, 25 Apr 2021 11:28:28 UTC")
diff --git a/test/lisp/erc/resources/base/reuse-buffers/server/foonet.eld b/test/lisp/erc/resources/base/reuse-buffers/server/foonet.eld
index 3a846108466..260ff74c20c 100644
--- a/test/lisp/erc/resources/base/reuse-buffers/server/foonet.eld
+++ b/test/lisp/erc/resources/base/reuse-buffers/server/foonet.eld
@@ -1,7 +1,7 @@
;; -*- mode: lisp-data; -*-
-((pass 1 "PASS :foonet:changeme"))
-((nick 1 "NICK tester"))
-((user 1 "USER user 0 * :tester")
+((pass 10 "PASS :foonet:changeme"))
+((nick 10 "NICK tester"))
+((user 10 "USER user 0 * :tester")
(0 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester")
(0 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version oragono-2.6.0-7481bf0385b95b16")
(0 ":irc.foonet.org 003 tester :This server was created Sun, 25 Apr 2021 11:28:28 UTC")
diff --git a/test/lisp/erc/resources/base/send-message/noncommands.eld b/test/lisp/erc/resources/base/send-message/noncommands.eld
new file mode 100644
index 00000000000..ba210bfff6f
--- /dev/null
+++ b/test/lisp/erc/resources/base/send-message/noncommands.eld
@@ -0,0 +1,52 @@
+;; -*- mode: lisp-data; -*-
+((nick 10 "NICK tester"))
+((user 10 "USER user 0 * :tester")
+ (0.00 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester")
+ (0.01 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version ergo-v2.11.1")
+ (0.01 ":irc.foonet.org 003 tester :This server was created Sun, 12 Nov 2023 17:40:20 UTC")
+ (0.01 ":irc.foonet.org 004 tester irc.foonet.org ergo-v2.11.1 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0.00 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# CHATHISTORY=1000 ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX :are supported by this server")
+ (0.02 ":irc.foonet.org 005 tester KICKLEN=390 MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=foonet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8ONLY WHOX :are supported by this server")
+ (0.01 ":irc.foonet.org 005 tester draft/CHATHISTORY=1000 :are supported by this server")
+ (0.01 ":irc.foonet.org 251 tester :There are 0 users and 4 invisible on 1 server(s)")
+ (0.01 ":irc.foonet.org 252 tester 0 :IRC Operators online")
+ (0.01 ":irc.foonet.org 253 tester 0 :unregistered connections")
+ (0.01 ":irc.foonet.org 254 tester 2 :channels formed")
+ (0.01 ":irc.foonet.org 255 tester :I have 4 clients and 0 servers")
+ (0.01 ":irc.foonet.org 265 tester 4 4 :Current local users 4, max 4")
+ (0.01 ":irc.foonet.org 266 tester 4 4 :Current global users 4, max 4")
+ (0.02 ":irc.foonet.org 422 tester :MOTD File is missing")
+ (0.00 ":irc.foonet.org 221 tester +i")
+ (0.01 ":irc.foonet.org NOTICE tester :This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect."))
+
+((mode-tester 10 "MODE tester +i"))
+
+((join-chan 10 "JOIN #chan")
+ (0.00 ":irc.foonet.org 221 tester +i")
+ (0.01 ":tester!~u@ggpg6r3a68wak.irc JOIN #chan")
+ (0.03 ":irc.foonet.org 353 tester = #chan :@fsbot bob alice tester")
+ (0.01 ":irc.foonet.org 366 tester #chan :End of NAMES list")
+ (0.00 ":bob!~u@cjn7mjwx57gbi.irc PRIVMSG #chan :tester, welcome!")
+ (0.01 ":alice!~u@cjn7mjwx57gbi.irc PRIVMSG #chan :tester, welcome!"))
+
+((mode-chan 10 "MODE #chan")
+ (0.00 ":irc.foonet.org 324 tester #chan +Cnt")
+ (0.02 ":irc.foonet.org 329 tester #chan 1699810829")
+ (0.01 ":alice!~u@cjn7mjwx57gbi.irc PRIVMSG #chan :bob: To prove him false that says I love thee not.")
+ (0.02 ":bob!~u@cjn7mjwx57gbi.irc PRIVMSG #chan :alice: For hands, to do Rome service, are but vain."))
+
+((privmsg-action 10 "PRIVMSG #chan :\1ACTION sad\1")
+ (0.07 ":alice!~u@cjn7mjwx57gbi.irc PRIVMSG #chan :bob: Spotted, detested, and abominable."))
+
+((privmsg-me 10 "PRIVMSG #chan :/me sad")
+ (0.03 ":bob!~u@cjn7mjwx57gbi.irc PRIVMSG #chan :Marcus, my brother! 'tis sad Titus calls."))
+
+((privmsg-sv 10 "PRIVMSG #chan :I'm using ERC " (+ (not " ")) " with GNU Emacs")
+ (0.07 ":bob!~u@cjn7mjwx57gbi.irc PRIVMSG #chan :alice: You still wrangle with her, Boyet, and she strikes at the brow."))
+
+((privmsg-sm 10 "PRIVMSG #chan :I'm using the following modules: `erc-autojoin-mode', ")
+ (0.04 ":alice!~u@cjn7mjwx57gbi.irc PRIVMSG #chan :No, not till Thursday; there is time enough."))
+
+((quit 10 "QUIT :\2ERC\2")
+ (0.05 ":tester!~u@ggpg6r3a68wak.irc QUIT :Quit: \2ERC\2 5.x (IRC client for GNU Emacs)")
+ (0.02 "ERROR :Quit: \2ERC\2 5.x (IRC client for GNU Emacs)"))
diff --git a/test/lisp/erc/resources/base/commands/motd.eld b/test/lisp/erc/resources/commands/motd.eld
index 6d10ee122e2..6d10ee122e2 100644
--- a/test/lisp/erc/resources/base/commands/motd.eld
+++ b/test/lisp/erc/resources/commands/motd.eld
diff --git a/test/lisp/erc/resources/commands/squery.eld b/test/lisp/erc/resources/commands/squery.eld
new file mode 100644
index 00000000000..bcd176e515b
--- /dev/null
+++ b/test/lisp/erc/resources/commands/squery.eld
@@ -0,0 +1,31 @@
+;; -*- mode: lisp-data; -*-
+((nick 10 "NICK tester"))
+((user 10 "USER user 0 * :tester")
+ (0.07 ":ircnet.hostsailor.com 020 * :Please wait while we process your connection.")
+ (0.03 ":ircnet.hostsailor.com 001 tester :Welcome to the Internet Relay Network tester!~user@93.184.216.34")
+ (0.02 ":ircnet.hostsailor.com 002 tester :Your host is ircnet.hostsailor.com, running version 2.11.2p3+0PNv1.06")
+ (0.03 ":ircnet.hostsailor.com 003 tester :This server was created Thu May 20 2021 at 17:13:24 EDT")
+ (0.01 ":ircnet.hostsailor.com 004 tester ircnet.hostsailor.com 2.11.2p3+0PNv1.06 aoOirw abeiIklmnoOpqrRstv")
+ (0.00 ":ircnet.hostsailor.com 005 tester RFC2812 PREFIX=(ov)@+ CHANTYPES=#&!+ MODES=3 CHANLIMIT=#&!+:42 NICKLEN=15 TOPICLEN=255 KICKLEN=255 MAXLIST=beIR:64 CHANNELLEN=50 IDCHAN=!:5 CHANMODES=beIR,k,l,imnpstaqrzZ :are supported by this server")
+ (0.01 ":ircnet.hostsailor.com 005 tester PENALTY FNC EXCEPTS=e INVEX=I CASEMAPPING=ascii NETWORK=IRCnet :are supported by this server")
+ (0.01 ":ircnet.hostsailor.com 042 tester 0PNHANAWX :your unique ID")
+ (0.01 ":ircnet.hostsailor.com 251 tester :There are 18711 users and 2 services on 26 servers")
+ (0.01 ":ircnet.hostsailor.com 252 tester 63 :operators online")
+ (0.01 ":ircnet.hostsailor.com 253 tester 4 :unknown connections")
+ (0.01 ":ircnet.hostsailor.com 254 tester 10493 :channels formed")
+ (0.01 ":ircnet.hostsailor.com 255 tester :I have 933 users, 0 services and 1 servers")
+ (0.01 ":ircnet.hostsailor.com 265 tester 933 1328 :Current local users 933, max 1328")
+ (0.01 ":ircnet.hostsailor.com 266 tester 18711 25625 :Current global users 18711, max 25625")
+ (0.02 ":ircnet.hostsailor.com 375 tester :- ircnet.hostsailor.com Message of the Day - ")
+ (0.01 ":ircnet.hostsailor.com 372 tester :- 17/11/2023 3:08")
+ (0.02 ":ircnet.hostsailor.com 376 tester :End of MOTD command."))
+
+((mode 10 "MODE tester +i")
+ (0.00 ":ircnet.hostsailor.com NOTICE tester :Your connection is secure (SSL/TLS).")
+ (0.01 ":tester MODE tester :+i"))
+
+((squery 10 "SQUERY alis :help list")
+ (0.08 ":Alis@hub.uk NOTICE tester :Searches for a channel")
+ (0.01 ":Alis@hub.uk NOTICE tester :/SQUERY Alis LIST mask [-options]")
+ (0.04 ":Alis@hub.uk NOTICE tester :[...]")
+ (0.01 ":Alis@hub.uk NOTICE tester :See also: HELP EXAMPLES"))
diff --git a/test/lisp/erc/resources/commands/vhost.eld b/test/lisp/erc/resources/commands/vhost.eld
new file mode 100644
index 00000000000..42013198fbc
--- /dev/null
+++ b/test/lisp/erc/resources/commands/vhost.eld
@@ -0,0 +1,40 @@
+;; -*- mode: lisp-data; -*-
+((pass 10 "PASS :changeme"))
+((nick 10 "NICK tester"))
+((user 10 "USER user 0 * :tester")
+ (0 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester")
+ (0 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version oragono-2.6.0-7481bf0385b95b16")
+ (0 ":irc.foonet.org 003 tester :This server was created Tue, 04 May 2021 05:06:18 UTC")
+ (0 ":irc.foonet.org 004 tester irc.foonet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server")
+ (0 ":irc.foonet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=foonet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server")
+ (0 ":irc.foonet.org 005 tester draft/CHATHISTORY=100 :are supported by this server")
+ (0 ":irc.foonet.org 251 tester :There are 0 users and 3 invisible on 1 server(s)")
+ (0 ":irc.foonet.org 252 tester 0 :IRC Operators online")
+ (0 ":irc.foonet.org 253 tester 0 :unregistered connections")
+ (0 ":irc.foonet.org 254 tester 1 :channels formed")
+ (0 ":irc.foonet.org 255 tester :I have 3 clients and 0 servers")
+ (0 ":irc.foonet.org 265 tester 3 3 :Current local users 3, max 3")
+ (0 ":irc.foonet.org 266 tester 3 3 :Current global users 3, max 3")
+ (0 ":irc.foonet.org 422 tester :MOTD File is missing"))
+
+((mode-user 10 "MODE tester +i")
+ (0 ":irc.foonet.org 221 tester +i")
+ (0 ":irc.foonet.org NOTICE tester :This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect."))
+
+((join 10 "JOIN #chan")
+ (0 ":tester!~u@9g6b728983yd2.irc JOIN #chan")
+ (0 ":irc.foonet.org 353 tester = #chan :alice tester @bob")
+ (0 ":irc.foonet.org 366 tester #chan :End of NAMES list"))
+
+((mode-chan 10 "MODE #chan")
+ (0 ":irc.foonet.org 324 tester #chan +nt")
+ (0 ":irc.foonet.org 329 tester #chan 1620104779")
+ (0 ":bob!~u@rz2v467q4rwhy.irc PRIVMSG #chan :tester, welcome!")
+ (0 ":alice!~u@rz2v467q4rwhy.irc PRIVMSG #chan :tester, welcome!"))
+
+((vhost 10 "VHOST tester changeme")
+ (0 ":irc.foonet.org NOTICE tester :Setting your VHost: some.host.test.cc")
+ (0 ":irc.foonet.org 396 tester some.host.test.cc :is now your displayed host")
+ (0 ":bob!~u@rz2v467q4rwhy.irc PRIVMSG #chan :alice: But, as it seems, did violence on herself.")
+ (0 ":alice!~u@rz2v467q4rwhy.irc PRIVMSG #chan :bob: Well, this is the forest of Arden."))
diff --git a/test/lisp/erc/resources/dcc/chat/accept.eld b/test/lisp/erc/resources/dcc/chat/accept.eld
index a23e9580bcc..463f931d26f 100644
--- a/test/lisp/erc/resources/dcc/chat/accept.eld
+++ b/test/lisp/erc/resources/dcc/chat/accept.eld
@@ -17,7 +17,7 @@
(0 ":irc.foonet.org 266 tester 4 4 :Current global users 4, max 4")
(0 ":irc.foonet.org 422 tester :MOTD File is missing"))
-((mode-user 1.2 "MODE tester +i")
+((mode-user 10 "MODE tester +i")
;; No mode answer
(0 ":irc.foonet.org NOTICE tester :This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect.")
(0.2 ":dummy!~u@34n9brushbpj2.irc PRIVMSG tester :\C-aDCC CHAT chat 2130706433 " port "\C-a"))
diff --git a/test/lisp/erc/resources/erc-d/erc-d-i.el b/test/lisp/erc/resources/erc-d/erc-d-i.el
index 05302e4f0be..219ab6d63f0 100644
--- a/test/lisp/erc/resources/erc-d/erc-d-i.el
+++ b/test/lisp/erc/resources/erc-d/erc-d-i.el
@@ -1,6 +1,6 @@
;;; erc-d-i.el --- IRC helpers for ERC test server -*- lexical-binding: t -*-
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/erc/resources/erc-d/erc-d-t.el b/test/lisp/erc/resources/erc-d/erc-d-t.el
index 7b2adf4f07b..2dc8398198f 100644
--- a/test/lisp/erc/resources/erc-d/erc-d-t.el
+++ b/test/lisp/erc/resources/erc-d/erc-d-t.el
@@ -1,6 +1,6 @@
;;; erc-d-t.el --- ERT helpers for ERC test server -*- lexical-binding: t -*-
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -83,6 +83,8 @@ returning."
(ignore-errors (kill-buffer buf)))))
(sleep-for erc-d-t-cleanup-sleep-secs)))))
+(defvar erc-d-t--wait-message-prefix "Awaiting: ")
+
(defmacro erc-d-t-wait-for (max-secs msg &rest body)
"Wait for BODY to become non-nil.
Or signal error with MSG after MAX-SECS. When MAX-SECS is negative,
@@ -99,7 +101,7 @@ be desirable."
(let ((inverted (make-symbol "inverted"))
(time-out (make-symbol "time-out"))
(result (make-symbol "result")))
- `(ert-info ((concat "Awaiting: " ,msg))
+ `(ert-info ((concat erc-d-t--wait-message-prefix ,msg))
(let ((,time-out (abs ,max-secs))
(,inverted (< ,max-secs 0))
(,result ',result))
@@ -120,7 +122,8 @@ On failure, emit MSG."
(unless (or (stringp msg) (memq (car-safe msg) '(format concat)))
(push msg body)
(setq msg (prin1-to-string body)))
- `(erc-d-t-wait-for (- (abs ,max-secs)) ,msg (not (progn ,@body))))
+ `(let ((erc-d-t--wait-message-prefix "Sustaining: "))
+ (erc-d-t-wait-for (- (abs ,max-secs)) ,msg (not (progn ,@body)))))
(defun erc-d-t-search-for (timeout text &optional from on-success)
"Wait for TEXT to appear in current buffer before TIMEOUT secs.
@@ -154,6 +157,7 @@ ON-SUCCESS, is nonexistent. To reset, specify a FROM argument."
(let (positions)
(lambda (timeout text &optional reset-from)
(let* ((pos (cdr (assq (current-buffer) positions)))
+ (erc-d-t--wait-message-prefix (and (< timeout 0) "Sustaining: "))
(cb (lambda ()
(unless pos
(push (cons (current-buffer) (setq pos (make-marker)))
diff --git a/test/lisp/erc/resources/erc-d/erc-d-tests.el b/test/lisp/erc/resources/erc-d/erc-d-tests.el
index 0ae70087fd1..78f87399afb 100644
--- a/test/lisp/erc/resources/erc-d/erc-d-tests.el
+++ b/test/lisp/erc/resources/erc-d/erc-d-tests.el
@@ -1,6 +1,6 @@
;;; erc-d-tests.el --- tests for erc-d -*- lexical-binding: t -*-
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/erc/resources/erc-d/erc-d-u.el b/test/lisp/erc/resources/erc-d/erc-d-u.el
index e26fa8b47dd..11202f41112 100644
--- a/test/lisp/erc/resources/erc-d/erc-d-u.el
+++ b/test/lisp/erc/resources/erc-d/erc-d-u.el
@@ -1,6 +1,6 @@
;;; erc-d-u.el --- Helpers for ERC test server -*- lexical-binding: t -*-
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -74,6 +74,7 @@
(let ((hunks (erc-d-u-scan-e-sd info))
(pos (erc-d-u-scan-e-pos info)))
(or (and (erc-d-u-scan-d-hunks hunks)
+ (buffer-live-p (erc-d-u-scan-d-buf hunks))
(with-current-buffer (erc-d-u-scan-d-buf hunks)
(goto-char pos)
(condition-case _err
diff --git a/test/lisp/erc/resources/erc-d/erc-d.el b/test/lisp/erc/resources/erc-d/erc-d.el
index e9d880644d4..89701442ff6 100644
--- a/test/lisp/erc/resources/erc-d/erc-d.el
+++ b/test/lisp/erc/resources/erc-d/erc-d.el
@@ -1,6 +1,6 @@
;;; erc-d.el --- A dumb test server for ERC -*- lexical-binding: t -*-
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -254,7 +254,7 @@ return a replacement.")
(ending (process-get process :dialog-ending))
(dialog (make-erc-d-dialog :name name
:process process
- :queue (make-ring 5)
+ :queue (make-ring 10)
:exchanges (make-ring 10)
:match-handlers mat-h
:server-fqdn fqdn)))
@@ -292,33 +292,27 @@ With int SKIP, advance past that many exchanges."
(defvar erc-d--m-debug (getenv "ERC_D_DEBUG"))
-(defmacro erc-d--m (process format-string &rest args)
- "Output ARGS using FORMAT-STRING somewhere depending on context.
-PROCESS should be a client connection or a server network process."
- `(let ((format-string (if erc-d--m-debug
- (concat (format-time-string "%s.%N: ")
- ,format-string)
- ,format-string))
- (want-insert (and ,process erc-d--in-process))
- (buffer (process-buffer (process-get ,process :server))))
- (when (and want-insert (buffer-live-p buffer))
- (with-current-buffer buffer
- (goto-char (point-max))
- (insert (concat (format ,format-string ,@args) "\n"))))
- (when (or erc-d--m-debug (not want-insert))
- (message format-string ,@args))))
-
-(defmacro erc-d--log (process string &optional outbound)
- "Log STRING sent to (OUTBOUND) or received from PROCESS peer."
- `(let ((id (or (process-get ,process :log-id)
- (let ((port (erc-d-u--get-remote-port ,process)))
- (process-put ,process :log-id port)
- port)))
- (name (erc-d-dialog-name (process-get ,process :dialog))))
- (if ,outbound
- (erc-d--m process "-> %s:%s %s" name id ,string)
- (dolist (line (split-string ,string (process-get process :ending)))
- (erc-d--m process "<- %s:%s %s" name id line)))))
+(defun erc-d--m (process format-string &rest args)
+ "Output ARGS using FORMAT-STRING to PROCESS's buffer or elsewhere."
+ (when erc-d--m-debug
+ (setq format-string (concat (format-time-string "%s.%N: ") format-string)))
+ (let ((insertp (and process erc-d--in-process))
+ (buffer (and process (process-buffer (process-get process :server)))))
+ (when (and insertp (buffer-live-p buffer))
+ (princ (concat (apply #'format format-string args) "\n") buffer))
+ (when (or erc-d--m-debug (not insertp))
+ (apply #'message format-string args))))
+
+(defun erc-d--log (process string &optional outbound)
+ "Log STRING received from or OUTBOUND to PROCESS peer."
+ (let ((id (or (process-get process :log-id)
+ (let ((port (erc-d-u--get-remote-port process)))
+ (process-put process :log-id port) port)))
+ (name (erc-d-dialog-name (process-get process :dialog))))
+ (if outbound
+ (erc-d--m process "-> %s:%s %s" name id string)
+ (dolist (line (split-string string (process-get process :ending)))
+ (erc-d--m process "<- %s:%s %s" name id line)))))
(defun erc-d--log-process-event (server process msg)
(erc-d--m server "%s: %s" process (string-trim-right msg)))
@@ -463,7 +457,7 @@ including line delimiters."
;; Misc process properties:
;;
;; The server property `:dialog-dialogs' is an alist of (symbol
-;; . erc-d-u-scan-d) conses, each of which pairs a dialogs name with
+;; . erc-d-u-scan-d) conses, each of which pairs a dialog's name with
;; info on its read progress (described above in the Commentary).
;; This list is populated by `erc-d-run' at the start of each session.
;;
diff --git a/test/lisp/erc/resources/erc-d/resources/dynamic-barnet.eld b/test/lisp/erc/resources/erc-d/resources/dynamic-barnet.eld
index 4994e9c5503..e8feb2e6fd8 100644
--- a/test/lisp/erc/resources/erc-d/resources/dynamic-barnet.eld
+++ b/test/lisp/erc/resources/erc-d/resources/dynamic-barnet.eld
@@ -18,14 +18,14 @@
(0. ":irc.barnet.org 266 tester 3 3 :Current global users 3, max 3")
(0. ":irc.barnet.org 422 tester :MOTD File is missing"))
-((mode-user 1.2 "MODE tester +i")
+((mode-user 2 "MODE tester +i")
(0. ":irc.barnet.org 221 tester +Zi")
(0. ":irc.barnet.org 306 tester :You have been marked as being away")
(0 ":tester!~u@awyxgybtkx7uq.irc JOIN #chan")
(0 ":irc.barnet.org 353 joe = #chan :+joe!~joe@example.com @%+mike!~mike@example.org")
(0 ":irc.barnet.org 366 joe #chan :End of NAMES list"))
-((mode 1 "MODE #chan")
+((mode 3 "MODE #chan")
(0 ":irc.barnet.org 324 tester #chan +nt")
(0 ":irc.barnet.org 329 tester #chan 1620805269")
(0.1 ":joe!~u@awyxgybtkx7uq.irc PRIVMSG #chan :mike: Yes, a dozen; and as many to the vantage, as would store the world they played for.")
diff --git a/test/lisp/erc/resources/erc-d/resources/dynamic-foonet.eld b/test/lisp/erc/resources/erc-d/resources/dynamic-foonet.eld
index a47998e7d32..2db750e49da 100644
--- a/test/lisp/erc/resources/erc-d/resources/dynamic-foonet.eld
+++ b/test/lisp/erc/resources/erc-d/resources/dynamic-foonet.eld
@@ -17,14 +17,14 @@
(0. ":irc.foonet.org 266 tester 3 3 :Current global users 3, max 3")
(0. ":irc.foonet.org 422 tester :MOTD File is missing"))
-((mode-user 1.2 "MODE tester +i")
+((mode-user 4 "MODE tester +i")
(0. ":irc.foonet.org 221 tester +Zi")
(0. ":irc.foonet.org 306 tester :You have been marked as being away")
(0 ":tester!~u@awyxgybtkx7uq.irc JOIN #chan")
(0 ":irc.foonet.org 353 alice = #chan :+alice!~alice@example.com @%+bob!~bob@example.org")
(0 ":irc.foonet.org 366 alice #chan :End of NAMES list"))
-((mode 2 "MODE #chan")
+((mode 3 "MODE #chan")
(0 ":irc.foonet.org 324 tester #chan +nt")
(0 ":irc.foonet.org 329 tester #chan 1620805269")
(0.1 ":alice!~u@awyxgybtkx7uq.irc PRIVMSG #chan :bob: Yes, a dozen; and as many to the vantage, as would store the world they played for.")
diff --git a/test/lisp/erc/resources/erc-d/resources/linger.eld b/test/lisp/erc/resources/erc-d/resources/linger.eld
index 36c81a3af4b..e456370a800 100644
--- a/test/lisp/erc/resources/erc-d/resources/linger.eld
+++ b/test/lisp/erc/resources/erc-d/resources/linger.eld
@@ -20,14 +20,14 @@
(0 ":irc.example.org 266 tester 3 3 :Current global users 3, max 3")
(0 ":irc.example.org 422 tester :MOTD File is missing"))
-((mode-user 1.2 "MODE tester +i")
+((mode-user 2 "MODE tester +i")
(0 ":irc.example.org 221 tester +Zi")
(0 ":irc.example.org 306 tester :You have been marked as being away")
(0 ":tester!~tester@localhost JOIN #chan")
(0 ":irc.example.org 353 alice = #chan :+alice!~alice@example.com @%+bob!~bob@example.org")
(0 ":irc.example.org 366 alice #chan :End of NAMES list"))
-((mode-chan 1.2 "MODE #chan")
+((mode-chan 2 "MODE #chan")
(0 ":bob!~bob@example.org PRIVMSG #chan :hey"))
((linger 1.0 LINGER))
diff --git a/test/lisp/erc/resources/erc-d/resources/proxy-subprocess.el b/test/lisp/erc/resources/erc-d/resources/proxy-subprocess.el
index 541c222dc21..38ab9f3136a 100644
--- a/test/lisp/erc/resources/erc-d/resources/proxy-subprocess.el
+++ b/test/lisp/erc/resources/erc-d/resources/proxy-subprocess.el
@@ -1,6 +1,6 @@
;;; proxy-subprocess.el --- Example setup file for erc-d -*- lexical-binding: t; -*-
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/erc/resources/erc-scenarios-common.el b/test/lisp/erc/resources/erc-scenarios-common.el
index 972faa5c73f..0ec48d766ef 100644
--- a/test/lisp/erc/resources/erc-scenarios-common.el
+++ b/test/lisp/erc/resources/erc-scenarios-common.el
@@ -1,6 +1,6 @@
;;; erc-scenarios-common.el --- Common helpers for ERC scenarios -*- lexical-binding: t -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -61,6 +61,25 @@
;; always associated with the fake network FooNet, while nicks Joe and
;; Mike are always on BarNet. (Networks are sometimes downcased.)
;;
+;; Environment variables:
+;;
+;; `ERC_TESTS_GRAPHICAL': Internal variable to unskip those few tests
+;; capable of running consecutively while interactive on a graphical
+;; display. This triggers both the tests and the suite to commence
+;; with teardown activities normally skipped to allow for inspection
+;; while interactive. This is also handy when needing to quickly
+;; run `ert-results-rerun-test-at-point-debugging-errors' on a
+;; failing test because you don't have to go around hunting for and
+;; killing associated buffers and processes.
+;;
+;; `ERC_TESTS_GRAPHICAL_ALL': Currently targets a single "meta" test,
+;; `erc-scenarios-internal--run-interactive-all', that runs all
+;; tests tagged `:erc--graphical' in an interactive subprocess.
+;;
+;; `ERC_TESTS_SUBPROCESS': Used internally to detect nested tests.
+;;
+;; `ERC_D_DEBUG': Tells `erc-d' to emit debugging info to stderr.
+;;
;; XXX This file should *not* contain any test cases.
;;; Code:
@@ -91,6 +110,7 @@
(defvar erc-scenarios-common-dialog nil)
(defvar erc-scenarios-common-extra-teardown nil)
+(defvar erc-scenarios-common--graphical-p nil)
(defun erc-scenarios-common--add-silence ()
(advice-add #'erc-login :around #'erc-d-t-silence-around)
@@ -110,7 +130,11 @@
(eval-and-compile
(defun erc-scenarios-common--make-bindings (bindings)
- `((erc-d-u-canned-dialog-dir (expand-file-name
+ `((erc-scenarios-common--graphical-p
+ (and (or erc-scenarios-common--graphical-p
+ (memq :erc--graphical (ert-test-tags (ert-running-test))))
+ (not (and noninteractive (ert-skip "Interactive only")))))
+ (erc-d-u-canned-dialog-dir (expand-file-name
(or erc-scenarios-common-dialog
(cadr (assq 'erc-scenarios-common-dialog
',bindings)))
@@ -119,9 +143,10 @@
(quit . ,(erc-quit/part-reason-default))
(erc-version . ,erc-version)))
(erc-modules (copy-sequence erc-modules))
- (inhibit-interaction t)
+ (inhibit-interaction noninteractive)
(auth-source-do-cache nil)
(timer-list (copy-sequence timer-list))
+ (timer-idle-list (copy-sequence timer-idle-list))
(erc-auth-source-parameters-join-function nil)
(erc-autojoin-channels-alist nil)
(erc-server-auto-reconnect nil)
@@ -138,13 +163,19 @@ disabled by BODY. Other defaults common to these test cases are added
below and can be overridden, except when wanting the \"real\" default
value, which must be looked up or captured outside of the calling form.
+When running tests tagged as serially runnable while interactive
+and the flag `erc-scenarios-common--graphical-p' is non-nil, run
+teardown tasks normally inhibited when interactive. That is,
+behave almost as if `noninteractive' were also non-nil, and
+ensure buffers and other resources are destroyed on completion.
+
Dialog resource directories are located by expanding the variable
`erc-scenarios-common-dialog' or its value in BINDINGS."
(declare (indent 1))
(let* ((orig-autojoin-mode (make-symbol "orig-autojoin-mode"))
(combined `((,orig-autojoin-mode (bound-and-true-p erc-autojoin-mode))
- ,@(erc-scenarios-common--make-bindings bindings))))
+ ,@(erc-scenarios-common--make-bindings bindings))))
`(erc-d-t-with-cleanup (,@combined)
@@ -164,8 +195,9 @@ Dialog resource directories are located by expanding the variable
(not (eq erc-autojoin-mode ,orig-autojoin-mode)))
(erc-autojoin-mode (if ,orig-autojoin-mode +1 -1)))
- (when noninteractive
- (erc-scenarios-common--print-trace)
+ (when (or noninteractive erc-scenarios-common--graphical-p)
+ (when noninteractive
+ (erc-scenarios-common--print-trace))
(erc-d-t-kill-related-buffers)
(delete-other-windows)))
@@ -178,11 +210,118 @@ Dialog resource directories are located by expanding the variable
(erc-d-t-search-for 3 "Starting")))))
(ert-info ("Activate erc-debug-irc-protocol")
- (unless (and noninteractive (not erc-debug-irc-protocol))
+ (unless (and (or noninteractive erc-scenarios-common--graphical-p)
+ (not erc-debug-irc-protocol))
(erc-toggle-debug-irc-protocol)))
,@body)))
+(defvar erc-scenarios-common--term-size '(34 . 80))
+(declare-function term-char-mode "term" nil)
+(declare-function term-line-mode "term" nil)
+
+;; Much of this concerns accommodating test environments outside of
+;; the emacs.git tree, such as CI jobs running ERC's ELPA-package on
+;; older Emacsen. See also `erc-tests--assert-printed-in-subprocess'.
+(defun erc-scenarios-common--run-in-term (&optional debug)
+ (require 'term)
+ (let* ((default-directory (or (getenv "EMACS_TEST_DIRECTORY")
+ (expand-file-name
+ ".." erc-scenarios-common--resources-dir)))
+ ;; In the emacs.git tree, "HOME" will be "/nonexistent", which
+ ;; is fine because we don't need any ELPA packages.
+ (process-environment (cons "ERC_TESTS_SUBPROCESS=1"
+ process-environment))
+ (name (ert-test-name (ert-running-test)))
+ (temp-file (make-temp-file "erc-term-test-"))
+ (cmd `(let ((stats 1))
+ (setq enable-dir-local-variables nil)
+ (unwind-protect
+ (setq stats (ert-run-tests-batch ',name))
+ (unless ',debug
+ (let ((buf (with-current-buffer (messages-buffer)
+ (buffer-string))))
+ (with-temp-file ,temp-file
+ (insert buf)))
+ (kill-emacs (ert-stats-completed-unexpected stats))))))
+ ;; The `ert-test' object in Emacs 29 has a `file-name' field.
+ (file-name (symbol-file name 'ert--test))
+ (default-directory (expand-file-name (file-name-directory file-name)))
+ (package (if-let* ((found (getenv "ERC_PACKAGE_NAME"))
+ ((string-prefix-p "erc-" found)))
+ (intern found)
+ 'erc))
+ (init (and-let* ((found (getenv "ERC_TESTS_INIT"))
+ (files (split-string found ",")))
+ (mapcan (lambda (f) (list "-l" f)) files)))
+ (setup `(progn
+ ,@(and (not init) (featurep 'compat)
+ `((require 'package)
+ (let ((package-load-list
+ '((compat t) (,package t))))
+ (package-initialize))))
+ (require 'erc)
+ (cl-assert (equal erc-version ,erc-version) t)))
+ ;; Make subprocess terminal bigger than controlling.
+ (buf (cl-letf (((symbol-function 'window-screen-lines)
+ (lambda () (car erc-scenarios-common--term-size)))
+ ((symbol-function 'window-max-chars-per-line)
+ (lambda () (cdr erc-scenarios-common--term-size))))
+ (apply #'make-term (symbol-name name)
+ (expand-file-name invocation-name invocation-directory)
+ nil `(,@(or init '("-Q")) "-nw"
+ "-eval" ,(format "%S" setup)
+ "-l" ,file-name
+ "-eval" ,(format "%S" cmd)))))
+ (proc (get-buffer-process buf))
+ (err (lambda ()
+ (with-temp-buffer
+ (insert-file-contents temp-file)
+ (message "Subprocess: %s" (buffer-string))
+ (delete-file temp-file)))))
+ (unless noninteractive
+ (set-window-buffer (selected-window) buf)
+ (delete-other-windows))
+ (with-current-buffer buf
+ (set-process-query-on-exit-flag proc nil)
+ (unless noninteractive (term-char-mode))
+ (erc-d-t-wait-for 30 (process-live-p proc))
+ (while (accept-process-output proc))
+ (term-line-mode)
+ (goto-char (point-min))
+ ;; Otherwise gives process exited abnormally with exit-code >0
+ (unless (search-forward (format "Process %s finished" name) nil t)
+ (funcall err)
+ (ert-fail (when (search-forward "exited" nil t)
+ (buffer-substring-no-properties (line-beginning-position)
+ (line-end-position)))))
+ (delete-file temp-file)
+ (when noninteractive
+ (kill-buffer)))))
+
+(defvar erc-scenarios-common-interactive-debug-term-p nil
+ "Non-nil means run test in an inferior Emacs, even if interactive.")
+
+(defmacro erc-scenarios-common-with-noninteractive-in-term (&rest body)
+ "Run BODY via `erc-scenarios-common-with-cleanup' in a `term' subprocess.
+Also do so when `erc-scenarios-common-interactive-debug-term-p'
+is non-nil. When debugging, leave the `term-mode' buffer around
+for inspection and name it after the test, bounded by asterisks.
+When debugging, ensure the test always fails, as a reminder to
+disable `erc-scenarios-common-interactive-debug-term-p'.
+
+See Info node `(emacs) Term Mode' for the various commands."
+ (declare (indent 1))
+ `(if (and (or erc-scenarios-common-interactive-debug-term-p
+ noninteractive)
+ (not (getenv "ERC_TESTS_SUBPROCESS")))
+ (progn
+ (when (memq system-type '(windows-nt ms-dos cygwin haiku))
+ (ert-skip "System must be UNIX-like"))
+ (erc-scenarios-common--run-in-term
+ erc-scenarios-common-interactive-debug-term-p))
+ (erc-scenarios-common-with-cleanup ,@body)))
+
(defun erc-scenarios-common-assert-initial-buf-name (id port)
;; Assert no limbo period when explicit ID given
(should (string= (if id
@@ -209,9 +348,111 @@ Dialog resource directories are located by expanding the variable
(insert str)
(erc-send-current-line)))
+(defun erc-scenarios-common--at-win-end-p (&optional window)
+ (= (window-body-height window)
+ (count-screen-lines (window-start window) (point-max) nil window)))
+
+(defun erc-scenarios-common--above-win-end-p (&optional window)
+ (> (window-body-height window)
+ (count-screen-lines (window-start window) (point-max))))
+
+(defun erc-scenarios-common--prompt-past-win-end-p (&optional window)
+ (< (window-body-height window)
+ (count-screen-lines (window-start window) (point-max))))
+
+(defun erc-scenarios-common--recenter-top-bottom-around (orig &rest args)
+ (let (this-command last-command) (apply orig args)))
+
+(defun erc-scenarios-common--recenter-top-bottom ()
+ (advice-add 'recenter-top-bottom
+ :around #'erc-scenarios-common--recenter-top-bottom-around)
+ (execute-kbd-macro "\C-l")
+ (advice-remove 'recenter-top-bottom
+ #'erc-scenarios-common--recenter-top-bottom-around))
+
;;;; Fixtures
+(defun erc-scenarios-common-scrolltobottom--normal (test)
+ (erc-scenarios-common-with-noninteractive-in-term
+ ((erc-scenarios-common-dialog "scrolltobottom")
+ (dumb-server (erc-d-run "localhost" t 'help))
+ (port (process-contact dumb-server :service))
+ (erc-modules `(scrolltobottom fill-wrap ,@erc-modules))
+ (erc-server-flood-penalty 0.1)
+ (expect (erc-d-t-make-expecter)))
+
+ (ert-info ("Connect")
+ (with-current-buffer (erc :server "127.0.0.1"
+ :port port
+ :full-name "tester"
+ :nick "tester")
+ (funcall expect 10 "debug mode")))
+
+ (with-current-buffer "foonet"
+ (should (looking-at " and"))
+ (set-window-buffer nil (current-buffer))
+ (delete-other-windows)
+ (split-window-below 15)
+ (recenter 0)
+
+ (ert-info ("Moving into prompt in other window triggers scroll")
+ (with-selected-window (next-window)
+ (should-not (erc-scenarios-common--at-win-end-p))
+ (goto-char (1- erc-insert-marker))
+ (execute-kbd-macro "\C-n")
+ ;; Ensure point is at prompt and aligned to bottom.
+ (should (erc-scenarios-common--at-win-end-p))))
+
+ (ert-info ("Module `move-to-prompt' still works")
+ ;; Prompt is somewhere in the middle of the window.
+ (should (erc-scenarios-common--above-win-end-p))
+ ;; Hitting a self-insert key triggers `move-to-prompt' as well
+ ;; as a scroll (to bottom).
+ (execute-kbd-macro "hi")
+ ;; Prompt and input appear on last line of window.
+ (should (erc-scenarios-common--at-win-end-p)))
+
+ (ert-info ("Command `recenter-top-bottom' disallowed at prompt")
+ ;; Hitting C-l does not recenter the window.
+ (erc-scenarios-common--recenter-top-bottom)
+ (should (erc-scenarios-common--at-win-end-p))
+ (erc-scenarios-common--recenter-top-bottom)
+ (should (erc-scenarios-common--at-win-end-p)))
+
+ (ert-info ("Command `beginning-of-buffer' allowed at prompt")
+ ;; Hitting C-< goes to beginning of buffer.
+ (call-interactively #'beginning-of-buffer)
+ (should (= 1 (point)))
+ (redisplay)
+ (should (zerop (count-screen-lines (window-start) (point))))
+ (should (erc-scenarios-common--prompt-past-win-end-p)))
+
+ (ert-info ("New message doesn't trigger scroll when away from prompt")
+ ;; Arriving insertions don't trigger a scroll when away from the
+ ;; prompt. New output not seen.
+ (erc-cmd-MSG "NickServ help register")
+ (save-excursion (erc-d-t-search-for 10 "End of NickServ"))
+ (should (= 1 (point)))
+ (redisplay)
+ (should (zerop (count-screen-lines (window-start) (window-point))))
+ (should (erc-scenarios-common--prompt-past-win-end-p)))
+
+ (funcall test)
+
+ (ert-info ("New message does trigger a scroll when at prompt")
+ ;; Recenter so prompt is above rather than at window's end.
+ (funcall expect 10 "If you are currently logged in")
+ (recenter 0)
+ ;; Prompt is somewhere in the middle of the window.
+ (erc-d-t-wait-for 10 (erc-scenarios-common--above-win-end-p))
+ (erc-scenarios-common-say "/msg NickServ help identify")
+ ;; New arriving messages trigger a snap when inserted.
+ (erc-d-t-wait-for 10 (erc-scenarios-common--at-win-end-p))
+ (funcall expect 10 "IDENTIFY lets you login"))
+
+ (erc-scrolltobottom-mode -1))))
+
(cl-defun erc-scenarios-common--base-network-id-bouncer
((&key autop foo-id bar-id after
&aux
@@ -248,7 +489,7 @@ buffer-naming collisions involving bouncers in ERC."
:id foo-id))
(setq erc-server-process-foo erc-server-process)
(erc-scenarios-common-assert-initial-buf-name foo-id port)
- (erc-d-t-wait-for 3 (eq (erc-network) 'foonet))
+ (erc-d-t-wait-for 6 (eq (erc-network) 'foonet))
(erc-d-t-wait-for 3 (string= (buffer-name) serv-buf-foo))
(funcall expect 5 "foonet")))
@@ -367,7 +608,7 @@ buffer-naming collisions involving bouncers in ERC."
:password "changeme"
:full-name "tester")
(erc-scenarios-common-assert-initial-buf-name nil port)
- (erc-d-t-wait-for 3 (eq (erc-network) 'foonet))
+ (erc-d-t-wait-for 6 (eq (erc-network) 'foonet))
(erc-d-t-wait-for 3 (string= (buffer-name) "foonet"))
(funcall expect 5 "foonet")))
@@ -447,10 +688,17 @@ Bug#48598: 28.0.50; buffer-naming collisions involving bouncers in ERC."
(with-current-buffer erc-server-buffer-foo (erc-cmd-JOIN "#chan"))
(with-current-buffer (erc-d-t-wait-for 5 (get-buffer "#chan"))
(funcall expect 5 "vile thing")
- (erc-cmd-QUIT "")))
+ (erc-cmd-QUIT "")
+
+ (ert-info ("Prompt hidden in channel buffer upon quitting")
+ (erc-d-t-wait-for 10 (erc--prompt-hidden-p))
+ (should (overlays-in erc-insert-marker erc-input-marker)))))
- (erc-d-t-wait-for 2 "Foonet connection deceased"
- (not (erc-server-process-alive erc-server-buffer-foo)))
+ (with-current-buffer erc-server-buffer-foo
+ (ert-info ("Prompt hidden after process dies in server buffer")
+ (erc-d-t-wait-for 2 (not (erc-server-process-alive)))
+ (erc-d-t-wait-for 10 (erc--prompt-hidden-p))
+ (should (overlays-in erc-insert-marker erc-input-marker))))
(should (equal erc-autojoin-channels-alist
(if foo-id '((oofnet "#chan")) '((foonet "#chan")))))
@@ -499,6 +747,10 @@ Bug#48598: 28.0.50; buffer-naming collisions involving bouncers in ERC."
(setq erc-server-process-foo erc-server-process)
(erc-d-t-wait-for 2 (eq erc-network 'foonet))
(should (string= (buffer-name) (if foo-id "oofnet" "foonet")))
+
+ (ert-info ("Prompt unhidden")
+ (should-not (erc--prompt-hidden-p))
+ (should-not (overlays-in erc-insert-marker erc-input-marker)))
(funcall expect 5 "foonet")))
(ert-info ("#chan@foonet is clean, no cross-contamination")
@@ -506,7 +758,11 @@ Bug#48598: 28.0.50; buffer-naming collisions involving bouncers in ERC."
(erc-d-t-wait-for 3 (eq erc-server-process erc-server-process-foo))
(funcall expect 3 "<bob>")
(erc-d-t-absent-for 0.1 "<joe>")
- (funcall expect 10 "not given me")))
+ (funcall expect 30 "not given me")
+
+ (ert-info ("Prompt unhidden")
+ (should-not (erc--prompt-hidden-p))
+ (should-not (overlays-in erc-insert-marker erc-input-marker)))))
(ert-info ("All #chan@barnet output received")
(with-current-buffer chan-buf-bar
diff --git a/test/lisp/erc/resources/erc-tests-common.el b/test/lisp/erc/resources/erc-tests-common.el
new file mode 100644
index 00000000000..fc5649798b5
--- /dev/null
+++ b/test/lisp/erc/resources/erc-tests-common.el
@@ -0,0 +1,301 @@
+;;; erc-tests-common.el --- Common helpers for ERC tests -*- lexical-binding: t -*-
+
+;; Copyright (C) 2023-2024 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; This file must *not* contain any `ert-deftest' definitions. See
+;; top of test/lisp/erc/erc-tests.el for loading example.
+;;
+;; Environment variables:
+;;
+;; `ERC_PACKAGE_NAME': Name of the installed ERC package currently
+;; running. ERC needs this in order to load the same package in
+;; tests that run in a subprocess. Necessary even when the package
+;; name is `erc' and not something like `erc-49860'.
+;;
+;; `ERC_TESTS_INIT': The name of an alternate init file. Mainly for
+;; integrations tests involving starter kits.
+;;
+;; `ERC_TESTS_SNAPSHOT_SAVE': When set, ERC saves the current test's
+;; snapshots to disk.
+;;
+
+;;; Code:
+(require 'ert-x)
+(require 'erc)
+
+
+(defmacro erc-tests-common-equal-with-props (a b)
+ "Compare strings A and B for equality including text props.
+Use `ert-equal-including-properties' on older Emacsen."
+ (list (if (< emacs-major-version 29)
+ 'ert-equal-including-properties
+ 'equal-including-properties)
+ a b))
+
+;; Caller should probably shadow `erc-insert-modify-hook' or populate
+;; user tables for erc-button.
+;; FIXME explain this comment ^ in more detail or delete.
+(defun erc-tests-common-prep-for-insertion ()
+ "Initialize current buffer with essentials for message insertion.
+Assume caller intends to use `erc-display-message'."
+ (erc-mode)
+ (erc--initialize-markers (point) nil)
+ (should (= (point) erc-input-marker)))
+
+(defun erc-tests-common-init-server-proc (&rest args)
+ "Create a process with `start-process' from ARGS.
+Assign the result to `erc-server-process' in the current buffer."
+ (setq erc-server-process
+ (apply #'start-process (car args) (current-buffer) args))
+ (set-process-query-on-exit-flag erc-server-process nil)
+ erc-server-process)
+
+;; After dropping support for Emacs 27, callers can use
+;; `get-buffer-create' with INHIBIT-BUFFER-HOOKS.
+(defun erc-tests-common-kill-buffers (&rest extra-buffers)
+ "Kill all ERC buffers and possibly EXTRA-BUFFERS."
+ (let (erc-kill-channel-hook erc-kill-server-hook erc-kill-buffer-hook)
+ (dolist (buf (erc-buffer-list))
+ (kill-buffer buf))
+ (named-let doit ((buffers extra-buffers))
+ (dolist (buf buffers)
+ (if (consp buf) (doit buf) (kill-buffer buf))))))
+
+(defun erc-tests-common-with-process-input-spy (test-fn)
+ "Mock `erc-process-input-line' and call TEST-FN.
+Shadow `erc--input-review-functions' and `erc-pre-send-functions'
+with `erc-add-to-input-ring' removed. Shadow other relevant
+variables as nil, and bind `erc-last-input-time' to 0. Also mock
+`erc-server-buffer' to return the current buffer. Call TEST-FN
+with a utility function that returns the set of arguments most
+recently passed to the mocked `erc-process-input-line'. Make
+`inhibit-message' non-nil unless running interactively."
+ (with-current-buffer (get-buffer-create "FakeNet")
+ (let* ((erc--input-review-functions
+ (remove 'erc-add-to-input-ring erc--input-review-functions))
+ (erc-pre-send-functions
+ (remove 'erc-add-to-input-ring erc-pre-send-functions)) ; for now
+ (inhibit-message noninteractive)
+ (erc-server-current-nick "tester")
+ (erc-last-input-time 0)
+ erc-accidental-paste-threshold-seconds
+ erc-send-modify-hook
+ ;;
+ calls)
+ (cl-letf (((symbol-function 'erc-process-input-line)
+ (lambda (&rest r) (push r calls)))
+ ((symbol-function 'erc-server-buffer)
+ (lambda () (current-buffer))))
+ (erc-tests-common-prep-for-insertion)
+ (funcall test-fn (lambda () (pop calls)))))
+ (when noninteractive (kill-buffer))))
+
+(defun erc-tests-common-make-server-buf (&optional name)
+ "Return a server buffer named NAME, creating it if necessary.
+Use NAME for the network and the session server as well."
+ (unless name
+ (cl-assert (string-prefix-p " *temp*" (setq name (buffer-name)))))
+ (with-current-buffer (get-buffer-create name)
+ (erc-tests-common-prep-for-insertion)
+ (erc-tests-common-init-server-proc "sleep" "1")
+ (setq erc-session-server (concat "irc." name ".org")
+ erc-server-announced-name (concat "west." name ".org")
+ erc-server-users (make-hash-table :test #'equal)
+ erc-server-parameters nil
+ erc--isupport-params (make-hash-table)
+ erc-session-port 6667
+ erc-network (intern name)
+ erc-networks--id (erc-networks--id-create nil))
+ (current-buffer)))
+
+(defun erc-tests-common-string-to-propertized-parts (string)
+ "Return a sequence of `propertize' forms for generating STRING.
+Expect maintainers manipulating template catalogs to use this
+with `pp-eval-last-sexp' or similar to convert back and forth
+between literal strings."
+ `(concat
+ ,@(mapcar
+ (pcase-lambda (`(,beg ,end ,plist))
+ ;; At the time of writing, `propertize' produces a string
+ ;; with the order of the input plist reversed.
+ `(propertize ,(substring-no-properties string beg end)
+ ,@(let (out)
+ (while-let ((plist)
+ (k (pop plist))
+ (v (pop plist)))
+ (push (if (or (consp v) (symbolp v)) `',v v) out)
+ (push `',k out))
+ out)))
+ (object-intervals string))))
+
+(defun erc-tests-common-pp-propertized-parts (arg)
+ "Convert literal string before point into a `propertize'd form.
+For simplicity, assume string evaluates to itself."
+ (interactive "P")
+ (let ((sexp (erc-tests-common-string-to-propertized-parts (pp-last-sexp))))
+ (if arg (insert (pp-to-string sexp)) (pp-eval-expression sexp))))
+
+;; The following utilities are meant to help prepare tests for
+;; `erc--get-inserted-msg-bounds' and friends.
+(defun erc-tests-common-get-inserted-msg-setup ()
+ (erc-tests-common-prep-for-insertion)
+ (let ((parsed (make-erc-response :unparsed ":bob PRIVMSG #chan :hi"
+ :sender "bob"
+ :command "PRIVMSG"
+ :command-args (list "#chan" "hi")
+ :contents "hi"))
+ (erc--msg-prop-overrides '((erc--ts . 0))))
+ (erc-display-message parsed nil (current-buffer)
+ (erc-format-privmessage "bob" "hi" nil t)))
+ (goto-char 3)
+ (should (looking-at "<bob> hi")))
+
+;; All these bounds-finding functions take an optional POINT argument.
+;; So run each case with and without it at each pos in the message.
+(defun erc-tests-common-assert-get-inserted-msg (from to assert-fn)
+ (dolist (pt-arg '(nil t))
+ (dolist (i (number-sequence from to))
+ (goto-char i)
+ (ert-info ((format "At %d (%c) %s param" i (char-after i)
+ (if pt-arg "with" "")))
+ (funcall assert-fn (and pt-arg i))))))
+
+(defun erc-tests-common-assert-get-inserted-msg/basic (test-fn)
+ (erc-tests-common-get-inserted-msg-setup)
+ (goto-char 11)
+ (should (looking-back "<bob> hi"))
+ (erc-tests-common-assert-get-inserted-msg 3 11 test-fn))
+
+;; This is a "mixin" and requires a base assertion function, like
+;; `erc-tests-common-assert-get-inserted-msg/basic', to work.
+(defun erc-tests-common-assert-get-inserted-msg-readonly-with
+ (assert-fn test-fn)
+ (defvar erc-readonly-mode)
+ (defvar erc-readonly-mode-hook)
+ (let ((erc-readonly-mode nil)
+ (erc-readonly-mode-hook nil)
+ (erc-send-post-hook erc-send-post-hook)
+ (erc-insert-post-hook erc-insert-post-hook))
+ (erc-readonly-mode +1)
+ (funcall assert-fn test-fn)))
+
+
+;;;; Buffer snapshots
+
+;; Use this variable to generate new snapshots after carefully
+;; reviewing the output of *each* snapshot (not just first and last).
+;; Obviously, only run one test at a time.
+(defvar erc-tests-common-snapshot-save-p (getenv "ERC_TESTS_SNAPSHOT_SAVE"))
+
+(defun erc-tests-common-snapshot-compare (name dir trans-fn buf-init-fn)
+ "Compare `buffer-string' to snapshot NAME.eld in DIR, if present.
+When non-nil, run TRANS-FN to fiter the current buffer string,
+and expect a similar string in return. Call BUF-INIT-FN, when
+non-nil, in the preview buffer after inserting the filtered
+string."
+ (let* ((expect-file (file-name-with-extension (expand-file-name name dir)
+ "eld"))
+ (erc--own-property-names
+ (seq-difference `(font-lock-face ,@erc--own-property-names)
+ `(field display wrap-prefix line-prefix
+ erc--msg erc--cmd erc--spkr erc--ts erc--ctcp
+ erc--ephemeral)
+ #'eq))
+ (print-circle t)
+ (print-escape-newlines t)
+ (print-escape-nonascii t)
+ (got (erc--remove-text-properties
+ (buffer-substring (point-min) erc-insert-marker)))
+ (repr (funcall (or trans-fn #'identity) (prin1-to-string got))))
+ (with-current-buffer (generate-new-buffer name)
+ (with-silent-modifications
+ (insert (setq got (read repr))))
+ (when buf-init-fn (funcall buf-init-fn))
+ (erc-mode))
+ ;; LHS is a string, RHS is a symbol.
+ (if (string= erc-tests-common-snapshot-save-p
+ (ert-test-name (ert-running-test)))
+ (let (inhibit-message)
+ (with-temp-file expect-file
+ (insert repr))
+ ;; Limit writing snapshots to one test at a time.
+ (message "erc-tests-common-snapshot-compare: wrote %S" expect-file))
+ (if (file-exists-p expect-file)
+ ;; Ensure string-valued properties, like timestamps, aren't
+ ;; recursive (signals `max-lisp-eval-depth' exceeded).
+ (named-let assert-equal
+ ((latest (read repr))
+ (expect (read (with-temp-buffer
+ (insert-file-contents-literally expect-file)
+ (buffer-string)))))
+ (pcase latest
+ ((or "" 'nil) t)
+ ((pred stringp)
+ (should (equal-including-properties latest expect))
+ (let ((latest-intervals (object-intervals latest))
+ (expect-intervals (object-intervals expect)))
+ (while-let ((l-iv (pop latest-intervals))
+ (x-iv (pop expect-intervals))
+ (l-tab (map-into (nth 2 l-iv) 'hash-table))
+ (x-tab (map-into (nth 2 x-iv) 'hash-table)))
+ (pcase-dolist (`(,l-k . ,l-v) (map-pairs l-tab))
+ (assert-equal l-v (gethash l-k x-tab))
+ (remhash l-k x-tab))
+ (should (zerop (hash-table-count x-tab))))))
+ ((pred sequencep)
+ (assert-equal (seq-first latest) (seq-first expect))
+ (assert-equal (seq-rest latest) (seq-rest expect)))
+ (_ (should (equal latest expect)))))
+ (message "Snapshot file missing: %S" expect-file)))))
+
+(defun erc-tests-common-create-subprocess (code switches libs)
+ "Return subprocess for running CODE in an inferior Emacs.
+Include SWITCHES, like \"-batch\", as well as libs, after
+interspersing \"-l\" between members."
+ (let* ((package (if-let ((found (getenv "ERC_PACKAGE_NAME"))
+ ((string-prefix-p "erc-" found)))
+ (intern found)
+ 'erc))
+ ;; For integrations testing with managed configs that use a
+ ;; different package manager.
+ (init (and-let* ((found (getenv "ERC_TESTS_INIT"))
+ (files (split-string found ",")))
+ (mapcan (lambda (f) (list "-l" f)) files)))
+ (prog
+ `(progn
+ ,@(and (not init) (featurep 'compat)
+ `((require 'package)
+ (let ((package-load-list '((compat t) (,package t))))
+ (package-initialize))))
+ (require 'erc)
+ (cl-assert (equal erc-version ,erc-version) t)
+ ,code))
+ (proc (apply #'start-process
+ (symbol-name (ert-test-name (ert-running-test)))
+ (current-buffer)
+ (concat invocation-directory invocation-name)
+ `(,@(or init '("-Q"))
+ ,@switches
+ ,@(mapcan (lambda (f) (list "-l" f)) libs)
+ "-eval" ,(format "%S" prog)))))
+ (set-process-query-on-exit-flag proc t)
+ proc))
+
+(provide 'erc-tests-common)
diff --git a/test/lisp/erc/resources/fill/snapshots/merge-01-start.eld b/test/lisp/erc/resources/fill/snapshots/merge-01-start.eld
index 689bacc7012..3c32719a052 100644
--- a/test/lisp/erc/resources/fill/snapshots/merge-01-start.eld
+++ b/test/lisp/erc/resources/fill/snapshots/merge-01-start.eld
@@ -1 +1 @@
-#("\n\n\n[Thu Jan 1 1970]\n*** This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect.[00:00]\n<alice> bob: come, you are a tedious fool: to the purpose. What was done to Elbow's wife, that he hath cause to complain of? Come me to what was done to her.\n<bob> alice: Either your unparagoned mistress is dead, or she's outprized by a trifle.\n\n[Sat Apr 1 2023]\n<bob> zero.[07:00]\n<alice> one.\n<alice> two.\n<bob> three.\n<bob> four.\n<Dummy> five.\n<Dummy> six.\n" 2 20 (erc-timestamp 0 line-prefix (space :width (- 27 (18))) field erc-timestamp) 20 21 (erc-timestamp 0 field erc-timestamp) 21 183 (erc-timestamp 0 wrap-prefix #2=(space :width 27) line-prefix #3=(space :width (- 27 (4)))) 183 190 (erc-timestamp 0 field erc-timestamp wrap-prefix #2# line-prefix #3# display #1=(#7=(margin right-margin) #("[00:00]" 0 7 (display #1# isearch-open-invisible timestamp invisible timestamp font-lock-face erc-timestamp-face)))) 191 192 (erc-timestamp 0 wrap-prefix #2# line-prefix #4=(space :width (- 27 (8))) erc-command PRIVMSG) 192 197 (erc-timestamp 0 wrap-prefix #2# line-prefix #4# erc-command PRIVMSG) 197 199 (erc-timestamp 0 wrap-prefix #2# line-prefix #4# erc-command PRIVMSG) 199 202 (erc-timestamp 0 wrap-prefix #2# line-prefix #4# erc-command PRIVMSG) 202 315 (erc-timestamp 0 wrap-prefix #2# line-prefix #4# erc-command PRIVMSG) 315 316 (erc-timestamp 0 erc-command PRIVMSG) 316 348 (erc-timestamp 0 wrap-prefix #2# line-prefix #4# erc-command PRIVMSG) 349 350 (erc-timestamp 0 wrap-prefix #2# line-prefix #5=(space :width (- 27 (6))) erc-command PRIVMSG) 350 353 (erc-timestamp 0 wrap-prefix #2# line-prefix #5# erc-command PRIVMSG) 353 355 (erc-timestamp 0 wrap-prefix #2# line-prefix #5# erc-command PRIVMSG) 355 360 (erc-timestamp 0 wrap-prefix #2# line-prefix #5# erc-command PRIVMSG) 360 435 (erc-timestamp 0 wrap-prefix #2# line-prefix #5# erc-command PRIVMSG) 436 454 (erc-timestamp 1680332400 line-prefix (space :width (- 27 (18))) field erc-timestamp) 454 455 (erc-timestamp 1680332400 field erc-timestamp) 455 456 (erc-timestamp 1680332400 wrap-prefix #2# line-prefix #6=(space :width (- 27 (6))) erc-command PRIVMSG) 456 459 (erc-timestamp 1680332400 wrap-prefix #2# line-prefix #6# erc-command PRIVMSG) 459 466 (erc-timestamp 1680332400 wrap-prefix #2# line-prefix #6# erc-command PRIVMSG) 466 473 (erc-timestamp 1680332400 field erc-timestamp wrap-prefix #2# line-prefix #6# display #8=(#7# #("[07:00]" 0 7 (display #8# isearch-open-invisible timestamp invisible timestamp font-lock-face erc-timestamp-face)))) 474 475 (erc-timestamp 1680332400 wrap-prefix #2# line-prefix #9=(space :width (- 27 (8))) erc-command PRIVMSG) 475 480 (erc-timestamp 1680332400 wrap-prefix #2# line-prefix #9# erc-command PRIVMSG) 480 486 (erc-timestamp 1680332400 wrap-prefix #2# line-prefix #9# erc-command PRIVMSG) 487 488 (erc-timestamp 1680332400 wrap-prefix #2# line-prefix #10=(space :width (- 27 0)) display #11="" erc-command PRIVMSG) 488 493 (erc-timestamp 1680332400 wrap-prefix #2# line-prefix #10# display #11# erc-command PRIVMSG) 493 495 (erc-timestamp 1680332400 wrap-prefix #2# line-prefix #10# display #11# erc-command PRIVMSG) 495 499 (erc-timestamp 1680332400 wrap-prefix #2# line-prefix #10# erc-command PRIVMSG) 500 501 (erc-timestamp 1680332400 wrap-prefix #2# line-prefix #12=(space :width (- 27 (6))) erc-command PRIVMSG) 501 504 (erc-timestamp 1680332400 wrap-prefix #2# line-prefix #12# erc-command PRIVMSG) 504 512 (erc-timestamp 1680332400 wrap-prefix #2# line-prefix #12# erc-command PRIVMSG) 513 514 (erc-timestamp 1680332400 wrap-prefix #2# line-prefix #13=(space :width (- 27 0)) display #11# erc-command PRIVMSG) 514 517 (erc-timestamp 1680332400 wrap-prefix #2# line-prefix #13# display #11# erc-command PRIVMSG) 517 519 (erc-timestamp 1680332400 wrap-prefix #2# line-prefix #13# display #11# erc-command PRIVMSG) 519 524 (erc-timestamp 1680332400 wrap-prefix #2# line-prefix #13# erc-command PRIVMSG) 525 526 (erc-timestamp 1680332400 wrap-prefix #2# line-prefix #14=(space :width (- 27 (8))) erc-command PRIVMSG) 526 531 (erc-timestamp 1680332400 wrap-prefix #2# line-prefix #14# erc-command PRIVMSG) 531 538 (erc-timestamp 1680332400 wrap-prefix #2# line-prefix #14# erc-command PRIVMSG) 539 540 (erc-timestamp 1680332400 wrap-prefix #2# line-prefix #15=(space :width (- 27 0)) display #11# erc-command PRIVMSG) 540 545 (erc-timestamp 1680332400 wrap-prefix #2# line-prefix #15# display #11# erc-command PRIVMSG) 545 547 (erc-timestamp 1680332400 wrap-prefix #2# line-prefix #15# display #11# erc-command PRIVMSG) 547 551 (erc-timestamp 1680332400 wrap-prefix #2# line-prefix #15# erc-command PRIVMSG)) \ No newline at end of file
+#("\n\n\n[Thu Jan 1 1970]\n*** This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect.[00:00]\n<alice> bob: come, you are a tedious fool: to the purpose. What was done to Elbow's wife, that he hath cause to complain of? Come me to what was done to her.\n<bob> alice: Either your unparagoned mistress is dead, or she's outprized by a trifle.\n\n[Sat Apr 1 2023]\n<bob> zero.[07:00]\n<alice> one.\n<alice> two.\n<bob> three.\n<bob> four.\n<Dummy> five.\n<Dummy> six.\n" 2 3 (erc--msg datestamp erc--ts 0 field erc-timestamp) 3 20 (field erc-timestamp wrap-prefix #1=(space :width 27) line-prefix (space :width (- 27 (18)))) 21 22 (erc--msg notice erc--ts 0 wrap-prefix #1# line-prefix #2=(space :width (- 27 (4)))) 22 183 (wrap-prefix #1# line-prefix #2#) 183 190 (field erc-timestamp wrap-prefix #1# line-prefix #2# display (#6=(margin right-margin) #("[00:00]" 0 7 (invisible timestamp)))) 191 192 (erc--msg msg erc--ts 0 erc--spkr "alice" erc--cmd PRIVMSG wrap-prefix #1# line-prefix #3=(space :width (- 27 (8)))) 192 197 (wrap-prefix #1# line-prefix #3#) 197 199 (wrap-prefix #1# line-prefix #3#) 199 202 (wrap-prefix #1# line-prefix #3#) 202 315 (wrap-prefix #1# line-prefix #3#) 316 348 (wrap-prefix #1# line-prefix #3#) 349 350 (erc--msg msg erc--ts 0 erc--spkr "bob" erc--cmd PRIVMSG wrap-prefix #1# line-prefix #4=(space :width (- 27 (6)))) 350 353 (wrap-prefix #1# line-prefix #4#) 353 355 (wrap-prefix #1# line-prefix #4#) 355 360 (wrap-prefix #1# line-prefix #4#) 360 435 (wrap-prefix #1# line-prefix #4#) 436 437 (erc--msg datestamp erc--ts 1680307200 field erc-timestamp) 437 454 (field erc-timestamp wrap-prefix #1# line-prefix (space :width (- 27 (18)))) 455 456 (erc--msg msg erc--ts 1680332400 erc--spkr "bob" erc--cmd PRIVMSG wrap-prefix #1# line-prefix #5=(space :width (- 27 (6)))) 456 459 (wrap-prefix #1# line-prefix #5#) 459 466 (wrap-prefix #1# line-prefix #5#) 466 473 (field erc-timestamp wrap-prefix #1# line-prefix #5# display (#6# #("[07:00]" 0 7 (invisible timestamp)))) 474 475 (erc--msg msg erc--ts 1680332400 erc--spkr "alice" erc--cmd PRIVMSG wrap-prefix #1# line-prefix #7=(space :width (- 27 (8)))) 475 480 (wrap-prefix #1# line-prefix #7#) 480 486 (wrap-prefix #1# line-prefix #7#) 487 488 (erc--msg msg erc--ts 1680332400 erc--spkr "alice" erc--cmd PRIVMSG wrap-prefix #1# line-prefix #8=(space :width (- 27 0)) display #9="") 488 493 (wrap-prefix #1# line-prefix #8# display #9#) 493 495 (wrap-prefix #1# line-prefix #8# display #9#) 495 499 (wrap-prefix #1# line-prefix #8#) 500 501 (erc--msg msg erc--ts 1680332400 erc--spkr "bob" erc--cmd PRIVMSG wrap-prefix #1# line-prefix #10=(space :width (- 27 (6)))) 501 504 (wrap-prefix #1# line-prefix #10#) 504 512 (wrap-prefix #1# line-prefix #10#) 513 514 (erc--msg msg erc--ts 1680332400 erc--spkr "bob" erc--cmd PRIVMSG wrap-prefix #1# line-prefix #11=(space :width (- 27 0)) display #9#) 514 517 (wrap-prefix #1# line-prefix #11# display #9#) 517 519 (wrap-prefix #1# line-prefix #11# display #9#) 519 524 (wrap-prefix #1# line-prefix #11#) 525 526 (erc--msg msg erc--ts 1680332400 erc--spkr "Dummy" erc--cmd PRIVMSG wrap-prefix #1# line-prefix #12=(space :width (- 27 (8)))) 526 531 (wrap-prefix #1# line-prefix #12#) 531 538 (wrap-prefix #1# line-prefix #12#) 539 540 (erc--msg msg erc--ts 1680332400 erc--spkr "Dummy" erc--cmd PRIVMSG wrap-prefix #1# line-prefix #13=(space :width (- 27 0)) display #9#) 540 545 (wrap-prefix #1# line-prefix #13# display #9#) 545 547 (wrap-prefix #1# line-prefix #13# display #9#) 547 551 (wrap-prefix #1# line-prefix #13#)) \ No newline at end of file
diff --git a/test/lisp/erc/resources/fill/snapshots/merge-02-right.eld b/test/lisp/erc/resources/fill/snapshots/merge-02-right.eld
index 9fa23a7d332..e2064b914c4 100644
--- a/test/lisp/erc/resources/fill/snapshots/merge-02-right.eld
+++ b/test/lisp/erc/resources/fill/snapshots/merge-02-right.eld
@@ -1 +1 @@
-#("\n\n\n[Thu Jan 1 1970]\n*** This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect.[00:00]\n<alice> bob: come, you are a tedious fool: to the purpose. What was done to Elbow's wife, that he hath cause to complain of? Come me to what was done to her.\n<bob> alice: Either your unparagoned mistress is dead, or she's outprized by a trifle.\n\n[Sat Apr 1 2023]\n<bob> zero.[07:00]\n<alice> one.\n<alice> two.\n<bob> three.\n<bob> four.\n<Dummy> five.\n<Dummy> six.\n" 2 20 (erc-timestamp 0 line-prefix (space :width (- 29 (18))) field erc-timestamp) 20 21 (erc-timestamp 0 field erc-timestamp) 21 183 (erc-timestamp 0 wrap-prefix #2=(space :width 29) line-prefix #3=(space :width (- 29 (4)))) 183 190 (erc-timestamp 0 field erc-timestamp wrap-prefix #2# line-prefix #3# display #1=(#7=(margin right-margin) #("[00:00]" 0 7 (display #1# isearch-open-invisible timestamp invisible timestamp font-lock-face erc-timestamp-face)))) 191 192 (erc-timestamp 0 wrap-prefix #2# line-prefix #4=(space :width (- 29 (8))) erc-command PRIVMSG) 192 197 (erc-timestamp 0 wrap-prefix #2# line-prefix #4# erc-command PRIVMSG) 197 199 (erc-timestamp 0 wrap-prefix #2# line-prefix #4# erc-command PRIVMSG) 199 202 (erc-timestamp 0 wrap-prefix #2# line-prefix #4# erc-command PRIVMSG) 202 315 (erc-timestamp 0 wrap-prefix #2# line-prefix #4# erc-command PRIVMSG) 315 316 (erc-timestamp 0 erc-command PRIVMSG) 316 348 (erc-timestamp 0 wrap-prefix #2# line-prefix #4# erc-command PRIVMSG) 349 350 (erc-timestamp 0 wrap-prefix #2# line-prefix #5=(space :width (- 29 (6))) erc-command PRIVMSG) 350 353 (erc-timestamp 0 wrap-prefix #2# line-prefix #5# erc-command PRIVMSG) 353 355 (erc-timestamp 0 wrap-prefix #2# line-prefix #5# erc-command PRIVMSG) 355 360 (erc-timestamp 0 wrap-prefix #2# line-prefix #5# erc-command PRIVMSG) 360 435 (erc-timestamp 0 wrap-prefix #2# line-prefix #5# erc-command PRIVMSG) 436 454 (erc-timestamp 1680332400 line-prefix (space :width (- 29 (18))) field erc-timestamp) 454 455 (erc-timestamp 1680332400 field erc-timestamp) 455 456 (erc-timestamp 1680332400 wrap-prefix #2# line-prefix #6=(space :width (- 29 (6))) erc-command PRIVMSG) 456 459 (erc-timestamp 1680332400 wrap-prefix #2# line-prefix #6# erc-command PRIVMSG) 459 466 (erc-timestamp 1680332400 wrap-prefix #2# line-prefix #6# erc-command PRIVMSG) 466 473 (erc-timestamp 1680332400 field erc-timestamp wrap-prefix #2# line-prefix #6# display #8=(#7# #("[07:00]" 0 7 (display #8# isearch-open-invisible timestamp invisible timestamp font-lock-face erc-timestamp-face)))) 474 475 (erc-timestamp 1680332400 wrap-prefix #2# line-prefix #9=(space :width (- 29 (8))) erc-command PRIVMSG) 475 480 (erc-timestamp 1680332400 wrap-prefix #2# line-prefix #9# erc-command PRIVMSG) 480 486 (erc-timestamp 1680332400 wrap-prefix #2# line-prefix #9# erc-command PRIVMSG) 487 488 (erc-timestamp 1680332400 wrap-prefix #2# line-prefix #10=(space :width (- 29 0)) display #11="" erc-command PRIVMSG) 488 493 (erc-timestamp 1680332400 wrap-prefix #2# line-prefix #10# display #11# erc-command PRIVMSG) 493 495 (erc-timestamp 1680332400 wrap-prefix #2# line-prefix #10# display #11# erc-command PRIVMSG) 495 499 (erc-timestamp 1680332400 wrap-prefix #2# line-prefix #10# erc-command PRIVMSG) 500 501 (erc-timestamp 1680332400 wrap-prefix #2# line-prefix #12=(space :width (- 29 (6))) erc-command PRIVMSG) 501 504 (erc-timestamp 1680332400 wrap-prefix #2# line-prefix #12# erc-command PRIVMSG) 504 512 (erc-timestamp 1680332400 wrap-prefix #2# line-prefix #12# erc-command PRIVMSG) 513 514 (erc-timestamp 1680332400 wrap-prefix #2# line-prefix #13=(space :width (- 29 0)) display #11# erc-command PRIVMSG) 514 517 (erc-timestamp 1680332400 wrap-prefix #2# line-prefix #13# display #11# erc-command PRIVMSG) 517 519 (erc-timestamp 1680332400 wrap-prefix #2# line-prefix #13# display #11# erc-command PRIVMSG) 519 524 (erc-timestamp 1680332400 wrap-prefix #2# line-prefix #13# erc-command PRIVMSG) 525 526 (erc-timestamp 1680332400 wrap-prefix #2# line-prefix #14=(space :width (- 29 (8))) erc-command PRIVMSG) 526 531 (erc-timestamp 1680332400 wrap-prefix #2# line-prefix #14# erc-command PRIVMSG) 531 538 (erc-timestamp 1680332400 wrap-prefix #2# line-prefix #14# erc-command PRIVMSG) 539 540 (erc-timestamp 1680332400 wrap-prefix #2# line-prefix #15=(space :width (- 29 0)) display #11# erc-command PRIVMSG) 540 545 (erc-timestamp 1680332400 wrap-prefix #2# line-prefix #15# display #11# erc-command PRIVMSG) 545 547 (erc-timestamp 1680332400 wrap-prefix #2# line-prefix #15# display #11# erc-command PRIVMSG) 547 551 (erc-timestamp 1680332400 wrap-prefix #2# line-prefix #15# erc-command PRIVMSG)) \ No newline at end of file
+#("\n\n\n[Thu Jan 1 1970]\n*** This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect.[00:00]\n<alice> bob: come, you are a tedious fool: to the purpose. What was done to Elbow's wife, that he hath cause to complain of? Come me to what was done to her.\n<bob> alice: Either your unparagoned mistress is dead, or she's outprized by a trifle.\n\n[Sat Apr 1 2023]\n<bob> zero.[07:00]\n<alice> one.\n<alice> two.\n<bob> three.\n<bob> four.\n<Dummy> five.\n<Dummy> six.\n" 2 3 (erc--msg datestamp erc--ts 0 field erc-timestamp) 3 20 (wrap-prefix #1=(space :width 29) line-prefix (space :width (- 29 (18))) field erc-timestamp) 21 22 (wrap-prefix #1# line-prefix #2=(space :width (- 29 (4))) erc--msg notice erc--ts 0) 22 183 (wrap-prefix #1# line-prefix #2#) 183 190 (wrap-prefix #1# line-prefix #2# field erc-timestamp display (#6=(margin right-margin) #("[00:00]" 0 7 (invisible timestamp)))) 191 192 (wrap-prefix #1# line-prefix #3=(space :width (- 29 (8))) erc--msg msg erc--ts 0 erc--spkr "alice" erc--cmd PRIVMSG) 192 197 (wrap-prefix #1# line-prefix #3#) 197 199 (wrap-prefix #1# line-prefix #3#) 199 202 (wrap-prefix #1# line-prefix #3#) 202 315 (wrap-prefix #1# line-prefix #3#) 316 348 (wrap-prefix #1# line-prefix (space :width (- 29 (8)))) 349 350 (wrap-prefix #1# line-prefix #4=(space :width (- 29 (6))) erc--msg msg erc--ts 0 erc--spkr "bob" erc--cmd PRIVMSG) 350 353 (wrap-prefix #1# line-prefix #4#) 353 355 (wrap-prefix #1# line-prefix #4#) 355 360 (wrap-prefix #1# line-prefix #4#) 360 435 (wrap-prefix #1# line-prefix #4#) 436 437 (erc--msg datestamp erc--ts 1680307200 field erc-timestamp) 437 454 (wrap-prefix #1# line-prefix (space :width (- 29 (18))) field erc-timestamp) 455 456 (wrap-prefix #1# line-prefix #5=(space :width (- 29 (6))) erc--msg msg erc--ts 1680332400 erc--spkr "bob" erc--cmd PRIVMSG) 456 459 (wrap-prefix #1# line-prefix #5#) 459 466 (wrap-prefix #1# line-prefix #5#) 466 473 (wrap-prefix #1# line-prefix #5# field erc-timestamp display (#6# #("[07:00]" 0 7 (invisible timestamp)))) 474 475 (wrap-prefix #1# line-prefix #7=(space :width (- 29 (8))) erc--msg msg erc--ts 1680332400 erc--spkr "alice" erc--cmd PRIVMSG) 475 480 (wrap-prefix #1# line-prefix #7#) 480 486 (wrap-prefix #1# line-prefix #7#) 487 488 (wrap-prefix #1# line-prefix #8=(space :width (- 29 0)) erc--msg msg erc--ts 1680332400 erc--spkr "alice" erc--cmd PRIVMSG display #9="") 488 493 (wrap-prefix #1# line-prefix #8# display #9#) 493 495 (wrap-prefix #1# line-prefix #8# display #9#) 495 499 (wrap-prefix #1# line-prefix #8#) 500 501 (wrap-prefix #1# line-prefix #10=(space :width (- 29 (6))) erc--msg msg erc--ts 1680332400 erc--spkr "bob" erc--cmd PRIVMSG) 501 504 (wrap-prefix #1# line-prefix #10#) 504 512 (wrap-prefix #1# line-prefix #10#) 513 514 (wrap-prefix #1# line-prefix #11=(space :width (- 29 0)) erc--msg msg erc--ts 1680332400 erc--spkr "bob" erc--cmd PRIVMSG display #9#) 514 517 (wrap-prefix #1# line-prefix #11# display #9#) 517 519 (wrap-prefix #1# line-prefix #11# display #9#) 519 524 (wrap-prefix #1# line-prefix #11#) 525 526 (wrap-prefix #1# line-prefix #12=(space :width (- 29 (8))) erc--msg msg erc--ts 1680332400 erc--spkr "Dummy" erc--cmd PRIVMSG) 526 531 (wrap-prefix #1# line-prefix #12#) 531 538 (wrap-prefix #1# line-prefix #12#) 539 540 (wrap-prefix #1# line-prefix #13=(space :width (- 29 0)) erc--msg msg erc--ts 1680332400 erc--spkr "Dummy" erc--cmd PRIVMSG display #9#) 540 545 (wrap-prefix #1# line-prefix #13# display #9#) 545 547 (wrap-prefix #1# line-prefix #13# display #9#) 547 551 (wrap-prefix #1# line-prefix #13#)) \ No newline at end of file
diff --git a/test/lisp/erc/resources/fill/snapshots/merge-wrap-01.eld b/test/lisp/erc/resources/fill/snapshots/merge-wrap-01.eld
index a3d533c87b5..feaba85ec90 100644
--- a/test/lisp/erc/resources/fill/snapshots/merge-wrap-01.eld
+++ b/test/lisp/erc/resources/fill/snapshots/merge-wrap-01.eld
@@ -1 +1 @@
-#("\n\n\n[Thu Jan 1 1970]\n*** This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect.[00:00]\n<alice> bob: come, you are a tedious fool: to the purpose. What was done to Elbow's wife, that he hath cause to complain of? Come me to what was done to her.\n<bob> alice: Either your unparagoned mistress is dead, or she's outprized by a trifle.\n\n[Sat Apr 1 2023]\n<bob> zero.[07:00]\n* bob one\n<bob> two.\n* bob three\n<bob> four.\n" 2 20 (erc-timestamp 0 line-prefix (space :width (- 27 (18))) field erc-timestamp) 20 21 (erc-timestamp 0 field erc-timestamp) 21 183 (erc-timestamp 0 wrap-prefix #2=(space :width 27) line-prefix #3=(space :width (- 27 (4)))) 183 190 (erc-timestamp 0 field erc-timestamp wrap-prefix #2# line-prefix #3# display #1=(#7=(margin right-margin) #("[00:00]" 0 7 (display #1# invisible timestamp font-lock-face erc-timestamp-face)))) 191 192 (erc-timestamp 0 wrap-prefix #2# line-prefix #4=(space :width (- 27 (8))) erc-command PRIVMSG) 192 197 (erc-timestamp 0 wrap-prefix #2# line-prefix #4# erc-command PRIVMSG) 197 199 (erc-timestamp 0 wrap-prefix #2# line-prefix #4# erc-command PRIVMSG) 199 202 (erc-timestamp 0 wrap-prefix #2# line-prefix #4# erc-command PRIVMSG) 202 315 (erc-timestamp 0 wrap-prefix #2# line-prefix #4# erc-command PRIVMSG) 315 316 (erc-timestamp 0 erc-command PRIVMSG) 316 348 (erc-timestamp 0 wrap-prefix #2# line-prefix #4# erc-command PRIVMSG) 349 350 (erc-timestamp 0 wrap-prefix #2# line-prefix #5=(space :width (- 27 (6))) erc-command PRIVMSG) 350 353 (erc-timestamp 0 wrap-prefix #2# line-prefix #5# erc-command PRIVMSG) 353 355 (erc-timestamp 0 wrap-prefix #2# line-prefix #5# erc-command PRIVMSG) 355 360 (erc-timestamp 0 wrap-prefix #2# line-prefix #5# erc-command PRIVMSG) 360 435 (erc-timestamp 0 wrap-prefix #2# line-prefix #5# erc-command PRIVMSG) 436 454 (erc-timestamp 1680332400 line-prefix (space :width (- 27 (18))) field erc-timestamp) 454 455 (erc-timestamp 1680332400 field erc-timestamp) 455 456 (erc-timestamp 1680332400 wrap-prefix #2# line-prefix #6=(space :width (- 27 (6))) erc-command PRIVMSG) 456 459 (erc-timestamp 1680332400 wrap-prefix #2# line-prefix #6# erc-command PRIVMSG) 459 466 (erc-timestamp 1680332400 wrap-prefix #2# line-prefix #6# erc-command PRIVMSG) 466 473 (erc-timestamp 1680332400 field erc-timestamp wrap-prefix #2# line-prefix #6# display #8=(#7# #("[07:00]" 0 7 (display #8# invisible timestamp font-lock-face erc-timestamp-face)))) 474 476 (erc-timestamp 1680332400 wrap-prefix #2# line-prefix #9=(space :width (- 27 (6))) erc-ctcp ACTION erc-command PRIVMSG) 476 479 (erc-timestamp 1680332400 wrap-prefix #2# line-prefix #9# erc-ctcp ACTION erc-command PRIVMSG) 479 483 (erc-timestamp 1680332400 wrap-prefix #2# line-prefix #9# erc-ctcp ACTION erc-command PRIVMSG) 484 485 (erc-timestamp 1680332400 wrap-prefix #2# line-prefix #10=(space :width (- 27 (6))) erc-command PRIVMSG) 485 488 (erc-timestamp 1680332400 wrap-prefix #2# line-prefix #10# erc-command PRIVMSG) 488 494 (erc-timestamp 1680332400 wrap-prefix #2# line-prefix #10# erc-command PRIVMSG) 495 497 (erc-timestamp 1680332400 wrap-prefix #2# line-prefix #11=(space :width (- 27 (2))) erc-ctcp ACTION erc-command PRIVMSG) 497 500 (erc-timestamp 1680332400 wrap-prefix #2# line-prefix #11# erc-ctcp ACTION erc-command PRIVMSG) 500 506 (erc-timestamp 1680332400 wrap-prefix #2# line-prefix #11# erc-ctcp ACTION erc-command PRIVMSG) 507 508 (erc-timestamp 1680332400 wrap-prefix #2# line-prefix #12=(space :width (- 27 (6))) erc-command PRIVMSG) 508 511 (erc-timestamp 1680332400 wrap-prefix #2# line-prefix #12# erc-command PRIVMSG) 511 518 (erc-timestamp 1680332400 wrap-prefix #2# line-prefix #12# erc-command PRIVMSG)) \ No newline at end of file
+#("\n\n\n[Thu Jan 1 1970]\n*** This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect.[00:00]\n<alice> bob: come, you are a tedious fool: to the purpose. What was done to Elbow's wife, that he hath cause to complain of? Come me to what was done to her.\n<bob> alice: Either your unparagoned mistress is dead, or she's outprized by a trifle.\n\n[Sat Apr 1 2023]\n<bob> zero.[07:00]\n<bob> 0.5\n* bob one.\n<bob> two.\n<bob> 2.5\n* bob three\n<bob> four.\n" 2 3 (erc--msg datestamp erc--ts 0 field erc-timestamp) 3 20 (field erc-timestamp wrap-prefix #1=(space :width 27) line-prefix (space :width (- 27 (18)))) 21 22 (erc--msg notice erc--ts 0 wrap-prefix #1# line-prefix #2=(space :width (- 27 (4)))) 22 183 (wrap-prefix #1# line-prefix #2#) 183 190 (field erc-timestamp wrap-prefix #1# line-prefix #2# display (#5=(margin right-margin) #("[00:00]" 0 7 (invisible timestamp)))) 191 192 (erc--msg msg erc--spkr "alice" erc--ts 0 erc--cmd PRIVMSG wrap-prefix #1# line-prefix #3=(space :width (- 27 (8)))) 192 197 (wrap-prefix #1# line-prefix #3#) 197 199 (wrap-prefix #1# line-prefix #3#) 199 202 (wrap-prefix #1# line-prefix #3#) 202 315 (wrap-prefix #1# line-prefix #3#) 316 348 (wrap-prefix #1# line-prefix #3#) 349 350 (erc--msg msg erc--spkr "bob" erc--ts 0 erc--cmd PRIVMSG wrap-prefix #1# line-prefix #4=(space :width (- 27 (6)))) 350 353 (wrap-prefix #1# line-prefix #4#) 353 355 (wrap-prefix #1# line-prefix #4#) 355 360 (wrap-prefix #1# line-prefix #4#) 360 435 (wrap-prefix #1# line-prefix #4#) 436 437 (erc--msg datestamp erc--ts 1680307200 field erc-timestamp) 437 454 (field erc-timestamp wrap-prefix #1# line-prefix (space :width (- 27 (18)))) 455 456 (erc--msg msg erc--spkr "bob" erc--ts 1680332400 erc--cmd PRIVMSG wrap-prefix #1# line-prefix #6=(space :width (- 27 (6)))) 456 459 (wrap-prefix #1# line-prefix #6#) 459 466 (wrap-prefix #1# line-prefix #6#) 466 473 (field erc-timestamp wrap-prefix #1# line-prefix #6# display (#5# #("[07:00]" 0 7 (invisible timestamp)))) 474 475 (erc--msg msg erc--spkr "bob" erc--ts 1680332400 erc--cmd PRIVMSG wrap-prefix #1# line-prefix #7=(space :width (- 27 0)) display #8="") 475 478 (wrap-prefix #1# line-prefix #7# display #8#) 478 480 (wrap-prefix #1# line-prefix #7# display #8#) 480 483 (wrap-prefix #1# line-prefix #7#) 484 485 (erc--msg ctcp-action erc--spkr "bob" erc--ts 1680332400 erc--cmd PRIVMSG erc--ctcp ACTION wrap-prefix #1# line-prefix #9=(space :width (- 27 (6)))) 485 486 (wrap-prefix #1# line-prefix #9#) 486 489 (wrap-prefix #1# line-prefix #9#) 489 494 (wrap-prefix #1# line-prefix #9#) 495 496 (erc--msg msg erc--spkr "bob" erc--ts 1680332400 erc--cmd PRIVMSG wrap-prefix #1# line-prefix #10=(space :width (- 27 (6)))) 496 499 (wrap-prefix #1# line-prefix #10#) 499 505 (wrap-prefix #1# line-prefix #10#) 506 507 (erc--msg msg erc--spkr "bob" erc--ts 1680332400 erc--cmd PRIVMSG wrap-prefix #1# line-prefix #11=(space :width (- 27 0)) display #8#) 507 510 (wrap-prefix #1# line-prefix #11# display #8#) 510 512 (wrap-prefix #1# line-prefix #11# display #8#) 512 515 (wrap-prefix #1# line-prefix #11#) 516 517 (erc--msg ctcp-action erc--spkr "bob" erc--ts 1680332400 erc--cmd PRIVMSG erc--ctcp ACTION wrap-prefix #1# line-prefix #12=(space :width (- 27 (2)))) 517 518 (wrap-prefix #1# line-prefix #12#) 518 521 (wrap-prefix #1# line-prefix #12#) 521 527 (wrap-prefix #1# line-prefix #12#) 528 529 (erc--msg msg erc--spkr "bob" erc--ts 1680332400 erc--cmd PRIVMSG wrap-prefix #1# line-prefix #13=(space :width (- 27 (6)))) 529 532 (wrap-prefix #1# line-prefix #13#) 532 539 (wrap-prefix #1# line-prefix #13#)) \ No newline at end of file
diff --git a/test/lisp/erc/resources/fill/snapshots/merge-wrap-indicator-post-01.eld b/test/lisp/erc/resources/fill/snapshots/merge-wrap-indicator-post-01.eld
new file mode 100644
index 00000000000..ed1488c8595
--- /dev/null
+++ b/test/lisp/erc/resources/fill/snapshots/merge-wrap-indicator-post-01.eld
@@ -0,0 +1 @@
+#("\n\n\n[Thu Jan 1 1970]\n*** This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect.[00:00]\n<alice> bob: come, you are a tedious fool: to the purpose. What was done to Elbow's wife, that he hath cause to complain of? Come me to what was done to her.\n<bob> alice: Either your unparagoned mistress is dead, or she's outprized by a trifle.\n\n[Sat Apr 1 2023]\n<bob> zero.[07:00]\n<bob> 0.5\n* bob one.\n<bob> two.\n<bob> 2.5\n* bob three\n<bob> four.\n" 2 3 (erc--msg datestamp erc--ts 0 field erc-timestamp) 3 20 (field erc-timestamp wrap-prefix #1=(space :width 27) line-prefix (space :width (- 27 (18)))) 21 22 (erc--msg notice erc--ts 0 wrap-prefix #1# line-prefix #2=(space :width (- 27 (4)))) 22 183 (wrap-prefix #1# line-prefix #2#) 183 190 (field erc-timestamp wrap-prefix #1# line-prefix #2# display (#5=(margin right-margin) #("[00:00]" 0 7 (invisible timestamp)))) 191 192 (erc--msg msg erc--spkr "alice" erc--ts 0 erc--cmd PRIVMSG wrap-prefix #1# line-prefix #3=(space :width (- 27 (8)))) 192 197 (wrap-prefix #1# line-prefix #3#) 197 199 (wrap-prefix #1# line-prefix #3#) 199 202 (wrap-prefix #1# line-prefix #3#) 202 315 (wrap-prefix #1# line-prefix #3#) 316 348 (wrap-prefix #1# line-prefix #3#) 349 350 (erc--msg msg erc--spkr "bob" erc--ts 0 erc--cmd PRIVMSG wrap-prefix #1# line-prefix #4=(space :width (- 27 (6)))) 350 353 (wrap-prefix #1# line-prefix #4#) 353 355 (wrap-prefix #1# line-prefix #4#) 355 360 (wrap-prefix #1# line-prefix #4#) 360 435 (wrap-prefix #1# line-prefix #4#) 436 437 (erc--msg datestamp erc--ts 1680307200 field erc-timestamp) 437 454 (field erc-timestamp wrap-prefix #1# line-prefix (space :width (- 27 (18)))) 455 456 (erc--msg msg erc--spkr "bob" erc--ts 1680332400 erc--cmd PRIVMSG wrap-prefix #1# line-prefix #6=(space :width (- 27 (6)))) 456 459 (wrap-prefix #1# line-prefix #6#) 459 466 (wrap-prefix #1# line-prefix #6#) 466 473 (field erc-timestamp wrap-prefix #1# line-prefix #6# display (#5# #("[07:00]" 0 7 (invisible timestamp)))) 474 475 (erc--msg msg erc--spkr "bob" erc--ts 1680332400 erc--cmd PRIVMSG wrap-prefix #1# line-prefix #7=(space :width (- 27 0)) display #8="") 475 478 (wrap-prefix #1# line-prefix #7# display #8#) 478 480 (wrap-prefix #1# line-prefix #7# display #8#) 480 483 (wrap-prefix #1# line-prefix #7#) 484 485 (erc--msg ctcp-action erc--spkr "bob" erc--ts 1680332400 erc--cmd PRIVMSG erc--ctcp ACTION wrap-prefix #1# line-prefix #9=(space :width (- 27 (6)))) 485 486 (wrap-prefix #1# line-prefix #9#) 486 489 (wrap-prefix #1# line-prefix #9#) 489 494 (wrap-prefix #1# line-prefix #9#) 495 496 (erc--msg msg erc--spkr "bob" erc--ts 1680332400 erc--cmd PRIVMSG wrap-prefix #1# line-prefix #10=(space :width (- 27 (6)))) 496 499 (wrap-prefix #1# line-prefix #10#) 499 505 (wrap-prefix #1# line-prefix #10#) 505 506 (display #("~\n" 0 2 (font-lock-face shadow))) 506 507 (erc--msg msg erc--spkr "bob" erc--ts 1680332400 erc--cmd PRIVMSG wrap-prefix #1# line-prefix #11=(space :width (- 27 0)) display #8#) 507 510 (wrap-prefix #1# line-prefix #11# display #8#) 510 512 (wrap-prefix #1# line-prefix #11# display #8#) 512 515 (wrap-prefix #1# line-prefix #11#) 516 517 (erc--msg ctcp-action erc--spkr "bob" erc--ts 1680332400 erc--cmd PRIVMSG erc--ctcp ACTION wrap-prefix #1# line-prefix #12=(space :width (- 27 (2)))) 517 518 (wrap-prefix #1# line-prefix #12#) 518 521 (wrap-prefix #1# line-prefix #12#) 521 527 (wrap-prefix #1# line-prefix #12#) 528 529 (erc--msg msg erc--spkr "bob" erc--ts 1680332400 erc--cmd PRIVMSG wrap-prefix #1# line-prefix #13=(space :width (- 27 (6)))) 529 532 (wrap-prefix #1# line-prefix #13#) 532 539 (wrap-prefix #1# line-prefix #13#)) \ No newline at end of file
diff --git a/test/lisp/erc/resources/fill/snapshots/merge-wrap-indicator-pre-01.eld b/test/lisp/erc/resources/fill/snapshots/merge-wrap-indicator-pre-01.eld
new file mode 100644
index 00000000000..a3530a6c44d
--- /dev/null
+++ b/test/lisp/erc/resources/fill/snapshots/merge-wrap-indicator-pre-01.eld
@@ -0,0 +1 @@
+#("\n\n\n[Thu Jan 1 1970]\n*** This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect.[00:00]\n<alice> bob: come, you are a tedious fool: to the purpose. What was done to Elbow's wife, that he hath cause to complain of? Come me to what was done to her.\n<bob> alice: Either your unparagoned mistress is dead, or she's outprized by a trifle.\n\n[Sat Apr 1 2023]\n<bob> zero.[07:00]\n<bob> 0.5\n* bob one.\n<bob> two.\n<bob> 2.5\n* bob three\n<bob> four.\n" 2 3 (erc--msg datestamp erc--ts 0 field erc-timestamp) 3 20 (field erc-timestamp wrap-prefix #1=(space :width 27) line-prefix (space :width (- 27 (18)))) 21 22 (erc--msg notice erc--ts 0 wrap-prefix #1# line-prefix #2=(space :width (- 27 (4)))) 22 183 (wrap-prefix #1# line-prefix #2#) 183 190 (field erc-timestamp wrap-prefix #1# line-prefix #2# display (#5=(margin right-margin) #("[00:00]" 0 7 (invisible timestamp)))) 191 192 (erc--msg msg erc--spkr "alice" erc--ts 0 erc--cmd PRIVMSG wrap-prefix #1# line-prefix #3=(space :width (- 27 (8)))) 192 197 (wrap-prefix #1# line-prefix #3#) 197 199 (wrap-prefix #1# line-prefix #3#) 199 202 (wrap-prefix #1# line-prefix #3#) 202 315 (wrap-prefix #1# line-prefix #3#) 316 348 (wrap-prefix #1# line-prefix #3#) 349 350 (erc--msg msg erc--spkr "bob" erc--ts 0 erc--cmd PRIVMSG wrap-prefix #1# line-prefix #4=(space :width (- 27 (6)))) 350 353 (wrap-prefix #1# line-prefix #4#) 353 355 (wrap-prefix #1# line-prefix #4#) 355 360 (wrap-prefix #1# line-prefix #4#) 360 435 (wrap-prefix #1# line-prefix #4#) 436 437 (erc--msg datestamp erc--ts 1680307200 field erc-timestamp) 437 454 (field erc-timestamp wrap-prefix #1# line-prefix (space :width (- 27 (18)))) 455 456 (erc--msg msg erc--spkr "bob" erc--ts 1680332400 erc--cmd PRIVMSG wrap-prefix #1# line-prefix #6=(space :width (- 27 (6)))) 456 459 (wrap-prefix #1# line-prefix #6#) 459 466 (wrap-prefix #1# line-prefix #6#) 466 473 (field erc-timestamp wrap-prefix #1# line-prefix #6# display (#5# #("[07:00]" 0 7 (invisible timestamp)))) 474 475 (erc--msg msg erc--spkr "bob" erc--ts 1680332400 erc--cmd PRIVMSG wrap-prefix #1# line-prefix #7=(space :width (- 27 #10=(2))) display #8=#("> " 0 1 (font-lock-face shadow))) 475 478 (wrap-prefix #1# line-prefix #7# display #8#) 478 480 (wrap-prefix #1# line-prefix #7# display #8#) 480 483 (wrap-prefix #1# line-prefix #7#) 484 485 (erc--msg ctcp-action erc--spkr "bob" erc--ts 1680332400 erc--cmd PRIVMSG erc--ctcp ACTION wrap-prefix #1# line-prefix #9=(space :width (- 27 (6)))) 485 486 (wrap-prefix #1# line-prefix #9#) 486 489 (wrap-prefix #1# line-prefix #9#) 489 494 (wrap-prefix #1# line-prefix #9#) 495 496 (erc--msg msg erc--spkr "bob" erc--ts 1680332400 erc--cmd PRIVMSG wrap-prefix #1# line-prefix #11=(space :width (- 27 (6)))) 496 499 (wrap-prefix #1# line-prefix #11#) 499 505 (wrap-prefix #1# line-prefix #11#) 506 507 (erc--msg msg erc--spkr "bob" erc--ts 1680332400 erc--cmd PRIVMSG wrap-prefix #1# line-prefix #12=(space :width (- 27 #10#)) display #8#) 507 510 (wrap-prefix #1# line-prefix #12# display #8#) 510 512 (wrap-prefix #1# line-prefix #12# display #8#) 512 515 (wrap-prefix #1# line-prefix #12#) 516 517 (erc--msg ctcp-action erc--spkr "bob" erc--ts 1680332400 erc--cmd PRIVMSG erc--ctcp ACTION wrap-prefix #1# line-prefix #13=(space :width (- 27 (2)))) 517 518 (wrap-prefix #1# line-prefix #13#) 518 521 (wrap-prefix #1# line-prefix #13#) 521 527 (wrap-prefix #1# line-prefix #13#) 528 529 (erc--msg msg erc--spkr "bob" erc--ts 1680332400 erc--cmd PRIVMSG wrap-prefix #1# line-prefix #14=(space :width (- 27 (6)))) 529 532 (wrap-prefix #1# line-prefix #14#) 532 539 (wrap-prefix #1# line-prefix #14#)) \ No newline at end of file
diff --git a/test/lisp/erc/resources/fill/snapshots/monospace-01-start.eld b/test/lisp/erc/resources/fill/snapshots/monospace-01-start.eld
index 80c9e1d80f5..c94629cf357 100644
--- a/test/lisp/erc/resources/fill/snapshots/monospace-01-start.eld
+++ b/test/lisp/erc/resources/fill/snapshots/monospace-01-start.eld
@@ -1 +1 @@
-#("\n\n\n[Thu Jan 1 1970]\n*** This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect.[00:00]\n<alice> bob: come, you are a tedious fool: to the purpose. What was done to Elbow's wife, that he hath cause to complain of? Come me to what was done to her.\n<bob> alice: Either your unparagoned mistress is dead, or she's outprized by a trifle.\n" 2 20 (erc-timestamp 0 line-prefix (space :width (- 27 (18))) field erc-timestamp) 20 21 (erc-timestamp 0 field erc-timestamp) 21 183 (erc-timestamp 0 wrap-prefix #2=(space :width 27) line-prefix #3=(space :width (- 27 (4)))) 183 190 (erc-timestamp 0 field erc-timestamp wrap-prefix #2# line-prefix #3# display #1=((margin right-margin) #("[00:00]" 0 7 (display #1# isearch-open-invisible timestamp invisible timestamp font-lock-face erc-timestamp-face)))) 191 192 (erc-timestamp 0 wrap-prefix #2# line-prefix #4=(space :width (- 27 (8))) erc-command PRIVMSG) 192 197 (erc-timestamp 0 wrap-prefix #2# line-prefix #4# erc-command PRIVMSG) 197 199 (erc-timestamp 0 wrap-prefix #2# line-prefix #4# erc-command PRIVMSG) 199 202 (erc-timestamp 0 wrap-prefix #2# line-prefix #4# erc-command PRIVMSG) 202 315 (erc-timestamp 0 wrap-prefix #2# line-prefix #4# erc-command PRIVMSG) 315 316 (erc-timestamp 0 erc-command PRIVMSG) 316 348 (erc-timestamp 0 wrap-prefix #2# line-prefix #4# erc-command PRIVMSG) 349 350 (erc-timestamp 0 wrap-prefix #2# line-prefix #5=(space :width (- 27 (6))) erc-command PRIVMSG) 350 353 (erc-timestamp 0 wrap-prefix #2# line-prefix #5# erc-command PRIVMSG) 353 355 (erc-timestamp 0 wrap-prefix #2# line-prefix #5# erc-command PRIVMSG) 355 360 (erc-timestamp 0 wrap-prefix #2# line-prefix #5# erc-command PRIVMSG) 360 435 (erc-timestamp 0 wrap-prefix #2# line-prefix #5# erc-command PRIVMSG)) \ No newline at end of file
+#("\n\n\n[Thu Jan 1 1970]\n*** This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect.[00:00]\n<alice> bob: come, you are a tedious fool: to the purpose. What was done to Elbow's wife, that he hath cause to complain of? Come me to what was done to her.\n<bob> alice: Either your unparagoned mistress is dead, or she's outprized by a trifle.\n" 2 3 (erc--msg datestamp erc--ts 0 field erc-timestamp) 3 20 (field erc-timestamp wrap-prefix #1=(space :width 27) line-prefix (space :width (- 27 (18)))) 21 22 (erc--msg notice erc--ts 0 wrap-prefix #1# line-prefix #2=(space :width (- 27 (4)))) 22 183 (wrap-prefix #1# line-prefix #2#) 183 190 (field erc-timestamp wrap-prefix #1# line-prefix #2# display ((margin right-margin) #("[00:00]" 0 7 (invisible timestamp)))) 191 192 (erc--msg msg erc--ts 0 erc--spkr "alice" erc--cmd PRIVMSG wrap-prefix #1# line-prefix #3=(space :width (- 27 (8)))) 192 197 (wrap-prefix #1# line-prefix #3#) 197 199 (wrap-prefix #1# line-prefix #3#) 199 202 (wrap-prefix #1# line-prefix #3#) 202 315 (wrap-prefix #1# line-prefix #3#) 316 348 (wrap-prefix #1# line-prefix #3#) 349 350 (erc--msg msg erc--ts 0 erc--spkr "bob" erc--cmd PRIVMSG wrap-prefix #1# line-prefix #4=(space :width (- 27 (6)))) 350 353 (wrap-prefix #1# line-prefix #4#) 353 355 (wrap-prefix #1# line-prefix #4#) 355 360 (wrap-prefix #1# line-prefix #4#) 360 435 (wrap-prefix #1# line-prefix #4#)) \ No newline at end of file
diff --git a/test/lisp/erc/resources/fill/snapshots/monospace-02-right.eld b/test/lisp/erc/resources/fill/snapshots/monospace-02-right.eld
index e675695f660..127c0b29bc9 100644
--- a/test/lisp/erc/resources/fill/snapshots/monospace-02-right.eld
+++ b/test/lisp/erc/resources/fill/snapshots/monospace-02-right.eld
@@ -1 +1 @@
-#("\n\n\n[Thu Jan 1 1970]\n*** This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect.[00:00]\n<alice> bob: come, you are a tedious fool: to the purpose. What was done to Elbow's wife, that he hath cause to complain of? Come me to what was done to her.\n<bob> alice: Either your unparagoned mistress is dead, or she's outprized by a trifle.\n" 2 20 (erc-timestamp 0 line-prefix (space :width (- 29 (18))) field erc-timestamp) 20 21 (erc-timestamp 0 field erc-timestamp) 21 183 (erc-timestamp 0 wrap-prefix #2=(space :width 29) line-prefix #3=(space :width (- 29 (4)))) 183 190 (erc-timestamp 0 field erc-timestamp wrap-prefix #2# line-prefix #3# display #1=((margin right-margin) #("[00:00]" 0 7 (display #1# isearch-open-invisible timestamp invisible timestamp font-lock-face erc-timestamp-face)))) 191 192 (erc-timestamp 0 wrap-prefix #2# line-prefix #4=(space :width (- 29 (8))) erc-command PRIVMSG) 192 197 (erc-timestamp 0 wrap-prefix #2# line-prefix #4# erc-command PRIVMSG) 197 199 (erc-timestamp 0 wrap-prefix #2# line-prefix #4# erc-command PRIVMSG) 199 202 (erc-timestamp 0 wrap-prefix #2# line-prefix #4# erc-command PRIVMSG) 202 315 (erc-timestamp 0 wrap-prefix #2# line-prefix #4# erc-command PRIVMSG) 315 316 (erc-timestamp 0 erc-command PRIVMSG) 316 348 (erc-timestamp 0 wrap-prefix #2# line-prefix #4# erc-command PRIVMSG) 349 350 (erc-timestamp 0 wrap-prefix #2# line-prefix #5=(space :width (- 29 (6))) erc-command PRIVMSG) 350 353 (erc-timestamp 0 wrap-prefix #2# line-prefix #5# erc-command PRIVMSG) 353 355 (erc-timestamp 0 wrap-prefix #2# line-prefix #5# erc-command PRIVMSG) 355 360 (erc-timestamp 0 wrap-prefix #2# line-prefix #5# erc-command PRIVMSG) 360 435 (erc-timestamp 0 wrap-prefix #2# line-prefix #5# erc-command PRIVMSG)) \ No newline at end of file
+#("\n\n\n[Thu Jan 1 1970]\n*** This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect.[00:00]\n<alice> bob: come, you are a tedious fool: to the purpose. What was done to Elbow's wife, that he hath cause to complain of? Come me to what was done to her.\n<bob> alice: Either your unparagoned mistress is dead, or she's outprized by a trifle.\n" 2 3 (erc--msg datestamp erc--ts 0 field erc-timestamp) 3 20 (field erc-timestamp wrap-prefix #1=(space :width 29) line-prefix (space :width (- 29 (18)))) 21 22 (erc--msg notice erc--ts 0 wrap-prefix #1# line-prefix #2=(space :width (- 29 (4)))) 22 183 (wrap-prefix #1# line-prefix #2#) 183 190 (field erc-timestamp wrap-prefix #1# line-prefix #2# display ((margin right-margin) #("[00:00]" 0 7 (invisible timestamp)))) 191 192 (erc--msg msg erc--ts 0 erc--spkr "alice" erc--cmd PRIVMSG wrap-prefix #1# line-prefix #3=(space :width (- 29 (8)))) 192 197 (wrap-prefix #1# line-prefix #3#) 197 199 (wrap-prefix #1# line-prefix #3#) 199 202 (wrap-prefix #1# line-prefix #3#) 202 315 (wrap-prefix #1# line-prefix #3#) 316 348 (wrap-prefix #1# line-prefix #3#) 349 350 (erc--msg msg erc--ts 0 erc--spkr "bob" erc--cmd PRIVMSG wrap-prefix #1# line-prefix #4=(space :width (- 29 (6)))) 350 353 (wrap-prefix #1# line-prefix #4#) 353 355 (wrap-prefix #1# line-prefix #4#) 355 360 (wrap-prefix #1# line-prefix #4#) 360 435 (wrap-prefix #1# line-prefix #4#)) \ No newline at end of file
diff --git a/test/lisp/erc/resources/fill/snapshots/monospace-03-left.eld b/test/lisp/erc/resources/fill/snapshots/monospace-03-left.eld
index a6070c2e3ff..a9f3f1d1904 100644
--- a/test/lisp/erc/resources/fill/snapshots/monospace-03-left.eld
+++ b/test/lisp/erc/resources/fill/snapshots/monospace-03-left.eld
@@ -1 +1 @@
-#("\n\n\n[Thu Jan 1 1970]\n*** This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect.[00:00]\n<alice> bob: come, you are a tedious fool: to the purpose. What was done to Elbow's wife, that he hath cause to complain of? Come me to what was done to her.\n<bob> alice: Either your unparagoned mistress is dead, or she's outprized by a trifle.\n" 2 20 (erc-timestamp 0 line-prefix (space :width (- 25 (18))) field erc-timestamp) 20 21 (erc-timestamp 0 field erc-timestamp) 21 183 (erc-timestamp 0 wrap-prefix #2=(space :width 25) line-prefix #3=(space :width (- 25 (4)))) 183 190 (erc-timestamp 0 field erc-timestamp wrap-prefix #2# line-prefix #3# display #1=((margin right-margin) #("[00:00]" 0 7 (display #1# isearch-open-invisible timestamp invisible timestamp font-lock-face erc-timestamp-face)))) 191 192 (erc-timestamp 0 wrap-prefix #2# line-prefix #4=(space :width (- 25 (8))) erc-command PRIVMSG) 192 197 (erc-timestamp 0 wrap-prefix #2# line-prefix #4# erc-command PRIVMSG) 197 199 (erc-timestamp 0 wrap-prefix #2# line-prefix #4# erc-command PRIVMSG) 199 202 (erc-timestamp 0 wrap-prefix #2# line-prefix #4# erc-command PRIVMSG) 202 315 (erc-timestamp 0 wrap-prefix #2# line-prefix #4# erc-command PRIVMSG) 315 316 (erc-timestamp 0 erc-command PRIVMSG) 316 348 (erc-timestamp 0 wrap-prefix #2# line-prefix #4# erc-command PRIVMSG) 349 350 (erc-timestamp 0 wrap-prefix #2# line-prefix #5=(space :width (- 25 (6))) erc-command PRIVMSG) 350 353 (erc-timestamp 0 wrap-prefix #2# line-prefix #5# erc-command PRIVMSG) 353 355 (erc-timestamp 0 wrap-prefix #2# line-prefix #5# erc-command PRIVMSG) 355 360 (erc-timestamp 0 wrap-prefix #2# line-prefix #5# erc-command PRIVMSG) 360 435 (erc-timestamp 0 wrap-prefix #2# line-prefix #5# erc-command PRIVMSG)) \ No newline at end of file
+#("\n\n\n[Thu Jan 1 1970]\n*** This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect.[00:00]\n<alice> bob: come, you are a tedious fool: to the purpose. What was done to Elbow's wife, that he hath cause to complain of? Come me to what was done to her.\n<bob> alice: Either your unparagoned mistress is dead, or she's outprized by a trifle.\n" 2 3 (erc--msg datestamp erc--ts 0 field erc-timestamp) 3 20 (field erc-timestamp wrap-prefix #1=(space :width 25) line-prefix (space :width (- 25 (18)))) 21 22 (erc--msg notice erc--ts 0 wrap-prefix #1# line-prefix #2=(space :width (- 25 (4)))) 22 183 (wrap-prefix #1# line-prefix #2#) 183 190 (field erc-timestamp wrap-prefix #1# line-prefix #2# display ((margin right-margin) #("[00:00]" 0 7 (invisible timestamp)))) 191 192 (erc--msg msg erc--ts 0 erc--spkr "alice" erc--cmd PRIVMSG wrap-prefix #1# line-prefix #3=(space :width (- 25 (8)))) 192 197 (wrap-prefix #1# line-prefix #3#) 197 199 (wrap-prefix #1# line-prefix #3#) 199 202 (wrap-prefix #1# line-prefix #3#) 202 315 (wrap-prefix #1# line-prefix #3#) 316 348 (wrap-prefix #1# line-prefix #3#) 349 350 (erc--msg msg erc--ts 0 erc--spkr "bob" erc--cmd PRIVMSG wrap-prefix #1# line-prefix #4=(space :width (- 25 (6)))) 350 353 (wrap-prefix #1# line-prefix #4#) 353 355 (wrap-prefix #1# line-prefix #4#) 355 360 (wrap-prefix #1# line-prefix #4#) 360 435 (wrap-prefix #1# line-prefix #4#)) \ No newline at end of file
diff --git a/test/lisp/erc/resources/fill/snapshots/monospace-04-reset.eld b/test/lisp/erc/resources/fill/snapshots/monospace-04-reset.eld
index 80c9e1d80f5..c94629cf357 100644
--- a/test/lisp/erc/resources/fill/snapshots/monospace-04-reset.eld
+++ b/test/lisp/erc/resources/fill/snapshots/monospace-04-reset.eld
@@ -1 +1 @@
-#("\n\n\n[Thu Jan 1 1970]\n*** This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect.[00:00]\n<alice> bob: come, you are a tedious fool: to the purpose. What was done to Elbow's wife, that he hath cause to complain of? Come me to what was done to her.\n<bob> alice: Either your unparagoned mistress is dead, or she's outprized by a trifle.\n" 2 20 (erc-timestamp 0 line-prefix (space :width (- 27 (18))) field erc-timestamp) 20 21 (erc-timestamp 0 field erc-timestamp) 21 183 (erc-timestamp 0 wrap-prefix #2=(space :width 27) line-prefix #3=(space :width (- 27 (4)))) 183 190 (erc-timestamp 0 field erc-timestamp wrap-prefix #2# line-prefix #3# display #1=((margin right-margin) #("[00:00]" 0 7 (display #1# isearch-open-invisible timestamp invisible timestamp font-lock-face erc-timestamp-face)))) 191 192 (erc-timestamp 0 wrap-prefix #2# line-prefix #4=(space :width (- 27 (8))) erc-command PRIVMSG) 192 197 (erc-timestamp 0 wrap-prefix #2# line-prefix #4# erc-command PRIVMSG) 197 199 (erc-timestamp 0 wrap-prefix #2# line-prefix #4# erc-command PRIVMSG) 199 202 (erc-timestamp 0 wrap-prefix #2# line-prefix #4# erc-command PRIVMSG) 202 315 (erc-timestamp 0 wrap-prefix #2# line-prefix #4# erc-command PRIVMSG) 315 316 (erc-timestamp 0 erc-command PRIVMSG) 316 348 (erc-timestamp 0 wrap-prefix #2# line-prefix #4# erc-command PRIVMSG) 349 350 (erc-timestamp 0 wrap-prefix #2# line-prefix #5=(space :width (- 27 (6))) erc-command PRIVMSG) 350 353 (erc-timestamp 0 wrap-prefix #2# line-prefix #5# erc-command PRIVMSG) 353 355 (erc-timestamp 0 wrap-prefix #2# line-prefix #5# erc-command PRIVMSG) 355 360 (erc-timestamp 0 wrap-prefix #2# line-prefix #5# erc-command PRIVMSG) 360 435 (erc-timestamp 0 wrap-prefix #2# line-prefix #5# erc-command PRIVMSG)) \ No newline at end of file
+#("\n\n\n[Thu Jan 1 1970]\n*** This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect.[00:00]\n<alice> bob: come, you are a tedious fool: to the purpose. What was done to Elbow's wife, that he hath cause to complain of? Come me to what was done to her.\n<bob> alice: Either your unparagoned mistress is dead, or she's outprized by a trifle.\n" 2 3 (erc--msg datestamp erc--ts 0 field erc-timestamp) 3 20 (field erc-timestamp wrap-prefix #1=(space :width 27) line-prefix (space :width (- 27 (18)))) 21 22 (erc--msg notice erc--ts 0 wrap-prefix #1# line-prefix #2=(space :width (- 27 (4)))) 22 183 (wrap-prefix #1# line-prefix #2#) 183 190 (field erc-timestamp wrap-prefix #1# line-prefix #2# display ((margin right-margin) #("[00:00]" 0 7 (invisible timestamp)))) 191 192 (erc--msg msg erc--ts 0 erc--spkr "alice" erc--cmd PRIVMSG wrap-prefix #1# line-prefix #3=(space :width (- 27 (8)))) 192 197 (wrap-prefix #1# line-prefix #3#) 197 199 (wrap-prefix #1# line-prefix #3#) 199 202 (wrap-prefix #1# line-prefix #3#) 202 315 (wrap-prefix #1# line-prefix #3#) 316 348 (wrap-prefix #1# line-prefix #3#) 349 350 (erc--msg msg erc--ts 0 erc--spkr "bob" erc--cmd PRIVMSG wrap-prefix #1# line-prefix #4=(space :width (- 27 (6)))) 350 353 (wrap-prefix #1# line-prefix #4#) 353 355 (wrap-prefix #1# line-prefix #4#) 355 360 (wrap-prefix #1# line-prefix #4#) 360 435 (wrap-prefix #1# line-prefix #4#)) \ No newline at end of file
diff --git a/test/lisp/erc/resources/fill/snapshots/spacing-01-mono.eld b/test/lisp/erc/resources/fill/snapshots/spacing-01-mono.eld
index 2b8766c27f4..754d7989cea 100644
--- a/test/lisp/erc/resources/fill/snapshots/spacing-01-mono.eld
+++ b/test/lisp/erc/resources/fill/snapshots/spacing-01-mono.eld
@@ -1 +1 @@
-#("\n\n\n[Thu Jan 1 1970]\n*** This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect.[00:00]\n<alice> bob: come, you are a tedious fool: to the purpose. What was done to Elbow's wife, that he hath cause to complain of? Come me to what was done to her.\n<bob> alice: Either your unparagoned mistress is dead, or she's outprized by a trifle.\n<bob> This buffer is for text.\n*** one two three\n*** four five six\n<bob> Somebody stop me\n" 2 20 (erc-timestamp 0 line-prefix (space :width (- 27 (18))) field erc-timestamp) 20 21 (erc-timestamp 0 field erc-timestamp) 21 183 (erc-timestamp 0 wrap-prefix #2=(space :width 27) line-prefix #3=(space :width (- 27 (4)))) 183 190 (erc-timestamp 0 field erc-timestamp wrap-prefix #2# line-prefix #3# display #1=((margin right-margin) #("[00:00]" 0 7 (display #1# isearch-open-invisible timestamp invisible timestamp font-lock-face erc-timestamp-face)))) 190 191 (line-spacing 0.5) 191 192 (erc-timestamp 0 wrap-prefix #2# line-prefix #4=(space :width (- 27 (8))) erc-command PRIVMSG) 192 197 (erc-timestamp 0 wrap-prefix #2# line-prefix #4# erc-command PRIVMSG) 197 199 (erc-timestamp 0 wrap-prefix #2# line-prefix #4# erc-command PRIVMSG) 199 202 (erc-timestamp 0 wrap-prefix #2# line-prefix #4# erc-command PRIVMSG) 202 315 (erc-timestamp 0 wrap-prefix #2# line-prefix #4# erc-command PRIVMSG) 315 316 (erc-timestamp 0 erc-command PRIVMSG) 316 348 (erc-timestamp 0 wrap-prefix #2# line-prefix #4# erc-command PRIVMSG) 348 349 (line-spacing 0.5) 349 350 (erc-timestamp 0 wrap-prefix #2# line-prefix #5=(space :width (- 27 (6))) erc-command PRIVMSG) 350 353 (erc-timestamp 0 wrap-prefix #2# line-prefix #5# erc-command PRIVMSG) 353 355 (erc-timestamp 0 wrap-prefix #2# line-prefix #5# erc-command PRIVMSG) 355 360 (erc-timestamp 0 wrap-prefix #2# line-prefix #5# erc-command PRIVMSG) 360 435 (erc-timestamp 0 wrap-prefix #2# line-prefix #5# erc-command PRIVMSG) 435 436 (line-spacing 0.5) 436 437 (erc-timestamp 0 wrap-prefix #2# line-prefix #6=(space :width (- 27 0)) display #7="" erc-command PRIVMSG) 437 440 (erc-timestamp 0 wrap-prefix #2# line-prefix #6# display #7# erc-command PRIVMSG) 440 442 (erc-timestamp 0 wrap-prefix #2# line-prefix #6# display #7# erc-command PRIVMSG) 442 466 (erc-timestamp 0 wrap-prefix #2# line-prefix #6# erc-command PRIVMSG) 466 467 (line-spacing 0.5) 467 484 (erc-timestamp 0 wrap-prefix #2# line-prefix (space :width (- 27 (4)))) 485 502 (erc-timestamp 0 wrap-prefix #2# line-prefix (space :width (- 27 (4)))) 502 503 (line-spacing 0.5) 503 504 (erc-timestamp 0 wrap-prefix #2# line-prefix #8=(space :width (- 27 (6))) erc-command PRIVMSG) 504 507 (erc-timestamp 0 wrap-prefix #2# line-prefix #8# erc-command PRIVMSG) 507 525 (erc-timestamp 0 wrap-prefix #2# line-prefix #8# erc-command PRIVMSG)) \ No newline at end of file
+#("\n\n\n[Thu Jan 1 1970]\n*** This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect.[00:00]\n<alice> bob: come, you are a tedious fool: to the purpose. What was done to Elbow's wife, that he hath cause to complain of? Come me to what was done to her.\n<bob> alice: Either your unparagoned mistress is dead, or she's outprized by a trifle.\n<bob> This buffer is for text.\n*** one two three\n*** four five six\n<bob> Somebody stop me\n" 2 3 (erc--msg datestamp erc--ts 0 field erc-timestamp) 3 20 (field erc-timestamp wrap-prefix #1=(space :width 27) line-prefix (space :width (- 27 (18)))) 21 22 (erc--msg notice erc--ts 0 wrap-prefix #1# line-prefix #2=(space :width (- 27 (4)))) 22 183 (wrap-prefix #1# line-prefix #2#) 183 190 (field erc-timestamp wrap-prefix #1# line-prefix #2# display ((margin right-margin) #("[00:00]" 0 7 (invisible timestamp)))) 190 191 (line-spacing 0.5) 191 192 (erc--msg msg erc--ts 0 erc--spkr "alice" erc--cmd PRIVMSG wrap-prefix #1# line-prefix #3=(space :width (- 27 (8)))) 192 197 (wrap-prefix #1# line-prefix #3#) 197 199 (wrap-prefix #1# line-prefix #3#) 199 202 (wrap-prefix #1# line-prefix #3#) 202 315 (wrap-prefix #1# line-prefix #3#) 316 348 (wrap-prefix #1# line-prefix #3#) 348 349 (line-spacing 0.5) 349 350 (erc--msg msg erc--ts 0 erc--spkr "bob" erc--cmd PRIVMSG wrap-prefix #1# line-prefix #4=(space :width (- 27 (6)))) 350 353 (wrap-prefix #1# line-prefix #4#) 353 355 (wrap-prefix #1# line-prefix #4#) 355 360 (wrap-prefix #1# line-prefix #4#) 360 435 (wrap-prefix #1# line-prefix #4#) 435 436 (line-spacing 0.5) 436 437 (erc--msg msg erc--ts 0 erc--spkr "bob" erc--cmd PRIVMSG wrap-prefix #1# line-prefix #5=(space :width (- 27 0)) display #6="") 437 440 (wrap-prefix #1# line-prefix #5# display #6#) 440 442 (wrap-prefix #1# line-prefix #5# display #6#) 442 466 (wrap-prefix #1# line-prefix #5#) 466 467 (line-spacing 0.5) 467 468 (erc--msg notice erc--ts 0 wrap-prefix #1# line-prefix #7=(space :width (- 27 (4)))) 468 484 (wrap-prefix #1# line-prefix #7#) 485 486 (erc--msg notice erc--ts 0 wrap-prefix #1# line-prefix #8=(space :width (- 27 (4)))) 486 502 (wrap-prefix #1# line-prefix #8#) 502 503 (line-spacing 0.5) 503 504 (erc--msg msg erc--ts 0 erc--spkr "bob" erc--cmd PRIVMSG wrap-prefix #1# line-prefix #9=(space :width (- 27 (6)))) 504 507 (wrap-prefix #1# line-prefix #9#) 507 525 (wrap-prefix #1# line-prefix #9#)) \ No newline at end of file
diff --git a/test/lisp/erc/resources/fill/snapshots/stamps-left-01.eld b/test/lisp/erc/resources/fill/snapshots/stamps-left-01.eld
index f62b65cd170..1b22b6c5cfd 100644
--- a/test/lisp/erc/resources/fill/snapshots/stamps-left-01.eld
+++ b/test/lisp/erc/resources/fill/snapshots/stamps-left-01.eld
@@ -1 +1 @@
-#("\n\n[00:00]*** This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect.\n[00:00]<alice> bob: come, you are a tedious fool: to the purpose. What was done to Elbow's wife, that he hath cause to complain of? Come me to what was done to her.\n[00:00]<bob> alice: Either your unparagoned mistress is dead, or she's outprized by a trifle.\n" 2 9 (erc-timestamp 0 display (#4=(margin left-margin) #("[00:00]" 0 7 (invisible timestamp font-lock-face erc-timestamp-face))) field erc-timestamp wrap-prefix #1=(space :width 27) line-prefix #2=(space :width (- 27 (4)))) 9 171 (erc-timestamp 0 wrap-prefix #1# line-prefix #2#) 172 179 (erc-timestamp 0 display (#4# #("[00:00]" 0 7 (invisible timestamp font-lock-face erc-timestamp-face))) field erc-timestamp wrap-prefix #1# line-prefix #3=(space :width (- 27 (8)))) 179 180 (erc-timestamp 0 wrap-prefix #1# line-prefix #3# erc-command PRIVMSG) 180 185 (erc-timestamp 0 wrap-prefix #1# line-prefix #3# erc-command PRIVMSG) 185 187 (erc-timestamp 0 wrap-prefix #1# line-prefix #3# erc-command PRIVMSG) 187 190 (erc-timestamp 0 wrap-prefix #1# line-prefix #3# erc-command PRIVMSG) 190 303 (erc-timestamp 0 wrap-prefix #1# line-prefix #3# erc-command PRIVMSG) 303 304 (erc-timestamp 0 erc-command PRIVMSG) 304 336 (erc-timestamp 0 wrap-prefix #1# line-prefix #3# erc-command PRIVMSG) 337 344 (erc-timestamp 0 display (#4# #("[00:00]" 0 7 (invisible timestamp font-lock-face erc-timestamp-face))) field erc-timestamp wrap-prefix #1# line-prefix #5=(space :width (- 27 (6)))) 344 345 (erc-timestamp 0 wrap-prefix #1# line-prefix #5# erc-command PRIVMSG) 345 348 (erc-timestamp 0 wrap-prefix #1# line-prefix #5# erc-command PRIVMSG) 348 350 (erc-timestamp 0 wrap-prefix #1# line-prefix #5# erc-command PRIVMSG) 350 355 (erc-timestamp 0 wrap-prefix #1# line-prefix #5# erc-command PRIVMSG) 355 430 (erc-timestamp 0 wrap-prefix #1# line-prefix #5# erc-command PRIVMSG)) \ No newline at end of file
+#("\n\n[00:00]*** This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect.\n[00:00]<alice> bob: come, you are a tedious fool: to the purpose. What was done to Elbow's wife, that he hath cause to complain of? Come me to what was done to her.\n[00:00]<bob> alice: Either your unparagoned mistress is dead, or she's outprized by a trifle.\n" 2 3 (erc--msg notice erc--ts 0 display #3=(#5=(margin left-margin) #("[00:00]" 0 7 (invisible timestamp font-lock-face erc-timestamp-face))) field erc-timestamp wrap-prefix #1=(space :width 27) line-prefix #2=(space :width (- 27 (4)))) 3 9 (display #3# field erc-timestamp wrap-prefix #1# line-prefix #2#) 9 171 (wrap-prefix #1# line-prefix #2#) 172 173 (erc--msg msg erc--ts 0 erc--spkr "alice" erc--cmd PRIVMSG display #6=(#5# #("[00:00]" 0 7 (invisible timestamp font-lock-face erc-timestamp-face))) field erc-timestamp wrap-prefix #1# line-prefix #4=(space :width (- 27 (8)))) 173 179 (display #6# field erc-timestamp wrap-prefix #1# line-prefix #4#) 179 180 (wrap-prefix #1# line-prefix #4#) 180 185 (wrap-prefix #1# line-prefix #4#) 185 187 (wrap-prefix #1# line-prefix #4#) 187 190 (wrap-prefix #1# line-prefix #4#) 190 303 (wrap-prefix #1# line-prefix #4#) 304 336 (wrap-prefix #1# line-prefix #4#) 337 338 (erc--msg msg erc--ts 0 erc--spkr "bob" erc--cmd PRIVMSG display #8=(#5# #("[00:00]" 0 7 (invisible timestamp font-lock-face erc-timestamp-face))) field erc-timestamp wrap-prefix #1# line-prefix #7=(space :width (- 27 (6)))) 338 344 (display #8# field erc-timestamp wrap-prefix #1# line-prefix #7#) 344 345 (wrap-prefix #1# line-prefix #7#) 345 348 (wrap-prefix #1# line-prefix #7#) 348 350 (wrap-prefix #1# line-prefix #7#) 350 355 (wrap-prefix #1# line-prefix #7#) 355 430 (wrap-prefix #1# line-prefix #7#)) \ No newline at end of file
diff --git a/test/lisp/erc/resources/join/legacy/foonet.eld b/test/lisp/erc/resources/join/legacy/foonet.eld
index 4025094a59c..5c0ea13b6a7 100644
--- a/test/lisp/erc/resources/join/legacy/foonet.eld
+++ b/test/lisp/erc/resources/join/legacy/foonet.eld
@@ -18,7 +18,7 @@
(0 ":irc.foonet.org 266 tester 3 3 :Current global users 3, max 3")
(0 ":irc.foonet.org 422 tester :MOTD File is missing"))
-((mode-user 3.2 "MODE tester +i")
+((mode-user 10 "MODE tester +i")
(0 ":irc.foonet.org 221 tester +i")
(0 ":irc.foonet.org NOTICE tester :This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect."))
diff --git a/test/lisp/erc/resources/join/network-id/barnet.eld b/test/lisp/erc/resources/join/network-id/barnet.eld
index e33dd6be29e..ad6a7c820a9 100644
--- a/test/lisp/erc/resources/join/network-id/barnet.eld
+++ b/test/lisp/erc/resources/join/network-id/barnet.eld
@@ -40,4 +40,4 @@
(0.05 ":mike!~u@6yximxrnkg65a.irc PRIVMSG #chan :joe: And now, dear maid, be you as free to us.")
(0.00 ":joe!~u@6yximxrnkg65a.irc PRIVMSG #chan :mike: He hath an uncle here in Messina will be very much glad of it."))
-((linger 3.5 LINGER))
+((linger 30 LINGER))
diff --git a/test/lisp/erc/resources/join/network-id/foonet-again.eld b/test/lisp/erc/resources/join/network-id/foonet-again.eld
index b230eff27c7..a8b8a52f87a 100644
--- a/test/lisp/erc/resources/join/network-id/foonet-again.eld
+++ b/test/lisp/erc/resources/join/network-id/foonet-again.eld
@@ -43,4 +43,4 @@
(0.1 ":bob!~u@q6ddatxcq6txy.irc PRIVMSG #chan :alice: But we are spirits of another sort.")
(0.1 ":alice!~u@q6ddatxcq6txy.irc PRIVMSG #chan :bob: It was not given me, nor I did not buy it."))
-((linger 6 LINGER))
+((linger 30 LINGER))
diff --git a/test/lisp/erc/resources/join/network-id/foonet.eld b/test/lisp/erc/resources/join/network-id/foonet.eld
index 7d63f5f0c6c..74a107f8144 100644
--- a/test/lisp/erc/resources/join/network-id/foonet.eld
+++ b/test/lisp/erc/resources/join/network-id/foonet.eld
@@ -1,8 +1,8 @@
;; -*- mode: lisp-data; -*-
((pass 10 "PASS :foonet:changeme"))
-((nick 1 "NICK tester"))
+((nick 10 "NICK tester"))
-((user 1 "USER user 0 * :tester")
+((user 10 "USER user 0 * :tester")
(0 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester")
(0 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version oragono-2.6.0-7481bf0385b95b16")
(0 ":irc.foonet.org 003 tester :This server was created Mon, 10 May 2021 00:58:22 UTC")
diff --git a/test/lisp/erc/resources/keep-place/follow.eld b/test/lisp/erc/resources/keep-place/follow.eld
new file mode 100644
index 00000000000..db9352d93be
--- /dev/null
+++ b/test/lisp/erc/resources/keep-place/follow.eld
@@ -0,0 +1,78 @@
+;; -*- mode: lisp-data; -*-
+((nick 10 "NICK tester"))
+((user 10 "USER tester 0 * :tester")
+ (0.00 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester")
+ (0.01 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version ergo-v2.11.1")
+ (0.01 ":irc.foonet.org 003 tester :This server was created Tue, 26 Dec 2023 08:36:35 UTC")
+ (0.01 ":irc.foonet.org 004 tester irc.foonet.org ergo-v2.11.1 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0.00 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# CHATHISTORY=1000 ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX :are supported by this server")
+ (0.01 ":irc.foonet.org 005 tester KICKLEN=390 MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=foonet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8ONLY WHOX :are supported by this server")
+ (0.01 ":irc.foonet.org 005 tester draft/CHATHISTORY=1000 :are supported by this server")
+ (0.01 ":irc.foonet.org 251 tester :There are 0 users and 4 invisible on 1 server(s)")
+ (0.01 ":irc.foonet.org 252 tester 0 :IRC Operators online")
+ (0.00 ":irc.foonet.org 253 tester 0 :unregistered connections")
+ (0.00 ":irc.foonet.org 254 tester 2 :channels formed")
+ (0.00 ":irc.foonet.org 255 tester :I have 4 clients and 0 servers")
+ (0.00 ":irc.foonet.org 265 tester 4 4 :Current local users 4, max 4")
+ (0.00 ":irc.foonet.org 266 tester 4 4 :Current global users 4, max 4")
+ (0.03 ":irc.foonet.org 422 tester :MOTD File is missing")
+ (0.01 ":irc.foonet.org NOTICE tester :This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect."))
+
+((mode 10 "MODE tester +i"))
+
+((join 10 "JOIN #chan")
+ (0.01 ":irc.foonet.org 221 tester +i")
+ (0.01 ":tester!~u@p64eqfwvvbxrk.irc JOIN #chan")
+ (0.03 ":irc.foonet.org 353 tester = #chan :@fsbot bob alice tester")
+ (0.01 ":irc.foonet.org 366 tester #chan :End of NAMES list")
+ (0.00 ":bob!~u@2q6ysndq32az6.irc PRIVMSG #chan :tester, welcome!")
+ (0.01 ":alice!~u@2q6ysndq32az6.irc PRIVMSG #chan :tester, welcome!"))
+
+((join 10 "JOIN #spam")
+ (0.00 ":tester!~u@p64eqfwvvbxrk.irc JOIN #spam")
+ (0.06 ":irc.foonet.org 353 tester = #spam :@fsbot bob alice tester")
+ (0.01 ":irc.foonet.org 366 tester #spam :End of NAMES list")
+ (0.03 ":alice!~u@2q6ysndq32az6.irc PRIVMSG #spam :tester, welcome!")
+ (0.01 ":bob!~u@2q6ysndq32az6.irc PRIVMSG #spam :tester, welcome!"))
+
+((mode 10 "MODE #chan")
+ (0.00 ":irc.foonet.org 324 tester #chan +Cnt")
+ (0.02 ":irc.foonet.org 329 tester #chan 1703579802")
+ (0.02 ":alice!~u@2q6ysndq32az6.irc PRIVMSG #chan :bob: Madam, my lord is gone, for ever gone.")
+ (0.10 ":alice!~u@2q6ysndq32az6.irc PRIVMSG #chan :The kinder we, to give them thanks for nothing."))
+
+((mode 10 "MODE #spam")
+ (0.00 ":irc.foonet.org 324 tester #spam +Cnt")
+ (0.02 ":irc.foonet.org 329 tester #spam 1703579805")
+ (0.02 ":bob!~u@2q6ysndq32az6.irc PRIVMSG #chan :Most manifest, and not denied by himself.")
+ (0.02 ":bob!~u@2q6ysndq32az6.irc PRIVMSG #chan :alice: To bed, to bed: there's knocking at the gate. Come, come, come, come, give me your hand. What's done cannot be undone.")
+ (0.02 ":alice!~u@2q6ysndq32az6.irc PRIVMSG #chan :bob: And what I spake, I spake it to my face.")
+ (0.08 ":bob!~u@2q6ysndq32az6.irc PRIVMSG #chan :alice: Since you can cog, I'll play no more with you.")
+ (0.06 ":alice!~u@2q6ysndq32az6.irc PRIVMSG #chan :bob: The little casket bring me hither.")
+ (0.01 ":bob!~u@2q6ysndq32az6.irc PRIVMSG #chan :alice: Not to-night, good Iago: I have very poor and unhappy brains for drinking: I could well wish courtesy would invent some other custom of entertainment.")
+ (0.02 ":alice!~u@2q6ysndq32az6.irc PRIVMSG #chan :Yes, faith will I, Fridays and Saturdays and all."))
+
+((privmsg 10 "PRIVMSG #spam :one")
+ (0.03 ":alice!~u@2q6ysndq32az6.irc PRIVMSG #chan :bob: This is the first truth that e'er thine own tongue was guilty of.")
+ (0.02 ":bob!~u@2q6ysndq32az6.irc PRIVMSG #chan :alice: Drown the lamenting fool in sea-salt tears.")
+
+ ;; Insert some lines ^ before rendezvous, so #chan can update scrolltobottom.
+ (0.01 ":bob!~u@2q6ysndq32az6.irc PRIVMSG #spam :Ay, the heads of the maids, or their maidenheads; take it in what sense thou wilt.")
+
+ (0.05 ":bob!~u@2q6ysndq32az6.irc PRIVMSG #chan :alice: And work confusion on his enemies.")
+ (0.06 ":alice!~u@2q6ysndq32az6.irc PRIVMSG #chan :bob: Truly, she must be given, or the marriage is not lawful."))
+
+((privmsg 10 "PRIVMSG #spam :two")
+ (0.02 ":bob!~u@2q6ysndq32az6.irc PRIVMSG #chan :To be whipped; and yet a better love than my master.")
+ (0.06 ":alice!~u@2q6ysndq32az6.irc PRIVMSG #chan :And duty in his service perishing.")
+
+ ;; Second check point.
+ (0.01 ":bob!~u@2q6ysndq32az6.irc PRIVMSG #spam :Cause they take vengeance of such kind of men.")
+
+ (0.03 ":bob!~u@2q6ysndq32az6.irc PRIVMSG #chan :alice: No egma, no riddle, no l'envoy; no salve in the mail, sir. O! sir, plantain, a plain plantain: no l'envoy, no l'envoy: no salve, sir, but a plantain.")
+ (0.03 ":alice!~u@2q6ysndq32az6.irc PRIVMSG #chan :Signior Iachimo will not from it. Pray, let us follow 'em."))
+
+((privmsg 10 "PRIVMSG #spam :three")
+ ;; Third check point.
+ (0.01 ":bob!~u@2q6ysndq32az6.irc PRIVMSG #spam :Moved.")
+ (0.01 ":bob!~u@2q6ysndq32az6.irc PRIVMSG #chan :Ready."))
diff --git a/test/lisp/erc/resources/match/fools/fill-wrap.eld b/test/lisp/erc/resources/match/fools/fill-wrap.eld
new file mode 100644
index 00000000000..dff75ef9cd2
--- /dev/null
+++ b/test/lisp/erc/resources/match/fools/fill-wrap.eld
@@ -0,0 +1,41 @@
+;; -*- mode: lisp-data; -*-
+((pass 10 "PASS :changeme"))
+((nick 1 "NICK tester"))
+((user 1 "USER user 0 * :tester")
+ (0 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester")
+ (0 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version oragono-2.6.0-7481bf0385b95b16")
+ (0 ":irc.foonet.org 003 tester :This server was created Tue, 04 May 2021 05:06:18 UTC")
+ (0 ":irc.foonet.org 004 tester irc.foonet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server")
+ (0 ":irc.foonet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=FooNet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server")
+ (0 ":irc.foonet.org 005 tester draft/CHATHISTORY=100 :are supported by this server")
+ (0 ":irc.foonet.org 251 tester :There are 0 users and 3 invisible on 1 server(s)")
+ (0 ":irc.foonet.org 252 tester 0 :IRC Operators online")
+ (0 ":irc.foonet.org 253 tester 0 :unregistered connections")
+ (0 ":irc.foonet.org 254 tester 1 :channels formed")
+ (0 ":irc.foonet.org 255 tester :I have 3 clients and 0 servers")
+ (0 ":irc.foonet.org 265 tester 3 3 :Current local users 3, max 3")
+ (0 ":irc.foonet.org 266 tester 3 3 :Current global users 3, max 3")
+ (0 ":irc.foonet.org 422 tester :MOTD File is missing"))
+
+((mode-user 10 "MODE tester +i")
+ (0 ":irc.foonet.org 221 tester +i")
+ (0 ":irc.foonet.org NOTICE tester :This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect."))
+
+((join 6 "JOIN #chan")
+ (0 ":tester!~u@9g6b728983yd2.irc JOIN #chan")
+ (0 ":irc.foonet.org 353 tester = #chan :alice tester @bob")
+ (0 ":irc.foonet.org 366 tester #chan :End of NAMES list"))
+
+((mode 5 "MODE #chan")
+ (0 ":irc.foonet.org 324 tester #chan +nt")
+ (0 ":irc.foonet.org 329 tester #chan 1620104779")
+ (0.1 ":bob!~u@rz2v467q4rwhy.irc PRIVMSG #chan :tester, welcome!")
+ (0 ":alice!~u@rz2v467q4rwhy.irc PRIVMSG #chan :None better than to let him fetch off his drum, which you hear him so confidently undertake to do.")
+ (0 ":alice!~u@rz2v467q4rwhy.irc PRIVMSG #chan :bob: Still we went coupled and inseparable.")
+ (0 ":bob!~u@rz2v467q4rwhy.irc PRIVMSG #chan :alice: Give me your hand. This hand is moist, my lady."))
+
+((privmsg 5 "PRIVMSG #chan :hey")
+ (0 ":bob!~u@rz2v467q4rwhy.irc PRIVMSG #chan :You have paid the heavens your function, and the prisoner the very debt of your calling. I have laboured for the poor gentleman to the extremest shore of my modesty; but my brother justice have I found so severe, that he hath forced me to tell him he is indeed Justice.")
+ (0 ":alice!~u@rz2v467q4rwhy.irc PRIVMSG #chan :bob: In the sick air: let not thy sword skip one.")
+ (0 ":alice!~u@rz2v467q4rwhy.irc PRIVMSG #chan :The web of our life is of a mingled yarn, good and ill together: our virtues would be proud if our faults whipped them not; and our crimes would despair if they were not cherished by our virtues."))
diff --git a/test/lisp/erc/resources/sasl/plain-failed.eld b/test/lisp/erc/resources/sasl/plain-failed.eld
index 336700290c5..47d13de18e5 100644
--- a/test/lisp/erc/resources/sasl/plain-failed.eld
+++ b/test/lisp/erc/resources/sasl/plain-failed.eld
@@ -1,16 +1,16 @@
;; -*- mode: lisp-data; -*-
((cap-req 10 "CAP REQ :sasl"))
-((nick 1 "NICK tester"))
-((user 1 "USER tester 0 * :tester")
+((nick 10 "NICK tester"))
+((user 10 "USER tester 0 * :tester")
(0.0 ":irc.foonet.org NOTICE * :*** Looking up your hostname...")
(0.0 ":irc.foonet.org NOTICE * :*** Found your hostname")
(0.0 ":irc.foonet.org CAP * ACK :cap-notify sasl"))
-((authenticate-plain 3.2 "AUTHENTICATE PLAIN")
+((authenticate-plain 10 "AUTHENTICATE PLAIN")
(0.0 ":irc.foonet.org AUTHENTICATE +"))
-((authenticate-gimme 3.2 "AUTHENTICATE AHRlc3RlcgB3cm9uZw==")
+((authenticate-gimme 10 "AUTHENTICATE AHRlc3RlcgB3cm9uZw==")
(0.0 ":irc.foonet.org 900 * * tester :You are now logged in as tester")
(0.0 ":irc.foonet.org 904 * :SASL authentication failed: Invalid account credentials"))
-((cap-end 3.2 "CAP END"))
+((eof 10 EOF))
diff --git a/test/lisp/erc/resources/sasl/scram-sha-1.eld b/test/lisp/erc/resources/sasl/scram-sha-1.eld
index 49980e9e12a..d6adf529c5d 100644
--- a/test/lisp/erc/resources/sasl/scram-sha-1.eld
+++ b/test/lisp/erc/resources/sasl/scram-sha-1.eld
@@ -42,6 +42,6 @@
(0 ":jaguar.test 372 jilles : ~~ or rkpryyrag gb rnpu bgure ~~")
(0 ":jaguar.test 376 jilles :End of message of the day."))
-((mode-user 1.2 "MODE jilles +i")
+((mode-user 10 "MODE jilles +i")
(0 ":jilles!~jilles@127.0.0.1 MODE jilles :+ri")
(0 ":jaguar.test 306 jilles :You have been marked as being away"))
diff --git a/test/lisp/erc/resources/sasl/scram-sha-256.eld b/test/lisp/erc/resources/sasl/scram-sha-256.eld
index 74de9a23ecf..8b16f7109cf 100644
--- a/test/lisp/erc/resources/sasl/scram-sha-256.eld
+++ b/test/lisp/erc/resources/sasl/scram-sha-256.eld
@@ -42,6 +42,6 @@
(0 ":jaguar.test 372 jilles : ~~ or rkpryyrag gb rnpu bgure ~~")
(0 ":jaguar.test 376 jilles :End of message of the day."))
-((mode-user 1.2 "MODE jilles +i")
+((mode-user 10 "MODE jilles +i")
(0 ":jilles!~jilles@127.0.0.1 MODE jilles :+ri")
(0 ":jaguar.test 306 jilles :You have been marked as being away"))
diff --git a/test/lisp/erc/resources/scrolltobottom/help.eld b/test/lisp/erc/resources/scrolltobottom/help.eld
new file mode 100644
index 00000000000..ba44a0def39
--- /dev/null
+++ b/test/lisp/erc/resources/scrolltobottom/help.eld
@@ -0,0 +1,46 @@
+;; -*- mode: lisp-data; -*-
+((nick 10 "NICK tester"))
+((user 10 "USER user 0 * :tester")
+ (0.00 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester")
+ (0.01 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version ergo-v2.11.1")
+ (0.01 ":irc.foonet.org 003 tester :This server was created Mon, 21 Aug 2023 06:18:36 UTC")
+ (0.02 ":irc.foonet.org 004 tester irc.foonet.org ergo-v2.11.1 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv")
+ (0.00 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# CHATHISTORY=1000 ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX :are supported by this server")
+ (0.01 ":irc.foonet.org 005 tester KICKLEN=390 MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=foonet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8ONLY WHOX :are supported by this server")
+ (0.01 ":irc.foonet.org 005 tester draft/CHATHISTORY=1000 :are supported by this server")
+ (0.01 ":irc.foonet.org 251 tester :There are 0 users and 4 invisible on 1 server(s)")
+ (0.01 ":irc.foonet.org 252 tester 0 :IRC Operators online")
+ (0.01 ":irc.foonet.org 253 tester 0 :unregistered connections")
+ (0.01 ":irc.foonet.org 254 tester 2 :channels formed")
+ (0.01 ":irc.foonet.org 255 tester :I have 4 clients and 0 servers")
+ (0.01 ":irc.foonet.org 265 tester 4 4 :Current local users 4, max 4")
+ (0.01 ":irc.foonet.org 266 tester 4 4 :Current global users 4, max 4")
+ (0.01 ":irc.foonet.org 422 tester :MOTD File is missing"))
+
+((mode 10 "MODE tester +i")
+ (0.00 ":irc.foonet.org 221 tester +i")
+ (0.01 ":irc.foonet.org NOTICE tester :This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect.")
+ (0.02 ":irc.foonet.org 221 tester +i"))
+
+((privmsg-help-register 10 "PRIVMSG NickServ :help register")
+ (0.05 ":NickServ!NickServ@localhost NOTICE tester :*** \2NickServ HELP\2 ***")
+ (0.02 ":NickServ!NickServ@localhost NOTICE tester :Syntax: \2REGISTER <password> [email]\2")
+ (0.02 ":NickServ!NickServ@localhost NOTICE tester :")
+ (0.01 ":NickServ!NickServ@localhost NOTICE tester :REGISTER lets you register your current nickname as a user account. If the")
+ (0.01 ":NickServ!NickServ@localhost NOTICE tester :server allows anonymous registration, you can omit the e-mail address.")
+ (0.01 ":NickServ!NickServ@localhost NOTICE tester :")
+ (0.01 ":NickServ!NickServ@localhost NOTICE tester :If you are currently logged in with a TLS client certificate and wish to use")
+ (0.02 ":NickServ!NickServ@localhost NOTICE tester :it instead of a password to log in, send * as the password.")
+ (0.02 ":NickServ!NickServ@localhost NOTICE tester :*** \2End of NickServ HELP\2 ***"))
+
+((privmsg-help-identify 20 "PRIVMSG NickServ :help identify")
+ (0.06 ":NickServ!NickServ@localhost NOTICE tester :*** \2NickServ HELP\2 ***")
+ (0.02 ":NickServ!NickServ@localhost NOTICE tester :Syntax: \2IDENTIFY <username> [password]\2")
+ (0.02 ":NickServ!NickServ@localhost NOTICE tester :")
+ (0.02 ":NickServ!NickServ@localhost NOTICE tester :IDENTIFY lets you login to the given username using either password auth, or")
+ (0.02 ":NickServ!NickServ@localhost NOTICE tester :certfp (your client certificate) if a password is not given.")
+ (0.02 ":NickServ!NickServ@localhost NOTICE tester :*** \2End of NickServ HELP\2 ***"))
+
+((quit 10 "QUIT :\2ERC\2 ")
+ (0.07 ":tester!~u@26axz8nh8zaag.irc QUIT :Quit: \2ERC\2")
+ (0.02 "ERROR :Quit: \2ERC\2"))
diff --git a/test/lisp/eshell/em-alias-tests.el b/test/lisp/eshell/em-alias-tests.el
index ec1704545a4..b70ca185730 100644
--- a/test/lisp/eshell/em-alias-tests.el
+++ b/test/lisp/eshell/em-alias-tests.el
@@ -1,6 +1,6 @@
;;; em-alias-tests.el --- em-alias test suite -*- lexical-binding:t -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/eshell/em-basic-tests.el b/test/lisp/eshell/em-basic-tests.el
index 6ac7226ffa0..960e04690a5 100644
--- a/test/lisp/eshell/em-basic-tests.el
+++ b/test/lisp/eshell/em-basic-tests.el
@@ -1,6 +1,6 @@
;;; em-basic-tests.el --- em-basic test suite -*- lexical-binding:t -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/eshell/em-cmpl-tests.el b/test/lisp/eshell/em-cmpl-tests.el
index 29a41625d5e..13e42ffac88 100644
--- a/test/lisp/eshell/em-cmpl-tests.el
+++ b/test/lisp/eshell/em-cmpl-tests.el
@@ -1,6 +1,6 @@
;;; em-cmpl-tests.el --- em-cmpl test suite -*- lexical-binding:t -*-
-;; Copyright (C) 2023 Free Software Foundation, Inc.
+;; Copyright (C) 2023-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -243,14 +243,17 @@ See <lisp/eshell/esh-cmd.el>."
"echo $(eshell/echo"))))
(ert-deftest em-cmpl-test/special-ref-completion/type ()
- "Test completion of the start of special references like \"#<buffer\".
+ "Test completion of the start of special reference types like \"#<buffer\".
See <lisp/eshell/esh-arg.el>."
(with-temp-eshell
(should (equal (eshell-insert-and-complete "echo hi > #<buf")
"echo hi > #<buffer ")))
(with-temp-eshell
(should (equal (eshell-insert-and-complete "echo hi > #<proc")
- "echo hi > #<process "))))
+ "echo hi > #<process ")))
+ (with-temp-eshell
+ (should (equal (eshell-insert-and-complete "echo hi > #<mark")
+ "echo hi > #<marker "))))
(ert-deftest em-cmpl-test/special-ref-completion/implicit-buffer ()
"Test completion of special references like \"#<buf>\".
@@ -282,6 +285,31 @@ See <lisp/eshell/esh-arg.el>."
(format "echo hi > #<buffer %s> "
(string-replace " " "\\ " bufname))))))))
+(ert-deftest em-cmpl-test/special-ref-completion/marker ()
+ "Test completion of special references like \"#<marker 1 buf>\".
+See <lisp/eshell/esh-arg.el>."
+ (let (bufname)
+ (with-temp-buffer
+ (setq bufname (rename-buffer "my-buffer" t))
+ ;; Complete the buffer name in various forms.
+ (with-temp-eshell
+ (should (equal (eshell-insert-and-complete
+ "echo hi > #<marker 1 my-buf")
+ (format "echo hi > #<marker 1 %s> " bufname))))
+ (with-temp-eshell
+ (should (equal (eshell-insert-and-complete
+ "echo hi > #<marker 1 #<my-buf")
+ (format "echo hi > #<marker 1 #<%s>> " bufname))))
+ (with-temp-eshell
+ (should (equal (eshell-insert-and-complete
+ "echo hi > #<marker 1 #<buffer my-buf")
+ (format "echo hi > #<marker 1 #<buffer %s>> " bufname))))
+ ;; Partially-complete the "buffer" type name.
+ (with-temp-eshell
+ (should (equal (eshell-insert-and-complete
+ "echo hi > #<marker 1 #<buf")
+ "echo hi > #<marker 1 #<buffer "))))))
+
(ert-deftest em-cmpl-test/variable-ref-completion ()
"Test completion of variable references like \"$var\".
See <lisp/eshell/esh-var.el>."
diff --git a/test/lisp/eshell/em-dirs-tests.el b/test/lisp/eshell/em-dirs-tests.el
index 9864b72ba78..2f170fb0c63 100644
--- a/test/lisp/eshell/em-dirs-tests.el
+++ b/test/lisp/eshell/em-dirs-tests.el
@@ -1,6 +1,6 @@
;;; em-dirs-tests.el --- em-dirs test suite -*- lexical-binding:t -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/eshell/em-extpipe-tests.el b/test/lisp/eshell/em-extpipe-tests.el
index bdffcd9b320..610e3d41524 100644
--- a/test/lisp/eshell/em-extpipe-tests.el
+++ b/test/lisp/eshell/em-extpipe-tests.el
@@ -1,6 +1,6 @@
;;; em-extpipe-tests.el --- em-extpipe test suite -*- lexical-binding:t -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;; Author: Sean Whitton <spwhitton@spwhitton.name>
@@ -55,7 +55,9 @@
"temp\\([^>]\\|\\'\\)" temp
(string-replace
"#<buffer temp>"
- (concat "#<buffer " (buffer-name temp-buffer) ">")
+ (format "#<buffer %s>"
+ (eshell-quote-argument
+ (buffer-name temp-buffer)))
input))))
,@body)
(when (buffer-name temp-buffer)
@@ -110,7 +112,7 @@
'(progn
(ignore
(eshell-set-output-handle 1 'overwrite
- (get-buffer-create "temp")))
+ (eshell-get-buffer "temp")))
(eshell-named-command "sh"
(list "-c" "echo \"bar\" | rev"))))
(with-substitute-for-temp
@@ -133,7 +135,7 @@
'(progn
(ignore
(eshell-set-output-handle 1 'overwrite
- (get-buffer-create "quux")))
+ (eshell-get-buffer "quux")))
(ignore
(eshell-set-output-handle 1 'append
(get-process "other")))
diff --git a/test/lisp/eshell/em-glob-tests.el b/test/lisp/eshell/em-glob-tests.el
index 6e07225657c..6d922666ea3 100644
--- a/test/lisp/eshell/em-glob-tests.el
+++ b/test/lisp/eshell/em-glob-tests.el
@@ -1,6 +1,6 @@
;;; em-glob-tests.el --- em-glob test suite -*- lexical-binding:t -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/eshell/em-hist-tests.el b/test/lisp/eshell/em-hist-tests.el
index 35ae6bdc239..a4e1e01b124 100644
--- a/test/lisp/eshell/em-hist-tests.el
+++ b/test/lisp/eshell/em-hist-tests.el
@@ -1,6 +1,6 @@
;;; em-hist-tests.el --- em-hist test suite -*- lexical-binding:t -*-
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -19,11 +19,107 @@
;;; Code:
+(eval-when-compile
+ (require 'cl-lib))
+
(require 'ert)
(require 'ert-x)
(require 'em-hist)
+(require 'eshell)
+
+(require 'eshell-tests-helpers
+ (expand-file-name "eshell-tests-helpers"
+ (file-name-directory (or load-file-name
+ default-directory))))
+
+(cl-defun em-hist-test/check-history-file (file-name expected &optional
+ (expected-ring t))
+ "Check that the contents of FILE-NAME match the EXPECTED history entries.
+Additionally, check that after loading the file, the history ring
+matches too. If EXPECTED-RING is a list, compare the ring
+elements against that; if t (the default), check against EXPECTED."
+ (when (eq expected-ring t) (setq expected-ring expected))
+ ;; First check the actual file.
+ (should (equal (with-temp-buffer
+ (insert-file-contents file-name)
+ (buffer-string))
+ (mapconcat (lambda (i) (concat i "\n")) expected)))
+ ;; Now read the history ring and check that too.
+ (let (eshell-history-ring eshell-history-index eshell-hist--new-items)
+ (eshell-read-history file-name)
+ (should (equal (nreverse (ring-elements eshell-history-ring))
+ expected-ring))))
+
+;;; Tests:
+
+(ert-deftest em-hist-test/write-history/append ()
+ "Test appending new history to history file."
+ (ert-with-temp-file histfile
+ (with-temp-eshell
+ (em-hist-test/check-history-file histfile nil)
+ (eshell-insert-command "echo hi")
+ (eshell-write-history histfile 'append)
+ (em-hist-test/check-history-file histfile '("echo hi"))
+ (eshell-insert-command "echo bye")
+ (eshell-write-history histfile 'append)
+ (em-hist-test/check-history-file histfile '("echo hi" "echo bye")))))
+
+(ert-deftest em-hist-test/write-history/append-multiple-eshells ()
+ "Test appending new history to history file from multiple Eshells."
+ (ert-with-temp-file histfile
+ (with-temp-eshell
+ (with-temp-eshell
+ ;; Enter some commands and save them.
+ (eshell-insert-command "echo foo")
+ (eshell-insert-command "echo bar")
+ (eshell-write-history histfile 'append)
+ (em-hist-test/check-history-file histfile '("echo foo" "echo bar")))
+ ;; Now do the same in the first Eshell buffer.
+ (eshell-insert-command "echo goat")
+ (eshell-insert-command "echo panda")
+ (eshell-write-history histfile 'append)
+ (em-hist-test/check-history-file
+ histfile '("echo foo" "echo bar" "echo goat" "echo panda")))))
-(ert-deftest eshell-write-readonly-history ()
+(ert-deftest em-hist-test/write-history/overwrite ()
+ "Test overwriting history file."
+ (ert-with-temp-file histfile
+ (with-temp-eshell
+ (em-hist-test/check-history-file histfile nil)
+ (eshell-insert-command "echo hi")
+ (eshell-insert-command "echo bye")
+ (eshell-insert-command "echo bye")
+ (eshell-insert-command "echo hi")
+ (eshell-write-history histfile)
+ (em-hist-test/check-history-file
+ histfile '("echo hi" "echo bye" "echo bye" "echo hi"))
+ (let ((eshell-hist-ignoredups t))
+ (em-hist-test/check-history-file
+ histfile '("echo hi" "echo bye" "echo bye" "echo hi")
+ '("echo hi" "echo bye" "echo hi")))
+ (let ((eshell-hist-ignoredups 'erase))
+ (em-hist-test/check-history-file
+ histfile '("echo hi" "echo bye" "echo bye" "echo hi")
+ '("echo bye" "echo hi"))))))
+
+(ert-deftest em-hist-test/write-history/overwrite-multiple-shells ()
+ "Test overwriting history file from multiple Eshells."
+ (ert-with-temp-file histfile
+ (with-temp-eshell
+ (with-temp-eshell
+ ;; Enter some commands and save them.
+ (eshell-insert-command "echo foo")
+ (eshell-insert-command "echo bar")
+ (eshell-write-history histfile)
+ (em-hist-test/check-history-file histfile '("echo foo" "echo bar")))
+ ;; Now do the same in the first Eshell buffer.
+ (eshell-insert-command "echo goat")
+ (eshell-insert-command "echo panda")
+ (eshell-write-history histfile)
+ (em-hist-test/check-history-file
+ histfile '("echo goat" "echo panda")))))
+
+(ert-deftest em-hist-test/write-history/read-only ()
"Test that having read-only strings in history is okay."
(ert-with-temp-file histfile
(let ((eshell-history-ring (make-ring 2)))
@@ -31,7 +127,41 @@
(propertize "echo foo" 'read-only t))
(ring-insert eshell-history-ring
(propertize "echo bar" 'read-only t))
- (eshell-write-history histfile))))
+ (eshell-write-history histfile)
+ (em-hist-test/check-history-file histfile '("echo foo" "echo bar")))))
+
+(ert-deftest em-hist-test/add-to-history/allow-dups ()
+ "Test adding to history, allowing dups."
+ (let ((eshell-hist-ignoredups nil))
+ (with-temp-eshell
+ (eshell-insert-command "echo hi")
+ (eshell-insert-command "echo bye")
+ (eshell-insert-command "echo bye")
+ (eshell-insert-command "echo hi")
+ (should (equal (ring-elements eshell-history-ring)
+ '("echo hi" "echo bye" "echo bye" "echo hi"))))))
+
+(ert-deftest em-hist-test/add-to-history/no-consecutive-dups ()
+ "Test adding to history, ignoring consecutive dups."
+ (let ((eshell-hist-ignoredups t))
+ (with-temp-eshell
+ (eshell-insert-command "echo hi")
+ (eshell-insert-command "echo bye")
+ (eshell-insert-command "echo bye")
+ (eshell-insert-command "echo hi")
+ (should (equal (ring-elements eshell-history-ring)
+ '("echo hi" "echo bye" "echo hi"))))))
+
+(ert-deftest em-hist-test/add-to-history/erase-dups ()
+ "Test adding to history, erasing any old dups."
+ (let ((eshell-hist-ignoredups 'erase))
+ (with-temp-eshell
+ (eshell-insert-command "echo hi")
+ (eshell-insert-command "echo bye")
+ (eshell-insert-command "echo bye")
+ (eshell-insert-command "echo hi")
+ (should (equal (ring-elements eshell-history-ring)
+ '("echo hi" "echo bye"))))))
(provide 'em-hist-test)
diff --git a/test/lisp/eshell/em-ls-tests.el b/test/lisp/eshell/em-ls-tests.el
index 862a6dfd9f8..347716a577f 100644
--- a/test/lisp/eshell/em-ls-tests.el
+++ b/test/lisp/eshell/em-ls-tests.el
@@ -1,6 +1,6 @@
;;; em-ls-tests.el --- em-ls test suite -*- lexical-binding:t -*-
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
;; Author: Tino Calancha <tino.calancha@gmail.com>
diff --git a/test/lisp/eshell/em-pred-tests.el b/test/lisp/eshell/em-pred-tests.el
index adc4ac01eb1..3bffc918b66 100644
--- a/test/lisp/eshell/em-pred-tests.el
+++ b/test/lisp/eshell/em-pred-tests.el
@@ -1,6 +1,6 @@
;;; em-pred-tests.el --- em-pred test suite -*- lexical-binding:t -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/eshell/em-prompt-tests.el b/test/lisp/eshell/em-prompt-tests.el
index 93bf9d84ab3..964609e6410 100644
--- a/test/lisp/eshell/em-prompt-tests.el
+++ b/test/lisp/eshell/em-prompt-tests.el
@@ -1,6 +1,6 @@
;;; em-prompt-tests.el --- em-prompt test suite -*- lexical-binding:t -*-
-;; Copyright (C) 2023 Free Software Foundation, Inc.
+;; Copyright (C) 2023-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -32,6 +32,11 @@
(file-name-directory (or load-file-name
default-directory))))
+(defmacro em-prompt-test--with-multiline (&rest body)
+ "Execute BODY with a multiline Eshell prompt."
+ `(let ((eshell-prompt-function (lambda () "multiline prompt\n$ ")))
+ ,@body))
+
;;; Tests:
(ert-deftest em-prompt-test/field-properties ()
@@ -80,64 +85,108 @@ This tests the case when `eshell-highlight-prompt' is nil."
(apply #'propertize "hello\n"
eshell-command-output-properties)))))))
-(defmacro em-prompt-test--with-multiline (&rest body)
- "Execute BODY with a multiline Eshell prompt."
- `(let ((eshell-prompt-function (lambda () "multiline prompt\n$ ")))
- ,@body))
+(ert-deftest em-prompt-test/after-failure ()
+ "Check that current prompt shows the exit code of the last failed command."
+ (with-temp-eshell
+ (let ((debug-on-error nil))
+ (eshell-insert-command "(zerop \"foo\")"))
+ (let ((current-prompt (field-string (1- (point)))))
+ (should (equal-including-properties
+ current-prompt
+ (propertize
+ (concat (directory-file-name default-directory)
+ (unless (eshell-exit-success-p)
+ (format " [%d]" eshell-last-command-status))
+ (if (= (file-user-uid) 0) " # " " $ "))
+ 'read-only t
+ 'field 'prompt
+ 'font-lock-face 'eshell-prompt
+ 'front-sticky '(read-only field font-lock-face)
+ 'rear-nonsticky '(read-only field font-lock-face)))))))
-(defun em-prompt-test/next-previous-prompt-with ()
+(defun em-prompt-test/next-previous-prompt-1 ()
"Helper for checking forward/backward navigation of old prompts."
(with-temp-eshell
(eshell-insert-command "echo one")
(eshell-insert-command "echo two")
(eshell-insert-command "echo three")
+ (let ((debug-on-error nil)) ; A failed command.
+ (eshell-insert-command "(zerop \"foo\")"))
(insert "echo fou") ; A partially-entered command.
- ;; Go back one prompt.
- (eshell-previous-prompt 1)
- (should (equal (eshell-get-old-input) "echo three"))
- ;; Go back two prompts, starting from the end of this line.
- (end-of-line)
- (eshell-previous-prompt 2)
- (should (equal (eshell-get-old-input) "echo one"))
- ;; Go forward three prompts.
- (eshell-next-prompt 3)
- (should (equal (eshell-get-old-input) "echo fou"))))
+ (ert-info ("Go back one prompt")
+ (eshell-previous-prompt)
+ (should (equal (point) (field-beginning)))
+ (should (equal (field-string) "(zerop \"foo\")\n")))
+ (ert-info ("Go back three prompts, starting from the end of the input")
+ (end-of-line)
+ (eshell-previous-prompt 3)
+ (should (equal (point) (field-beginning)))
+ (should (equal (field-string) "echo one\n")))
+ (ert-info ("Go to the current prompt, starting from the end of the input")
+ (end-of-line)
+ (eshell-previous-prompt 0)
+ (should (equal (point) (field-beginning)))
+ (should (equal (field-string) "echo one\n")))
+ (ert-info ("Go forward one prompt")
+ (eshell-next-prompt)
+ (should (equal (point) (field-beginning)))
+ (should (equal (field-string) "echo two\n")))
+ (ert-info ("Go forward three prompts")
+ (eshell-next-prompt 3)
+ (should (equal (point) (field-beginning)))
+ (should (equal (field-string) "echo fou")))
+ (ert-info ("Go back one prompt, starting from the beginning of the line")
+ (forward-line 0)
+ (eshell-previous-prompt 1)
+ (should (equal (point) (field-beginning)))
+ (should (equal (field-string) "(zerop \"foo\")\n")))
+ (ert-info ("Go back one prompt, starting from the previous prompt's output")
+ (forward-line -1)
+ (eshell-previous-prompt 1)
+ (should (equal (point) (field-beginning)))
+ (should (equal (field-string) "echo three\n")))))
(ert-deftest em-prompt-test/next-previous-prompt ()
"Check that navigating forward/backward through old prompts works correctly."
- (em-prompt-test/next-previous-prompt-with))
+ (em-prompt-test/next-previous-prompt-1))
(ert-deftest em-prompt-test/next-previous-prompt-multiline ()
"Check old prompt forward/backward navigation for multiline prompts."
(em-prompt-test--with-multiline
- (em-prompt-test/next-previous-prompt-with)))
+ (em-prompt-test/next-previous-prompt-1)))
-(defun em-prompt-test/forward-backward-matching-input-with ()
+(defun em-prompt-test/forward-backward-matching-input-1 ()
"Helper for checking forward/backward navigation via regexps."
(with-temp-eshell
(eshell-insert-command "echo one")
(eshell-insert-command "printnl something else")
(eshell-insert-command "echo two")
(eshell-insert-command "echo three")
+ (let ((debug-on-error nil)) ; A failed command.
+ (eshell-insert-command "(zerop \"foo\")"))
(insert "echo fou") ; A partially-entered command.
- ;; Go back one prompt.
- (eshell-backward-matching-input "echo" 1)
- (should (equal (eshell-get-old-input) "echo three"))
- ;; Go back two prompts, starting from the end of this line.
- (end-of-line)
- (eshell-backward-matching-input "echo" 2)
- (should (equal (eshell-get-old-input) "echo one"))
- ;; Go forward three prompts.
- (eshell-forward-matching-input "echo" 3)
- (should (equal (eshell-get-old-input) "echo fou"))))
+ (ert-info ("Search for \"echo\", back one prompt")
+ (eshell-backward-matching-input "echo" 1)
+ (should (equal (point) (field-beginning)))
+ (should (equal (field-string) "echo three\n")))
+ (ert-info ((concat "Search for \"echo\", back two prompts, "
+ "starting from the end of this line"))
+ (end-of-line)
+ (eshell-backward-matching-input "echo" 2)
+ (should (equal (point) (field-beginning)))
+ (should (equal (field-string) "echo one\n")))
+ (ert-info ("Search for \"echo\", forward three prompts")
+ (eshell-forward-matching-input "echo" 3)
+ (should (equal (point) (field-beginning)))
+ (should (equal (field-string) "echo fou")))))
(ert-deftest em-prompt-test/forward-backward-matching-input ()
"Check that navigating forward/backward via regexps works correctly."
- (em-prompt-test/forward-backward-matching-input-with))
+ (em-prompt-test/forward-backward-matching-input-1))
(ert-deftest em-prompt-test/forward-backward-matching-input-multiline ()
"Check forward/backward regexp navigation for multiline prompts."
(em-prompt-test--with-multiline
- (em-prompt-test/forward-backward-matching-input-with)))
+ (em-prompt-test/forward-backward-matching-input-1)))
;;; em-prompt-tests.el ends here
diff --git a/test/lisp/eshell/em-script-tests.el b/test/lisp/eshell/em-script-tests.el
index 74328844778..f77c4568ea8 100644
--- a/test/lisp/eshell/em-script-tests.el
+++ b/test/lisp/eshell/em-script-tests.el
@@ -1,6 +1,6 @@
;;; em-script-tests.el --- em-script test suite -*- lexical-binding:t -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -63,6 +63,19 @@
"\\`\\'"))
(should (equal (buffer-string) "hibye")))))
+(ert-deftest em-script-test/source-script/background ()
+ "Test sourcing a script in the background."
+ (skip-unless (executable-find "echo"))
+ (ert-with-temp-file temp-file
+ :text "*echo hi\nif {[ foo = foo ]} {*echo bye}"
+ (eshell-with-temp-buffer bufname "old"
+ (with-temp-eshell
+ (eshell-match-command-output
+ (format "source %s > #<%s> &" temp-file bufname)
+ "\\`\\'")
+ (eshell-wait-for-subprocess t))
+ (should (equal (buffer-string) "hi\nbye\n")))))
+
(ert-deftest em-script-test/source-script/arg-vars ()
"Test sourcing script with $0, $1, ... variables."
(ert-with-temp-file temp-file :text "printnl $0 \"$1 $2\""
diff --git a/test/lisp/eshell/em-tramp-tests.el b/test/lisp/eshell/em-tramp-tests.el
index a3bda970b63..d33f6a2b46a 100644
--- a/test/lisp/eshell/em-tramp-tests.el
+++ b/test/lisp/eshell/em-tramp-tests.el
@@ -1,6 +1,6 @@
;;; em-tramp-tests.el --- em-tramp test suite -*- lexical-binding:t -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/eshell/em-unix-tests.el b/test/lisp/eshell/em-unix-tests.el
index d7b6c55fe45..a92c7d3f80a 100644
--- a/test/lisp/eshell/em-unix-tests.el
+++ b/test/lisp/eshell/em-unix-tests.el
@@ -1,6 +1,6 @@
;;; em-unix-tests.el --- em-unix test suite -*- lexical-binding:t -*-
-;; Copyright (C) 2023 Free Software Foundation, Inc.
+;; Copyright (C) 2023-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/eshell/esh-arg-tests.el b/test/lisp/eshell/esh-arg-tests.el
index c883db3907f..b626cf10bf1 100644
--- a/test/lisp/eshell/esh-arg-tests.el
+++ b/test/lisp/eshell/esh-arg-tests.el
@@ -1,6 +1,6 @@
;;; esh-arg-tests.el --- esh-arg test suite -*- lexical-binding:t -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -118,7 +118,68 @@ treated literally, as a backslash and a newline."
(format "echo #<buffer %s>" (buffer-name))
(current-buffer))))
-(ert-deftest esh-arg-test/special-reference/special ()
+(ert-deftest esh-arg-test/special-reference/marker ()
+ "Test that \"#<marker N buf>\" refers to a marker in the buffer \"buf\"."
+ (with-temp-buffer
+ (rename-buffer "my-buffer" t)
+ (insert "hello")
+ (let ((marker (make-marker)))
+ (set-marker marker 1 (current-buffer))
+ (eshell-command-result-equal
+ (format "echo #<marker 1 %s>" (buffer-name))
+ marker))))
+
+(ert-deftest esh-arg-test/special-reference/quoted ()
+ "Test that '#<buffer \"foo bar\">' refers to the buffer \"foo bar\"."
+ (with-temp-buffer
+ (rename-buffer "foo bar" t)
+ (eshell-command-result-equal
+ (format "echo #<buffer \"%s\">" (buffer-name))
+ (current-buffer))
+ (eshell-command-result-equal
+ (format "echo #<buffer '%s'>" (buffer-name))
+ (current-buffer))))
+
+(ert-deftest esh-arg-test/special-reference/nested ()
+ "Test that nested special references work correctly."
+ (with-temp-buffer
+ (rename-buffer "my-buffer" t)
+ (insert "hello")
+ (let ((marker (make-marker)))
+ (set-marker marker 1 (current-buffer))
+ (eshell-command-result-equal
+ (format "echo #<marker 1 #<%s>>" (buffer-name))
+ marker)
+ (eshell-command-result-equal
+ (format "echo #<marker 1 #<buffer %s>>" (buffer-name))
+ marker))))
+
+(ert-deftest esh-arg-test/special-reference/var-expansion ()
+ "Test that variable expansion inside special references works."
+ (with-temp-buffer
+ (rename-buffer "my-buffer" t)
+ (let ((eshell-test-value (buffer-name)))
+ (eshell-command-result-equal
+ "echo #<buffer $eshell-test-value>"
+ (current-buffer))
+ (eshell-command-result-equal
+ "echo #<buffer \"$eshell-test-value\">"
+ (current-buffer)))))
+
+(ert-deftest esh-arg-test/special-reference/lisp-form ()
+ "Test that Lisp forms inside special references work."
+ (with-temp-eshell
+ (let ((marker (make-marker))
+ eshell-test-value)
+ (set-marker marker 1 (current-buffer))
+ (eshell-insert-command
+ "setq eshell-test-value #<marker 1 (current-buffer)>")
+ (should (equal eshell-test-value marker))
+ (eshell-insert-command
+ "setq eshell-test-value #<marker 1 #<buffer (buffer-name)>>")
+ (should (equal eshell-test-value marker)))))
+
+(ert-deftest esh-arg-test/special-reference/special-characters ()
"Test that \"#<...>\" works correctly when escaping special characters."
(with-temp-buffer
(rename-buffer "<my buffer>" t)
diff --git a/test/lisp/eshell/esh-cmd-tests.el b/test/lisp/eshell/esh-cmd-tests.el
index a7208eb3a0b..be31681267b 100644
--- a/test/lisp/eshell/esh-cmd-tests.el
+++ b/test/lisp/eshell/esh-cmd-tests.el
@@ -1,6 +1,6 @@
;;; esh-cmd-tests.el --- esh-cmd test suite -*- lexical-binding:t -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -80,6 +80,12 @@ e.g. \"{(+ 1 2)} 3\" => 3"
(eshell-match-command-output "echo ${echo $value}"
"hello\n")))
+(ert-deftest esh-cmd-test/skip-leading-nils ()
+ "Test that Eshell skips leading nil arguments for named commands."
+ (eshell-command-result-equal "$eshell-test-value echo hello" "hello")
+ (eshell-command-result-equal
+ "$eshell-test-value $eshell-test-value echo hello" "hello"))
+
(ert-deftest esh-cmd-test/let-rebinds-after-defer ()
"Test that let-bound values are properly updated after `eshell-defer'.
When inside a `let' block in an Eshell command form, we need to
@@ -98,6 +104,32 @@ bug#59469."
"value\nexternal\nvalue\n")))
+;; Background command invocation
+
+(ert-deftest esh-cmd-test/background/simple-command ()
+ "Test invocation with a simple background command."
+ (skip-unless (executable-find "echo"))
+ (eshell-with-temp-buffer bufname ""
+ (with-temp-eshell
+ (eshell-match-command-output
+ (format "*echo hi > #<%s> &" bufname)
+ (rx "[echo" (? ".exe") "] " (+ digit) "\n"))
+ (eshell-wait-for-subprocess t))
+ (should (equal (buffer-string) "hi\n"))))
+
+(ert-deftest esh-cmd-test/background/subcommand ()
+ "Test invocation with a background command containing subcommands."
+ (skip-unless (and (executable-find "echo")
+ (executable-find "rev")))
+ (eshell-with-temp-buffer bufname ""
+ (with-temp-eshell
+ (eshell-match-command-output
+ (format "*echo ${*echo hello | rev} > #<%s> &" bufname)
+ (rx "[echo" (? ".exe") "] " (+ digit) "\n"))
+ (eshell-wait-for-subprocess t))
+ (should (equal (buffer-string) "olleh\n"))))
+
+
;; Lisp forms
(ert-deftest esh-cmd-test/quoted-lisp-form ()
@@ -138,6 +170,78 @@ bug#59469."
"hi\n")))
+;; Pipelines
+
+(ert-deftest esh-cmd-test/pipeline-wait/head-proc ()
+ "Check that piping a non-process to a process command waits for the process."
+ (skip-unless (executable-find "cat"))
+ (with-temp-eshell
+ (eshell-match-command-output "echo hi | *cat"
+ "hi")))
+
+(ert-deftest esh-cmd-test/pipeline-wait/tail-proc ()
+ "Check that piping a process to a non-process command waits for the process."
+ (skip-unless (executable-find "echo"))
+ (with-temp-eshell
+ (eshell-match-command-output "*echo hi | echo bye"
+ "bye\nhi\n")))
+
+(ert-deftest esh-cmd-test/pipeline-wait/multi-proc ()
+ "Check that a pipeline waits for all its processes before returning."
+ (skip-unless (and (executable-find "echo")
+ (executable-find "sh")
+ (executable-find "rev")))
+ (with-temp-eshell
+ (eshell-match-command-output
+ "*echo hello | sh -c 'sleep 1; rev' 1>&2 | *echo goodbye"
+ "goodbye\nolleh\n")))
+
+(ert-deftest esh-cmd-test/pipeline-wait/subcommand ()
+ "Check that piping with an asynchronous subcommand waits for the subcommand."
+ (skip-unless (and (executable-find "echo")
+ (executable-find "cat")))
+ (with-temp-eshell
+ (eshell-match-command-output "echo ${*echo hi} | *cat"
+ "hi")))
+
+(ert-deftest esh-cmd-test/pipeline-wait/subcommand-with-pipe ()
+ "Check that piping with an asynchronous subcommand with its own pipe works.
+This should also wait for the subcommand."
+ (skip-unless (and (executable-find "echo")
+ (executable-find "cat")))
+ (with-temp-eshell
+ (eshell-match-command-output "echo ${*echo hi | *cat} | *cat"
+ "hi")))
+
+(ert-deftest esh-cmd-test/reset-in-pipeline/subcommand ()
+ "Check that subcommands reset `eshell-in-pipeline-p'."
+ (skip-unless (executable-find "cat"))
+ (dolist (template '("echo {%s} | *cat"
+ "echo ${%s} | *cat"
+ "*cat $<%s> | *cat"))
+ (eshell-command-result-equal
+ (format template "echo $eshell-in-pipeline-p")
+ nil)
+ (eshell-command-result-equal
+ (format template "echo | echo $eshell-in-pipeline-p")
+ "last")
+ (eshell-command-result-equal
+ (format template "echo $eshell-in-pipeline-p | echo")
+ "first")
+ (eshell-command-result-equal
+ (format template "echo | echo $eshell-in-pipeline-p | echo")
+ "t")))
+
+(ert-deftest esh-cmd-test/reset-in-pipeline/lisp ()
+ "Check that interpolated Lisp forms reset `eshell-in-pipeline-p'."
+ (skip-unless (executable-find "cat"))
+ (dolist (template '("echo (%s) | *cat"
+ "echo $(%s) | *cat"))
+ (eshell-command-result-equal
+ (format template "format \"%s\" eshell-in-pipeline-p")
+ "nil")))
+
+
;; Control flow statements
(ert-deftest esh-cmd-test/for-loop ()
@@ -364,4 +468,19 @@ This tests when `eshell-lisp-form-nil-is-failure' is nil."
(eshell-command-result-equal "unless {[ foo = bar ]} {echo no} {echo yes}"
"no"))
+
+;; Error handling
+
+(ert-deftest esh-cmd-test/throw ()
+ "Test that calling `throw' as an Eshell command unwinds everything properly."
+ (with-temp-eshell
+ (should (= (catch 'tag
+ (eshell-insert-command
+ "echo hi; (throw 'tag 42); echo bye"))
+ 42))
+ (should (eshell-match-output "\\`hi\n\\'"))
+ (should-not eshell-foreground-command)
+ ;; Make sure we can call another command after throwing.
+ (eshell-match-command-output "echo again" "\\`again\n")))
+
;; esh-cmd-tests.el ends here
diff --git a/test/lisp/eshell/esh-ext-tests.el b/test/lisp/eshell/esh-ext-tests.el
index aae297cd413..8abbd74f737 100644
--- a/test/lisp/eshell/esh-ext-tests.el
+++ b/test/lisp/eshell/esh-ext-tests.el
@@ -1,6 +1,6 @@
;;; esh-ext-tests.el --- esh-ext test suite -*- lexical-binding:t -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/eshell/esh-io-tests.el b/test/lisp/eshell/esh-io-tests.el
index ce80f3a8f08..188570161c7 100644
--- a/test/lisp/eshell/esh-io-tests.el
+++ b/test/lisp/eshell/esh-io-tests.el
@@ -1,6 +1,6 @@
;;; esh-io-tests.el --- esh-io test suite -*- lexical-binding:t -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -328,12 +328,23 @@ stdout originally pointed (the terminal)."
"tuodts\nrredts\n"))
(ert-deftest esh-io-test/pipeline/subcommands ()
- "Chek that all commands in a subcommand are properly piped."
+ "Check that all commands in a subcommand are properly piped."
(skip-unless (executable-find "rev"))
(with-temp-eshell
(eshell-match-command-output "{echo foo; echo bar} | rev"
"\\`raboof\n?")))
+(ert-deftest esh-io-test/pipeline/stdin-to-head ()
+ "Check that standard input is sent to the head process in a pipeline."
+ (skip-unless (and (executable-find "tr")
+ (executable-find "rev")))
+ (with-temp-eshell
+ (eshell-insert-command "tr a-z A-Z | rev")
+ (eshell-insert-command "hello")
+ (eshell-send-eof-to-process)
+ (eshell-wait-for-subprocess)
+ (should (eshell-match-output "OLLEH\n"))))
+
;; Virtual targets
diff --git a/test/lisp/eshell/esh-opt-tests.el b/test/lisp/eshell/esh-opt-tests.el
index f4529ed4f22..8d6e0c1e426 100644
--- a/test/lisp/eshell/esh-opt-tests.el
+++ b/test/lisp/eshell/esh-opt-tests.el
@@ -1,6 +1,6 @@
;;; esh-opt-tests.el --- esh-opt test suite -*- lexical-binding:t -*-
-;; Copyright (C) 2018-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2018-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/eshell/esh-proc-tests.el b/test/lisp/eshell/esh-proc-tests.el
index fa20efa71e1..63fb8f46dfa 100644
--- a/test/lisp/eshell/esh-proc-tests.el
+++ b/test/lisp/eshell/esh-proc-tests.el
@@ -1,6 +1,6 @@
;;; esh-proc-tests.el --- esh-proc test suite -*- lexical-binding:t -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -86,7 +86,7 @@
"\\`\\'"))
(should (equal (buffer-string) "stdout\nstderr\n"))))
-(ert-deftest esh-var-test/output/remote-redirect ()
+(ert-deftest esh-proc-test/output/remote-redirect ()
"Check that redirecting stdout for a remote process works."
(skip-unless (and (eshell-tests-remote-accessible-p)
(executable-find "echo")))
@@ -137,18 +137,19 @@
(skip-unless (and (executable-find "sh")
(executable-find "echo")
(executable-find "sleep")))
- (with-temp-eshell
- (eshell-match-command-output
- ;; The first command is like `yes' but slower. This is to prevent
- ;; it from taxing Emacs's process filter too much and causing a
- ;; hang. Note that we use "|&" to connect the processes so that
- ;; Emacs doesn't create an extra pipe process for the first "sh"
- ;; invocation.
- (concat "sh -c 'while true; do echo y; sleep 1; done' |& "
- "sh -c 'read NAME; echo ${NAME}'")
- "y\n")
- (eshell-wait-for-subprocess t)
- (should (eq (process-list) nil))))
+ (let ((starting-process-list (process-list)))
+ (with-temp-eshell
+ (eshell-match-command-output
+ ;; The first command is like `yes' but slower. This is to prevent
+ ;; it from taxing Emacs's process filter too much and causing a
+ ;; hang. Note that we use "|&" to connect the processes so that
+ ;; Emacs doesn't create an extra pipe process for the first "sh"
+ ;; invocation.
+ (concat "sh -c 'while true; do echo y; sleep 1; done' |& "
+ "sh -c 'read NAME; echo ${NAME}'")
+ "y\n")
+ (eshell-wait-for-subprocess t)
+ (should (equal (process-list) starting-process-list)))))
(ert-deftest esh-proc-test/pipeline-connection-type/no-pipeline ()
"Test that all streams are PTYs when a command is not in a pipeline."
@@ -173,23 +174,17 @@
pipeline."
(skip-unless (and (executable-find "sh")
(executable-find "cat")))
- ;; An `eshell-pipe-broken' signal might occur internally; let Eshell
- ;; handle it!
- (let ((debug-on-error nil))
- (eshell-command-result-equal
- (concat "echo hi | " esh-proc-test--detect-pty-cmd " | cat")
- nil)))
+ (eshell-command-result-equal
+ (concat "(ignore) | " esh-proc-test--detect-pty-cmd " | cat")
+ nil))
(ert-deftest esh-proc-test/pipeline-connection-type/last ()
"Test that only output streams are PTYs when a command ends a pipeline."
(skip-unless (executable-find "sh"))
- ;; An `eshell-pipe-broken' signal might occur internally; let Eshell
- ;; handle it!
- (let ((debug-on-error nil))
- (eshell-command-result-equal
- (concat "echo hi | " esh-proc-test--detect-pty-cmd)
- (unless (eq system-type 'windows-nt)
- "stdout\nstderr\n"))))
+ (eshell-command-result-equal
+ (concat "(ignore) | " esh-proc-test--detect-pty-cmd)
+ (unless (eq system-type 'windows-nt)
+ "stdout\nstderr\n")))
;; Synchronous processes
@@ -281,7 +276,7 @@ prompt. See bug#54136."
(executable-find "sleep")))
;; This test doesn't work on EMBA with AOT nativecomp, but works
;; fine elsewhere.
- (skip-unless (not (getenv "EMACS_EMBA_CI")))
+ (skip-when (getenv "EMACS_EMBA_CI"))
(with-temp-eshell
(eshell-insert-command
(concat "sh -c 'while true; do echo y; sleep 1; done' | "
@@ -312,4 +307,28 @@ write the exit status to the pipe. See bug#54136."
output-start (eshell-end-of-output))
"")))))
+(ert-deftest esh-proc-test/kill-process/redirect-message ()
+ "Test that killing a process with a redirected stderr omits the exit status."
+ (skip-unless (executable-find "sleep"))
+ (eshell-with-temp-buffer bufname ""
+ (with-temp-eshell
+ (eshell-insert-command (format "sleep 100 2> #<buffer %s>" bufname))
+ (kill-process (eshell-head-process)))
+ (should (equal (buffer-string) ""))))
+
+
+;; Remote processes
+
+(ert-deftest esh-var-test/remote/remote-path ()
+ "Ensure that setting the remote PATH in Eshell doesn't interfere with Tramp.
+See bug#65551."
+ (skip-unless (and (eshell-tests-remote-accessible-p)
+ (executable-find "echo")))
+ (let ((default-directory ert-remote-temporary-file-directory))
+ (with-temp-eshell
+ (eshell-insert-command "set PATH ''")
+ (eshell-match-command-output
+ (format "%s hello" (executable-find "echo" t))
+ "\\`hello\n"))))
+
;;; esh-proc-tests.el ends here
diff --git a/test/lisp/eshell/esh-util-tests.el b/test/lisp/eshell/esh-util-tests.el
index fe4eb9f31dd..71a047b1801 100644
--- a/test/lisp/eshell/esh-util-tests.el
+++ b/test/lisp/eshell/esh-util-tests.el
@@ -1,6 +1,6 @@
;;; esh-util-tests.el --- esh-util test suite -*- lexical-binding:t -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -19,9 +19,15 @@
;;; Code:
+(require 'tramp)
(require 'ert)
(require 'esh-util)
+(require 'eshell-tests-helpers
+ (expand-file-name "eshell-tests-helpers"
+ (file-name-directory (or load-file-name
+ default-directory))))
+
;;; Tests:
(ert-deftest esh-util-test/eshell-stringify/string ()
@@ -156,4 +162,28 @@
(ert-deftest esh-util-test/eshell-printable-size/human-readable-arg ()
(should-error (eshell-printable-size 0 999 nil t)))
+(ert-deftest esh-util-test/path/get ()
+ "Test that getting the Eshell path returns the expected results."
+ (let ((expected-path (butlast (exec-path))))
+ (should (equal (eshell-get-path)
+ (if (eshell-under-windows-p)
+ (cons "." expected-path)
+ expected-path)))
+ (should (equal (eshell-get-path 'literal)
+ expected-path))))
+
+(ert-deftest esh-util-test/path/get-remote ()
+ "Test that getting the remote Eshell path returns the expected results."
+ (let* ((default-directory ert-remote-temporary-file-directory)
+ (expected-path (butlast (exec-path))))
+ ;; Make sure we don't have a doubled directory separator.
+ (should (seq-every-p (lambda (i) (not (string-match-p "//" i)))
+ (eshell-get-path)))
+ (should (equal (eshell-get-path)
+ (mapcar (lambda (i)
+ (concat (file-remote-p default-directory) i))
+ expected-path)))
+ (should (equal (eshell-get-path 'literal)
+ expected-path))))
+
;;; esh-util-tests.el ends here
diff --git a/test/lisp/eshell/esh-var-tests.el b/test/lisp/eshell/esh-var-tests.el
index 3e58fe749dd..39c278a6277 100644
--- a/test/lisp/eshell/esh-var-tests.el
+++ b/test/lisp/eshell/esh-var-tests.el
@@ -1,6 +1,6 @@
;;; esh-var-tests.el --- esh-var test suite -*- lexical-binding:t -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -645,6 +645,14 @@ nil, use FUNCTION instead."
(eshell-match-command-output "VAR=hello env" "VAR=hello\n")
(should (equal (getenv "VAR") "value"))))
+(ert-deftest esh-var-test/local-variables/skip-nil ()
+ "Test that Eshell skips leading nil arguments after local variable setting."
+ (with-temp-eshell
+ (push "VAR=value" process-environment)
+ (eshell-match-command-output "VAR=hello $eshell-test-value env"
+ "VAR=hello\n")
+ (should (equal (getenv "VAR") "value"))))
+
;; Variable aliases
@@ -766,6 +774,52 @@ it, since the setter is nil."
(eshell-match-command-output "echo $INSIDE_EMACS[, 1]"
"eshell")))
+(ert-deftest esh-var-test/pager-var/default ()
+ "Test that retrieving the default value of $PAGER works.
+This should be the value of `comint-pager' if non-nil, otherwise
+the value of the $PAGER env var."
+ (let ((comint-pager nil)
+ (process-environment (cons "PAGER=cat" process-environment)))
+ (eshell-command-result-equal "echo $PAGER" "cat")
+ (setq comint-pager "less")
+ (eshell-command-result-equal "echo $PAGER" "less")))
+
+(ert-deftest esh-var-test/pager-var/set ()
+ "Test that setting $PAGER in Eshell overrides the default value."
+ (let ((comint-pager nil)
+ (process-environment (cons "PAGER=cat" process-environment)))
+ (with-temp-eshell
+ (eshell-match-command-output "set PAGER bat" "bat")
+ (eshell-match-command-output "echo $PAGER" "bat"))
+ (setq comint-pager "less")
+ (with-temp-eshell
+ (eshell-match-command-output "set PAGER bat" "bat")
+ (eshell-match-command-output "echo $PAGER" "bat"))))
+
+(ert-deftest esh-var-test/pager-var/unset ()
+ "Test that unsetting $PAGER in Eshell overrides the default value."
+ (let ((comint-pager nil)
+ (process-environment (cons "PAGER=cat" process-environment)))
+ (with-temp-eshell
+ (eshell-insert-command "unset PAGER")
+ (eshell-match-command-output "echo $PAGER" "\\`\\'"))
+ (setq comint-pager "less")
+ (with-temp-eshell
+ (eshell-insert-command "unset PAGER")
+ (eshell-match-command-output "echo $PAGER" "\\`\\'"))))
+
+(ert-deftest esh-var-test/pager-var/set-locally ()
+ "Test setting $PAGER temporarily for a single command."
+ (let ((comint-pager nil)
+ (process-environment (cons "PAGER=cat" process-environment)))
+ (with-temp-eshell
+ (eshell-match-command-output "PAGER=bat env" "PAGER=bat\n")
+ (eshell-match-command-output "echo $PAGER" "cat"))
+ (setq comint-pager "less")
+ (with-temp-eshell
+ (eshell-match-command-output "PAGER=bat env" "PAGER=bat\n")
+ (eshell-match-command-output "echo $PAGER" "less"))))
+
(ert-deftest esh-var-test/path-var/local-directory ()
"Test using $PATH in a local directory."
(let ((expected-path (string-join (eshell-get-path t) (path-separator))))
diff --git a/test/lisp/eshell/eshell-tests-helpers.el b/test/lisp/eshell/eshell-tests-helpers.el
index 2c913d71cb4..652146fefcc 100644
--- a/test/lisp/eshell/eshell-tests-helpers.el
+++ b/test/lisp/eshell/eshell-tests-helpers.el
@@ -1,6 +1,6 @@
;;; eshell-tests-helpers.el --- Eshell test suite helpers -*- lexical-binding:t -*-
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
;; Author: John Wiegley <johnw@gnu.org>
@@ -54,6 +54,13 @@ beginning of the test file."
(let* (;; We want no history file, so prevent Eshell from falling
;; back on $HISTFILE.
(process-environment (cons "HISTFILE" process-environment))
+ ;; Enable process debug instrumentation. We may be able
+ ;; to remove this eventually once we're confident that
+ ;; all the process bugs have been worked out. (At that
+ ;; point, we can just enable this selectively when
+ ;; needed.) See also `eshell-test-command-result'
+ ;; below.
+ (eshell-debug-command (cons 'process eshell-debug-command))
(eshell-history-file-name nil)
(eshell-last-dir-ring-file-name nil)
(eshell-buffer (eshell t)))
@@ -96,6 +103,13 @@ raise an error."
(lambda ()
(not (if all eshell-process-list (eshell-interactive-process-p))))))
+(defun eshell-get-debug-logs ()
+ "Get debug command logs for displaying on test failures."
+ (when (get-buffer eshell-debug-command-buffer)
+ (let ((separator (make-string 40 ?-)))
+ (with-current-buffer eshell-debug-command-buffer
+ (string-replace "\f" separator (buffer-string))))))
+
(defun eshell-insert-command (command &optional func)
"Insert a COMMAND at the end of the buffer.
After inserting, call FUNC. If FUNC is nil, instead call
@@ -135,17 +149,21 @@ FUNC is the function to call after inserting the text (see
If IGNORE-ERRORS is non-nil, ignore any errors signaled when
inserting the command."
- (let ((debug-on-error (and (not ignore-errors) debug-on-error)))
- (eshell-insert-command command func))
- (eshell-wait-for-subprocess)
- (should (eshell-match-output regexp)))
+ (ert-info (#'eshell-get-debug-logs :prefix "Command logs: ")
+ (let ((debug-on-error (and (not ignore-errors) debug-on-error)))
+ (eshell-insert-command command func))
+ (eshell-wait-for-subprocess)
+ (should (eshell-match-output regexp))))
(defvar eshell-history-file-name)
(defun eshell-test-command-result (command)
"Like `eshell-command-result', but not using HOME."
(ert-with-temp-directory eshell-directory-name
- (let ((eshell-history-file-name nil))
+ (let ((eshell-history-file-name nil)
+ ;; Enable process debug instrumentation. See
+ ;; `with-temp-eshell' above.
+ (eshell-debug-command (cons 'process eshell-debug-command)))
(eshell-command-result command))))
(defun eshell-command-result--equal (_command actual expected)
@@ -164,10 +182,11 @@ inserting the command."
(defun eshell-command-result-equal (command result)
"Execute COMMAND non-interactively and compare it to RESULT."
- (should (eshell-command-result--equal
- command
- (eshell-test-command-result command)
- result)))
+ (ert-info (#'eshell-get-debug-logs :prefix "Command logs: ")
+ (should (eshell-command-result--equal
+ command
+ (eshell-test-command-result command)
+ result))))
(provide 'eshell-tests-helpers)
diff --git a/test/lisp/eshell/eshell-tests-unload.el b/test/lisp/eshell/eshell-tests-unload.el
index cdd58efef18..bf8291ba47a 100644
--- a/test/lisp/eshell/eshell-tests-unload.el
+++ b/test/lisp/eshell/eshell-tests-unload.el
@@ -1,6 +1,6 @@
;;; eshell-tests-unload.el --- test unloading Eshell -*- lexical-binding:t -*-
-;; Copyright (C) 2023 Free Software Foundation, Inc.
+;; Copyright (C) 2023-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/eshell/eshell-tests.el b/test/lisp/eshell/eshell-tests.el
index 46c9482ecf4..e01e033e25e 100644
--- a/test/lisp/eshell/eshell-tests.el
+++ b/test/lisp/eshell/eshell-tests.el
@@ -1,6 +1,6 @@
;;; eshell-tests.el --- Eshell test suite -*- lexical-binding:t -*-
-;; Copyright (C) 1999-2023 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
;; Author: John Wiegley <johnw@gnu.org>
@@ -38,75 +38,6 @@
;;; Tests:
-(ert-deftest eshell-test/pipe-headproc ()
- "Check that piping a non-process to a process command waits for the process"
- (skip-unless (executable-find "cat"))
- (with-temp-eshell
- (eshell-match-command-output "echo hi | *cat"
- "hi")))
-
-(ert-deftest eshell-test/pipe-tailproc ()
- "Check that piping a process to a non-process command waits for the process"
- (skip-unless (executable-find "echo"))
- (with-temp-eshell
- (eshell-match-command-output "*echo hi | echo bye"
- "bye\nhi\n")))
-
-(ert-deftest eshell-test/pipe-headproc-stdin ()
- "Check that standard input is sent to the head process in a pipeline"
- (skip-unless (and (executable-find "tr")
- (executable-find "rev")))
- (with-temp-eshell
- (eshell-insert-command "tr a-z A-Z | rev")
- (eshell-insert-command "hello")
- (eshell-send-eof-to-process)
- (eshell-wait-for-subprocess)
- (should (eshell-match-output "OLLEH\n"))))
-
-(ert-deftest eshell-test/pipe-subcommand ()
- "Check that piping with an asynchronous subcommand works"
- (skip-unless (and (executable-find "echo")
- (executable-find "cat")))
- (with-temp-eshell
- (eshell-match-command-output "echo ${*echo hi} | *cat"
- "hi")))
-
-(ert-deftest eshell-test/pipe-subcommand-with-pipe ()
- "Check that piping with an asynchronous subcommand with its own pipe works"
- (skip-unless (and (executable-find "echo")
- (executable-find "cat")))
- (with-temp-eshell
- (eshell-match-command-output "echo ${*echo hi | *cat} | *cat"
- "hi")))
-
-(ert-deftest eshell-test/subcommand-reset-in-pipeline ()
- "Check that subcommands reset `eshell-in-pipeline-p'."
- (skip-unless (executable-find "cat"))
- (dolist (template '("echo {%s} | *cat"
- "echo ${%s} | *cat"
- "*cat $<%s> | *cat"))
- (eshell-command-result-equal
- (format template "echo $eshell-in-pipeline-p")
- nil)
- (eshell-command-result-equal
- (format template "echo | echo $eshell-in-pipeline-p")
- "last")
- (eshell-command-result-equal
- (format template "echo $eshell-in-pipeline-p | echo")
- "first")
- (eshell-command-result-equal
- (format template "echo | echo $eshell-in-pipeline-p | echo")
- "t")))
-
-(ert-deftest eshell-test/lisp-reset-in-pipeline ()
- "Check that interpolated Lisp forms reset `eshell-in-pipeline-p'."
- (skip-unless (executable-find "cat"))
- (dolist (template '("echo (%s) | *cat"
- "echo $(%s) | *cat"))
- (eshell-command-result-equal
- (format template "format \"%s\" eshell-in-pipeline-p")
- "nil")))
-
(ert-deftest eshell-test/eshell-command/simple ()
"Test that the `eshell-command' function writes to the current buffer."
(skip-unless (executable-find "echo"))
@@ -127,6 +58,18 @@ This test uses a pipeline for the command."
(eshell-command "*echo hi | *cat" t)
(should (equal (buffer-string) "hi\n"))))))
+(ert-deftest eshell-test/eshell-command/pipeline-wait ()
+ "Check that `eshell-command' waits for all its processes before returning."
+ (skip-unless (and (executable-find "echo")
+ (executable-find "sh")
+ (executable-find "rev")))
+ (ert-with-temp-directory eshell-directory-name
+ (let ((eshell-history-file-name nil))
+ (with-temp-buffer
+ (eshell-command
+ "*echo hello | sh -c 'sleep 1; rev' 1>&2 | *echo goodbye" t)
+ (should (equal (buffer-string) "goodbye\nolleh\n"))))))
+
(ert-deftest eshell-test/eshell-command/background ()
"Test that `eshell-command' works for background commands."
(skip-unless (executable-find "echo"))
@@ -144,13 +87,36 @@ This test uses a pipeline for the command."
(skip-unless (and (executable-find "echo")
(executable-find "cat")))
(ert-with-temp-directory eshell-directory-name
- (let ((orig-processes (copy-tree (process-list)))
+ (let ((orig-processes (process-list))
(eshell-history-file-name nil))
(with-temp-buffer
(eshell-command "*echo hi | *cat &" t)
(eshell-wait-for (lambda () (equal (process-list) orig-processes)))
(should (equal (buffer-string) "hi\n"))))))
+(ert-deftest eshell-test/eshell-command/output-buffer/sync ()
+ "Test that the `eshell-command' function writes to its output buffer."
+ (skip-unless (executable-find "echo"))
+ (ert-with-temp-directory eshell-directory-name
+ (let ((eshell-history-file-name nil))
+ (eshell-command "*echo 'hi\nbye'")
+ (with-current-buffer "*Eshell Command Output*"
+ (should (equal (buffer-string) "hi\nbye")))
+ (kill-buffer "*Eshell Command Output*"))))
+
+(ert-deftest eshell-test/eshell-command/output-buffer/async ()
+ "Test that the `eshell-command' function writes to its async output buffer."
+ (skip-unless (executable-find "echo"))
+ (ert-with-temp-directory eshell-directory-name
+ (let ((orig-processes (process-list))
+ (eshell-history-file-name nil))
+ (eshell-command "*echo hi &")
+ (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 "hi\n"))))))
+
(ert-deftest eshell-test/command-running-p ()
"Modeline should show no command running"
(with-temp-eshell
@@ -178,7 +144,7 @@ insert the queued one at the next prompt, and finally run it."
(eshell-insert-command "sleep 1; echo slept")
(eshell-insert-command "echo alpha" #'eshell-queue-input)
(let ((start (marker-position (eshell-beginning-of-output))))
- (eshell-wait-for (lambda () (not eshell-current-command)))
+ (eshell-wait-for (lambda () (not eshell-foreground-command)))
(should (string-match "^slept\n.*echo alpha\nalpha\n$"
(buffer-substring-no-properties
start (eshell-end-of-output)))))))
@@ -229,6 +195,25 @@ insert the queued one at the next prompt, and finally run it."
(eshell-send-input)
(eshell-match-output "(\"hello\" \"there\")")))
+(ert-deftest eshell-test/yank-output ()
+ "Test that yanking a line of output into the next prompt works (bug#66469)."
+ (with-temp-eshell
+ (eshell-insert-command "echo hello")
+ ;; Go to the output and kill the line of text.
+ (forward-line -1)
+ (kill-line)
+ ;; Go to the last prompt and yank the previous output.
+ (goto-char (point-max))
+ (yank)
+ ;; Go to the beginning of the prompt and add some text.
+ (move-beginning-of-line 1)
+ (insert-and-inherit "echo ")
+ ;; Make sure when we go to the beginning of the line, we go to the
+ ;; right spot (before the "echo").
+ (move-end-of-line 1)
+ (move-beginning-of-line 1)
+ (should (looking-at "echo hello"))))
+
(provide 'eshell-tests)
;;; eshell-tests.el ends here
diff --git a/test/lisp/faces-resources/faces-test-dark-theme.el b/test/lisp/faces-resources/faces-test-dark-theme.el
index c73a8823a09..6c7492c4a7e 100644
--- a/test/lisp/faces-resources/faces-test-dark-theme.el
+++ b/test/lisp/faces-resources/faces-test-dark-theme.el
@@ -1,6 +1,6 @@
;;; faces-test-dark-theme.el --- A dark theme from tests ;;; -*- lexical-binding: t; -*-
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/faces-resources/faces-test-light-theme.el b/test/lisp/faces-resources/faces-test-light-theme.el
index acbc54d769b..76e485d3176 100644
--- a/test/lisp/faces-resources/faces-test-light-theme.el
+++ b/test/lisp/faces-resources/faces-test-light-theme.el
@@ -1,6 +1,6 @@
;;; faces-test-light-theme.el --- A dark theme from tests ;;; -*- lexical-binding: t; -*-
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/faces-tests.el b/test/lisp/faces-tests.el
index 2c772a27f74..529eb846bbd 100644
--- a/test/lisp/faces-tests.el
+++ b/test/lisp/faces-tests.el
@@ -1,6 +1,6 @@
;;; faces-tests.el --- Tests for faces.el -*- lexical-binding: t; -*-
-;; Copyright (C) 2013-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2024 Free Software Foundation, Inc.
;; Author: Artur Malabarba <bruce.connor.am@gmail.com>
;; Keywords:
diff --git a/test/lisp/ffap-tests.el b/test/lisp/ffap-tests.el
index a47e1900ae4..593d2d42af6 100644
--- a/test/lisp/ffap-tests.el
+++ b/test/lisp/ffap-tests.el
@@ -1,6 +1,6 @@
;;; ffap-tests.el --- Test suite for ffap.el -*- lexical-binding: t -*-
-;; Copyright (C) 2016-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2016-2024 Free Software Foundation, Inc.
;; Author: Tino Calancha <tino.calancha@gmail.com>
diff --git a/test/lisp/filenotify-tests.el b/test/lisp/filenotify-tests.el
index 0873910ddf9..11af1f75574 100644
--- a/test/lisp/filenotify-tests.el
+++ b/test/lisp/filenotify-tests.el
@@ -1,6 +1,6 @@
;;; filenotify-tests.el --- Tests of file notifications -*- lexical-binding: t; -*-
-;; Copyright (C) 2013-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2024 Free Software Foundation, Inc.
;; Author: Michael Albinus <michael.albinus@gmx.de>
@@ -973,8 +973,7 @@ delivered."
(setq file-notify--test-desc auto-revert-notify-watch-descriptor)
;; GKqueueFileMonitor does not report the `changed' event.
- (skip-unless
- (not (eq (file-notify--test-monitor) 'GKqueueFileMonitor)))
+ (skip-when (eq (file-notify--test-monitor) 'GKqueueFileMonitor))
;; Check, that file notification has been used.
(should auto-revert-mode)
@@ -1583,7 +1582,7 @@ the file watch."
:tags '(:expensive-test)
(skip-unless (file-notify--test-local-enabled))
;; This test does not work for kqueue (yet).
- (skip-unless (not (string-equal (file-notify--test-library) "kqueue")))
+ (skip-when (string-equal (file-notify--test-library) "kqueue"))
(setq file-notify--test-tmpfile (file-notify--test-make-temp-name)
file-notify--test-tmpfile1 (file-notify--test-make-temp-name))
@@ -1708,6 +1707,71 @@ the file watch."
(file-notify--deftest-remote file-notify-test11-symlinks
"Check `file-notify-test11-symlinks' for remote files.")
+(ert-deftest file-notify-test12-unmount ()
+ "Check that file notification stop after unmounting the filesystem."
+ :tags '(:expensive-test)
+ (skip-unless (file-notify--test-local-enabled))
+ ;; This test does not work for w32notify.
+ (skip-when (string-equal (file-notify--test-library) "w32notify"))
+
+ (unwind-protect
+ (progn
+ (setq file-notify--test-tmpfile (file-notify--test-make-temp-name))
+ ;; File monitors like kqueue insist, that the watched file
+ ;; exists. Directory monitors are not bound to this
+ ;; restriction.
+ (when (string-equal (file-notify--test-library) "kqueue")
+ (write-region
+ "any text" nil file-notify--test-tmpfile nil 'no-message))
+
+ (should
+ (setq file-notify--test-desc
+ (file-notify--test-add-watch
+ file-notify--test-tmpfile
+ '(attribute-change change) #'file-notify--test-event-handler)))
+ (should (file-notify-valid-p file-notify--test-desc))
+
+ ;; Unmounting the filesystem should stop watching.
+ (file-notify--test-with-actions '(stopped)
+ ;; We emulate unmounting by calling
+ ;; `file-notify-handle-event' with a corresponding event.
+ (file-notify-handle-event
+ (make-file-notify
+ :-event
+ (list file-notify--test-desc
+ (pcase (file-notify--test-library)
+ ((or "inotify" "inotifywait") '(unmount isdir))
+ ((or "gfilenotify" "gio") '(unmounted))
+ ("kqueue" '(revoke))
+ (err (ert-fail (format "Library %s not supported" err))))
+ (pcase (file-notify--test-library)
+ ("kqueue" (file-local-name file-notify--test-tmpfile))
+ (_ (file-local-name file-notify--test-tmpdir)))
+ ;; In the inotify case, there is a 4th slot `cookie'.
+ ;; Since it is unused for `unmount', we ignore it.
+ )
+ :-callback
+ (pcase (file-notify--test-library)
+ ("inotify" #'file-notify--callback-inotify)
+ ("gfilenotify" #'file-notify--callback-gfilenotify)
+ ("kqueue" #'file-notify--callback-kqueue)
+ ((or "inotifywait" "gio") #'file-notify-callback)
+ (err (ert-fail (format "Library %s not supported" err)))))))
+
+ ;; The watch has been stopped.
+ (should-not (file-notify-valid-p file-notify--test-desc))
+
+ ;; The environment shall be cleaned up.
+ (when (string-equal (file-notify--test-library) "kqueue")
+ (delete-file file-notify--test-tmpfile))
+ (file-notify--test-cleanup-p))
+
+ ;; Cleanup.
+ (file-notify--test-cleanup)))
+
+(file-notify--deftest-remote file-notify-test12-unmount
+ "Check `file-notify-test12-unmount' for remote files.")
+
(defun file-notify-test-all (&optional interactive)
"Run all tests for \\[file-notify]."
(interactive "p")
diff --git a/test/lisp/files-tests.el b/test/lisp/files-tests.el
index 0e460009cea..718ecd51f8b 100644
--- a/test/lisp/files-tests.el
+++ b/test/lisp/files-tests.el
@@ -1,6 +1,6 @@
;;; files-tests.el --- tests for files.el. -*- lexical-binding: t; -*-
-;; Copyright (C) 2012-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2012-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -683,6 +683,24 @@ unquoted file names."
(files-tests--with-temp-non-special-and-file-name-handler (tmpfile nospecial)
(should (equal (expand-file-name nospecial) nospecial))))
+(ert-deftest files-tests-file-name-non-special-expand-file-name-tilde ()
+ (let ((process-environment
+ (cons (format "HOME=%s" (file-truename temporary-file-directory))
+ process-environment))
+ abbreviated-home-dir)
+ (files-tests--with-temp-non-special (tmpfile nospecial)
+ (let (file-name-handler-alist)
+ (setq nospecial (file-name-quote (abbreviate-file-name tmpfile))))
+ (should (equal (expand-file-name nospecial)
+ (expand-file-name (file-name-unquote nospecial t)))))
+ (files-tests--with-temp-non-special-and-file-name-handler (tmpfile nospecial)
+ (let (file-name-handler-alist)
+ (setq nospecial (file-name-quote (abbreviate-file-name tmpfile))))
+ (should-not
+ (equal (expand-file-name nospecial)
+ ;; The file name handler deletes the ".special" extension.
+ (expand-file-name (file-name-unquote nospecial t)))))))
+
(ert-deftest files-tests-file-name-non-special-file-accessible-directory-p ()
(files-tests--with-temp-non-special (tmpdir nospecial-dir t)
(should (file-accessible-directory-p nospecial-dir)))
@@ -1638,6 +1656,31 @@ The door of all subtleties!
(should (equal (file-name-base "foo") "foo"))
(should (equal (file-name-base "foo/bar") "bar")))
+(defun files-tests--check-shebang (shebang expected-mode)
+ "Assert that mode for SHEBANG derives from EXPECTED-MODE."
+ (let ((actual-mode
+ (ert-with-temp-file script-file
+ :text shebang
+ (find-file script-file)
+ (if (derived-mode-p expected-mode)
+ expected-mode
+ major-mode))))
+ ;; Tuck all the information we need in the `should' form: input
+ ;; shebang, expected mode vs actual.
+ (should
+ (equal (list shebang actual-mode)
+ (list shebang expected-mode)))))
+
+(ert-deftest files-tests-auto-mode-interpreter ()
+ "Test that `set-auto-mode' deduces correct modes from shebangs."
+ (files-tests--check-shebang "#!/bin/bash" 'sh-mode)
+ (files-tests--check-shebang "#!/usr/bin/env bash" 'sh-mode)
+ (files-tests--check-shebang "#!/usr/bin/env python" 'python-base-mode)
+ (files-tests--check-shebang "#!/usr/bin/env python3" 'python-base-mode)
+ (files-tests--check-shebang "#!/usr/bin/env -S awk -v FS=\"\\t\" -v OFS=\"\\t\" -f" 'awk-mode)
+ (files-tests--check-shebang "#!/usr/bin/env -S make -f" 'makefile-mode)
+ (files-tests--check-shebang "#!/usr/bin/make -f" 'makefile-mode))
+
(ert-deftest files-test-dir-locals-auto-mode-alist ()
"Test an `auto-mode-alist' entry in `.dir-locals.el'"
(find-file (ert-resource-file "whatever.quux"))
@@ -1699,6 +1742,157 @@ let-bound to PRED and passing nil as second arg of
(set-buffer-modified-p nil)
(kill-buffer buf)))))))
+(defmacro files-tests--with-yes-or-no-p (reply &rest body)
+ "Execute BODY, providing replies to `yes-or-no-p' queries.
+REPLY should be a cons (PROMPT . VALUE), and during execution of
+BODY this macro provides VALUE as return value to all
+`yes-or-no-p' calls prompting for PROMPT and nil to all other
+`yes-or-no-p' calls. After execution of BODY, this macro ensures
+that exactly one `yes-or-no-p' call prompting for PROMPT has been
+executed during execution of BODY."
+ (declare (indent 1) (debug (sexp body)))
+ `(cl-letf*
+ ((reply ,reply)
+ (prompts nil)
+ ((symbol-function 'yes-or-no-p)
+ (lambda (prompt)
+ (let ((reply (cdr (assoc prompt (list reply)))))
+ (push (cons prompt reply) prompts)
+ reply))))
+ ,@body
+ (should (equal prompts (list reply)))))
+
+(ert-deftest files-tests-save-buffer-read-only-file ()
+ "Test writing to write-protected files with `save-buffer'.
+Ensure that the issues from bug#66546 are fixed."
+ (ert-with-temp-directory dir
+ (cl-flet (;; Define convenience functions.
+ (file-contents (file)
+ (if (file-exists-p file)
+ (condition-case err
+ (with-temp-buffer
+ (insert-file-contents-literally file)
+ (buffer-string))
+ (error err))
+ 'missing))
+ (signal-write-failed (&rest _)
+ (signal 'file-error "Write failed")))
+
+ (let* (;; Sanitize environment.
+ ;; The tests below test text for equality, so we need to
+ ;; disable any code- and EOL-conversions to avoid false
+ ;; positives and false negatives.
+ (coding-system-for-read 'no-conversion)
+ (coding-system-for-write 'no-conversion)
+ (auto-save-default nil)
+ (backup-enable-predicate nil)
+ (before-save-hook nil)
+ (write-contents-functions nil)
+ (write-file-functions nil)
+ (after-save-hook nil)
+
+ ;; Set the name of the game.
+ (base "read-only-test")
+ (file (expand-file-name base dir))
+ (backup (make-backup-file-name file))
+
+ (override-read-only-prompt
+ (format "File %s is write-protected; try to save anyway? "
+ base)))
+
+ ;; Ensure that set-file-modes renders our test file read-only,
+ ;; otherwise skip this test. Use `file-writable-p' to test
+ ;; for read-only-ness, because that's what function
+ ;; `save-buffer' uses as well.
+ (with-temp-file file (insert "foo\n"))
+ (skip-unless (file-writable-p file))
+ (set-file-modes file (logand (file-modes file)
+ (lognot #o0222)))
+ (skip-unless (not (file-writable-p file)))
+
+ (with-current-buffer (find-file-noselect file)
+ ;; Prepare for tests backing up the file.
+ (setq buffer-read-only nil)
+ (goto-char (point-min))
+ (insert "bar\n")
+
+ ;; Save to read-only file with backup, declining prompt.
+ (files-tests--with-yes-or-no-p
+ (cons override-read-only-prompt nil)
+ (should-error
+ (save-buffer)
+ ;; "Attempt to save to a file that you aren't allowed to write"
+ :type 'error))
+ (should-not buffer-backed-up)
+ (should (buffer-modified-p))
+ (should-not (file-writable-p file))
+ (should (equal (file-contents file) "foo\n"))
+ (should (equal (file-contents backup) 'missing))
+
+ ;; Save to read-only file with backup, accepting prompt,
+ ;; experiencing a write error.
+ (files-tests--with-yes-or-no-p
+ (cons override-read-only-prompt t)
+ (should-error
+ (cl-letf (((symbol-function 'write-region)
+ #'signal-write-failed))
+ (save-buffer))
+ ;; "Write failed"
+ :type 'file-error))
+ (should-not buffer-backed-up)
+ (should (buffer-modified-p))
+ (should-not (file-writable-p file))
+ (should (equal (file-contents file) "foo\n"))
+ (should (equal (file-contents backup) 'missing))
+
+ ;; Save to read-only file with backup, accepting prompt.
+ (files-tests--with-yes-or-no-p
+ (cons override-read-only-prompt t)
+ (save-buffer))
+ (should buffer-backed-up)
+ (should-not (buffer-modified-p))
+ (should-not (file-writable-p file))
+ (should-not (file-writable-p backup))
+ (should (equal (file-contents file) "bar\nfoo\n"))
+ (should (equal (file-contents backup) "foo\n"))
+
+ ;; Prepare for tests not backing up the file.
+ (setq buffer-backed-up nil)
+ (delete-file backup)
+ (goto-char (point-min))
+ (insert "baz\n")
+
+ ;; Save to read-only file without backup, accepting prompt,
+ ;; experiencing a write error. This tests that issue B of
+ ;; bug#66546 is fixed. The results of the "with backup" and
+ ;; "without backup" subtests are identical when a write
+ ;; error occurs, but the code paths to reach these results
+ ;; are not. In other words, this subtest is not redundant.
+ (files-tests--with-yes-or-no-p
+ (cons override-read-only-prompt t)
+ (should-error
+ (cl-letf (((symbol-function 'write-region)
+ #'signal-write-failed))
+ (save-buffer 0))
+ ;; "Write failed"
+ :type 'file-error))
+ (should-not buffer-backed-up)
+ (should (buffer-modified-p))
+ (should-not (file-writable-p file))
+ (should (equal (file-contents file) "bar\nfoo\n"))
+ (should (equal (file-contents backup) 'missing))
+
+ ;; Save to read-only file without backup, accepting prompt.
+ ;; This tests that issue A of bug#66546 is fixed.
+ (files-tests--with-yes-or-no-p
+ (cons override-read-only-prompt t)
+ (save-buffer 0))
+ (should-not buffer-backed-up)
+ (should-not (buffer-modified-p))
+ (should-not (file-writable-p file))
+ (should (equal (file-contents file) "baz\nbar\nfoo\n"))
+ (should (equal (file-contents backup) 'missing)))))))
+
(ert-deftest files-tests-save-some-buffers ()
"Test `save-some-buffers'.
Test the 3 cases for the second argument PRED, i.e., nil, t, or
@@ -1907,5 +2101,9 @@ Prompt users for any modified buffer with `buffer-offer-save' non-nil."
(should (documentation 'bar))
(should (documentation 'zot)))))
+(ert-deftest files-tests--expand-wildcards ()
+ (should (file-expand-wildcards
+ (concat (directory-file-name default-directory) "*/"))))
+
(provide 'files-tests)
;;; files-tests.el ends here
diff --git a/test/lisp/files-x-tests.el b/test/lisp/files-x-tests.el
index 4e14ae68fb8..a2f16d5ae35 100644
--- a/test/lisp/files-x-tests.el
+++ b/test/lisp/files-x-tests.el
@@ -1,6 +1,6 @@
;;; files-x-tests.el --- tests for files-x.el. -*- lexical-binding: t -*-
-;; Copyright (C) 2016-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2016-2024 Free Software Foundation, Inc.
;; Author: Michael Albinus <michael.albinus@gmx.de>
@@ -39,6 +39,7 @@
(defconst files-x-test--variables5
'((remote-lazy-var . nil)
(remote-null-device . "/dev/null")))
+(defvar remote-shell-file-name)
(defvar remote-null-device)
(defvar remote-lazy-var nil)
(put 'remote-shell-file-name 'safe-local-variable #'identity)
@@ -482,5 +483,80 @@ If it's not initialized yet, initialize it."
`(connection-local-profile-alist ',clpa now)
`(connection-local-criteria-alist ',clca now))))
+(ert-deftest files-x-test-connection-local-value ()
+ "Test getting connection-local values."
+
+ (let ((clpa connection-local-profile-alist)
+ (clca connection-local-criteria-alist))
+ (connection-local-set-profile-variables
+ 'remote-bash files-x-test--variables1)
+ (connection-local-set-profile-variables
+ 'remote-ksh files-x-test--variables2)
+ (connection-local-set-profile-variables
+ 'remote-nullfile files-x-test--variables3)
+
+ (connection-local-set-profiles
+ nil 'remote-ksh 'remote-nullfile)
+
+ (connection-local-set-profile-variables
+ 'remote-lazy files-x-test--variables5)
+ (connection-local-set-profiles
+ files-x-test--application 'remote-lazy 'remote-bash)
+
+ (with-temp-buffer
+ ;; We need a remote `default-directory'.
+ (let ((enable-connection-local-variables t)
+ (default-directory "/method:host:")
+ (remote-null-device "null"))
+ (should-not connection-local-variables-alist)
+ (should-not (local-variable-p 'remote-shell-file-name))
+ (should-not (local-variable-p 'remote-null-device))
+ (should-not (boundp 'remote-shell-file-name))
+ (should (string-equal (symbol-value 'remote-null-device) "null"))
+
+ ;; The proper variable values are set.
+ (should (connection-local-p remote-shell-file-name))
+ (should
+ (string-equal
+ (connection-local-value remote-shell-file-name) "/bin/ksh"))
+ (should (connection-local-p remote-null-device))
+ (should
+ (string-equal
+ (connection-local-value remote-null-device) "/dev/null"))
+ (should-not (connection-local-p remote-lazy-var))
+
+ ;; Run with a different application.
+ (should
+ (connection-local-p
+ remote-shell-file-name (cadr files-x-test--application)))
+ (should
+ (string-equal
+ (connection-local-value
+ remote-shell-file-name (cadr files-x-test--application))
+ "/bin/bash"))
+ (should
+ (connection-local-p
+ remote-null-device (cadr files-x-test--application)))
+ (should
+ (string-equal
+ (connection-local-value
+ remote-null-device (cadr files-x-test--application))
+ "/dev/null"))
+ (should
+ (connection-local-p
+ remote-lazy-var (cadr files-x-test--application)))
+
+ ;; The previous bindings haven't changed.
+ (should-not connection-local-variables-alist)
+ (should-not (local-variable-p 'remote-shell-file-name))
+ (should-not (local-variable-p 'remote-null-device))
+ (should-not (boundp 'remote-shell-file-name))
+ (should (string-equal (symbol-value 'remote-null-device) "null"))))
+
+ ;; Cleanup.
+ (custom-set-variables
+ `(connection-local-profile-alist ',clpa now)
+ `(connection-local-criteria-alist ',clca now))))
+
(provide 'files-x-tests)
;;; files-x-tests.el ends here
diff --git a/test/lisp/find-cmd-tests.el b/test/lisp/find-cmd-tests.el
index 3fbd0fc4ea3..d1c57cc4cfa 100644
--- a/test/lisp/find-cmd-tests.el
+++ b/test/lisp/find-cmd-tests.el
@@ -1,6 +1,6 @@
;;; find-cmd-tests.el --- tests for find-cmd.el. -*- lexical-binding: t -*-
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/font-lock-tests.el b/test/lisp/font-lock-tests.el
index a4cfc19a770..d29b17d934a 100644
--- a/test/lisp/font-lock-tests.el
+++ b/test/lisp/font-lock-tests.el
@@ -1,6 +1,6 @@
;;; font-lock-tests.el --- Test suite for font-lock. -*- lexical-binding: t -*-
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/format-spec-tests.el b/test/lisp/format-spec-tests.el
index 31399f37250..48866ed1066 100644
--- a/test/lisp/format-spec-tests.el
+++ b/test/lisp/format-spec-tests.el
@@ -1,6 +1,6 @@
;;; format-spec-tests.el --- tests for format-spec.el -*- lexical-binding: t -*-
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/gnus/gnus-group-tests.el b/test/lisp/gnus/gnus-group-tests.el
index e12f42711ea..13301650e18 100644
--- a/test/lisp/gnus/gnus-group-tests.el
+++ b/test/lisp/gnus/gnus-group-tests.el
@@ -1,6 +1,6 @@
;;; gnus-group-tests.el --- Tests for gnus-group.el -*- lexical-binding: t; -*-
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -38,7 +38,7 @@
;; This is a very aggressive shortening of the left hand side.
("nnimap+email@banana.salesman.example.com:234" . "email@banana:234")
("nntp+some.where.edu:soc.motss" . "some:s.motss")
- ("nntp+news.gmane.org:gmane.emacs.gnus.general" . "news:g.e.g.general")
+ ("nntp+news.gmane.io:gmane.emacs.gnus.general" . "news:g.e.g.general")
("nntp+news.gnus.org:gmane.text.docbook.apps" . "news:g.t.d.apps")
;; nnimap groups.
diff --git a/test/lisp/gnus/gnus-icalendar-tests.el b/test/lisp/gnus/gnus-icalendar-tests.el
index 8f89e8f00ab..08c85013d17 100644
--- a/test/lisp/gnus/gnus-icalendar-tests.el
+++ b/test/lisp/gnus/gnus-icalendar-tests.el
@@ -1,6 +1,6 @@
;;; gnus-icalendar-tests.el --- tests -*- lexical-binding: t; -*-
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
;; Author: Jan Tatarik <jan.tatarik@gmail.com>
;; Keywords:
diff --git a/test/lisp/gnus/gnus-search-tests.el b/test/lisp/gnus/gnus-search-tests.el
index dbbe5089817..e10e31df573 100644
--- a/test/lisp/gnus/gnus-search-tests.el
+++ b/test/lisp/gnus/gnus-search-tests.el
@@ -1,6 +1,6 @@
;;; gnus-search-tests.el --- Tests for Gnus' search routines -*- lexical-binding: t; -*-
-;; Copyright (C) 2017, 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017, 2021-2024 Free Software Foundation, Inc.
;; Author: Eric Abrahamsen <eric@ericabrahamsen.net>
;; Keywords:
diff --git a/test/lisp/gnus/gnus-test-headers.el b/test/lisp/gnus/gnus-test-headers.el
index 936665fd1f8..7eeaf9c31c0 100644
--- a/test/lisp/gnus/gnus-test-headers.el
+++ b/test/lisp/gnus/gnus-test-headers.el
@@ -1,6 +1,6 @@
;;; gnus-test-headers.el --- Tests for Gnus header-related functions -*- lexical-binding: t; -*-
-;; Copyright (C) 2018-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2018-2024 Free Software Foundation, Inc.
;; Author: Eric Abrahamsen <eric@ericabrahamsen.net>
diff --git a/test/lisp/gnus/gnus-tests.el b/test/lisp/gnus/gnus-tests.el
index f50888e2077..2bd9fb3dff7 100644
--- a/test/lisp/gnus/gnus-tests.el
+++ b/test/lisp/gnus/gnus-tests.el
@@ -1,6 +1,6 @@
;;; gnus-tests.el --- Wrapper for the Gnus tests -*- lexical-binding:t -*-
-;; Copyright (C) 2011-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2011-2024 Free Software Foundation, Inc.
;; Author: Teodor Zlatanov <tzz@lifelogs.com>
diff --git a/test/lisp/gnus/gnus-util-tests.el b/test/lisp/gnus/gnus-util-tests.el
index 4b904ca6f1d..c5bf17523c2 100644
--- a/test/lisp/gnus/gnus-util-tests.el
+++ b/test/lisp/gnus/gnus-util-tests.el
@@ -1,5 +1,5 @@
;;; gnus-util-tests.el --- Selectived tests only. -*- lexical-binding:t -*-
-;; Copyright (C) 2015-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2024 Free Software Foundation, Inc.
;; Author: Jens Lechtenbörger <jens.lechtenboerger@fsfe.org>
diff --git a/test/lisp/gnus/message-tests.el b/test/lisp/gnus/message-tests.el
index 0844839c366..7f30a612126 100644
--- a/test/lisp/gnus/message-tests.el
+++ b/test/lisp/gnus/message-tests.el
@@ -1,6 +1,6 @@
;;; message-tests.el --- Tests for message-mode -*- lexical-binding: t; -*-
-;; Copyright (C) 2015-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2024 Free Software Foundation, Inc.
;; Author: João Távora <joaotavora@gmail.com>
diff --git a/test/lisp/gnus/mm-decode-tests.el b/test/lisp/gnus/mm-decode-tests.el
index e60295e21e7..27b3b85a053 100644
--- a/test/lisp/gnus/mm-decode-tests.el
+++ b/test/lisp/gnus/mm-decode-tests.el
@@ -1,6 +1,6 @@
;;; mm-decode-tests.el --- -*- lexical-binding:t -*-
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/gnus/mml-sec-tests.el b/test/lisp/gnus/mml-sec-tests.el
index a5dadf21c8c..2a18a13ba38 100644
--- a/test/lisp/gnus/mml-sec-tests.el
+++ b/test/lisp/gnus/mml-sec-tests.el
@@ -1,6 +1,6 @@
;;; mml-sec-tests.el --- Tests mml-sec.el, see README-mml-secure.txt. -*- lexical-binding:t -*-
-;; Copyright (C) 2015, 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2015, 2020-2024 Free Software Foundation, Inc.
;; Author: Jens Lechtenbörger <jens.lechtenboerger@fsfe.org>
diff --git a/test/lisp/gnus/nnrss-tests.el b/test/lisp/gnus/nnrss-tests.el
index 57ef8797475..b5bfbce9fb5 100644
--- a/test/lisp/gnus/nnrss-tests.el
+++ b/test/lisp/gnus/nnrss-tests.el
@@ -1,6 +1,6 @@
;;; nnrss-tests.el --- tests for gnus/nnrss.el -*- lexical-binding:t -*-
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/help-fns-tests.el b/test/lisp/help-fns-tests.el
index 56c521e765e..7035c8b7773 100644
--- a/test/lisp/help-fns-tests.el
+++ b/test/lisp/help-fns-tests.el
@@ -1,6 +1,6 @@
;;; help-fns-tests.el --- tests for help-fns.el -*- lexical-binding: t -*-
-;; Copyright (C) 2014-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2014-2024 Free Software Foundation, Inc.
;; Maintainer: emacs-devel@gnu.org
diff --git a/test/lisp/help-mode-tests.el b/test/lisp/help-mode-tests.el
index 30e944f6c80..4c149ae7430 100644
--- a/test/lisp/help-mode-tests.el
+++ b/test/lisp/help-mode-tests.el
@@ -1,6 +1,6 @@
;;; help-mode-tests.el --- Tests for help-mode.el -*- lexical-binding: t; -*-
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
;; Author: Simen Heggestøyl <simenheg@gmail.com>
;; Keywords:
diff --git a/test/lisp/help-tests.el b/test/lisp/help-tests.el
index 6c440f9e238..f27fa979ef0 100644
--- a/test/lisp/help-tests.el
+++ b/test/lisp/help-tests.el
@@ -1,6 +1,6 @@
;;; help-tests.el --- Tests for help.el -*- lexical-binding: t; -*-
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
;; Author: Juanma Barranquero <lekktu@gmail.com>
;; Eli Zaretskii <eliz@gnu.org>
@@ -378,7 +378,7 @@ Key Binding
(foo menu-item "Foo" foo
:enable mark-active
:help "Help text"))))))
- (describe-map-tree map nil nil nil nil t nil nil nil)
+ (help--describe-map-tree map nil nil nil nil t nil nil nil)
(should (string-match "
Key Binding
-+
@@ -393,7 +393,7 @@ C-a foo\n"
(foo menu-item "Foo" foo
:enable mark-active
:help "Help text"))))))
- (describe-map-tree map nil nil nil nil nil nil nil nil)
+ (help--describe-map-tree map nil nil nil nil nil nil nil nil)
(should (string-match "
Key Binding
-+
@@ -408,7 +408,7 @@ C-a foo
(map '(keymap . ((1 . foo)
(2 . bar))))
(shadow-maps '((keymap . ((1 . baz))))))
- (describe-map-tree map t shadow-maps nil nil t nil nil t)
+ (help--describe-map-tree map t shadow-maps nil nil t nil nil t)
(should (string-match "
Key Binding
-+
@@ -423,7 +423,7 @@ C-b bar\n"
(map '(keymap . ((1 . foo)
(2 . bar))))
(shadow-maps '((keymap . ((1 . baz))))))
- (describe-map-tree map t shadow-maps nil nil t nil nil nil)
+ (help--describe-map-tree map t shadow-maps nil nil t nil nil nil)
(should (string-match "
Key Binding
-+
@@ -435,7 +435,7 @@ C-b bar\n"
(let ((standard-output (current-buffer))
(map '(keymap . ((1 . foo)
(2 . undefined)))))
- (describe-map-tree map t nil nil nil nil nil nil nil)
+ (help--describe-map-tree map t nil nil nil nil nil nil nil)
(should (string-match "
Key Binding
-+
@@ -447,7 +447,7 @@ C-a foo\n"
(let ((standard-output (current-buffer))
(map '(keymap . ((1 . foo)
(2 . undefined)))))
- (describe-map-tree map nil nil nil nil nil nil nil nil)
+ (help--describe-map-tree map nil nil nil nil nil nil nil nil)
(should (string-match "
Key Binding
-+
diff --git a/test/lisp/hfy-cmap-tests.el b/test/lisp/hfy-cmap-tests.el
index 0d135aa8c36..79656c069c9 100644
--- a/test/lisp/hfy-cmap-tests.el
+++ b/test/lisp/hfy-cmap-tests.el
@@ -1,6 +1,6 @@
;;; hfy-cmap-tests.el --- tests for hfy-cmap.el -*- lexical-binding: t -*-
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/hi-lock-tests.el b/test/lisp/hi-lock-tests.el
index 794a3b1d0c2..82bce3bef2e 100644
--- a/test/lisp/hi-lock-tests.el
+++ b/test/lisp/hi-lock-tests.el
@@ -1,6 +1,6 @@
;;; hi-lock-tests.el --- Tests for hi-lock.el -*- lexical-binding: t; -*-
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
;; Author: Tino Calancha <tino.calancha@gmail.com>
;; Keywords:
diff --git a/test/lisp/hl-line-tests.el b/test/lisp/hl-line-tests.el
index 9c120e0d7ff..1b0b0ebe015 100644
--- a/test/lisp/hl-line-tests.el
+++ b/test/lisp/hl-line-tests.el
@@ -1,6 +1,6 @@
;;; hl-line-tests.el --- Test suite for hl-line. -*- lexical-binding: t -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/htmlfontify-tests.el b/test/lisp/htmlfontify-tests.el
index 0a351f0a8a5..e1ae0bf540d 100644
--- a/test/lisp/htmlfontify-tests.el
+++ b/test/lisp/htmlfontify-tests.el
@@ -1,6 +1,6 @@
;;; htmlfontify-tests.el --- Test suite. -*- lexical-binding: t -*-
-;; Copyright (C) 2015-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/ibuffer-tests.el b/test/lisp/ibuffer-tests.el
index 83bfa1f68af..ea9e663b1ad 100644
--- a/test/lisp/ibuffer-tests.el
+++ b/test/lisp/ibuffer-tests.el
@@ -1,6 +1,6 @@
;;; ibuffer-tests.el --- Test suite. -*- lexical-binding: t -*-
-;; Copyright (C) 2015-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -34,7 +34,7 @@
(ert-deftest ibuffer-0autoload () ; sort first
"Tests to see whether ibuffer has been autoloaded"
- (skip-unless (not (featurep 'ibuf-ext)))
+ (skip-when (featurep 'ibuf-ext))
(should
(fboundp 'ibuffer-mark-unsaved-buffers))
(should
diff --git a/test/lisp/ido-tests.el b/test/lisp/ido-tests.el
index 4f753479a06..705f96ac932 100644
--- a/test/lisp/ido-tests.el
+++ b/test/lisp/ido-tests.el
@@ -1,6 +1,6 @@
;;; ido-tests.el --- unit tests for ido.el -*- lexical-binding: t; -*-
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
;; Author: Philipp Stephani <phst@google.com>
diff --git a/test/lisp/image-file-tests.el b/test/lisp/image-file-tests.el
index d934867c1cb..1f2d0635343 100644
--- a/test/lisp/image-file-tests.el
+++ b/test/lisp/image-file-tests.el
@@ -1,6 +1,6 @@
;;; image-file-tests.el --- Test suite for image-files -*- lexical-binding: t; -*-
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/image-tests.el b/test/lisp/image-tests.el
index cb4821adefc..80142d6d6de 100644
--- a/test/lisp/image-tests.el
+++ b/test/lisp/image-tests.el
@@ -1,6 +1,6 @@
;;; image-tests.el --- tests for image.el -*- lexical-binding: t -*-
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/image/exif-tests.el b/test/lisp/image/exif-tests.el
index f803565dd62..e4ac55e4c1d 100644
--- a/test/lisp/image/exif-tests.el
+++ b/test/lisp/image/exif-tests.el
@@ -1,6 +1,6 @@
;;; exif-tests.el --- tests for exif.el -*- lexical-binding: t -*-
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/image/gravatar-tests.el b/test/lisp/image/gravatar-tests.el
index 8965be13c5d..edab6845775 100644
--- a/test/lisp/image/gravatar-tests.el
+++ b/test/lisp/image/gravatar-tests.el
@@ -1,6 +1,6 @@
;;; gravatar-tests.el --- tests for gravatar.el -*- lexical-binding: t -*-
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/image/image-dired-tests.el b/test/lisp/image/image-dired-tests.el
index 8a4acf6bd88..f58e1ba74a6 100644
--- a/test/lisp/image/image-dired-tests.el
+++ b/test/lisp/image/image-dired-tests.el
@@ -1,6 +1,6 @@
;;; image-dired-tests.el --- Tests for image-dired.el -*- lexical-binding: t -*-
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/image/image-dired-util-tests.el b/test/lisp/image/image-dired-util-tests.el
index 1f3747a82b1..5d3d0a512e6 100644
--- a/test/lisp/image/image-dired-util-tests.el
+++ b/test/lisp/image/image-dired-util-tests.el
@@ -1,6 +1,6 @@
;;; image-dired-util-tests.el --- Tests for image-dired.el -*- lexical-binding: t -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/image/wallpaper-tests.el b/test/lisp/image/wallpaper-tests.el
index c4167adbef2..5fad6b12e84 100644
--- a/test/lisp/image/wallpaper-tests.el
+++ b/test/lisp/image/wallpaper-tests.el
@@ -1,6 +1,6 @@
;;; wallpaper-tests.el --- tests for wallpaper.el -*- lexical-binding: t -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/imenu-tests.el b/test/lisp/imenu-tests.el
index cc6fdd41005..918a23160ae 100644
--- a/test/lisp/imenu-tests.el
+++ b/test/lisp/imenu-tests.el
@@ -1,6 +1,6 @@
;;; imenu-tests.el --- Test suite for imenu. -*- lexical-binding:t -*-
-;; Copyright (C) 2013-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2024 Free Software Foundation, Inc.
;; Author: Masatake YAMATO <yamato@redhat.com>
;; Keywords: tools convenience
diff --git a/test/lisp/info-tests.el b/test/lisp/info-tests.el
index 9ab00b4b82b..ebe718167bf 100644
--- a/test/lisp/info-tests.el
+++ b/test/lisp/info-tests.el
@@ -1,6 +1,6 @@
;;; info-tests.el --- Tests for info.el -*- lexical-binding: t; -*-
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/info-xref-tests.el b/test/lisp/info-xref-tests.el
index 0d98a242b7e..72b6706a22c 100644
--- a/test/lisp/info-xref-tests.el
+++ b/test/lisp/info-xref-tests.el
@@ -1,6 +1,6 @@
;;; info-xref-tests.el --- tests for info-xref.el -*- lexical-binding:t -*-
-;; Copyright (C) 2013-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/international/ccl-tests.el b/test/lisp/international/ccl-tests.el
index dfc090b3320..42862508436 100644
--- a/test/lisp/international/ccl-tests.el
+++ b/test/lisp/international/ccl-tests.el
@@ -1,6 +1,6 @@
;;; ccl-tests.el --- unit tests for ccl.el -*- lexical-binding:t -*-
-;; Copyright (C) 2018-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2018-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/international/mule-tests.el b/test/lisp/international/mule-tests.el
index 3e0c5bf9f4b..5c742451a57 100644
--- a/test/lisp/international/mule-tests.el
+++ b/test/lisp/international/mule-tests.el
@@ -1,6 +1,6 @@
;;; mule-tests.el --- unit tests for mule.el -*- lexical-binding: t; -*-
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -49,6 +49,30 @@
(kbd "C-x RET c u t f - 8 RET C-u C-u c a b RET")
(read-string "prompt:"))))))
+;;Bug#65997, ensure that old-names haven't overridden new names.
+(ert-deftest mule-cmds-tests--ucs-names-old-name-override ()
+ (let (code-points)
+ (dotimes (u (1+ (max-char 'ucs)))
+ (when-let* ((name (get-char-code-property u 'name))
+ (c (char-from-name name)))
+ (when (and (not (<= #xD800 u #xDFFF))
+ (not (= c u)))
+ (push (format "%X" u) code-points))))
+ (setq code-points (nreverse code-points))
+ (should (null code-points))))
+
+;; Bug#65997, ensure that all codepoints with names are in '(ucs-names)'.
+(ert-deftest mule-cmds-tests--ucs-names-missing-names ()
+ (let (code-points)
+ (dotimes (u (1+ (max-char 'ucs)))
+ (when-let ((name (get-char-code-property u 'name)))
+ (when (and (not (<= #xD800 u #xDFFF))
+ (not (<= #x18800 u #x18AFF))
+ (not (char-from-name name)))
+ (push (format "%X" u) code-points))))
+ (setq code-points (nreverse code-points))
+ (should (null code-points))))
+
(ert-deftest mule-utf-7 ()
;; utf-7 and utf-7-imap are not ASCII-compatible.
(should-not (coding-system-get 'utf-7 :ascii-compatible-p))
diff --git a/test/lisp/international/mule-util-tests.el b/test/lisp/international/mule-util-tests.el
index 848909985b2..cebcbd7ce33 100644
--- a/test/lisp/international/mule-util-tests.el
+++ b/test/lisp/international/mule-util-tests.el
@@ -1,6 +1,6 @@
;;; mule-util-tests.el --- tests for international/mule-util.el -*- lexical-binding:t -*-
-;; Copyright (C) 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/international/textsec-tests.el b/test/lisp/international/textsec-tests.el
index b9243cff875..edfaff5f74b 100644
--- a/test/lisp/international/textsec-tests.el
+++ b/test/lisp/international/textsec-tests.el
@@ -1,6 +1,6 @@
;;; textsec-tests.el --- Tests for textsec.el -*- lexical-binding: t; -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/international/ucs-normalize-tests.el b/test/lisp/international/ucs-normalize-tests.el
index 97b8fa66cd3..7b17ee56fb9 100644
--- a/test/lisp/international/ucs-normalize-tests.el
+++ b/test/lisp/international/ucs-normalize-tests.el
@@ -1,6 +1,6 @@
;;; ucs-normalize-tests.el --- tests for international/ucs-normalize.el -*- lexical-binding: t -*-
-;; Copyright (C) 2002-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2002-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -184,43 +184,7 @@ Must be called with `ucs-normalize-tests--norm-buf' as current buffer."
(should-not (ucs-normalize-tests--rule1-failing-for-partX 0)))
(defconst ucs-normalize-tests--failing-lines-part1
- (list 2412 2413 2414 15133 15134 15135 15136 15137
- 15138 15139 15140 15141 15142 15143 15144 15145
- 15146 15147 15148 15149 15150 15151 15152 15153
- 15154 15155 15156 15157 15158 15159 15160 15161
- 15162 15163 15164 15165 15166 15167 15168 15169
- 15170 15171 15172 15173 15174 15175 15176 15177
- 15178 15179 15180 15181 15182 15183 15184 15185
- 15186 15187 15188 15192 15193 15194 15195 15196
- 15197 15198 15199 15200 15201 16211 16212 16213
- 16214 16215 16216 16217 16218 16219 16220 16221
- 16222 16223 16224 16225 16226 16227 16228 16229
- 16230 16231 16232 16233 16234 16235 16236 16237
- 16238 16239 16240 16241 16242 16243 16244 16245
- 16246 16247 16248 16249 16250 16251 16252 16253
- 16254 16255 16256 16257 16258 16259 16260 16261
- 16262 16263 16264 16265 16266 16267 16268 16269
- 16270 16271 16272 16273 16274 16275 16276 16277
- 16278 16279 16280 16281 16282 16283 16284 16285
- 16286 16287 16288 16289 16290 16291 16292 16293
- 16294 16295 16296 16297 16298 16299 16300 16301
- 16302 16303 16304 16305 16306 16307 16308 16309
- 16310 16311 16312 16313 16314 16315 16316 16317
- 16318 16319 16320 16321 16322 16323 16324 16325
- 16326 16327 16328 16329 16330 16331 16332 16333
- 16334 16335 16336 16337 16338 16339 16340 16341
- 16342 16343 16344 16345 16346 16347 16348 16349
- 16350 16351 16352 16353 16354 16355 16356 16357
- 16358 16359 16360 16361 16362 16363 16364 16365
- 16366 16367 16368 16369 16370 16371 16372 16373
- 16374 16375 16376 16377 16378 16379 16380 16381
- 16382 16383 16384 16385 16386 16387 16388 16389
- 16390 16391 16392 16393 16394 16395 16396 16397
- 16398 16399 16400 16401 16402 16403 16404 16405
- 16406 16407 16408 16409 16410 16411 16412 16413
- 16550 16551 16552 16553 16554 16555 16556 16557
- 16488 16489 16490 16491 16492 16493 16494 16495
- 16496 16497 16558 16559))
+ (list ))
;; Keep a record of failures, for consulting afterwards (the ert
;; backtrace only shows a truncated version of these lists).
@@ -255,8 +219,8 @@ Must be called with `ucs-normalize-tests--norm-buf' as current buffer."
(ert-deftest ucs-normalize-part1 ()
:tags '(:expensive-test)
- (skip-unless (not (or (getenv "EMACS_HYDRA_CI")
- (getenv "EMACS_EMBA_CI")))) ; SLOW ~ 1800s
+ (skip-when (or (getenv "EMACS_HYDRA_CI")
+ (getenv "EMACS_EMBA_CI"))) ; SLOW ~ 1800s
;; This takes a long time, so make sure we're compiled.
(dolist (fun '(ucs-normalize-tests--part1-rule2
ucs-normalize-tests--rule1-failing-for-partX
@@ -283,88 +247,20 @@ Must be called with `ucs-normalize-tests--norm-buf' as current buffer."
ucs-normalize-tests--failing-lines-part1)))
(defconst ucs-normalize-tests--failing-lines-part2
- (list 17087 17088 17089 17090 17091 17092 17093 17094
- 17098 17099 17100 17101 17102 17103 17104 17105
- 17106 17107 17108 17113 17114 17115 17116 17117
- 17118 17119 17120 17125 17126 17127 17128 17129
- 17130 17131 17132 17133 17134 17135 17136 17137
- 17138 17139 17140 17141 17142 17143 17144 17145
- 17146 17157 17158 17159 17160 17161 17162 17163
- 17164 17185 17186 17187 17188 17189 17190 17197
- 17198 17199 17200 17207 17208 17209 17210 17211
- 17212 17213 17214 17219 17220 17221 17222 17275
- 17276 17285 17286 17295 17296 17309 17310 17311
- 17312 17313 17314 17315 17316 17317 17318 17319
- 17320 17325 17326 17373 17374 17419 17420 17421
- 17422 17433 17434 17439 17440 17465 17466 17473
- 17474 17479 17480 17485 17486 17491 17492 17497
- 17498 17499 17500 17501 17502 17505 17506 17507
- 17508 17511 17512 17519 17520 17523 17524 17527
- 17528 17531 17532 17551 17552 17555 17556 17599
- 17600 17601 17602 17603 17604 17605 17607 17608
- 17609 17610 17611 17612 17613 17615 17617 17619
- 17621 17623 17625 17627 17629 17631 17632 17633
- 17634 17635 17636 17637 17638 17639 17640 17669
- 17670 17675 17676 17681 17682 17689 17690 17691
- 17692 17693 17694 17707 17708 17713 17714 17715
- 17716 17727 17728 17733 17734 17739 17740 17745
- 17746 17749 17750 17753 17754 17759 17760 17767
- 17768 17789 17790 17801 17802 17807 17808 17809
- 17810 17811 17812 17813 17814 17815 17816 17821
- 17822 17829 17830 17843 17844 17845 17846 17851
- 17852 17861 17875 17876 17879 17880 17899 17900
- 17097 17907 17908 17911 17912 17913 17914 17915
- 17916 17917 17918 17919 17920 17921 17922 17927
- 17928 17929 17930 17931 17932 17933 17935 17937
- 17938 17939 17940 17941 17943 17945 17947 17949
- 17951 17952 17953 17955 17957 17959 17961 17962
- 17967 17968 17987 17988 17993 17994 18003 18004
- 18005 18006 18007 18008 18009 18010 18011 18012
- 18017 18018 18019 18020 18021 18022 18023 18024
- 18041 18042 18049 18050 18053 18054 18055 18056
- 18069 18070 18079 18080 18163 18164 18165 18166
- 18171 18172 18175 18176 18211 18212 18219 18220
- 18221 18222 18223 18224 18225 18226 18301 18302
- 18389 18390 18391 18392 18393 18394 18397 18398
- 18407 18408 18439 18440 18441 18442 18443 18444
- 18445 18446 18447 18448 18449 18450 18451 18452
- 18457 18458 18459 18460 18471 18472 18479 18480
- 18485 18486 18499 18500 18501 18502 18509 18510
- 18513 18514 18515 18516 18517 18518 18519 18520
- 18521 18523 18524 18525 18527 18528 18531 18537
- 18538 18539 18541 18543 18545 18547 18549 18550
- 18551 18553 18554 18555 18557 18558 18559 18560
- 18561 18562 18563 18564 18565 18566 18567 18569
- 18571 18573 18575 18577 18579 18581 18583 18585
- 18587 18589 18591 18593 18595 18596 18597 18599
- 18601 18602 18603 18605 18606 18607 18609 18611
- 18612 18613 18615 18617 18618 18619 18621 18622
- 18623 18624 18625 18626 18627 18628 18629 18631
- 18632 18633 18634 18635 18636 18637 18639 18641
- 18643 18645 18647 18649 18651 18653 18655 18657
- 18659 18661 18663 18664 18665 18667 18668 18669
- 18670 18671 18673 18674 18675 18676 18677 18679
- 18680 18681 18683 18685 18686 18687 18688 18689
- 18690 18691 18692 18693 18694 18695 18696 18697
- 18698 18699 18700 18701 18702 18703 18704 18705
- 18706 18707 18708 18709 18710 18711 18712 18713
- 18714 18715 18717 18719 18721 18722 18723 18724
- 18725 18727 18729 18731 18733 18735 18737 18739
- 18740 18741 18742 18743 18745 18747 18749 18751
- 18753 18755 18757 18759 18761 18763 18765 18767
- 18769 18771 18773 18775 18777 18779 18781 18783
- 18785 18787 18789 18791 18793 18795 18797 18799
- 18801 18803 18805 18807 18809 18811 18813 18815
- 18817 18819 18821 18823 18825 18827 18829 18831
- 18833 18835 18837 18839 18840 18841 18842 18843
- 18844 18845 18846 18847 18848 18849 18850 18851
- 18852 18853 18855 18857 18859 18861 18863 18865
- 18866 18867 18869 18871 18873 18875 18877 18879
- 18881 18883 18885 18887 18888 18889 18891 18893
- 18895 18897 18899 18901 18903 18905 18907 18909
- 18911 18913 18914 18915 18916 18917 18918 18919
- 18920 18921 18923 18925 18927 18929 18931 18933
- 18935 18937 18939 18941 18943 18945 18947 18948))
+ (list 17789 17790 17801 17802 17807 17808 17811 17812
+ 17815 17816 17821 17822 17829 17830 17907 17908
+ 18023 18024 18049 18050 18055 18056 18459 18460
+ 18605 18606 18617 18618 18621 18622 18625 18626
+ 18627 18628 18631 18632 18633 18634 18663 18664
+ 18669 18670 18673 18674 18679 18680 18685 18686
+ 18691 18692 18695 18697 18699 18701 18703 18704
+ 18705 18707 18709 18711 18713 18715 18717 18719
+ 18721 18723 18725 18727 18729 18731 18733 18735
+ 18737 18739 18740 18741 18742 18743 18889 18891
+ 18893 18895 18897 18899 18901 18903 18905 18907
+ 18909 18911 18913 18914 18915 18916 18917 18919
+ 18921 18923 18925 18927 18929 18931 18933 18935
+ 18937 18939 18941 18943 18945 18947 18948))
(ert-deftest ucs-normalize-part2 ()
:tags '(:expensive-test)
diff --git a/test/lisp/isearch-tests.el b/test/lisp/isearch-tests.el
index e71f0a5785f..b5b1b20e932 100644
--- a/test/lisp/isearch-tests.el
+++ b/test/lisp/isearch-tests.el
@@ -1,6 +1,6 @@
;;; isearch-tests.el --- Tests for isearch.el -*- lexical-binding: t; -*-
-;; Copyright (C) 2013-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2024 Free Software Foundation, Inc.
;; Author: Artur Malabarba <bruce.connor.am@gmail.com>
@@ -39,6 +39,157 @@
(isearch-done))
+;; Search invisible.
+
+(declare-function outline-hide-sublevels "outline")
+
+(ert-deftest isearch--test-invisible ()
+ (require 'outline)
+ (with-temp-buffer
+ (set-window-buffer nil (current-buffer))
+ (insert "\n1\n"
+ (propertize "2" 'invisible t)
+ (propertize "3" 'inhibit-isearch t)
+ "\n* h\n4\n\n")
+ (outline-mode)
+ (outline-hide-sublevels 1)
+ (goto-char (point-min))
+
+ (let ((isearch-lazy-count nil)
+ (search-invisible t)
+ (inhibit-message t))
+
+ (isearch-forward-regexp nil 1)
+ (isearch-process-search-string "[0-9]" "[0-9]")
+ (should (eq (point) 3))
+
+ (isearch-lazy-highlight-start)
+ (should (equal (seq-uniq (mapcar #'overlay-start isearch-lazy-highlight-overlays))
+ '(2)))
+
+ (isearch-repeat-forward)
+ (should (eq (point) 5))
+ (should (get-char-property 4 'invisible))
+ (isearch-repeat-forward)
+ (should (eq (point) 12))
+ (should (get-char-property 11 'invisible))
+
+ (goto-char isearch-opoint)
+ (isearch-done t)
+
+ (isearch-forward-regexp nil 1)
+ (setq isearch-invisible nil) ;; isearch-toggle-invisible
+ (isearch-process-search-string "[0-9]" "[0-9]")
+
+ (isearch-lazy-highlight-start)
+ (should (equal (seq-uniq (mapcar #'overlay-start isearch-lazy-highlight-overlays))
+ '(2)))
+
+ (goto-char isearch-opoint)
+ (isearch-done t)
+
+ (isearch-forward-regexp nil 1)
+ (setq isearch-invisible 'open) ;; isearch-toggle-invisible
+ (isearch-process-search-string "[0-9]" "[0-9]")
+ (should (eq (point) 3))
+
+ (isearch-lazy-highlight-start)
+ (should (equal (seq-uniq (mapcar #'overlay-start isearch-lazy-highlight-overlays))
+ '(2 11)))
+
+ (let ((isearch-hide-immediately t))
+ (isearch-repeat-forward)
+ (should (eq (point) 12))
+ (should-not (get-char-property 11 'invisible))
+ (isearch-delete-char)
+ (should (get-char-property 11 'invisible)))
+
+ (let ((isearch-hide-immediately nil))
+ (isearch-repeat-forward)
+ (should (eq (point) 12))
+ (should-not (get-char-property 11 'invisible))
+ (isearch-delete-char)
+ (should-not (get-char-property 11 'invisible)))
+
+ (goto-char isearch-opoint)
+ (isearch-done t)
+ (isearch-clean-overlays)
+ (should (get-char-property 11 'invisible)))
+
+ (let ((isearch-lazy-count t)
+ (search-invisible t)
+ (inhibit-message t))
+
+ (isearch-forward-regexp nil 1)
+ (isearch-process-search-string "[0-9]" "[0-9]")
+ (should (eq (point) 3))
+
+ (setq isearch-lazy-count-invisible nil isearch-lazy-count-total nil)
+ (isearch-lazy-highlight-start)
+ (isearch-lazy-highlight-buffer-update)
+ (should (eq isearch-lazy-count-invisible nil))
+ (should (eq isearch-lazy-count-total 3))
+ (should (equal (seq-uniq (mapcar #'overlay-start isearch-lazy-highlight-overlays))
+ '(2)))
+
+ (isearch-repeat-forward)
+ (should (eq (point) 5))
+ (should (get-char-property 4 'invisible))
+ (isearch-repeat-forward)
+ (should (eq (point) 12))
+ (should (get-char-property 11 'invisible))
+
+ (goto-char isearch-opoint)
+ (isearch-done t)
+
+ (isearch-forward-regexp nil 1)
+ (setq isearch-invisible nil) ;; isearch-toggle-invisible
+ (isearch-process-search-string "[0-9]" "[0-9]")
+
+ (setq isearch-lazy-count-invisible nil isearch-lazy-count-total nil)
+ (isearch-lazy-highlight-start)
+ (isearch-lazy-highlight-buffer-update)
+ (should (eq isearch-lazy-count-invisible 2))
+ (should (eq isearch-lazy-count-total 1))
+ (should (equal (seq-uniq (mapcar #'overlay-start isearch-lazy-highlight-overlays))
+ '(2)))
+
+ (goto-char isearch-opoint)
+ (isearch-done t)
+
+ (isearch-forward-regexp nil 1)
+ (setq isearch-invisible 'open) ;; isearch-toggle-invisible
+ (isearch-process-search-string "[0-9]" "[0-9]")
+ (should (eq (point) 3))
+
+ (setq isearch-lazy-count-invisible nil isearch-lazy-count-total nil)
+ (isearch-lazy-highlight-start)
+ (isearch-lazy-highlight-buffer-update)
+ (should (eq isearch-lazy-count-invisible 1))
+ (should (eq isearch-lazy-count-total 2))
+ (should (equal (seq-uniq (mapcar #'overlay-start isearch-lazy-highlight-overlays))
+ '(2 11)))
+
+ (let ((isearch-hide-immediately t))
+ (isearch-repeat-forward)
+ (should (eq (point) 12))
+ (should-not (get-char-property 11 'invisible))
+ (isearch-delete-char)
+ (should (get-char-property 11 'invisible)))
+
+ (let ((isearch-hide-immediately nil))
+ (isearch-repeat-forward)
+ (should (eq (point) 12))
+ (should-not (get-char-property 11 'invisible))
+ (isearch-delete-char)
+ (should-not (get-char-property 11 'invisible)))
+
+ (goto-char isearch-opoint)
+ (isearch-done t)
+ (isearch-clean-overlays)
+ (should (get-char-property 11 'invisible)))))
+
+
;; Search functions.
(defun isearch--test-search-within-boundaries (pairs)
diff --git a/test/lisp/jit-lock-tests.el b/test/lisp/jit-lock-tests.el
index 6944068828a..ea04a213d57 100644
--- a/test/lisp/jit-lock-tests.el
+++ b/test/lisp/jit-lock-tests.el
@@ -1,6 +1,6 @@
;;; jit-lock-tests.el --- tests for jit-lock -*- lexical-binding:t -*-
-;; Copyright (C) 2016-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2016-2024 Free Software Foundation, Inc.
;; Author: Dmitry Gutov <dgutov@yandex.ru>
diff --git a/test/lisp/json-tests.el b/test/lisp/json-tests.el
index 92edb6e13f1..fbcfa826a6f 100644
--- a/test/lisp/json-tests.el
+++ b/test/lisp/json-tests.el
@@ -1,6 +1,6 @@
;;; json-tests.el --- Test suite for json.el -*- lexical-binding:t -*-
-;; Copyright (C) 2015-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2024 Free Software Foundation, Inc.
;; Author: Dmitry Gutov <dgutov@yandex.ru>
diff --git a/test/lisp/jsonrpc-tests.el b/test/lisp/jsonrpc-tests.el
index 85ac96a931c..cfbea7378e2 100644
--- a/test/lisp/jsonrpc-tests.el
+++ b/test/lisp/jsonrpc-tests.el
@@ -1,6 +1,6 @@
;;; jsonrpc-tests.el --- tests for jsonrpc.el -*- lexical-binding: t; -*-
-;; Copyright (C) 2018-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2018-2024 Free Software Foundation, Inc.
;; Author: João Távora <joaotavora@gmail.com>
;; Keywords: tests
@@ -103,6 +103,7 @@
(process-get listen-server 'handlers))))))))
(cl-defmacro jsonrpc--with-emacsrpc-fixture ((endpoint-sym) &body body)
+ (declare (indent 1))
`(jsonrpc--call-with-emacsrpc-fixture (lambda (,endpoint-sym) ,@body)))
(ert-deftest returns-3 ()
@@ -151,14 +152,6 @@
[1 2 3 3 4 5]
(jsonrpc-request conn 'vconcat [[1 2 3] [3 4 5]])))))
-(ert-deftest json-el-cant-serialize-this ()
- "Can't serialize a response that is half-vector/half-list."
- (jsonrpc--with-emacsrpc-fixture (conn)
- (should-error
- ;; (append [1 2 3] [3 4 5]) => (1 2 3 . [3 4 5]), which can't be
- ;; serialized
- (jsonrpc-request conn 'append [[1 2 3] [3 4 5]]))))
-
(cl-defmethod jsonrpc-connection-ready-p
((conn jsonrpc--test-client) what)
(and (cl-call-next-method)
diff --git a/test/lisp/kmacro-tests.el b/test/lisp/kmacro-tests.el
index a325220e8d9..2eead234988 100644
--- a/test/lisp/kmacro-tests.el
+++ b/test/lisp/kmacro-tests.el
@@ -1,6 +1,6 @@
;;; kmacro-tests.el --- Tests for kmacro.el -*- lexical-binding: t; -*-
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
;; Author: Gemini Lasswell <gazally@runbox.com>
diff --git a/test/lisp/loadhist-resources/loadhist--bar.el b/test/lisp/loadhist-resources/loadhist--bar.el
index 882d073ab56..022f9c149c4 100644
--- a/test/lisp/loadhist-resources/loadhist--bar.el
+++ b/test/lisp/loadhist-resources/loadhist--bar.el
@@ -1,6 +1,6 @@
;;; loadhist--bar.el --- Dummy package for loadhist-tests -*- lexical-binding: t; -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
diff --git a/test/lisp/loadhist-resources/loadhist--foo.el b/test/lisp/loadhist-resources/loadhist--foo.el
index 239066b6def..9c5ee310600 100644
--- a/test/lisp/loadhist-resources/loadhist--foo.el
+++ b/test/lisp/loadhist-resources/loadhist--foo.el
@@ -1,6 +1,6 @@
;;; loadhist--foo.el --- Dummy package for loadhist-tests -*- lexical-binding: t; -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
diff --git a/test/lisp/loadhist-tests.el b/test/lisp/loadhist-tests.el
index 28f6607d95c..0192edf2a8f 100644
--- a/test/lisp/loadhist-tests.el
+++ b/test/lisp/loadhist-tests.el
@@ -1,6 +1,6 @@
;;; loadhist-tests.el --- Tests for loadhist.el -*- lexical-binding:t -*-
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
;; Author: Stefan Kangas <stefankangas@gmail.com>
diff --git a/test/lisp/lpr-tests.el b/test/lisp/lpr-tests.el
index 382b3ae905f..446633a9385 100644
--- a/test/lisp/lpr-tests.el
+++ b/test/lisp/lpr-tests.el
@@ -1,6 +1,6 @@
;;; lpr-tests.el --- Tests for lpr.el -*- lexical-binding: t -*-
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/ls-lisp-tests.el b/test/lisp/ls-lisp-tests.el
index 8c6262819c4..77046871ea7 100644
--- a/test/lisp/ls-lisp-tests.el
+++ b/test/lisp/ls-lisp-tests.el
@@ -1,6 +1,6 @@
;;; ls-lisp-tests.el --- tests for ls-lisp.el -*- lexical-binding: t-*-
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
;; Author: Tino Calancha <tino.calancha@gmail.com>
;; Keywords:
@@ -29,13 +29,6 @@
(require 'ls-lisp)
(require 'dired)
-(ert-deftest ls-lisp-unload ()
- "Test for https://debbugs.gnu.org/xxxxx ."
- (should (advice-member-p 'ls-lisp--insert-directory 'insert-directory))
- (unload-feature 'ls-lisp 'force)
- (should-not (advice-member-p 'ls-lisp--insert-directory 'insert-directory))
- (require 'ls-lisp))
-
(ert-deftest ls-lisp-test-bug27762 ()
"Test for https://debbugs.gnu.org/27762 ."
(let* ((dir source-directory)
diff --git a/test/lisp/mail/flow-fill-tests.el b/test/lisp/mail/flow-fill-tests.el
index f6e92199814..1f698f538f3 100644
--- a/test/lisp/mail/flow-fill-tests.el
+++ b/test/lisp/mail/flow-fill-tests.el
@@ -1,6 +1,6 @@
;;; flow-fill-tests.el --- Tests for flow-fill.el -*- lexical-binding: t -*-
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/mail/footnote-tests.el b/test/lisp/mail/footnote-tests.el
index 1415d2944a7..62927655375 100644
--- a/test/lisp/mail/footnote-tests.el
+++ b/test/lisp/mail/footnote-tests.el
@@ -1,6 +1,6 @@
;;; footnote-tests.el --- Tests for footnote-mode -*- lexical-binding: t; -*-
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
;; Keywords:
diff --git a/test/lisp/mail/ietf-drums-date-tests.el b/test/lisp/mail/ietf-drums-date-tests.el
index 822b5bd041d..3ae3c6b9524 100644
--- a/test/lisp/mail/ietf-drums-date-tests.el
+++ b/test/lisp/mail/ietf-drums-date-tests.el
@@ -1,6 +1,6 @@
;;; ietf-drums-date-tests.el --- Test suite for ietf-drums-date.el -*- lexical-binding:t -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;; Author: Bob Rogers <rogers@rgrjr.com>
diff --git a/test/lisp/mail/ietf-drums-tests.el b/test/lisp/mail/ietf-drums-tests.el
index c55c5467f60..0f71d80e79d 100644
--- a/test/lisp/mail/ietf-drums-tests.el
+++ b/test/lisp/mail/ietf-drums-tests.el
@@ -1,6 +1,6 @@
;;; ietf-drums-tests.el --- Test suite for ietf-drums.el -*- lexical-binding:t -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;; Author: Bob Rogers <rogers@rgrjr.com>
diff --git a/test/lisp/mail/mail-extr-tests.el b/test/lisp/mail/mail-extr-tests.el
index 1013b9e2058..5e526d27da6 100644
--- a/test/lisp/mail/mail-extr-tests.el
+++ b/test/lisp/mail/mail-extr-tests.el
@@ -1,6 +1,6 @@
;;; mail-extr-tests.el --- Tests for mail-extr.el -*- lexical-binding: t -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/mail/mail-parse-tests.el b/test/lisp/mail/mail-parse-tests.el
index c4abbaa93ca..d0a3edd0b93 100644
--- a/test/lisp/mail/mail-parse-tests.el
+++ b/test/lisp/mail/mail-parse-tests.el
@@ -1,6 +1,6 @@
;;; mail-parse-tests.el --- tests for mail-parse.el -*- lexical-binding: t -*-
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/mail/mail-utils-tests.el b/test/lisp/mail/mail-utils-tests.el
index 3bf5f2065e1..3d650485944 100644
--- a/test/lisp/mail/mail-utils-tests.el
+++ b/test/lisp/mail/mail-utils-tests.el
@@ -1,6 +1,6 @@
;;; mail-utils-tests.el --- tests for mail-utils.el -*- lexical-binding: t -*-
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
;; Author: Stefan Kangas <stefankangas@gmail.com>
diff --git a/test/lisp/mail/qp-tests.el b/test/lisp/mail/qp-tests.el
index 9f0857a0ba6..2835707d89b 100644
--- a/test/lisp/mail/qp-tests.el
+++ b/test/lisp/mail/qp-tests.el
@@ -1,6 +1,6 @@
;;; qp-tests.el --- Tests for qp.el -*- lexical-binding:t; coding:utf-8 -*-
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
;; Author: Stefan Kangas <stefankangas@gmail.com>
diff --git a/test/lisp/mail/rfc2045-tests.el b/test/lisp/mail/rfc2045-tests.el
index 0982e057609..23af9abc03e 100644
--- a/test/lisp/mail/rfc2045-tests.el
+++ b/test/lisp/mail/rfc2045-tests.el
@@ -1,6 +1,6 @@
;;; rfc2045-tests.el --- Tests for rfc2045.el -*- lexical-binding:t -*-
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
;; Author: Stefan Kangas <stefankangas@gmail.com>
diff --git a/test/lisp/mail/rfc2047-tests.el b/test/lisp/mail/rfc2047-tests.el
index 3ce3bc10614..432b7632efb 100644
--- a/test/lisp/mail/rfc2047-tests.el
+++ b/test/lisp/mail/rfc2047-tests.el
@@ -1,6 +1,6 @@
;;; rfc2047-tests.el --- tests for rfc2047.el -*- lexical-binding: t -*-
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/mail/rfc6068-tests.el b/test/lisp/mail/rfc6068-tests.el
index 6b7de3dfedd..44052237415 100644
--- a/test/lisp/mail/rfc6068-tests.el
+++ b/test/lisp/mail/rfc6068-tests.el
@@ -1,6 +1,6 @@
;;; rfc6068-tests.el --- Tests for rfc6068.el -*- lexical-binding:t -*-
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/mail/rfc822-tests.el b/test/lisp/mail/rfc822-tests.el
index 53175fef079..9faa10ae81e 100644
--- a/test/lisp/mail/rfc822-tests.el
+++ b/test/lisp/mail/rfc822-tests.el
@@ -1,6 +1,6 @@
;;; rfc822-tests.el --- Tests for rfc822.el -*- lexical-binding:t -*-
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/mail/rmail-tests.el b/test/lisp/mail/rmail-tests.el
index ae810c2e8df..f0c58543745 100644
--- a/test/lisp/mail/rmail-tests.el
+++ b/test/lisp/mail/rmail-tests.el
@@ -1,6 +1,6 @@
;;; rmail-tests.el --- Test suite. -*- lexical-binding: t -*-
-;; Copyright (C) 2015-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/mail/rmailmm-tests.el b/test/lisp/mail/rmailmm-tests.el
index 0daaf2954dd..1029aa19b0f 100644
--- a/test/lisp/mail/rmailmm-tests.el
+++ b/test/lisp/mail/rmailmm-tests.el
@@ -1,6 +1,6 @@
;;; rmailmm-tests.el --- Tests for rmailmm.el -*- lexical-binding:t -*-
-;; Copyright (C) 2006-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2006-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/mail/undigest-tests.el b/test/lisp/mail/undigest-tests.el
index 4fe65258b1e..8a0716b61dd 100644
--- a/test/lisp/mail/undigest-tests.el
+++ b/test/lisp/mail/undigest-tests.el
@@ -1,6 +1,6 @@
;;; undigest-tests.el --- Tests for undigest.el -*- lexical-binding:t -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/mail/uudecode-tests.el b/test/lisp/mail/uudecode-tests.el
index 6cfbc5e1b53..89a9b574321 100644
--- a/test/lisp/mail/uudecode-tests.el
+++ b/test/lisp/mail/uudecode-tests.el
@@ -1,6 +1,6 @@
;;; uudecode-tests.el --- Tests for uudecode.el -*- lexical-binding: t -*-
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
;; Author: Stefan Kangas <stefankangas@gmail.com>
diff --git a/test/lisp/man-tests.el b/test/lisp/man-tests.el
index e3657d7df8a..140482ee622 100644
--- a/test/lisp/man-tests.el
+++ b/test/lisp/man-tests.el
@@ -1,6 +1,6 @@
;;; man-tests.el --- Test suite for man. -*- lexical-binding:t -*-
-;; Copyright (C) 2013-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2024 Free Software Foundation, Inc.
;; Author: Wolfgang Jenkner <wjenkner@inode.at>
;; Keywords: help, internal, unix
diff --git a/test/lisp/md4-tests.el b/test/lisp/md4-tests.el
index 50d1a7feabc..aa14e859b3c 100644
--- a/test/lisp/md4-tests.el
+++ b/test/lisp/md4-tests.el
@@ -1,6 +1,6 @@
;;; md4-tests.el --- tests for md4.el -*- lexical-binding: t -*-
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
;; Author: Mark Oteiza <mvoteiza@udel.edu>
;; Maintainer: emacs-devel@gnu.org
diff --git a/test/lisp/mh-e/mh-limit-tests.el b/test/lisp/mh-e/mh-limit-tests.el
index 1fab3e1d9cc..4c6c0f389a7 100644
--- a/test/lisp/mh-e/mh-limit-tests.el
+++ b/test/lisp/mh-e/mh-limit-tests.el
@@ -1,6 +1,6 @@
;;; mh-limit-tests.el --- tests for mh-limit.el -*- lexical-binding: t -*-
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/mh-e/mh-thread-tests.el b/test/lisp/mh-e/mh-thread-tests.el
index 3cc21f45ab9..1b3cf399c51 100644
--- a/test/lisp/mh-e/mh-thread-tests.el
+++ b/test/lisp/mh-e/mh-thread-tests.el
@@ -1,6 +1,6 @@
;;; mh-thread-tests.el --- tests for mh-thread.el -*- lexical-binding: t -*-
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/mh-e/mh-utils-tests.el b/test/lisp/mh-e/mh-utils-tests.el
index 25be86070b8..2032e915387 100644
--- a/test/lisp/mh-e/mh-utils-tests.el
+++ b/test/lisp/mh-e/mh-utils-tests.el
@@ -1,6 +1,6 @@
;;; mh-utils-tests.el --- tests for mh-utils.el -*- lexical-binding: t -*-
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/mh-e/mh-xface-tests.el b/test/lisp/mh-e/mh-xface-tests.el
index 0630c018f60..c103b951b72 100644
--- a/test/lisp/mh-e/mh-xface-tests.el
+++ b/test/lisp/mh-e/mh-xface-tests.el
@@ -1,6 +1,6 @@
;;; mh-xface-tests.el --- tests for mh-xface.el -*- lexical-binding: t -*-
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/mh-e/test-all-mh-variants.sh b/test/lisp/mh-e/test-all-mh-variants.sh
index 5e6b26fd2ec..a23289701fc 100755
--- a/test/lisp/mh-e/test-all-mh-variants.sh
+++ b/test/lisp/mh-e/test-all-mh-variants.sh
@@ -1,7 +1,7 @@
#! /bin/bash
# Run the mh-utils-tests against all MH variants found on this system.
-# Copyright (C) 2021-2023 Free Software Foundation, Inc.
+# Copyright (C) 2021-2024 Free Software Foundation, Inc.
# This file is part of GNU Emacs.
@@ -81,8 +81,10 @@ for path in "${mh_sys_path[@]}"; do
fi
echo "** Testing with PATH $path"
((++tests_total))
+ # The LD_LIBRARY_PATH setting is needed
+ # to run locally installed Mailutils.
TEST_MH_PATH=$path TEST_MH_DEBUG=$debug \
- HOME=/nonexistent \
+ LD_LIBRARY_PATH=/usr/local/lib HOME=/nonexistent \
"${emacs[@]}" -l ert \
--eval "(setq load-prefer-newer t)" \
--eval "(load \"$PWD/test/lisp/mh-e/mh-utils-tests\" nil t)" \
diff --git a/test/lisp/minibuffer-tests.el b/test/lisp/minibuffer-tests.el
index ff58d35eb3e..6dc15d0801f 100644
--- a/test/lisp/minibuffer-tests.el
+++ b/test/lisp/minibuffer-tests.el
@@ -1,6 +1,6 @@
;;; minibuffer-tests.el --- Tests for completion functions -*- lexical-binding: t; -*-
-;; Copyright (C) 2013-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2024 Free Software Foundation, Inc.
;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
;; Keywords:
@@ -33,14 +33,13 @@
(ert-deftest completion-test1 ()
(with-temp-buffer
- (cl-flet* ((test/completion-table (_string _pred action)
- (if (eq action 'lambda)
- nil
- "test: "))
+ (cl-flet* ((test/completion-table (string pred action)
+ (let ((completion-ignore-case t))
+ (complete-with-action action '("test: ") string pred)))
(test/completion-at-point ()
- (list (copy-marker (point-min))
- (copy-marker (point))
- #'test/completion-table)))
+ (list (copy-marker (point-min))
+ (copy-marker (point))
+ #'test/completion-table)))
(let ((completion-at-point-functions (list #'test/completion-at-point)))
(insert "TEST")
(completion-at-point)
@@ -190,7 +189,8 @@
(defun completion--pcm-score (comp)
"Get `completion-score' from COMP."
- (get-text-property 0 'completion-score comp))
+ ;; FIXME, uses minibuffer.el implementation details
+ (completion--flex-score comp completion-pcm--regexp))
(defun completion--pcm-first-difference-pos (comp)
"Get `completions-first-difference' from COMP."
@@ -298,6 +298,19 @@
"jab" '("dabjabstabby" "many") nil 3)))
6)))
+(ert-deftest completion-substring-test-5 ()
+ ;; merge-completions needs to work correctly when
+ (should (equal
+ (completion-pcm--merge-completions '("ab" "sab") '(prefix "b"))
+ '("b" "a" prefix)))
+ (should (equal
+ (completion-pcm--merge-completions '("ab" "ab") '(prefix "b"))
+ '("b" "a")))
+ ;; substring completion should successfully complete the entire string
+ (should (equal
+ (completion-substring-try-completion "b" '("ab" "ab") nil 0)
+ '("ab" . 2))))
+
(ert-deftest completion-flex-test-1 ()
;; Fuzzy match
(should (equal
@@ -407,6 +420,21 @@
(next-completion 5)
(should (equal "ac" (get-text-property (point) 'completion--string)))
(previous-completion 5)
+ (should (equal "aa" (get-text-property (point) 'completion--string)))
+
+ (first-completion)
+ (should (equal "aa" (get-text-property (point) 'completion--string)))
+ (next-line-completion 2)
+ (should (equal "ac" (get-text-property (point) 'completion--string)))
+ (next-line-completion 5)
+ (should (equal "ac" (get-text-property (point) 'completion--string)))
+ (previous-line-completion 5)
+ (should (equal "aa" (get-text-property (point) 'completion--string)))
+ (goto-char (point-min))
+ (next-line-completion 5)
+ (should (equal "ac" (get-text-property (point) 'completion--string)))
+ (goto-char (point-min))
+ (previous-line-completion 5)
(should (equal "aa" (get-text-property (point) 'completion--string)))))
(let ((completion-auto-wrap t))
(completing-read-with-minibuffer-setup
@@ -420,6 +448,21 @@
(next-completion 1)
(should (equal "aa" (get-text-property (point) 'completion--string)))
(previous-completion 1)
+ (should (equal "ac" (get-text-property (point) 'completion--string)))
+
+ (first-completion)
+ (should (equal "aa" (get-text-property (point) 'completion--string)))
+ (next-line-completion 2)
+ (should (equal "ac" (get-text-property (point) 'completion--string)))
+ (next-line-completion 1)
+ (should (equal "aa" (get-text-property (point) 'completion--string)))
+ (previous-line-completion 1)
+ (should (equal "ac" (get-text-property (point) 'completion--string)))
+ (goto-char (point-min))
+ (next-line-completion 4)
+ (should (equal "aa" (get-text-property (point) 'completion--string)))
+ (goto-char (point-min))
+ (previous-line-completion 4)
(should (equal "ac" (get-text-property (point) 'completion--string))))))
(ert-deftest completions-header-format-test ()
@@ -441,6 +484,16 @@
(should (equal "ac" (get-text-property (point) 'completion--string)))
(next-completion 1)
(should (equal "aa" (get-text-property (point) 'completion--string)))
+
+ (next-line-completion 2)
+ (should (equal "ac" (get-text-property (point) 'completion--string)))
+ (previous-line-completion 2)
+ (should (equal "aa" (get-text-property (point) 'completion--string)))
+ (previous-line-completion 1)
+ (should (equal "ac" (get-text-property (point) 'completion--string)))
+ (next-line-completion 1)
+ (should (equal "aa" (get-text-property (point) 'completion--string)))
+
;; Fixed in bug#55430
(execute-kbd-macro (kbd "C-u RET"))
(should (equal (minibuffer-contents) "aa")))
@@ -475,8 +528,58 @@
;; Fixed in bug#54374
(goto-char (1- (point-max)))
(should-not (equal 'highlight (get-text-property (point) 'mouse-face)))
+
+ (first-completion)
+ (should (equal "aa" (get-text-property (point) 'completion--string)))
+ (let ((completion-auto-wrap t))
+ (next-line-completion 3))
+ (should (equal "aa" (get-text-property (point) 'completion--string)))
+ (let ((completion-auto-wrap nil))
+ (next-line-completion 3))
+ (should (equal "ac" (get-text-property (point) 'completion--string)))
+
(execute-kbd-macro (kbd "C-u RET"))
(should (equal (minibuffer-contents) "ac")))))
+(ert-deftest completions-group-navigation-test ()
+ (completing-read-with-minibuffer-setup
+ (lambda (string pred action)
+ (if (eq action 'metadata)
+ `(metadata
+ (group-function
+ . ,(lambda (name transform)
+ (if transform
+ name
+ (pcase name
+ (`"aa" "Group 1")
+ (`"ab" "Group 2")
+ (`"ac" "Group 3")))))
+ (category . unicode-name))
+ (complete-with-action action '("aa" "ab" "ac") string pred)))
+ (insert "a")
+ (minibuffer-completion-help)
+ (switch-to-completions)
+ (should (equal "aa" (get-text-property (point) 'completion--string)))
+ (let ((completion-auto-wrap t))
+ (next-completion 3))
+ (should (equal "aa" (get-text-property (point) 'completion--string)))
+ (let ((completion-auto-wrap nil))
+ (next-completion 3))
+ (should (equal "ac" (get-text-property (point) 'completion--string)))
+
+ (first-completion)
+ (let ((completion-auto-wrap t))
+ (next-line-completion 1)
+ (should (equal "ab" (get-text-property (point) 'completion--string)))
+ (next-line-completion 2)
+ (should (equal "aa" (get-text-property (point) 'completion--string)))
+ (previous-line-completion 2)
+ (should (equal "ab" (get-text-property (point) 'completion--string))))
+ (let ((completion-auto-wrap nil))
+ (next-line-completion 3)
+ (should (equal "ac" (get-text-property (point) 'completion--string)))
+ (previous-line-completion 3)
+ (should (equal "aa" (get-text-property (point) 'completion--string))))))
+
(provide 'minibuffer-tests)
;;; minibuffer-tests.el ends here
diff --git a/test/lisp/misc-tests.el b/test/lisp/misc-tests.el
index b9bafe4bd11..c118aba50a1 100644
--- a/test/lisp/misc-tests.el
+++ b/test/lisp/misc-tests.el
@@ -1,6 +1,6 @@
;;; misc-tests.el --- Tests for misc.el -*- lexical-binding:t -*-
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
;; Author: Stefan Kangas <stefankangas@gmail.com>
diff --git a/test/lisp/mouse-tests.el b/test/lisp/mouse-tests.el
index 2af6cac6325..00ecdd79574 100644
--- a/test/lisp/mouse-tests.el
+++ b/test/lisp/mouse-tests.el
@@ -1,6 +1,6 @@
;;; mouse-tests.el --- unit tests for mouse.el -*- lexical-binding: t; -*-
-;; Copyright (C) 2016-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2016-2024 Free Software Foundation, Inc.
;; Author: Philipp Stephani <phst@google.com>
diff --git a/test/lisp/mwheel-tests.el b/test/lisp/mwheel-tests.el
index 3255b5de200..2b0f0ff384a 100644
--- a/test/lisp/mwheel-tests.el
+++ b/test/lisp/mwheel-tests.el
@@ -1,6 +1,6 @@
;;; mwheel-tests.el --- tests for mwheel.el -*- lexical-binding:t -*-
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/net/browse-url-tests.el b/test/lisp/net/browse-url-tests.el
index 0fe2fa788b9..168aa1c43e0 100644
--- a/test/lisp/net/browse-url-tests.el
+++ b/test/lisp/net/browse-url-tests.el
@@ -1,6 +1,6 @@
;;; browse-url-tests.el --- Tests for browse-url.el -*- lexical-binding: t; -*-
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
;; Author: Simen Heggestøyl <simenheg@gmail.com>
;; Keywords:
diff --git a/test/lisp/net/dbus-tests.el b/test/lisp/net/dbus-tests.el
index 418ae61bb42..fec252e12dd 100644
--- a/test/lisp/net/dbus-tests.el
+++ b/test/lisp/net/dbus-tests.el
@@ -1,6 +1,6 @@
;;; dbus-tests.el --- Tests of D-Bus integration into Emacs -*- lexical-binding:t -*-
-;; Copyright (C) 2013-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2024 Free Software Foundation, Inc.
;; Author: Michael Albinus <michael.albinus@gmx.de>
@@ -465,6 +465,9 @@
(should (eq (dbus-unregister-service bus dbus--test-service) :non-existent))
(should-not (member dbus--test-service (dbus-list-known-names bus)))
+ ;; Unregistering a unique name returns nil.
+ (should-not (dbus-unregister-service bus ":1.1"))
+
;; A service name is a string, constructed of at least two words
;; separated by ".".
(should
diff --git a/test/lisp/net/dig-tests.el b/test/lisp/net/dig-tests.el
index b264fd40ae1..a78c335488d 100644
--- a/test/lisp/net/dig-tests.el
+++ b/test/lisp/net/dig-tests.el
@@ -1,6 +1,6 @@
;;; dig-tests.el --- Tests for dig.el -*- lexical-binding:t -*-
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/net/eudc-tests.el b/test/lisp/net/eudc-tests.el
index 431d7c46231..1129e452cea 100644
--- a/test/lisp/net/eudc-tests.el
+++ b/test/lisp/net/eudc-tests.el
@@ -1,6 +1,6 @@
;;; eudc-tests.el --- tests for eudc.el -*- lexical-binding: t -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/net/gnutls-tests.el b/test/lisp/net/gnutls-tests.el
index cb911577385..9fdf33db075 100644
--- a/test/lisp/net/gnutls-tests.el
+++ b/test/lisp/net/gnutls-tests.el
@@ -1,6 +1,6 @@
;;; gnutls-tests.el --- Test suite for gnutls.el -*- lexical-binding:t -*-
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
;; Author: Ted Zlatanov <tzz@lifelogs.com>
diff --git a/test/lisp/net/hmac-md5-tests.el b/test/lisp/net/hmac-md5-tests.el
index 0caa6c46952..9481f618ad2 100644
--- a/test/lisp/net/hmac-md5-tests.el
+++ b/test/lisp/net/hmac-md5-tests.el
@@ -1,6 +1,6 @@
;;; hmac-md5-tests.el --- Tests for hmac-md5.el -*- lexical-binding:t -*-
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/net/mailcap-tests.el b/test/lisp/net/mailcap-tests.el
index e47ead98f42..5c03e73d371 100644
--- a/test/lisp/net/mailcap-tests.el
+++ b/test/lisp/net/mailcap-tests.el
@@ -1,6 +1,6 @@
;;; mailcap-tests.el --- tests for mailcap.el -*- lexical-binding: t -*-
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
;; Author: Mark Oteiza <mvoteiza@udel.edu>
@@ -537,5 +537,29 @@ help to verify the correct addition and merging of an entry."
("minor" . ((viewer . "viewer")
(edit . "edit")))))))))
+
+
+(ert-deftest mailcap-viewer-passes-test-w/o-test-returns-t ()
+ "A VIEWER-INFO without a test should return t with a valid viewer (Bug#65224)."
+
+ (should (equal t
+ (let ((mailcap-viewer-test-cache)
+ (viewer-info
+ (list (cons 'viewer "viewer-w/o-test"))))
+ (mailcap-viewer-passes-test viewer-info nil))))
+
+ (should (equal '(t t nil t)
+ (let ((mailcap-viewer-test-cache)
+ (viewer-infos
+ (list
+ (list (cons 'viewer "viewer-w/o-test"))
+ (list (cons 'viewer "viewer-w/o-test"))
+ (list (cons 'viewer "viewer-w/nil-test")
+ (cons 'test nil))
+ (list (cons 'viewer "viewer-w/o-test"))
+ )))
+ (mapcar (lambda (vi)
+ (mailcap-viewer-passes-test vi nil))
+ viewer-infos)))))
;;; mailcap-tests.el ends here
diff --git a/test/lisp/net/network-stream-tests.el b/test/lisp/net/network-stream-tests.el
index 0fd9549c305..4e600573e7a 100644
--- a/test/lisp/net/network-stream-tests.el
+++ b/test/lisp/net/network-stream-tests.el
@@ -1,6 +1,6 @@
;;; network-stream-tests.el --- tests for network processes -*- lexical-binding: t; -*-
-;; Copyright (C) 2016-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2016-2024 Free Software Foundation, Inc.
;; Author: Lars Ingebrigtsen <larsi@gnus.org>
@@ -236,7 +236,7 @@
(while (and (eq (process-status proc) 'connect)
(< (setq times (1+ times)) 10))
(sit-for 0.1))
- (skip-unless (not (eq (process-status proc) 'connect)))
+ (skip-when (eq (process-status proc) 'connect))
(with-current-buffer (process-buffer proc)
(process-send-string proc "echo foo")
(sleep-for 0.1)
@@ -323,7 +323,7 @@
(while (and (eq (process-status proc) 'connect)
(< (setq times (1+ times)) 10))
(sit-for 0.1))
- (skip-unless (not (eq (process-status proc) 'connect))))
+ (skip-when (eq (process-status proc) 'connect)))
(if (process-live-p server) (delete-process server)))
(setq status (gnutls-peer-status proc))
(should (consp status))
@@ -336,7 +336,7 @@
(ert-deftest connect-to-tls-ipv6-nowait ()
(skip-unless (executable-find "gnutls-serv"))
(skip-unless (gnutls-available-p))
- (skip-unless (not (eq system-type 'windows-nt)))
+ (skip-when (eq system-type 'windows-nt))
(skip-unless (featurep 'make-network-process '(:family ipv6)))
(let ((server (make-tls-server 44333))
(times 0)
@@ -368,7 +368,7 @@
(while (and (eq (process-status proc) 'connect)
(< (setq times (1+ times)) 10))
(sit-for 0.1))
- (skip-unless (not (eq (process-status proc) 'connect))))
+ (skip-when (eq (process-status proc) 'connect)))
(if (process-live-p server) (delete-process server)))
(setq status (gnutls-peer-status proc))
(should (consp status))
@@ -403,7 +403,7 @@
(< (setq times (1+ times)) 10))
(sit-for 0.1))
(should proc)
- (skip-unless (not (eq (process-status proc) 'connect))))
+ (skip-when (eq (process-status proc) 'connect)))
(if (process-live-p server) (delete-process server)))
(setq status (gnutls-peer-status proc))
(should (consp status))
@@ -446,7 +446,7 @@
(while (and (eq (process-status proc) 'connect)
(< (setq times (1+ times)) 10))
(sit-for 0.1))
- (skip-unless (not (eq (process-status proc) 'connect))))
+ (skip-when (eq (process-status proc) 'connect)))
(if (process-live-p server) (delete-process server)))
(setq status (gnutls-peer-status proc))
(should (consp status))
@@ -484,7 +484,7 @@
(< (setq times (1+ times)) 10))
(sit-for 0.1))
(should proc)
- (skip-unless (not (eq (process-status proc) 'connect))))
+ (skip-when (eq (process-status proc) 'connect)))
(if (process-live-p server) (delete-process server)))
(setq status (gnutls-peer-status proc))
(should (consp status))
@@ -523,7 +523,7 @@
(< (setq times (1+ times)) 10))
(sit-for 0.1))
(should proc)
- (skip-unless (not (eq (process-status proc) 'connect))))
+ (skip-when (eq (process-status proc) 'connect)))
(if (process-live-p server) (delete-process server)))
(setq status (gnutls-peer-status proc))
(should (consp status))
@@ -673,7 +673,7 @@
(while (and (eq (process-status proc) 'connect)
(< (setq times (1+ times)) 10))
(sit-for 0.1))
- (skip-unless (not (eq (process-status proc) 'connect))))
+ (skip-when (eq (process-status proc) 'connect)))
(if (process-live-p server) (delete-process server)))
(setq status (gnutls-peer-status proc))
(should (consp status))
@@ -712,7 +712,7 @@
(while (and (eq (process-status proc) 'connect)
(< (setq times (1+ times)) 10))
(sit-for 0.1))
- (skip-unless (not (eq (process-status proc) 'connect))))
+ (skip-when (eq (process-status proc) 'connect)))
(if (process-live-p server) (delete-process server)))
(setq status (gnutls-peer-status proc))
(should (consp status))
diff --git a/test/lisp/net/newsticker-tests.el b/test/lisp/net/newsticker-tests.el
index 3ed4b7b1dd5..7daa9f83a6d 100644
--- a/test/lisp/net/newsticker-tests.el
+++ b/test/lisp/net/newsticker-tests.el
@@ -1,6 +1,6 @@
;;; newsticker-tests.el --- Test suite for newsticker. -*- lexical-binding:t -*-
-;; Copyright (C) 2003-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003-2024 Free Software Foundation, Inc.
;; Author: Ulf Jasper <ulf.jasper@web.de>
;; Keywords: News, RSS, Atom
diff --git a/test/lisp/net/nsm-tests.el b/test/lisp/net/nsm-tests.el
index 391015dae9a..ba4ec2d5717 100644
--- a/test/lisp/net/nsm-tests.el
+++ b/test/lisp/net/nsm-tests.el
@@ -1,6 +1,6 @@
;;; nsm-tests.el --- tests for network security manager -*- lexical-binding: t; -*-
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
;; Author: Robert Pluim <rpluim@gmail.com>
diff --git a/test/lisp/net/ntlm-tests.el b/test/lisp/net/ntlm-tests.el
index 625c5e902bb..0f4d1d02b5e 100644
--- a/test/lisp/net/ntlm-tests.el
+++ b/test/lisp/net/ntlm-tests.el
@@ -1,6 +1,6 @@
;;; ntlm-tests.el --- tests for ntlm.el -*- lexical-binding: t -*-
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/net/puny-tests.el b/test/lisp/net/puny-tests.el
index 48d03791853..57f4380e758 100644
--- a/test/lisp/net/puny-tests.el
+++ b/test/lisp/net/puny-tests.el
@@ -1,6 +1,6 @@
;;; puny-tests.el --- tests for net/puny.el -*- coding: utf-8; lexical-binding:t -*-
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/net/rcirc-tests.el b/test/lisp/net/rcirc-tests.el
index 0a49951b410..2912462c796 100644
--- a/test/lisp/net/rcirc-tests.el
+++ b/test/lisp/net/rcirc-tests.el
@@ -1,6 +1,6 @@
;;; rcirc-tests.el --- Tests for rcirc -*- lexical-binding:t -*-
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
;;
diff --git a/test/lisp/net/rfc2104-tests.el b/test/lisp/net/rfc2104-tests.el
index 713a08d6dde..be5da619eaa 100644
--- a/test/lisp/net/rfc2104-tests.el
+++ b/test/lisp/net/rfc2104-tests.el
@@ -1,6 +1,6 @@
;;; rfc2104-tests.el --- Tests of RFC2104 hashes -*- lexical-binding:t -*-
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
;; Author: Lars Ingebrigtsen <larsi@gnus.org>
diff --git a/test/lisp/net/sasl-cram-tests.el b/test/lisp/net/sasl-cram-tests.el
index be703685fc3..3955fc6ca8c 100644
--- a/test/lisp/net/sasl-cram-tests.el
+++ b/test/lisp/net/sasl-cram-tests.el
@@ -1,6 +1,6 @@
;;; sasl-cram-tests.el --- tests for sasl-cram.el -*- lexical-binding: t; -*-
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
;; Author: Stefan Kangas <stefankangas@gmail.com>
diff --git a/test/lisp/net/sasl-scram-rfc-tests.el b/test/lisp/net/sasl-scram-rfc-tests.el
index 8b624f9123f..6866493759f 100644
--- a/test/lisp/net/sasl-scram-rfc-tests.el
+++ b/test/lisp/net/sasl-scram-rfc-tests.el
@@ -1,6 +1,6 @@
;;; sasl-scram-rfc-tests.el --- tests for SCRAM -*- lexical-binding: t; -*-
-;; Copyright (C) 2014-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2014-2024 Free Software Foundation, Inc.
;; Author: Magnus Henoch <magnus.henoch@gmail.com>
diff --git a/test/lisp/net/sasl-tests.el b/test/lisp/net/sasl-tests.el
index 2abbfd559f0..3aa0f15e94f 100644
--- a/test/lisp/net/sasl-tests.el
+++ b/test/lisp/net/sasl-tests.el
@@ -1,6 +1,6 @@
;;; sasl-tests.el --- tests for sasl.el -*- lexical-binding: t; -*-
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
;; Author: Stefan Kangas <stefankangas@gmail.com>
diff --git a/test/lisp/net/secrets-tests.el b/test/lisp/net/secrets-tests.el
index 6307390aad5..9feba514413 100644
--- a/test/lisp/net/secrets-tests.el
+++ b/test/lisp/net/secrets-tests.el
@@ -1,6 +1,6 @@
;;; secrets-tests.el --- Tests of Secret Service API -*- lexical-binding: t -*-
-;; Copyright (C) 2018-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2018-2024 Free Software Foundation, Inc.
;; Author: Michael Albinus <michael.albinus@gmx.de>
diff --git a/test/lisp/net/shr-tests.el b/test/lisp/net/shr-tests.el
index 64ed070f851..0c6e2c091bf 100644
--- a/test/lisp/net/shr-tests.el
+++ b/test/lisp/net/shr-tests.el
@@ -1,6 +1,6 @@
;;; shr-tests.el --- tests for shr.el -*- lexical-binding: t; -*-
-;; Copyright (C) 2016-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2016-2024 Free Software Foundation, Inc.
;; Author: Lars Ingebrigtsen <larsi@gnus.org>
diff --git a/test/lisp/net/socks-tests.el b/test/lisp/net/socks-tests.el
index 958e2ff44a8..b9515876d6c 100644
--- a/test/lisp/net/socks-tests.el
+++ b/test/lisp/net/socks-tests.el
@@ -1,6 +1,6 @@
;;; socks-tests.el --- tests for SOCKS -*- coding: utf-8; lexical-binding: t; -*-
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -63,21 +63,21 @@
(process-put proc 'socks-state socks-state-waiting)
(process-put proc 'socks-server-protocol 4)
(ert-info ("Receive initial incomplete segment")
- (socks-filter proc (concat [0 90 0 0 93 184 216]))
- ;; From example.com: OK status ^ ^ msg start
+ (socks-filter proc (unibyte-string 0 90 0 0 93 184 216))
+ ;; From example.com: OK status ^ ^ msg start
(ert-info ("State still set to waiting")
(should (eq (process-get proc 'socks-state) socks-state-waiting)))
(ert-info ("Response field is nil because processing incomplete")
(should-not (process-get proc 'socks-response)))
(ert-info ("Scratch field holds stashed partial payload")
- (should (string= (concat [0 90 0 0 93 184 216])
+ (should (string= (unibyte-string 0 90 0 0 93 184 216)
(process-get proc 'socks-scratch)))))
(ert-info ("Last part arrives")
(socks-filter proc "\42") ; ?\" 34
(ert-info ("State transitions to complete (length check passes)")
(should (eq (process-get proc 'socks-state) socks-state-connected)))
(ert-info ("Scratch and response fields hold stash w. last chunk")
- (should (string= (concat [0 90 0 0 93 184 216 34])
+ (should (string= (unibyte-string 0 90 0 0 93 184 216 34)
(process-get proc 'socks-response)))
(should (string= (process-get proc 'socks-response)
(process-get proc 'socks-scratch)))))
@@ -133,17 +133,19 @@ Vectors must match verbatim. Strings are considered regex patterns.")
(defun socks-tests-canned-server-create ()
"Create and return a fake SOCKS server."
(let* ((port (nth 2 socks-server))
- (name (format "socks-server:%d" port))
+ (name (format "socks-server:%s"
+ (if (numberp port) port (ert-test-name (ert-running-test)))))
(pats socks-tests-canned-server-patterns)
(filt (lambda (proc line)
(pcase-let ((`(,pat . ,resp) (pop pats)))
(unless (or (and (vectorp pat) (equal pat (vconcat line)))
- (string-match-p pat line))
+ (and (stringp pat) (string-match-p pat line)))
(error "Unknown request: %s" line))
+ (setq resp (apply #'unibyte-string (append resp nil)))
(let ((print-escape-control-characters t))
(message "[%s] <- %s" name (prin1-to-string line))
(message "[%s] -> %s" name (prin1-to-string resp)))
- (process-send-string proc (concat resp)))))
+ (process-send-string proc resp))))
(serv (make-network-process :server 1
:buffer (get-buffer-create name)
:filter filt
@@ -151,8 +153,10 @@ Vectors must match verbatim. Strings are considered regex patterns.")
:family 'ipv4
:host 'local
:coding 'binary
- :service port)))
+ :service (or port t))))
(set-process-query-on-exit-flag serv nil)
+ (unless (numberp (nth 2 socks-server))
+ (setf (nth 2 socks-server) (process-contact serv :service)))
serv))
(defvar socks-tests--hello-world-http-request-pattern
@@ -161,9 +165,9 @@ Vectors must match verbatim. Strings are considered regex patterns.")
"Content-Length: 13\r\n\r\n"
"Hello World!\n")))
-(defun socks-tests-perform-hello-world-http-request ()
+(defun socks-tests-perform-hello-world-http-request (&optional method)
"Start canned server, validate hello-world response, and finalize."
- (let* ((url-gateway-method 'socks)
+ (let* ((url-gateway-method (or method 'socks))
(url (url-generic-parse-url "http://example.com"))
(server (socks-tests-canned-server-create))
;;
@@ -191,8 +195,9 @@ Vectors must match verbatim. Strings are considered regex patterns.")
(ert-deftest socks-tests-v4-basic ()
"Show correct preparation of SOCKS4 connect command (Bug#46342)."
- (let ((socks-server '("server" "127.0.0.1" 10079 4))
+ (let ((socks-server '("server" "127.0.0.1" t 4))
(url-user-agent "Test/4-basic")
+ (socks-username "foo")
(socks-tests-canned-server-patterns
`(([4 1 0 80 93 184 216 34 ?f ?o ?o 0] . [0 90 0 0 0 0 0 0])
,socks-tests--hello-world-http-request-pattern))
@@ -201,11 +206,35 @@ Vectors must match verbatim. Strings are considered regex patterns.")
(cl-letf (((symbol-function 'socks-nslookup-host)
(lambda (host)
(should (equal host "example.com"))
- (list 93 184 216 34)))
- ((symbol-function 'user-full-name)
- (lambda (&optional _) "foo")))
+ (list 93 184 216 34))))
(socks-tests-perform-hello-world-http-request)))))
+(ert-deftest socks-tests-v4a-basic ()
+ "Show correct preparation of SOCKS4a connect command."
+ (let ((socks-server '("server" "127.0.0.1" t 4a))
+ (socks-username "foo")
+ (url-user-agent "Test/4a-basic")
+ (socks-tests-canned-server-patterns
+ `(([4 1 0 80 0 0 0 1 ?f ?o ?o 0 ?e ?x ?a ?m ?p ?l ?e ?. ?c ?o ?m 0]
+ . [0 90 0 0 0 0 0 0])
+ ,socks-tests--hello-world-http-request-pattern)))
+ (ert-info ("Make HTTP request over SOCKS4A")
+ (socks-tests-perform-hello-world-http-request))))
+
+(ert-deftest socks-tests-v4a-error ()
+ "Show error signaled when destination address rejected."
+ (let ((socks-server '("server" "127.0.0.1" t 4a))
+ (url-user-agent "Test/4a-basic")
+ (socks-username "")
+ (socks-tests-canned-server-patterns
+ `(([4 1 0 80 0 0 0 1 0 ?e ?x ?a ?m ?p ?l ?e ?. ?c ?o ?m 0]
+ . [0 91 0 0 0 0 0 0])
+ ,socks-tests--hello-world-http-request-pattern)))
+ (ert-info ("Make HTTP request over SOCKS4A")
+ (let ((err (should-error
+ (socks-tests-perform-hello-world-http-request))))
+ (should (equal err '(error "SOCKS: Rejected or failed")))))))
+
;; Replace first pattern below with ([5 3 0 1 2] . [5 2]) to validate
;; against curl 7.71 with the following options:
;; $ curl --verbose -U foo:bar --proxy socks5h://127.0.0.1:10080 example.com
@@ -213,7 +242,7 @@ Vectors must match verbatim. Strings are considered regex patterns.")
(ert-deftest socks-tests-v5-auth-user-pass ()
"Verify correct handling of SOCKS5 user/pass authentication."
(should (assq 2 socks-authentication-methods))
- (let ((socks-server '("server" "127.0.0.1" 10080 5))
+ (let ((socks-server '("server" "127.0.0.1" t 5))
(socks-username "foo")
(socks-password "bar")
(url-user-agent "Test/auth-user-pass")
@@ -247,7 +276,7 @@ Vectors must match verbatim. Strings are considered regex patterns.")
(ert-deftest socks-tests-v5-auth-user-pass-blank ()
"Verify correct SOCKS5 user/pass authentication with empty pass."
(should (assq 2 socks-authentication-methods))
- (let ((socks-server '("server" "127.0.0.1" 10081 5))
+ (let ((socks-server '("server" "127.0.0.1" t 5))
(socks-username "foo") ; defaults to (user-login-name)
(socks-password "") ; simulate user hitting enter when prompted
(url-user-agent "Test/auth-user-pass-blank")
@@ -264,9 +293,9 @@ Vectors must match verbatim. Strings are considered regex patterns.")
;; against curl 7.71 with the following options:
;; $ curl --verbose --proxy socks5h://127.0.0.1:10082 example.com
-(ert-deftest socks-tests-v5-auth-none ()
+(defun socks-tests-v5-auth-none (method)
"Verify correct handling of SOCKS5 when auth method 0 requested."
- (let ((socks-server '("server" "127.0.0.1" 10082 5))
+ (let ((socks-server '("server" "127.0.0.1" t 5))
(socks-authentication-methods (append socks-authentication-methods
nil))
(url-user-agent "Test/auth-none")
@@ -278,7 +307,24 @@ Vectors must match verbatim. Strings are considered regex patterns.")
(socks-unregister-authentication-method 2)
(should-not (assq 2 socks-authentication-methods))
(ert-info ("Make HTTP request over SOCKS5 with no auth method")
- (socks-tests-perform-hello-world-http-request)))
+ (socks-tests-perform-hello-world-http-request method)))
(should (assq 2 socks-authentication-methods)))
+(ert-deftest socks-tests-v5-auth-none ()
+ (socks-tests-v5-auth-none 'socks))
+
+;; This simulates the top-level advice around `open-network-stream'
+;; that's applied when loading the library with a non-nil
+;; `socks-override-functions'.
+(ert-deftest socks-override-functions ()
+ (should-not socks-override-functions)
+ (should-not (advice-member-p #'socks--open-network-stream
+ 'open-network-stream))
+ (advice-add 'open-network-stream :around #'socks--open-network-stream)
+ (unwind-protect (let ((socks-override-functions t))
+ (socks-tests-v5-auth-none 'native))
+ (advice-remove 'open-network-stream #'socks--open-network-stream))
+ (should-not (advice-member-p #'socks--open-network-stream
+ 'open-network-stream)))
+
;;; socks-tests.el ends here
diff --git a/test/lisp/net/tramp-archive-tests.el b/test/lisp/net/tramp-archive-tests.el
index 9500ce0efca..978342b1bb1 100644
--- a/test/lisp/net/tramp-archive-tests.el
+++ b/test/lisp/net/tramp-archive-tests.el
@@ -1,6 +1,6 @@
;;; tramp-archive-tests.el --- Tests of file archive access -*- lexical-binding:t -*-
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
;; Author: Michael Albinus <michael.albinus@gmx.de>
diff --git a/test/lisp/net/tramp-tests.el b/test/lisp/net/tramp-tests.el
index 50687dfe993..3216a8be1b0 100644
--- a/test/lisp/net/tramp-tests.el
+++ b/test/lisp/net/tramp-tests.el
@@ -1,6 +1,6 @@
;;; tramp-tests.el --- Tests of remote file access -*- lexical-binding:t -*-
-;; Copyright (C) 2013-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2024 Free Software Foundation, Inc.
;; Author: Michael Albinus <michael.albinus@gmx.de>
@@ -2325,6 +2325,17 @@ is greater than 10.
(should (string-equal (expand-file-name local dir) dir))
(should (string-equal (expand-file-name (concat dir local)) dir)))))
+;; The following test is inspired by Bug#65685.
+(ert-deftest tramp-test05-expand-file-name-tilde ()
+ "Check `expand-file-name'."
+ (skip-unless (tramp--test-enabled))
+ (skip-unless (not (tramp--test-ange-ftp-p)))
+
+ (let ((dir (file-remote-p ert-remote-temporary-file-directory))
+ (tramp-tolerate-tilde t))
+ (should (string-equal (expand-file-name (concat dir "~"))
+ (expand-file-name (concat dir "/:~"))))))
+
(ert-deftest tramp-test06-directory-file-name ()
"Check `directory-file-name'.
This checks also `file-name-as-directory', `file-name-directory',
@@ -3441,12 +3452,12 @@ This tests also `file-directory-p' and `file-accessible-directory-p'."
(rx-to-string
`(:
;; There might be a summary line.
- (? "total" (+ nonl) (+ digit) (? blank)
+ (? (* blank) "total" (+ nonl) (+ digit) (? blank)
(? (any "EGKMPTYZk")) (? "i") (? "B") "\n")
;; We don't know in which order ".", ".." and "foo" appear.
(= ,(length (directory-files tmp-name1))
(+ nonl) blank
- (regexp ,(regexp-opt (directory-files tmp-name1)))
+ (| . ,(directory-files tmp-name1))
(? " ->" (+ nonl)) "\n"))))))
;; Check error cases.
@@ -3800,7 +3811,7 @@ This tests also `access-file', `file-readable-p',
(should (eq (file-attribute-type attr) t)))
;; Cleanup.
- (ignore-errors (delete-directory tmp-name1))
+ (ignore-errors (delete-directory tmp-name1 'recursive))
(ignore-errors (delete-file tmp-name1))
(ignore-errors (delete-file tmp-name2))))))
@@ -4870,6 +4881,7 @@ This tests also `make-symbolic-link', `file-truename' and `add-name-to-file'."
(if (tramp--test-expensive-test-p)
;; It doesn't work for `initials' and `shorthand'
;; completion styles. Should it?
+ ;; `orderless' passes the tests, but it is an ELPA package.
'(emacs21 emacs22 basic partial-completion substring flex)
'(basic)))
@@ -5182,10 +5194,11 @@ This tests also `make-symbolic-link', `file-truename' and `add-name-to-file'."
(defun tramp--test-timeout-handler (&rest _ignore)
"Timeout handler, reporting a failed test."
(interactive)
- (let ((proc (get-buffer-process (current-buffer))))
- (when (processp proc)
- (tramp--test-message
- "cmd: %s\nbuf:\n%s\n---" (process-command proc) (buffer-string))))
+ (tramp--test-message "proc: %s" (get-buffer-process (current-buffer)))
+ (when-let ((proc (get-buffer-process (current-buffer)))
+ ((processp proc)))
+ (tramp--test-message "cmd: %s" (process-command proc)))
+ (tramp--test-message "buf: %s\n%s\n---" (current-buffer) (buffer-string))
(ert-fail (format "`%s' timed out" (ert-test-name (ert-running-test)))))
(ert-deftest tramp-test29-start-file-process ()
@@ -5671,55 +5684,69 @@ If UNSTABLE is non-nil, the test is tagged as `:unstable'."
(delete-exited-processes t)
kill-buffer-query-functions command proc)
- (dolist (sigcode '(2 INT))
- (unwind-protect
- (with-temp-buffer
- (setq command "trap 'echo boom; exit 1' 2; sleep 100"
- proc (start-file-process-shell-command
- (format "test1%s" sigcode) (current-buffer) command))
- (should (processp proc))
- (should (process-live-p proc))
- (should (equal (process-status proc) 'run))
- (should (numberp (process-get proc 'remote-pid)))
- (should (equal (process-get proc 'remote-command)
- (with-connection-local-variables
- `(,shell-file-name ,shell-command-switch ,command))))
- (should (zerop (signal-process proc sigcode)))
- ;; Let the process accept the signal.
- (with-timeout (10 (tramp--test-timeout-handler))
- (while (accept-process-output proc 0 nil t)))
- (should-not (process-live-p proc)))
+ ;; If PROCESS is a string, it must be a process name or a process
+ ;; number. Check error handling.
+ (should-error
+ (signal-process (md5 (current-time-string)) 0)
+ :type 'wrong-type-argument)
+
+ ;; The PROCESS argument of `signal-process' can be a string. Test
+ ;; this as well.
+ (dolist
+ (func '(identity
+ (lambda (x) (format "%s" (if (processp x) (process-name x) x)))))
+ (dolist (sigcode '(2 INT))
+ (unwind-protect
+ (with-temp-buffer
+ (setq command "trap 'echo boom; exit 1' 2; sleep 100"
+ proc (start-file-process-shell-command
+ (format "test1-%s" sigcode) (current-buffer) command))
+ (should (processp proc))
+ (should (process-live-p proc))
+ (should (equal (process-status proc) 'run))
+ (should (numberp (process-get proc 'remote-pid)))
+ (should
+ (equal (process-get proc 'remote-command)
+ (with-connection-local-variables
+ `(,shell-file-name ,shell-command-switch ,command))))
+ (should (zerop (signal-process (funcall func proc) sigcode)))
+ ;; Let the process accept the signal.
+ (with-timeout (10 (tramp--test-timeout-handler))
+ (while (accept-process-output proc 0 nil t)))
+ (should-not (process-live-p proc)))
- ;; Cleanup.
- (ignore-errors (kill-process proc))
- (ignore-errors (delete-process proc)))
+ ;; Cleanup.
+ (ignore-errors (kill-process proc))
+ (ignore-errors (delete-process proc)))
- (unwind-protect
- (with-temp-buffer
- (setq command "trap 'echo boom; exit 1' 2; sleep 100"
- proc (start-file-process-shell-command
- (format "test2%s" sigcode) (current-buffer) command))
- (should (processp proc))
- (should (process-live-p proc))
- (should (equal (process-status proc) 'run))
- (should (numberp (process-get proc 'remote-pid)))
- (should (equal (process-get proc 'remote-command)
- (with-connection-local-variables
- `(,shell-file-name ,shell-command-switch ,command))))
- ;; `signal-process' has argument REMOTE since Emacs 29.
- (with-no-warnings
+ (unwind-protect
+ (with-temp-buffer
+ (setq command "trap 'echo boom; exit 1' 2; sleep 100"
+ proc (start-file-process-shell-command
+ (format "test2-%s" sigcode) (current-buffer) command))
+ (should (processp proc))
+ (should (process-live-p proc))
+ (should (equal (process-status proc) 'run))
+ (should (numberp (process-get proc 'remote-pid)))
(should
- (zerop
- (signal-process
- (process-get proc 'remote-pid) sigcode default-directory))))
- ;; Let the process accept the signal.
- (with-timeout (10 (tramp--test-timeout-handler))
- (while (accept-process-output proc 0 nil t)))
- (should-not (process-live-p proc)))
+ (equal (process-get proc 'remote-command)
+ (with-connection-local-variables
+ `(,shell-file-name ,shell-command-switch ,command))))
+ ;; `signal-process' has argument REMOTE since Emacs 29.
+ (with-no-warnings
+ (should
+ (zerop
+ (signal-process
+ (funcall func (process-get proc 'remote-pid))
+ sigcode default-directory))))
+ ;; Let the process accept the signal.
+ (with-timeout (10 (tramp--test-timeout-handler))
+ (while (accept-process-output proc 0 nil t)))
+ (should-not (process-live-p proc)))
- ;; Cleanup.
- (ignore-errors (kill-process proc))
- (ignore-errors (delete-process proc))))))
+ ;; Cleanup.
+ (ignore-errors (kill-process proc))
+ (ignore-errors (delete-process proc)))))))
(ert-deftest tramp-test31-list-system-processes ()
"Check `list-system-processes'."
@@ -6320,6 +6347,8 @@ INPUT, if non-nil, is a string sent to the process."
;; Cleanup.
(ignore-errors (delete-file tmp-name)))))
+(tramp--test-deftest-direct-async-process tramp-test35-exec-path)
+
;; This test is inspired by Bug#33781.
(ert-deftest tramp-test35-remote-path ()
"Check loooong `tramp-remote-path'."
@@ -6333,6 +6362,8 @@ INPUT, if non-nil, is a string sent to the process."
(tramp-remote-path tramp-remote-path)
(orig-tramp-remote-path tramp-remote-path)
path)
+ ;; The "flatpak" method modifies `tramp-remote-path'.
+ (skip-unless (not (tramp-compat-connection-local-p tramp-remote-path)))
(unwind-protect
(progn
;; Non existing directories are removed.
@@ -6382,6 +6413,8 @@ INPUT, if non-nil, is a string sent to the process."
(setq tramp-remote-path orig-tramp-remote-path)
(ignore-errors (delete-directory tmp-name 'recursive)))))
+(tramp--test-deftest-direct-async-process tramp-test35-remote-path)
+
(ert-deftest tramp-test36-vc-registered ()
"Check `vc-registered'."
:tags '(:expensive-test)
@@ -7020,7 +7053,7 @@ This is used in tests which we don't want to tag
(ert--stats-selector ert--current-run-stats)
(list (make-ert-test :name (ert-test-name (ert-running-test))
:body nil :tags '(:tramp-asynchronous-processes))))
- ;; tramp-adb.el cannot apply multi-byte commands.
+ ;; tramp-adb.el cannot apply multibyte commands.
(not (and (tramp--test-adb-p)
(string-match-p (rx multibyte) default-directory)))))
@@ -7096,6 +7129,12 @@ This does not support external Emacs calls."
(string-equal
"mock" (file-remote-p ert-remote-temporary-file-directory 'method)))
+(defun tramp--test-netbsd-p ()
+ "Check, whether the remote host runs NetBSD."
+ ;; We must refill the cache. `file-truename' does it.
+ (file-truename ert-remote-temporary-file-directory)
+ (ignore-errors (tramp-check-remote-uname tramp-test-vec "NetBSD")))
+
(defun tramp--test-openbsd-p ()
"Check, whether the remote host runs OpenBSD."
;; We must refill the cache. `file-truename' does it.
@@ -7333,9 +7372,11 @@ This requires restrictions of file name syntax."
;; Check symlink in `directory-files-and-attributes'.
;; It does not work in the "smb" case, only relative
- ;; symlinks to existing files are shown there.
+ ;; symlinks to existing files are shown there. On
+ ;; NetBSD, there are problems with loooong file names,
+ ;; see Bug#65324.
(tramp--test-ignore-make-symbolic-link-error
- (unless (tramp--test-smb-p)
+ (unless (or (tramp--test-netbsd-p) (tramp--test-smb-p))
(make-symbolic-link file2 file3)
(should (file-symlink-p file3))
(should
@@ -7391,13 +7432,13 @@ This requires restrictions of file name syntax."
;; of process output. So we unset it temporarily.
(setenv "PS1")
(with-temp-buffer
- (should (zerop (process-file "printenv" nil t nil)))
- (goto-char (point-min))
- (should
- (search-forward-regexp
- (rx
- bol (literal envvar)
- "=" (literal (getenv envvar)) eol))))))))
+ (when (zerop (process-file "printenv" nil t nil))
+ (goto-char (point-min))
+ (should
+ (search-forward-regexp
+ (rx
+ bol (literal envvar)
+ "=" (literal (getenv envvar)) eol)))))))))
;; Cleanup.
(ignore-errors (kill-buffer buffer))
@@ -7868,7 +7909,7 @@ process sentinels. They shall not disturb each other."
(ert-deftest tramp-test47-read-password ()
"Check Tramp password handling."
- :tags '(:expensive-test :unstable)
+ :tags '(:expensive-test)
(skip-unless (tramp--test-enabled))
(skip-unless (tramp--test-mock-p))
;; Not all read commands understand argument "-s" or "-p".
@@ -7878,7 +7919,7 @@ process sentinels. They shall not disturb each other."
(shell-command-to-string "read -s -p Password: pass"))))
(let ((pass "secret")
- (mock-entry (copy-sequence (assoc "mock" tramp-methods)))
+ (mock-entry (copy-tree (assoc "mock" tramp-methods)))
mocked-input tramp-methods)
;; We must mock `read-string', in order to avoid interactive
;; arguments.
@@ -7925,6 +7966,65 @@ process sentinels. They shall not disturb each other."
(let ((auth-sources `(,netrc-file)))
(should (file-exists-p ert-remote-temporary-file-directory)))))))))
+(ert-deftest tramp-test47-read-otp-password ()
+ "Check Tramp one-time password handling."
+ :tags '(:expensive-test)
+ (skip-unless (tramp--test-mock-p))
+ ;; Not all read commands understand argument "-s" or "-p".
+ (skip-unless
+ (string-empty-p
+ (let ((shell-file-name "sh"))
+ (shell-command-to-string "read -s -p Password: pass"))))
+
+ (let ((pass "secret")
+ (mock-entry (copy-tree (assoc "mock" tramp-methods)))
+ mocked-input tramp-methods)
+ ;; We must mock `read-string', in order to avoid interactive
+ ;; arguments.
+ (cl-letf* (((symbol-function #'read-string)
+ (lambda (&rest _args) (pop mocked-input))))
+ (setcdr
+ (assq 'tramp-login-args mock-entry)
+ `((("-c")
+ (,(tramp-shell-quote-argument
+ (concat
+ "read -s -p 'Verification code: ' pass; echo; "
+ "(test \"pass$pass\" != \"pass" pass "\" && "
+ "echo \"Login incorrect\" || sh -i)"))))))
+ (setq tramp-methods `(,mock-entry))
+
+ ;; Reading password from stdin works.
+ (tramp-cleanup-connection tramp-test-vec 'keep-debug)
+ ;; We don't want to invalidate the password.
+ (setq mocked-input `(,(copy-sequence pass)))
+ (should (file-exists-p ert-remote-temporary-file-directory))
+
+ ;; Don't entering a password returns in error.
+ (tramp-cleanup-connection tramp-test-vec 'keep-debug)
+ (setq mocked-input nil)
+ (should-error (file-exists-p ert-remote-temporary-file-directory))
+
+ ;; A wrong password doesn't work either.
+ (tramp-cleanup-connection tramp-test-vec 'keep-debug)
+ (setq mocked-input `(,(concat pass pass)))
+ (should-error (file-exists-p ert-remote-temporary-file-directory))
+
+ ;; The password shouldn't be read from auth-source.
+ ;; Macro `ert-with-temp-file' was introduced in Emacs 29.1.
+ (with-no-warnings (when (symbol-plist 'ert-with-temp-file)
+ (tramp-cleanup-connection tramp-test-vec 'keep-debug)
+ (setq mocked-input nil)
+ (auth-source-forget-all-cached)
+ (ert-with-temp-file netrc-file
+ :prefix "tramp-test" :suffix ""
+ :text (format
+ "machine %s port mock password %s"
+ (file-remote-p ert-remote-temporary-file-directory 'host)
+ pass)
+ (let ((auth-sources `(,netrc-file)))
+ (should-error
+ (file-exists-p ert-remote-temporary-file-directory)))))))))
+
;; This test is inspired by Bug#29163.
(ert-deftest tramp-test48-auto-load ()
"Check that Tramp autoloads properly."
@@ -8150,6 +8250,7 @@ If INTERACTIVE is non-nil, the tests are run interactively."
;; * tramp-set-file-uid-gid
;; * Work on skipped tests. Make a comment, when it is impossible.
+;; * Use `skip-when' starting with Emacs 30.1.
;; * Revisit expensive tests, once problems in `tramp-error' are solved.
;; * Fix `tramp-test06-directory-file-name' for "ftp".
;; * Check, why a process filter t doesn't work in
diff --git a/test/lisp/net/webjump-tests.el b/test/lisp/net/webjump-tests.el
index 42fa346a869..eeec499b557 100644
--- a/test/lisp/net/webjump-tests.el
+++ b/test/lisp/net/webjump-tests.el
@@ -1,6 +1,6 @@
;;; webjump-tests.el --- Tests for webjump.el -*- lexical-binding: t; -*-
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
;; Author: Simen Heggestøyl <simenheg@gmail.com>
;; Keywords:
@@ -58,7 +58,7 @@
(ert-deftest webjump-tests-url-fix ()
(should (equal (webjump-url-fix nil) ""))
(should (equal (webjump-url-fix "/tmp/") "file:///tmp/"))
- (should (equal (webjump-url-fix "gnu.org") "http://gnu.org/"))
+ (should (equal (webjump-url-fix "gnu.org") "https://gnu.org/"))
(should (equal (webjump-url-fix "ftp.x.org") "ftp://ftp.x.org/"))
(should (equal (webjump-url-fix "https://gnu.org")
"https://gnu.org/")))
diff --git a/test/lisp/newcomment-tests.el b/test/lisp/newcomment-tests.el
index cb0f304c463..8bc08825aa4 100644
--- a/test/lisp/newcomment-tests.el
+++ b/test/lisp/newcomment-tests.el
@@ -1,6 +1,6 @@
;;; newcomment-tests.el --- Tests for newcomment.el -*- lexical-binding:t -*-
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/nxml/nxml-mode-tests.el b/test/lisp/nxml/nxml-mode-tests.el
index 973f2ebb67e..de60070555f 100644
--- a/test/lisp/nxml/nxml-mode-tests.el
+++ b/test/lisp/nxml/nxml-mode-tests.el
@@ -1,6 +1,6 @@
;;; nxml-mode-tests.el --- Test NXML Mode -*- lexical-binding: t; -*-
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/nxml/xsd-regexp-tests.el b/test/lisp/nxml/xsd-regexp-tests.el
index 6258e6c0fb0..797da3a3155 100644
--- a/test/lisp/nxml/xsd-regexp-tests.el
+++ b/test/lisp/nxml/xsd-regexp-tests.el
@@ -1,6 +1,6 @@
;;; xsd-regexp-tests.el --- Test NXML Mode -*- lexical-binding: t; -*-
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/obarray-tests.el b/test/lisp/obarray-tests.el
index 1831dc07a6d..d7e547fcf29 100644
--- a/test/lisp/obarray-tests.el
+++ b/test/lisp/obarray-tests.el
@@ -1,6 +1,6 @@
;;; obarray-tests.el --- Tests for obarray -*- lexical-binding: t; -*-
-;; Copyright (C) 2015-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2024 Free Software Foundation, Inc.
;; Author: Przemysław Wojnowski <esperanto@cumego.com>
diff --git a/test/lisp/obsolete/cl-tests.el b/test/lisp/obsolete/cl-tests.el
index f52c4749c9a..6a798f6792b 100644
--- a/test/lisp/obsolete/cl-tests.el
+++ b/test/lisp/obsolete/cl-tests.el
@@ -1,6 +1,6 @@
;;; cl-tests.el --- tests for emacs-lisp/cl.el -*- lexical-binding:t -*-
-;; Copyright (C) 2018-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2018-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/obsolete/inversion-tests.el b/test/lisp/obsolete/inversion-tests.el
index 728362eae0e..29c9705ba5d 100644
--- a/test/lisp/obsolete/inversion-tests.el
+++ b/test/lisp/obsolete/inversion-tests.el
@@ -1,6 +1,6 @@
;;; inversion-tests.el --- Tests for inversion.el -*- lexical-binding:t -*-
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/test/lisp/obsolete/makesum-tests.el b/test/lisp/obsolete/makesum-tests.el
index 280a43f77d5..68e464413ca 100644
--- a/test/lisp/obsolete/makesum-tests.el
+++ b/test/lisp/obsolete/makesum-tests.el
@@ -1,6 +1,6 @@
;;; makesum-tests.el --- Tests for makesum.el -*- lexical-binding: t; -*-
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
;; Author: Simen Heggestøyl <simenheg@gmail.com>
;; Keywords:
diff --git a/test/lisp/obsolete/rfc2368-tests.el b/test/lisp/obsolete/rfc2368-tests.el
index a7f80a689f8..2421ce6b912 100644
--- a/test/lisp/obsolete/rfc2368-tests.el
+++ b/test/lisp/obsolete/rfc2368-tests.el
@@ -1,6 +1,6 @@
;;; rfc2368-tests.el --- Tests for rfc2368.el -*- lexical-binding:t -*-
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/obsolete/thumbs-tests.el b/test/lisp/obsolete/thumbs-tests.el
index 87f8227c978..483418895fe 100644
--- a/test/lisp/obsolete/thumbs-tests.el
+++ b/test/lisp/obsolete/thumbs-tests.el
@@ -1,6 +1,6 @@
;;; thumbs-tests.el --- tests for thumbs.el -*- lexical-binding: t -*-
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/org/org-tests.el b/test/lisp/org/org-tests.el
index a498164f2f4..f519822cb42 100644
--- a/test/lisp/org/org-tests.el
+++ b/test/lisp/org/org-tests.el
@@ -1,6 +1,6 @@
;;; org-tests.el --- tests for org/org.el -*- lexical-binding:t -*-
-;; Copyright (C) 2018-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2018-2024 Free Software Foundation, Inc.
;; Maintainer: emacs-devel@gnu.org
diff --git a/test/lisp/paren-tests.el b/test/lisp/paren-tests.el
index 5e8b906a37f..352d436efb3 100644
--- a/test/lisp/paren-tests.el
+++ b/test/lisp/paren-tests.el
@@ -1,6 +1,6 @@
;;; paren-tests.el --- Tests for paren.el -*- lexical-binding: t; -*-
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
;; Author: Simen Heggestøyl <simenheg@gmail.com>
;; Keywords:
diff --git a/test/lisp/password-cache-tests.el b/test/lisp/password-cache-tests.el
index 45d2ec76f7b..08d85744ea1 100644
--- a/test/lisp/password-cache-tests.el
+++ b/test/lisp/password-cache-tests.el
@@ -1,6 +1,6 @@
;;; password-cache-tests.el --- Tests for password-cache.el -*- lexical-binding: t -*-
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
;; Author: Stefan Kangas <stefankangas@gmail.com>
diff --git a/test/lisp/pcmpl-linux-tests.el b/test/lisp/pcmpl-linux-tests.el
index eaceb216d38..da20428df9e 100644
--- a/test/lisp/pcmpl-linux-tests.el
+++ b/test/lisp/pcmpl-linux-tests.el
@@ -1,6 +1,6 @@
;;; pcmpl-linux-tests.el --- Tests for pcmpl-linux.el -*- lexical-binding: t -*-
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/pcomplete-tests.el b/test/lisp/pcomplete-tests.el
index 805a645198a..25f572090b6 100644
--- a/test/lisp/pcomplete-tests.el
+++ b/test/lisp/pcomplete-tests.el
@@ -1,6 +1,6 @@
;;; pcomplete-tests.el --- Tests for pcomplete.el -*- lexical-binding: t -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/play/animate-tests.el b/test/lisp/play/animate-tests.el
index a11ac6f1730..3dc34370789 100644
--- a/test/lisp/play/animate-tests.el
+++ b/test/lisp/play/animate-tests.el
@@ -1,6 +1,6 @@
;;; animate-tests.el --- Tests for animate.el -*- lexical-binding:t -*-
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/play/cookie1-tests.el b/test/lisp/play/cookie1-tests.el
index 0432ffb0f7e..058c80416a6 100644
--- a/test/lisp/play/cookie1-tests.el
+++ b/test/lisp/play/cookie1-tests.el
@@ -1,6 +1,6 @@
;;; cookie1-tests.el --- Tests for cookie1.el -*- lexical-binding: t -*-
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/play/dissociate-tests.el b/test/lisp/play/dissociate-tests.el
index 7bc15bb9827..f9b9ad7fd81 100644
--- a/test/lisp/play/dissociate-tests.el
+++ b/test/lisp/play/dissociate-tests.el
@@ -1,6 +1,6 @@
;;; dissociate-tests.el --- Tests for dissociate.el -*- lexical-binding:t -*-
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/play/fortune-tests.el b/test/lisp/play/fortune-tests.el
index 5f0ee6d0d6a..c90bad02b69 100644
--- a/test/lisp/play/fortune-tests.el
+++ b/test/lisp/play/fortune-tests.el
@@ -1,6 +1,6 @@
;;; fortune-tests.el --- Tests for fortune.el -*- lexical-binding: t -*-
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/play/life-tests.el b/test/lisp/play/life-tests.el
index 98ab11a886a..794dd14a774 100644
--- a/test/lisp/play/life-tests.el
+++ b/test/lisp/play/life-tests.el
@@ -1,6 +1,6 @@
;;; life-tests.el --- Tests for life.el -*- lexical-binding:t -*-
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
;; Author: Stefan Kangas <stefankangas@gmail.com>
diff --git a/test/lisp/play/morse-tests.el b/test/lisp/play/morse-tests.el
index 3fe4c9335c2..397cc3fa346 100644
--- a/test/lisp/play/morse-tests.el
+++ b/test/lisp/play/morse-tests.el
@@ -1,6 +1,6 @@
;;; morse-tests.el --- Tests for morse.el -*- lexical-binding: t -*-
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
;; Author: Stefan Kangas <stefankangas@gmail.com>
diff --git a/test/lisp/play/studly-tests.el b/test/lisp/play/studly-tests.el
index c563023ad12..e291e3302a6 100644
--- a/test/lisp/play/studly-tests.el
+++ b/test/lisp/play/studly-tests.el
@@ -1,6 +1,6 @@
;;; studly-tests.el --- Tests for studly.el -*- lexical-binding: t -*-
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
;; Author: Stefan Kangas <stefankangas@gmail.com>
diff --git a/test/lisp/proced-tests.el b/test/lisp/proced-tests.el
index bffbf5486d3..6f16a241146 100644
--- a/test/lisp/proced-tests.el
+++ b/test/lisp/proced-tests.el
@@ -1,6 +1,6 @@
;;; proced-tests.el --- Test suite for proced.el -*- lexical-binding: t -*-
-;; Copyright (C) 2022 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -18,6 +18,7 @@
;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
;;; Code:
+
(require 'ert)
(require 'proced)
(require 'thingatpt)
@@ -45,7 +46,7 @@
(move-to-column (string-match attribute proced-header-line)))
(defun proced--assert-process-valid-pid-refinement (pid)
- "Fail unless the process at point could be present after a refinment using PID."
+ "Fail unless the process at point could be present after a refinement using PID."
(proced--move-to-column "PID")
(let ((pid-equal (string= pid (word-at-point))))
(should
diff --git a/test/lisp/progmodes/asm-mode-tests.el b/test/lisp/progmodes/asm-mode-tests.el
index f4191493b27..55e937bd9ce 100644
--- a/test/lisp/progmodes/asm-mode-tests.el
+++ b/test/lisp/progmodes/asm-mode-tests.el
@@ -1,6 +1,6 @@
;;; asm-mode-tests.el --- Tests for asm-mode.el -*- lexical-binding: t; -*-
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
;; Author: Simen Heggestøyl <simenheg@gmail.com>
;; Keywords:
diff --git a/test/lisp/progmodes/autoconf-tests.el b/test/lisp/progmodes/autoconf-tests.el
index 3b67e6483d9..d170c9497fc 100644
--- a/test/lisp/progmodes/autoconf-tests.el
+++ b/test/lisp/progmodes/autoconf-tests.el
@@ -1,6 +1,6 @@
;;; autoconf-tests.el --- Tests for autoconf.el -*- lexical-binding: t; -*-
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
;; Author: Simen Heggestøyl <simenheg@gmail.com>
;; Keywords:
diff --git a/test/lisp/progmodes/bat-mode-tests.el b/test/lisp/progmodes/bat-mode-tests.el
index 8b80956c9af..80a5b5aa6b3 100644
--- a/test/lisp/progmodes/bat-mode-tests.el
+++ b/test/lisp/progmodes/bat-mode-tests.el
@@ -1,6 +1,6 @@
;;; bat-mode-tests.el --- Tests for bat-mode.el -*- lexical-binding: t; -*-
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
;; Author: Vladimir Panteleev <vladimir@thecybershadow.net>
;; Keywords:
diff --git a/test/lisp/progmodes/bug-reference-tests.el b/test/lisp/progmodes/bug-reference-tests.el
index 790582aed4c..8cca354705b 100644
--- a/test/lisp/progmodes/bug-reference-tests.el
+++ b/test/lisp/progmodes/bug-reference-tests.el
@@ -1,6 +1,6 @@
;;; bug-reference-tests.el --- Tests for bug-reference.el -*- lexical-binding: t; -*-
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -25,6 +25,7 @@
(require 'bug-reference)
(require 'ert)
+(require 'ert-x)
(defun test--get-github-entry (url)
(and (string-match
@@ -125,4 +126,18 @@
(test--get-gitea-entry "https://gitea.com/magit/magit/")
"magit/magit")))
+(ert-deftest test-thing-at-point ()
+ "Ensure that (thing-at-point 'url) returns the bug URL."
+ (ert-with-test-buffer (:name "thingatpt")
+ (setq-local bug-reference-url-format "https://debbugs.gnu.org/%s")
+ (insert "bug#1234")
+ (bug-reference-mode)
+ (jit-lock-fontify-now (point-min) (point-max))
+ (goto-char (point-min))
+ ;; Make sure we get the URL when `bug-reference-mode' is active...
+ (should (equal (thing-at-point 'url) "https://debbugs.gnu.org/1234"))
+ (bug-reference-mode -1)
+ ;; ... and get nil when `bug-reference-mode' is inactive.
+ (should-not (thing-at-point 'url))))
+
;;; bug-reference-tests.el ends here
diff --git a/test/lisp/progmodes/c-ts-mode-resources/indent-bsd.erts b/test/lisp/progmodes/c-ts-mode-resources/indent-bsd.erts
index 74e34fe821b..fa65ba83a69 100644
--- a/test/lisp/progmodes/c-ts-mode-resources/indent-bsd.erts
+++ b/test/lisp/progmodes/c-ts-mode-resources/indent-bsd.erts
@@ -91,3 +91,37 @@ main (int argc,
}
}
=-=-=
+
+Name: Bracketless Simple Statement (bug#66152)
+
+=-=
+for (int i = 0; i < 5; i++)
+continue;
+
+while (true)
+return 1;
+
+do
+i++;
+while (true)
+
+if (true)
+break;
+else
+break;
+=-=
+for (int i = 0; i < 5; i++)
+ continue;
+
+while (true)
+ return 1;
+
+do
+ i++;
+while (true)
+
+if (true)
+ break;
+else
+ break;
+=-=-=
diff --git a/test/lisp/progmodes/c-ts-mode-resources/indent.erts b/test/lisp/progmodes/c-ts-mode-resources/indent.erts
index 221b3d809af..2fd26d75844 100644
--- a/test/lisp/progmodes/c-ts-mode-resources/indent.erts
+++ b/test/lisp/progmodes/c-ts-mode-resources/indent.erts
@@ -151,6 +151,21 @@ Name: Bracketless Simple Statement
=-=
for (int i = 0; i < 5; i++)
+continue;
+
+while (true)
+return 1;
+
+do
+i++;
+while (true)
+
+if (true)
+break;
+else
+break;
+=-=
+for (int i = 0; i < 5; i++)
continue;
while (true)
@@ -159,6 +174,11 @@ while (true)
do
i++;
while (true)
+
+if (true)
+ break;
+else
+ break;
=-=-=
Name: Nested If-Else
@@ -310,7 +330,7 @@ label:
Name: Bracket-less Block-Statement (Linux Style) (bug#61026)
-=-=-=
+=-=
int main() {
while (true)
if (true) {
@@ -331,6 +351,8 @@ int main() {
if (true) {
puts ("Hello");
}
+ else
+ puts("Hello");
}
=-=-=
@@ -379,6 +401,34 @@ void foo(
}
=-=-=
+Name: Block-Statement where first siblings are comments (Linux Style)
+
+=-=
+int main() {
+ while (true) { /* foo */
+ if (true) { // bar
+ puts ("Hello");
+ }
+ }
+ for (;;) { // 1. fooo
+ /* 2. baaa */
+ /* 3. rrr */
+ if (true)
+ // 2. baaa
+ puts ("Hello");
+ }
+ if (1) { // 1
+ /*
+ * 2
+ */
+ if (1) /*3*/ {
+ /* 4 */
+ puts("Hello");
+ }
+ }
+}
+=-=-=
+
Name: Initializer List (Linux Style) (Bug#61398)
=-=
@@ -478,3 +528,19 @@ main (void)
{
|
=-=-=
+
+Code:
+ (lambda ()
+ (c-ts-mode)
+ (setq-local indent-tabs-mode nil)
+ (goto-line 3)
+ (indent-for-tab-command))
+
+Name: Block-Statement where previous sibling is comment
+
+=-=
+int main() {
+ puts ("Hello"); // unusual indent and has trailing comment.
+ return true; // Should align with previous non-comment sibling (rather than one level up against parent).
+}
+=-=-=
diff --git a/test/lisp/progmodes/c-ts-mode-tests.el b/test/lisp/progmodes/c-ts-mode-tests.el
index ea5fab4cbef..d8d8aabaa36 100644
--- a/test/lisp/progmodes/c-ts-mode-tests.el
+++ b/test/lisp/progmodes/c-ts-mode-tests.el
@@ -1,6 +1,6 @@
;;; c-ts-mode-tests.el --- Tests for Tree-sitter-based C mode -*- lexical-binding: t; -*-
-;; Copyright (C) 2023 Free Software Foundation, Inc.
+;; Copyright (C) 2023-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/progmodes/cc-mode-tests.el b/test/lisp/progmodes/cc-mode-tests.el
index 7158b8f9e45..c6e43ab3360 100644
--- a/test/lisp/progmodes/cc-mode-tests.el
+++ b/test/lisp/progmodes/cc-mode-tests.el
@@ -1,6 +1,6 @@
;;; cc-mode-tests.el --- Test suite for cc-mode. -*- lexical-binding: t; -*-
-;; Copyright (C) 2016-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2016-2024 Free Software Foundation, Inc.
;; Author: Michal Nazarewicz <mina86@mina86.com>
;; Keywords: internal
diff --git a/test/lisp/progmodes/compile-tests.el b/test/lisp/progmodes/compile-tests.el
index 078eef36774..f5b5cad9c0b 100644
--- a/test/lisp/progmodes/compile-tests.el
+++ b/test/lisp/progmodes/compile-tests.el
@@ -1,6 +1,6 @@
;;; compile-tests.el --- Test suite for compile.el. -*- lexical-binding: t; -*-
-;; Copyright (C) 2011-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2011-2024 Free Software Foundation, Inc.
;; Author: Chong Yidong <cyd@stupidchicken.com>
;; Keywords: internal
@@ -121,9 +121,7 @@
;; cucumber
(cucumber "Scenario: undefined step # features/cucumber.feature:3"
29 nil 3 "features/cucumber.feature")
- ;; This rule is actually handled by the `cucumber' pattern but when
- ;; `omake' is included, then `gnu' matches it first.
- (gnu " /home/gusev/.rvm/foo/bar.rb:500:in `_wrap_assertion'"
+ (cucumber " /home/gusev/.rvm/foo/bar.rb:500:in `_wrap_assertion'"
1 nil 500 "/home/gusev/.rvm/foo/bar.rb")
;; edg-1 edg-2
(edg-1 "build/intel/debug/../../../struct.cpp(42): error: identifier \"foo\" is undefined"
@@ -312,10 +310,6 @@
1 nil 109 "..\\src\\ctrl\\lister.c")
(watcom "..\\src\\ctrl\\lister.c(120): Warning! W201: Unreachable code"
1 nil 120 "..\\src\\ctrl\\lister.c")
- ;; omake
- ;; FIXME: This doesn't actually test the omake rule.
- (gnu " alpha.c:5:15: error: expected ';' after expression"
- 1 15 5 "alpha.c")
;; oracle
(oracle "Semantic error at line 528, column 5, file erosacqdb.pc:"
1 5 528 "erosacqdb.pc")
@@ -497,8 +491,22 @@ The test data is in `compile-tests--test-regexps-data'."
(font-lock-mode -1)
(let ((compilation-num-errors-found 0)
(compilation-num-warnings-found 0)
- (compilation-num-infos-found 0))
- (mapc #'compile--test-error-line compile-tests--test-regexps-data)
+ (compilation-num-infos-found 0)
+ (all-rules (mapcar #'car compilation-error-regexp-alist-alist)))
+
+ ;; Test all built-in rules except `omake' to avoid interference.
+ (let ((compilation-error-regexp-alist (remq 'omake all-rules)))
+ (mapc #'compile--test-error-line compile-tests--test-regexps-data))
+
+ ;; Test the `omake' rule separately.
+ ;; This doesn't actually test the `omake' rule itself but its
+ ;; indirect effects.
+ (let ((compilation-error-regexp-alist all-rules)
+ (test
+ '(gnu " alpha.c:5:15: error: expected ';' after expression"
+ 1 15 5 "alpha.c")))
+ (compile--test-error-line test))
+
(should (eq compilation-num-errors-found 100))
(should (eq compilation-num-warnings-found 35))
(should (eq compilation-num-infos-found 28)))))
diff --git a/test/lisp/progmodes/cperl-mode-resources/cperl-bug-35925.pl b/test/lisp/progmodes/cperl-mode-resources/cperl-bug-35925.pl
new file mode 100644
index 00000000000..e3f96241ab7
--- /dev/null
+++ b/test/lisp/progmodes/cperl-mode-resources/cperl-bug-35925.pl
@@ -0,0 +1,36 @@
+# This resource file can be run with cperl--run-testcases from
+# cperl-tests.el and works with both perl-mode and cperl-mode.
+
+# -------- Bug#35925: input -------
+format FH =
+@### @.### @###
+42, 3.1415, 0
+.
+write FH;
+
+# -------- Bug#35925: expected output -------
+format FH =
+@### @.### @###
+42, 3.1415, 0
+.
+write FH;
+
+# -------- Bug#35925: end -------
+
+# -------- format not as top-level: input -------
+foo: {
+ format STDOUT =
+^<<<<
+$foo
+.
+write;
+}
+# -------- format not as top-level: expected output -------
+foo: {
+ format STDOUT =
+^<<<<
+$foo
+.
+ write;
+}
+# -------- format not as top-level: end -------
diff --git a/test/lisp/progmodes/cperl-mode-resources/cperl-bug-65834.pl b/test/lisp/progmodes/cperl-mode-resources/cperl-bug-65834.pl
new file mode 100644
index 00000000000..775a113ac17
--- /dev/null
+++ b/test/lisp/progmodes/cperl-mode-resources/cperl-bug-65834.pl
@@ -0,0 +1,5 @@
+# -*- mode: cperl -*-
+if ($t->[3]<<5) {
+ return 0;
+}
+# comment
diff --git a/test/lisp/progmodes/cperl-mode-resources/cperl-bug-66145.pl b/test/lisp/progmodes/cperl-mode-resources/cperl-bug-66145.pl
new file mode 100644
index 00000000000..70f12346ded
--- /dev/null
+++ b/test/lisp/progmodes/cperl-mode-resources/cperl-bug-66145.pl
@@ -0,0 +1,62 @@
+# The original code, from the bug report, with variables renamed
+
+sub foo {
+ # Here we do something like
+ # this: $array_comment [ num_things ]->{key_comment}
+}
+
+# --------------------------------------------------
+# Comments containing hash and array sigils
+
+# This is an @array, and this is a %hash
+# $array_comment[$index] = $hash_comment{key_comment}
+# The last element has the index $#array_comment
+# my @a_slice = @array_comment[1,2,3];
+# my @h_slice = @hash_comment{qw(a b c)};
+# my %a_set = %array_comment[1,2,3];
+# my %h_set = %hash_comment{qw(a b c)};
+
+# --------------------------------------------------
+# in POD
+
+=head1 NAME
+
+cperl-bug-66145 - don't fontify arrays and hashes in POD
+
+=head1 SYNOPSIS
+
+ $array_comment[$index] = $hash_comment{key_comment};
+ @array_comment = qw(in pod);
+ %hash_comment = key_comment => q(pod);
+ @array_comment = @array_comment[1,2,3];
+ @array_comment = @hash_comment{qw(a b c)};
+ %hash_comment = %array_comment[1,2,3];
+ %hash_comment = %hash_comment{qw(a b c)};
+
+=cut
+
+# --------------------------------------------------
+# in strings
+
+my @strings = (
+ q/$array_string[$index] = $hash_string{key_string};/,
+ q/my @array_string = qw(in unquoted string);/,
+ q/my %hash_string = (key_string => q(pod);)/,
+ q/@array_string = @array_string[1,2,3];/,
+ q/@array_string = @hash_string{qw(a b c)};/,
+ q/%hash_string = %array_string[1,2,3];/,
+ q/%hash_string = %hash_string{qw(a b c)};/,
+);
+
+# --------------------------------------------------
+# in a HERE-document (perl-mode has an extra face for that)
+
+my $here = <<DONE;
+ $array_here[$index_here] = $hash_here{key_here};
+ @array_here = qw(in a hrere-document);
+ %hash_here = key_here => q(pod);
+ @array_here = @array_here[1,2,3];
+ @array_here = @hash_here{qw(a b c)};
+ %hash_here = %array_here[1,2,3];
+ %hash_here = %hash_here{qw(a b c)};
+DONE
diff --git a/test/lisp/progmodes/cperl-mode-resources/cperl-bug-66161.pl b/test/lisp/progmodes/cperl-mode-resources/cperl-bug-66161.pl
new file mode 100644
index 00000000000..e39cfdd3b24
--- /dev/null
+++ b/test/lisp/progmodes/cperl-mode-resources/cperl-bug-66161.pl
@@ -0,0 +1,13 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+print("Hello World\n");
+
+__END__
+
+TODO:
+What's happening?
+
+It's all messed up.
diff --git a/test/lisp/progmodes/cperl-mode-tests.el b/test/lisp/progmodes/cperl-mode-tests.el
index 8f334245c64..e3026dbfb5a 100644
--- a/test/lisp/progmodes/cperl-mode-tests.el
+++ b/test/lisp/progmodes/cperl-mode-tests.el
@@ -1,6 +1,6 @@
;;; cperl-mode-tests.el --- Test for cperl-mode -*- lexical-binding: t -*-
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
;; Author: Harald Jörg <haj@posteo.de>
;; Maintainer: Harald Jörg
@@ -25,6 +25,10 @@
;;; Commentary:
;; This is a collection of tests for CPerl-mode.
+;; The maintainer would like to use this test file with cperl-mode.el
+;; also in older Emacs versions (currently: Emacs 26.1): Please don't
+;; use Emacs features which are not available in that version (unless
+;; they're already used in existing tests).
;;; Code:
@@ -1139,6 +1143,20 @@ Perl is not Lisp: An open paren in column 0 does not start a function."
(cperl-indent-command)
(forward-line 1))))
+(ert-deftest cperl-test-bug-35925 ()
+ "Check that indentation is correct after a terminating format declaration."
+ (cperl-set-style "PBP") ; Make cperl-mode use the same settings as perl-mode.
+ (cperl--run-test-cases
+ (ert-resource-file "cperl-bug-35925.pl")
+ (let ((tab-function
+ (if (equal cperl-test-mode 'perl-mode)
+ #'indent-for-tab-command
+ #'cperl-indent-command)))
+ (goto-char (point-max))
+ (forward-line -2)
+ (funcall tab-function)))
+ (cperl-set-style-back))
+
(ert-deftest cperl-test-bug-37127 ()
"Verify that closing a paren in a regex goes without a message.
Also check that the message is issued if the regex terminator is
@@ -1361,6 +1379,59 @@ as a regex."
(forward-line 1))))
(cperl-set-style-back))
+(ert-deftest cperl-test-bug-65834 ()
+ "Verify that CPerl mode identifies a left-shift operator.
+Left-shift and here-documents both use the \"<<\" operator.
+In the code provided by this bug report, it needs to be
+detected as left-shift operator."
+ (with-temp-buffer
+ (insert-file-contents (ert-resource-file "cperl-bug-65834.pl"))
+ (funcall cperl-test-mode)
+ (font-lock-ensure)
+ (search-forward "retur") ; leaves point before the "n"
+ (should (equal (get-text-property (point) 'face)
+ font-lock-keyword-face))
+ (search-forward "# comm") ; leaves point before "ent"
+ (should (equal (get-text-property (point) 'face)
+ font-lock-comment-face))))
+
+(ert-deftest cperl-test-bug-66145 ()
+ "Verify that hashes and arrays are only fontified in code.
+In strings, comments and POD the syntaxified faces should
+prevail. The tests exercise all combinations of sigils $@% and
+parenthesess [{ for comments, POD, strings and HERE-documents.
+Fontification in code for `cperl-mode' is done in the tests
+beginning with `cperl-test-unicode`."
+ (let ((types '("array" "hash" "key"))
+ (faces `(("string" . font-lock-string-face)
+ ("comment" . font-lock-comment-face)
+ ("here" . ,(if (equal cperl-test-mode 'perl-mode)
+ 'perl-heredoc
+ font-lock-string-face)))))
+ (with-temp-buffer
+ (insert-file-contents (ert-resource-file "cperl-bug-66145.pl"))
+ (funcall cperl-test-mode)
+ (font-lock-ensure)
+ (dolist (type types)
+ (goto-char (point-min))
+ (while (re-search-forward (concat type "_\\([a-z]+\\)") nil t)
+ (should (equal (get-text-property (match-beginning 1) 'face)
+ (cdr (assoc (match-string-no-properties 1)
+ faces)))))))))
+
+(ert-deftest cperl-test-bug-66161 ()
+ "Verify that text after \"__END__\" is fontified as comment.
+For `cperl-mode', this needs the custom variable
+`cperl-fontify-trailer' to be set to `comment'. Per default,
+cperl-mode fontifies text after the delimiter as Perl code."
+ (with-temp-buffer
+ (insert-file-contents (ert-resource-file "cperl-bug-66161.pl"))
+ (setq cperl-fontify-trailer 'comment)
+ (funcall cperl-test-mode)
+ (font-lock-ensure)
+ (search-forward "TODO") ; leaves point before the colon
+ (should (equal (get-text-property (point) 'face)
+ font-lock-comment-face))))
(ert-deftest test-indentation ()
(ert-test-erts-file (ert-resource-file "cperl-indents.erts")))
diff --git a/test/lisp/progmodes/eglot-tests.el b/test/lisp/progmodes/eglot-tests.el
index 725b877fd3c..4725885038e 100644
--- a/test/lisp/progmodes/eglot-tests.el
+++ b/test/lisp/progmodes/eglot-tests.el
@@ -1,6 +1,6 @@
;;; eglot-tests.el --- Tests for eglot.el -*- lexical-binding: t; -*-
-;; Copyright (C) 2018-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2018-2024 Free Software Foundation, Inc.
;; Author: João Távora <joaotavora@gmail.com>
;; Keywords: tests
@@ -199,40 +199,40 @@ directory hierarchy."
&rest body)
"Run BODY saving LSP JSON messages in variables, most recent first."
(declare (indent 1) (debug (sexp &rest form)))
- (let ((log-event-ad-sym (make-symbol "eglot--event-sniff")))
- `(unwind-protect
- (let ,(delq nil (list server-requests
- server-notifications
- server-replies
- client-requests
- client-notifications
- client-replies))
- (advice-add
- #'jsonrpc--log-event :before
- (lambda (_proc message &optional type)
- (cl-destructuring-bind (&key method id _error &allow-other-keys)
- message
- (let ((req-p (and method id))
- (notif-p method)
- (reply-p id))
- (cond
- ((eq type 'server)
- (cond (req-p ,(when server-requests
- `(push message ,server-requests)))
- (notif-p ,(when server-notifications
- `(push message ,server-notifications)))
- (reply-p ,(when server-replies
- `(push message ,server-replies)))))
- ((eq type 'client)
- (cond (req-p ,(when client-requests
- `(push message ,client-requests)))
- (notif-p ,(when client-notifications
- `(push message ,client-notifications)))
- (reply-p ,(when client-replies
- `(push message ,client-replies)))))))))
- '((name . ,log-event-ad-sym)))
- ,@body)
- (advice-remove #'jsonrpc--log-event ',log-event-ad-sym))))
+ (let ((log-event-hook-sym (make-symbol "eglot--event-sniff")))
+ `(let* (,@(delq nil (list server-requests
+ server-notifications
+ server-replies
+ client-requests
+ client-notifications
+ client-replies)))
+ (cl-flet ((,log-event-hook-sym (_connection
+ origin
+ &key _json kind message _foreign-message
+ &allow-other-keys)
+ (let ((req-p (eq kind 'request))
+ (notif-p (eq kind 'notification))
+ (reply-p (eql kind 'reply)))
+ (cond
+ ((eq origin 'server)
+ (cond (req-p ,(when server-requests
+ `(push message ,server-requests)))
+ (notif-p ,(when server-notifications
+ `(push message ,server-notifications)))
+ (reply-p ,(when server-replies
+ `(push message ,server-replies)))))
+ ((eq origin 'client)
+ (cond (req-p ,(when client-requests
+ `(push message ,client-requests)))
+ (notif-p ,(when client-notifications
+ `(push message ,client-notifications)))
+ (reply-p ,(when client-replies
+ `(push message ,client-replies)))))))))
+ (unwind-protect
+ (progn
+ (add-hook 'jsonrpc-event-hook #',log-event-hook-sym)
+ ,@body)
+ (remove-hook 'jsonrpc-event-hook #',log-event-hook-sym))))))
(cl-defmacro eglot--wait-for ((events-sym &optional (timeout 1) message) args &body body)
(declare (indent 2) (debug (sexp sexp sexp &rest form)))
@@ -415,7 +415,7 @@ directory hierarchy."
(and (string= method "workspace/didChangeWatchedFiles")
(cl-destructuring-bind (&key uri type)
(elt (plist-get params :changes) 0)
- (and (string= (eglot--path-to-uri "Cargo.toml") uri)
+ (and (string= (eglot-path-to-uri "Cargo.toml") uri)
(= type 3))))))))))
(ert-deftest eglot-test-basic-diagnostics ()
@@ -544,10 +544,7 @@ directory hierarchy."
`(("project" . (("coiso.c" . "#include <stdio.h>\nint main () {fprin"))))
(with-current-buffer
(eglot--find-file-noselect "project/coiso.c")
- (eglot--sniffing (:server-notifications s-notifs)
- (eglot--wait-for-clangd)
- (eglot--wait-for (s-notifs 20) (&key method &allow-other-keys)
- (string= method "textDocument/publishDiagnostics")))
+ (eglot--wait-for-clangd)
(goto-char (point-max))
(completion-at-point)
(message (buffer-string))
@@ -927,7 +924,7 @@ int main() {
(should-error (apply #'eglot--connect (eglot--guess-contact)))))))
(ert-deftest eglot-test-capabilities ()
- "Unit test for `eglot--server-capable'."
+ "Unit test for `eglot-server-capable'."
(cl-letf (((symbol-function 'eglot--capabilities)
(lambda (_dummy)
;; test data lifted from Golangserver example at
@@ -942,11 +939,11 @@ int main() {
:xdefinitionProvider t :xworkspaceSymbolByProperties t)))
((symbol-function 'eglot--current-server-or-lose)
(lambda () nil)))
- (should (eql 2 (eglot--server-capable :textDocumentSync)))
- (should (eglot--server-capable :completionProvider :triggerCharacters))
- (should (equal '(:triggerCharacters ["."]) (eglot--server-capable :completionProvider)))
- (should-not (eglot--server-capable :foobarbaz))
- (should-not (eglot--server-capable :textDocumentSync :foobarbaz))))
+ (should (eql 2 (eglot-server-capable :textDocumentSync)))
+ (should (eglot-server-capable :completionProvider :triggerCharacters))
+ (should (equal '(:triggerCharacters ["."]) (eglot-server-capable :completionProvider)))
+ (should-not (eglot-server-capable :foobarbaz))
+ (should-not (eglot-server-capable :textDocumentSync :foobarbaz))))
(defmacro eglot--without-interface-warnings (&rest body)
(let ((eglot-strict-mode nil))
@@ -1276,9 +1273,9 @@ GUESSED-MAJOR-MODES-SYM are bound to the useful return values of
(ert-deftest eglot-test-path-to-uri-windows ()
(skip-unless (eq system-type 'windows-nt))
(should (string-prefix-p "file:///"
- (eglot--path-to-uri "c:/Users/Foo/bar.lisp")))
+ (eglot-path-to-uri "c:/Users/Foo/bar.lisp")))
(should (string-suffix-p "c%3A/Users/Foo/bar.lisp"
- (eglot--path-to-uri "c:/Users/Foo/bar.lisp"))))
+ (eglot-path-to-uri "c:/Users/Foo/bar.lisp"))))
(ert-deftest eglot-test-same-server-multi-mode ()
"Check single LSP instance manages multiple modes in same project."
diff --git a/test/lisp/progmodes/elisp-mode-tests.el b/test/lisp/progmodes/elisp-mode-tests.el
index 5b6ef88dceb..1d1ef9981e5 100644
--- a/test/lisp/progmodes/elisp-mode-tests.el
+++ b/test/lisp/progmodes/elisp-mode-tests.el
@@ -1,6 +1,6 @@
;;; elisp-mode-tests.el --- Tests for emacs-lisp-mode -*- lexical-binding: t; -*-
-;; Copyright (C) 2015-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2024 Free Software Foundation, Inc.
;; Author: Dmitry Gutov <dgutov@yandex.ru>
;; Author: Stephen Leake <stephen_leake@member.fsf.org>
@@ -128,7 +128,7 @@
(ert-deftest eval-last-sexp-print-format-sym-echo ()
;; We can only check the echo area when running interactive.
- (skip-unless (not noninteractive))
+ (skip-when noninteractive)
(with-temp-buffer
(let ((current-prefix-arg nil))
(erase-buffer) (insert "t") (message nil)
@@ -147,7 +147,7 @@
(should (equal (buffer-string) "?A65 (#o101, #x41, ?A)")))))
(ert-deftest eval-last-sexp-print-format-small-int-echo ()
- (skip-unless (not noninteractive))
+ (skip-when noninteractive)
(with-temp-buffer
(let ((current-prefix-arg nil))
(erase-buffer) (insert "?A") (message nil)
@@ -171,7 +171,7 @@
(should (equal (buffer-string) "?B66 (#o102, #x42, ?B)"))))))
(ert-deftest eval-last-sexp-print-format-large-int-echo ()
- (skip-unless (not noninteractive))
+ (skip-when noninteractive)
(with-temp-buffer
(let ((eval-expression-print-maximum-character ?A))
(let ((current-prefix-arg nil))
@@ -186,7 +186,7 @@
;;; eval-defun
(ert-deftest eval-defun-prints-edebug-when-instrumented ()
- (skip-unless (not noninteractive))
+ (skip-when noninteractive)
(with-temp-buffer
(let ((current-prefix-arg '(4)))
(erase-buffer) (insert "(defun foo ())") (message nil)
diff --git a/test/lisp/progmodes/elixir-ts-mode-resources/indent.erts b/test/lisp/progmodes/elixir-ts-mode-resources/indent.erts
index 1f855d3c977..fe09a37a32b 100644
--- a/test/lisp/progmodes/elixir-ts-mode-resources/indent.erts
+++ b/test/lisp/progmodes/elixir-ts-mode-resources/indent.erts
@@ -330,6 +330,22 @@ Name: Long tuple
"October", "November", "December"}
=-=-=
+Name: Doc
+
+=-=
+defmodule Foo do
+"""
+ bar
+ """
+end
+=-=
+defmodule Foo do
+ """
+ bar
+ """
+end
+=-=-=
+
Name: Embedded HEEx
=-=
diff --git a/test/lisp/progmodes/elixir-ts-mode-tests.el b/test/lisp/progmodes/elixir-ts-mode-tests.el
index 488fc1b646f..109030a4476 100644
--- a/test/lisp/progmodes/elixir-ts-mode-tests.el
+++ b/test/lisp/progmodes/elixir-ts-mode-tests.el
@@ -1,6 +1,6 @@
;;; elixir-ts-mode-tests.el --- Tests for elixir-ts-mode -*- lexical-binding: t; -*-
-;; Copyright (C) 2023 Free Software Foundation, Inc.
+;; Copyright (C) 2023-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/progmodes/etags-tests.el b/test/lisp/progmodes/etags-tests.el
index 2e1a73d977e..99d66a20e6d 100644
--- a/test/lisp/progmodes/etags-tests.el
+++ b/test/lisp/progmodes/etags-tests.el
@@ -1,6 +1,6 @@
;;; etags-tests.el --- Test suite for etags.el. -*- lexical-binding:t -*-
-;; Copyright (C) 2016-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2016-2024 Free Software Foundation, Inc.
;; Author: Eli Zaretskii <eliz@gnu.org>
diff --git a/test/lisp/progmodes/executable-tests.el b/test/lisp/progmodes/executable-tests.el
index 406762fe4de..be4fe7de049 100644
--- a/test/lisp/progmodes/executable-tests.el
+++ b/test/lisp/progmodes/executable-tests.el
@@ -1,6 +1,6 @@
;;; executable-tests.el --- Tests for executable.el -*- lexical-binding:t -*-
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/progmodes/f90-tests.el b/test/lisp/progmodes/f90-tests.el
index 6028b58bb9e..e8e16534a97 100644
--- a/test/lisp/progmodes/f90-tests.el
+++ b/test/lisp/progmodes/f90-tests.el
@@ -1,6 +1,6 @@
;;; f90-tests.el --- tests for progmodes/f90.el -*- lexical-binding:t -*-
-;; Copyright (C) 2011-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2011-2024 Free Software Foundation, Inc.
;; Author: Glenn Morris <rgm@gnu.org>
;; Maintainer: emacs-devel@gnu.org
diff --git a/test/lisp/progmodes/flymake-tests.el b/test/lisp/progmodes/flymake-tests.el
index f6608dffca2..21dbb0711d2 100644
--- a/test/lisp/progmodes/flymake-tests.el
+++ b/test/lisp/progmodes/flymake-tests.el
@@ -1,6 +1,6 @@
;;; flymake-tests.el --- Test suite for flymake -*- lexical-binding: t -*-
-;; Copyright (C) 2011-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2011-2024 Free Software Foundation, Inc.
;; Author: Eduard Wiebe <usenet@pusto.de>
@@ -213,6 +213,7 @@ SEVERITY-PREDICATE is used to setup
(ert-deftest dummy-backends ()
"Test many different kinds of backends."
+ (let ((debug-on-error nil))
(with-temp-buffer
(cl-letf
(((symbol-function 'error-backend)
@@ -291,7 +292,7 @@ SEVERITY-PREDICATE is used to setup
(should (eq 'flymake-warning (face-at-point))) ; dolor
(flymake-goto-next-error)
(should (eq 'flymake-error (face-at-point))) ; prognata
- (should-error (flymake-goto-next-error nil nil t))))))
+ (should-error (flymake-goto-next-error nil nil t)))))))
(ert-deftest recurrent-backend ()
"Test a backend that calls REPORT-FN multiple times."
diff --git a/test/lisp/progmodes/gdb-mi-tests.el b/test/lisp/progmodes/gdb-mi-tests.el
index b75de1a9d45..d85f8e6cbb1 100644
--- a/test/lisp/progmodes/gdb-mi-tests.el
+++ b/test/lisp/progmodes/gdb-mi-tests.el
@@ -1,6 +1,6 @@
;;; gdb-mi-tests.el --- tests for gdb-mi.el -*- lexical-binding: t -*-
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/progmodes/glasses-tests.el b/test/lisp/progmodes/glasses-tests.el
index a577d9a46d8..cb1b17b1c05 100644
--- a/test/lisp/progmodes/glasses-tests.el
+++ b/test/lisp/progmodes/glasses-tests.el
@@ -1,6 +1,6 @@
;;; glasses-tests.el --- Tests for glasses.el -*- lexical-binding: t; -*-
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
;; Author: Simen Heggestøyl <simenheg@gmail.com>
;; Keywords:
diff --git a/test/lisp/progmodes/go-ts-mode-tests.el b/test/lisp/progmodes/go-ts-mode-tests.el
index 548465208f9..fd9b57e8691 100644
--- a/test/lisp/progmodes/go-ts-mode-tests.el
+++ b/test/lisp/progmodes/go-ts-mode-tests.el
@@ -1,6 +1,6 @@
;;; go-ts-mode-tests.el --- Tests for Tree-sitter-based Go mode -*- lexical-binding: t; -*-
-;; Copyright (C) 2023 Free Software Foundation, Inc.
+;; Copyright (C) 2023-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/progmodes/grep-tests.el b/test/lisp/progmodes/grep-tests.el
index 9b7f83086bf..303e5e90042 100644
--- a/test/lisp/progmodes/grep-tests.el
+++ b/test/lisp/progmodes/grep-tests.el
@@ -1,6 +1,6 @@
;;; grep-tests.el --- Test suite for grep.el -*- lexical-binding:t -*-
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/progmodes/heex-ts-mode-tests.el b/test/lisp/progmodes/heex-ts-mode-tests.el
index def6d845de9..7f9c0bf272c 100644
--- a/test/lisp/progmodes/heex-ts-mode-tests.el
+++ b/test/lisp/progmodes/heex-ts-mode-tests.el
@@ -1,6 +1,6 @@
;;; heex-ts-mode-tests.el --- Tests for heex-ts-mode -*- lexical-binding: t; -*-
-;; Copyright (C) 2023 Free Software Foundation, Inc.
+;; Copyright (C) 2023-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/progmodes/hideshow-tests.el b/test/lisp/progmodes/hideshow-tests.el
index ce3efb6dc95..1c0b9333656 100644
--- a/test/lisp/progmodes/hideshow-tests.el
+++ b/test/lisp/progmodes/hideshow-tests.el
@@ -1,6 +1,6 @@
;;; hideshow-tests.el --- Test suite for hideshow.el -*- lexical-binding:t -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/progmodes/java-ts-mode-tests.el b/test/lisp/progmodes/java-ts-mode-tests.el
index 4fd8fc3019f..9fa313e173e 100644
--- a/test/lisp/progmodes/java-ts-mode-tests.el
+++ b/test/lisp/progmodes/java-ts-mode-tests.el
@@ -1,6 +1,6 @@
;;; java-ts-mode-tests.el --- Tests for Tree-sitter-based Java mode -*- lexical-binding: t; -*-
-;; Copyright (C) 2023 Free Software Foundation, Inc.
+;; Copyright (C) 2023-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/progmodes/js-resources/js-ts-indents.erts b/test/lisp/progmodes/js-resources/js-ts-indents.erts
new file mode 100644
index 00000000000..2e34b23acef
--- /dev/null
+++ b/test/lisp/progmodes/js-resources/js-ts-indents.erts
@@ -0,0 +1,44 @@
+Code:
+ (lambda ()
+ (setq indent-tabs-mode nil)
+ (setq js-indent-level 2)
+ (js-ts-mode)
+ (indent-region (point-min) (point-max)))
+
+Name: Basic indentation
+
+=-=
+const foo = () => {
+ console.log("bar");
+ if (x) {
+ return y;
+ } else if (y) {
+ return u;
+ }
+ return baz.x()
+ ? true
+ : false;
+}
+=-=-=
+
+Name: Statement indentation without braces
+
+=-=
+function bracketless_statements(x) {
+ if (x == 0)
+ console.log("if_statement");
+ else if (x == 1)
+ console.log("if_statement");
+ else
+ console.log("else_clause");
+ for (let i = 0; i < 1; i++)
+ console.log("for_statement");
+ for (let _ of [true])
+ console.log("for_in_statement");
+ while (x-- > 0)
+ console.log("while_statement");
+ do
+ console.log("do_statement");
+ while (false)
+};
+=-=-=
diff --git a/test/lisp/progmodes/js-tests.el b/test/lisp/progmodes/js-tests.el
index 5db92b08f8a..39c5c4fb565 100644
--- a/test/lisp/progmodes/js-tests.el
+++ b/test/lisp/progmodes/js-tests.el
@@ -1,6 +1,6 @@
;;; js-tests.el --- Test suite for js-mode -*- lexical-binding:t -*-
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -288,6 +288,12 @@ function bar() {
;; end-of-defun should move point to eob.
(should (eobp))))
+;;;; Tree-sitter tests.
+
+(ert-deftest js-ts-mode-test-indentation ()
+ (skip-unless (treesit-ready-p 'javascript))
+ (ert-test-erts-file (ert-resource-file "js-ts-indents.erts")))
+
(provide 'js-tests)
;;; js-tests.el ends here
diff --git a/test/lisp/progmodes/lua-ts-mode-resources/font-lock.lua b/test/lisp/progmodes/lua-ts-mode-resources/font-lock.lua
new file mode 100644
index 00000000000..93d589e3825
--- /dev/null
+++ b/test/lisp/progmodes/lua-ts-mode-resources/font-lock.lua
@@ -0,0 +1,339 @@
+#!/usr/bin/env lua
+-- ^ font-lock-comment-face
+-- Comment
+-- <- font-lock-comment-delimiter-face
+-- ^ font-lock-comment-face
+--[[
+-- ^ font-lock-comment-face
+Multi-line comment
+-- ^ font-lock-comment-face
+]]
+-- <- font-lock-comment-face
+local line_comment = "comment" -- comment
+-- ^ font-lock-comment-face
+
+-- Definition
+local function f1() end
+-- ^ font-lock-function-name-face
+local f2 = function() end
+-- ^ font-lock-function-name-face
+local tb = { f1 = function() end }
+-- ^ font-lock-function-name-face
+function tb.f2() end
+-- ^ font-lock-function-name-face
+function tb:f3() end
+-- ^ font-lock-function-name-face
+tbl.f4 = function() end
+-- ^ font-lock-function-name-face
+function x.y:z() end
+-- ^ font-lock-function-name-face
+
+-- Keyword
+if true then
+-- <- font-lock-keyword-face
+-- ^ font-lock-keyword-face
+elseif true then
+-- <- font-lock-keyword-face
+else end
+-- <- font-lock-keyword-face
+-- ^ font-lock-keyword-face
+local p = {}
+-- ^ font-lock-keyword-face
+for k,v in pairs({}) do end
+-- <- font-lock-keyword-face
+-- ^ font-lock-keyword-face
+repeat if true then break end until false
+-- <- font-lock-keyword-face
+-- ^ font-lock-keyword-face
+-- ^ font-lock-keyword-face
+while true do end
+-- <- font-lock-keyword-face
+-- ^ font-lock-keyword-face
+function fn() return true end
+-- <- font-lock-keyword-face
+-- ^ font-lock-keyword-face
+goto label1
+-- ^ font-lock-keyword-face
+::label1::
+if true and not false or nil then
+-- ^ font-lock-keyword-face
+-- ^ font-lock-keyword-face
+-- ^ font-lock-keyword-face
+end
+
+-- String
+local _
+_ = "x"
+-- ^ font-lock-string-face
+_ = 'x'
+-- ^ font-lock-string-face
+_ = "x\ty"
+-- ^ font-lock-string-face
+-- ^ font-lock-string-face
+_ = "x\"y"
+-- ^ font-lock-string-face
+-- ^ font-lock-string-face
+_ = 'x\'y'
+-- ^ font-lock-string-face
+-- ^ font-lock-string-face
+_ = "x\z
+ y"
+-- ^ font-lock-string-face
+_ = "x\0900y"
+-- ^ font-lock-string-face
+_ = "x\09y"
+-- ^ font-lock-string-face
+_ = "x\0y"
+-- ^ font-lock-string-face
+_ = "x\u{1f602}y"
+-- ^ font-lock-string-face
+_ = [[x]]
+-- ^ font-lock-string-face
+_ = [=[x]=]
+-- ^ font-lock-string-face
+
+-- Assignment
+local n = 0
+-- ^ font-lock-variable-name-face
+o, p, q = 1, 2, 3
+-- <- font-lock-variable-name-face
+-- ^ font-lock-variable-name-face
+-- ^ font-lock-variable-name-face
+tbl[k] = "A"
+-- ^ font-lock-variable-name-face
+tbl.x = 1
+-- ^ font-lock-variable-name-face
+for i=0,9 do end
+-- ^ font-lock-variable-name-face
+
+-- Constant
+local x <const> = 1
+-- ^ font-lock-constant-face
+local f <close> = io.open('/file')
+-- ^ font-lock-constant-face
+local a, b, c = true, false, nil
+-- ^ font-lock-constant-face
+-- ^ font-lock-constant-face
+-- ^ font-lock-constant-face
+::label2::
+-- ^ font-lock-constant-face
+goto label2
+-- ^ font-lock-constant-face
+
+-- Number
+n = 123
+-- ^ font-lock-number-face
+print(99)
+-- ^ font-lock-number-face
+print(tbl[1])
+-- ^ font-lock-number-face
+
+-- Bracket
+local t = {}
+-- ^ font-lock-bracket-face
+-- ^ font-lock-bracket-face
+print(t[1])
+-- ^ font-lock-bracket-face
+-- ^ font-lock-bracket-face
+-- ^ font-lock-bracket-face
+-- ^ font-lock-bracket-face
+
+-- Builtin
+assert()
+-- <- font-lock-builtin-face
+bit32()
+-- <- font-lock-builtin-face
+collectgarbage()
+-- <- font-lock-builtin-face
+coroutine()
+-- <- font-lock-builtin-face
+debug()
+-- <- font-lock-builtin-face
+dofile()
+-- <- font-lock-builtin-face
+error()
+-- <- font-lock-builtin-face
+getmetatable()
+-- <- font-lock-builtin-face
+io()
+-- <- font-lock-builtin-face
+ipairs()
+-- <- font-lock-builtin-face
+load()
+-- <- font-lock-builtin-face
+loadfile()
+-- <- font-lock-builtin-face
+math()
+-- <- font-lock-builtin-face
+next()
+-- <- font-lock-builtin-face
+os()
+-- <- font-lock-builtin-face
+package()
+-- <- font-lock-builtin-face
+pairs()
+-- <- font-lock-builtin-face
+pcall()
+-- <- font-lock-builtin-face
+print()
+-- <- font-lock-builtin-face
+rawequal()
+-- <- font-lock-builtin-face
+rawget()
+-- <- font-lock-builtin-face
+rawlen()
+-- <- font-lock-builtin-face
+rawset()
+-- <- font-lock-builtin-face
+require()
+-- <- font-lock-builtin-face
+select()
+-- <- font-lock-builtin-face
+setmetatable()
+-- <- font-lock-builtin-face
+string()
+-- <- font-lock-builtin-face
+table()
+-- <- font-lock-builtin-face
+tonumber()
+-- <- font-lock-builtin-face
+tostring()
+-- <- font-lock-builtin-face
+type()
+-- <- font-lock-builtin-face
+utf8()
+-- <- font-lock-builtin-face
+warn()
+-- <- font-lock-builtin-face
+xpcall()
+-- <- font-lock-builtin-face
+print(_G)
+-- ^ font-lock-builtin-face
+print(_VERSION)
+-- ^ font-lock-builtin-face
+f.close()
+-- ^ font-lock-builtin-face
+f.flush()
+-- ^ font-lock-builtin-face
+f.lines()
+-- ^ font-lock-builtin-face
+f.read()
+-- ^ font-lock-builtin-face
+f.seek()
+-- ^ font-lock-builtin-face
+f.setvbuf()
+-- ^ font-lock-builtin-face
+f.write()
+-- ^ font-lock-builtin-face
+
+-- Delimiter
+t = { 1, 2 };
+-- ^ font-lock-delimiter-face
+-- ^ font-lock-delimiter-face
+
+-- Escape
+_ = "x\ty"
+-- ^ font-lock-escape-face
+-- ^ font-lock-escape-face
+_ = "x\"y"
+-- ^ font-lock-escape-face
+-- ^ font-lock-escape-face
+_ = 'x\'y'
+-- ^ font-lock-escape-face
+-- ^ font-lock-escape-face
+_ = "x\z
+ y"
+-- <- font-lock-escape-face
+_ = "x\x5Ay"
+-- ^ font-lock-escape-face
+-- ^ font-lock-escape-face
+_ = "x\0900y"
+-- ^ font-lock-escape-face
+_ = "x\09y"
+-- ^ font-lock-escape-face
+_ = "x\0y"
+-- ^ font-lock-escape-face
+_ = "x\u{1f602}y"
+-- ^ font-lock-escape-face
+-- ^ font-lock-escape-face
+
+-- Function
+func_one()
+-- ^ font-lock-function-call-face
+tbl.func_two()
+-- ^ font-lock-function-call-face
+tbl:func_three()
+-- ^ font-lock-function-call-face
+tbl.f = f4()
+-- ^ font-lock-function-call-face
+
+-- Operator
+local a, b = 1, 2
+-- ^ font-lock-operator-face
+print(a & b)
+-- ^ font-lock-operator-face
+print(a | b)
+-- ^ font-lock-operator-face
+print(a ~ b)
+-- ^ font-lock-operator-face
+print(a << 1)
+-- ^ font-lock-operator-face
+-- ^ font-lock-operator-face
+print(a >> 1)
+-- ^ font-lock-operator-face
+-- ^ font-lock-operator-face
+print(a+b-a*b/a%b^a//b)
+-- ^ font-lock-operator-face
+-- ^ font-lock-operator-face
+-- ^ font-lock-operator-face
+-- ^ font-lock-operator-face
+-- ^ font-lock-operator-face
+-- ^ font-lock-operator-face
+-- ^ font-lock-operator-face
+print(#t)
+-- ^ font-lock-operator-face
+print("h".."at")
+-- ^ font-lock-operator-face
+print(a==b)
+-- ^ font-lock-operator-face
+print(a~=b)
+-- ^ font-lock-operator-face
+print(a<=b)
+-- ^ font-lock-operator-face
+print(a>=b)
+-- ^ font-lock-operator-face
+print(a<b)
+-- ^ font-lock-operator-face
+print(a>b)
+-- ^ font-lock-operator-face
+function ff(...) end
+-- ^ font-lock-operator-face
+
+-- Property
+t = { a=1 }
+-- ^ font-lock-property-name-face
+print(t.a)
+-- ^ font-lock-property-use-face
+
+-- Punctuation
+tbl.f2()
+-- ^ font-lock-punctuation-face
+tbl:f3()
+-- ^ font-lock-punctuation-face
+
+-- Variable
+function fn(x, y) end
+-- ^ font-lock-variable-name-face
+-- ^ font-lock-variable-name-face
+fn(a, b)
+-- ^ font-lock-variable-use-face
+-- ^ font-lock-variable-use-face
+print(a + b)
+-- ^ font-lock-variable-use-face
+-- ^ font-lock-variable-use-face
+print(t[a])
+-- ^ font-lock-variable-use-face
+tbl.f1(p)
+-- ^ font-lock-variable-use-face
+tbl:f2(q)
+-- ^ font-lock-variable-use-face
diff --git a/test/lisp/progmodes/lua-ts-mode-resources/indent.erts b/test/lisp/progmodes/lua-ts-mode-resources/indent.erts
new file mode 100644
index 00000000000..9797467bbe5
--- /dev/null
+++ b/test/lisp/progmodes/lua-ts-mode-resources/indent.erts
@@ -0,0 +1,679 @@
+Code:
+ (lambda ()
+ (setq indent-tabs-mode nil)
+ (setq lua-ts-indent-offset 2)
+ (lua-ts-mode)
+ (indent-region (point-min) (point-max)))
+
+Name: Chunk Indent
+
+=-=
+ print(1)
+ print(2)
+=-=
+print(1)
+print(2)
+=-=-=
+
+Name: Function Indent
+
+=-=
+function f1(n)
+print(n)
+return n + 1
+end
+
+local function f2(n)
+print(n)
+return n * 2
+end
+
+local f3 = function(n)
+print(n)
+return n / 3
+end
+
+function f4(...)
+local f = function (...)
+if ok
+then print(1)
+else print(0)
+end
+end
+return f
+end
+
+function f5(...)
+local f = function (...)
+if ok
+then
+print(1)
+else
+print(0)
+end
+end
+return f
+end
+
+function f6(...)
+local f = function (...)
+if ok then
+print(1)
+else
+print(0)
+end
+end
+return f
+end
+
+;(function ()
+ return true
+ end)()
+=-=
+function f1(n)
+ print(n)
+ return n + 1
+end
+
+local function f2(n)
+ print(n)
+ return n * 2
+end
+
+local f3 = function(n)
+ print(n)
+ return n / 3
+end
+
+function f4(...)
+ local f = function (...)
+ if ok
+ then print(1)
+ else print(0)
+ end
+ end
+ return f
+end
+
+function f5(...)
+ local f = function (...)
+ if ok
+ then
+ print(1)
+ else
+ print(0)
+ end
+ end
+ return f
+end
+
+function f6(...)
+ local f = function (...)
+ if ok then
+ print(1)
+ else
+ print(0)
+ end
+ end
+ return f
+end
+
+;(function ()
+ return true
+end)()
+=-=-=
+
+Name: Conditional Indent
+
+=-=
+if true then
+print(true)
+return 1
+elseif false then
+print(false)
+return -1
+else
+print(nil)
+return 0
+end
+
+if true
+ then
+ print(true)
+ return 1
+ elseif false
+ then
+ print(false)
+ return -1
+ else
+ print(nil)
+ return 0
+end
+
+if true
+ then return 1
+ elseif false
+ then return -1
+ else return 0
+end
+=-=
+if true then
+ print(true)
+ return 1
+elseif false then
+ print(false)
+ return -1
+else
+ print(nil)
+ return 0
+end
+
+if true
+then
+ print(true)
+ return 1
+elseif false
+then
+ print(false)
+ return -1
+else
+ print(nil)
+ return 0
+end
+
+if true
+then return 1
+elseif false
+then return -1
+else return 0
+end
+=-=-=
+
+Name: Loop Indent
+
+=-=
+for k,v in pairs({}) do
+ print(k)
+ print(v)
+end
+
+for i=1,10
+ do print(i)
+end
+
+while n < 10 do
+ n = n + 1
+ print(n)
+end
+
+while n < 10
+ do
+ n = n + 1
+ print(n)
+end
+
+for i=0,9 do
+repeat n = n+1
+ until n > 99
+end
+
+repeat
+z = z * 2
+print(z)
+until z > 12
+
+ for i,x in ipairs(t) do
+ while i < 9
+ do
+ local n = t[x]
+ repeat n = n + 1
+ until n > #t
+ while n < 99
+ do
+ print(n)
+ end
+ end
+ print(t[i])
+ end
+
+do
+local a = b
+print(a + 1)
+end
+=-=
+for k,v in pairs({}) do
+ print(k)
+ print(v)
+end
+
+for i=1,10
+do print(i)
+end
+
+while n < 10 do
+ n = n + 1
+ print(n)
+end
+
+while n < 10
+do
+ n = n + 1
+ print(n)
+end
+
+for i=0,9 do
+ repeat n = n+1
+ until n > 99
+end
+
+repeat
+ z = z * 2
+ print(z)
+until z > 12
+
+for i,x in ipairs(t) do
+ while i < 9
+ do
+ local n = t[x]
+ repeat n = n + 1
+ until n > #t
+ while n < 99
+ do
+ print(n)
+ end
+ end
+ print(t[i])
+end
+
+do
+ local a = b
+ print(a + 1)
+end
+=-=-=
+
+Name: Bracket Indent
+
+=-=
+fn(
+ )
+
+tb={
+ }
+=-=
+fn(
+)
+
+tb={
+}
+=-=-=
+
+Name: Multi-line String Indent
+
+=-=
+local s = [[
+ Multi-line
+ string content
+ ]]
+
+function f()
+ local str = [[
+ multi-line
+ string
+ ]]
+return true
+end
+=-=
+local s = [[
+ Multi-line
+ string content
+ ]]
+
+function f()
+ local str = [[
+ multi-line
+ string
+ ]]
+ return true
+end
+=-=-=
+
+Name: Multi-line Comment Indent
+
+=-=
+--[[
+ Multi-line
+ comment content
+ ]]
+
+function f()
+--[[
+multi-line
+ comment
+ ]]
+ return true
+end
+=-=
+--[[
+ Multi-line
+ comment content
+ ]]
+
+function f()
+--[[
+multi-line
+ comment
+ ]]
+ return true
+end
+=-=-=
+
+Name: Argument Indent
+
+=-=
+ h(
+ "string",
+ 1000
+ )
+
+local p = h(
+"string",
+ 1000
+)
+
+fn(1,
+2,
+ 3)
+
+fn( 1, 2,
+3, 4 )
+
+f({
+x = 1,
+y = 2,
+z = 3,
+})
+
+f({ x = 1,
+y = 2,
+z = 3, })
+
+Test({
+a=1
+})
+
+Test({
+a = 1,
+b = 2,
+},
+nil)
+=-=
+h(
+ "string",
+ 1000
+)
+
+local p = h(
+ "string",
+ 1000
+)
+
+fn(1,
+ 2,
+ 3)
+
+fn( 1, 2,
+ 3, 4 )
+
+f({
+ x = 1,
+ y = 2,
+ z = 3,
+})
+
+f({ x = 1,
+ y = 2,
+ z = 3, })
+
+Test({
+ a=1
+})
+
+Test({
+ a = 1,
+ b = 2,
+ },
+ nil)
+=-=-=
+
+Name: Parameter Indent
+
+=-=
+function f1(
+a,
+b
+)
+print(a,b)
+end
+
+local function f2(a,
+ b)
+print(a,b)
+end
+
+local f3 = function( a, b,
+ c, d )
+print(a,b,c,d)
+end
+=-=
+function f1(
+ a,
+ b
+)
+ print(a,b)
+end
+
+local function f2(a,
+ b)
+ print(a,b)
+end
+
+local f3 = function( a, b,
+ c, d )
+ print(a,b,c,d)
+end
+=-=-=
+
+Name: Table Indent
+
+=-=
+local Other = {
+ First={up={Step=true,Jump=true},
+ down={Step=true,Jump=true},
+ left={Step=true,Jump=true},
+ right={Step=true,Jump=true}},
+ Second={up={Step=true,Jump=true},
+ down={Step=true,Jump=true},
+ left={Step=true,Jump=true},
+ right={Step=true,Jump=true}},
+ Third={up={Goto=true},
+ down={Goto=true},
+ left={Goto=true},
+ right={Goto=true}}
+}
+
+local Other = {
+a = 1,
+ b = 2,
+ c = 3,
+}
+=-=
+local Other = {
+ First={up={Step=true,Jump=true},
+ down={Step=true,Jump=true},
+ left={Step=true,Jump=true},
+ right={Step=true,Jump=true}},
+ Second={up={Step=true,Jump=true},
+ down={Step=true,Jump=true},
+ left={Step=true,Jump=true},
+ right={Step=true,Jump=true}},
+ Third={up={Goto=true},
+ down={Goto=true},
+ left={Goto=true},
+ right={Goto=true}}
+}
+
+local Other = {
+ a = 1,
+ b = 2,
+ c = 3,
+}
+=-=-=
+
+Code:
+ (lambda ()
+ (setq indent-tabs-mode nil)
+ (setq lua-ts-indent-offset 4)
+ (lua-ts-mode)
+ (indent-region (point-min) (point-max)))
+
+Name: End Indent
+
+=-=
+function f(x)
+ for y=1,x.y do
+ for x=1,x.z do
+ if x.y and x.z then
+ if y <= x then
+ y = y + 1
+ end end end end
+ return {x,y} or {math.random(),math.random()}
+ end
+
+for y=1,x.y do
+ for x=1,x.z do
+ if x.y and x.z then
+ if y <= x then
+ y = y + 1
+ end
+ end end end
+=-=
+function f(x)
+ for y=1,x.y do
+ for x=1,x.z do
+ if x.y and x.z then
+ if y <= x then
+ y = y + 1
+ end end end end
+ return {x,y} or {math.random(),math.random()}
+end
+
+for y=1,x.y do
+ for x=1,x.z do
+ if x.y and x.z then
+ if y <= x then
+ y = y + 1
+ end
+end end end
+=-=-=
+
+Name: Nested Function Indent
+
+=-=
+function a(...)
+ return (function (x)
+ return x
+ end)(foo(...))
+end
+
+function b(n)
+ local x = 1
+ return function (i)
+ return function (...)
+ return (function (n, ...)
+ return function (f, ...)
+ return (function (...)
+ if ... and x < 9 then
+ x = x + 1
+ return ...
+ end end)(n(f, ...))
+ end, ...
+ end)(i(...))
+end end end
+
+function c(f)
+ local f1 = function (...)
+ if nil ~= ... then
+ return f(...)
+ end
+ end
+ return function (i)
+ return function (...)
+ local fn = function (n, ...)
+ local x = function (f, ...)
+ return f1(n(f, ...))
+ end
+ return x
+ end
+ return fn(i(...))
+ end
+ end
+end
+
+function d(f)
+ local f1 = function (c, f, ...)
+ if ... then
+ if f(...) then
+ return ...
+ else
+ return c(f, ...)
+ end end end
+ return function (i)
+ return function (...)
+ return (function (n, ...)
+ local function j (f, ...)
+ return f1(j, f, n(f, ...))
+ end
+ return j, ...
+ end)(i(...))
+end end end
+
+function e (n, t)
+ return function (i)
+ return function (...)
+ return (
+ function (n, ...)
+ local x, y, z = 0, {}
+ return (function (f, ...)
+ return (function (i, ...) return i(i, ...) end)(
+ function (i, ...)
+ return f(function (x, ...)
+ return i(i, ...)(x, ...)
+ end, ...)
+ end)
+ end)(function (j)
+ return function(f, ...)
+ return (function (c, f, ...)
+ if ... then
+ if n+1 == x then
+ local y1, x1 = y, x
+ y, x = {}, 0
+ return (function (...)
+ z = ...
+ return ...
+ end)(t(y1-1, x1-1, ...))
+ else
+ x = x - 1
+ return c(f,
+ (function (...)
+ z = ...
+ return ...
+ end)(t(y, x, ...)))
+ end
+ elseif x ~= 0 then
+ x = 0
+ return z, y
+ end end)(j, f, n(f, ...))
+ end end), ...
+ end)(i(...))
+end end end
+=-=-=
diff --git a/test/lisp/progmodes/lua-ts-mode-resources/movement.erts b/test/lisp/progmodes/lua-ts-mode-resources/movement.erts
new file mode 100644
index 00000000000..11e86f12926
--- /dev/null
+++ b/test/lisp/progmodes/lua-ts-mode-resources/movement.erts
@@ -0,0 +1,603 @@
+Code:
+ (lambda ()
+ (lua-ts-mode)
+ (beginning-of-defun 1))
+
+Point-Char: |
+
+Name: beginning-of-defun moves to start of function declaration
+
+=-=
+local function Test()
+ if true then
+ print(1)
+ else
+ print(0)
+ end|
+end
+=-=
+|local function Test()
+ if true then
+ print(1)
+ else
+ print(0)
+ end
+end
+=-=-=
+
+Name: beginning-of-defun moves to start of function definition
+
+=-=
+local t = {
+ f = function()
+ return true
+ end,
+}|
+=-=
+local t = {
+| f = function()
+ return true
+ end,
+}
+=-=-=
+
+Code:
+ (lambda ()
+ (lua-ts-mode)
+ (end-of-defun 1))
+
+Point-Char: |
+
+Name: end-of-defun moves to end of function declaration
+
+=-=
+local function Test()
+ if true then
+ pr|int(1)
+ else
+ print(0)
+ end
+end
+
+local t = Test()
+=-=
+local function Test()
+ if true then
+ print(1)
+ else
+ print(0)
+ end
+end
+|
+local t = Test()
+=-=-=
+
+Name: end-of-defun moves to end of function definition
+
+=-=
+local t = {
+ f = function()
+ re|turn true
+ end,
+}
+=-=
+local t = {
+ f = function()
+ return true
+ end|,
+}
+=-=-=
+
+Code:
+ (lambda ()
+ (lua-ts-mode)
+ (forward-sentence 1))
+
+Point-Char: |
+
+Name: forward-sentence moves over if statements
+
+=-=
+function f()
+ |if true then
+ print(1)
+ elseif false then
+ print(0)
+ else
+ print(2)
+ end
+end
+=-=
+function f()
+ if true then
+ print(1)
+ elseif false then
+ print(0)
+ else
+ print(2)
+ end|
+end
+=-=-=
+
+Name: forward-sentence moves over variable declaration
+
+=-=
+|local n = 1
+
+print(n)
+=-=
+local n = 1|
+
+print(n)
+=-=-=
+
+Name: forward-sentence moves over for statements
+
+=-=
+|for k, v in pairs({}) do
+ print(k, v)
+end
+
+print(1)
+=-=
+for k, v in pairs({}) do
+ print(k, v)
+end|
+
+print(1)
+=-=-=
+
+Name: forward-sentence moves over do statements
+
+=-=
+|do
+ local x = 1
+ local y = 2
+
+ print(x, y)
+end
+
+print(1)
+=-=
+do
+ local x = 1
+ local y = 2
+
+ print(x, y)
+end|
+
+print(1)
+=-=-=
+
+Name: forward-sentence moves over while statements
+
+=-=
+local i = 0
+|while i < 9 do
+ print(i)
+ i = i + 1
+end
+
+print(1)
+=-=
+local i = 0
+while i < 9 do
+ print(i)
+ i = i + 1
+end|
+
+print(1)
+=-=-=
+
+Name: forward-sentence moves over repeat statements
+
+=-=
+local i = 0
+|repeat
+ print(i)
+ i = i + 1
+until i > 9
+
+print(1)
+=-=
+local i = 0
+repeat
+ print(i)
+ i = i + 1
+until i > 9|
+
+print(1)
+=-=-=
+
+Name: forward-sentence moves over function calls
+
+=-=
+|print(1)
+=-=
+print(1)|
+=-=-=
+
+Name: forward-sentence moves over return statements
+
+=-=
+function f()
+ |return math.random()
+end
+=-=
+function f()
+ return math.random()|
+end
+=-=-=
+
+Code:
+ (lambda ()
+ (lua-ts-mode)
+ (forward-sentence 2))
+
+Name: forward-sentence moves over table fields
+
+=-=
+local t = {
+ |a = 1,
+ b = 2,
+}
+=-=
+local t = {
+ a = 1,
+ b = 2|,
+}
+=-=-=
+
+Code:
+ (lambda ()
+ (lua-ts-mode)
+ (backward-sentence 1))
+
+Point-Char: |
+
+Name: backward-sentence moves over if statements
+
+=-=
+function f()
+ if true then
+ print(1)
+ elseif false then
+ print(0)
+ else
+ print(2)
+ end|
+end
+=-=
+function f()
+ |if true then
+ print(1)
+ elseif false then
+ print(0)
+ else
+ print(2)
+ end
+end
+=-=-=
+
+Name: backward-sentence moves over variable declaration
+
+=-=
+local n = 1|
+
+print(n)
+=-=
+|local n = 1
+
+print(n)
+=-=-=
+
+Name: backward-sentence moves over for statements
+
+=-=
+for k, v in pairs({}) do
+ print(k, v)
+end|
+
+print(1)
+=-=
+|for k, v in pairs({}) do
+ print(k, v)
+end
+
+print(1)
+=-=-=
+
+Name: backward-sentence moves over for statements
+
+=-=
+do
+ local x = 1
+ local y = 2
+
+ print(x, y)
+end|
+
+print(1)
+=-=
+|do
+ local x = 1
+ local y = 2
+
+ print(x, y)
+end
+
+print(1)
+=-=-=
+
+Name: backward-sentence moves over while statements
+
+=-=
+local i = 0
+while i < 9 do
+ print(i)
+ i = i + 1
+end|
+
+print(1)
+=-=
+local i = 0
+|while i < 9 do
+ print(i)
+ i = i + 1
+end
+
+print(1)
+=-=-=
+
+Name: backward-sentence moves over repeat statements
+
+=-=
+local i = 0
+repeat
+ print(i)
+ i = i + 1
+until i > 9|
+
+print(1)
+=-=
+local i = 0
+|repeat
+ print(i)
+ i = i + 1
+until i > 9
+
+print(1)
+=-=-=
+
+Name: backward-sentence moves over function calls
+
+=-=
+print(1)|
+=-=
+|print(1)
+=-=-=
+
+Name: backward-sentence moves over return statements
+
+=-=
+function f()
+ return math.random()|
+end
+=-=
+function f()
+ |return math.random()
+end
+=-=-=
+
+Code:
+ (lambda ()
+ (lua-ts-mode)
+ (backward-sentence 2))
+
+Point-Char: |
+
+Name: backward-sentence moves over table fields
+
+=-=
+local t = {
+ a = 1,
+ b = 2|,
+}
+=-=
+local t = {
+ |a = 1,
+ b = 2,
+}
+=-=-=
+
+Code:
+ (lambda ()
+ (lua-ts-mode)
+ (forward-sexp 1))
+
+Point-Char: |
+
+Name: forward-sexp moves over arguments
+
+=-=
+print|(1, 2, 3)
+=-=
+print(1, 2, 3)|
+=-=-=
+
+Name: forward-sexp moves over parameters
+
+=-=
+function f|(a, b) end
+=-=
+function f(a, b)| end
+=-=-=
+
+Name: forward-sexp moves over strings
+
+=-=
+print("|1, 2, 3")
+=-=
+print("1, 2, 3|")
+=-=-=
+
+Name: forward-sexp moves over tables
+
+=-=
+local t = |{ 1,
+ 2,
+ 3 }
+=-=
+local t = { 1,
+ 2,
+ 3 }|
+=-=-=
+
+Name: forward-sexp moves over parenthesized expressions
+
+=-=
+|(function (x) return x + 1 end)(41)
+=-=
+(function (x) return x + 1 end)|(41)
+=-=-=
+
+Name: forward-sexp moves over function declarations
+
+=-=
+|function foo (x)
+ if false then
+ print "foo"
+ elseif true then
+ print "bar"
+ end
+end
+=-=
+function foo (x)
+ if false then
+ print "foo"
+ elseif true then
+ print "bar"
+ end
+end|
+=-=-=
+
+Name: forward-sexp moves over do statements
+
+=-=
+|do
+ print(a + 1)
+end
+=-=
+do
+ print(a + 1)
+end|
+=-=-=
+
+Name: forward-sexp moves over for statements
+
+=-=
+|for k,v in pairs({}) do
+ print(k, v)
+end
+=-=
+for k,v in pairs({}) do
+ print(k, v)
+end|
+=-=-=
+
+Name: forward-sexp moves over repeat statements
+
+=-=
+|repeat
+ n = n + 1
+until n > 10
+=-=
+repeat
+ n = n + 1
+until n > 10|
+=-=-=
+
+Name: forward-sexp moves over while statements
+
+=-=
+|while n < 99
+do
+ n = n+1
+end
+=-=
+while n < 99
+do
+ n = n+1
+end|
+=-=-=
+
+Code:
+ (lambda ()
+ (lua-ts-mode)
+ (backward-sexp 1))
+
+Point-Char: |
+
+Name: backward-sexp moves over arguments
+
+=-=
+print(1, 2, 3)|
+=-=
+print|(1, 2, 3)
+=-=-=
+
+Name: backward-sexp moves over parameters
+
+=-=
+function f(a, b)| end
+=-=
+function f|(a, b) end
+=-=-=
+
+Name: backward-sexp moves over strings
+
+=-=
+print("1, 2, 3|")
+=-=
+print("|1, 2, 3")
+=-=-=
+
+Name: backward-sexp moves over tables
+
+=-=
+local t = { 1,
+ 2,
+ 3 }|
+=-=
+local t = |{ 1,
+ 2,
+ 3 }
+=-=-=
+
+Name: backward-sexp moves over parenthesized expressions
+
+=-=
+(function (x) return x + 1 end)|(41)
+=-=
+|(function (x) return x + 1 end)(41)
+=-=-=
+
+Name: backward-sexp moves over function declarations
+
+=-=
+function foo (x)
+ if false then
+ print "foo"
+ elseif true then
+ print "bar"
+ end
+end|
+=-=
+|function foo (x)
+ if false then
+ print "foo"
+ elseif true then
+ print "bar"
+ end
+end
+=-=-=
diff --git a/test/lisp/progmodes/lua-ts-mode-tests.el b/test/lisp/progmodes/lua-ts-mode-tests.el
new file mode 100644
index 00000000000..565e6f91dbd
--- /dev/null
+++ b/test/lisp/progmodes/lua-ts-mode-tests.el
@@ -0,0 +1,42 @@
+;;; lua-ts-mode-tests.el --- Tests for lua-ts-mode -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2023-2024 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert)
+(require 'ert-font-lock)
+(require 'ert-x)
+(require 'treesit)
+
+(ert-deftest lua-ts-test-indentation ()
+ (skip-unless (treesit-ready-p 'lua))
+ (ert-test-erts-file (ert-resource-file "indent.erts")))
+
+(ert-deftest lua-ts-test-movement ()
+ (skip-unless (treesit-ready-p 'lua))
+ (ert-test-erts-file (ert-resource-file "movement.erts")))
+
+(ert-deftest lua-ts-test-font-lock ()
+ (skip-unless (treesit-ready-p 'lua))
+ (let ((treesit-font-lock-level 4))
+ (ert-font-lock-test-file (ert-resource-file "font-lock.lua") 'lua-ts-mode)))
+
+(provide 'lua-ts-mode-tests)
+
+;;; lua-ts-mode-tests.el ends here
diff --git a/test/lisp/progmodes/octave-tests.el b/test/lisp/progmodes/octave-tests.el
index bb7e3cd6531..8753c7eef0d 100644
--- a/test/lisp/progmodes/octave-tests.el
+++ b/test/lisp/progmodes/octave-tests.el
@@ -1,6 +1,6 @@
;;; octave-tests.el --- Test suite for octave.el -*- lexical-binding:t -*-
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/progmodes/opascal-tests.el b/test/lisp/progmodes/opascal-tests.el
index 25eb2b4c1cd..e3f14def943 100644
--- a/test/lisp/progmodes/opascal-tests.el
+++ b/test/lisp/progmodes/opascal-tests.el
@@ -1,6 +1,6 @@
;;; opascal-tests.el --- tests for opascal.el -*- lexical-binding: t -*-
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/progmodes/pascal-tests.el b/test/lisp/progmodes/pascal-tests.el
index db14a320a70..e7f3ee7cae7 100644
--- a/test/lisp/progmodes/pascal-tests.el
+++ b/test/lisp/progmodes/pascal-tests.el
@@ -1,6 +1,6 @@
;;; pascal-tests.el --- tests for pascal.el -*- lexical-binding: t -*-
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/progmodes/perl-mode-tests.el b/test/lisp/progmodes/perl-mode-tests.el
index 3757ac25547..49320566139 100644
--- a/test/lisp/progmodes/perl-mode-tests.el
+++ b/test/lisp/progmodes/perl-mode-tests.el
@@ -1,6 +1,6 @@
;;; perl-mode-tests.el --- Test for perl-mode -*- lexical-binding: t -*-
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -28,7 +28,24 @@
(font-lock-ensure (point-min) (point-max))
(should (equal (get-text-property 4 'face) 'font-lock-variable-name-face))))
-;;;; Re-use cperl-mode tests
+(ert-deftest perl-test-bug-34245 ()
+ "Test correct indentation after a hanging paren, with and without comments."
+ (with-temp-buffer
+ (perl-mode)
+ (insert "my @foo = (\n\"bar\",\n\"baz\",\n);")
+ (insert "\n\n")
+ (insert "my @ofoo = (\t\t# A comment.\n\"obar\",\n\"obaz\",\n);")
+ (indent-region (point-min) (point-max))
+ (goto-char (point-min))
+ (forward-line)
+ (skip-chars-forward " \t")
+ (should (equal (current-column) perl-indent-level))
+ (search-forward "# A comment.")
+ (forward-line)
+ (skip-chars-forward " \t")
+ (should (equal (current-column) perl-indent-level))))
+
+;;;; Reuse cperl-mode tests
(defvar cperl-test-mode)
(setq cperl-test-mode #'perl-mode)
diff --git a/test/lisp/progmodes/project-tests.el b/test/lisp/progmodes/project-tests.el
index 5a206b67db1..04cdf1dea29 100644
--- a/test/lisp/progmodes/project-tests.el
+++ b/test/lisp/progmodes/project-tests.el
@@ -1,6 +1,6 @@
;;; project-tests.el --- tests for project.el -*- lexical-binding: t; -*-
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
;; Keywords:
@@ -137,6 +137,7 @@ When `project-ignores' includes a name matching project dir."
(project-vc-extra-root-markers '("files-x-tests.*"))
(project (project-current nil dir)))
(should-not (null project))
+ (should (nth 1 project))
(should (string-match-p "/test/lisp/\\'" (project-root project)))))
(ert-deftest project-vc-supports-project-in-different-dir ()
diff --git a/test/lisp/progmodes/ps-mode-tests.el b/test/lisp/progmodes/ps-mode-tests.el
index 3d7408cda10..9bf355900b9 100644
--- a/test/lisp/progmodes/ps-mode-tests.el
+++ b/test/lisp/progmodes/ps-mode-tests.el
@@ -1,6 +1,6 @@
;;; ps-mode-tests.el --- Test suite for ps-mode -*- lexical-binding:t -*-
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/progmodes/python-tests.el b/test/lisp/progmodes/python-tests.el
index 9f935f2748c..1df0c42a0ce 100644
--- a/test/lisp/progmodes/python-tests.el
+++ b/test/lisp/progmodes/python-tests.el
@@ -1,6 +1,6 @@
;;; python-tests.el --- Test suite for python.el -*- lexical-binding:t -*-
-;; Copyright (C) 2013-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -4918,7 +4918,7 @@ import abc
;; Skip the test on macOS, since the standard Python installation uses
;; libedit rather than readline which confuses the running of an inferior
;; interpreter in this case (see bug#59477 and bug#25753).
- (skip-unless (not (eq system-type 'darwin)))
+ (skip-when (eq system-type 'darwin))
(trace-function 'python-shell-output-filter)
(python-tests-with-temp-buffer-with-shell
"
@@ -7299,6 +7299,308 @@ buffer with overlapping strings."
"Unused import a.b.c (unused-import)"
"W0611: Unused import a.b.c (unused-import)"))))))
+;;; python-ts-mode font-lock tests
+
+(defmacro python-ts-tests-with-temp-buffer (contents &rest body)
+ "Create a `python-ts-mode' enabled temp buffer with CONTENTS.
+BODY is code to be executed within the temp buffer. Point is
+always located at the beginning of buffer."
+ (declare (indent 1) (debug t))
+ `(with-temp-buffer
+ (skip-unless (treesit-ready-p 'python))
+ (require 'python)
+ (let ((python-indent-guess-indent-offset nil))
+ (python-ts-mode)
+ (setopt treesit-font-lock-level 3)
+ (insert ,contents)
+ (font-lock-ensure)
+ (goto-char (point-min))
+ ,@body)))
+
+(ert-deftest python-ts-mode-compound-keywords-face ()
+ (dolist (test '("is not" "not in"))
+ (python-ts-tests-with-temp-buffer
+ (concat "t " test " t")
+ (forward-to-word 1)
+ (should (eq (face-at-point) font-lock-keyword-face))
+ (forward-to-word 1)
+ (should (eq (face-at-point) font-lock-keyword-face)))))
+
+(ert-deftest python-ts-mode-named-assignement-face-1 ()
+ (python-ts-tests-with-temp-buffer
+ "var := 3"
+ (should (eq (face-at-point) font-lock-variable-name-face))))
+
+(ert-deftest python-ts-mode-assignement-face-2 ()
+ (python-ts-tests-with-temp-buffer
+ "var, *rest = call()"
+ (dolist (test '("var" "rest"))
+ (search-forward test)
+ (goto-char (match-beginning 0))
+ (should (eq (face-at-point) font-lock-variable-name-face))))
+
+ (python-ts-tests-with-temp-buffer
+ "def func(*args):"
+ (dolist (test '("args"))
+ (search-forward test)
+ (goto-char (match-beginning 0))
+ (should (not (eq (face-at-point) font-lock-variable-name-face))))))
+
+(ert-deftest python-ts-mode-nested-types-face-1 ()
+ (python-ts-tests-with-temp-buffer
+ "def func(v:dict[ list[ tuple[str] ], int | None] | None):"
+ (dolist (test '("dict" "list" "tuple" "str" "int" "None" "None"))
+ (search-forward test)
+ (goto-char (match-beginning 0))
+ (should (eq (face-at-point) font-lock-type-face)))))
+
+(ert-deftest python-ts-mode-union-types-face-1 ()
+ (python-ts-tests-with-temp-buffer
+ "def f(val: tuple[tuple, list[Lvl1 | Lvl2[Lvl3[Lvl4[Lvl5 | None]], Lvl2]]]):"
+ (dolist (test '("tuple" "tuple" "list" "Lvl1" "Lvl2" "Lvl3" "Lvl4" "Lvl5" "None" "Lvl2"))
+ (search-forward test)
+ (goto-char (match-beginning 0))
+ (should (eq (face-at-point) font-lock-type-face)))))
+
+(ert-deftest python-ts-mode-union-types-face-2 ()
+ (python-ts-tests-with-temp-buffer
+ "def f(val: Type0 | Type1[Type2, pack0.Type3] | pack1.pack2.Type4 | None):"
+ (dolist (test '("Type0" "Type1" "Type2" "Type3" "Type4" "None"))
+ (search-forward test)
+ (goto-char (match-beginning 0))
+ (should (eq (face-at-point) font-lock-type-face)))
+
+ (goto-char (point-min))
+ (dolist (test '("pack0" "pack1" "pack2"))
+ (search-forward test)
+ (goto-char (match-beginning 0))
+ (should (not (eq (face-at-point) font-lock-type-face))))))
+
+(ert-deftest python-ts-mode-types-face-1 ()
+ (python-ts-tests-with-temp-buffer
+ "def f(val: Callable[[Type0], (Type1, Type2)]):"
+ (dolist (test '("Callable" "Type0" "Type1" "Type2"))
+ (search-forward test)
+ (goto-char (match-beginning 0))
+ (should (eq (face-at-point) font-lock-type-face)))))
+
+(ert-deftest python-ts-mode-types-face-2 ()
+ (python-ts-tests-with-temp-buffer
+ "def annot3(val:pack0.Type0)->pack1.pack2.pack3.Type1:"
+ (dolist (test '("Type0" "Type1"))
+ (search-forward test)
+ (goto-char (match-beginning 0))
+ (should (eq (face-at-point) font-lock-type-face)))
+ (goto-char (point-min))
+ (dolist (test '("pack0" "pack1" "pack2" "pack3"))
+ (search-forward test)
+ (goto-char (match-beginning 0))
+ (should (not (eq (face-at-point) font-lock-type-face))))))
+
+(ert-deftest python-ts-mode-types-face-3 ()
+ (python-ts-tests-with-temp-buffer
+ "def annot3(val:collections.abc.Iterator[Type0]):"
+ (dolist (test '("Iterator" "Type0"))
+ (search-forward test)
+ (goto-char (match-beginning 0))
+ (should (eq (face-at-point) font-lock-type-face)))
+ (goto-char (point-min))
+ (dolist (test '("collections" "abc"))
+ (search-forward test)
+ (goto-char (match-beginning 0))
+ (should (not (eq (face-at-point) font-lock-type-face))))))
+
+(ert-deftest python-ts-mode-isinstance-type-face-1 ()
+ (python-ts-tests-with-temp-buffer
+ "isinstance(var1, pkg.Type0)
+ isinstance(var2, (str, dict, Type1, type(None)))
+ isinstance(var3, my_type())"
+
+ (dolist (test '("var1" "pkg" "var2" "type" "None" "var3" "my_type"))
+ (let ((case-fold-search nil))
+ (search-forward test))
+ (goto-char (match-beginning 0))
+ (should (not (eq (face-at-point) font-lock-type-face))))
+
+ (goto-char (point-min))
+ (dolist (test '("Type0" "str" "dict" "Type1"))
+ (search-forward test)
+ (goto-char (match-beginning 0))
+ (should (eq (face-at-point) font-lock-type-face)))))
+
+(ert-deftest python-ts-mode-isinstance-type-face-2 ()
+ (python-ts-tests-with-temp-buffer
+ "issubclass(mytype, int|list|collections.abc.Iterable)"
+ (dolist (test '("int" "list" "Iterable"))
+ (search-forward test)
+ (goto-char (match-beginning 0))
+ (should (eq (face-at-point) font-lock-type-face)))))
+
+(ert-deftest python-ts-mode-isinstance-type-face-3 ()
+ (python-ts-tests-with-temp-buffer
+ "issubclass(mytype, typevar1)
+ isinstance(mytype, (Type1, typevar2, tuple, abc.Coll))
+ isinstance(mytype, pkg0.Type2|self.typevar3|typevar4)"
+
+ (dolist (test '("typevar1" "typevar2" "pkg0" "self" "typevar3" "typevar4"))
+ (search-forward test)
+ (goto-char (match-beginning 0))
+ (should (not (eq (face-at-point) font-lock-type-face))))
+
+ (goto-char (point-min))
+ (dolist (test '("Type1" "tuple" "Coll" "Type2"))
+ (search-forward test)
+ (goto-char (match-beginning 0))
+ (should (eq (face-at-point) font-lock-type-face)))))
+
+(ert-deftest python-ts-mode-superclass-type-face ()
+ (python-ts-tests-with-temp-buffer
+ "class Temp(Base1, pack0.Base2, Sequence[T1, T2]):"
+
+ (dolist (test '("Base1" "Base2" "Sequence" "T1" "T2"))
+ (search-forward test)
+ (goto-char (match-beginning 0))
+ (should (eq (face-at-point) font-lock-type-face)))
+
+ (goto-char (point-min))
+ (dolist (test '("pack0"))
+ (search-forward test)
+ (goto-char (match-beginning 0))
+ (should (not (eq (face-at-point) font-lock-type-face))))))
+
+(ert-deftest python-ts-mode-class-patterns-face ()
+ (python-ts-tests-with-temp-buffer
+ "match tt:
+ case str():
+ pass
+ case [Type0() | bytes(b) | pack0.pack1.Type1()]:
+ pass
+ case {'i': int(i), 'f': float() as f}:
+ pass"
+
+ (dolist (test '("str" "Type0" "bytes" "Type1" "int" "float"))
+ (search-forward test)
+ (goto-char (match-beginning 0))
+ (should (eq (face-at-point) font-lock-type-face)))
+
+ (goto-char (point-min))
+ (dolist (test '("pack0" "pack1"))
+ (search-forward test)
+ (goto-char (match-beginning 0))
+ (should (not (eq (face-at-point) font-lock-type-face))))))
+
+(ert-deftest python-ts-mode-dotted-decorator-face-1 ()
+ (python-ts-tests-with-temp-buffer
+ "@pytest.mark.skip
+ @pytest.mark.skip(reason='msg')
+ def test():"
+
+ (dolist (test '("pytest" "mark" "skip" "pytest" "mark" "skip"))
+ (search-forward test)
+ (goto-char (match-beginning 0))
+ (should (eq (face-at-point) font-lock-type-face)))))
+
+(ert-deftest python-ts-mode-dotted-decorator-face-2 ()
+ (python-ts-tests-with-temp-buffer
+ "@pytest.mark.skip(reason='msg')
+ def test():"
+
+ (setopt treesit-font-lock-level 4)
+ (dolist (test '("pytest" "mark" "skip"))
+ (search-forward test)
+ (goto-char (match-beginning 0))
+ (should (eq (face-at-point) font-lock-type-face)))))
+
+(ert-deftest python-ts-mode-builtin-call-face ()
+ (python-ts-tests-with-temp-buffer
+ "all()"
+ ;; enable 'function' feature from 4th level
+ (setopt treesit-font-lock-level 4)
+ (should (eq (face-at-point) font-lock-builtin-face))))
+
+(ert-deftest python-ts-mode-interpolation-nested-string ()
+ (python-ts-tests-with-temp-buffer
+ "t = f\"beg {True + 'string'}\""
+
+ (search-forward "True")
+ (goto-char (match-beginning 0))
+ (should (eq (face-at-point) font-lock-constant-face))
+
+ (goto-char (point-min))
+ (dolist (test '("f" "{" "+" "}"))
+ (search-forward test)
+ (goto-char (match-beginning 0))
+ (should (not (eq (face-at-point) font-lock-string-face))))
+
+
+ (goto-char (point-min))
+ (dolist (test '("beg" "'string'" "\""))
+ (search-forward test)
+ (goto-char (match-beginning 0))
+ (should (eq (face-at-point) font-lock-string-face)))))
+
+(ert-deftest python-ts-mode-level-fontification-wo-interpolation ()
+ (python-ts-tests-with-temp-buffer
+ "t = f\"beg {True + var}\""
+
+ (setopt treesit-font-lock-level 2)
+ (search-forward "f")
+ (goto-char (match-beginning 0))
+ (should (not (eq (face-at-point) font-lock-string-face)))
+
+ (dolist (test '("\"" "beg" "{" "True" "var" "}" "\""))
+ (search-forward test)
+ (goto-char (match-beginning 0))
+ (should (eq (face-at-point) font-lock-string-face)))))
+
+(ert-deftest python-ts-mode-disabled-string-interpolation ()
+ (python-ts-tests-with-temp-buffer
+ "t = f\"beg {True + var}\""
+
+ (unwind-protect
+ (progn
+ (setf (nth 2 treesit-font-lock-feature-list)
+ (remq 'string-interpolation (nth 2 treesit-font-lock-feature-list)))
+ (setopt treesit-font-lock-level 3)
+
+ (search-forward "f")
+ (goto-char (match-beginning 0))
+ (should (not (eq (face-at-point) font-lock-string-face)))
+
+ (dolist (test '("\"" "beg" "{" "True" "var" "}" "\""))
+ (search-forward test)
+ (goto-char (match-beginning 0))
+ (should (eq (face-at-point) font-lock-string-face))))
+
+ (setf (nth 2 treesit-font-lock-feature-list)
+ (append (nth 2 treesit-font-lock-feature-list) '(string-interpolation))))))
+
+(ert-deftest python-ts-mode-interpolation-doc-string ()
+ (python-ts-tests-with-temp-buffer
+ "f\"\"\"beg {'s1' + True + 's2'} end\"\"\""
+
+ (search-forward "True")
+ (goto-char (match-beginning 0))
+ (should (eq (face-at-point) font-lock-constant-face))
+
+ (goto-char (point-min))
+ (dolist (test '("f" "{" "+" "}"))
+ (search-forward test)
+ (goto-char (match-beginning 0))
+ (should (not (eq (face-at-point) font-lock-string-face))))
+
+ (goto-char (point-min))
+ (dolist (test '("\"\"\"" "beg" "end" "\"\"\""))
+ (search-forward test)
+ (goto-char (match-beginning 0))
+ (should (eq (face-at-point) font-lock-doc-face)))
+
+ (goto-char (point-min))
+ (dolist (test '("'s1'" "'s2'"))
+ (search-forward test)
+ (goto-char (match-beginning 0))
+ (should (eq (face-at-point) font-lock-string-face)))))
+
(provide 'python-tests)
;;; python-tests.el ends here
diff --git a/test/lisp/progmodes/ruby-mode-resources/ruby-ts.rb b/test/lisp/progmodes/ruby-mode-resources/ruby-ts.rb
index 4be532a5e9d..8e372de6e45 100644
--- a/test/lisp/progmodes/ruby-mode-resources/ruby-ts.rb
+++ b/test/lisp/progmodes/ruby-mode-resources/ruby-ts.rb
@@ -85,6 +85,10 @@ foo(foo, bar:
foo(foo, :bar =>
tee)
+foo = %w[
+ asd
+]
+
# Local Variables:
# mode: ruby-ts
# ruby-after-operator-indent: t
diff --git a/test/lisp/progmodes/ruby-mode-resources/ruby.rb b/test/lisp/progmodes/ruby-mode-resources/ruby.rb
index 81d0dfd75c9..a411b39a8fc 100644
--- a/test/lisp/progmodes/ruby-mode-resources/ruby.rb
+++ b/test/lisp/progmodes/ruby-mode-resources/ruby.rb
@@ -34,11 +34,11 @@ x = # "tot %q/to"; =
# Regexp after whitelisted method.
"abc".sub /b/, 'd'
-# Don't mismatch "sub" at the end of words.
-a = asub / aslb + bsub / bslb;
+# Don't mistake division for regexp.
+a = sub / aslb + bsub / bslb;
# Highlight the regexp after "if".
-x = toto / foo if /do bar/ =~ "dobar"
+x = toto / foo if / do bar/ =~ "dobar"
# Regexp options are highlighted.
diff --git a/test/lisp/progmodes/ruby-mode-tests.el b/test/lisp/progmodes/ruby-mode-tests.el
index 117385ea3e8..2b8506a7adc 100644
--- a/test/lisp/progmodes/ruby-mode-tests.el
+++ b/test/lisp/progmodes/ruby-mode-tests.el
@@ -1,6 +1,6 @@
;;; ruby-mode-tests.el --- Test suite for ruby-mode -*- lexical-binding:t -*-
-;; Copyright (C) 2012-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2012-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -157,6 +157,18 @@ VALUES-PLIST is a list with alternating index and value elements."
(ert-deftest ruby-regexp-is-not-mistaken-for-slash-symbol ()
(ruby-assert-state "x = /foo:/" 3 nil))
+(ert-deftest ruby-slash-not-regexp-when-surrounded-by-spaces ()
+ (ruby-assert-state "x = index / 3" 3 nil))
+
+(ert-deftest ruby-slash-not-regexp-when-no-spaces ()
+ (ruby-assert-state "x = index/3" 3 nil))
+
+(ert-deftest ruby-regexp-not-division-when-only-space-before ()
+ (ruby-assert-state "x = foo_index /3" 3 ?/))
+
+(ert-deftest ruby-slash-not-regexp-when-only-space-after ()
+ (ruby-assert-state "x = index/ 3" 3 nil))
+
(ert-deftest ruby-indent-simple ()
(ruby-should-indent-buffer
"if foo
diff --git a/test/lisp/progmodes/ruby-ts-mode-tests.el b/test/lisp/progmodes/ruby-ts-mode-tests.el
index 55782f886f6..61ef80eb610 100644
--- a/test/lisp/progmodes/ruby-ts-mode-tests.el
+++ b/test/lisp/progmodes/ruby-ts-mode-tests.el
@@ -1,6 +1,6 @@
;;; ruby-mode-tests.el --- Test suite for ruby-mode -*- lexical-binding:t -*-
-;; Copyright (C) 2023 Free Software Foundation, Inc.
+;; Copyright (C) 2023-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/progmodes/scheme-tests.el b/test/lisp/progmodes/scheme-tests.el
index ce41413e949..08e09883ea5 100644
--- a/test/lisp/progmodes/scheme-tests.el
+++ b/test/lisp/progmodes/scheme-tests.el
@@ -1,6 +1,6 @@
;;; scheme-tests.el --- Test suite for scheme.el -*- lexical-binding:t -*-
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/progmodes/sh-script-resources/sh-indents.erts b/test/lisp/progmodes/sh-script-resources/sh-indents.erts
index 1f92610b3aa..36f4e4c22ab 100644
--- a/test/lisp/progmodes/sh-script-resources/sh-indents.erts
+++ b/test/lisp/progmodes/sh-script-resources/sh-indents.erts
@@ -38,3 +38,10 @@ if test ;then
fi
other
=-=-=
+
+Name: sh-indents5
+
+=-=
+for i do echo 1; done
+for i; do echo 1; done
+=-=-=
diff --git a/test/lisp/progmodes/sh-script-tests.el b/test/lisp/progmodes/sh-script-tests.el
index 52c1303c414..e73d52399d3 100644
--- a/test/lisp/progmodes/sh-script-tests.el
+++ b/test/lisp/progmodes/sh-script-tests.el
@@ -1,6 +1,6 @@
;;; sh-script-tests.el --- Tests for sh-script.el -*- lexical-binding: t; -*-
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -87,4 +87,15 @@
(should-not (test-sh-back "foo;bar"))
(should (test-sh-back "foo#zot")))
+(ert-deftest sh-script-test-do-fontification ()
+ "Test that \"do\" gets fontified correctly, even with no \";\"."
+ (with-temp-buffer
+ (shell-script-mode)
+ (insert "for i do echo 1; done")
+ (font-lock-ensure)
+ (goto-char (point-min))
+ (search-forward "do")
+ (forward-char -1)
+ (should (equal (get-text-property (point) 'face) 'font-lock-keyword-face))))
+
;;; sh-script-tests.el ends here
diff --git a/test/lisp/progmodes/sql-tests.el b/test/lisp/progmodes/sql-tests.el
index b0a1f8b0519..0ba7c31acc5 100644
--- a/test/lisp/progmodes/sql-tests.el
+++ b/test/lisp/progmodes/sql-tests.el
@@ -1,6 +1,6 @@
;;; sql-tests.el --- Tests for sql.el -*- lexical-binding: t; -*-
-;; Copyright (C) 2016-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2016-2024 Free Software Foundation, Inc.
;; Author: Simen Heggestøyl <simenheg@gmail.com>
;; Keywords:
diff --git a/test/lisp/progmodes/subword-tests.el b/test/lisp/progmodes/subword-tests.el
index 278db9287ef..592bc794d8b 100644
--- a/test/lisp/progmodes/subword-tests.el
+++ b/test/lisp/progmodes/subword-tests.el
@@ -1,6 +1,6 @@
;;; subword-tests.el --- Testing the subword rules -*- lexical-binding:t -*-
-;; Copyright (C) 2011-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2011-2024 Free Software Foundation, Inc.
;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
;; Keywords:
diff --git a/test/lisp/progmodes/tcl-tests.el b/test/lisp/progmodes/tcl-tests.el
index 7d3a67d1610..ddb5c4e040b 100644
--- a/test/lisp/progmodes/tcl-tests.el
+++ b/test/lisp/progmodes/tcl-tests.el
@@ -1,6 +1,6 @@
;;; tcl-tests.el --- Test suite for tcl-mode -*- lexical-binding:t -*-
-;; Copyright (C) 2018-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2018-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/progmodes/typescript-ts-mode-resources/indent.erts b/test/lisp/progmodes/typescript-ts-mode-resources/indent.erts
index 146ee76574e..7b6185e0386 100644
--- a/test/lisp/progmodes/typescript-ts-mode-resources/indent.erts
+++ b/test/lisp/progmodes/typescript-ts-mode-resources/indent.erts
@@ -23,6 +23,45 @@ const foo = () => {
}
=-=-=
+Name: Statement indentation without braces
+
+=-=
+const foo = () => {
+ if (true)
+ console.log("if_statement");
+ else if (false)
+ console.log("if_statement");
+ else
+ console.log("else_clause");
+ for (let i = 0; i < 1; i++)
+ console.log("for_statement");
+ for (let i of [true])
+ console.log("for_in_statement");
+ while (false)
+ console.log("while_statement");
+ do
+ console.log("do_statement");
+ while (false)
+};
+=-=-=
+
+Name: Switch statement
+
+=-=
+const foo = (x: string) => {
+ switch (x) {
+ case "a":
+ console.log(x);
+ return 1;
+ case "b":
+ return 2;
+ case "c":
+ default:
+ return 0;
+ }
+};
+=-=-=
+
Code:
(lambda ()
(setq indent-tabs-mode nil)
diff --git a/test/lisp/progmodes/typescript-ts-mode-tests.el b/test/lisp/progmodes/typescript-ts-mode-tests.el
index 126f5e3298f..27b7df714e6 100644
--- a/test/lisp/progmodes/typescript-ts-mode-tests.el
+++ b/test/lisp/progmodes/typescript-ts-mode-tests.el
@@ -1,6 +1,6 @@
;;; typescript-ts-mode-tests.el --- Tests for Tree-sitter-based TypeScript mode -*- lexical-binding: t; -*-
-;; Copyright (C) 2023 Free Software Foundation, Inc.
+;; Copyright (C) 2023-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/progmodes/which-func-tests.el b/test/lisp/progmodes/which-func-tests.el
new file mode 100644
index 00000000000..0baee576463
--- /dev/null
+++ b/test/lisp/progmodes/which-func-tests.el
@@ -0,0 +1,58 @@
+;;; which-func-tests.el --- tests for which-func -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2023-2024 Free Software Foundation, Inc.
+
+;; Author: Spencer Baugh <sbaugh@catern.com>
+
+;; This file is part of GNU Emacs.
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+(require 'ert)
+(require 'which-func)
+
+(ert-deftest which-func-tests-toggle ()
+ (let ((which-func-display 'mode-and-header) buf-code buf-not)
+ (setq buf-code (find-file-noselect "which-func-tests.el"))
+ (setq buf-not (get-buffer-create "fundamental"))
+ (with-current-buffer buf-code
+ (should-not which-func-mode) (should-not header-line-format))
+ (with-current-buffer buf-not
+ (should-not which-func-mode) (should-not header-line-format))
+ (which-function-mode 1)
+ (with-current-buffer buf-code
+ (should which-func-mode) (should header-line-format))
+ (with-current-buffer buf-not
+ (should-not which-func-mode) (should-not header-line-format))
+ (which-function-mode -1)
+ ;; which-func-mode stays set even when which-function-mode is off.
+ (with-current-buffer buf-code
+ (should which-func-mode) (should-not header-line-format))
+ (with-current-buffer buf-not
+ (should-not which-func-mode) (should-not header-line-format))
+ (kill-buffer buf-code)
+ (kill-buffer buf-not)
+ (which-function-mode 1)
+ (setq buf-code (find-file-noselect "which-func-tests.el"))
+ (setq buf-not (get-buffer-create "fundamental"))
+ (with-current-buffer buf-code
+ (should which-func-mode) (should header-line-format))
+ (with-current-buffer buf-not
+ (should-not which-func-mode) (should-not header-line-format))))
+
+(provide 'which-func-tests)
+;;; which-func-tests.el ends here
diff --git a/test/lisp/progmodes/xref-tests.el b/test/lisp/progmodes/xref-tests.el
index e74f38cb616..89051256273 100644
--- a/test/lisp/progmodes/xref-tests.el
+++ b/test/lisp/progmodes/xref-tests.el
@@ -1,6 +1,6 @@
;;; xref-tests.el --- tests for xref -*- lexical-binding:t -*-
-;; Copyright (C) 2016-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2016-2024 Free Software Foundation, Inc.
;; Author: Dmitry Gutov <dgutov@yandex.ru>
diff --git a/test/lisp/ps-print-tests.el b/test/lisp/ps-print-tests.el
index 05a74ebf241..bb1cd3f1891 100644
--- a/test/lisp/ps-print-tests.el
+++ b/test/lisp/ps-print-tests.el
@@ -1,6 +1,6 @@
;;; ps-print-tests.el --- Test suite for ps-print.el -*- lexical-binding: t; -*-
-;; Copyright (C) 2015-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2024 Free Software Foundation, Inc.
;; Author: Phillip Lord <phillip.lord@russet.org.uk>
diff --git a/test/lisp/register-tests.el b/test/lisp/register-tests.el
index 6283d1c31e0..bbb470c0aa1 100644
--- a/test/lisp/register-tests.el
+++ b/test/lisp/register-tests.el
@@ -1,6 +1,6 @@
;;; register-tests.el --- tests for register.el -*- lexical-binding: t-*-
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
;; Author: Tino Calancha <tino.calancha@gmail.com>
;; Keywords:
diff --git a/test/lisp/repeat-tests.el b/test/lisp/repeat-tests.el
index 64a7ba2cde9..4e86510f19b 100644
--- a/test/lisp/repeat-tests.el
+++ b/test/lisp/repeat-tests.el
@@ -1,6 +1,6 @@
;;; repeat-tests.el --- Tests for repeat.el -*- lexical-binding: t; -*-
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
;; Author: Juri Linkov <juri@linkov.net>
diff --git a/test/lisp/replace-tests.el b/test/lisp/replace-tests.el
index 899c3cb3c6c..11260204750 100644
--- a/test/lisp/replace-tests.el
+++ b/test/lisp/replace-tests.el
@@ -1,6 +1,6 @@
;;; replace-tests.el --- tests for replace.el. -*- lexical-binding:t -*-
-;; Copyright (C) 2010-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2010-2024 Free Software Foundation, Inc.
;; Author: Nicolas Richard <youngfrog@members.fsf.org>
;; Author: Juri Linkov <juri@jurta.org>
diff --git a/test/lisp/rot13-tests.el b/test/lisp/rot13-tests.el
index 788a80f368c..8025081a6e5 100644
--- a/test/lisp/rot13-tests.el
+++ b/test/lisp/rot13-tests.el
@@ -1,6 +1,6 @@
;;; rot13-tests.el --- Tests for rot13.el -*- lexical-binding: t; -*-
-;; Copyright (C) 2016-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2016-2024 Free Software Foundation, Inc.
;; Author: Simen Heggestøyl <simenheg@gmail.com>
;; Keywords:
diff --git a/test/lisp/saveplace-tests.el b/test/lisp/saveplace-tests.el
index 3c0b14c8c03..dca888555cc 100644
--- a/test/lisp/saveplace-tests.el
+++ b/test/lisp/saveplace-tests.el
@@ -1,6 +1,6 @@
;;; saveplace-tests.el --- Tests for saveplace.el -*- lexical-binding:t -*-
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
;; Author: Stefan Kangas <stefankangas@gmail.com>
diff --git a/test/lisp/scroll-lock-tests.el b/test/lisp/scroll-lock-tests.el
index b8d3d82bd5b..288693f72d2 100644
--- a/test/lisp/scroll-lock-tests.el
+++ b/test/lisp/scroll-lock-tests.el
@@ -1,6 +1,6 @@
;;; scroll-lock-tests.el --- Test suite for scroll-lock -*- lexical-binding: t -*-
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/server-tests.el b/test/lisp/server-tests.el
index de1aa80c272..420338346f1 100644
--- a/test/lisp/server-tests.el
+++ b/test/lisp/server-tests.el
@@ -1,6 +1,6 @@
;;; server-tests.el --- Emacs server test suite -*- lexical-binding:t -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/ses-tests.el b/test/lisp/ses-tests.el
index a941605a4d8..be6784be7a0 100644
--- a/test/lisp/ses-tests.el
+++ b/test/lisp/ses-tests.el
@@ -1,6 +1,6 @@
-;;; ses-tests.el --- Tests for ses.el -*- lexical-binding: t; -*-
+;;; SES-tests.el --- Tests for ses.el -*- lexical-binding: t; -*-
-;; Copyright (C) 2015-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2024 Free Software Foundation, Inc.
;; Author: Vincent Belaïche <vincentb1@users.sourceforge.net>
@@ -241,6 +241,28 @@ to `ses--bar' and inserting a row, makes A2 value empty, and `ses--bar' equal to
(ses-command-hook)
(should (eq (ses--cell-at-pos (point)) 'ses--toto)))))
+(ert-deftest ses-set-formula-write-cells-with-changed-references ()
+ "Test fix of bug#5852.
+When setting a formula has some cell with changed references, this
+cell has to be rewritten to data area."
+ (let ((ses-initial-size '(4 . 3))
+ ses-after-entry-functions beg)
+ (with-temp-buffer
+ (ses-mode)
+ (dolist (c '((0 1 1); B1
+ (1 0 2) (1 1 (+ B1 A2)); A2 B2
+ (2 0 4); A3
+ (3 0 3) (3 1 (+ B2 A4))));A4 B4
+ (apply 'ses-cell-set-formula c)
+ (apply 'ses-calculate-cell (list (car c) (cadr c) nil)))
+ (ses-cell-set-formula 2 1 '(+ B2 A3)); B3
+ (ses-command-hook)
+ (ses-cell-set-formula 3 1 (+ B3 A4)); B4
+ (ses-command-hook)
+ (should (equal (ses-cell-references 1 1) '(B3)))
+ (ses-mode)
+ (should (equal (ses-cell-references 1 1) '(B3))))))
+
(provide 'ses-tests)
;;; ses-tests.el ends here
diff --git a/test/lisp/shadowfile-tests.el b/test/lisp/shadowfile-tests.el
index 5edba039032..4485c73a7bc 100644
--- a/test/lisp/shadowfile-tests.el
+++ b/test/lisp/shadowfile-tests.el
@@ -1,6 +1,6 @@
;;; shadowfile-tests.el --- Tests of shadowfile -*- lexical-binding:t -*-
-;; Copyright (C) 2018-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2018-2024 Free Software Foundation, Inc.
;; Author: Michael Albinus <michael.albinus@gmx.de>
@@ -101,7 +101,7 @@ Per definition, all files are identical on the different hosts of
a cluster (or site). This is not tested here; it must be
guaranteed by the originator of a cluster definition."
:tags '(:expensive-test)
- (skip-unless (not (memq system-type '(windows-nt ms-dos))))
+ (skip-when (memq system-type '(windows-nt ms-dos)))
(skip-unless (file-remote-p ert-remote-temporary-file-directory))
(let ((text-quoting-style 'grave) ;; We inspect the *Messages* buffer!
@@ -219,7 +219,7 @@ guaranteed by the originator of a cluster definition."
Per definition, all files are identical on the different hosts of
a cluster (or site). This is not tested here; it must be
guaranteed by the originator of a cluster definition."
- (skip-unless (not (memq system-type '(windows-nt ms-dos))))
+ (skip-when (memq system-type '(windows-nt ms-dos)))
(skip-unless (file-remote-p ert-remote-temporary-file-directory))
(let ((shadow-info-file shadow-test-info-file)
@@ -320,7 +320,7 @@ guaranteed by the originator of a cluster definition."
(ert-deftest shadow-test02-files ()
"Check file manipulation functions."
- (skip-unless (not (memq system-type '(windows-nt ms-dos))))
+ (skip-when (memq system-type '(windows-nt ms-dos)))
(skip-unless (file-remote-p ert-remote-temporary-file-directory))
(let ((shadow-info-file shadow-test-info-file)
@@ -391,7 +391,7 @@ guaranteed by the originator of a cluster definition."
(ert-deftest shadow-test03-expand-cluster-in-file-name ()
"Check canonical file name of a cluster or site."
- (skip-unless (not (memq system-type '(windows-nt ms-dos))))
+ (skip-when (memq system-type '(windows-nt ms-dos)))
(skip-unless (file-remote-p ert-remote-temporary-file-directory))
(let ((shadow-info-file shadow-test-info-file)
@@ -456,7 +456,7 @@ guaranteed by the originator of a cluster definition."
(ert-deftest shadow-test04-contract-file-name ()
"Check canonical file name of a cluster or site."
- (skip-unless (not (memq system-type '(windows-nt ms-dos))))
+ (skip-when (memq system-type '(windows-nt ms-dos)))
(skip-unless (file-remote-p ert-remote-temporary-file-directory))
(let ((shadow-info-file shadow-test-info-file)
@@ -511,7 +511,7 @@ guaranteed by the originator of a cluster definition."
(ert-deftest shadow-test05-file-match ()
"Check `shadow-same-site' and `shadow-file-match'."
- (skip-unless (not (memq system-type '(windows-nt ms-dos))))
+ (skip-when (memq system-type '(windows-nt ms-dos)))
(skip-unless (file-remote-p ert-remote-temporary-file-directory))
(let ((shadow-info-file shadow-test-info-file)
@@ -563,7 +563,7 @@ guaranteed by the originator of a cluster definition."
(ert-deftest shadow-test06-literal-groups ()
"Check literal group definitions."
- (skip-unless (not (memq system-type '(windows-nt ms-dos))))
+ (skip-when (memq system-type '(windows-nt ms-dos)))
(skip-unless (file-remote-p ert-remote-temporary-file-directory))
(let ((shadow-info-file shadow-test-info-file)
@@ -648,7 +648,7 @@ guaranteed by the originator of a cluster definition."
(ert-deftest shadow-test07-regexp-groups ()
"Check regexp group definitions."
- (skip-unless (not (memq system-type '(windows-nt ms-dos))))
+ (skip-when (memq system-type '(windows-nt ms-dos)))
(skip-unless (file-remote-p ert-remote-temporary-file-directory))
(let ((shadow-info-file shadow-test-info-file)
@@ -710,7 +710,7 @@ guaranteed by the originator of a cluster definition."
(ert-deftest shadow-test08-shadow-todo ()
"Check that needed shadows are added to todo."
- (skip-unless (not (memq system-type '(windows-nt ms-dos))))
+ (skip-when (memq system-type '(windows-nt ms-dos)))
(skip-unless (file-remote-p ert-remote-temporary-file-directory))
(skip-unless (file-writable-p ert-remote-temporary-file-directory))
@@ -855,7 +855,7 @@ guaranteed by the originator of a cluster definition."
(ert-deftest shadow-test09-shadow-copy-files ()
"Check that needed shadow files are copied."
:tags '(:expensive-test)
- (skip-unless (not (memq system-type '(windows-nt ms-dos))))
+ (skip-when (memq system-type '(windows-nt ms-dos)))
(skip-unless (file-remote-p ert-remote-temporary-file-directory))
(skip-unless (file-writable-p ert-remote-temporary-file-directory))
diff --git a/test/lisp/shell-tests.el b/test/lisp/shell-tests.el
index ddddfdb2e0f..9bdf6b1c0eb 100644
--- a/test/lisp/shell-tests.el
+++ b/test/lisp/shell-tests.el
@@ -1,6 +1,6 @@
;;; shell-tests.el --- Tests for shell.el -*- lexical-binding:t -*-
-;; Copyright (C) 2010-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2010-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/simple-tests.el b/test/lisp/simple-tests.el
index 7dabb735522..afd75786804 100644
--- a/test/lisp/simple-tests.el
+++ b/test/lisp/simple-tests.el
@@ -1,6 +1,6 @@
;;; simple-tests.el --- Tests for simple.el -*- lexical-binding: t; -*-
-;; Copyright (C) 2015-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2024 Free Software Foundation, Inc.
;; Author: Artur Malabarba <bruce.connor.am@gmail.com>
@@ -742,7 +742,7 @@ See Bug#21722."
(ert-deftest eval-expression-print-format-sym-echo ()
;; We can only check the echo area when running interactive.
- (skip-unless (not noninteractive))
+ (skip-when noninteractive)
(with-temp-buffer
(cl-letf (((symbol-function 'read--expression) (lambda (&rest _) t)))
(let ((current-prefix-arg nil))
@@ -763,7 +763,7 @@ See Bug#21722."
(should (equal (buffer-string) "65 (#o101, #x41, ?A)"))))))
(ert-deftest eval-expression-print-format-small-int-echo ()
- (skip-unless (not noninteractive))
+ (skip-when noninteractive)
(with-temp-buffer
(cl-letf (((symbol-function 'read--expression) (lambda (&rest _) ?A)))
(let ((current-prefix-arg nil))
@@ -789,7 +789,7 @@ See Bug#21722."
(should (equal (buffer-string) "66 (#o102, #x42, ?B)"))))))
(ert-deftest eval-expression-print-format-large-int-echo ()
- (skip-unless (not noninteractive))
+ (skip-when noninteractive)
(with-temp-buffer
(cl-letf (((symbol-function 'read--expression) (lambda (&rest _) ?B))
(eval-expression-print-maximum-character ?A))
diff --git a/test/lisp/so-long-tests/autoload-longlines-mode-tests.el b/test/lisp/so-long-tests/autoload-longlines-mode-tests.el
index f015103eecb..771f6c3085a 100644
--- a/test/lisp/so-long-tests/autoload-longlines-mode-tests.el
+++ b/test/lisp/so-long-tests/autoload-longlines-mode-tests.el
@@ -1,6 +1,6 @@
;;; autoload-longlines-mode-tests.el --- Test suite for so-long.el -*- lexical-binding: t; -*-
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
;; Author: Phil Sainty <psainty@orcon.net.nz>
;; Keywords: convenience
diff --git a/test/lisp/so-long-tests/autoload-major-mode-tests.el b/test/lisp/so-long-tests/autoload-major-mode-tests.el
index a3bed852f60..baa50275472 100644
--- a/test/lisp/so-long-tests/autoload-major-mode-tests.el
+++ b/test/lisp/so-long-tests/autoload-major-mode-tests.el
@@ -1,6 +1,6 @@
;;; autoload-major-mode-tests.el --- Test suite for so-long.el -*- lexical-binding: t; -*-
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
;; Author: Phil Sainty <psainty@orcon.net.nz>
;; Keywords: convenience
diff --git a/test/lisp/so-long-tests/autoload-minor-mode-tests.el b/test/lisp/so-long-tests/autoload-minor-mode-tests.el
index c4545c8dd0b..23d9a433110 100644
--- a/test/lisp/so-long-tests/autoload-minor-mode-tests.el
+++ b/test/lisp/so-long-tests/autoload-minor-mode-tests.el
@@ -1,6 +1,6 @@
;;; autoload-minor-mode-tests.el --- Test suite for so-long.el -*- lexical-binding: t; -*-
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
;; Author: Phil Sainty <psainty@orcon.net.nz>
;; Keywords: convenience
diff --git a/test/lisp/so-long-tests/so-long-tests-helpers.el b/test/lisp/so-long-tests/so-long-tests-helpers.el
index 21f96602fbe..324cbbefed3 100644
--- a/test/lisp/so-long-tests/so-long-tests-helpers.el
+++ b/test/lisp/so-long-tests/so-long-tests-helpers.el
@@ -1,6 +1,6 @@
;;; so-long-tests-helpers.el --- Test suite for so-long.el -*- lexical-binding: t; -*-
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
;; Author: Phil Sainty <psainty@orcon.net.nz>
;; Keywords: convenience
diff --git a/test/lisp/so-long-tests/so-long-tests.el b/test/lisp/so-long-tests/so-long-tests.el
index d725c07d881..b9326ce54ba 100644
--- a/test/lisp/so-long-tests/so-long-tests.el
+++ b/test/lisp/so-long-tests/so-long-tests.el
@@ -1,6 +1,6 @@
;;; so-long-tests.el --- Test suite for so-long.el -*- lexical-binding: t; -*-
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
;; Author: Phil Sainty <psainty@orcon.net.nz>
;; Keywords: convenience
diff --git a/test/lisp/so-long-tests/spelling-tests.el b/test/lisp/so-long-tests/spelling-tests.el
index 5e5d1d34c71..6fb5f2d5f58 100644
--- a/test/lisp/so-long-tests/spelling-tests.el
+++ b/test/lisp/so-long-tests/spelling-tests.el
@@ -1,6 +1,6 @@
;;; spelling-tests.el --- Test suite for so-long.el -*- lexical-binding: t; -*-
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
;; Author: Phil Sainty <psainty@orcon.net.nz>
;; Keywords: convenience
diff --git a/test/lisp/sort-tests.el b/test/lisp/sort-tests.el
index d8af5595a5e..bbf349350dd 100644
--- a/test/lisp/sort-tests.el
+++ b/test/lisp/sort-tests.el
@@ -1,6 +1,6 @@
;;; sort-tests.el --- Tests for sort.el -*- lexical-binding: t; -*-
-;; Copyright (C) 2015-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2024 Free Software Foundation, Inc.
;; Author: Artur Malabarba <bruce.connor.am@gmail.com>
diff --git a/test/lisp/soundex-tests.el b/test/lisp/soundex-tests.el
index 47d6394df03..afe2a56ebd9 100644
--- a/test/lisp/soundex-tests.el
+++ b/test/lisp/soundex-tests.el
@@ -1,6 +1,6 @@
;;; soundex-tests.el --- tests for soundex.el -*- lexical-binding: t -*-
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
;; Maintainer: emacs-devel@gnu.org
diff --git a/test/lisp/startup-tests.el b/test/lisp/startup-tests.el
index 3e71d8ccec5..46654d1a80f 100644
--- a/test/lisp/startup-tests.el
+++ b/test/lisp/startup-tests.el
@@ -1,6 +1,6 @@
;;; startup-tests.el --- unit tests for startup.el -*- lexical-binding: t; -*-
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
;; Author: Philipp Stephani <phst@google.com>
diff --git a/test/lisp/subr-tests.el b/test/lisp/subr-tests.el
index 0d409cead26..4e3f743cc93 100644
--- a/test/lisp/subr-tests.el
+++ b/test/lisp/subr-tests.el
@@ -1,6 +1,6 @@
;;; subr-tests.el --- Tests for subr.el -*- lexical-binding:t -*-
-;; Copyright (C) 2015-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2024 Free Software Foundation, Inc.
;; Author: Oleh Krehel <ohwoeowho@gmail.com>,
;; Nicolas Petton <nicolas@petton.fr>
@@ -345,18 +345,54 @@
;;;; Mode hooks.
-(defalias 'subr-tests--parent-mode
- (if (fboundp 'prog-mode) 'prog-mode 'fundamental-mode))
+(defalias 'subr-tests--parent-mode #'prog-mode)
+(define-derived-mode subr-tests--derived-mode-1 prog-mode "test")
+(define-derived-mode subr-tests--derived-mode-2 subr-tests--parent-mode "test")
(ert-deftest provided-mode-derived-p ()
;; base case: `derived-mode' directly derives `prog-mode'
- (should (progn
- (define-derived-mode derived-mode prog-mode "test")
- (provided-mode-derived-p 'derived-mode 'prog-mode)))
- ;; edge case: `derived-mode' derives an alias of `prog-mode'
- (should (progn
- (define-derived-mode derived-mode subr-tests--parent-mode "test")
- (provided-mode-derived-p 'derived-mode 'prog-mode))))
+ (should (provided-mode-derived-p 'subr-tests--derived-mode-1 'prog-mode))
+ ;; Edge cases: aliases along the derivation.
+ (should (provided-mode-derived-p 'subr-tests--parent-mode
+ 'subr-tests--parent-mode))
+ (should (provided-mode-derived-p 'subr-tests--derived-mode-2
+ 'subr-tests--parent-mode))
+ (should (provided-mode-derived-p 'subr-tests--derived-mode-2 'prog-mode)))
+
+
+(define-derived-mode subr-tests--mode-A subr-tests--derived-mode-1 "t")
+(define-derived-mode subr-tests--mode-B subr-tests--mode-A "t")
+(defalias 'subr-tests--mode-C #'subr-tests--mode-B)
+(derived-mode-add-parents 'subr-tests--mode-A '(subr-tests--mode-C))
+
+(ert-deftest subr-tests--derived-mode-add-parents ()
+ ;; The Right Answer is somewhat unclear in the presence of cycles,
+ ;; but let's make sure we get tolerable answers.
+ ;; FIXME: Currently `prog-mode' doesn't always end up at the end :-(
+ (let ((set-equal (lambda (a b)
+ (not (or (cl-set-difference a b)
+ (cl-set-difference b a))))))
+ (dolist (mode '(subr-tests--mode-A subr-tests--mode-B subr-tests--mode-C))
+ (should (eq (derived-mode-all-parents mode)
+ (derived-mode-all-parents mode)))
+ (should (eq mode (car (derived-mode-all-parents mode))))
+ (should (funcall set-equal
+ (derived-mode-all-parents mode)
+ '(subr-tests--mode-A subr-tests--mode-B prog-mode
+ subr-tests--mode-C subr-tests--derived-mode-1))))))
+
+(ert-deftest subr-tests--merge-ordered-lists ()
+ (should (equal (merge-ordered-lists
+ '((B A) (C A) (D B) (E D C))
+ (lambda (_) (error "cycle")))
+ '(E D B C A)))
+ (should (equal (merge-ordered-lists
+ '((E D C) (B A) (C A) (D B))
+ (lambda (_) (error "cycle")))
+ '(E D C B A)))
+ (should-error (merge-ordered-lists
+ '((E C D) (B A) (A C) (D B))
+ (lambda (_) (error "cycle")))))
(ert-deftest number-sequence-test ()
(should (= (length
diff --git a/test/lisp/tab-bar-tests.el b/test/lisp/tab-bar-tests.el
index 543bb8717fe..aa8384b24e8 100644
--- a/test/lisp/tab-bar-tests.el
+++ b/test/lisp/tab-bar-tests.el
@@ -1,6 +1,6 @@
;;; tab-bar-tests.el --- Tests for tab-bar.el -*- lexical-binding: t; -*-
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
;; Author: Juri Linkov <juri@linkov.net>
diff --git a/test/lisp/tabify-tests.el b/test/lisp/tabify-tests.el
index 5ff2f311296..f8348e52386 100644
--- a/test/lisp/tabify-tests.el
+++ b/test/lisp/tabify-tests.el
@@ -1,6 +1,6 @@
;;; tabify-tests.el --- tests for tabify.el -*- lexical-binding: t -*-
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
;; Author: Stefan Kangas <stefankangas@gmail.com>
diff --git a/test/lisp/tar-mode-tests.el b/test/lisp/tar-mode-tests.el
index 919602ecef2..b40cd39d112 100644
--- a/test/lisp/tar-mode-tests.el
+++ b/test/lisp/tar-mode-tests.el
@@ -1,6 +1,6 @@
;;; tar-mode-tests.el --- Test suite for tar-mode. -*- lexical-binding: t -*-
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/tempo-tests.el b/test/lisp/tempo-tests.el
index 89edccf4fa7..ba3ca670286 100644
--- a/test/lisp/tempo-tests.el
+++ b/test/lisp/tempo-tests.el
@@ -1,6 +1,6 @@
;;; tempo-tests.el --- Test suite for tempo.el -*- lexical-binding: t; -*-
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
;; Author: Federico Tedin <federicotedin@gmail.com>
;; Keywords: abbrev
diff --git a/test/lisp/term-tests.el b/test/lisp/term-tests.el
index ee2bb6574ae..f5209d6f580 100644
--- a/test/lisp/term-tests.el
+++ b/test/lisp/term-tests.el
@@ -1,6 +1,6 @@
;;; term-tests.el --- tests for term.el -*- lexical-binding: t -*-
-;; Copyright (C) 2017, 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017, 2019-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -110,7 +110,7 @@
(buffer-substring (point-min) (point-max))))))
(ert-deftest term-simple-lines ()
- (skip-unless (not (memq system-type '(windows-nt ms-dos))))
+ (skip-when (memq system-type '(windows-nt ms-dos)))
(let ((str "\
first line\r
next line\r\n"))
@@ -118,14 +118,14 @@ next line\r\n"))
(string-replace "\r" "" str)))))
(ert-deftest term-carriage-return ()
- (skip-unless (not (memq system-type '(windows-nt ms-dos))))
+ (skip-when (memq system-type '(windows-nt ms-dos)))
(let ((str "\
first line\r_next line\r\n"))
(should (equal (term-test-screen-from-input 40 12 str)
"_next line\n"))))
(ert-deftest term-line-wrap ()
- (skip-unless (not (memq system-type '(windows-nt ms-dos))))
+ (skip-when (memq system-type '(windows-nt ms-dos)))
(should (string-match-p
;; Don't be strict about trailing whitespace.
"\\`a\\{40\\}\na\\{20\\} *\\'"
@@ -137,7 +137,7 @@ first line\r_next line\r\n"))
(list str str))))))
(ert-deftest term-colors ()
- (skip-unless (not (memq system-type '(windows-nt ms-dos))))
+ (skip-when (memq system-type '(windows-nt ms-dos)))
(pcase-dolist (`(,str ,expected) ansi-test-strings)
(let ((result (term-test-screen-from-input 40 12 str)))
(should (equal result expected))
@@ -145,7 +145,7 @@ first line\r_next line\r\n"))
(text-properties-at 0 expected))))))
(ert-deftest term-colors-bold-is-bright ()
- (skip-unless (not (memq system-type '(windows-nt ms-dos))))
+ (skip-when (memq system-type '(windows-nt ms-dos)))
(let ((ansi-color-bold-is-bright t))
(pcase-dolist (`(,str ,expected ,bright-expected) ansi-test-strings)
(let ((expected (or bright-expected expected))
@@ -155,7 +155,7 @@ first line\r_next line\r\n"))
(text-properties-at 0 expected)))))))
(ert-deftest term-cursor-movement ()
- (skip-unless (not (memq system-type '(windows-nt ms-dos))))
+ (skip-when (memq system-type '(windows-nt ms-dos)))
;; Absolute positioning.
(should (equal "ab\ncd"
(term-test-screen-from-input
@@ -186,7 +186,7 @@ first line\r_next line\r\n"))
"\e[D\e[Da")))))
(ert-deftest term-scrolling-region ()
- (skip-unless (not (memq system-type '(windows-nt ms-dos))))
+ (skip-when (memq system-type '(windows-nt ms-dos)))
(should (equal "\
line3
line4
@@ -338,7 +338,7 @@ line6\r
line7")))))
(ert-deftest term-set-directory ()
- (skip-unless (not (memq system-type '(windows-nt ms-dos))))
+ (skip-when (memq system-type '(windows-nt ms-dos)))
(let ((term-ansi-at-user (user-real-login-name)))
(should (equal (term-test-screen-from-input
40 12 "\eAnSiTc /foo/\n" 'default-directory)
@@ -354,7 +354,7 @@ A real-life example is the default zsh prompt which writes spaces
to the end of line (triggering line-wrapping state), and then
sends a carriage return followed by another space to overwrite
the first character of the line."
- (skip-unless (not (memq system-type '(windows-nt ms-dos))))
+ (skip-when (memq system-type '(windows-nt ms-dos)))
(let* ((width 10)
(strs (list "x" (make-string (1- width) ?_)
"\r_")))
@@ -364,7 +364,7 @@ the first character of the line."
(ert-deftest term-to-margin ()
"Test cursor movement at the scroll margin.
This is a reduced example from GNU nano's initial screen."
- (skip-unless (not (memq system-type '(windows-nt ms-dos))))
+ (skip-when (memq system-type '(windows-nt ms-dos)))
(let* ((width 10)
(x (make-string width ?x))
(y (make-string width ?y)))
diff --git a/test/lisp/term/tty-colors-tests.el b/test/lisp/term/tty-colors-tests.el
index 934e635183c..ef7c839295a 100644
--- a/test/lisp/term/tty-colors-tests.el
+++ b/test/lisp/term/tty-colors-tests.el
@@ -1,6 +1,6 @@
;;; tty-colors-tests.el --- tests for tty-colors.el -*- lexical-binding: t -*-
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/textmodes/bibtex-tests.el b/test/lisp/textmodes/bibtex-tests.el
index 5e53cab3515..d2721d2829f 100644
--- a/test/lisp/textmodes/bibtex-tests.el
+++ b/test/lisp/textmodes/bibtex-tests.el
@@ -1,6 +1,6 @@
;;; bibtex-tests.el --- Test suite for bibtex. -*- lexical-binding:t -*-
-;; Copyright (C) 2013-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2024 Free Software Foundation, Inc.
;; Keywords: bibtex
diff --git a/test/lisp/textmodes/conf-mode-tests.el b/test/lisp/textmodes/conf-mode-tests.el
index 677a6d35d66..343342be886 100644
--- a/test/lisp/textmodes/conf-mode-tests.el
+++ b/test/lisp/textmodes/conf-mode-tests.el
@@ -1,6 +1,6 @@
;;; conf-mode-tests.el --- Test suite for conf mode -*- lexical-binding: t; -*-
-;; Copyright (C) 2016-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2016-2024 Free Software Foundation, Inc.
;; Author: J. Alexander Branham <alex.branham@gmail.com>
;; Keywords: internal
diff --git a/test/lisp/textmodes/css-mode-tests.el b/test/lisp/textmodes/css-mode-tests.el
index 9a5f4fcc92a..290b73f7e85 100644
--- a/test/lisp/textmodes/css-mode-tests.el
+++ b/test/lisp/textmodes/css-mode-tests.el
@@ -1,6 +1,6 @@
;;; css-mode-tests.el --- Test suite for CSS mode -*- lexical-binding: t; -*-
-;; Copyright (C) 2016-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2016-2024 Free Software Foundation, Inc.
;; Author: Simen Heggestøyl <simenheg@gmail.com>
;; Keywords: internal
diff --git a/test/lisp/textmodes/dns-mode-tests.el b/test/lisp/textmodes/dns-mode-tests.el
index f9c81b7f842..197dde6f6a0 100644
--- a/test/lisp/textmodes/dns-mode-tests.el
+++ b/test/lisp/textmodes/dns-mode-tests.el
@@ -1,6 +1,6 @@
;;; dns-mode-tests.el --- Test suite for dns-mode -*- lexical-binding: t; -*-
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
;; Author: Peder O. Klingenberg <peder@klingenberg.no>
;; Keywords: dns zone
diff --git a/test/lisp/textmodes/emacs-news-mode-tests.el b/test/lisp/textmodes/emacs-news-mode-tests.el
index 676a3270da6..5894114b20a 100644
--- a/test/lisp/textmodes/emacs-news-mode-tests.el
+++ b/test/lisp/textmodes/emacs-news-mode-tests.el
@@ -1,6 +1,6 @@
;;; emacs-news-mode-tests.el --- Tests for emacs-news-mode.el -*- lexical-binding: t -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/textmodes/fill-tests.el b/test/lisp/textmodes/fill-tests.el
index ef822ba805b..484f6ed395b 100644
--- a/test/lisp/textmodes/fill-tests.el
+++ b/test/lisp/textmodes/fill-tests.el
@@ -1,9 +1,9 @@
;;; fill-tests.el --- ERT tests for fill.el -*- lexical-binding: t -*-
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
;; Author: Marcin Borkowski <mbork@mbork.pl>
-;; Keywords: text, wp
+;; Keywords: text
;; This file is part of GNU Emacs.
diff --git a/test/lisp/textmodes/mhtml-mode-tests.el b/test/lisp/textmodes/mhtml-mode-tests.el
index ec48188fc11..c9e0dc8f888 100644
--- a/test/lisp/textmodes/mhtml-mode-tests.el
+++ b/test/lisp/textmodes/mhtml-mode-tests.el
@@ -1,6 +1,6 @@
;;; mhtml-mode-tests.el --- Tests for mhtml-mode -*- lexical-binding:t -*-
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
;; Keywords: tests
diff --git a/test/lisp/textmodes/page-tests.el b/test/lisp/textmodes/page-tests.el
index 4bfa8d9941c..f3a2c5fbe00 100644
--- a/test/lisp/textmodes/page-tests.el
+++ b/test/lisp/textmodes/page-tests.el
@@ -1,6 +1,6 @@
;;; page-tests.el --- Tests for page.el -*- lexical-binding: t; -*-
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
;; Author: Simen Heggestøyl <simenheg@gmail.com>
;; Keywords:
diff --git a/test/lisp/textmodes/paragraphs-tests.el b/test/lisp/textmodes/paragraphs-tests.el
index 81e88113c2a..ff8cdfe8b44 100644
--- a/test/lisp/textmodes/paragraphs-tests.el
+++ b/test/lisp/textmodes/paragraphs-tests.el
@@ -1,6 +1,6 @@
;;; paragraphs-tests.el --- Tests for paragraphs.el -*- lexical-binding: t; -*-
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
;; Author: Stefan Kangas <stefankangas@gmail.com>
diff --git a/test/lisp/textmodes/po-tests.el b/test/lisp/textmodes/po-tests.el
index 2bfb0dd5330..a9b405df609 100644
--- a/test/lisp/textmodes/po-tests.el
+++ b/test/lisp/textmodes/po-tests.el
@@ -1,6 +1,6 @@
;;; po-tests.el --- Tests for po.el -*- lexical-binding: t; -*-
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
;; Author: Simen Heggestøyl <simenheg@gmail.com>
;; Keywords:
diff --git a/test/lisp/textmodes/reftex-tests.el b/test/lisp/textmodes/reftex-tests.el
index 6aa12bc3b58..7f7c99a40a4 100644
--- a/test/lisp/textmodes/reftex-tests.el
+++ b/test/lisp/textmodes/reftex-tests.el
@@ -1,6 +1,6 @@
;;; reftex-tests.el --- Test suite for reftex. -*- lexical-binding: t -*-
-;; Copyright (C) 2013-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2024 Free Software Foundation, Inc.
;; Author: Rüdiger Sonderfeld <ruediger@c-plusplus.de>
;; Keywords: internal
diff --git a/test/lisp/textmodes/sgml-mode-tests.el b/test/lisp/textmodes/sgml-mode-tests.el
index 57467483bfe..f74fe84f1bd 100644
--- a/test/lisp/textmodes/sgml-mode-tests.el
+++ b/test/lisp/textmodes/sgml-mode-tests.el
@@ -1,6 +1,6 @@
;;; sgml-mode-tests.el --- Tests for sgml-mode -*- lexical-binding:t -*-
-;; Copyright (C) 2015-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2024 Free Software Foundation, Inc.
;; Author: Przemysław Wojnowski <esperanto@cumego.com>
;; Keywords: tests
diff --git a/test/lisp/textmodes/texinfo-tests.el b/test/lisp/textmodes/texinfo-tests.el
index 37a461167e9..b4bbcbc0ab1 100644
--- a/test/lisp/textmodes/texinfo-tests.el
+++ b/test/lisp/textmodes/texinfo-tests.el
@@ -1,6 +1,6 @@
;;; texinfo-tests.el --- Tests for texinfo.el -*- lexical-binding: t; -*-
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/textmodes/tildify-tests.el b/test/lisp/textmodes/tildify-tests.el
index 962aeb4747c..b6bdae5edd5 100644
--- a/test/lisp/textmodes/tildify-tests.el
+++ b/test/lisp/textmodes/tildify-tests.el
@@ -1,10 +1,10 @@
;;; tildify-tests.el --- ERT tests for tildify.el -*- lexical-binding: t -*-
-;; Copyright (C) 2014-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2014-2024 Free Software Foundation, Inc.
;; Author: Michal Nazarewicz <mina86@mina86.com>
;; Version: 4.5
-;; Keywords: text, TeX, SGML, wp
+;; Keywords: text, TeX, SGML
;; This file is part of GNU Emacs.
diff --git a/test/lisp/textmodes/underline-tests.el b/test/lisp/textmodes/underline-tests.el
index d0f899f8f5c..bf3fcaa13d1 100644
--- a/test/lisp/textmodes/underline-tests.el
+++ b/test/lisp/textmodes/underline-tests.el
@@ -1,6 +1,6 @@
;;; underline-tests.el --- Tests for underline.el -*- lexical-binding: t; -*-
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
;; Author: Stefan Kangas <stefankangas@gmail.com>
diff --git a/test/lisp/thingatpt-tests.el b/test/lisp/thingatpt-tests.el
index 7cf41d2817b..ba51f375cc6 100644
--- a/test/lisp/thingatpt-tests.el
+++ b/test/lisp/thingatpt-tests.el
@@ -1,6 +1,6 @@
;;; thingatpt-tests.el --- tests for thing-at-point. -*- lexical-binding:t -*-
-;; Copyright (C) 2013-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -85,16 +85,16 @@
("<foo@example.com>" 5 email "<foo@example.com>")
("<foo@example.com>" 16 email "<foo@example.com>")
("<foo@example.com>" 17 email "<foo@example.com>")
- ;; email adresses containing numbers
+ ;; email addresses containing numbers
("foo1@example.com" 1 email "foo1@example.com")
("1foo@example.com" 1 email "1foo@example.com")
("11@example.com" 1 email "11@example.com")
("1@example.com" 1 email "1@example.com")
- ;; email adresses user portion containing dots
+ ;; email addresses user portion containing dots
("foo.bar@example.com" 1 email "foo.bar@example.com")
(".foobar@example.com" 1 email nil)
(".foobar@example.com" 2 email "foobar@example.com")
- ;; email adresses domain portion containing dots and dashes
+ ;; email addresses domain portion containing dots and dashes
("foobar@.example.com" 1 email nil)
("foobar@-example.com" 1 email "foobar@-example.com")
;; These are illegal, but thingatpt doesn't yet handle them
diff --git a/test/lisp/thread-tests.el b/test/lisp/thread-tests.el
index 4ba7b99719c..c0f8396e6ec 100644
--- a/test/lisp/thread-tests.el
+++ b/test/lisp/thread-tests.el
@@ -1,6 +1,6 @@
;;; thread-tests.el --- Test suite for thread.el -*- lexical-binding: t; -*-
-;; Copyright (C) 2018-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2018-2024 Free Software Foundation, Inc.
;; Author: Gemini Lasswell <gazally@runbox.com>
;; Keywords: threads
@@ -88,7 +88,7 @@
(ert-deftest thread-tests-list-threads-error-when-not-configured ()
"Signal an error running `list-threads' if threads are not configured."
- (skip-unless (not (featurep 'threads)))
+ (skip-when (featurep 'threads))
(should-error (list-threads)))
(provide 'thread-tests)
diff --git a/test/lisp/time-stamp-tests.el b/test/lisp/time-stamp-tests.el
index 341c40b617b..a4c30d64225 100644
--- a/test/lisp/time-stamp-tests.el
+++ b/test/lisp/time-stamp-tests.el
@@ -1,6 +1,6 @@
;;; time-stamp-tests.el --- tests for time-stamp.el -*- lexical-binding: t -*-
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -89,12 +89,12 @@
(iter-defun time-stamp-test-pattern-sequential ()
"Iterate through each possibility for a part of `time-stamp-pattern'."
(let ((pattern-value-parts
- '(("4/" "10/" "-9/" "0/" "") ;0: line limit
- ("stamp<" "") ;1: start
- ("%-d" "%_H" "%^a" "%#Z" "%:A" "%09z" "%%" "") ;2: format part 1
- (" " "x" ":" "\n" "") ;3: format part 2
- ("%-d" "%_H" "%^a" "%#Z" "%:A" "%09z" "%%") ;4: format part 3
- (">end" "")))) ;5: end
+ '(("4/" "10/" "-9/" "0/" "") ;0: line limit
+ ("stamp:" "") ;1: start
+ ("%-d" "%_H" "%^a" "%#Z" "%:A" "%019z" "%%" "") ;2: format part 1
+ (" " "x" ":" "\n" "") ;3: format part 2
+ ("%-d" "%_H" "%^a" "%#Z" "%:A" "%019z" "%%") ;4: format part 3
+ ("end" "")))) ;5: end
(dotimes (cur (length pattern-value-parts))
(dotimes (cur-index (length (nth cur pattern-value-parts)))
(cl-flet ((extract-part
@@ -118,15 +118,21 @@
(iter-defun time-stamp-test-pattern-multiply ()
"Iterate through every combination of parts of `time-stamp-pattern'."
(let ((line-limit-values '("" "4/"))
- (start-values '("" "/stamp/"))
- (format-values '("%%" "%m"))
+ (start-values '("" "/stamp1/"))
+ (format-values '("" "%%" "%m"))
(end-values '("" ">end")))
;; yield all combinations of the above
(dolist (line-limit line-limit-values)
(dolist (start start-values)
(dolist (format format-values)
(dolist (end end-values)
- (iter-yield (list line-limit start format end))))))))
+ ;; If the format is not supplied, the end cannot be either,
+ ;; so not all generated combinations are valid.
+ ;; (This is why the format can be supplied as "%%" to
+ ;; preserve the default format.)
+ (if (or (not (equal format ""))
+ (equal end ""))
+ (iter-yield (list line-limit start format end)))))))))
(iter-defun time-stamp-test-pattern-all ()
(iter-yield-from (time-stamp-test-pattern-sequential))
@@ -156,7 +162,8 @@
(if (equal start1 "")
(should (equal ts-start time-stamp-start))
(should (equal ts-start start1)))
- (if (equal whole-format "%%")
+ (if (or (equal whole-format "")
+ (equal whole-format "%%"))
(should (equal ts-format time-stamp-format))
(should (equal ts-format whole-format)))
(if (equal end1 "")
@@ -165,7 +172,8 @@
;; return nil to stop time-stamp from calling us again
nil)))
(let ((time-stamp-pattern (concat
- line-limit1 start1 whole-format end1)))
+ line-limit1 start1 whole-format end1))
+ (case-fold-search nil))
(with-temp-buffer
;; prep the buffer with more than the
;; largest line-limit1 number of lines
@@ -758,12 +766,14 @@ and is called by some low-level `time-stamp' \"%z\" unit tests."
(defun fz-make+zone (h &optional m s)
"Creates a non-negative offset."
+ (declare (pure t))
(let ((m (or m 0))
(s (or s 0)))
(+ (* 3600 h) (* 60 m) s)))
(defun fz-make-zone (h &optional m s)
"Creates a negative offset. The arguments are all non-negative."
+ (declare (pure t))
(- (fz-make+zone h m s)))
(defmacro formatz-should-equal (zone expect)
diff --git a/test/lisp/time-tests.el b/test/lisp/time-tests.el
index 359f3ea3313..1c63e87d786 100644
--- a/test/lisp/time-tests.el
+++ b/test/lisp/time-tests.el
@@ -1,6 +1,6 @@
;;; time-tests.el --- Tests for time.el -*- lexical-binding: t; -*-
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
;; Author: Stefan Kangas <stefankangas@gmail.com>
diff --git a/test/lisp/timezone-tests.el b/test/lisp/timezone-tests.el
index 5f8896656cc..484477e0428 100644
--- a/test/lisp/timezone-tests.el
+++ b/test/lisp/timezone-tests.el
@@ -1,6 +1,6 @@
;;; timezone-tests.el --- Tests for timezone.el -*- lexical-binding: t; -*-
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
;; Author: Stefan Kangas <stefankangas@gmail.com>
diff --git a/test/lisp/uniquify-tests.el b/test/lisp/uniquify-tests.el
index 38510c3bd77..4124ce056d3 100644
--- a/test/lisp/uniquify-tests.el
+++ b/test/lisp/uniquify-tests.el
@@ -1,6 +1,6 @@
;;; uniquify-tests.el --- Tests for uniquify -*- lexical-binding: t; -*-
-;; Copyright (C) 2023 Free Software Foundation, Inc.
+;; Copyright (C) 2023-2024 Free Software Foundation, Inc.
;; Author: Spencer Baugh <sbaugh@janestreet.com>
diff --git a/test/lisp/url/url-auth-tests.el b/test/lisp/url/url-auth-tests.el
index 5527d3a3bfc..d9262a24870 100644
--- a/test/lisp/url/url-auth-tests.el
+++ b/test/lisp/url/url-auth-tests.el
@@ -1,6 +1,6 @@
;;; url-auth-tests.el --- Test suite for url-auth. -*- lexical-binding:t -*-
-;; Copyright (C) 2015-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2024 Free Software Foundation, Inc.
;; Author: Jarno Malmari <jarno@malmari.fi>
diff --git a/test/lisp/url/url-domsuf-tests.el b/test/lisp/url/url-domsuf-tests.el
index 8dbf65dae44..cae25d8e04e 100644
--- a/test/lisp/url/url-domsuf-tests.el
+++ b/test/lisp/url/url-domsuf-tests.el
@@ -1,6 +1,6 @@
;;; url-domsuf-tests.el --- Tests for url-domsuf.el -*- lexical-binding:t -*-
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/url/url-expand-tests.el b/test/lisp/url/url-expand-tests.el
index 651bd690811..127c18b73b6 100644
--- a/test/lisp/url/url-expand-tests.el
+++ b/test/lisp/url/url-expand-tests.el
@@ -1,9 +1,8 @@
;;; url-expand-tests.el --- Test suite for relative URI/URL resolution. -*- lexical-binding:t -*-
-;; Copyright (C) 2012-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2012-2024 Free Software Foundation, Inc.
;; Author: Alain Schneble <a.s@realize.ch>
-;; Version: 1.0
;; This file is part of GNU Emacs.
diff --git a/test/lisp/url/url-file-tests.el b/test/lisp/url/url-file-tests.el
index 4c3bcc9163e..a841195e8c4 100644
--- a/test/lisp/url/url-file-tests.el
+++ b/test/lisp/url/url-file-tests.el
@@ -1,6 +1,6 @@
;;; url-file-tests.el --- Test suite for url-file. -*- lexical-binding: t -*-
-;; Copyright (C) 2018-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2018-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/url/url-future-tests.el b/test/lisp/url/url-future-tests.el
index 18e6e31c8ce..af56fb59ee0 100644
--- a/test/lisp/url/url-future-tests.el
+++ b/test/lisp/url/url-future-tests.el
@@ -1,6 +1,6 @@
;;; url-future-tests.el --- Test suite for url-future. -*- lexical-binding:t -*-
-;; Copyright (C) 2011-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2011-2024 Free Software Foundation, Inc.
;; Author: Teodor Zlatanov <tzz@lifelogs.com>
;; Keywords: data
diff --git a/test/lisp/url/url-handlers-tests.el b/test/lisp/url/url-handlers-tests.el
index 68afee4ce93..eef6050886a 100644
--- a/test/lisp/url/url-handlers-tests.el
+++ b/test/lisp/url/url-handlers-tests.el
@@ -1,6 +1,6 @@
;;; url-handlers-tests.el --- Test suite for url-handlers.el -*- lexical-binding: t; -*-
-;; Copyright (C) 2018-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2018-2024 Free Software Foundation, Inc.
;; Author: Nicolas Petton <nicolas@petton.fr>
diff --git a/test/lisp/url/url-misc-tests.el b/test/lisp/url/url-misc-tests.el
index 8d2e20f11d0..432aa6c0e6c 100644
--- a/test/lisp/url/url-misc-tests.el
+++ b/test/lisp/url/url-misc-tests.el
@@ -1,6 +1,6 @@
;;; url-misc-tests.el --- Test suite for url-misc. -*- lexical-binding: t -*-
-;; Copyright (C) 2018-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2018-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/url/url-parse-tests.el b/test/lisp/url/url-parse-tests.el
index cf75738d00a..6882ed26932 100644
--- a/test/lisp/url/url-parse-tests.el
+++ b/test/lisp/url/url-parse-tests.el
@@ -1,9 +1,8 @@
;;; url-parse-tests.el --- Test suite for URI/URL parsing. -*- lexical-binding:t -*-
-;; Copyright (C) 2012-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2012-2024 Free Software Foundation, Inc.
;; Author: Alain Schneble <a.s@realize.ch>
-;; Version: 1.0
;; This file is part of GNU Emacs.
diff --git a/test/lisp/url/url-tramp-tests.el b/test/lisp/url/url-tramp-tests.el
index b31913c8371..1751b4ed603 100644
--- a/test/lisp/url/url-tramp-tests.el
+++ b/test/lisp/url/url-tramp-tests.el
@@ -1,6 +1,6 @@
;;; url-tramp-tests.el --- Test suite for Tramp / URL conversion. -*- lexical-binding:t -*-
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
;; Author: Michael Albinus <michael.albinus@gmx.de>
diff --git a/test/lisp/url/url-util-tests.el b/test/lisp/url/url-util-tests.el
index 092a25ebfff..133aa0ffd88 100644
--- a/test/lisp/url/url-util-tests.el
+++ b/test/lisp/url/url-util-tests.el
@@ -1,6 +1,6 @@
;;; url-util-tests.el --- Test suite for url-util. -*- lexical-binding:t -*-
-;; Copyright (C) 2012-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2012-2024 Free Software Foundation, Inc.
;; Author: Teodor Zlatanov <tzz@lifelogs.com>
;; Keywords: data
diff --git a/test/lisp/use-package/use-package-tests.el b/test/lisp/use-package/use-package-tests.el
index 9181a8171a7..d1e68c2a790 100644
--- a/test/lisp/use-package/use-package-tests.el
+++ b/test/lisp/use-package/use-package-tests.el
@@ -1,6 +1,6 @@
;;; use-package-tests.el --- Tests for use-package.el -*- lexical-binding: t; -*-
-;; Copyright (C) 2014-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2014-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/vc/add-log-tests.el b/test/lisp/vc/add-log-tests.el
index 07da65c74f6..510807dc825 100644
--- a/test/lisp/vc/add-log-tests.el
+++ b/test/lisp/vc/add-log-tests.el
@@ -1,6 +1,6 @@
;;; add-log-tests.el --- Test suite for add-log. -*- lexical-binding:t -*-
-;; Copyright (C) 2013-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2024 Free Software Foundation, Inc.
;; Author: Masatake YAMATO <yamato@redhat.com>
;; Keywords: vc tools
diff --git a/test/lisp/vc/diff-mode-tests.el b/test/lisp/vc/diff-mode-tests.el
index 8033dc9cbbd..5ab159c7ab6 100644
--- a/test/lisp/vc/diff-mode-tests.el
+++ b/test/lisp/vc/diff-mode-tests.el
@@ -1,6 +1,6 @@
;;; diff-mode-tests.el --- Tests for diff-mode.el -*- lexical-binding:t -*-
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
;; Author: Dima Kogan <dima@secretsauce.net>
;; Maintainer: emacs-devel@gnu.org
diff --git a/test/lisp/vc/ediff-diff-tests.el b/test/lisp/vc/ediff-diff-tests.el
index b250148da8d..8ee6bdc2559 100644
--- a/test/lisp/vc/ediff-diff-tests.el
+++ b/test/lisp/vc/ediff-diff-tests.el
@@ -1,6 +1,6 @@
;;; ediff-diff-tests.el --- Unit tests for ediff-diff.el -*- lexical-binding: t; -*-
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
;; Author: Philipp Stephani <phst@google.com>
diff --git a/test/lisp/vc/ediff-ptch-tests.el b/test/lisp/vc/ediff-ptch-tests.el
index 74701ee1802..7b8ff7ebc1a 100644
--- a/test/lisp/vc/ediff-ptch-tests.el
+++ b/test/lisp/vc/ediff-ptch-tests.el
@@ -1,6 +1,6 @@
;;; ediff-ptch-tests.el --- Tests for ediff-ptch.el -*- lexical-binding:t -*-
-;; Copyright (C) 2016-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2016-2024 Free Software Foundation, Inc.
;; Author: Tino Calancha <tino.calancha@gmail.com>
diff --git a/test/lisp/vc/log-edit-tests.el b/test/lisp/vc/log-edit-tests.el
index 237b743aa24..1a2af716f34 100644
--- a/test/lisp/vc/log-edit-tests.el
+++ b/test/lisp/vc/log-edit-tests.el
@@ -1,6 +1,6 @@
;;; log-edit-tests.el --- Unit tests for log-edit.el -*- lexical-binding: t; -*-
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/vc/smerge-mode-tests.el b/test/lisp/vc/smerge-mode-tests.el
index a7d41607bc5..d69c629ad69 100644
--- a/test/lisp/vc/smerge-mode-tests.el
+++ b/test/lisp/vc/smerge-mode-tests.el
@@ -1,6 +1,6 @@
;;; smerge-mode-tests.el --- Tests for smerge-mode.el -*- lexical-binding:t -*-
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
;; Maintainer: emacs-devel@gnu.org
diff --git a/test/lisp/vc/vc-bzr-tests.el b/test/lisp/vc/vc-bzr-tests.el
index d8ed1013c38..8ed63d11a8f 100644
--- a/test/lisp/vc/vc-bzr-tests.el
+++ b/test/lisp/vc/vc-bzr-tests.el
@@ -1,6 +1,6 @@
;;; vc-bzr-tests.el --- tests for vc/vc-bzr.el -*- lexical-binding: t -*-
-;; Copyright (C) 2011-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2011-2024 Free Software Foundation, Inc.
;; Author: Glenn Morris <rgm@gnu.org>
;; Maintainer: emacs-devel@gnu.org
diff --git a/test/lisp/vc/vc-cvs-tests.el b/test/lisp/vc/vc-cvs-tests.el
index 473ac69e24c..f6fa7a81a1a 100644
--- a/test/lisp/vc/vc-cvs-tests.el
+++ b/test/lisp/vc/vc-cvs-tests.el
@@ -1,6 +1,6 @@
;;; vc-cvs-tests.el --- tests for vc/vc-cvs.el -*- lexical-binding:t -*-
-;; Copyright (C) 2023 Free Software Foundation, Inc.
+;; Copyright (C) 2023-2024 Free Software Foundation, Inc.
;; Author: Olivier Certner <olce.emacs@certner.fr>
;; Maintainer: emacs-devel@gnu.org
diff --git a/test/lisp/vc/vc-git-tests.el b/test/lisp/vc/vc-git-tests.el
index b331b77cf01..c52cd9c5875 100644
--- a/test/lisp/vc/vc-git-tests.el
+++ b/test/lisp/vc/vc-git-tests.el
@@ -1,6 +1,6 @@
;;; vc-git-tests.el --- tests for vc/vc-git.el -*- lexical-binding:t -*-
-;; Copyright (C) 2016-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2016-2024 Free Software Foundation, Inc.
;; Author: Justin Schell <justinmschell@gmail.com>
;; Maintainer: emacs-devel@gnu.org
diff --git a/test/lisp/vc/vc-hg-tests.el b/test/lisp/vc/vc-hg-tests.el
index 89d518b2a91..f578c86d401 100644
--- a/test/lisp/vc/vc-hg-tests.el
+++ b/test/lisp/vc/vc-hg-tests.el
@@ -1,6 +1,6 @@
;;; vc-hg-tests.el --- tests for vc/vc-hg.el -*- lexical-binding:t -*-
-;; Copyright (C) 2016-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2016-2024 Free Software Foundation, Inc.
;; Author: Dmitry Gutov <dgutov@yandex.ru>
;; Maintainer: emacs-devel@gnu.org
@@ -53,6 +53,8 @@
(ert-deftest vc-hg-annotate-time ()
(with-temp-buffer
(save-excursion (insert "philringnalda 218075 2014-11-28 CLOBBER:"))
- (should (floatp (vc-hg-annotate-time)))))
+ (should (equal (vc-hg-annotate-time)
+ (vc-annotate-convert-time
+ (encode-time 0 0 0 28 11 2014))))))
;;; vc-hg-tests.el ends here
diff --git a/test/lisp/vc/vc-tests.el b/test/lisp/vc/vc-tests.el
index 11c20d2783c..6be8af40e3a 100644
--- a/test/lisp/vc/vc-tests.el
+++ b/test/lisp/vc/vc-tests.el
@@ -1,6 +1,6 @@
;;; vc-tests.el --- Tests of different backends of vc.el -*- lexical-binding:t -*-
-;; Copyright (C) 2014-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2014-2024 Free Software Foundation, Inc.
;; Author: Michael Albinus <michael.albinus@gmx.de>
@@ -596,8 +596,9 @@ This checks also `vc-backend' and `vc-responsible-backend'."
(let ((vc-handled-backends `(,backend))
(default-directory
(file-name-as-directory
- (expand-file-name
- (make-temp-name "vc-test") temporary-file-directory)))
+ (file-truename
+ (expand-file-name
+ (make-temp-name "vc-test") temporary-file-directory))))
(process-environment process-environment)
vc-test--cleanup-hook)
(when (eq backend 'Bzr)
@@ -780,7 +781,7 @@ This checks also `vc-backend' and `vc-responsible-backend'."
;; CVS calls vc-delete-file, which insists on prompting
;; "Really want to delete ...?", and `vc-mtn.el' does not implement
;; `delete-file' at all.
- (skip-unless (not (memq ',backend '(CVS Mtn))))
+ (skip-when (memq ',backend '(CVS Mtn)))
(vc-test--rename-file ',backend))
(ert-deftest
@@ -795,7 +796,7 @@ This checks also `vc-backend' and `vc-responsible-backend'."
(format "vc-test-%s01-register" backend-string))))))
;; `vc-mtn.el' gives me:
;; "Failed (status 1): mtn commit -m Testing vc-version-diff\n\n foo"
- (skip-unless (not (memq ',backend '(Mtn))))
+ (skip-when (memq ',backend '(Mtn)))
(vc-test--version-diff ',backend))
))))
diff --git a/test/lisp/version-tests.el b/test/lisp/version-tests.el
index 95ecf9600b5..81bb769d089 100644
--- a/test/lisp/version-tests.el
+++ b/test/lisp/version-tests.el
@@ -1,6 +1,6 @@
;;; version-tests.el --- Tests for version.el -*- lexical-binding: t -*-
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/wdired-tests.el b/test/lisp/wdired-tests.el
index 20caaff17c7..f7bff743058 100644
--- a/test/lisp/wdired-tests.el
+++ b/test/lisp/wdired-tests.el
@@ -1,6 +1,6 @@
;;; wdired-tests.el --- tests for wdired.el -*- lexical-binding: t; -*-
-;; Copyright (C) 2018-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2018-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/whitespace-tests.el b/test/lisp/whitespace-tests.el
index f059104cdb9..73c7e742ec5 100644
--- a/test/lisp/whitespace-tests.el
+++ b/test/lisp/whitespace-tests.el
@@ -1,6 +1,6 @@
;;; whitespace-tests.el --- Test suite for whitespace -*- lexical-binding: t -*-
-;; Copyright (C) 2016-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2016-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/wid-edit-tests.el b/test/lisp/wid-edit-tests.el
index ebfe729bc9a..4b049478b29 100644
--- a/test/lisp/wid-edit-tests.el
+++ b/test/lisp/wid-edit-tests.el
@@ -1,6 +1,6 @@
;;; wid-edit-tests.el --- tests for wid-edit.el -*- lexical-binding: t -*-
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -380,4 +380,15 @@ return nil, even with a non-nil bubblep argument."
:value (("1" . 1) ("2" . 2))))))
(should (equal '(("1" . 1) ("2" . 2)) (widget-default-get w))))))
+(ert-deftest widget-test-restricted-sexp-empty-val ()
+ "Test that we handle an empty restricted-sexp widget just fine."
+ (with-temp-buffer
+ (let ((w (widget-create '(restricted-sexp
+ :value 3
+ :match-alternatives (integerp)))))
+ (widget-setup)
+ (widget-backward 1)
+ (delete-char 1)
+ (should (string= (widget-value w) "")))))
+
;;; wid-edit-tests.el ends here
diff --git a/test/lisp/x-dnd-tests.el b/test/lisp/x-dnd-tests.el
index 2ed4c3e7662..37a1beafd54 100644
--- a/test/lisp/x-dnd-tests.el
+++ b/test/lisp/x-dnd-tests.el
@@ -1,6 +1,6 @@
;;; dnd-tests.el --- Tests for X DND support -*- lexical-binding: t; -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/lisp/xdg-tests.el b/test/lisp/xdg-tests.el
index 962f26cd975..c10a258210c 100644
--- a/test/lisp/xdg-tests.el
+++ b/test/lisp/xdg-tests.el
@@ -1,6 +1,6 @@
;;; xdg-tests.el --- tests for xdg.el -*- lexical-binding: t -*-
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
;; Author: Mark Oteiza <mvoteiza@udel.edu>
;; Maintainer: emacs-devel@gnu.org
diff --git a/test/lisp/xml-tests.el b/test/lisp/xml-tests.el
index 8d419765fe6..d423a34f70e 100644
--- a/test/lisp/xml-tests.el
+++ b/test/lisp/xml-tests.el
@@ -1,6 +1,6 @@
;;; xml-tests.el --- Test suite for XML parsing. -*- lexical-binding:t -*-
-;; Copyright (C) 2012-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2012-2024 Free Software Foundation, Inc.
;; Author: Chong Yidong <cyd@stupidchicken.com>
;; Keywords: internal
diff --git a/test/lisp/xt-mouse-tests.el b/test/lisp/xt-mouse-tests.el
index 19719c75fc3..cfc8042f796 100644
--- a/test/lisp/xt-mouse-tests.el
+++ b/test/lisp/xt-mouse-tests.el
@@ -1,6 +1,6 @@
;;; xt-mouse-tests.el --- Test suite for xt-mouse. -*- lexical-binding: t; -*-
-;; Copyright (C) 2016-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2016-2024 Free Software Foundation, Inc.
;; Author: Philipp Stephani <phst@google.com>
diff --git a/test/lisp/yank-media-tests.el b/test/lisp/yank-media-tests.el
index 2ce879c418f..2eee60002fe 100644
--- a/test/lisp/yank-media-tests.el
+++ b/test/lisp/yank-media-tests.el
@@ -1,6 +1,6 @@
;;; yank-media-tests.el --- Tests for yank-media.el -*- lexical-binding: t; -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/manual/BidiCharacterTest.txt b/test/manual/BidiCharacterTest.txt
index 619d4b4412b..6b3ef016036 100644
--- a/test/manual/BidiCharacterTest.txt
+++ b/test/manual/BidiCharacterTest.txt
@@ -1,6 +1,6 @@
-# BidiCharacterTest-15.0.0.txt
-# Date: 2022-05-03, 18:46:00 GMT [LI]
-# © 2022 Unicode®, Inc.
+# BidiCharacterTest-15.1.0.txt
+# Date: 2023-01-05
+# © 2023 Unicode®, Inc.
# For terms of use, see https://www.unicode.org/terms_of_use.html
#
# Unicode Character Database
diff --git a/test/manual/biditest.el b/test/manual/biditest.el
index aefd322dede..7c49591b84e 100644
--- a/test/manual/biditest.el
+++ b/test/manual/biditest.el
@@ -1,6 +1,6 @@
;;; biditest.el --- test bidi reordering in GNU Emacs display engine. -*- lexical-binding: t; -*-
-;; Copyright (C) 2013-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2024 Free Software Foundation, Inc.
;; Author: Eli Zaretskii
;; Maintainer: emacs-devel@gnu.org
diff --git a/test/manual/cedet/cedet-utests.el b/test/manual/cedet/cedet-utests.el
index 336e417c44f..49a18b2ac55 100644
--- a/test/manual/cedet/cedet-utests.el
+++ b/test/manual/cedet/cedet-utests.el
@@ -1,6 +1,6 @@
;;; cedet-utests.el --- Run all unit tests in the CEDET suite. -*- lexical-binding: t; -*-
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/test/manual/cedet/ede-tests.el b/test/manual/cedet/ede-tests.el
index 89407108e58..0c9fc72e2ce 100644
--- a/test/manual/cedet/ede-tests.el
+++ b/test/manual/cedet/ede-tests.el
@@ -1,6 +1,6 @@
;;; ede-tests.el --- Some tests for the Emacs Development Environment -*- lexical-binding: t -*-
-;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/test/manual/cedet/semantic-tests.el b/test/manual/cedet/semantic-tests.el
index 5eca5fb5c62..f928a2f8b0b 100644
--- a/test/manual/cedet/semantic-tests.el
+++ b/test/manual/cedet/semantic-tests.el
@@ -1,6 +1,6 @@
;;; semantic-tests.el --- Miscellaneous Semantic tests. -*- lexical-binding: t; -*-
-;; Copyright (C) 2003-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2003-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/test/manual/cedet/tests/test.c b/test/manual/cedet/tests/test.c
index cddbd85b45b..093b806ac3b 100644
--- a/test/manual/cedet/tests/test.c
+++ b/test/manual/cedet/tests/test.c
@@ -1,6 +1,6 @@
/* test.c --- Semantic unit test for C.
- Copyright (C) 2001-2023 Free Software Foundation, Inc.
+ Copyright (C) 2001-2024 Free Software Foundation, Inc.
Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/test/manual/cedet/tests/test.el b/test/manual/cedet/tests/test.el
index c75ea331223..d96289296fa 100644
--- a/test/manual/cedet/tests/test.el
+++ b/test/manual/cedet/tests/test.el
@@ -1,6 +1,6 @@
;;; test.el --- Unit test file for Semantic Emacs Lisp support. -*- lexical-binding: t -*-
-;; Copyright (C) 2005-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2005-2024 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/test/manual/cedet/tests/test.make b/test/manual/cedet/tests/test.make
index fc171214420..7bb1e4133a7 100644
--- a/test/manual/cedet/tests/test.make
+++ b/test/manual/cedet/tests/test.make
@@ -1,6 +1,6 @@
# test.make --- Semantic unit test for Make -*- makefile -*-
-# Copyright (C) 2001-2002, 2010-2023 Free Software Foundation, Inc.
+# Copyright (C) 2001-2002, 2010-2024 Free Software Foundation, Inc.
# Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/test/manual/cedet/tests/testpolymorph.cpp b/test/manual/cedet/tests/testpolymorph.cpp
index 0cf645c2f43..b3cb90be2d6 100644
--- a/test/manual/cedet/tests/testpolymorph.cpp
+++ b/test/manual/cedet/tests/testpolymorph.cpp
@@ -1,6 +1,6 @@
/** testpolymorph.cpp --- A sequence of polymorphism examples.
*
- * Copyright (C) 2009-2023 Free Software Foundation, Inc.
+ * Copyright (C) 2009-2024 Free Software Foundation, Inc.
*
* Author: Eric M. Ludlam <zappo@gnu.org>
*
diff --git a/test/manual/cedet/tests/testspp.c b/test/manual/cedet/tests/testspp.c
index a439cee2a7d..05326ef6e1f 100644
--- a/test/manual/cedet/tests/testspp.c
+++ b/test/manual/cedet/tests/testspp.c
@@ -1,6 +1,6 @@
/* testspp.cpp --- Semantic unit test for the C preprocessor
- Copyright (C) 2007-2023 Free Software Foundation, Inc.
+ Copyright (C) 2007-2024 Free Software Foundation, Inc.
Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/test/manual/cedet/tests/testsppreplace.c b/test/manual/cedet/tests/testsppreplace.c
index 2c913934bea..acb4c9bbce2 100644
--- a/test/manual/cedet/tests/testsppreplace.c
+++ b/test/manual/cedet/tests/testsppreplace.c
@@ -1,5 +1,5 @@
/* testsppreplace.c --- unit test for CPP/SPP Replacement
- Copyright (C) 2007-2023 Free Software Foundation, Inc.
+ Copyright (C) 2007-2024 Free Software Foundation, Inc.
Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/test/manual/cedet/tests/testsppreplaced.c b/test/manual/cedet/tests/testsppreplaced.c
index f0f78ca8dd2..f4520d3d48f 100644
--- a/test/manual/cedet/tests/testsppreplaced.c
+++ b/test/manual/cedet/tests/testsppreplaced.c
@@ -1,5 +1,5 @@
/* testsppreplaced.c --- unit test for CPP/SPP Replacement
- Copyright (C) 2007-2023 Free Software Foundation, Inc.
+ Copyright (C) 2007-2024 Free Software Foundation, Inc.
Author: Eric M. Ludlam <zappo@gnu.org>
diff --git a/test/manual/etags/c-src/abbrev.c b/test/manual/etags/c-src/abbrev.c
index acd5884886c..70f4987eccc 100644
--- a/test/manual/etags/c-src/abbrev.c
+++ b/test/manual/etags/c-src/abbrev.c
@@ -1,5 +1,5 @@
/* Primitives for word-abbrev mode.
- Copyright (C) 1985-1986, 1993, 1996, 1998, 2016-2023 Free Software
+ Copyright (C) 1985-1986, 1993, 1996, 1998, 2016-2024 Free Software
Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/test/manual/etags/c-src/emacs/src/gmalloc.c b/test/manual/etags/c-src/emacs/src/gmalloc.c
index cf3ad6ee766..afa36994b59 100644
--- a/test/manual/etags/c-src/emacs/src/gmalloc.c
+++ b/test/manual/etags/c-src/emacs/src/gmalloc.c
@@ -1,5 +1,5 @@
/* Declarations for `malloc' and friends.
- Copyright (C) 1990-1993, 1995-1996, 1999, 2002-2007, 2013-2023 Free
+ Copyright (C) 1990-1993, 1995-1996, 1999, 2002-2007, 2013-2024 Free
Software Foundation, Inc.
Written May 1989 by Mike Haertel.
diff --git a/test/manual/etags/c-src/emacs/src/keyboard.c b/test/manual/etags/c-src/emacs/src/keyboard.c
index 310dba27c89..b27f98903ce 100644
--- a/test/manual/etags/c-src/emacs/src/keyboard.c
+++ b/test/manual/etags/c-src/emacs/src/keyboard.c
@@ -1,6 +1,6 @@
/* Keyboard and mouse input; editor command loop.
-Copyright (C) 1985-1989, 1993-1997, 1999-2023 Free Software Foundation,
+Copyright (C) 1985-1989, 1993-1997, 1999-2024 Free Software Foundation,
Inc.
This file is part of GNU Emacs.
diff --git a/test/manual/etags/c-src/emacs/src/lisp.h b/test/manual/etags/c-src/emacs/src/lisp.h
index aa8dc8c9a66..0382acf06ed 100644
--- a/test/manual/etags/c-src/emacs/src/lisp.h
+++ b/test/manual/etags/c-src/emacs/src/lisp.h
@@ -1,6 +1,6 @@
/* Fundamental definitions for GNU Emacs Lisp interpreter.
-Copyright (C) 1985-1987, 1993-1995, 1997-2023 Free Software Foundation,
+Copyright (C) 1985-1987, 1993-1995, 1997-2024 Free Software Foundation,
Inc.
This file is part of GNU Emacs.
diff --git a/test/manual/etags/c-src/emacs/src/regex.h b/test/manual/etags/c-src/emacs/src/regex.h
index b31fa9982d9..75a9b5893be 100644
--- a/test/manual/etags/c-src/emacs/src/regex.h
+++ b/test/manual/etags/c-src/emacs/src/regex.h
@@ -1,7 +1,7 @@
/* Definitions for data structures and routines for the regular
expression library, version 0.12.
- Copyright (C) 1985, 1989-1993, 1995, 2000-2023 Free Software
+ Copyright (C) 1985, 1989-1993, 1995, 2000-2024 Free Software
Foundation, Inc.
This program is free software; you can redistribute it and/or modify
diff --git a/test/manual/etags/c-src/etags.c b/test/manual/etags/c-src/etags.c
index bd09e75a5d0..a5b464ae520 100644
--- a/test/manual/etags/c-src/etags.c
+++ b/test/manual/etags/c-src/etags.c
@@ -28,7 +28,7 @@ OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-Copyright (C) 1984, 1987-1989, 1993-1995, 1998-2023 Free Software
+Copyright (C) 1984, 1987-1989, 1993-1995, 1998-2024 Free Software
Foundation, Inc.
This file is not considered part of GNU Emacs.
diff --git a/test/manual/etags/c-src/exit.c b/test/manual/etags/c-src/exit.c
index 8101562c985..bd21f5dcd9b 100644
--- a/test/manual/etags/c-src/exit.c
+++ b/test/manual/etags/c-src/exit.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991, 2016-2023 Free Software Foundation, Inc.
+/* Copyright (C) 1991, 2016-2024 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/test/manual/etags/c-src/exit.strange_suffix b/test/manual/etags/c-src/exit.strange_suffix
index 8101562c985..bd21f5dcd9b 100644
--- a/test/manual/etags/c-src/exit.strange_suffix
+++ b/test/manual/etags/c-src/exit.strange_suffix
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991, 2016-2023 Free Software Foundation, Inc.
+/* Copyright (C) 1991, 2016-2024 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/test/manual/etags/c-src/getopt.h b/test/manual/etags/c-src/getopt.h
index 29536410f29..069d7b9bc3b 100644
--- a/test/manual/etags/c-src/getopt.h
+++ b/test/manual/etags/c-src/getopt.h
@@ -1,5 +1,5 @@
/* Declarations for getopt.
- Copyright (C) 1989-1992, 2016-2023 Free Software Foundation, Inc.
+ Copyright (C) 1989-1992, 2016-2024 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
diff --git a/test/manual/etags/c-src/sysdep.h b/test/manual/etags/c-src/sysdep.h
index c29ed8b64a6..d8fc292e185 100644
--- a/test/manual/etags/c-src/sysdep.h
+++ b/test/manual/etags/c-src/sysdep.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 1992-1993, 2016-2023 Free Software Foundation, Inc.
+/* Copyright (C) 1992-1993, 2016-2024 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/test/manual/etags/el-src/emacs/lisp/progmodes/etags.el b/test/manual/etags/el-src/emacs/lisp/progmodes/etags.el
index 4f4663701f0..288bd325c04 100644
--- a/test/manual/etags/el-src/emacs/lisp/progmodes/etags.el
+++ b/test/manual/etags/el-src/emacs/lisp/progmodes/etags.el
@@ -1,6 +1,6 @@
;;; etags.el --- etags facility for Emacs -*- lexical-binding: t -*-
-;; Copyright (C) 1985-1986, 1988-1989, 1992-1996, 1998, 2000-2023 Free
+;; Copyright (C) 1985-1986, 1988-1989, 1992-1996, 1998, 2000-2024 Free
;; Software Foundation, Inc.
;; Author: Roland McGrath <roland@gnu.org>
diff --git a/test/manual/etags/tex-src/texinfo.tex b/test/manual/etags/tex-src/texinfo.tex
index f523af7da30..cc8b80aa3c3 100644
--- a/test/manual/etags/tex-src/texinfo.tex
+++ b/test/manual/etags/tex-src/texinfo.tex
@@ -1,6 +1,6 @@
%% TeX macros to handle texinfo files
-% Copyright (C) 1985--1986, 1988, 1990--1991, 2016--2023 Free Software
+% Copyright (C) 1985--1986, 1988, 1990--1991, 2016--2024 Free Software
% Foundation, Inc.
%This texinfo.tex file is free software; you can redistribute it and/or
diff --git a/test/manual/etags/y-src/cccp.c b/test/manual/etags/y-src/cccp.c
index 879de5b0d8f..bc30e23772c 100644
--- a/test/manual/etags/y-src/cccp.c
+++ b/test/manual/etags/y-src/cccp.c
@@ -320,7 +320,7 @@ static const short yycheck[] =
#line 3 "/usr/share/bison/bison.simple"
/* Skeleton output parser for bison,
- Copyright (C) 1984, 1989-1990, 2000-2001, 2016-2023 Free Software
+ Copyright (C) 1984, 1989-1990, 2000-2001, 2016-2024 Free Software
Foundation, Inc.
This program is free software; you can redistribute it and/or modify
diff --git a/test/manual/etags/y-src/parse.c b/test/manual/etags/y-src/parse.c
index 8ba6b23675d..c4aac438fc5 100644
--- a/test/manual/etags/y-src/parse.c
+++ b/test/manual/etags/y-src/parse.c
@@ -28,7 +28,7 @@
#line 1 "y-src/parse.y"
-/* Copyright (C) 1990, 1992-1993, 2016-2023 Free Software Foundation,
+/* Copyright (C) 1990, 1992-1993, 2016-2024 Free Software Foundation,
* Inc.
This file is part of Oleo, the GNU Spreadsheet.
diff --git a/test/manual/etags/y-src/parse.y b/test/manual/etags/y-src/parse.y
index c4d4b1e0eac..9812787f914 100644
--- a/test/manual/etags/y-src/parse.y
+++ b/test/manual/etags/y-src/parse.y
@@ -1,5 +1,5 @@
%{
-/* Copyright (C) 1990, 1992-1993, 2016-2023 Free Software Foundation,
+/* Copyright (C) 1990, 1992-1993, 2016-2024 Free Software Foundation,
* Inc.
This file is part of Oleo, the GNU Spreadsheet.
diff --git a/test/manual/image-circular-tests.el b/test/manual/image-circular-tests.el
index efd96895f84..ac62d1c58ec 100644
--- a/test/manual/image-circular-tests.el
+++ b/test/manual/image-circular-tests.el
@@ -1,6 +1,6 @@
;;; image-circular-tests.el --- test image functions with circular objects -*- lexical-binding: t; -*-
-;; Copyright (C) 2019, 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019, 2021-2024 Free Software Foundation, Inc.
;; Author: Pip Cet <pipcet@gmail.com>
;; Keywords: internal
diff --git a/test/manual/image-size-tests.el b/test/manual/image-size-tests.el
index 544a38b6ba3..a96e1afc960 100644
--- a/test/manual/image-size-tests.el
+++ b/test/manual/image-size-tests.el
@@ -1,6 +1,6 @@
;;; image-size-tests.el --- tests for image scaling -*- lexical-binding: t; -*-
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/manual/image-tests.el b/test/manual/image-tests.el
index a359bb0f91f..e186586be3b 100644
--- a/test/manual/image-tests.el
+++ b/test/manual/image-tests.el
@@ -1,6 +1,6 @@
;;; image-tests.el --- tests for image.c -*- lexical-binding: t; -*-
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
;; Author: Stefan Kangas <stefankangas@gmail.com>
;; Keywords: internal
@@ -31,6 +31,8 @@
;;; Code:
+(require 'ert)
+
(defmacro image-skip-unless (format &rest condition)
`(skip-unless (and (and (display-images-p)
(image-type-available-p ,format))
@@ -41,9 +43,9 @@
source-directory))
(jpeg . ,(expand-file-name "test/data/image/black.jpg"
source-directory))
- (pbm . ,(find-image '((:file "splash.svg" :type svg))))
+ (svg . ,(find-image '((:file "splash.svg" :type svg))))
(png . ,(find-image '((:file "splash.png" :type png))))
- (svg . ,(find-image '((:file "splash.pbm" :type pbm))))
+ (pbm . ,(find-image '((:file "splash.pbm" :type pbm))))
(tiff . ,(expand-file-name
"nextstep/GNUstep/Emacs.base/Resources/emacs.tiff"
source-directory))
@@ -80,6 +82,7 @@
(image-tests-make-load-image-test 'xpm)
(ert-deftest image-tests-load-image/svg-too-big ()
+ (image-skip-unless svg)
(with-temp-buffer
(let* ((max-image-size 0)
(messages-buffer-name (buffer-name (current-buffer)))
@@ -95,6 +98,7 @@
(should-not (string-match-p "error parsing" (buffer-string))))))
(ert-deftest image-tests-load-image/svg-invalid ()
+ (image-skip-unless svg)
(with-temp-buffer
(let ((messages-buffer-name (buffer-name (current-buffer))))
(with-temp-buffer
@@ -240,6 +244,8 @@
(ert-deftest image-tests-image-metadata/gif ()
(image-skip-unless 'gif
+ ;; FIXME: Why is this failing on macOS?
+ (not (eq system-type 'darwin))
(not (bound-and-true-p w32-use-native-image-API)))
(should (memq 'delay
(image-metadata
@@ -268,7 +274,9 @@
(create-image (cdr (assq 'tiff image-tests--images))))))
(ert-deftest image-tests-image-metadata/webp ()
- (image-skip-unless 'webp)
+ (image-skip-unless 'webp
+ ;; FIXME: Why is this failing on macOS?
+ (not (eq system-type 'darwin)))
(should (memq 'delay
(image-metadata
(create-image (cdr (assq 'webp image-tests--images)))))))
diff --git a/test/manual/image-transforms-tests.el b/test/manual/image-transforms-tests.el
index cdf812ee177..92dd73263b1 100644
--- a/test/manual/image-transforms-tests.el
+++ b/test/manual/image-transforms-tests.el
@@ -1,6 +1,6 @@
;;; image-transforms-tests.el --- Test suite for image transforms. -*- lexical-binding: t -*-
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
;; Author: Alan Third <alan@idiocy.org>
;; Keywords: internal
diff --git a/test/manual/indent/pascal.pas b/test/manual/indent/pascal.pas
index 3b35acdc801..54794895be7 100644
--- a/test/manual/indent/pascal.pas
+++ b/test/manual/indent/pascal.pas
@@ -1,6 +1,6 @@
{ GPC demo program for the CRT unit.
-Copyright (C) 1999-2006, 2013-2023 Free Software Foundation, Inc.
+Copyright (C) 1999-2006, 2013-2024 Free Software Foundation, Inc.
Author: Frank Heckenbach <frank@pascal.gnu.de>
diff --git a/test/manual/noverlay/Makefile.in b/test/manual/noverlay/Makefile.in
index 29c7bacd258..280230b569a 100644
--- a/test/manual/noverlay/Makefile.in
+++ b/test/manual/noverlay/Makefile.in
@@ -1,6 +1,6 @@
### @configure_input@
-# Copyright (C) 2017-2023 Free Software Foundation, Inc.
+# Copyright (C) 2017-2024 Free Software Foundation, Inc.
# This file is part of GNU Emacs.
diff --git a/test/manual/noverlay/check-sanitize.sh b/test/manual/noverlay/check-sanitize.sh
index 735b85bbeeb..bec4f2f8e10 100755
--- a/test/manual/noverlay/check-sanitize.sh
+++ b/test/manual/noverlay/check-sanitize.sh
@@ -1,7 +1,7 @@
#!/usr/bin/env bash
### check-sanitize.sh - strip confusing parts of Check error output
-## Copyright (C) 2017-2023 Free Software Foundation, Inc.
+## Copyright (C) 2017-2024 Free Software Foundation, Inc.
## This file is part of GNU Emacs.
diff --git a/test/manual/noverlay/emacs-compat.h b/test/manual/noverlay/emacs-compat.h
index 16fa66e8ae4..b797f765dff 100644
--- a/test/manual/noverlay/emacs-compat.h
+++ b/test/manual/noverlay/emacs-compat.h
@@ -1,6 +1,6 @@
/* Mock necessary parts of lisp.h.
-Copyright (C) 2017-2023 Free Software Foundation, Inc.
+Copyright (C) 2017-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/test/manual/noverlay/itree-tests.c b/test/manual/noverlay/itree-tests.c
index 0f1e4138954..4d380fc1d2c 100644
--- a/test/manual/noverlay/itree-tests.c
+++ b/test/manual/noverlay/itree-tests.c
@@ -1,6 +1,6 @@
/* Test the interval data-structure in itree.c.
-Copyright (c) 2017-2023 Free Software Foundation, Inc.
+Copyright (c) 2017-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/test/manual/noverlay/overlay-perf.el b/test/manual/noverlay/overlay-perf.el
index 970b4541d9a..56cb72fc308 100644
--- a/test/manual/noverlay/overlay-perf.el
+++ b/test/manual/noverlay/overlay-perf.el
@@ -1,6 +1,6 @@
;; -*- lexical-binding:t -*-
-;; Copyright (C) 2015-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/manual/process-callout-tests.el b/test/manual/process-callout-tests.el
index a284dff50ad..4ec352e5018 100644
--- a/test/manual/process-callout-tests.el
+++ b/test/manual/process-callout-tests.el
@@ -1,6 +1,6 @@
;;; process-callout-tests.el --- Testing the process facilities -*- lexical-binding: t -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/manual/redisplay-testsuite.el b/test/manual/redisplay-testsuite.el
index 837f7417582..6d1232999ca 100644
--- a/test/manual/redisplay-testsuite.el
+++ b/test/manual/redisplay-testsuite.el
@@ -1,6 +1,6 @@
;;; redisplay-testsuite.el --- Test suite for redisplay. -*- lexical-binding: t; -*-
-;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
;; Author: Chong Yidong <cyd@stupidchicken.com>
;; Keywords: internal
diff --git a/test/manual/scroll-tests.el b/test/manual/scroll-tests.el
index c2a4ef17bff..431a4514b36 100644
--- a/test/manual/scroll-tests.el
+++ b/test/manual/scroll-tests.el
@@ -1,6 +1,6 @@
;;; scroll-tests.el --- tests for scrolling -*- lexical-binding: t -*-
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -80,25 +80,25 @@
,@body)))
(ert-deftest scroll-tests-scroll-margin-0 ()
- (skip-unless (not noninteractive))
+ (skip-when noninteractive)
(scroll-tests-with-buffer-window
(scroll-tests-up-and-down 0)))
(ert-deftest scroll-tests-scroll-margin-negative ()
"A negative `scroll-margin' should be the same as 0."
- (skip-unless (not noninteractive))
+ (skip-when noninteractive)
(scroll-tests-with-buffer-window
(scroll-tests-up-and-down -10 0)))
(ert-deftest scroll-tests-scroll-margin-max ()
- (skip-unless (not noninteractive))
+ (skip-when noninteractive)
(scroll-tests-with-buffer-window
(let ((max-margin (/ (window-text-height) 4)))
(scroll-tests-up-and-down max-margin))))
(ert-deftest scroll-tests-scroll-margin-over-max ()
"A `scroll-margin' more than max should be the same as max."
- (skip-unless (not noninteractive))
+ (skip-when noninteractive)
(scroll-tests-with-buffer-window 7
(let ((max-margin (/ (window-text-height) 4)))
(scroll-tests-up-and-down (+ max-margin 1) max-margin)
@@ -155,7 +155,7 @@ middle of the window."
(should (scroll-tests--point-in-middle-of-window-p)))))
(ert-deftest scroll-tests-scroll-margin-whole-window ()
- (skip-unless (not noninteractive))
+ (skip-when noninteractive)
(scroll-tests--scroll-margin-whole-window))
(ert-deftest scroll-tests-scroll-margin-whole-window-line-spacing ()
diff --git a/test/misc/test-custom-deps.el b/test/misc/test-custom-deps.el
index 9e5ba01fc5b..d04af23dc19 100644
--- a/test/misc/test-custom-deps.el
+++ b/test/misc/test-custom-deps.el
@@ -1,6 +1,6 @@
;;; test-custom-deps.el --- Test custom deps -*- lexical-binding:t -*-
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/misc/test-custom-libs.el b/test/misc/test-custom-libs.el
index eb565de8eee..0ecc64dd689 100644
--- a/test/misc/test-custom-libs.el
+++ b/test/misc/test-custom-libs.el
@@ -1,6 +1,6 @@
;;; test-custom-libs.el --- Test custom loads -*- lexical-binding:t -*-
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -39,7 +39,7 @@
:tags '(:expensive-test)
:expected-result :failed ; FIXME: See above.
;; This test is very slow, and IMO not worth the time it takes.
- (skip-unless (not (getenv "EMACS_HYDRA_CI")))
+ (skip-when (getenv "EMACS_HYDRA_CI"))
(skip-unless (file-readable-p custom-test-admin-cus-test))
(load custom-test-admin-cus-test)
(cus-test-libs t)
diff --git a/test/misc/test-custom-noloads.el b/test/misc/test-custom-noloads.el
index 585831aa466..3d669c72f7f 100644
--- a/test/misc/test-custom-noloads.el
+++ b/test/misc/test-custom-noloads.el
@@ -1,6 +1,6 @@
;;; test-custom-noloads.el --- Test custom noloads -*- lexical-binding:t -*-
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/misc/test-custom-opts.el b/test/misc/test-custom-opts.el
index f37553382c4..a4c286eed8a 100644
--- a/test/misc/test-custom-opts.el
+++ b/test/misc/test-custom-opts.el
@@ -1,6 +1,6 @@
;;; test-custom-opts.el --- Test custom opts -*- lexical-binding:t -*-
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/src/alloc-tests.el b/test/src/alloc-tests.el
index 19330e4a79c..74990574677 100644
--- a/test/src/alloc-tests.el
+++ b/test/src/alloc-tests.el
@@ -1,6 +1,6 @@
;;; alloc-tests.el --- alloc tests -*- lexical-binding: t -*-
-;; Copyright (C) 2015-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2024 Free Software Foundation, Inc.
;; Author: Daniel Colascione <dancol@dancol.org>
;; Keywords:
diff --git a/test/src/buffer-tests.el b/test/src/buffer-tests.el
index 45914b2b6b0..bb897377d41 100644
--- a/test/src/buffer-tests.el
+++ b/test/src/buffer-tests.el
@@ -1,6 +1,6 @@
;;; buffer-tests.el --- tests for buffer.c functions -*- lexical-binding: t -*-
-;; Copyright (C) 2015-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -142,6 +142,7 @@ properties."
(expected-calls . ((modification-hooks (nil 3 4))
(modification-hooks (t 3 4 1)))))
((replace . "4"))
+ ((replace . "4") (overlay-beg . 4)) ;bug#65929
((replace . "12")
(expected-calls . ((modification-hooks (nil 1 3))
(modification-hooks (t 1 2 2)))))
diff --git a/test/src/callint-tests.el b/test/src/callint-tests.el
index 4f7cceef619..6801ba7ce3b 100644
--- a/test/src/callint-tests.el
+++ b/test/src/callint-tests.el
@@ -1,6 +1,6 @@
;;; callint-tests.el --- unit tests for callint.c -*- lexical-binding: t; -*-
-;; Copyright (C) 2018-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2018-2024 Free Software Foundation, Inc.
;; Author: Philipp Stephani <phst@google.com>
diff --git a/test/src/callproc-tests.el b/test/src/callproc-tests.el
index 8ee40a46c11..a8b5a4372d6 100644
--- a/test/src/callproc-tests.el
+++ b/test/src/callproc-tests.el
@@ -1,6 +1,6 @@
;;; callproc-tests.el --- callproc.c tests -*- lexical-binding: t -*-
-;; Copyright (C) 2016-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2016-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/src/casefiddle-tests.el b/test/src/casefiddle-tests.el
index e7f4348b0c6..0a456c094ab 100644
--- a/test/src/casefiddle-tests.el
+++ b/test/src/casefiddle-tests.el
@@ -1,6 +1,6 @@
;;; casefiddle-tests.el --- tests for casefiddle.c functions -*- lexical-binding: t -*-
-;; Copyright (C) 2015-2016, 2018-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2016, 2018-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -294,4 +294,16 @@
;;(should (string-equal (capitalize "indIá") "İndıa"))
))
+(defun casefiddle-tests--check-syms (init with-words with-symbols)
+ (let ((case-symbols-as-words nil))
+ (should (string-equal (upcase-initials init) with-words)))
+ (let ((case-symbols-as-words t))
+ (should (string-equal (upcase-initials init) with-symbols))))
+
+(ert-deftest casefiddle-case-symbols-as-words ()
+ (casefiddle-tests--check-syms "Aa_bb Cc_dd" "Aa_Bb Cc_Dd" "Aa_bb Cc_dd")
+ (casefiddle-tests--check-syms "Aa_bb cc_DD" "Aa_Bb Cc_DD" "Aa_bb Cc_DD")
+ (casefiddle-tests--check-syms "aa_bb cc_dd" "Aa_Bb Cc_Dd" "Aa_bb Cc_dd")
+ (casefiddle-tests--check-syms "Aa_Bb Cc_Dd" "Aa_Bb Cc_Dd" "Aa_Bb Cc_Dd"))
+
;;; casefiddle-tests.el ends here
diff --git a/test/src/character-tests.el b/test/src/character-tests.el
index 76026ffc3a9..ae466800ec3 100644
--- a/test/src/character-tests.el
+++ b/test/src/character-tests.el
@@ -1,6 +1,6 @@
;;; character-tests.el --- tests for character.c -*- lexical-binding:t -*-
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/src/charset-tests.el b/test/src/charset-tests.el
index 34788ecbc05..3a4490fd272 100644
--- a/test/src/charset-tests.el
+++ b/test/src/charset-tests.el
@@ -1,6 +1,6 @@
;;; charset-tests.el --- Tests for charset.c -*- lexical-binding: t -*-
-;; Copyright 2017-2023 Free Software Foundation, Inc.
+;; Copyright 2017-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/src/chartab-tests.el b/test/src/chartab-tests.el
index 6433d3d09bb..3785f72135b 100644
--- a/test/src/chartab-tests.el
+++ b/test/src/chartab-tests.el
@@ -1,6 +1,6 @@
;;; chartab-tests.el --- Tests for char-tab.c -*- lexical-binding: t -*-
-;; Copyright (C) 2016-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2016-2024 Free Software Foundation, Inc.
;; Author: Eli Zaretskii <eliz@gnu.org>
diff --git a/test/src/cmds-tests.el b/test/src/cmds-tests.el
index 70d3d09e9d5..38bb4e71d16 100644
--- a/test/src/cmds-tests.el
+++ b/test/src/cmds-tests.el
@@ -1,6 +1,6 @@
;;; cmds-tests.el --- Testing some Emacs commands -*- lexical-binding: t -*-
-;; Copyright (C) 2013-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2024 Free Software Foundation, Inc.
;; Author: Nicolas Richard <youngfrog@members.fsf.org>
;; Keywords:
diff --git a/test/src/coding-tests.el b/test/src/coding-tests.el
index b27907027ba..443a0f9c630 100644
--- a/test/src/coding-tests.el
+++ b/test/src/coding-tests.el
@@ -1,6 +1,6 @@
;;; coding-tests.el --- tests for text encoding and decoding -*- lexical-binding: t -*-
-;; Copyright (C) 2013-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2024 Free Software Foundation, Inc.
;; Author: Eli Zaretskii <eliz@gnu.org>
;; Author: Kenichi Handa <handa@gnu.org>
diff --git a/test/src/comp-resources/comp-test-funcs-dyn.el b/test/src/comp-resources/comp-test-funcs-dyn.el
index 8cd127f7e1b..5a8a84b6a7b 100644
--- a/test/src/comp-resources/comp-test-funcs-dyn.el
+++ b/test/src/comp-resources/comp-test-funcs-dyn.el
@@ -1,6 +1,6 @@
;;; comp-test-funcs-dyn.el --- compilation unit tested by comp-tests.el -*- lexical-binding: nil; -*-
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
;; Author: Andrea Corallo <acorallo@gnu.org>
diff --git a/test/src/comp-resources/comp-test-funcs-dyn2.el b/test/src/comp-resources/comp-test-funcs-dyn2.el
index 3d70489d1ca..101674f74ce 100644
--- a/test/src/comp-resources/comp-test-funcs-dyn2.el
+++ b/test/src/comp-resources/comp-test-funcs-dyn2.el
@@ -1,6 +1,6 @@
;;; comp-test-funcs-dyn2.el -*- lexical-binding: nil; no-byte-compile: t; -*-
-;; Copyright (C) 2023 Free Software Foundation, Inc.
+;; Copyright (C) 2023-2024 Free Software Foundation, Inc.
;; Author: Alan Mackenzie <acm@muc.de>
diff --git a/test/src/comp-resources/comp-test-funcs.el b/test/src/comp-resources/comp-test-funcs.el
index 6d0cb353513..4cee084e211 100644
--- a/test/src/comp-resources/comp-test-funcs.el
+++ b/test/src/comp-resources/comp-test-funcs.el
@@ -1,6 +1,6 @@
;;; comp-test-funcs.el --- compilation unit tested by comp-tests.el -*- lexical-binding: t; -*-
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
;; Author: Andrea Corallo <acorallo@gnu.org>
@@ -242,6 +242,10 @@
(defun comp-tests-lambda-return-f ()
(lambda (x) (1+ x)))
+(defun comp-tests-lambda-return-f2 ()
+ (lambda ()
+ (lambda (x) (1+ x))))
+
(defun comp-tests-fib-f (n)
(cond ((= n 0) 0)
((= n 1) 1)
@@ -539,6 +543,22 @@
(if (comp-test-struct-p pkg) x)
t))
+
+(cl-defstruct comp-test-time
+ unix)
+
+(defun comp-test-67239-00-f (a)
+ (cl-assert (stringp a)))
+
+(defsubst comp-test-67239-0-f (x _y)
+ (cl-etypecase x
+ (comp-test-time (error "foo"))
+ (string (comp-test-67239-00-f x))))
+
+(defun comp-test-67239-1-f ()
+ (let ((time (make-comp-test-time :unix (time-convert (current-time) 'integer))))
+ (comp-test-67239-0-f "%F" time)))
+
;;;;;;;;;;;;;;;;;;;;
;; Tromey's tests ;;
diff --git a/test/src/comp-resources/comp-test-pure.el b/test/src/comp-resources/comp-test-pure.el
index cc5ba7edef7..84bb0287772 100644
--- a/test/src/comp-resources/comp-test-pure.el
+++ b/test/src/comp-resources/comp-test-pure.el
@@ -1,6 +1,6 @@
;;; comp-test-pure.el --- compilation unit tested by comp-tests.el -*- lexical-binding: t; -*-
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
;; Author: Andrea Corallo <acorallo@gnu.org>
diff --git a/test/src/comp-tests.el b/test/src/comp-tests.el
index 4444ab61219..0aa9e76fa2d 100644
--- a/test/src/comp-tests.el
+++ b/test/src/comp-tests.el
@@ -1,6 +1,6 @@
;;; comp-tests.el --- unit tests for src/comp.c -*- lexical-binding: t; -*-
-;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
;; Author: Andrea Corallo <acorallo@gnu.org>
@@ -327,6 +327,14 @@ Check that the resulting binaries do not differ."
(should (subr-native-elisp-p f))
(should (= (funcall f 3) 4))))
+(comp-deftest lambda-return2 ()
+ "Check a nested lambda function gets native compiled."
+ (let ((f (comp-tests-lambda-return-f2)))
+ (should (subr-native-elisp-p f))
+ (let ((f2 (funcall f)))
+ (should (subr-native-elisp-p f2))
+ (should (= (funcall f2 3) 4)))))
+
(comp-deftest recursive ()
(should (= (comp-tests-fib-f 10) 55)))
@@ -388,7 +396,27 @@ Check that the resulting binaries do not differ."
"Some doc."))
(should (commandp #'comp-tests-free-fun-f))
(should (equal (interactive-form #'comp-tests-free-fun-f)
- '(interactive))))
+ '(interactive nil))))
+
+(declare-function comp-tests-free-fun-f2 nil)
+
+(comp-deftest free-fun2 ()
+ "Check compiling a symbol's function compiles contained lambdas."
+ (eval '(defun comp-tests-free-fun-f2 ()
+ (lambda (x)
+ "Some doc."
+ (interactive)
+ x)))
+ (native-compile #'comp-tests-free-fun-f2)
+
+ (let* ((f (symbol-function 'comp-tests-free-fun-f2))
+ (f2 (funcall f)))
+ (should (subr-native-elisp-p f))
+ (should (subr-native-elisp-p f2))
+ (should (string= (documentation f2) "Some doc."))
+ (should (commandp f2))
+ (should (equal (interactive-form f2) '(interactive nil)))
+ (should (= (funcall f2 3) 3))))
(declare-function comp-tests/free\fun-f nil)
@@ -554,6 +582,10 @@ dedicated byte-op code."
(advice-remove #'delete-region f)
(should (equal comp-test-primitive-redefine-args '(1 2))))))
+(comp-deftest 67239-1 ()
+ "<https://lists.gnu.org/archive/html/bug-gnu-emacs/2023-11/msg00925.html>"
+ (should-not (comp-test-67239-1-f)))
+
;;;;;;;;;;;;;;;;;;;;;
;; Tromey's tests. ;;
@@ -977,7 +1009,7 @@ Return a list of results."
(if (= x y)
x
'foo))
- '(or (member foo) marker number))
+ '(or (member foo) number-or-marker))
;; 14
((defun comp-tests-ret-type-spec-f (x)
@@ -1117,7 +1149,7 @@ Return a list of results."
((defun comp-tests-ret-type-spec-f (x)
(when (> x 1.0)
x))
- '(or null marker number))
+ '(or null number-or-marker))
;; 36
((defun comp-tests-ret-type-spec-f (x y)
diff --git a/test/src/data-tests.el b/test/src/data-tests.el
index 8167cccdd18..8af7e902109 100644
--- a/test/src/data-tests.el
+++ b/test/src/data-tests.el
@@ -1,6 +1,6 @@
;;; data-tests.el --- tests for src/data.c -*- lexical-binding:t -*-
-;; Copyright (C) 2013-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/src/decompress-tests.el b/test/src/decompress-tests.el
index 1052ecee5c1..f8fa1f2f140 100644
--- a/test/src/decompress-tests.el
+++ b/test/src/decompress-tests.el
@@ -1,6 +1,6 @@
;;; decompress-tests.el --- Test suite for decompress. -*- lexical-binding: t -*-
-;; Copyright (C) 2013-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2024 Free Software Foundation, Inc.
;; Author: Lars Ingebrigtsen <larsi@gnus.org>
diff --git a/test/src/doc-tests.el b/test/src/doc-tests.el
index 79cac8c3d64..b41a7ac5fb6 100644
--- a/test/src/doc-tests.el
+++ b/test/src/doc-tests.el
@@ -1,6 +1,6 @@
;;; doc-tests.el --- tests for doc.c functions -*- lexical-binding: t -*-
-;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/src/editfns-tests.el b/test/src/editfns-tests.el
index a3353cc25a6..b3b7da65ad3 100644
--- a/test/src/editfns-tests.el
+++ b/test/src/editfns-tests.el
@@ -1,6 +1,6 @@
;;; editfns-tests.el --- tests for editfns.c -*- lexical-binding:t -*-
-;; Copyright (C) 2016-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2016-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/src/emacs-module-resources/mod-test.c b/test/src/emacs-module-resources/mod-test.c
index 5dfa6ed4b85..06049364b1e 100644
--- a/test/src/emacs-module-resources/mod-test.c
+++ b/test/src/emacs-module-resources/mod-test.c
@@ -1,6 +1,6 @@
/* Test GNU Emacs modules.
-Copyright 2015-2023 Free Software Foundation, Inc.
+Copyright 2015-2024 Free Software Foundation, Inc.
This file is part of GNU Emacs.
diff --git a/test/src/emacs-module-tests.el b/test/src/emacs-module-tests.el
index ac88011b543..b82d4a36304 100644
--- a/test/src/emacs-module-tests.el
+++ b/test/src/emacs-module-tests.el
@@ -1,6 +1,6 @@
;;; emacs-module-tests.el --- Test GNU Emacs modules. -*- lexical-binding: t; -*-
-;; Copyright 2015-2023 Free Software Foundation, Inc.
+;; Copyright 2015-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -457,7 +457,7 @@ See Bug#36226."
(ert-deftest module/async-pipe ()
"Check that writing data from another thread works."
- (skip-unless (not (eq system-type 'windows-nt))) ; FIXME!
+ (skip-when (eq system-type 'windows-nt)) ; FIXME!
(with-temp-buffer
(let ((process (make-pipe-process :name "module/async-pipe"
:buffer (current-buffer)
diff --git a/test/src/emacs-tests.el b/test/src/emacs-tests.el
index 0ea197d07f8..19c3793b93d 100644
--- a/test/src/emacs-tests.el
+++ b/test/src/emacs-tests.el
@@ -1,6 +1,6 @@
;;; emacs-tests.el --- unit tests for emacs.c -*- lexical-binding: t; -*-
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/src/eval-tests.el b/test/src/eval-tests.el
index 4589763b2f5..e4b18ec7849 100644
--- a/test/src/eval-tests.el
+++ b/test/src/eval-tests.el
@@ -1,6 +1,6 @@
;;; eval-tests.el --- unit tests for src/eval.c -*- lexical-binding: t; -*-
-;; Copyright (C) 2016-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2016-2024 Free Software Foundation, Inc.
;; Author: Philipp Stephani <phst@google.com>
@@ -282,4 +282,25 @@ expressions works for identifiers starting with period."
(should-error (defvaralias 'eval-tests--my-c 'eval-tests--my-d)
:type 'cyclic-variable-indirection))
+(defvar eval-tests/global-var 'value)
+(defvar-local eval-tests/buffer-local-var 'value)
+(ert-deftest eval-tests/default-value ()
+ ;; `let' overrides the default value for global variables.
+ (should (default-boundp 'eval-tests/global-var))
+ (should (eq 'value (default-value 'eval-tests/global-var)))
+ (should (eq 'value eval-tests/global-var))
+ (let ((eval-tests/global-var 'bar))
+ (should (eq 'bar (default-value 'eval-tests/global-var)))
+ (should (eq 'bar eval-tests/global-var)))
+ ;; `let' overrides the default value everywhere, but leaves
+ ;; buffer-local values unchanged in current buffer and in the
+ ;; buffers where there is no explicitly set buffer-local value.
+ (should (default-boundp 'eval-tests/buffer-local-var))
+ (should (eq 'value (default-value 'eval-tests/buffer-local-var)))
+ (should (eq 'value eval-tests/buffer-local-var))
+ (with-temp-buffer
+ (let ((eval-tests/buffer-local-var 'bar))
+ (should (eq 'bar (default-value 'eval-tests/buffer-local-var)))
+ (should (eq 'bar eval-tests/buffer-local-var)))))
+
;;; eval-tests.el ends here
diff --git a/test/src/fileio-tests.el b/test/src/fileio-tests.el
index 50642420ce9..81eef37b903 100644
--- a/test/src/fileio-tests.el
+++ b/test/src/fileio-tests.el
@@ -1,6 +1,6 @@
;;; fileio-tests.el --- unit tests for src/fileio.c -*- lexical-binding: t; -*-
-;; Copyright 2017-2023 Free Software Foundation, Inc.
+;; Copyright 2017-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -50,7 +50,7 @@ Also check that an encoding error can appear in a symlink."
;; Some Windows versions don't support symlinks, and those which do
;; will pop up UAC elevation prompts, so we disable this test on
;; MS-Windows.
- (skip-unless (not (eq system-type 'windows-nt)))
+ (skip-when (eq system-type 'windows-nt))
(should (equal nil (fileio-tests--symlink-failure))))
(ert-deftest fileio-tests--directory-file-name ()
diff --git a/test/src/filelock-tests.el b/test/src/filelock-tests.el
index c5e77f70bb2..c644747a23e 100644
--- a/test/src/filelock-tests.el
+++ b/test/src/filelock-tests.el
@@ -1,6 +1,6 @@
;;; filelock-tests.el --- test file locking -*- lexical-binding: t; -*-
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -26,7 +26,7 @@
;;; Code:
-(require 'cl-macs)
+(require 'cl-lib)
(require 'ert)
(require 'ert-x)
(require 'seq)
@@ -109,7 +109,7 @@ the case)."
(ert-deftest filelock-tests-lock-spoiled ()
"Check `lock-buffer'."
- (skip-unless (not (eq system-type 'ms-dos))) ; no filelock support
+ (skip-when (eq system-type 'ms-dos)) ; no filelock support
(filelock-tests--fixture
(filelock-tests--spoil-lock-file buffer-file-truename)
;; FIXME: errors when locking a file are ignored; should they be?
@@ -119,7 +119,7 @@ the case)."
(ert-deftest filelock-tests-file-locked-p-spoiled ()
"Check that `file-locked-p' fails if the lockfile is \"spoiled\"."
- (skip-unless (not (eq system-type 'ms-dos))) ; no filelock support
+ (skip-when (eq system-type 'ms-dos)) ; no filelock support
(filelock-tests--fixture
(filelock-tests--spoil-lock-file buffer-file-truename)
(let ((err (should-error (file-locked-p (buffer-file-name)))))
@@ -130,7 +130,7 @@ the case)."
(ert-deftest filelock-tests-unlock-spoiled ()
"Check that `unlock-buffer' fails if the lockfile is \"spoiled\"."
- (skip-unless (not (eq system-type 'ms-dos))) ; no filelock support
+ (skip-when (eq system-type 'ms-dos)) ; no filelock support
(filelock-tests--fixture
;; Set the buffer modified with file locking temporarily disabled.
(let ((create-lockfiles nil))
@@ -150,7 +150,7 @@ the case)."
(ert-deftest filelock-tests-kill-buffer-spoiled ()
"Check that `kill-buffer' fails if a lockfile is \"spoiled\"."
- (skip-unless (not (eq system-type 'ms-dos))) ; no filelock support
+ (skip-when (eq system-type 'ms-dos)) ; no filelock support
(filelock-tests--fixture
;; Set the buffer modified with file locking temporarily disabled.
(let ((create-lockfiles nil))
@@ -176,7 +176,7 @@ the case)."
(ert-deftest filelock-tests-detect-external-change ()
"Check that an external file modification is reported."
- (skip-unless (not (eq system-type 'ms-dos))) ; no filelock support
+ (skip-when (eq system-type 'ms-dos)) ; no filelock support
(skip-unless (executable-find "touch"))
(skip-unless (executable-find "echo"))
(dolist (cl '(t nil))
diff --git a/test/src/floatfns-tests.el b/test/src/floatfns-tests.el
index 97c855a43fa..359d2890134 100644
--- a/test/src/floatfns-tests.el
+++ b/test/src/floatfns-tests.el
@@ -1,6 +1,6 @@
;;; floatfns-tests.el --- tests for floating point operations -*- lexical-binding: t -*-
-;; Copyright 2017-2023 Free Software Foundation, Inc.
+;; Copyright 2017-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/src/fns-tests.el b/test/src/fns-tests.el
index 79ae4393f40..3893b8b0320 100644
--- a/test/src/fns-tests.el
+++ b/test/src/fns-tests.el
@@ -1,6 +1,6 @@
;;; fns-tests.el --- tests for src/fns.c -*- lexical-binding:t -*-
-;; Copyright (C) 2014-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2014-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -98,6 +98,26 @@
(should-not (equal-including-properties #("a" 0 1 (k "v"))
#("b" 0 1 (k "v")))))
+(ert-deftest fns-tests-equal-symbols-with-position ()
+ "Test `eq' and `equal' on symbols with position."
+ (let ((foo1 (position-symbol 'foo 42))
+ (foo2 (position-symbol 'foo 666))
+ (foo3 (position-symbol 'foo 42)))
+ (let (symbols-with-pos-enabled)
+ (should (eq foo1 foo1))
+ (should (equal foo1 foo1))
+ (should-not (eq foo1 foo2))
+ (should-not (equal foo1 foo2))
+ (should-not (eq foo1 foo3))
+ (should (equal foo1 foo3)))
+ (let ((symbols-with-pos-enabled t))
+ (should (eq foo1 foo1))
+ (should (equal foo1 foo1))
+ (should (eq foo1 foo2))
+ (should (equal foo1 foo2))
+ (should (eq foo1 foo3))
+ (should (equal foo1 foo3)))))
+
(ert-deftest fns-tests-reverse ()
(should-error (reverse))
(should-error (reverse 1))
diff --git a/test/src/font-tests.el b/test/src/font-tests.el
index 2bd20be21dc..a1ea84de9f7 100644
--- a/test/src/font-tests.el
+++ b/test/src/font-tests.el
@@ -1,6 +1,6 @@
;;; font-tests.el --- Test suite for font-related functions. -*- lexical-binding: t -*-
-;; Copyright (C) 2011-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2011-2024 Free Software Foundation, Inc.
;; Author: Chong Yidong <cyd@stupidchicken.com>
;; Keywords: internal
diff --git a/test/src/image-tests.el b/test/src/image-tests.el
index 317f4d3aab6..24e60fb100f 100644
--- a/test/src/image-tests.el
+++ b/test/src/image-tests.el
@@ -1,6 +1,6 @@
;;; image-tests.el --- Tests for image.c -*- lexical-binding: t -*-
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
;; Author: Stefan Kangas <stefankangas@gmail.com>
@@ -44,15 +44,15 @@
(xpm . ,(find-image '((:file "splash.xpm" :type xpm))))))
(ert-deftest image-tests-image-size/error-on-nongraphical-display ()
- (skip-unless (not (display-images-p)))
+ (skip-when (display-images-p))
(should-error (image-size 'invalid-spec)))
(ert-deftest image-tests-image-mask-p/error-on-nongraphical-display ()
- (skip-unless (not (display-images-p)))
+ (skip-when (display-images-p))
(should-error (image-mask-p (cdr (assq 'xpm image-tests--images)))))
(ert-deftest image-tests-image-metadata/error-on-nongraphical-display ()
- (skip-unless (not (display-images-p)))
+ (skip-when (display-images-p))
(should-error (image-metadata (cdr (assq 'xpm image-tests--images)))))
(ert-deftest image-tests-imagemagick-types ()
diff --git a/test/src/indent-tests.el b/test/src/indent-tests.el
index 9e111bf3476..a37ad1a3c3f 100644
--- a/test/src/indent-tests.el
+++ b/test/src/indent-tests.el
@@ -1,6 +1,6 @@
;;; indent-tests.el --- tests for src/indent.c -*- lexical-binding:t -*-
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/src/inotify-tests.el b/test/src/inotify-tests.el
index cebf4421fd5..0c078627786 100644
--- a/test/src/inotify-tests.el
+++ b/test/src/inotify-tests.el
@@ -1,6 +1,6 @@
;;; inotify-tests.el --- Test suite for inotify. -*- lexical-binding: t -*-
-;; Copyright (C) 2012-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2012-2024 Free Software Foundation, Inc.
;; Author: Rüdiger Sonderfeld <ruediger@c-plusplus.de>
;; Keywords: internal
diff --git a/test/src/json-tests.el b/test/src/json-tests.el
index 93e1273d7d6..dffc6291ca1 100644
--- a/test/src/json-tests.el
+++ b/test/src/json-tests.el
@@ -1,6 +1,6 @@
;;; json-tests.el --- unit tests for json.c -*- lexical-binding: t; -*-
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/src/keyboard-tests.el b/test/src/keyboard-tests.el
index bbb9c19e2e7..4cb141804b2 100644
--- a/test/src/keyboard-tests.el
+++ b/test/src/keyboard-tests.el
@@ -1,6 +1,6 @@
;;; keyboard-tests.el --- Tests for keyboard.c -*- lexical-binding: t -*-
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/src/keymap-tests.el b/test/src/keymap-tests.el
index 29220c95395..bc9977f31bf 100644
--- a/test/src/keymap-tests.el
+++ b/test/src/keymap-tests.el
@@ -1,6 +1,6 @@
;;; keymap-tests.el --- Test suite for src/keymap.c -*- lexical-binding: t -*-
-;; Copyright (C) 2015-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2024 Free Software Foundation, Inc.
;; Author: Juanma Barranquero <lekktu@gmail.com>
;; Stefan Kangas <stefankangas@gmail.com>
diff --git a/test/src/lcms-tests.el b/test/src/lcms-tests.el
index e34542b1921..a279fb7098c 100644
--- a/test/src/lcms-tests.el
+++ b/test/src/lcms-tests.el
@@ -1,6 +1,6 @@
;;; lcms-tests.el --- tests for Little CMS interface -*- lexical-binding: t -*-
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
;; Maintainer: emacs-devel@gnu.org
diff --git a/test/src/lread-tests.el b/test/src/lread-tests.el
index eae4893ee1b..4d7f8b71838 100644
--- a/test/src/lread-tests.el
+++ b/test/src/lread-tests.el
@@ -1,6 +1,6 @@
;;; lread-tests.el --- tests for lread.c -*- lexical-binding: t; -*-
-;; Copyright (C) 2016-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2016-2024 Free Software Foundation, Inc.
;; Author: Philipp Stephani <phst@google.com>
diff --git a/test/src/marker-tests.el b/test/src/marker-tests.el
index b766466a38a..9336436e53c 100644
--- a/test/src/marker-tests.el
+++ b/test/src/marker-tests.el
@@ -1,6 +1,6 @@
;;; marker-tests.el --- tests for marker.c functions -*- lexical-binding: t -*-
-;; Copyright (C) 2016-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2016-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/src/minibuf-tests.el b/test/src/minibuf-tests.el
index f096624cb27..14d160df25c 100644
--- a/test/src/minibuf-tests.el
+++ b/test/src/minibuf-tests.el
@@ -1,6 +1,6 @@
;;; minibuf-tests.el --- tests for minibuf.c functions -*- lexical-binding: t -*-
-;; Copyright (C) 2016-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2016-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/src/print-tests.el b/test/src/print-tests.el
index a67099c147f..aedaa9a4e06 100644
--- a/test/src/print-tests.el
+++ b/test/src/print-tests.el
@@ -1,6 +1,6 @@
;;; print-tests.el --- tests for src/print.c -*- lexical-binding: t; -*-
-;; Copyright (C) 2014-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2014-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/src/process-tests.el b/test/src/process-tests.el
index e17e1c0d833..19b14f2d0cb 100644
--- a/test/src/process-tests.el
+++ b/test/src/process-tests.el
@@ -1,6 +1,6 @@
;;; process-tests.el --- Testing the process facilities -*- lexical-binding: t -*-
-;; Copyright (C) 2013-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -231,7 +231,7 @@ process to complete."
(with-timeout (60 (ert-fail "Test timed out"))
;; Frequent random (?) failures on hydra.nixos.org, with no process output.
;; Maybe this test should be tagged unstable? See bug#31214.
- (skip-unless (not (getenv "EMACS_HYDRA_CI")))
+ (skip-when (getenv "EMACS_HYDRA_CI"))
(with-temp-buffer
(let ((process (make-process
:name "mix-stderr"
@@ -723,7 +723,7 @@ FD_SETSIZE file descriptors (Bug#24325)."
(skip-unless (featurep 'make-network-process '(:server t)))
(skip-unless (featurep 'make-network-process '(:family local)))
;; Avoid hang due to connect/accept handshake on Cygwin (bug#49496).
- (skip-unless (not (eq system-type 'cygwin)))
+ (skip-when (eq system-type 'cygwin))
(with-timeout (60 (ert-fail "Test timed out"))
(ert-with-temp-directory directory
(process-tests--with-processes processes
@@ -763,7 +763,7 @@ FD_SETSIZE file descriptors (Bug#24325)."
"Check that Emacs doesn't crash when trying to use more than
FD_SETSIZE file descriptors (Bug#24325)."
;; This test cannot be run if PTYs aren't supported.
- (skip-unless (not (eq system-type 'windows-nt)))
+ (skip-when (eq system-type 'windows-nt))
(with-timeout (60 (ert-fail "Test timed out"))
(process-tests--with-processes processes
;; In order to use `make-serial-process', we need to create some
diff --git a/test/src/regex-emacs-tests.el b/test/src/regex-emacs-tests.el
index 4e2c0f67a44..171d794360e 100644
--- a/test/src/regex-emacs-tests.el
+++ b/test/src/regex-emacs-tests.el
@@ -1,6 +1,6 @@
;;; regex-emacs-tests.el --- tests for regex-emacs.c -*- lexical-binding: t -*-
-;; Copyright (C) 2015-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -555,10 +555,10 @@ known/benign differences in behavior.")
(defconst regex-tests-PTESTS-whitelist
[
- ;; emacs doesn't see DEL (0x7f) as a [:cntrl:] character
+ ;; Emacs doesn't see DEL (0x7f) as a [:cntrl:] character
138
- ;; emacs doesn't barf on weird ranges such as [b-a], but simply
+ ;; Emacs doesn't barf on weird ranges such as [b-a], but simply
;; fails to match
168
]
@@ -872,19 +872,47 @@ This evaluates the TESTS test cases from glibc."
(should (equal (string-match "\\`\\(?:ab\\)*\\'" "a") nil))
(should (equal (string-match "\\`a\\{2\\}*\\'" "a") nil)))
-(ert-deftest regexp-tests-backtrack-optimization () ;bug#61514
+(ert-deftest regexp-tests-backtrack-optimization ()
;; Make sure we don't use up the regexp stack needlessly.
(with-current-buffer (get-buffer-create "*bug*")
(erase-buffer)
(insert (make-string 1000000 ?x) "=")
(goto-char (point-min))
+ ;; Make sure we do perform the optimization (if we don't, the
+ ;; below will burp with regexp-stack-overflow). ;bug#61514
(should (looking-at "x*=*"))
(should (looking-at "x*\\(=\\|:\\)"))
(should (looking-at "x*\\(=\\|:\\)*"))
- (should (looking-at "x*=*?"))))
+ (should (looking-at "x*=*?"))
+ ;; relint suppression: Repetition of expression matching an empty string
+ (should (looking-at "x*\\(=*\\|h\\)*?"))
+ ;; relint suppression: Repetition of expression matching an empty string
+ (should (looking-at "x*\\(=*\\|h\\)*"))
+ ;; relint suppression: Repetition of expression matching an empty string
+ (should (looking-at "x*\\(=*?\\|h\\)*"))
+ ;; relint suppression: Repetition of expression matching an empty string
+ (should (looking-at "x*\\(=*?\\|h\\)*?"))
+ ;; relint suppression: Repetition of expression matching an empty string
+ (should (looking-at "x*\\(=*\\|h\\)+?"))
+ ;; relint suppression: Repetition of expression matching an empty string
+ (should (looking-at "x*\\(=*\\|h\\)+"))
+ ;; relint suppression: Repetition of expression matching an empty string
+ (should (looking-at "x*\\(=*?\\|h\\)+"))
+ ;; relint suppression: Repetition of expression matching an empty string
+ (should (looking-at "x*\\(=*?\\|h\\)+?"))
+ (should (looking-at "x*\\(=+\\|h\\)+?"))
+ (should (looking-at "x*\\(=+\\|h\\)+"))
+ (should (looking-at "x*\\(=+?\\|h\\)+"))
+ (should (looking-at "x*\\(=+?\\|h\\)+?"))
+ ;; Regression check for overly optimistic optimization.
+ (should (eq 0 (string-match "\\(ca*\\|ab\\)+d" "cabd")))
+ (should (string-match "\\(aa*\\|b\\)*c" "ababc"))
+ (should (string-match " \\sw*\\bfoo" " foo"))
+ (should (string-match ".*\\>" "hello "))
+ ))
(ert-deftest regexp-tests-zero-width-assertion-repetition ()
- ;; Check compatibility behaviour with repetition operators after
+ ;; Check compatibility behavior with repetition operators after
;; certain zero-width assertions (bug#64128).
;; This function is just to hide ugly regexps from relint so that it
@@ -965,4 +993,9 @@ This evaluates the TESTS test cases from glibc."
(re-search-forward re nil t))
nil))))
+(ert-deftest regex-tests-mutual-exclusive-inf-rec ()
+ ;; Regression test for bug#65726, where this crashed Emacs.
+ ;; relint suppression: Repetition of expression matching an empty string
+ (should (equal (string-match "a*\\(?:c\\|b*\\)*" "a") 0)))
+
;;; regex-emacs-tests.el ends here
diff --git a/test/src/regex-resources/PTESTS b/test/src/regex-resources/PTESTS
index 68acc314d37..59dd4b3bc21 100644
--- a/test/src/regex-resources/PTESTS
+++ b/test/src/regex-resources/PTESTS
@@ -269,6 +269,7 @@
#W the expected result for \([a-c]*\)\{2,\} is failure which isn't correct
1¦3¦\([a-c]*\)\{2,\}¦abcdefg¦
1¦3¦\([a-c]*\)\{1,\}¦abcdefg¦
+0¦0¦\([a-c]*\)\{2,\}¦gabcdefg¦
-1¦-1¦a\{64,\}¦aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa¦
# GA142
1¦3¦a\{2,3\}¦aaaa¦
diff --git a/test/src/search-tests.el b/test/src/search-tests.el
index 293a715f5dc..bab503f36bf 100644
--- a/test/src/search-tests.el
+++ b/test/src/search-tests.el
@@ -1,6 +1,6 @@
;;; search-tests.el --- tests for search.c functions -*- lexical-binding: t -*-
-;; Copyright (C) 2015-2016, 2018-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2016, 2018-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -39,4 +39,42 @@
(replace-match "bcd"))
(should (= (point) 10)))))
+(ert-deftest search-test--replace-match-update-data ()
+ (with-temp-buffer
+ (pcase-dolist (`(,pre ,post) '(("" "")
+ ("a" "")
+ ("" "b")
+ ("a" "b")))
+ (erase-buffer)
+ (insert "hello ")
+ (save-excursion (insert pre post " world"))
+ (should (looking-at
+ (concat "\\(\\)" pre "\\(\\)\\(\\(\\)\\)\\(\\)" post "\\(\\)")))
+ (let* ((beg0 (match-beginning 0))
+ (beg4 (+ beg0 (length pre)))
+ (end4 (+ beg4 (length "BOO")))
+ (end0 (+ end4 (length post))))
+ (replace-match "BOO" t t nil 4)
+ (should (equal (match-beginning 0) beg0))
+ (should (equal (match-beginning 1) beg0))
+ (should (equal (match-beginning 2) beg4))
+ (should (equal (match-beginning 3) beg4))
+ (should (equal (match-beginning 4) beg4))
+ (should (equal (match-end 6) end0))
+ (should (equal (match-end 5) end4))
+ (should (equal (match-end 4) end4))
+ (should (equal (match-end 3) end4))
+ (should (equal (match-end 0) end0))
+ ;; `update_search_regs' doesn't have enough information to get
+ ;; the ones below correctly in all cases.
+ (when (> (length post) 0)
+ (should (equal (match-beginning 6) end0)))
+ (when (> (length pre) 0)
+ (should (equal (match-end 1) beg0)))
+ ;; `update_search_regs' doesn't have enough information to get
+ ;; the ones below correctly at all.
+ ;;(should (equal (match-beginning 5) end4))
+ ;;(should (equal (match-end 2) beg4))
+ ))))
+
;;; search-tests.el ends here
diff --git a/test/src/sqlite-tests.el b/test/src/sqlite-tests.el
index f7144c15887..a10dca9a0c9 100644
--- a/test/src/sqlite-tests.el
+++ b/test/src/sqlite-tests.el
@@ -1,6 +1,6 @@
;;; sqlite-tests.el --- Tests for sqlite.el -*- lexical-binding: t; -*-
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/src/syntax-tests.el b/test/src/syntax-tests.el
index 9e4740c17cc..f0f7cf28a3c 100644
--- a/test/src/syntax-tests.el
+++ b/test/src/syntax-tests.el
@@ -1,6 +1,6 @@
;;; syntax-tests.el --- tests for syntax.c functions -*- lexical-binding: t -*-
-;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/src/textprop-tests.el b/test/src/textprop-tests.el
index 12349a79497..d728b539955 100644
--- a/test/src/textprop-tests.el
+++ b/test/src/textprop-tests.el
@@ -1,6 +1,6 @@
;;; textprop-tests.el --- Test suite for text properties. -*- lexical-binding: t -*-
-;; Copyright (C) 2015-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2015-2024 Free Software Foundation, Inc.
;; Author: Wolfgang Jenkner <wjenkner@inode.at>
;; Keywords: internal
diff --git a/test/src/thread-tests.el b/test/src/thread-tests.el
index cfa253fb48e..d9048dcf287 100644
--- a/test/src/thread-tests.el
+++ b/test/src/thread-tests.el
@@ -1,6 +1,6 @@
;;; thread-tests.el --- tests for threads. -*- lexical-binding: t -*-
-;; Copyright (C) 2012-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2012-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/src/timefns-tests.el b/test/src/timefns-tests.el
index ca4ec308926..410efd0db84 100644
--- a/test/src/timefns-tests.el
+++ b/test/src/timefns-tests.el
@@ -1,6 +1,6 @@
;;; timefns-tests.el --- tests for timefns.c -*- lexical-binding: t -*-
-;; Copyright (C) 2016-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2016-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/src/treesit-tests.el b/test/src/treesit-tests.el
index 65994ce608f..a89bf1298c0 100644
--- a/test/src/treesit-tests.el
+++ b/test/src/treesit-tests.el
@@ -1,6 +1,6 @@
;;; treesit-tests.el --- tests for src/treesit.c -*- lexical-binding: t; -*-
-;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -166,6 +166,13 @@
;; `treesit-node-eq'.
(should (treesit-node-eq root-node root-node))
(should (not (treesit-node-eq root-node doc-node)))
+ ;; `treesit-node-enclosed-p'
+ (should (treesit-node-enclosed-p '(1 . 3) '(1 . 4)))
+ (should (treesit-node-enclosed-p '(1 . 3) '(1 . 3)))
+ (should (not (treesit-node-enclosed-p '(1 . 3) '(1 . 4) t)))
+ (should (treesit-node-enclosed-p '(1 . 3) '(1 . 4) 'partial))
+ (should (treesit-node-enclosed-p '(2 . 3) '(1 . 4) t))
+ (should (treesit-node-enclosed-p object-node root-node))
;; Further test for `treesit-node-check'.
(treesit-parser-delete parser)
@@ -662,6 +669,20 @@ visible_end.)"
;; TODO: More tests.
)))
+(ert-deftest treesit-range-offset ()
+ "Tests if range offsets work."
+ (skip-unless (treesit-language-available-p 'javascript))
+ (with-temp-buffer
+ (let ((query '(((call_expression (identifier) @_html_template_fn
+ (template_string) @capture)
+ (:equal "html" @_html_template_fn)))))
+ (progn
+ (insert "const x = html`<p>Hello</p>`;")
+ (treesit-parser-create 'javascript))
+ (should (equal '((15 . 29)) (treesit-query-range 'javascript query)))
+ (should (equal '((16 . 28)) (treesit-query-range
+ 'javascript query nil nil '(1 . -1)))))))
+
;;; Multiple language
(ert-deftest treesit-multi-lang ()
@@ -1146,6 +1167,42 @@ This tests bug#60355."
treesit--ert-defun-navigation-top-level-master
'top-level))
+(ert-deftest treesit-search-subtree-forward-1 ()
+ "Test search subtree forward."
+ (skip-unless (treesit-language-available-p 'python))
+ (require 'python)
+ (python-ts-mode)
+ (insert "Temp(1, 2)")
+ (goto-char (point-min))
+ (pcase-let* ((`((,_ . ,call-node))
+ (treesit-query-capture (treesit-buffer-root-node)
+ '((call) @c)))
+ (node (treesit-search-subtree
+ call-node
+ (lambda (n) (equal (treesit-node-type n) "integer")))))
+
+ (should node)
+ (should (equal (treesit-node-text node) "1"))))
+
+(ert-deftest treesit-search-subtree-backward-1 ()
+ "Test search subtree with backward=t."
+ (skip-unless (treesit-language-available-p 'python))
+ (require 'python)
+ (python-ts-mode)
+ (insert "Temp(1, 2)")
+ (goto-char (point-min))
+ (pcase-let* ((`((,_ . ,call-node))
+ (treesit-query-capture (treesit-buffer-root-node)
+ '((call) @c)))
+ (node (treesit-search-subtree
+ call-node
+ (lambda (n) (equal (treesit-node-type n) "integer"))
+ t)))
+
+ (should node)
+ (should (equal (treesit-node-text node) "2"))))
+
+
;; TODO
;; - Functions in treesit.el
;; - treesit-load-name-override-list
diff --git a/test/src/undo-tests.el b/test/src/undo-tests.el
index fd45a9101fa..b4888771e70 100644
--- a/test/src/undo-tests.el
+++ b/test/src/undo-tests.el
@@ -1,6 +1,6 @@
;;; undo-tests.el --- Tests of primitive-undo -*- lexical-binding: t -*-
-;; Copyright (C) 2012-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2012-2024 Free Software Foundation, Inc.
;; Author: Aaron S. Hawley <aaron.s.hawley@gmail.com>
diff --git a/test/src/xdisp-tests.el b/test/src/xdisp-tests.el
index dfd38a9d4c1..f2a2a72c658 100644
--- a/test/src/xdisp-tests.el
+++ b/test/src/xdisp-tests.el
@@ -1,6 +1,6 @@
;;; xdisp-tests.el --- tests for xdisp.c functions -*- lexical-binding: t -*-
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/src/xfaces-tests.el b/test/src/xfaces-tests.el
index d8707a0a08e..cdf6f30c356 100644
--- a/test/src/xfaces-tests.el
+++ b/test/src/xfaces-tests.el
@@ -1,6 +1,6 @@
;;; xfaces-tests.el --- tests for xfaces.c -*- lexical-binding: t -*-
-;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
diff --git a/test/src/xml-tests.el b/test/src/xml-tests.el
index dfb897ba011..5aa8593fe07 100644
--- a/test/src/xml-tests.el
+++ b/test/src/xml-tests.el
@@ -1,6 +1,6 @@
;;; xml-tests.el --- Test suite for libxml parsing. -*- lexical-binding: t -*-
-;; Copyright (C) 2014-2023 Free Software Foundation, Inc.
+;; Copyright (C) 2014-2024 Free Software Foundation, Inc.
;; Author: Ulf Jasper <ulf.jasper@web.de>
;; Keywords: internal